Diff for /loncom/interface/loncoursegroups.pm between versions 1.26 and 1.61

version 1.26, 2006/06/27 18:49:14 version 1.61, 2006/08/19 01:24:08
Line 34  use Apache::lonhtmlcommon; Line 34  use Apache::lonhtmlcommon;
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnavmaps;  use Apache::lonnavmaps;
 use Apache::longroup;  use Apache::longroup;
   use Apache::portfolio;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use lib '/home/httpd/lib/perl/';  use lib '/home/httpd/lib/perl/';
 use LONCAPA;  use LONCAPA;
Line 58  sub handler { Line 59  sub handler {
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                         ['action','refpage','state','groupname','branch']);                          ['action','refpage','state','groupname','branch']);
     my $function = &Apache::loncommon::get_users_function();  
     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');  
     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};      my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};      my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
   
     my $view_permission =      my $view_permission =
           &Apache::lonnet::allowed('vcg',$env{'request.course.id'});            &Apache::lonnet::allowed('vcg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
     my $manage_permission =      my $manage_permission =
           &Apache::lonnet::allowed('mdg',$env{'request.course.id'});            &Apache::lonnet::allowed('mdg',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
   
       my $gpterm = &Apache::loncommon::group_term();
       my $ucgpterm = $gpterm;
       $ucgpterm =~ s/^(\w)/uc($1)/e;
       my $crstype = &Apache::loncommon::course_type();
   
     my %functions = (      my %functions = (
                       email => 'E-mail',                        email => 'E-mail',
                       discussion => 'Discussion boards',                        discussion => 'Discussion boards',
                       chat => 'Chat',                        chat => 'Chat',
                       files => 'File repository',                        files => 'File repository',
                       roster => 'Membership roster',                        roster => 'Membership roster',
                       homepage => 'Group home page',                        homepage => $ucgpterm.' home page',
                     );                      );
   
     my %idx = ();      my %idx = ();
Line 83  sub handler { Line 87  sub handler {
     $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME();      $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME();
     $idx{udom} = &Apache::loncoursedata::CL_SDOM();      $idx{udom} = &Apache::loncoursedata::CL_SDOM();
     $idx{uname} = &Apache::loncoursedata::CL_SNAME();      $idx{uname} = &Apache::loncoursedata::CL_SNAME();
       $idx{section} = &Apache::loncoursedata::CL_SECTION();
     my $rowColor1 = "#dddddd";  
     my $rowColor2 = "#eeeeee";  
   
     my $action = $env{'form.action'};      my $action = $env{'form.action'};
     my $state = $env{'form.state'};      my $state = $env{'form.state'};
     if ((!defined($action)) || ($action eq 'view')) {      if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify')) {
         if (!defined($state)) {          if (!defined($state)) {
             $state = 'view';              $state = 'view';
         }          }
     }      }
     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') {       if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { 
         if ($view_permission || $manage_permission) {          if ($view_permission || $manage_permission) {
             &group_administration($r,$action,$state,$cdom,$cnum,$function,              if ($state eq 'view') {
                                   $tabcol,\%functions,\%idx,$view_permission,                  &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,
                                   $manage_permission,$rowColor1,$rowColor2);                                   $view_permission,$manage_permission,
                                    $action,$state,$gpterm,$ucgpterm,$crstype);
               } else {
                   &group_administration($r,$action,$state,$cdom,$cnum,
                                         \%functions,\%idx,$view_permission,
                                         $manage_permission,$gpterm,$ucgpterm,
           $crstype);
               }
         } else {          } else {
             $r->print(&mt('You do not have group administration '.              $r->print(&mt('You do not have [_1] administration '.
                           'privileges in this course'));                            'privileges in this [_2]',$gpterm,lc($crstype)));
         }          }
     } else {      } else {
         &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx,          &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,$view_permission,
                          $view_permission,$manage_permission,$action,$state,   $manage_permission,$action,$state,$gpterm,$ucgpterm,
                          $rowColor1,$rowColor2);   $crstype);
     }      }
     return OK;      return OK;
 }  }
   
 sub print_main_menu {  sub print_main_menu {
     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,      my ($r,$cdom,$cnum,$functions,$idx,$view_permission,$manage_permission,
         $manage_permission,$action,$state,$rowColor1,$rowColor2) = @_;   $action,$state,$gpterm,$ucgpterm,$crstype) = @_;
     my $jscript = qq|      my $jscript = qq|
 function changeSort(caller) {  function changeSort(caller) {
     document.$state.sortby.value = caller;      document.$state.sortby.value = caller;
     document.$state.submit();      document.$state.submit();
   }
   function openGroupRoster(group,status) {
       var url = '/adm/grouproster?';
       url += 'group='+group+'&status='+status+'&ref=popup';
       var title = 'Group Membership';
       var options = 'scrollbars=1,resizable=1,menubar=0';
       options += ',width=700,height=600';
       rosterbrowser = open(url,title,options,'1');
       rosterbrowser.focus();
 }\n|;  }\n|;
     $r->print(&header('Course Groups',$jscript,$action,$state,      $r->print(&header('Groups',$jscript,$action,$state));
                       undef,$function));      if ($env{'form.refpage'} eq 'enrl') {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>"/adm/dropadd",
                 text=>"Enrollment Manager"});
       }
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/coursegroups",          ({href=>"/adm/coursegroups",
           text=>"Course Groups",});            text=>"Groups"});
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Groups'));      $r->print(&Apache::lonhtmlcommon::breadcrumbs('Groups'));
     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,      &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
                     $view_permission,$manage_permission,$action,$state,      $manage_permission,$action,$state,$gpterm,$ucgpterm,
                     $rowColor1,$rowColor2);      $crstype);
     $r->print(&footer());      $r->print(&footer());
     return;      return;
 }  }
   
 sub display_groups {  sub display_groups {
     my ($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,$view_permission,      my ($r,$cdom,$cnum,$functions,$idx,$view_permission,
         $manage_permission,$action,$state,$rowColor1,$rowColor2) = @_;          $manage_permission,$action,$state,$gpterm,$ucgpterm,$crstype) = @_;
     my %curr_groups = ();      my %curr_groups = ();
     my %grp_info = ();      my %grp_info = ();
     my %actionlinks = (      my %actionlinks = (
       modify => '<a href="/adm/coursegroups?action=modify&refpage='.        modify => '<a href="/adm/coursegroups?action=modify&refpage='.
                          $env{'form.refpage'}.'&groupname=',                           $env{'form.refpage'}.'&state=pick_task&groupname=',
       view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',        view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',
       delete => '<a href="/adm/coursegroups?action=delete&refpage='.        delete => '<a href="/adm/coursegroups?action=delete&refpage='.
                          $env{'form.refpage'}.'&groupname=',                           $env{'form.refpage'}.'&groupname=',
Line 150  sub display_groups { Line 172  sub display_groups {
                           delete => 'Delete',                            delete => 'Delete',
                           act    => 'Action',                            act    => 'Action',
                           gname  => 'Group Name',                            gname  => 'Group Name',
                           desc   => 'Description',                            desc   => 'Group Title',
                           crea   => 'Creator',                            crea   => 'Creator',
                           crtd   => 'Created',                            crtd   => 'Created',
                           last   => 'Last Modified',                            last   => 'Last Modified',
                           func   => 'Functionality',                            func   => 'Collaborative Tools',
                           quot   => 'Quota (Mb)',                            quot   => 'Quota (Mb)',
                           memb   => 'Members',                            memb   => 'Members',
                           file   => 'Files',                            file   => 'Files',
                           dibd   => 'Discussion Boards',                            dibd   => 'Discussion Boards',
                           dius   => 'Disk Use',                            dius   => 'Disk Use (%)',
                           nogr   => 'No groups exist.',                            nogr   => 'No groups exist.',
                           crng   => 'Create a new group',                            crng   => 'Create a new group',
                           alth   => 'Although your current role has privileges'.                            alth   => 'Although your current role has privileges'.
                                     ' to view any existing groups in this course,'.                                      ' to view any existing groups in this'.
                                     ' you do not have privileges to create new'.                                      lc($crstype).', you do not have privileges'.
                                     ' groups.',                                      'to create new groups.',
                      );                       );
     if ($view_permission) {      if ($view_permission) {
         if (!defined($action)) {          if (!defined($action)) {
Line 173  sub display_groups { Line 195  sub display_groups {
         }          }
         my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);          my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
         if (%curr_groups) {          if (%curr_groups) {
               if ($manage_permission) {
                   if (!exists($env{'form.refpage'})) { 
                       $r->print('<br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>');
                   }
               }
             $r->print('<br /><br />');              $r->print('<br /><br />');
             $r->print(&Apache::lonhtmlcommon::start_pick_box());      $r->print(&Apache::loncommon::start_data_table().
         &Apache::loncommon::start_data_table_header_row());
         
             $r->print(<<"END");              $r->print(<<"END");
       <table border="0" cellpadding="4" cellspacing="1">          <th>$lt{'act'}</th>
        <tr bgcolor="$tabcol" align="center">          <th><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></th>
         <td><b>$lt{'act'}</b></td>          <th><a href="javascript:changeSort('description')">$lt{'desc'}</a></th>
         <td><b><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></b></td>          <th><a href="javascript:changeSort('creator')">$lt{'crea'}</a></th>
         <td><b><a href="javascript:changeSort('description')">$lt{'desc'}</a></b></td>          <th><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></th>
         <td><b><a href="javascript:changeSort('creator')">$lt{'crea'}</a></b>          <th><a href="javascript:changeSort('modified')">$lt{'last'}</a></th>
         </td>          <th>$lt{'func'}</b></td>
         <td><b><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></b>          <th><a href="javascript:changeSort('quota')">$lt{'quot'}</a></th>
         </td>          <th><a href="javascript:changeSort('totalmembers')">$lt{'memb'}</a></th>
         <td><b><a href="javascript:changeSort('modified')">$lt{'last'}</a></b>          <th><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></th>
         </td>          <th><a href="javascript:changeSort('boards')">$lt{'dibd'}</a></th>
         <td><b>$lt{'func'}</b>          <th><a href="javascript:changeSort('diskuse')">$lt{'dius'}</a></th>
         </td>  
         <td><b><a href="javascript:changeSort('quota')">$lt{'quot'}</a></b></td>  
         <td><b><a href="javascript:changeSort('totalmembers')">$lt{'memb'}</a></b></td>  
         <td><b><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></b></td>  
         <td><b><a href="javascript:changeSort('boards')">$lt{'dibd'}</a></b></td>  
         <td><b><a href="javascript:changeSort('diskuse')">$lt{'dius'}</a></b></td>  
        </tr>  
 END  END
       $r->print(&Apache::loncommon::end_data_table_header_row());
             my %Sortby = ();              my %Sortby = ();
             foreach my $group (sort(keys(%curr_groups))) {              foreach my $group (sort(keys(%curr_groups))) {
                 %{$grp_info{$group}} =                   %{$grp_info{$group}} = 
Line 203  END Line 226  END
                                                          $curr_groups{$group});                                                           $curr_groups{$group});
                 my $members_result = &group_members($cdom,$cnum,$group,                  my $members_result = &group_members($cdom,$cnum,$group,
                                                     \%grp_info);                                                      \%grp_info);
                 my $files_result = &group_files($group,\%grp_info);                   my $port_path = '/userfiles/groups/'.$group.'/portfolio';
                   my $port_dir = &Apache::loncommon::propath($cdom,$cnum).$port_path;
                   my $totaldirs = 0;
                   my $totalfiles = 0;
                   &group_files($group,$port_dir,\$totalfiles,\$totaldirs);
                   $grp_info{$group}{'totalfiles'} = $totalfiles;
                   $grp_info{$group}{'totaldirs'} = $totaldirs;
                   my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_dir);
                   if ($grp_info{$group}{'quota'} > 0) {
                       my $pct_use = 0.1 * $diskuse/$grp_info{$group}{'quota'};
                       $grp_info{$group}{'diskuse'} = sprintf("%.0f",$pct_use);
                   } else {
                       $grp_info{$group}{'diskuse'} = 'N/A';
                   }
                   my ($groupboards,$boardshash)=&Apache::longroup::get_group_bbinfo(
                                                                  $cdom,$cnum,$group);
                   $grp_info{$group}{'boards'} = scalar(@{$groupboards});
                 if ($env{'form.sortby'} eq 'groupname') {                  if ($env{'form.sortby'} eq 'groupname') {
                     push(@{$Sortby{$group}},$group);                      push(@{$Sortby{$group}},$group);
                 } elsif ($env{'form.sortby'} eq 'description') {                  } elsif ($env{'form.sortby'} eq 'description') {
                     push(@{$Sortby{$grp_info{$group}{'description'}}},                      push(@{$Sortby{$grp_info{$group}{'description'}}},$group);
                                                                      $group);  
                 } elsif ($env{'form.sortby'} eq 'creator') {                  } elsif ($env{'form.sortby'} eq 'creator') {
                     push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);
                 } elsif ($env{'form.sortby'} eq 'creation') {                  } elsif ($env{'form.sortby'} eq 'creation') {
Line 230  END Line 268  END
                     push(@{$Sortby{$group}},$group);                      push(@{$Sortby{$group}},$group);
                 }                  }
             }              }
             my $rowNum = 0;  
             my $rowColor;  
             foreach my $key (sort(keys(%Sortby))) {              foreach my $key (sort(keys(%Sortby))) {
                 foreach my $group (@{$Sortby{$key}}) {                  foreach my $group (@{$Sortby{$key}}) {
                     if ($rowNum %2 == 1) {  
                         $rowColor = $rowColor1;  
                     } else {  
                         $rowColor = $rowColor2;  
                     }  
                     my $description =                       my $description = 
                    &unescape($grp_info{$group}{'description'});   &unescape($grp_info{$group}{'description'});
                     my $creator = $grp_info{$group}{'creator'};                      my $creator = $grp_info{$group}{'creator'};
                     my $creation = $grp_info{$group}{'creation'};                      my $creation = $grp_info{$group}{'creation'};
                     my $modified = $grp_info{$group}{'modified'};                       my $modified = $grp_info{$group}{'modified'}; 
                     my $quota = $grp_info{$group}{'quota'};                      my $quota = $grp_info{$group}{'quota'};
                     my $totalmembers = $grp_info{$group}{'totalmembers'};                      my $totalmembers = $grp_info{$group}{'totalmembers'};
                     my $totalfiles = $grp_info{$group}{'totalfiles'};                      my $totalfiles = $grp_info{$group}{'totalfiles'};
                       my $totaldirs = $grp_info{$group}{'totaldirs'};
                     my $boards = $grp_info{$group}{'boards'};                      my $boards = $grp_info{$group}{'boards'};
                     my $diskuse = $grp_info{$group}{'diskuse'};                      my $diskuse = $grp_info{$group}{'diskuse'};
                     my $functionality;                      my $functionality;
Line 262  END Line 294  END
                     if ($action eq 'modify' || $action eq 'delete') {                      if ($action eq 'modify' || $action eq 'delete') {
                         $link .= $group;                          $link .= $group;
                     } else {                      } else {
                         $link .= $group.'/grppg';                          $link .= $group.'/smppg?ref=grouplist';
                           if (exists($env{'form.refpage'})) {
                               $link .= '&amp;refpage='.$env{'form.refpage'};
                           }
                     }                      }
                     $link .= '">'.$lt{$action}.'</a>';                      $link .= '">'.$lt{$action}.'</a>';
                     if ($action eq 'view') {                       if ($action eq 'view') { 
Line 272  END Line 307  END
                                       $group.'">'.$lt{'modify'}.'</a>';                                        $group.'">'.$lt{'modify'}.'</a>';
                         }                          }
                     }                      }
                     $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$link.'</small></td><td><small>'.$group.'</small></td><td><small>'.$description.'</small></td><td><small>'.$creator.'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($creation).'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($modified).'</small></td><td><small>'.$functionality.'</small></td><td><small>'.$quota.'</small></td><td><small>'.$totalmembers.'</small></td><td><small>'.$totalfiles.'</small></td><td><small>'.$boards.'</small></td><td><small>'.$diskuse.'</small></td></tr>');                      $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').
                     $rowNum ++;        '<td>'.$link.'</td>'.
         '<td>'.$group.'</td>'.
         '<td>'.$description.'</td>'.
         '<td>'.$creator.'</td>'.
         '<td>'. &Apache::lonnavmaps::timeToHumanString($creation).'</td>'.
         '<td>'. &Apache::lonnavmaps::timeToHumanString($modified).'</td>'.
         '<td>'.$functionality.'</td>'.
         '<td align="right">'.$quota.'</td>'.
         '<td align="right">'.$totalmembers.'</td>'.
         '<td align="right"><nobr>'.&mt('Files: ').$totalfiles.'</nobr><br /><nobr>'.&mt('Folders: ').$totaldirs.'</nobr></td>'.
         '<td align="right">'.$boards.'</td>'.
         '<td align="right">'.$diskuse.'</td>'.
         &Apache::loncommon::end_data_table_row());
                 }                  }
             }              }
             $r->print('</table>');              $r->print(&Apache::loncommon::end_data_table());
             $r->print(&Apache::lonhtmlcommon::end_pick_box());  
             $r->print('<input type="hidden" name="refpage" '.              $r->print('<input type="hidden" name="refpage" '.
                       'value="'.$env{'form.refpage'}.'" />');                        'value="'.$env{'form.refpage'}.'" />');
             if ($action eq 'view') {              if ($action eq 'view') {
Line 290  END Line 336  END
         } else {          } else {
             $r->print($lt{'nogr'});              $r->print($lt{'nogr'});
             if ($manage_permission) {              if ($manage_permission) {
                 $r->print('<br /><br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');                  if (!exists($env{'form.refpage'})) {
                       $r->print('<br /><br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>');
                   }
             } else {              } else {
                 $r->print('<br /><br />'.$lt{'crng'});                  $r->print('<br /><br />'.$lt{'alth'});
   
             }              }
         }          }
Line 307  END Line 355  END
                                         $curr_groups{$group});                                          $curr_groups{$group});
                     my $description = &unescape(                      my $description = &unescape(
                                         $group_info{description});                                          $group_info{description});
                     my ($uname,$udom) = split(/:/,$group_info{creator});                      $r->print('<font size="+1"><a href="/adm/'.$cdom.'/'.$cnum.'/'.$group.'/smppg?ref=grouplist">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');
                     $r->print('<font size="+1"><a href="/adm/'.$udom.'/'.$uname.'/'.$group.'/grppg">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');  
                 }                  }
             }              }
         } else {          } else {
             $r->print(&mt('You are not currently a member of any '.              $r->print(&mt('You are not currently a member of any '.
                           'active groups in this course'));                            'active [_1]s in this [_2]',$gpterm,
                             lc($crstype)));
         }          }
     }      }
     return;      return;
 }  }
   
 sub group_administration {  sub group_administration {
     my ($r,$action,$state,$cdom,$cnum,$function,$tabcol,$functions,$idx,      my ($r,$action,$state,$cdom,$cnum,$functions,$idx,$view_permission,
         $view_permission,$manage_permission,$rowColor1,$rowColor2) = @_;   $manage_permission,$gpterm,$ucgpterm,$crstype) = @_;
     my %sectioncount = ();      my %sectioncount = ();
     my @tools = ();      my @tools = ();
     my @types = ();      my @types = ();
     my @roles = ();      my @roles = ();
     my @sections = ();      my @sections = ();
       my @buildsections = ();
     my %users = ();      my %users = ();
     my %userdata = ();      my %userdata = ();
     my @members = ();      my @members = ();
Line 335  sub group_administration { Line 384  sub group_administration {
     my %memchg;      my %memchg;
     my @member_changes = ('deletion','expire','activate','reenable',      my @member_changes = ('deletion','expire','activate','reenable',
                           'changefunc','changepriv');                            'changefunc','changepriv');
     my ($groupname,$description,$startdate,$enddate,$granularity,$specificity);      my ($groupname,$description,$startdate,$enddate,$granularity,$specificity,
           $quota,$validate_script);
   
     if (defined($env{'form.groupname'})) {      if (defined($env{'form.groupname'})) {
         $groupname = $env{'form.groupname'};          $groupname = $env{'form.groupname'};
Line 359  sub group_administration { Line 409  sub group_administration {
         if (defined($env{'form.specificity'})) {          if (defined($env{'form.specificity'})) {
             $specificity=$env{'form.specificity'};              $specificity=$env{'form.specificity'};
         }          }
           if (defined($env{'form.quota'})) {
               $quota=$env{'form.quota'};
           }
     }      }
     if (($action eq 'create') || (($action eq 'modify')       if (($action eq 'create') || (($action eq 'modify') 
         && (($state eq 'pick_privs') || ($state eq 'addresult')))) {          && (($state eq 'pick_privs') || ($state eq 'addresult')))) {
Line 375  sub group_administration { Line 427  sub group_administration {
         if ($state eq '') {          if ($state eq '') {
             if (defined($env{'form.groupname'})) {              if (defined($env{'form.groupname'})) {
                 $state = 'pick_task';                  $state = 'pick_task';
             } else {  
                 $state = 'pick_group';  
             }              }
         } else {          } else {
             %stored = &retrieve_settings($cdom,$cnum,$groupname);              %stored = &retrieve_settings($cdom,$cnum,$groupname);
Line 398  sub group_administration { Line 448  sub group_administration {
                 $description = $stored{'description'};                  $description = $stored{'description'};
                 $granularity = $stored{'granularity'};                  $granularity = $stored{'granularity'};
                 $specificity =  $stored{'specificity'};                  $specificity =  $stored{'specificity'};
                   $quota = $stored{'quota'};
             }              }
         }          }
     }      }
   
     my %toolprivs =      my $toolprivs = &Apache::longroup::get_tool_privs($gpterm);
  (  
  email      => {  
      sgm => 'Send group mail',  
      sgb => 'Broadcast mail',  
  },  
  discussion => {  
      cgb => 'Create boards',  
      pgd => 'Post',  
      pag => 'Anon. posts',  
      rgi => 'Get identities',   
      vgb => 'View boards',  
  },  
  chat       => {  
      pgc => 'Chat',  
  },  
  files      => {  
      rgf => 'Retrieve',  
      ugf => 'Upload',  
              mgf => 'Modify',  
      dgf => 'Delete',  
              agf => 'Control Access',  
  },  
  roster     => {  
      vgm => 'View',  
  },  
  homepage   => {  
      vgh => 'View page',  
      mgh => 'Modify page',  
  },  
  );  
   
     my %fixedprivs =       my $fixedprivs = &Apache::longroup::get_fixed_privs();
  (  
  email      => {sgm => 1},  
  discussion => {vgb => 1},  
  chat       => {pgc => 1},  
  files      => {rgf => 1},  
  roster     => {vgm => 1},  
  homepage   => {vgh => 1},  
  );  
   
     my %elements =       my %elements = 
  (   (
Line 462  sub group_administration { Line 475  sub group_administration {
  enddate_second   => 'text',   enddate_second   => 'text',
  groupname        => 'text',   groupname        => 'text',
  description      => 'text',   description      => 'text',
                    quota            => 'text',
  tool             => 'checkbox',   tool             => 'checkbox',
  granularity      => 'radio',   granularity      => 'radio',
  no_end_date      => 'checkbox',   no_end_date      => 'checkbox',
Line 506  sub group_administration { Line 520  sub group_administration {
        (($action eq 'modify') && (($state eq 'change_settings') ||         (($action eq 'modify') && (($state eq 'change_settings') ||
                                   ($state eq 'add_members')))) {                                    ($state eq 'add_members')))) {
         %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);          %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
         if (%sectioncount) {          $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';          $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';
             $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';          $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';
             $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';  
         }  
     }      }
   
     if (($action eq 'create') ||       if (($action eq 'create') || 
Line 524  sub group_administration { Line 536  sub group_administration {
         if (defined($env{'form.sectionpick'})) {          if (defined($env{'form.sectionpick'})) {
             @sections=&Apache::loncommon::get_env_multiple('form.sectionpick');              @sections=&Apache::loncommon::get_env_multiple('form.sectionpick');
             if (grep/^all$/,@sections) {              if (grep/^all$/,@sections) {
                 @sections = sort {$a cmp $b} keys(%sectioncount);                  @buildsections = sort {$a cmp $b} keys(%sectioncount);
               } else {
                   @buildsections = @sections;
             }              }
         }          }
     }      }
   
     if (($state eq 'pick_members') || ($state eq 'pick_privs') || ($state eq 'change_privs')) {      if (($state eq 'pick_members') || ($state eq 'pick_privs') || ($state eq 'change_privs')) {
         &build_members_list($cdom,$cnum,\@types,\@roles,\@sections,\%users,          &build_members_list($cdom,$cnum,\@types,\@roles,\@buildsections,\%users,
                             \%userdata);                              \%userdata);
     }      }
     if ($state eq 'pick_members') {      if ($state eq 'pick_members') {
Line 566  sub group_administration { Line 580  sub group_administration {
                         $num_reenable ++;                          $num_reenable ++;
                         next;                          next;
                     } elsif (($start > $now)) {                      } elsif (($start > $now)) {
                         $num_activate = 1;                          $num_activate ++;
                         next;                          next;
                     } else {                      } else {
                         $num_expire ++;                          $num_expire ++;
Line 649  sub group_administration { Line 663  sub group_administration {
                         }                          }
                         my @currtools = ();                          my @currtools = ();
                         if (@userprivs > 0) {                          if (@userprivs > 0) {
                             foreach my $tool (sort(keys(%fixedprivs))) {                              foreach my $tool (sort(keys(%{$fixedprivs}))) {
                                 foreach my $priv (keys(%{$fixedprivs{$tool}})) {                                  foreach my $priv (keys(%{$$fixedprivs{$tool}})) {
                                     if (grep/^$priv$/,@userprivs) {                                      if (grep/^$priv$/,@userprivs) {
                                         push(@currtools,$tool);                                          push(@currtools,$tool);
                                         last;                                          last;
Line 720  sub group_administration { Line 734  sub group_administration {
         && ($specificity eq 'Yes')) {          && ($specificity eq 'Yes')) {
         foreach my $user (sort(keys(%usertools))) {          foreach my $user (sort(keys(%usertools))) {
             foreach my $tool (keys(%{$usertools{$user}})) {              foreach my $tool (keys(%{$usertools{$user}})) {
                 foreach my $priv (keys(%{$toolprivs{$tool}})) {                  foreach my $priv (keys(%{$$toolprivs{$tool}})) {
                     unless (exists($fixedprivs{$tool}{$priv})) {                      unless (exists($$fixedprivs{$tool}{$priv})) {
                         $elements{$action}{$state}{'userpriv_'.$priv} = 'checkbox';                          $elements{$action}{$state}{'userpriv_'.$priv} = 'checkbox';
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
    
       if (($action eq 'create' && $state eq 'pick_name') || 
           ($action eq 'modify' && $state eq 'change_settings')) {
           my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,\%stored);
           my $space_trim = '/^\s*|\s*\$/g,""';
           my $float_check = '/^([0-9]*\.?[0-9]*)$/';
           $validate_script = '
       var newquota = new String(document.'.$state.'.quota.value);
       newquota.replace('.$space_trim.');
       if (newquota == "" ) {
           document.'.$state.'.quota.value = 0;
           newquota = "0";
       }
       var maxposs = '.sprintf("%.2f",$maxposs).';
       if (newquota > maxposs) {
           alert("The file repository quota you entered for this group ("+newquota+" Mb) exceeds the maximum possible ("+maxposs+" Mb). Please enter a smaller number.");
           return;
       }
       var re_quota = '.$float_check.';
       var check_quota = newquota.match(re_quota);
       if (check_quota == null) {
           alert("The quota you entered contains invalid characters, the quota should only include numbers, with or without a decimal point.");
           return;
       }
       if (newquota == 0) {
           var warn_zero = 0;
           for (var i=0; i<document.'.$state.'.tool.length; i++) {
               if (document.'.$state.'.tool[i].value == "files") {
                   if (document.'.$state.'.tool[i].checked) {
                       warn_zero = 1;
                   }
               }
           }
           if (warn_zero == 1) {
               alert("You have indicated that the file repository should be enabled, but you have set the respository quota to 0 Mb.\nThis will prevent any upload of files.\nPlease set a value or disable the repository feature.");
               return;
           }
       } 
   ';
       }
     my $jscript = &Apache::loncommon::check_uncheck_jscript();      my $jscript = &Apache::loncommon::check_uncheck_jscript();
     $jscript .= qq|      $jscript .= qq|
 function nextPage(formname,nextstate) {  function nextPage(formname,nextstate) {
     formname.state.value= nextstate;      formname.state.value= nextstate;
       $validate_script
     formname.submit();      formname.submit();
 }  }
 function backPage(formname,prevstate) {  function backPage(formname,prevstate) {
Line 752  function changeSort(caller) { Line 806  function changeSort(caller) {
     my %states = ();      my %states = ();
     my %branchstates = ();      my %branchstates = ();
     @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');      @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
     @{$states{'modify'}} = ('pick_group','pick_task');      @{$states{'modify'}} = ('pick_task');
     @{$branchstates{'noprivs'}} = ('result');      @{$branchstates{'noprivs'}} = ('result');
     @{$branchstates{'settings'}} = ('change_settings','chgresult');      @{$branchstates{'settings'}} = ('change_settings','chgresult');
     @{$branchstates{'members'}} = ('change_members','change_privs','memresult');      @{$branchstates{'members'}} = ('change_members','change_privs','memresult');
Line 776  function changeSort(caller) { Line 830  function changeSort(caller) {
     }      }
   
     my $loaditems =  &onload_action($action,$state);      my $loaditems =  &onload_action($action,$state);
     $r->print(&header('Course Groups Manager',      $r->print(&header("Groups Manager",
       $jscript,$action,$state,$page,$function,$loaditems));        $jscript,$action,$state,$page,$loaditems));
   
     if ($env{'form.refpage'} eq 'enrl') {      if ($env{'form.refpage'} eq 'enrl') {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/dropadd",          ({href=>"/adm/dropadd",
           text=>"Enrollment Manager",            text=>"Enrollment Manager",
           faq=>9,bug=>'Instructor Interface',});            faq=>9,bug=>'Instructor Interface',});
     } else {          if ($action eq 'modify') {
               &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>"/adm/coursegroups?refpage=enrl&action=modify",
                 text=>"Groups",
                 faq=>9,bug=>'Instructor Interface',});
           }
       } else { 
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
        ({href=>"/adm/coursegroups",            ({href=>"/adm/coursegroups",
           text=>"Course Groups",              text=>"Groups",
           faq=>9,bug=>'Instructor Interface',});              faq=>9,bug=>'Instructor Interface',});
           if ($env{'form.refpage'} eq 'grouplist') {
               &Apache::lonhtmlcommon::add_breadcrumb
                ({href=>"/adm/$cdom/$cnum/$env{'form.groupname'}/smppg?ref=grouplist",
                  text=>"Group: $description",});
           }
     }      }
   
     my %trail = ();      my %trail = ();
     %{$trail{'create'}} = &Apache::lonlocal::texthash (      %{$trail{'create'}} = &Apache::lonlocal::texthash (
                             pick_name => 'Group Settings',                              pick_name => $ucgpterm.' Settings',
                             pick_members => 'Select Members',                              pick_members => 'Select Members',
                             pick_privs => 'Choose Privileges',                              pick_privs => 'Choose Privileges',
                             result => 'Creation Complete',                              result => 'Creation Complete',
                           );                            );
     %{$trail{'modify'}} = &Apache::lonlocal::texthash(      %{$trail{'modify'}} = &Apache::lonlocal::texthash(
                             pick_group => 'Groups',  
                             pick_task => 'Choose Task',                              pick_task => 'Choose Task',
                             change_settings => 'Group Settings',                              change_settings => "$ucgpterm Settings",
                             change_members => 'Modify/Delete Members',                              change_members => 'Modify/Delete Members',
                             change_privs => 'Change Privileges',                              change_privs => 'Change Privileges',
                             change_mapping => 'Membership Mapping',                              change_mapping => 'Membership Mapping',
Line 815  function changeSort(caller) { Line 879  function changeSort(caller) {
     my %navbuttons = &Apache::lonlocal::texthash(      my %navbuttons = &Apache::lonlocal::texthash(
                              gtns => 'Go to next step',                               gtns => 'Go to next step',
                              gtps => 'Go to previous step',                               gtps => 'Go to previous step',
                              crgr => 'Create group',                               crgr => 'Create '.$gpterm,
                              mose => 'Modify settings',                               mose => 'Modify settings',
                              gtpp => 'Go to previous page',                               gtpp => 'Go to previous page',
                              adme => 'Add members',                               adme => 'Add members',
Line 827  function changeSort(caller) { Line 891  function changeSort(caller) {
                 &Apache::lonhtmlcommon::add_breadcrumb(                  &Apache::lonhtmlcommon::add_breadcrumb(
                    {text=>"$trail{$action}{$state}"});                     {text=>"$trail{$action}{$state}"});
                 $r->print(&Apache::lonhtmlcommon::breadcrumbs                  $r->print(&Apache::lonhtmlcommon::breadcrumbs
   ('Course Groups Manager'));    ("Groups Manager","Creating_Groups"));
                 &display_control($r,$cdom,$cnum,$tabcol,$action,$state,$page,                  &display_control($r,$cdom,$cnum,$action,$state,$page,
                        \%sectioncount,$groupname,$description,$functions,                         \%sectioncount,$groupname,$description,$functions,
                        \@tools,\%toolprivs,\%fixedprivs,$startdate,$enddate,                         \@tools,$toolprivs,$fixedprivs,$startdate,$enddate,
                        \%users,\%userdata,$idx,\%memchg,\%usertools,                         \%users,\%userdata,$idx,\%memchg,\%usertools,
                        $function,$view_permission,$manage_permission,                         $view_permission,$manage_permission,
                        \%stored,$granularity,$specificity,\@types,\@roles,                         \%stored,$granularity,$quota,$specificity,\@types,\@roles,
                        \@sections,\%states,\%navbuttons,$rowColor1,$rowColor2);                         \@sections,\%states,\%navbuttons,$gpterm,$ucgpterm,
    $crstype);
                 last;                  last;
             } else {              } else {
                 if (($state eq 'result') && ($i > 0)) {                  if (($state eq 'result') && ($i > 0)) {
Line 850  function changeSort(caller) { Line 915  function changeSort(caller) {
         }          }
     } elsif (($action eq 'view') && ($view_permission)) {      } elsif (($action eq 'view') && ($view_permission)) {
                         &Apache::lonhtmlcommon::add_breadcrumb(                          &Apache::lonhtmlcommon::add_breadcrumb(
                    {text=>"View groups"});                     {text=>"View $gpterm".'s'});
         $r->print(&Apache::lonhtmlcommon::breadcrumbs          $r->print(&Apache::lonhtmlcommon::breadcrumbs
   ('Course Groups Manager'));    ('Groups Manager'));
         &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,          &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
                         $view_permission,$manage_permission,$action,$state,   $manage_permission,$action,$state,$gpterm,$ucgpterm,
                         $rowColor1,$rowColor2);   $crstype);
   
     }      }
     $r->print(&footer());      $r->print(&footer());
Line 884  sub retrieve_settings { Line 949  sub retrieve_settings {
     $stored{'specificity'} = $groupinfo{'specificity'};      $stored{'specificity'} = $groupinfo{'specificity'};
     $stored{'creation'} = $groupinfo{'creation'};      $stored{'creation'} = $groupinfo{'creation'};
     $stored{'creator'} = $groupinfo{'creator'};      $stored{'creator'} = $groupinfo{'creator'};
       $stored{'quota'} = $groupinfo{'quota'};
   
     foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) {      foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) {
  if ($groupinfo{functions}{$tool} eq 'on') {   if ($groupinfo{functions}{$tool} eq 'on') {
Line 908  sub retrieve_settings { Line 974  sub retrieve_settings {
  foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) {   foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) {
             if (ref($groupinfo{'autosec'}{$role}) eq 'ARRAY') {              if (ref($groupinfo{'autosec'}{$role}) eq 'ARRAY') {
         foreach my $section (@{$groupinfo{'autosec'}{$role}}) {          foreach my $section (@{$groupinfo{'autosec'}{$role}}) {
   
             push (@{$stored{'sec_'.$role}},$section);              push (@{$stored{'sec_'.$role}},$section);
         }          }
         if (@{$groupinfo{'autosec'}{$role}} > 0) {          if (@{$groupinfo{'autosec'}{$role}} > 0) {
Line 920  sub retrieve_settings { Line 987  sub retrieve_settings {
 }  }
   
 sub display_control {  sub display_control {
     my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$sectioncount,$groupname,      my ($r,$cdom,$cnum,$action,$state,$page,$sectioncount,$groupname,
         $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate,          $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate,
         $enddate,$users,$userdata,$idx,$memchg,$usertools,$function,          $enddate,$users,$userdata,$idx,$memchg,$usertools,
         $view_permission,$manage_permission,$stored,$granularity,$specificity,          $view_permission,$manage_permission,$stored,$granularity,$quota,
         $types,$roles,$sections,$states,$navbuttons,$rowColor1,$rowColor2)=@_;          $specificity,$types,$roles,$sections,$states,$navbuttons,
    $gpterm,$ucgpterm,$crstype) = @_;
     if ($action eq 'create') {      if ($action eq 'create') {
         if ($state eq 'pick_name') {          if ($state eq 'pick_name') {
             &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,              &general_settings_form($r,$cdom,$cnum,$action,$state,$page,
                                    $functions,$tools,$toolprivs,$fixedprivs,                                     $functions,$tools,$toolprivs,$fixedprivs,
                                    $sectioncount,$stored,$states,$navbuttons,                                     $sectioncount,$stored,$states,$navbuttons,
                                    $rowColor1,$rowColor2);                                     $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'pick_members') {          } elsif ($state eq 'pick_members') {
             &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &choose_members_form($r,$cdom,$cnum,$action,$state,$page,
                                  $groupname,$description,$granularity,                                   $groupname,$description,$granularity,$quota,
                                  $startdate,$enddate,$tools,$fixedprivs,                                   $startdate,$enddate,$tools,$fixedprivs,
                                  $toolprivs,$functions,$users,$userdata,$idx,                                   $toolprivs,$functions,$users,$userdata,$idx,
                                  $stored,$states,$navbuttons,$rowColor1,                                   $stored,$states,$navbuttons,$gpterm,$ucgpterm,
                                  $rowColor2);   $crstype);
         } elsif ($state eq 'pick_privs') {          } elsif ($state eq 'pick_privs') {
             &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &choose_privs_form($r,$cdom,$cnum,$action,$state,$page,
                                $startdate,$enddate,$tools,$functions,                                 $startdate,$enddate,$tools,$functions,
                                $toolprivs,$fixedprivs,$userdata,$usertools,                                 $toolprivs,$fixedprivs,$userdata,$usertools,
                                $idx,$states,$stored,$sectioncount,$navbuttons,                                 $idx,$states,$stored,$sectioncount,$navbuttons,
                                $rowColor1,$rowColor2);                                 $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'result') {          } elsif ($state eq 'result') {
             &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &process_request($r,$cdom,$cnum,$action,$state,$page,
                              $groupname,$description,$specificity,$userdata,                               $groupname,$description,$specificity,$userdata,
                              $startdate,$enddate,$tools,$functions,                               $startdate,$enddate,$tools,$functions,
                              $toolprivs,$usertools,$idx,$types,$roles,                               $toolprivs,$usertools,$idx,$types,$roles,
                              $sections,$states,$navbuttons,$memchg,                               $sections,$states,$navbuttons,$memchg,
                              $sectioncount,$stored,$rowColor1,$rowColor2);                               $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
         }          }
     } elsif ($action eq 'modify') {      } elsif ($action eq 'modify') {
         my $groupname = $env{'form.groupname'};          my $groupname = $env{'form.groupname'};
         if ($state eq 'pick_group') {          if ($state eq 'pick_task') {
             &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,              &modify_menu($r,$groupname,$page,$gpterm);
                             $view_permission,$manage_permission,$action,$state,  
                             $rowColor1,$rowColor2);  
         } elsif ($state eq 'pick_task') {  
             &modify_menu($r,$groupname,$page);  
         } elsif ($state eq 'change_settings') {          } elsif ($state eq 'change_settings') {
             &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,              &general_settings_form($r,$cdom,$cnum,$action,$state,$page,
                                    $functions,$tools,$toolprivs,$fixedprivs,                                     $functions,$tools,$toolprivs,$fixedprivs,
                                    $sectioncount,$stored,$states,$navbuttons,                                     $sectioncount,$stored,$states,$navbuttons,
                                    $rowColor1,$rowColor2);                                     $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'change_members') {          } elsif ($state eq 'change_members') {
             &change_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &change_members_form($r,$cdom,$cnum,$action,$state,$page,
                                  $groupname,$description,$startdate,$enddate,                                   $groupname,$description,$startdate,$enddate,
                                  $tools,$fixedprivs,$functions,$users,                                   $tools,$fixedprivs,$functions,$users,
                                  $userdata,$granularity,$specificity,$idx,                                   $userdata,$granularity,$quota,$specificity,
                                  $states,$navbuttons,$rowColor1,$rowColor2);                                   $idx,$states,$navbuttons,$gpterm,$ucgpterm);
         } elsif ($state eq 'add_members') {          } elsif ($state eq 'add_members') {
             &add_members_form($r,$tabcol,$action,$state,$page,$startdate,              &add_members_form($r,$cdom,$cnum,$action,$state,$page,$startdate,
                               $enddate,$groupname,$description,$granularity,                                $enddate,$groupname,$description,$granularity,
                               $sectioncount,$tools,$functions,$stored,$states,                                $quota,$sectioncount,$tools,$functions,$stored,
                               $navbuttons,$rowColor1,$rowColor2);                                $states,$navbuttons,$gpterm,$ucgpterm);
         } elsif ($state eq 'pick_members') {          } elsif ($state eq 'pick_members') {
             &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &choose_members_form($r,$cdom,$cnum,$action,$state,$page,
                                  $groupname,$description,$granularity,                                   $groupname,$description,$granularity,$quota,
                                  $startdate,$enddate,$tools,$fixedprivs,                                   $startdate,$enddate,$tools,$fixedprivs,
                                  $toolprivs,$functions,$users,$userdata,$idx,                                   $toolprivs,$functions,$users,$userdata,$idx,
                                  $stored,$states,$navbuttons,$rowColor1,                                   $stored,$states,$navbuttons,$gpterm,$ucgpterm,
                                  $rowColor2);   $crstype);
         } elsif ($state eq 'pick_privs') {          } elsif ($state eq 'pick_privs') {
             &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &choose_privs_form($r,$cdom,$cnum,$action,$state,$page,
                                $startdate,$enddate,$tools,$functions,                                 $startdate,$enddate,$tools,$functions,
                                $toolprivs,$fixedprivs,$userdata,$usertools,                                 $toolprivs,$fixedprivs,$userdata,$usertools,
                                $idx,$states,$stored,$sectioncount,$navbuttons,                                 $idx,$states,$stored,$sectioncount,$navbuttons,
                                $rowColor1,$rowColor2);                                 $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'change_privs') {          } elsif ($state eq 'change_privs') {
             &change_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &change_privs_form($r,$cdom,$cnum,$action,$state,$page,
                                $startdate,$enddate,$tools,$functions,                                 $startdate,$enddate,$tools,$functions,
                                $toolprivs,$fixedprivs,$userdata,$usertools,                                 $toolprivs,$fixedprivs,$userdata,$usertools,
                                $memchg,$idx,$states,$stored,$sectioncount,                                 $memchg,$idx,$states,$stored,$sectioncount,
                                $navbuttons,$rowColor1,$rowColor2);                                 $navbuttons,$gpterm,$ucgpterm);
         } elsif ($state eq 'chgresult' || $state eq 'memresult' ||           } elsif ($state eq 'chgresult' || $state eq 'memresult' || 
                  $state eq 'addresult') {                   $state eq 'addresult') {
             &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page,              &process_request($r,$cdom,$cnum,$action,$state,$page,
                              $groupname,$description,$specificity,$userdata,                               $groupname,$description,$specificity,$userdata,
                              $startdate,$enddate,$tools,$functions,                               $startdate,$enddate,$tools,$functions,
                              $toolprivs,$usertools,$idx,$types,$roles,                               $toolprivs,$usertools,$idx,$types,$roles,
                              $sections,$states,$navbuttons,$memchg,                               $sections,$states,$navbuttons,$memchg,
                              $sectioncount,$stored,$rowColor1,$rowColor2);                               $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
         }          }
     }      }
 }  }
   
 sub header {  sub header {
     my ($bodytitle,$jscript,$action,$state,$page,$function,$loaditems) = @_;      my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_;
     my $start_page=      my $start_page=
  &Apache::loncommon::start_page($bodytitle,   &Apache::loncommon::start_page($bodytitle,
        '<script type="text/javascript">'.         '<script type="text/javascript">'.
        $jscript.'</script>',         $jscript.'</script>',
        {'function'    => $function,         {'add_entries' => $loaditems,});
  'add_entries' => $loaditems,});  
     my $output = <<"END";      my $output = <<"END";
 $start_page  $start_page
 <form method="POST" name="$state">  <form method="POST" name="$state">
Line 1044  sub onload_action { Line 1107  sub onload_action {
     }      }
     if (($action eq 'modify') &&      if (($action eq 'modify') &&
                 ($state eq 'change_settings' || $state eq 'change_members' ||                  ($state eq 'change_settings' || $state eq 'change_members' ||
                  $state eq 'change_privs' || $state eq 'add_members' ||                   $state eq 'change_privs' || $state eq 'add_members')) {
                  $state eq 'pick_members')) {  
  $loaditems{'onload'} =    $loaditems{'onload'} = 
     'javascript:setFormElements(document.'.$state.')';      'javascript:setFormElements(document.'.$state.')';
     }      }
Line 1076  sub build_members_list { Line 1138  sub build_members_list {
 }  }
   
 sub group_files {  sub group_files {
       my ($group,$currdir,$numfiles,$numdirs) = @_;
       my $dirptr=16384;
       my @dir_list=&Apache::portfolio::get_dir_list($currdir,$group);
       foreach my $line (@dir_list) {
           my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$line,16);
           if (($filename !~ /^\.\.?$/) && ($filename !~ /\.meta$/ ) && ($filename !~ /(.*)\.(\d+)\.([^\.]*)$/) && ($filename ne 'no_such_dir')) { 
               if ($dirptr&$testdir) {
                   $currdir .= '/'.$filename;
                   $$numdirs ++;
                   &group_files($numfiles,$numdirs)
               } else {
                   $$numfiles ++;
               }
           }
       }
     return;      return;
 }  }
   
Line 1083  sub group_members { Line 1160  sub group_members {
     my ($cdom,$cnum,$group,$group_info) = @_;      my ($cdom,$cnum,$group,$group_info) = @_;
     my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);      my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);
     my $now = time;      my $now = time;
     my ($tmp)=keys(%memberhash);      my %lt = &Apache::lonlocal::texthash (
     if ($tmp=~/^error:/) {                                            active => 'active',
         $$group_info{'totalmembers'} = 'Unknown - an error occurred';                                            previous => 'previous',
         return $tmp;                                            future => 'future',
     }      );
     my $now = time;      my %membercounts = (  
                            active => 0,
                            previous => 0,
                            future => 0,
                          );
     my $totalmembers = 0;      my $totalmembers = 0;
     my $active = 0;  
     my $previous = 0;  
     my $future = 0;  
     foreach my $member (keys %memberhash) {      foreach my $member (keys %memberhash) {
         $totalmembers ++;          $totalmembers ++;
         my ($end,$start) = split(/:/,$memberhash{$member});          my ($end,$start) = split(/:/,$memberhash{$member});
         unless ($start == -1) {          unless ($start == -1) {
             if (($end!=0) && ($end<$now)) {              if (($end!=0) && ($end<$now)) {
                 $previous ++;                  $membercounts{previous} ++;
             } elsif (($start!=0) && ($start>$now)) {              } elsif (($start!=0) && ($start>$now)) {
                 $future ++;                  $membercounts{future} ++;
             } else {              } else {
                $active ++;                  $membercounts{active} ++;
             }              }
         }          }
     }      }
     if ($totalmembers == 0) {      if ($totalmembers == 0) {
         $$group_info{$group}{'totalmembers'} = 'None';          $$group_info{$group}{'totalmembers'} = 'None';
     } else {      } else {
         $$group_info{$group}{'totalmembers'} = $active.' - active<br />'.$previous.' -previous<br />'.$future.' -future';          foreach my $type ('active','previous','future') {
               $$group_info{$group}{'totalmembers'} .= 
                  &open_list_window($group,$type,$membercounts{$type},$lt{$type});
           }
     }      }
     return 'ok';      return 'ok';
 }  }
   
   sub open_list_window {
       my ($group,$status,$count,$text) = @_;
       my $entry;
       if ($count > 0) {
           $entry = '<nobr><a href="javascript:openGroupRoster('.
                    "'$group','$status'".')">'.$text.'</a>&nbsp;-&nbsp;'.$count.
                    '</nobr><br />';
       } else {
           $entry = '<nobr>'.$text.'&nbsp;-&nbsp;'.$count.'</nobr><br />';
       }
       return $entry;
   }
   
   
 sub general_settings_form {  sub general_settings_form {
     my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools,      my ($r,$cdom,$cnum,$action,$formname,$page,$functions,$tools,
         $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,          $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
         $rowColor1,$rowColor2) = @_;          $gpterm,$ucgpterm,$crstype) = @_;
     my ($nexttext,$prevtext);      my ($nexttext,$prevtext);
     $r->print(' <br />      &groupsettings_options($r,$functions,$action,$formname,$stored,1,
  <table width="100%" cellpadding="0" cellspacing="0" border="0">                             $gpterm,$ucgpterm,$crstype);
 ');      &access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm);
     &groupsettings_options($r,$tabcol,$functions,$action,$formname,$stored,1);  
     $r->print('   
   <tr>  
    <td colspan="4">&nbsp;</td>  
   </tr>');  
     &access_date_settings($r,$tabcol,$action,$formname,$stored,2);  
     $r->print('  
   <tr>  
    <td colspan="4">&nbsp;</td>  
   </tr>');  
     if ($action eq 'create') {      if ($action eq 'create') {
         &membership_options($r,$action,$formname,$tabcol,$sectioncount,3);          &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,3,
                               $gpterm,$ucgpterm);
         $nexttext = $$navbuttons{'gtns'};          $nexttext = $$navbuttons{'gtns'};
     } else {      } else {
         my @available = ();          my @available = ();
         my @unavailable = ();          my @unavailable = ();
         &check_tools($functions,$tools,\@available,\@unavailable);          &check_tools($functions,$tools,\@available,\@unavailable);
         @{$tools} = sort(keys(%{$functions}));          @{$tools} = sort(keys(%{$functions}));
         &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,          &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs,
                                3,$tools,$stored,$toolprivs,$fixedprivs,         $fixedprivs,\@available,$formname,
                                \@available,$formname);         $gpterm,$ucgpterm);
         $r->print('          &mapping_options($r,$action,$formname,$page,$sectioncount,
   <tr>                           $states,$stored,$navbuttons,4,5,
    <td colspan="4">&nbsp;</td>   $gpterm,$ucgpterm,$crstype,$cdom,$cnum);
   </tr>');  
         &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,  
                          $states,$stored,$navbuttons,4,5,$rowColor1,  
                          $rowColor2);  
         $nexttext = $$navbuttons{'mose'};          $nexttext = $$navbuttons{'mose'};
     }      }
     $prevtext = $$navbuttons{'gtpp'};      $prevtext = $$navbuttons{'gtpp'};
     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,      &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                         $$states{$action}[$page+1],$nexttext);                          $$states{$action}[$page+1],$nexttext);
     $r->print('  
  </table>');  
     return;      return;
 }  }
   
 sub groupsettings_options {  sub groupsettings_options {
     my ($r,$tabcol,$functions,$action,$formname,$stored,$image) = @_;      my ($r,$functions,$action,$formname,$stored,$image,$gpterm,
           $ucgpterm,$crstype) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'gdat' => 'Group open and close dates',          'gdat' => "Group access start and end dates",
         'sten' => 'Set a start date/time and end date/time for the group',          'gnde' => "Group name, title and available collaborative tools",
         'gfun' => 'Group functionality',          'desc' => 'Group Title',
         'gnde' => 'Group name, description and available functionality',          'func' => 'Collaborative Tools',
         'desc' => 'Description',  
         'func' => 'Functionality',  
         'gnam' => 'Group Name',          'gnam' => 'Group Name',
         'doyo' => 'Do you want to assign different functionality '.          'lett' => 'Letters, numbers and underscore only',
                   'to different group members?',          'doyo' => 'Different subsets of the chosen collaborative tools '.
                     'for different group members?',
     );      );
     &topic_bar($r,$tabcol,$image,$lt{'gnde'});      my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored);
       &topic_bar($r,$image,$lt{'gnde'});
     $r->print('      $r->print('
    <tr>       <table class="LC_descriptive_input">
     <td>&nbsp;</td>  
     <td colspan="3">  
      <table border="0" cellpadding="2" cellspacing="2">  
       <tr>        <tr>
        <td><b>'.$lt{'gnam'}.':</b></td>         <td class="LC_description">'.$lt{'gnam'}.':</td>
        <td colspan="5">         <td colspan="5">
 ');  ');
     if ($action eq 'create') {      if ($action eq 'create') {
         $r->print('<input type="text" name="groupname" size="25" />');          $r->print('<input type="text" name="groupname" size="25" />&nbsp;('.
                     $lt{'lett'}.')');
     } else {      } else {
         $r->print('<input type="hidden" name="groupname" value="'.          $r->print('<input type="hidden" name="groupname" value="'.
                          $env{'form.groupname'}.'" />'.$env{'form.groupname'});                           $env{'form.groupname'}.'" />'.$env{'form.groupname'});
Line 1194  sub groupsettings_options { Line 1272  sub groupsettings_options {
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>$lt{'desc'}:</b></td>         <td class="LC_description">$lt{'desc'}:</td>
        <td colspan="5"><input type="text" name="description" size="40"         <td colspan="5"><input type="text" name="description" size="40"
                                                     value="" />                                                      value="" />
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>$lt{'func'}:</b></td>         <td class="LC_description">$lt{'func'}:</td>
 END  END
     my $numitems = keys(%{$functions});      my $numitems = keys(%{$functions});
     my $halfnum = int($numitems/2);      my $halfnum = int($numitems/2);
Line 1234  END Line 1312  END
        </td>         </td>
       </tr>        </tr>
       <tr>        <tr>
        <td><b>Granularity:</b></td>         <td class="LC_description">'.&mt('Granularity:').'</td>
        <td colspan="9">'.$lt{'doyo'}.'&nbsp;<label><input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'</label>&nbsp;<label><input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No').'</label>');         <td colspan="10">'.$lt{'doyo'}.'&nbsp;<label><input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'</label>&nbsp;<label><input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No').'</label>');
     if ($action eq 'modify') {      if ($action eq 'modify') {
         $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',          $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',
                                       $$stored{'granularity'}).')');                                        $$stored{'granularity'}).')');
Line 1243  END Line 1321  END
     $r->print('      $r->print('
        </td>         </td>
       </tr>        </tr>
         <tr>
          <td class="LC_description">'.&mt('Disk quota: ').'</td><td colspan="10">');
       if ($action eq 'create') {
           $r->print(&mt('If you enable the file repository for the [_1], allocate a disk quota.',$gpterm));
       } else {
           $r->print(&mt('Quota allocated to file repository:'));
       } 
       $r->print('&nbsp;<input type="text" name="quota" size="4" />Mb');
       if ($action eq 'create') {
           $r->print('<br />'.
                     &mt('A total of [_1] Mb can be divided amongst all [_2]s in the '.
                     '[_3], and [_4] Mb are currently unallocated.',$crsquota,
                     $gpterm,lc($crstype),sprintf("%.2f",$freespace)));
       } else {
           $r->print('&nbsp;&nbsp;('.&mt('The quota is currently [_1] Mb',
                                         $$stored{'quota'}).').');
   
           $r->print('<br />'.&mt('The quota can be increased to [_1] Mb, '.
                     'by adding all unallocated space for [_2]s in the [_3].',
                     sprintf("%.2f",$maxposs),$gpterm,lc($crstype)));
       }
       $r->print('
          </td>
         </tr>
      </table>       </table>
     </td>  
    </tr>  
 ');  ');
     return;      return;
 }  }
   
   sub get_quota_constraints {
       my ($action,$stored) = @_;
       my ($crsquota,$freespace,$maxposs); 
       $crsquota = $env{'course.'.$env{'request.course.id'}.'.internal.coursequota'};
       if ($crsquota eq '') {
           $crsquota = 20;
       }
       $freespace = $crsquota - &Apache::longroup::sum_quotas();
       if ($action eq 'create') {
           $maxposs = $freespace;
       } else {
           $maxposs = $$stored{'quota'} + $freespace;
       }
       return ($crsquota,$freespace,$maxposs);
   }
   
 sub membership_options {  sub membership_options {
     my ($r,$action,$state,$tabcol,$sectioncount,$image) = @_;      my ($r,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm)=@_;
       my $crstype = &Apache::loncommon::course_type();
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                 'pipa' => 'Pick parameters to generate membership list',                  'pipa' => 'Build a list of users for selection of group members',
                 'gmem' => 'Group membership options',                  'gmem' => "Group membership selection list criteria:",
                 'picr' => 'Pick the criteria to use to build a list of '.                  'picr' => 'Pick the criteria to use to build a list of '.
                           'course users from which you will select ',                            lc($crstype).' users from which you will select ',
                 'meof' => 'members of the new group.',                  'meof' => "members of the new group.",
                 'admg' => 'additional members of the group.',                  'admg' => "additional members of the group.",
                 'ifno' => 'If you do not wish to add members when you first '.                  'ifno' => "If you do not wish to add members when you first ".
                           'create the group, do not make any selections.',                            "create the group, there is no need to pick any criteria.",
                 'asub' => 'A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified role and section changes.',                  'asub' => "A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section <i>changes</i> in the course.",
                 'acty' => 'Access types',                  'acty' => 'Access types',
                 'coro' => 'Course roles',                  'coro' => $crstype.' roles',
                 'cose' => 'Course sections',                  'cose' => $crstype.' sections',
              );               );
     my %status_types = (      my %status_types = (
                    active => &mt('Currently has access'),                     active => &mt('Currently has access'),
Line 1276  sub membership_options { Line 1393  sub membership_options {
   
     my @sections = keys(%{$sectioncount});      my @sections = keys(%{$sectioncount});
   
     &topic_bar($r,$tabcol,$image,$lt{'pipa'});      &topic_bar($r,$image,$lt{'pipa'});
     $r->print('      $r->print('
    <tr>       <b>'.$lt{'gmem'}.'</b><br />'.$lt{'picr'});
     <td>&nbsp;</td>  
     <td colspan="3">  
      <b>'.$lt{'gmem'}.'</b><br/>'.$lt{'picr'});  
     if ($action eq 'create') {      if ($action eq 'create') {
         $r->print($lt{'meof'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'});          $r->print($lt{'meof'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'});
     } else {      } else {
Line 1290  sub membership_options { Line 1404  sub membership_options {
     $r->print('      $r->print('
      <br />       <br />
      <br />       <br />
      <table border="0">       <table class="LC_status_selector">
       <tr>        <tr>
        <td><b>'.$lt{'acty'}.'</b></td>         <th>'.$lt{'acty'}.'</th>
        <td>&nbsp;</td>         <th>'.$lt{'coro'}.'</th>
        <td><b>'.$lt{'coro'}.'</b></td>');         <th>'.$lt{'cose'}.'</th>
     if (@sections >0) {        </tr><tr><td>');
         $r->print('  
        <td>&nbsp;</td>  
        <td><b>'.$lt{'cose'}.'</b></td>  
        <td>&nbsp;</td>');  
     }  
     $r->print('</tr><tr>');  
     $r->print(&Apache::lonhtmlcommon::status_select_row(\%status_types));      $r->print(&Apache::lonhtmlcommon::status_select_row(\%status_types));
     $r->print('<td>&nbsp;</td>');      $r->print('</td><td>');
     $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));      $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles,undef,undef,1,$cdom,$cnum));
     if (@sections > 0) {      if (@sections > 0) {
         @sections = sort {$a cmp $b} @sections;          @sections = sort {$a cmp $b} @sections;
         unshift(@sections,'all'); # Put 'all' at the front of the list  
         unshift(@sections,'none'); # Put 'no sections' next          unshift(@sections,'none'); # Put 'no sections' next
         $r->print('<td>&nbsp;</td>          unshift(@sections,'all'); # Put 'all' at the front of the list
                    <td colspan="3" align="center" valign="top">'.      } else {
         &sections_selection(\@sections,'sectionpick').'</td>');          @sections = ('all','none');
     }      }
     $r->print('      $r->print('</td><td>'.
                 &sections_selection(\@sections,'sectionpick').'</td>
       </tr>        </tr>
      </table>       </table>');
     </td>  
    </tr>');  
     return;      return;
 }  }
   
Line 1330  sub sections_selection { Line 1436  sub sections_selection {
     }      }
     foreach my $sec (@{$sections}) {      foreach my $sec (@{$sections}) {
         if ($sec eq 'all') {          if ($sec eq 'all') {
             $section_sel .= '  <option value="'.$sec.'" />all sections'."\n";              $section_sel .= '  <option value="'.$sec.'">'.&mt('all sections').'</option>'."\n";
         } elsif ($sec eq 'none') {          } elsif ($sec eq 'none') {
             $section_sel .= '  <option value="'.$sec.'" />no section'."\n";               $section_sel .= '  <option value="'.$sec.'">'.&mt('no section').'</option>'."\n"; 
         } else {          } else {
             $section_sel .= '  <option value="'.$sec.'" />'.$sec."\n";              $section_sel .= '  <option value="'.$sec.'">'.$sec."</option>\n";
         }          }
     }      }
     my $output = '      my $output = '
Line 1345  sub sections_selection { Line 1451  sub sections_selection {
 }  }
   
 sub access_date_settings {  sub access_date_settings {
     my ($r,$tabcol,$action,$formname,$stored,$image) = @_;      my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                 'sten' => 'Default start and end dates for group access',                  'sten' => "Default start and end dates for $gpterm access",
              );               );
     my $starttime = time;      my $starttime = time;
     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx      my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
Line 1357  sub access_date_settings { Line 1463  sub access_date_settings {
             $endtime = $$stored{'enddate'};              $endtime = $$stored{'enddate'};
         }          }
     }      }
     my ($start_table,$end_table) = &date_setting_table      my ($table) = &date_setting_table($starttime,$endtime,$formname);
                                     ($starttime,$endtime,$formname);      &topic_bar($r,$image,$lt{'sten'});
     &topic_bar($r,$tabcol,$image,$lt{'sten'});  
     $r->print('      $r->print('
    <tr>      '.$table.'
     <td>&nbsp;</td>      ');
     <td colspan="3">'.$start_table.'</td>  
    <tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>  
     <td>&nbsp;</td>  
     <td colspan="3">'.$end_table.'</td>  
    <tr>');  
     return;      return;
 }  }
   
 sub choose_members_form {  sub choose_members_form {
     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,      my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description,
         $granularity,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,          $granularity,$quota,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
         $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,          $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
         $rowColor1,$rowColor2) = @_;          $gpterm,$ucgpterm,$crstype) = @_;
     my @regexps = ('user_','userpriv_','sec_');      my @regexps = ('user_','userpriv_','sec_');
     my %origmembers;      my %origmembers;
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      $r->print(&Apache::lonhtmlcommon::echo_form_input(
          ['origin','action','state','page','member','specificity','branch',           ['origin','action','state','page','member','specificity','branch',
           'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'],            'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'],
          \@regexps));           \@regexps));
     my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);      my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
     $r->print('                                         $ucgpterm,$crstype);
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
 ');  
     if ($earlyout) {      if ($earlyout) {
         $r->print($earlyout.'</td></tr>');   $r->print($earlyout);
         &display_navbuttons($r,$formname,$$states{$action}[$page-1],          &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                            $$navbuttons{'gtps'});                             $$navbuttons{'gtps'});
         $r->print('</table>');  
         return;          return;
     }       } 
     my ($specimg,$memimg);      my ($specimg,$memimg);
Line 1405  sub choose_members_form { Line 1495  sub choose_members_form {
     my @unavailable = ();      my @unavailable = ();
     &check_tools($functions,$tools,\@available,\@unavailable);      &check_tools($functions,$tools,\@available,\@unavailable);
     if ($action eq 'create') {      if ($action eq 'create') {
         &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,          &print_current_settings($r,$action,$functions,$startdate,$enddate,
                                 $functions,$startdate,$enddate,$groupname,   $groupname,$description,$granularity,$quota,
                                 $description,$granularity,\@available,   \@available,\@unavailable,$gpterm,$ucgpterm);
                                 \@unavailable);  
         $specimg = 4;          $specimg = 4;
         $memimg = 5;          $memimg = 5;
     } else {      } else {
Line 1428  sub choose_members_form { Line 1517  sub choose_members_form {
             }              }
         }          }
     }      }
     &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,      &privilege_specificity($r,$action,$specimg,$tools,$stored,$toolprivs,
                           $specimg,$tools,$stored,$toolprivs,                            $fixedprivs,\@available,$formname,$gpterm,$ucgpterm);
                           $fixedprivs,\@available,$formname);      my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx,
     my $newusers = &pick_new_members($r,$action,$formname,$tabcol,$rowColor1,       $stored,$memimg,$users,$userdata,
                                     $rowColor2,\@available,$idx,$stored,       $granularity,\%origmembers,$gpterm,
                                     $memimg,$users,$userdata,$granularity,       $ucgpterm);
                                     \%origmembers);  
     if ($newusers || $action eq 'create') {      if ($newusers || $action eq 'create') {
         &display_navbuttons($r,$formname,$$states{$action}[$page-1],          &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                             $$navbuttons{'gtps'},$$states{$action}[$page+1],                              $$navbuttons{'gtps'},$$states{$action}[$page+1],
Line 1443  sub choose_members_form { Line 1531  sub choose_members_form {
         &display_navbuttons($r,$formname,$$states{$action}[$page-1],          &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                             $$navbuttons{'gtps'});                              $$navbuttons{'gtps'});
     }      }
     $r->print('</table>');  
     return;      return;
 }  }
   
 sub display_navbuttons {  sub display_navbuttons {
     my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;      my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
     $r->print('      $r->print('<div class="LC_navbuttons">');
     <tr>  
      <td colspan="4">&nbsp;</td>  
     </tr>  
     <tr>  
      <td>&nbsp;</td>  
      <td colspan="3">');  
     if ($prev) {      if ($prev) {
         $r->print('          $r->print('
       <input type="button" name="previous" value = "'.$prevtext.'"        <input type="button" name="previous" value = "'.$prevtext.'"
Line 1467  sub display_navbuttons { Line 1548  sub display_navbuttons {
       <input type="button" name="next" value="'.$nexttext.'"        <input type="button" name="next" value="'.$nexttext.'"
  onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');   onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
     }      }
     $r->print('      $r->print('</div>');
      </td>  
     </tr>  
 ');  
 }  }
   
 sub check_tools {  sub check_tools {
Line 1486  sub check_tools { Line 1564  sub check_tools {
 }  }
   
 sub print_current_settings {  sub print_current_settings {
     my ($r,$action,$tabcol,$rowColor1,$rowColor2,$functions,$startdate,$enddate,      my ($r,$action,$functions,$startdate,$enddate,$groupname,$description,
            $groupname,$description,$granularity,$available,$unavailable) =@_;   $granularity,$quota,$available,$unavailable,$gpterm,$ucgpterm) = @_;
   
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         grna => 'Group Name',          grna => 'Group Name',
         desc => 'Description',          desc => 'Group Title',
         grfn => 'Group Functions',          grfn => "Collaborative Tools",
         gran => 'Granularity',          gran => 'Granularity',
           quot => 'File quota',
         dfac => 'Default access dates',          dfac => 'Default access dates',
         ygrs => 'Your group selections',          ygrs => "Your group selections - ",
         tfwa => 'The following settings will apply to the group:',          tfwa => "The following settings will apply to the group:",
         difn => 'Different functionality<br />for different users:',          difn => 'Different collaborative tools<br />for different members:',
         stda => 'Start date',          stda => 'Start date',
         enda => 'End date:',          enda => 'End date:',
     );      );
Line 1508  sub print_current_settings { Line 1587  sub print_current_settings {
     } else {      } else {
         $showend = &Apache::lonlocal::locallocaltime($enddate);          $showend = &Apache::lonlocal::locallocaltime($enddate);
     }      }
     $r->print('<table border="0" cellpadding="0" cellspacing="20">');  
     if ($action eq 'create') {      if ($action eq 'create') {
         $r->print('          $r->print('
 <tr>  <div><span style="font-size: larger">'.$lt{'ygrs'}.'</span>
  <td><font face="arial,helvetica,sans-serif"><b>'.$lt{'ygrs'}.'</b></font>  
 <br />'.$lt{'tfwa'}.'  <br />'.$lt{'tfwa'}.'
  </td>  </div>');
 </tr>');  
     }      }
     $r->print('<tr><td>');      $r->print(&Apache::loncommon::start_data_table('LC_course_group_status').
     $r->print(&Apache::lonhtmlcommon::start_pick_box());        &Apache::loncommon::start_data_table_header_row());
     $r->print('      $r->print('
 <tr>    <th>'.$lt{'grna'}.'</th>
  <td>    <th>'.$lt{'desc'}.'</th>
 <table cellspacing="1" cellpadding="4">    <th>'.$lt{'grfn'}.'</th>
  <tr bgcolor="'.$tabcol.'" align="center">    <th>'.$lt{'gran'}.'</th>
   <td><b>'.$lt{'grna'}.'</b></td>    <th>'.$lt{'quot'}.'</th>
   <td><b>'.$lt{'desc'}.'</b></td>    <th>'.$lt{'dfac'}.'</th>
   <td><b>'.$lt{'grfn'}.'</b></td>  ');
   <td><b>'.$lt{'gran'}.'</b></td>      $r->print(&Apache::loncommon::end_data_table_header_row().
   <td><b>'.$lt{'dfac'}.'</b></td>        &Apache::loncommon::start_data_table_row('LC_data_table_dense'));
  </tr>      $r->print('
  <tr bgcolor="'.$rowColor2.'">    <td valign="top">'.$groupname.'</td>
   <td valign="top"><small>'.$groupname.'</small></td>    <td valign="top">'.$description.'</td>
   <td valign="top"><small>'.$description.'</small></td>  
   <td>    <td>
 ');  ');
     if (@{$available} > 0) {      if (@{$available} > 0) {
         $r->print('<small><b>Available:</b></small>          $r->print(&mt('<b>Available for assignment to members:</b>').
                     <table cellpadding="" cellspacing="1"><tr>');                      '<table class="LC_group_priv"><tr>');
         my $rowcell = int(@{$available}/2) + @{$available}%2;          my $rowcell = int(@{$available}/2) + @{$available}%2;
         for (my $i=0; $i<@{$available}; $i++) {          for (my $i=0; $i<@{$available}; $i++) {
             if (@{$available} > 3) {              if (@{$available} > 3) {
Line 1545  sub print_current_settings { Line 1620  sub print_current_settings {
                     $r->print('</tr><tr>');                      $r->print('</tr><tr>');
                 }                  }
             }              }
             $r->print('<td><small>'.$$functions{$$available[$i]}.              $r->print('<td>'.$$functions{$$available[$i]}.
                                           '</small></td><td>&nbsp;</td>');        '</td><td>&nbsp;</td>');
         }          }
         if ((@{$available} > 3) && (@{$available}%2)) {          if ((@{$available} > 3) && (@{$available}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');              $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
Line 1554  sub print_current_settings { Line 1629  sub print_current_settings {
         $r->print('</tr></table><br />');          $r->print('</tr></table><br />');
     }      }
     if (@{$unavailable} > 0) {      if (@{$unavailable} > 0) {
         $r->print('<small><b>Unavailable:</b></small>          $r->print(&mt('<b>Unavailable for assignment:</b>').
                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');                      '<table class="LC_group_priv"><tr>');
         my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2;          my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2;
         for (my $j=0; $j<@{$unavailable}; $j++) {          for (my $j=0; $j<@{$unavailable}; $j++) {
             if (@{$unavailable} > 3) {              if (@{$unavailable} > 3) {
Line 1563  sub print_current_settings { Line 1638  sub print_current_settings {
                     $r->print('</tr><tr>');                      $r->print('</tr><tr>');
                 }                  }
             }              }
             $r->print('<td><small>'.$$functions{$$unavailable[$j]}.              $r->print('<td>'.$$functions{$$unavailable[$j]}.
                                               '</small></td><td>&nbsp;</td>');        '</td><td>&nbsp;</td>');
         }          }
         if ((@{$unavailable} > 3) && (@{$unavailable}%2)) {          if ((@{$unavailable} > 3) && (@{$unavailable}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');              $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
Line 1573  sub print_current_settings { Line 1648  sub print_current_settings {
     }      }
     $r->print(<<"END");      $r->print(<<"END");
   </td>    </td>
   <td valign="top"><small><b>$lt{'difn'}    <td valign="top"><b>$lt{'difn'}</b> $granularity</td>
   </b> $granularity</small>     <td valign="top">$quota Mb</td> 
   <td valign="top"><small><b>$lt{'stda'}</b> $showstart<br />    <td valign="top"><b>$lt{'stda'}</b> $showstart<br />
       <b>$lt{'enda'}</b> $showend</small>        <b>$lt{'enda'}</b> $showend
   </td>    </td>
  </tr>  
 </table>  
 </td>  
 </tr>  
 END  END
     $r->print(&Apache::lonhtmlcommon::end_pick_box());      $r->print(&Apache::loncommon::end_data_table_row().
     $r->print('</td></tr></table><br />');        &Apache::loncommon::end_data_table());
     return;      return;
 }  }
   
 sub pick_new_members {  sub pick_new_members {
     my ($r,$action,$formname,$tabcol,$rowColor1,$rowColor2,$available,$idx,      my ($r,$action,$formname,$available,$idx,$stored,$img,$users,$userdata,
         $stored,$img,$users,$userdata,$granularity,$origmembers) = @_;   $granularity,$origmembers,$gpterm,$ucgpterm) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
           'gpme' => 'Group membership',            'gpme' => "Group membership",
           'addm' => 'Add members',            'addm' => 'Add members',
           'setf' => 'Set functionality',            'setf' => 'Assign collaborative tools', 
           'func' => 'Functionality',            'func' => 'Tools',
           'nome' => 'No members to add at this time.',            'nome' => 'No members to add at this time, as there are no users '.
           'nnew' => 'There are no users to add as new members, as all users'.                       'matching the specified type(s), role(s) and section(s).',
                     ' matching the specified type(s), role(s), and/or '.            'nnew' => "There are no users to add as new members, as all users".
                     'section(s) are already affiliated with this group.',                      " matching the specified type(s), role(s), and ".
                       "section(s) are already affiliated with this group.",
           'yoma' =>  'You may need to use the '."'".'modify existing, past or '.            'yoma' =>  'You may need to use the '."'".'modify existing, past or '.
                      'future members'."'".' page if you need to re-enable '.                       'future members'."'".' page if you need to re-enable '.
                      'or activate access for previous or future members.',                       'or activate access for previous or future members.',
Line 1626  sub pick_new_members { Line 1698  sub pick_new_members {
             $r->print(&check_uncheck_tools($r,$available));              $r->print(&check_uncheck_tools($r,$available));
         }          }
     }      }
     &topic_bar($r,$tabcol,$img,$lt{'gpme'});      &topic_bar($r,$img,$lt{'gpme'});
     if (keys(%members) > 0) {      if (keys(%members) > 0) {
         $r->print('          $r->print('
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
     <table>      <table>
      <tr>');       <tr>');
         &check_uncheck_buttons($r,$formname,'member',$lt{'addm'});          &check_uncheck_buttons($r,$formname,'member',$lt{'addm'});
         if (@{$available} > 0 && $granularity eq 'Yes') {          if (@{$available} > 0 && $granularity eq 'Yes') {
             $r->print('<td><nobr>              $r->print('<td>
      <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>       <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>
         <nobr>
       <input type="button" value="check all"        <input type="button" value="check all"
         onclick="javascript:checkAllTools(document.'.$formname.')" />          onclick="javascript:checkAllTools(document.'.$formname.')" />
         &nbsp;&nbsp;          &nbsp;&nbsp;
       <input type="button" value="uncheck all"        <input type="button" value="uncheck all"
         onclick="javascript:uncheckAllTools(document.'.$formname.')" />          onclick="javascript:uncheckAllTools(document.'.$formname.')" />
      </fieldset></nobr></td>');        </nobr>
        </fieldset></td>');
         }          }
         $r->print('</tr></table>          $r->print('</tr></table>
   </td>  
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
         ');          ');
         $r->print(&Apache::lonhtmlcommon::start_pick_box());          $r->print(&Apache::loncommon::start_data_table().
     &Apache::loncommon::start_data_table_header_row());
         $r->print('          $r->print('
    <table border="0" cellpadding="4" cellspacing="1">       <th>'.&mt('Add?').'</b></td>
     <tr bgcolor="'.$tabcol.'" align="center">       <th><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></td>
      <td><b>'.&mt('Add?').'</b></td>       <th><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></td>
      <td><b><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></b></td>       <th><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></td>
      <td><b><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></b>       <th><a href="javascript:changeSort('."'id'".')">'.&mt('ID').'</a></td>
      </td>       <th><a href="javascript:changeSort('."'section'".')">'.&mt('Section').'</a></td>
      <td><b><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></b></td>  
      <td><b><a href="javascript:changeSort('."'id'".')">ID</a></b></td>  
 ');  ');
         if (@{$available} > 0) {          if (@{$available} > 0) {
             $r->print('<td><b>'.$lt{'func'}.'</b></td>');              $r->print('<th>'.$lt{'func'}.'</th>');
         }          }
         $r->print('</tr>');          $r->print(&Apache::loncommon::end_data_table_header_row());
         if (@{$available} > 0) {          if (@{$available} > 0) {
             if ($granularity eq 'Yes') {              if ($granularity eq 'Yes') {
                 $r->print('<tr bgcolor="#cccccc">                  $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').'
  <td colspan="5">&nbsp;</td>   <td colspan="6">&nbsp;</td>
  <td align="center"><small><nobr><b>'.&mt('All:').'</b>&nbsp;');   <td align="center"><nobr><b>'.&mt('All:').'</b>&nbsp;');
                 foreach my $tool (@{$available}) {                  foreach my $tool (@{$available}) {
                     $r->print('<label><input type="checkbox" name="togglefunc" '.                      $r->print('<label><input type="checkbox" name="togglefunc" '.
    'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.     'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
    ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');     ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
                 }                  }
                 $r->print('</nobr></small></td></tr>');                  $r->print('</nobr></td></tr>');
             }              }
         }          }
         my %Sortby = ();          my %Sortby = ();
Line 1693  sub pick_new_members { Line 1755  sub pick_new_members {
                 push(@{$Sortby{$members{$user}[$$idx{udom}]}},$user);                  push(@{$Sortby{$members{$user}[$$idx{udom}]}},$user);
             } elsif ($env{'form.sortby'} eq 'id') {              } elsif ($env{'form.sortby'} eq 'id') {
                 push(@{$Sortby{$members{$user}[$$idx{id}]}},$user);                  push(@{$Sortby{$members{$user}[$$idx{id}]}},$user);
               } elsif ($env{'form.sortby'} eq 'section') {
                   push(@{$Sortby{$members{$user}[$$idx{section}]}},$user);
             } else {              } else {
                 push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);                  push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);
             }              }
         }          }
         my $rowNum = 0;  
         my $rowColor;  
         foreach my $key (sort(keys(%Sortby))) {          foreach my $key (sort(keys(%Sortby))) {
             foreach my $user (@{$Sortby{$key}}) {              foreach my $user (@{$Sortby{$key}}) {
                 if ($rowNum %2 == 1) {  
                     $rowColor = $rowColor1;  
                 } else {  
                     $rowColor = $rowColor2;  
                 }  
                 my $id = $members{$user}[$$idx{id}];                  my $id = $members{$user}[$$idx{id}];
                 my $fullname = $members{$user}[$$idx{fullname}];                  my $fullname = $members{$user}[$$idx{fullname}];
                 my $udom = $members{$user}[$$idx{udom}];                  my $udom = $members{$user}[$$idx{udom}];
                 my $uname = $members{$user}[$$idx{uname}];                  my $uname = $members{$user}[$$idx{uname}];
                 $r->print('<tr bgcolor="'.$rowColor.'"><td align="right">                  my $section = $members{$user}[$$idx{section}];
    <input type="checkbox" name="member" value="'.$user.'" /></td><td><small>'.                  $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').
     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.    '<td align="right"><input type="checkbox" name="member" value="'.$user.'" /></td>'.
     $udom.'</small></td><td><small>'.$id.'</small></td>');    '<td>'.$fullname.'</td>'.
     '<td>'.$uname.'</td>'.
     '<td>'.$udom.'</td>'.
     '<td>'.$id.'</td>'.
     '<td>'.$section.'</td>');
                 if (@{$available} > 0) {                  if (@{$available} > 0) {
                     $r->print('<td align="center"><nobr><small>'.                      $r->print('<td align="center"><nobr>'.
                               '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');                                '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                     foreach my $tool (@{$available}) {                      foreach my $tool (@{$available}) {
                         if ($granularity eq 'Yes') {                          if ($granularity eq 'Yes') {
Line 1726  sub pick_new_members { Line 1787  sub pick_new_members {
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');                            $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         }                          }
                     }                      }
                     $r->print('</small></nobr></td>');                      $r->print('</nobr></td>');
                 }                  }
                 $r->print('</tr>'."\n");                  $r->print(&Apache::loncommon::end_data_table_row()."\n");
                 $rowNum ++;  
             }              }
         }          }
         $r->print(&Apache::lonhtmlcommon::end_pick_box());          $r->print(&Apache::loncommon::end_data_table());
         $r->print('  
      </td>  
     </tr>');  
     } else {      } else {
         $r->print('  
     <tr>  
      <td>&nbsp;</td>  
      <td colspan="3">  
 ');  
         if ($totalusers > 0) {          if ($totalusers > 0) {
             $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});              $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});
         } else {           } else { 
             $r->print($lt{'nome'});              $r->print($lt{'nome'});
         }          }
         $r->print('  
      </td>  
     </tr>');  
     }      }
     return $newusers;      return $newusers;
 }  }
   
 sub privilege_specificity {  sub privilege_specificity {
     my ($r,$tabcol,$rowColor1,$rowColor2,$action,$img,$tools,$stored,      my ($r,$action,$img,$tools,$stored,$toolprivs,$fixedprivs,$available,
         $toolprivs,$fixedprivs,$available,$formname) = @_;   $formname,$gpterm,$ucgpterm) = @_;
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
       'uprv' => 'User privileges',        'uprv' => 'User privileges for collaborative tools',
       'frty' => 'For each type of functionality you have chosen to include, '.        'frty' => 'For each collaborative tool you have chosen to include, '.
                 'there is a set of standard privileges which apply to all '.                  'there is a set of core privileges which all group members '.
                 'of those for whom the functionality is enabled.',                  'assigned use of the tool will receive.',
       'thar' => 'There are also additional privileges which can be set for '.        'thar' => 'For some tools there are also additional optional '.
                 'some, or all, members. Please choose one of the following:',                   'privileges which can be set.',
       'fort' => 'For the types of functionality you have chosen to include '.        'plch' => 'Choose one of the following:',
                 'there are no additional privileges which can be set for some '.        'fort' => 'For the collaborative tools you have chosen to include '.
                 'or all members.',                  'only core privileges are available, '.
       'eaty' => 'Each of the types of functionality includes standard '.                  'so there are no optional privileges to assign.',
                 'privileges which apply to members with access to that '.        'eaty' => 'Each collaborative tool includes core '.
                 'functionality, and may also include additional privileges '.                  'privileges assigned to all members with access to the '.
                   'tool. Some tools may also feature additional privileges '.
                 'which can be set for specific members.',                  'which can be set for specific members.',
       'cutg' => 'Currently the group is configured ',        'cutg' => 'Currently the group is configured ',
       'sdif' => 'so different group members can receive different privileges.',        'sdif' => 'so different members can receive different optional privileges for a particular tool.',
       'sall' => 'so all group members will receive the same privileges.',        'sall' => 'so all members will receive the same optional privileges for a particular tool.',
       'algm' => 'All group members will receive the same privileges.',        'algm' => 'All group members will receive the same privileges for any tool assigned to them, including the default set of optional privileges.',
       'smgp' => 'Some group members will receive different privileges from '.        'smgp' => 'Different group members may receive different privileges from '.
                 'others.',                  'others for the tools they have been assigned.',
       'thwi' => 'These will be the privileges all group members receive, '.         'thwi' => 'These will be the privileges all group members receive for a particular assigned tool, '. 
                 'if you selected the first option above.',                  'if you selected the first option above.',
       'thes' => 'These will be the privileges given to members assigned '.           'thes' => "These will be the privileges given to members assigned ".   
                 'in the future, including via automatic group assignment '.                  "in the future via automatic group assignment ".
                 'for specific sections/roles ',                  "for users who receive specific sections/roles in the course ",
       'asyo' => 'As you have chosen not to include any functionality in the '.        'asyo' => "As you have chosen not to include any collaborative tools ".
                 'group, no default user privileges settings need to be set.',                  "in the group, no default optional privileges need to be set.",
       'plin' => 'Please indicate which <b>optional</b> privileges members '.        'plin' => 'Indicate which <b>optional</b> privileges members '.
                 'will receive by default.',                  'will receive by default for a specific tool.',
       'oppr' => 'Optional privileges',        'oppr' => 'Optional privileges',
       'defp' => 'The default privileges new members will receive are:',         'defp' => 'The default privileges new members will receive are:', 
     );      );
Line 1797  sub privilege_specificity { Line 1847  sub privilege_specificity {
             }              }
         }          }
     }      }
     &topic_bar($r,$tabcol,$img,$lt{'uprv'});      &topic_bar($r,$img,$lt{'uprv'});
     $r->print('  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
   ');  
     if ((($action eq 'create') && (@{$available} > 0)) ||       if ((($action eq 'create') && (@{$available} > 0)) || 
         (($action eq 'modify') && ($formname eq 'change_settings'))) {            (($action eq 'modify') && ($formname eq 'change_settings'))) {
         my %specific = (          my %specific = (
                       'No'  => 'checked="checked"',                        'No'  => 'checked="checked"',
                       'Yes' => '',                        'Yes' => '',
Line 1812  sub privilege_specificity { Line 1857  sub privilege_specificity {
         if ($action eq 'create') {          if ($action eq 'create') {
             $r->print($lt{'frty'}.'<br />');              $r->print($lt{'frty'}.'<br />');
             if ($totaloptionalprivs) {              if ($totaloptionalprivs) {
                 $r->print($lt{'thar'});                  $r->print($lt{'thar'}.'<br /><br />'.$lt{'plch'});
             } else {              } else {
                 $r->print($lt{'fort'});                  $r->print($lt{'fort'});
             }              }
Line 1828  sub privilege_specificity { Line 1873  sub privilege_specificity {
         }          }
         if ($totaloptionalprivs) {          if ($totaloptionalprivs) {
             $r->print('              $r->print('
 <br /><br /><label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr></label><br/>  <br />
 <label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr></label>  <label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr></label><br />
   </td>  <label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr></label><br /><br />');
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>');  
         } else {          } else {
             $r->print('<input type="hidden" name="specificity" value="No" />');              $r->print('<input type="hidden" name="specificity" value="No" />');
         }          }
         if ($totaloptionalprivs) {          if ($totaloptionalprivs) {
             $r->print('              $r->print($lt{'plin'});
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">'.$lt{'plin'});  
             if ($action eq 'create') {              if ($action eq 'create') {
                 $r->print(' '.$lt{'thwi'});                  $r->print('<br />'.$lt{'thwi'});
             }              }
             $r->print('<br />'.$lt{'thes'});              $r->print('<br />'.$lt{'thes'});
             if ($action eq 'create') {              if ($action eq 'create') {
Line 1853  sub privilege_specificity { Line 1891  sub privilege_specificity {
                 $r->print('('.&mt('if enabled below').').');                  $r->print('('.&mt('if enabled below').').');
             }              }
             $r->print('<br /><br />              $r->print('<br /><br />
   </td>    <table><tr>');
  </tr>  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="2"><table><tr>');  
         &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});          &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});
         $r->print('          $r->print('
     </tr>      </tr>
    </table>     </table>
   </td>  
   <td width="100%">&nbsp;</td>  
  </tr><tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
    <br />     <br />
 ');  ');
         } else {          } else {
             $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algm'}.'<br /><br />');              $r->print($lt{'algm'}.'<br /><br />');
         }          }
         &default_privileges($r,$action,$tabcol,$rowColor1,$rowColor2,          &default_privileges($r,$action,$tools,$toolprivs,$fixedprivs,
                             $tools,$toolprivs,$fixedprivs,$available);      $available);
     } else {      } else {
         if ($action eq 'create') {          if ($action eq 'create') {
             $r->print($lt{'asyo'});              $r->print($lt{'asyo'});
               $r->print('<input type="hidden" name="specificity" value="No" />');
         } elsif ($action eq 'modify' && $formname eq 'pick_members') {          } elsif ($action eq 'modify' && $formname eq 'pick_members') {
             my @defprivs;              my @defprivs;
             if (ref($$stored{'defpriv'}) eq 'ARRAY') {              if (ref($$stored{'defpriv'}) eq 'ARRAY') {
Line 1889  sub privilege_specificity { Line 1919  sub privilege_specificity {
                 $r->print($lt{'sall'});                  $r->print($lt{'sall'});
             }              }
             $r->print(' '.$lt{'defp'}.'<br /><br />');              $r->print(' '.$lt{'defp'}.'<br /><br />');
             &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,              &display_defprivs($r,$tools,$toolprivs,\@defprivs);
                               $toolprivs,\@defprivs);  
         }          }
     }      }
     $r->print('  
   </td>  
  </tr>  
 ');  
     return;      return;
 }  }
   
 sub default_privileges {  sub default_privileges {
     my ($r,$action,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,      my ($r,$action,$tools,$toolprivs,$fixedprivs,$available) = @_;
         $fixedprivs,$available) = @_;  
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                                 'addp' => 'Additional privileges',                                  'addp' => 'Additional privileges',
                                 'fixp' => 'Fixed privileges',                                  'fixp' => 'Fixed privileges',
                                 'oppr' => 'Optional privileges',                                  'oppr' => 'Optional privileges',
                                 'func' => 'Function',                                  'func' => 'Collaborative Tool',
     );      );
     $r->print(&Apache::lonhtmlcommon::start_pick_box());      $r->print(&Apache::lonhtmlcommon::start_pick_box('LC_group_priv_box').
     $r->print('<tr>        &Apache::lonhtmlcommon::row_title($lt{'func'},undef,
                 <td bgcolor="'.$tabcol.'" valign="top">   'LC_groups_functionality'));
                  <table cellspacing="0" cellpadding="1">      $r->print(join('</td><td class="LC_groups_functionality">',@{$tools}));
                   <tr>      $r->print(&Apache::lonhtmlcommon::row_closure(1));
                    <td valign="top"><b>'.$lt{'func'}.'</b></td>      my $fixed = '';
                   </tr>      my $dynamic = '';
                   <tr>  
                    <td valign="top"><b>'.$lt{'fixp'}.'</b></td>  
                   </tr>  
                   <tr>  
                    <td valign="top"><b>'.$lt{'oppr'}.'</b></td>  
                   </tr>  
                  </table>  
                 </td>  
     ');  
     foreach my $tool (@{$tools}) {      foreach my $tool (@{$tools}) {
         $r->print('<td align="center" valign="top">  
                     <table cellspacing="0" cellpadding="1">  
                      <tr bgcolor="#cccccc">  
                       <td colspan="2" align="center"><b>'.$tool.'</b></td>  
                      </tr>  
         ');  
         my $privcount = 0;          my $privcount = 0;
         my $fixed = '';   if ($dynamic ne '') {
         my $dynamic = '';      $dynamic .= '</td><td class="LC_groups_optional">';
    }
    $dynamic .= '<table class="LC_group_priv"><tr>';
         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
             if (exists($$fixedprivs{$tool}{$priv})) {              if (exists($$fixedprivs{$tool}{$priv})) {
                 $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';   if ($fixed ne '') {
       $fixed .= '</td><td class="LC_groups_fixed">';
    }
                   $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" /><nobr>'.$$toolprivs{$tool}{$priv}.'&nbsp;';
                 if ($action eq 'modify') {                  if ($action eq 'modify') {
                     if (grep/^$tool$/,@{$available}) {                      if (grep(/^$tool$/,@{$available})) {
                         $fixed .= '<small>'.&mt('(on)').'<small>&nbsp;';                          $fixed .= '<small>'.&mt('(on)').'<small>&nbsp;';
                     } else {                      } else {
                         $fixed .= '<small>'.&mt('(off)').'<small>&nbsp;';                          $fixed .= '<small>'.&mt('(off)').'<small>&nbsp;';
                     }                      }
                 }                  }
                   $fixed .= '</nobr>';
             } else {              } else {
                 $privcount ++;                  $privcount++;
                 if ($privcount == 3) {                  if ($privcount == 3) {
                     $dynamic .= '</tr>                      $dynamic .= '</tr>
                                  <tr bgcolor="'.$rowColor1.'">'."\n";                                   <tr>'."\n";
                 }                  }
                 $dynamic .= '<td><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></td>'."\n";                  $dynamic .= '<td><nobr><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></nobr></td>'."\n";
             }              }
         }          }
         if ($dynamic eq '') {          if ($privcount == 0) {
             $dynamic = '<td>None</td>'."\n";              $dynamic .= '<td>None</td>'."\n";
         }          }
         if ($privcount < 3) {          if ($privcount < 3) {
             $dynamic .= '</tr>              $dynamic .= '<td>&nbsp;</td>'."\n";
                          <tr bgcolor="'.$rowColor1.'">  
                           <td colspan="2">&nbsp;</td>'."\n";  
         } elsif ($privcount%2) {          } elsif ($privcount%2) {
             $dynamic = '<td>&nbsp;</td>'."\n";              $dynamic = '<td>&nbsp;</td>'."\n";
         }          }
         $r->print('<tr bgcolor="'.$rowColor2.'">   $dynamic .= '</tr></table>';
                     <td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td>  
                    </tr>  
                    <tr bgcolor="'.$rowColor1.'">'."\n".$dynamic.'</tr>'."\n".'</table>'."\n".'</td>  
         ');  
     }      }
     $r->print('</tr>'."\n");      $r->print(&Apache::lonhtmlcommon::row_title($lt{'fixp'},undef,
     $r->print(&Apache::lonhtmlcommon::end_pick_box());   'LC_groups_fixed').
         $fixed.
         &Apache::lonhtmlcommon::row_closure(1));
       $r->print(&Apache::lonhtmlcommon::row_title($lt{'oppr'},undef,
    'LC_groups_optional').
         $dynamic.
         &Apache::lonhtmlcommon::end_pick_box());
     $r->print('<br />');      $r->print('<br />');
     return;      return;
   
 }  }
   
 sub display_defprivs {  sub display_defprivs {
     my ($r,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,$defprivs) = @_;      my ($r,$tools,$toolprivs,$defprivs) = @_;
       my $function = &Apache::loncommon::get_users_function();
       my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
       my $rowColor1 = "#dddddd";
       my $rowColor2 = "#eeeeee";
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                                 'priv' => 'Privileges',                                  'priv' => 'Privileges',
                                 'func' => 'Function',                                  'func' => 'Collaborative Tool',
     );      );
     $r->print(&Apache::lonhtmlcommon::start_pick_box());      $r->print(&Apache::lonhtmlcommon::start_pick_box());
     $r->print('<tr>');      $r->print('<tr>');
Line 1990  sub display_defprivs { Line 2010  sub display_defprivs {
         @{$currprivs{$tool}} = ();          @{$currprivs{$tool}} = ();
         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
             if (ref($defprivs) eq 'ARRAY') {              if (ref($defprivs) eq 'ARRAY') {
                 if (grep/^\Q$priv\E$/,@{$defprivs}) {                  if (grep(/^\Q$priv\E$/,@{$defprivs})) {
                     push(@{$currprivs{$tool}},$priv);                      push(@{$currprivs{$tool}},$priv);
                 }                  }
             }              }
Line 2046  sub display_defprivs { Line 2066  sub display_defprivs {
   
   
 sub change_members_form {  sub change_members_form {
     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,      my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description,
         $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,          $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,
         $granularity,$specificity,$idx,$states,$navbuttons,$rowColor1,          $granularity,$quota,$specificity,$idx,$states,$navbuttons,$gpterm,
         $rowColor2) = @_;   $ucgpterm) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                                          grse => 'Group settings',                                           grse => "$ucgpterm settings",
                                          mogm => 'Modify group membership',                                           mogm => "Modify $gpterm membership",
                                         );                                          );
     my @regexps = ('user_','userpriv_');      my @regexps = ('user_','userpriv_');
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      $r->print(&Apache::lonhtmlcommon::echo_form_input(
Line 2067  sub change_members_form { Line 2087  sub change_members_form {
     my $prevtext = $$navbuttons{'gtpp'};      my $prevtext = $$navbuttons{'gtpp'};
     $r->print('      $r->print('
 <br />  <br />
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  
 ');  ');
     &topic_bar($r,$tabcol,1,$lt{'grse'});      &topic_bar($r,1,$lt{'grse'});
     $r->print('      &print_current_settings($r,$action,$functions,$startdate,$enddate,
  <tr>      $groupname,$description,$granularity,$quota,
   <td>&nbsp;</td>      \@available,\@unavailable,$gpterm,$ucgpterm);
   <td colspan="3">      &topic_bar($r,2,$lt{'mogm'});
 ');      my $numcurrent = &current_membership($r,$cdom,$cnum,$formname,$groupname,
     &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,                                           \@available,\@unavailable,$fixedprivs,
                             $functions,$startdate,$enddate,$groupname,                   $granularity,$specificity);
                           $description,$granularity,\@available,\@unavailable);      if ($numcurrent > 0) {
 $r->print('          &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
 </td></tr><tr><td colspan="4">&nbsp;</td></tr>');                              $$states{$action}[$page+1],$nexttext);
     &topic_bar($r,$tabcol,2,$lt{'mogm'});      } else {
     $r->print('          &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);
  <tr>      }
   <td>&nbsp;</td>  
   <td colspan="3">  
 ');  
     &current_membership($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,  
                         $rowColor2,$groupname,\@available,\@unavailable,  
                         $fixedprivs,$granularity,$specificity);  
     $r->print('</td>');  
     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,  
                         $$states{$action}[$page+1],$nexttext);  
     $r->print('</table>');  
     return;      return;
 }  }
   
 sub current_membership {  sub current_membership {
     my ($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,$rowColor2,$groupname,      my ($r,$cdom,$cnum,$formname,$groupname,$available,$unavailable,
         $available,$unavailable,$fixedprivs,$granularity,$specificity) = @_;   $fixedprivs,$granularity,$specificity) = @_;
     my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,      my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                    $groupname);                                                                     $groupname);
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
Line 2112  sub current_membership { Line 2121  sub current_membership {
                                           'reen' => 'Re-enable',                                            'reen' => 'Re-enable',
                                           'acti' => 'Activate',                                            'acti' => 'Activate',
                                           'dele' => 'Delete',                                            'dele' => 'Delete',
                                           'curf' => 'Current Functionality',                                            'curf' => 'Current Tool Set',
                                           'chpr' => 'Change Privileges'                                             'chpr' => 'Change Privileges' 
                                         );                                          );
     if (keys(%membership) > 0) {      my ($current,$num_items,$hastools,$addtools) =
         my %current = ();          &Apache::longroup::group_memberlist($cdom,$cnum,$groupname,$fixedprivs,
         my %allnames = ();                                              $available);
         my $hastools = 0;      my $numcurrent = scalar(keys(%{$current}));
         my $addtools = 0;      if ($numcurrent > 0) {
         my $num_reenable = 0;          $r->print('
         my $num_activate = 0;  
         my $num_expire - 0;  
         foreach my $key (sort(keys(%membership))) {  
             if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {  
                 my $uname = $1;  
                 my $udom = $2;  
                 my $user = $uname.':'.$udom;  
                 my($end,$start,@userprivs) = split(/:/,$membership{$key});  
                 unless ($start == -1) {  
                     $allnames{$udom}{$uname} = 1;  
                     $current{$user} = {  
  uname     => $uname,  
  udom      => $udom,  
  start     => &Apache::lonlocal::locallocaltime($start),  
  currtools => [],  
  newtools  => [],  
     };  
   
                     if ($end == 0) {  
                         $current{$user}{end} =  'No end date';  
                     } else {  
                         $current{$user}{end} =   
                                      &Apache::lonlocal::locallocaltime($end);  
                     }  
                     my $now = time;  
                     if (($end > 0) && ($end < $now)) {  
                         $current{$user}{changestate} = 'reenable';  
                         $num_reenable++;  
                     } elsif (($start > $now)) {  
                         $current{$user}{changestate} = 'activate';  
                         $num_activate ++;  
                     } else {  
                         $current{$user}{changestate} = 'expire';  
                         $num_expire ++;  
                     }  
                     if (@userprivs > 0) {  
                         foreach my $tool (sort(keys(%{$fixedprivs}))) {  
                             foreach my $priv (keys(%{$$fixedprivs{$tool}})) {  
                                 if (grep/^$priv$/,@userprivs) {  
                                     push(@{$current{$user}{currtools}},$tool);  
                                     last;  
                                 }  
                             }  
                         }  
                         $hastools = 1;  
                     }  
                     if (@{$available} > 0) {  
                         if (@{$current{$user}{currtools}} > 0) {  
                             if ("@{$available}" ne "@{$current{$user}{currtools}}") {  
                                 foreach my $tool (@{$available}) {  
                                     unless (grep/^$tool$/,@{$current{$user}{currtools}}) {  
                                         push(@{$current{$user}{newtools}},$tool);  
                                     }  
                                 }  
                             }  
                         } else {  
                             @{$current{$user}{newtools}} = @{$available};  
                         }  
                         if (@{$current{$user}{newtools}} > 0) {  
                             $addtools = 1;  
                         }  
                     }  
                 }  
             }  
         }  
         if (keys(%current) > 0) {  
             my %idhash;  
             foreach my $udom (keys(%allnames)) {  
                 %{$idhash{$udom}} = &Apache::lonnet::idrget($udom,  
                                                 keys(%{$allnames{$udom}}));  
                 foreach my $uname (keys(%{$idhash{$udom}})) {  
                     $current{$uname.':'.$udom}{'id'} = $idhash{$udom}{$uname};  
                 }  
                 foreach my $uname (keys(%{$allnames{$udom}})) {  
                     $current{$uname.':'.$udom}{'fullname'} =  
                                 &Apache::loncommon::plainname($uname,$udom,  
                                                                   'lastname');  
                 }  
             }  
             $r->print('  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="2">  
    <table>     <table>
     <tr>');      <tr>');
             if ($num_expire) {          if ($num_items->{'active'}) {
                 &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});              &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});
             }          }
             if ($num_reenable) {          if ($num_items->{'previous'}) {
                 &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});              &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});
             }          }
             if ($num_activate) {          if ($num_items->{'future'}) {
                 &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'});              &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'});
           }
           &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'});
           if (@{$available} > 0) {
               if ($specificity eq 'Yes') {
                   &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'});
             }              }
             &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'});              if ($granularity eq 'Yes') {
             if (@{$available} > 0) {                  $r->print(&check_uncheck_tools($r,$available));
                 if ($specificity eq 'Yes') {                  $r->print('
                     &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'});  
                 }  
                 if ($granularity eq 'Yes') {  
                     $r->print(&check_uncheck_tools($r,$available));  
                     $r->print('  
      <td>       <td>
       <nobr>        <nobr>
        <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>         <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>
Line 2235  sub current_membership { Line 2161  sub current_membership {
      </nobr>       </nobr>
     </td>      </td>
 ');  ');
                 }  
             }              }
             $r->print(<<"END");          }
           $r->print(<<"END");
    </tr>     </tr>
   </table>    </table>
   </td>    <br />
   <td width="100%">&nbsp;</td>  
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
 END  END
             $r->print(&Apache::lonhtmlcommon::start_pick_box());          $r->print(&Apache::loncommon::start_data_table().
             $r->print(<<"END");    &Apache::loncommon::start_data_table_header_row());
    <table border="0" cellpadding="4" cellspacing="1">          $r->print(<<"END");
     <tr bgcolor="$tabcol" align="center">       <th>$lt{'actn'}</th>
      <td><b>$lt{'actn'}</b></td>       <th><a href="javascript:changeSort('fullname')">$lt{'name'}</a></th>
      <td><b><a href="javascript:changeSort('fullname')">$lt{'name'}</a></b></td>       <th><a href="javascript:changeSort('username')">$lt{'usnm'}</a></th>
      <td><b><a href="javascript:changeSort('username')">$lt{'usnm'}</a></b>       <th><a href="javascript:changeSort('domain')">$lt{'doma'}</a></th>
      </td>       <th><a href="javascript:changeSort('id')">ID</a></th>
      <td><b><a href="javascript:changeSort('domain')">$lt{'doma'}</a></b></td>       <th><a href="javascript:changeSort('start')">$lt{'stda'}</a></th>
      <td><b><a href="javascript:changeSort('id')">ID</a></b></td>       <th><a href="javascript:changeSort('end')">$lt{'enda'}</a></th>
      <td><b><a href="javascript:changeSort('start')">$lt{'stda'}</a></b></td>  
      <td><b><a href="javascript:changeSort('end')">$lt{'enda'}</a></b></td>  
 END  END
             my $colspan = 0;          my $colspan = 0;
             if ($hastools) {          if ($hastools) {
                 $r->print('<td><b>'.$lt{'curf'}.'</b></td>');              $r->print('<th>'.$lt{'curf'}.'</th>');
                 $colspan ++;                $colspan++;  
             }          }
             if ($addtools) {          if ($addtools) {
                 $r->print('<td><b>Additional Functionality</b></td>');              $r->print('<th>'.&mt('Additional Tools').'</th>');
                 $colspan ++;              $colspan++;
             }          }
             $r->print('</tr>');          $r->print(&Apache::loncommon::end_data_table_header_row());
             if ($colspan) {          if ($colspan) {
                 if ($granularity eq 'Yes') {              if ($granularity eq 'Yes') {
                     $r->print('<tr bgcolor="#cccccc">                  $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').'
  <td colspan="7">&nbsp;</td>   <td colspan="7">&nbsp;</td>
  <td colspan="'.$colspan.'" align="center"><small><nobr><b>'.&mt('All:').   <td colspan="'.$colspan.'" align="center"><nobr><b>'.&mt('All:').
   '</b>&nbsp;');    '</b>&nbsp;');
                     foreach my $tool (@{$available}) {                  foreach my $tool (@{$available}) {
                         $r->print('<label><input type="checkbox" name="togglefunc"'.                      $r->print('<label><input type="checkbox" name="togglefunc"'.
    ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.     ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
    ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');     ' value="'.$tool.'" />'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
                     }  
                     $r->print('</nobr></small></td></tr>');  
                 }                  }
                   $r->print('</nobr></td></tr>');
             }              }
             my %Sortby = ();          }
             foreach my $user (sort(keys(%current))) {          my %Sortby = ();
                 if ($env{'form.sortby'} eq 'fullname') {          foreach my $user (sort(keys(%{$current}))) {
                     push(@{$Sortby{$current{$user}{fullname}}},$user);              if ($env{'form.sortby'} eq 'fullname') {
                 } elsif ($env{'form.sortby'} eq 'username') {                  push(@{$Sortby{$$current{$user}{fullname}}},$user);
                     push(@{$Sortby{$current{$user}{uname}}},$user);              } elsif ($env{'form.sortby'} eq 'username') {
                 } elsif ($env{'form.sortby'} eq 'domain') {                  push(@{$Sortby{$$current{$user}{uname}}},$user);
                     push(@{$Sortby{$current{$user}{udom}}},$user);              } elsif ($env{'form.sortby'} eq 'domain') {
                 } elsif ($env{'form.sortby'} eq 'id') {                  push(@{$Sortby{$$current{$user}{udom}}},$user);
                     push(@{$Sortby{$current{$user}{id}}},$user);              } elsif ($env{'form.sortby'} eq 'id') {
                 } else {                  push(@{$Sortby{$$current{$user}{id}}},$user);
                     push(@{$Sortby{$current{$user}{fullname}}},$user);              } else {
                 }                  push(@{$Sortby{$$current{$user}{fullname}}},$user);
             }              }
             my $rowNum = 0;          }
             my $rowColor;          foreach my $key (sort(keys(%Sortby))) {
             foreach my $key (sort(keys(%Sortby))) {              foreach my $user (@{$Sortby{$key}}) {
                 foreach my $user (@{$Sortby{$key}}) {                  my $id = $$current{$user}{id};
                     if ($rowNum %2 == 1) {                  my $fullname = $$current{$user}{fullname};
                         $rowColor = $rowColor1;                  my $udom = $$current{$user}{udom};
                     } else {                  my $uname = $$current{$user}{uname};
                         $rowColor = $rowColor2;                  my $start = $$current{$user}{start};
                     }                  my $end = $$current{$user}{end};
                     my $id = $current{$user}{id};                  $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').'
                     my $fullname = $current{$user}{fullname};                              <td>');
                     my $udom = $current{$user}{udom};                  if ($$current{$user}{changestate} eq 'reenable') {
                     my $uname = $current{$user}{uname};                      $r->print('<nobr><label>'. 
                     my $start = $current{$user}{start};  
                     my $end = $current{$user}{end};  
                     $r->print('<tr bgcolor="'.$rowColor.'">  
                                 <td><small>');  
                     if ($current{$user}{changestate} eq 'reenable') {  
                         $r->print('<nobr><label>'.   
    '<input type="checkbox" name="reenable" value="'.$user.'" />'.     '<input type="checkbox" name="reenable" value="'.$user.'" />'.
    $lt{'reen'}.'</label></nobr><br />');     $lt{'reen'}.'</label></nobr><br />');
                     } elsif ($current{$user}{changestate} eq 'expire') {                  } elsif ($$current{$user}{changestate} eq 'expire') {
                         $r->print('<nobr><label>'.                      $r->print('<nobr><label>'.
    '<input type="checkbox" name="expire" value="'.$user.'" />'.     '<input type="checkbox" name="expire" value="'.$user.'" />'.
    $lt{'expi'}.'</label></nobr><br />');     $lt{'expi'}.'</label></nobr><br />');
                     } elsif ($current{$user}{changestate} eq 'activate') {                  } elsif ($$current{$user}{changestate} eq 'activate') {
                         $r->print('<nobr><label>'.                      $r->print('<nobr><label>'.
    '<input type="checkbox" name="activate" value="'.$user.'" />'.     '<input type="checkbox" name="activate" value="'.$user.'" />'.
    $lt{'acti'}.'</label></nobr><br />');     $lt{'acti'}.'</label></nobr><br />');
                     }                  }
                     $r->print('<nobr><label>'.                  $r->print('<nobr><label>'.
    '<input type="checkbox" name="deletion" value="'.$user.'" />'.     '<input type="checkbox" name="deletion" value="'.$user.'" />'.
    $lt{'dele'}.'</label></nobr>');     $lt{'dele'}.'</label></nobr>');
                     if ($specificity eq 'Yes') {                  if ($specificity eq 'Yes') {
                         $r->print('<br /><nobr><label>'.                      $r->print('<br /><nobr><label>'.
    '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.     '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
    '</label></nobr>');     '</label></nobr>');
                     }                  }
                     $r->print('                  $r->print('
    </td>     </td>'.
    <td><small>'.     '<td>'.$fullname.'</td>'.
     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.     '<td>'.$uname.'</td>'.
     $udom.'</small></td><td><small>'.$id.'</small></td><td><small>'.$start.     '<td>'. $udom.'</td>'.
     '</small></td><td><small>'.$end.'</small></td>');     '<td>'.$id.'</td>'.
                     if ($hastools) {     '<td>'.$start.'</td>'.
                         $r->print('<td align="left"><small><nobr>'.     '<td>'.$end.'</td>');
                   if ($hastools) {
                       $r->print('<td align="left"><nobr>'.
                                   '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');                                    '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                         foreach my $tool (@{$current{$user}{currtools}}) {                      foreach my $tool (@{$$current{$user}{currtools}}) {
                             if ($granularity eq 'Yes') {                          if ($granularity eq 'Yes') {
                                 $r->print('<label><input type="checkbox" '.                               $r->print('<label><input type="checkbox" '. 
                                        'checked="checked" '.                                          'checked="checked" '. 
                                        'name="user_'.$tool.'" value="'.                                         'name="user_'.$tool.'" value="'.
                                        $user.'" />'.$tool.'</label>');                                         $user.'" />'.$tool.'</label>');
                              } else {                           } else {
                                $r->print('<input type="hidden" '.                               $r->print('<input type="hidden" '.
                                        'checked="checked" '.                                         'checked="checked" '.
                                        'name="user_'.$tool.'" value="'.                                         'name="user_'.$tool.'" value="'.
                                        $user.'" />'.$tool);                                         $user.'" />'.$tool);
                              }                           }
                              $r->print('&nbsp;&nbsp;&nbsp;');                           $r->print('&nbsp;&nbsp;&nbsp;');
                         }  
                         $r->print('</nobr></small></td>');  
                     }                      }
                     if ($addtools) {                      $r->print('</nobr></td>');
                         $r->print('<td align="left"><small>');                  }
                         if ($granularity eq 'Yes') {                  if ($addtools) {
                             foreach my $tool (@{$current{$user}{newtools}}) {                      $r->print('<td align="left">');
                                 $r->print('<nobr><label><input type="checkbox"                      if ($granularity eq 'Yes') {
                           foreach my $tool (@{$$current{$user}{newtools}}) {
                               $r->print('<nobr><label><input type="checkbox"
                                           name="user_'.$tool.'" value="'.                                            name="user_'.$tool.'" value="'.
                                           $user.'" />'.$tool.                                            $user.'" />'.$tool.
                                           '</label></nobr>&nbsp;&nbsp;&nbsp;');                                            '</label></nobr>&nbsp;&nbsp;&nbsp;');
                             }                          }
                         } else {                      } else {
                             foreach my $tool (@{$current{$user}{newtools}}) {                          foreach my $tool (@{$$current{$user}{newtools}}) {
                                 $r->print('<nobr><input type="hidden"                               $r->print('<nobr><input type="hidden" 
                                           name="user_'. $tool.'" value="'.                                            name="user_'. $tool.'" value="'.
                                           $user.'" />'.$tool.                                            $user.'" />'.$tool.
                                           '</nobr>&nbsp;&nbsp;&nbsp;');                                            '</nobr>&nbsp;&nbsp;&nbsp;');
                             }  
                         }                          }
                         $r->print('</small></td>');  
                     }                      }
                     $r->print('</tr>'."\n");                      $r->print('</td>');
                     $rowNum ++;  
                 }                  }
                   $r->print(&Apache::loncommon::end_data_table_row()."\n");
             }              }
             $r->print(&Apache::lonhtmlcommon::end_pick_box());  
             $r->print('  
   </td>  
  </tr>');  
         }          }
           $r->print(&Apache::loncommon::end_data_table());
       } else {
           $r->print(&mt('There are no active, future or previous group members to modify.'));
     }      }
     return;      return $numcurrent;
 }  }
   
 sub check_uncheck_buttons {  sub check_uncheck_buttons {
     my ($r,$formname,$field,$title,$colspan) = @_;      my ($r,$formname,$field,$title,$colspan) = @_;
     $r->print('      $r->print('
      <td '.$colspan.'>       <td '.$colspan.'>
       <nobr>  
        <fieldset>         <fieldset>
        <legend><b>'.$title.'</b></legend>         <legend><b>'.$title.'</b></legend>
         <nobr>
        <input type="button" value="check all"         <input type="button" value="check all"
        onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />         onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
        &nbsp;&nbsp;         &nbsp;&nbsp;
        <input type="button" value="uncheck all"         <input type="button" value="uncheck all"
        onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />         onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
        </fieldset>  
       </nobr>        </nobr>
          </fieldset>
      </td>       </td>
 ');  ');
 }  }
   
   
 sub change_privs_form {  sub change_privs_form {
     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,      my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
        $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,   $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,
        $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$rowColor1,   $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$gpterm,
        $rowColor2) = @_;   $ucgpterm) = @_;
     my @regexps = ('userpriv_');      my @regexps = ('userpriv_');
     my $nexttext;      my $nexttext;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
                'tode' => 'To be deleted',                 'tode' => 'To be deleted',
                'toex' => 'To be expired',                 'toex' => 'To be expired',
                'nome' => 'No members to be deleted or expired from the group.',                 'nome' => "No members to be deleted or expired from the $gpterm.",
     );      );
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      $r->print(&Apache::lonhtmlcommon::echo_form_input(
          ['origin','action','state','page','sortby'],\@regexps));           ['origin','action','state','page','sortby'],\@regexps));
Line 2434  sub change_privs_form { Line 2342  sub change_privs_form {
     } else {      } else {
         $nexttext = $$navbuttons{'mose'};          $nexttext = $$navbuttons{'mose'};
     }      }
     $r->print('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');      &topic_bar($r,3,&mt('Members to delete or expire'));
     &topic_bar($r,$tabcol,3,&mt('Members to delete or expire'));  
     my $exp_or_del = 0;      my $exp_or_del = 0;
     if (ref($$memchg{'deletion'}) eq 'ARRAY') {      if (ref($$memchg{'deletion'}) eq 'ARRAY') {
         if (@{$$memchg{'deletion'}} > 0) {          if (@{$$memchg{'deletion'}} > 0) {
             $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'tode'}.':</b><br /><ul>');              $r->print('<b>'.$lt{'tode'}.':</b><br /><ul>');
             foreach my $user (@{$$memchg{'deletion'}}) {              foreach my $user (@{$$memchg{'deletion'}}) {
                 $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].                  $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                           '&nbsp;('.$user.')</li>');                            '&nbsp;('.$user.')</li>');
             }              }
             $r->print('</ul></td><tr><td colspan="4">&nbsp;</td></tr>');              $r->print('</ul>');
             $exp_or_del += @{$$memchg{'deletion'}};              $exp_or_del += @{$$memchg{'deletion'}};
         }          }
     }      }
     if (ref($$memchg{'expire'}) eq 'ARRAY') {      if (ref($$memchg{'expire'}) eq 'ARRAY') {
         if (@{$$memchg{'expire'}} > 0) {          if (@{$$memchg{'expire'}} > 0) {
             $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'toex'}.':</b><br /><ul>');              $r->print('<b>'.$lt{'toex'}.':</b><br /><ul>');
             foreach my $user (@{$$memchg{'expire'}}) {              foreach my $user (@{$$memchg{'expire'}}) {
                 $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].                  $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                           '&nbsp;('.$user.')</li>');                            '&nbsp;('.$user.')</li>');
             }              }
             $r->print('</ul></td><tr><td colspan="4">&nbsp;</td></tr>');              $r->print('</ul>');
             $exp_or_del += @{$$memchg{'expire'}};              $exp_or_del += @{$$memchg{'expire'}};
         }          }
     }      }
     if (!$exp_or_del) {      if (!$exp_or_del) {
         $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'nome'}.          $r->print($lt{'nome'}.'<br />');
                   '</td></tr><tr><td colspan="4">&nbsp;</td></tr>');  
     }      }
           
     &topic_bar($r,$tabcol,4,&mt('Group member privileges'));      &topic_bar($r,4,&mt('Setting optional privileges for specific group members'));
   
     my $numchgs = &member_privileges_form($r,$tabcol,$action,$formname,$tools,      my $numchgs = &member_privileges_form($r,$action,$formname,$tools,
                                           $toolprivs,$fixedprivs,$userdata,                                            $toolprivs,$fixedprivs,$userdata,
                                           $usertools,$idx,$memchg,$states,                                            $usertools,$idx,$memchg,$states,
                                           $stored,$rowColor1,$rowColor2);                                            $stored,$gpterm);
     $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');  
     my $prevtext = $$navbuttons{'gtps'};      my $prevtext = $$navbuttons{'gtps'};
     if ($numchgs || $exp_or_del) {      if ($numchgs || $exp_or_del) {
         &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,          &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
Line 2478  sub change_privs_form { Line 2383  sub change_privs_form {
     } else {      } else {
         &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);          &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);
     }      }
     $r->print('</table>');  
     return;      return;
 }  }
   
 sub add_members_form {  sub add_members_form {
     my ($r,$tabcol,$action,$formname,$page,$startdate,$enddate,$groupname,      my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,$groupname,
         $description,$granularity,$sectioncount,$tools,$functions,$stored,          $description,$granularity,$quota,$sectioncount,$tools,$functions,
         $states,$navbuttons,$rowColor1,$rowColor2) = @_;           $stored,$states,$navbuttons,$gpterm,$ucgpterm)=@_; 
     $r->print(' <br />      $r->print(' <br />');
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="3">  
 ');  
     my @available = ();      my @available = ();
     my @unavailable = ();      my @unavailable = ();
     &check_tools($functions,$tools,\@available,\@unavailable);      &check_tools($functions,$tools,\@available,\@unavailable);
     &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,      &print_current_settings($r,$action,$functions,$startdate,$enddate,
                             $functions,$startdate,$enddate,$groupname,      $groupname,$description,$granularity,$quota,
                             $description,$granularity,\@available,\@unavailable);      \@available,\@unavailable,$gpterm,$ucgpterm);
     $r->print('      &membership_options($r,$cdom,$cnum,$action,$formname,$sectioncount,1,$gpterm,
    </td>                          $ucgpterm);
   </tr>  
   <tr>  
    <td colspan="4">&nbsp;</td>  
   </tr>');  
   
     &membership_options($r,$action,$formname,$tabcol,$sectioncount,1);  
     my $nexttext = $$navbuttons{'gtns'};      my $nexttext = $$navbuttons{'gtns'};
     my $prevtext = $$navbuttons{'gtpp'};      my $prevtext = $$navbuttons{'gtpp'};
     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,      &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                         $$states{$action}[$page+1],$nexttext);                          $$states{$action}[$page+1],$nexttext);
     $r->print('  
  </table>');  
     return;      return;
 }  }
   
 sub choose_privs_form {  sub choose_privs_form {
     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,      my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
        $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,   $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,
        $states,$stored,$sectioncount,$navbuttons,$rowColor1,$rowColor2) = @_;   $states,$stored,$sectioncount,$navbuttons,$gpterm,$ucgpterm,
    $crstype) = @_;
   
     my @regexps = ('userpriv_');      my @regexps = ('userpriv_');
     my $nexttext;      my $nexttext;
Line 2535  sub choose_privs_form { Line 2427  sub choose_privs_form {
         $nexttext = $$navbuttons{'adme'};          $nexttext = $$navbuttons{'adme'};
     }      }
   
     $r->print('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');      &topic_bar($r,6,&mt('Setting optional privileges for specific group members'));
     &topic_bar($r,$tabcol,6,&mt('Group member privileges'));  
   
     &member_privileges_form($r,$tabcol,$action,$formname,$tools,$toolprivs,      &member_privileges_form($r,$action,$formname,$tools,$toolprivs,
                             $fixedprivs,$userdata,$usertools,$idx,undef,                              $fixedprivs,$userdata,$usertools,$idx,undef,
                             $states,$stored,$rowColor1,$rowColor2);                              $states,$stored,$gpterm);
   
     $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');  
     if ($action eq 'create') {      if ($action eq 'create') {
         if (keys(%{$sectioncount}) > 0) {          my $img1 = 7;
             my $img1 = 7;          my $img2 = 8;
             my $img2 = 8;          &mapping_options($r,$action,$formname,$page,$sectioncount,
             &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,                           $states,$stored,$navbuttons,$img1,$img2,
                              $states,$stored,$navbuttons,$img1,$img2,                           $gpterm,$ucgpterm,$crstype,$cdom,$cnum);
                              $rowColor1,$rowColor2);  
         }  
     }      }
     my $prevtext = $$navbuttons{'gtps'};      my $prevtext = $$navbuttons{'gtps'};
     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,      &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                         $$states{$action}[$page+1],$nexttext);                          $$states{$action}[$page+1],$nexttext);
     $r->print('</table>');  
     return;      return;
 }  }
   
Line 2618  function uncheckAllTools(formname) { Line 2505  function uncheckAllTools(formname) {
 }  }
   
 sub member_privileges_form {  sub member_privileges_form {
     my ($r,$tabcol,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,      my ($r,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,
         $usertools,$idx,$memchg,$states,$stored,$rowColor1,$rowColor2) = @_;          $usertools,$idx,$memchg,$states,$stored,$gpterm) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
             'addp' => 'Additional privileges',              'addp' => 'Additional privileges',
             'fixp' => 'Fixed privileges',              'fixp' => 'Core privileges',
             'oppr' => 'Optional privileges',              'oppr' => 'Optional privileges',
             'func' => 'Function',              'func' => 'Tool',
             'forf' => 'For the functionality you have chosen to include '.              'forf' => 'For the collaborative tools included for group '.
                       'there are no optional privileges to set besides '.                        'members being added or modified, '. 
                       'the standard privileges.',                        'there are no optional privileges to set '.
             'algr' => 'All group members will receive the same privileges.',                        'for specific members.',
               'algr' => 'All new group members will receive the same privileges.',            'ifex' => 'If previously expired members are being re-enabled, or '.
                         'if access for future members is being activated now, '.
                         'previously set privileges will be preserved.',
             'asno' => 'As no group members are being added, '.              'asno' => 'As no group members are being added, '.
                       'there are no specific user privileges to set.',                        'there are no specific user privileges to set.',
             'asng' => 'As no group tools will be made available to users, '.              'asng' => 'As no group tools will be made available to users, '.
Line 2636  sub member_privileges_form { Line 2526  sub member_privileges_form {
             'nogm' => 'No group member privileges to display or set, '.              'nogm' => 'No group member privileges to display or set, '.
                       'as you have not indicated that you will be activating,'.                        'as you have not indicated that you will be activating,'.
                       ' re-enabling, changing privileges, or adding/removing '.                        ' re-enabling, changing privileges, or adding/removing '.
                       'functionality for any current members ',                        'tools for any current members.',
             'full' => 'Fullname',              'full' => 'Fullname',
             'user' => 'Username',              'user' => 'Username',
             'doma' => 'Domain',              'doma' => 'Domain',
Line 2680  sub member_privileges_form { Line 2570  sub member_privileges_form {
         }          }
         $numchgs = @currmembers;          $numchgs = @currmembers;
         if (!$numchgs) {          if (!$numchgs) {
             $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'nogm'});               $r->print($lt{'nogm'}); 
             return $numchgs;              return $numchgs;
         }          }
     }      }
Line 2696  sub member_privileges_form { Line 2586  sub member_privileges_form {
                 my %total;                  my %total;
                 if (keys(%{$usertools}) > 1) {                  if (keys(%{$usertools}) > 1) {
                     $r->print('                      $r->print('
  <tr>     <table border="0" cellspacing="2" cellpadding="2">
   <td>&nbsp;</td>  
   <td colspan="3">  
    <table border="0" cellspacing="2" cellpadding="2" border="0">  
     <tr>      <tr>
 ');  ');
                     foreach my $tool (@{$tools}) {                      foreach my $tool (@{$tools}) {
                         if (@{$showboxes{$tool}} > 0) {                          if (@{$showboxes{$tool}} > 0) {
                             $r->print('<td valign="top">');                              $r->print('<td valign="top">');
                             $r->print('<table class="thinborder"><tr bgcolor="'.                              $r->print('<table class="thinborder"><tr>'.
                                       $tabcol.'"><th colspan="'.$colspan.'">'.        '<th colspan="'.$colspan.'">'.
                                       $tool.'</th></tr><tr>');                                        $tool.'</th></tr><tr>');
                             my $privcount = 0;                              my $privcount = 0;
                             foreach my $priv (@{$showboxes{$tool}}) {                              foreach my $priv (@{$showboxes{$tool}}) {
Line 2744  sub member_privileges_form { Line 2631  sub member_privileges_form {
                             $r->print('</tr></table></td><td>&nbsp;</td>');                              $r->print('</tr></table></td><td>&nbsp;</td>');
                         }                          }
                     }                      }
                     $r->print('</tr></table></td></tr>');                      $r->print('</tr></table>');
                     $r->print('<tr><td colspan="4">&nbsp;</td></tr>');  
                 }                  }
                 $r->print('<tr><td>&nbsp;</td><td colspan="3">');                  $r->print(&Apache::loncommon::start_data_table().
                 $r->print(&Apache::lonhtmlcommon::start_pick_box());    &Apache::loncommon::start_data_table_header_row());
                 $r->print(<<"END");                  $r->print(<<"END");
    <tr bgcolor="$tabcol">      <th>$lt{'full'}</th>
     <th><b>$lt{'full'}</th>      <th>$lt{'user'}</th>
     <th><b>$lt{'user'}</th>  
     <th>$lt{'doma'}</th>      <th>$lt{'doma'}</th>
     <th colspan="$numtools">$lt{'addp'}</th>      <th colspan="$numtools">$lt{'addp'}</th>
   </tr>  
 END  END
                 &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,                  $r->print(&Apache::loncommon::end_data_table_header_row());
                                       $usertools,$toolprivs,$fixedprivs,                  &member_privs_entries($r,$usertools,$toolprivs,$fixedprivs,
                                       $userdata,$idx,\@showtools,\@defprivs,                                        $userdata,$idx,\@showtools,\@defprivs,
                                       \@excluded);                                        \@excluded);
                 $r->print('</td>');                  $r->print(&Apache::loncommon::end_data_table());
                 $r->print(&Apache::lonhtmlcommon::end_pick_box());  
                 $r->print('</td></tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
 ');  
             } else {              } else {
                 $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'forf'}.                  $r->print($lt{'forf'}.'<br />');
                           '<br />');                  &display_defprivs($r,$tools,$toolprivs,\@defprivs);
                 &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,  
                             $toolprivs,\@defprivs);  
             }              }
         } else {          } else {
             if (keys(%{$usertools}) > 0) {              if (keys(%{$usertools}) > 0) {
                 $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algr'}.                  $r->print($lt{'algr'}.'<br />'.$lt{'ifex'}.'<br /><br />');
                           '<br /><br />');                  &display_defprivs($r,$tools,$toolprivs,\@defprivs);
                 &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,  
                             $toolprivs,\@defprivs);  
             } else {              } else {
                 $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asno'}.                  $r->print($lt{'asno'}.'<br />');
                           '<br />');  
             }              }
         }          }
     } else {      } else {
         $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asng'});          $r->print($lt{'asng'});
     }      }
     return $numchgs;      return $numchgs;
 }  }
   
 sub process_request {  sub process_request {
     my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$groupname,$description,      my ($r,$cdom,$cnum,$action,$state,$page,$groupname,$description,
         $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,          $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,
         $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,          $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,
         $sectioncount,$stored,$rowColor1,$rowColor2) = @_;          $sectioncount,$stored,$gpterm,$ucgpterm,$crstype) = @_;
   
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      $r->print(&Apache::lonhtmlcommon::echo_form_input(
                                  ['origin','action','state','page','sortby']));                                   ['origin','action','state','page','sortby']));
   
     my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);      my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
                                          $ucgpterm,$crstype);
     if ($earlyout) {      if ($earlyout) {
         $r->print('          $r->print('
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  <table width="100%" cellpadding="0" cellspacing="0" border="0">
Line 2846  sub process_request { Line 2720  sub process_request {
                                      $description,$startdate,$enddate,                                       $description,$startdate,$enddate,
                                      $specificity,$functions,$tools,                                       $specificity,$functions,$tools,
                                      $sectioncount,$roles,$types,$sections,                                       $sectioncount,$roles,$types,$sections,
                                      \@defprivs,$stored);                                        \@defprivs,$stored,$gpterm,$ucgpterm,
                                        $crstype); 
     }      }
     if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') &&       if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') && 
        (($state eq 'memresult') || ($state eq 'addresult')))) {         (($state eq 'memresult') || ($state eq 'addresult')))) {
         &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools,          &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools,
                             $enddate,$startdate,$userdata,$idx,$toolprivs,                              $enddate,$startdate,$userdata,$idx,$toolprivs,
                             $usertools,$specificity,\@defprivs,$memchg);                              $usertools,$specificity,\@defprivs,$memchg,$gpterm,
                               $ucgpterm);
     }      }
     return;      return;
 }  }
Line 2860  sub process_request { Line 2736  sub process_request {
 sub write_group_data {  sub write_group_data {
     my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate,      my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate,
         $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types,          $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types,
         $sections,$defprivs,$stored) = @_;          $sections,$defprivs,$stored,$gpterm,$ucgpterm,$crstype) = @_;
     my $now = time;      my $now = time;
     my $creation = $now;      my $creation = $now;
     my $creator = $env{'user.name'}.':'.$env{'user.domain'};      my $creator = $env{'user.name'}.':'.$env{'user.domain'};
Line 2871  sub write_group_data { Line 2747  sub write_group_data {
     my $esc_description = &escape($description);      my $esc_description = &escape($description);
     my @single_attributes = ('description','functions','startdate','enddate',      my @single_attributes = ('description','functions','startdate','enddate',
                              'creation','modified','creator','granularity',                               'creation','modified','creator','granularity',
                              'specificity','autoadd','autodrop');                               'specificity','autoadd','autodrop','quota');
     my @mult_attributes = ('roles','types','sectionpick','defpriv');      my @mult_attributes = ('roles','types','sectionpick','defpriv');
   
       my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,
                                                                   $stored);
       my $quota = $env{'form.quota'};
       
       $quota =~ s/^\s*([^\s]*)\s*$/$1/;
       if ($quota eq '') {
           $quota = 0;
       }
       if ($quota !~ /^\d*\.?\d*$/) {
           $quota = 0;
           $r->print(&mt('The value you entered for the quota for the file repository in this [_1] contained invalid characters, so it has been set to 0 Mb. You can change this by modifying the [_1] settings.<br />',$gpterm));
       }
       if ($quota > $maxposs) {
           $quota = $maxposs;
           $r->print(&mt('The value you entered for the quota for the file repository in this [_1] exceeded the maximum possible value, so it has been set to [_2] Mb (the maximum possible value).<br />',$gpterm,sprintf("%.2f",$maxposs)));
       }
     my %groupinfo = (      my %groupinfo = (
                      description => $esc_description,                       description => $esc_description,
                      startdate => $startdate,                       startdate => $startdate,
Line 2885  sub write_group_data { Line 2777  sub write_group_data {
                      specificity => $specificity,                       specificity => $specificity,
                      autoadd => $env{'form.autoadd'},                       autoadd => $env{'form.autoadd'},
                      autodrop => $env{'form.autodrop'},                       autodrop => $env{'form.autodrop'},
                        quota => $quota,
                    );                     );
   
     foreach my $func (keys(%{$functions})) {      foreach my $func (keys(%{$functions})) {
         my $status;          my $status;
         if (grep(/^$func$/,@{$tools})) {          if (grep(/^$func$/,@{$tools})) {
Line 2932  sub write_group_data { Line 2826  sub write_group_data {
   
     if ($result eq 'ok') {      if ($result eq 'ok') {
         if ($action eq 'create') {          if ($action eq 'create') {
             my $put_result = &create_homepage($cdom,$cnum,$groupname,              my $result = &add_group_folder($cdom,$cnum,$now,$groupname,$action,
                                               \%groupinfo,$tools);                                             $description,$tools,\%groupinfo,
             $r->print('Group '.$groupname.' was created.<br />');                                             $gpterm,$ucgpterm,$crstype);
         } else {              if ($result ne 'ok') {
             $r->print('Group '.$groupname.' was updated.<br />');                  $r->print(&mt('A problem occurred when creating folders for the new [_1]. [_2].<br />',$gpterm,$result));
               }
               $r->print(&mt('[_1] [_2] was created.<br />',$ucgpterm,$groupname));
           } elsif ($action eq 'modify') {
               my (@oldtools,@newtools); 
               if (ref($$stored{'tool'}) eq 'ARRAY') {
                   @oldtools = @{$$stored{'tool'}};
               }
               if (ref($tools) eq 'ARRAY') {
                   @newtools = @{$tools};
               }
               if (!grep(/^discussion$/,@oldtools) && 
                    grep(/^discussion$/,@newtools)) {
                   my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
                   my $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence';
                   my $navmap = Apache::lonnavmaps::navmap->new();
                   my $bbmapres = $navmap->getResourceByUrl($boardsmap);
                   undef($navmap);
                   if (!$bbmapres) {
                       my $grpmap = $crspath.'group_folder_'.$groupname.'.sequence';
                       my $disctitle = &mt('Discussion Boards');
                       my $outcome = &map_updater($cdom,$cnum,'group_boards_'.
                                                  $groupname.'.sequence','bbseq',
                                                  $disctitle,$grpmap);
                       my ($furl,$ferr) = 
                           &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
                       $navmap = Apache::lonnavmaps::navmap->new();
                       # modify parameter
                       if ($outcome eq 'ok') {
                           my $parm_result = &parm_setter($navmap,$cdom,$boardsmap,
                                                          $groupname);
                           if ($parm_result) {
                               $r->print(&mt('Error while setting parameters '.
                                             'for Discussion Boards folder: '.
                                             '[_1]<br />.',$parm_result));
                           } else {
                               $r->print(&mt('Discussion Boards Folder created.<br />'));
                           }
                       } else {
                           $r->print($outcome);
                       }
                       undef($navmap);
                   }
               }
               $r->print(&mt('[_1] [_2] was updated.<br />',$ucgpterm,$groupname));
         }          }
     } else {      } else {
         my %actiontype = (          my %actiontype = (
                           'create' => 'creating',                            'create' => 'creating',
                           'modify' => 'modifying',                            'modify' => 'modifying',
                          );                           );
         &Apache::lonnet::logthis('Failed to store group '.$groupname.          &Apache::lonnet::logthis("Failed to store $gpterm $groupname ".
                                  'in course: '.$cnum.' in domain: '.$cdom);                                   'in '.lc($crstype).': '.$cnum.
         $r->print(&mt('An error occurred when [_1] the new group. '.                                   ' in domain: '.$cdom);
                       'Please try again.',$actiontype{$action}));          $r->print(&mt('An error occurred when [_1] the [_2]. '.
                         'Please try again.',$actiontype{$action},$gpterm));
     }      }
     return $result;      return $result;
 }  }
   
 sub process_membership {  sub process_membership {
     my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,      my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,
         $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg)=@_;          $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg,
           $gpterm,$ucgpterm)=@_;
     my %usersettings = ();      my %usersettings = ();
     my %added= ();      my %added= ();
     my %failed = ();      my %failed = ();
Line 3064  sub process_membership { Line 3004  sub process_membership {
         my $start = $startdate;          my $start = $startdate;
         my $end = $enddate;          my $end = $enddate;
         if ($state eq 'memresult') {          if ($state eq 'memresult') {
             if ($curr_privs{$user} eq $group_privs{$user}) {  
                push(@unchanged,$user);  
                next;  
             }  
             if (exists($curr_start{$user})) {  
                 $start = $curr_start{$user};  
             }  
             if (exists($curr_end{$user})) {  
                 $end = $curr_end{$user};  
             }  
             $type = 'modified';  
             if (@activate > 0) {              if (@activate > 0) {
                 if (grep/^$user$/,@activate) {                  if (grep/^$user$/,@activate) {
                     $start = $now;                      $start = $now;
Line 3089  sub process_membership { Line 3018  sub process_membership {
                     $type = 'reenabled';                      $type = 'reenabled';
                 }                  }
             }              }
               if ($type eq '') {
                   if ($curr_privs{$user} eq $group_privs{$user}) {
                       push(@unchanged,$user);
                       next;
                   }
                   if (exists($curr_start{$user})) {
                       $start = $curr_start{$user};
                   }
                   if (exists($curr_end{$user})) {
                       $end = $curr_end{$user};
                   }
                   $type = 'modified';
               }
         } else {          } else {
             $type = 'added';              $type = 'added';
         }          }
Line 3150  sub process_membership { Line 3092  sub process_membership {
         $r->print('<br />');          $r->print('<br />');
     }      }
     if ($roster_result eq 'ok') {      if ($roster_result eq 'ok') {
         $r->print('<br />'.&mt('Group membership list updated.'));          $r->print('<br />'.&mt('[_1] membership list updated.',$ucgpterm));
    $r->print('<p>'.&mt("Any currently logged in course users affected by the changes you made to group membership or privileges for the [_1] group will need to log out and log back in for their LON-CAPA sessions to reflect these changes.",$groupname).'</p>');
     } else {      } else {
         $r->print('<br />'.&mt('An error occurred while updating the group membership list -').$roster_result.'<br />');          $r->print('<br />'.&mt('An error occurred while updating the [_1] membership list -',$gpterm).$roster_result.'<br />');
     }      }
     return;      return;
 }  }
   
 sub mapping_options {  sub mapping_options {
     my ($r,$action,$formname,$page,$tabcol,$sectioncount,$states,$stored,      my ($r,$action,$formname,$page,$sectioncount,$states,$stored,
         $navbuttons,$img1,$img2,$rowColor1,$rowColor2) = @_;          $navbuttons,$img1,$img2,$gpterm,$ucgpterm,$crstype,$cdom,$cnum) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'auto' => 'Settings for automatic group enrollment',          'auto' => "Settings for automatic $gpterm enrollment",
         'gmma' => 'Group membership mapping to specific sections/roles',          'gmma' => "$ucgpterm membership mapping to specific sections/roles",
         'endi' => 'Enable/disable automatic group enrollment for '.          'endi' => "Enable/disable automatic $gpterm enrollment for ".
                           'users in specified roles and sections',                            "users in specified roles and sections",
         'adds'  => 'If automatic group enrollment is enabled, when a user is assigned a course-wide or section-specific role, he/she will automatically be added as a member of the group, with start and end access dates defined by the default dates set for the group, unless he/she is already a group member, with access dates that permit either current or future group access.',          'adds'  => "If automatic $gpterm enrollment is enabled, when a user is newly assigned a ".lc($crstype)."-wide or section-specific role, he/she will automatically be added as a member of the $gpterm, with start and end access dates defined by the default dates set for the $gpterm, unless he/she is already a $gpterm member, with access dates that permit either current or future $gpterm access.",
         'drops'  => "If automatic group disenrollment is enabled, when a user's role is expired, access to the group will be terminated unless the user continues to have other course-wide or section-specific active or future roles which receive automatic membership in the group.",          'drops'  => "If automatic $gpterm disenrollment is enabled, when a user's role is expired, access to the $gpterm will be terminated unless the user continues to have other ".lc($crstype)."-wide or section-specific active or future roles which receive automatic membership in the $gpterm.",
         'pirs' => 'Pick roles and sections for automatic group enrollment',          'pirs' => "Pick roles and sections for automatic $gpterm enrollment",
         'curr' => 'Currently set to',          'curr' => 'Currently set to',
         'on' => 'on',          'on' => 'on',
         'off' => 'off',          'off' => 'off',
         'auad' => 'Automatically enable group membership when roles are added?',          'auad' => "Automatically enable $gpterm membership when roles are added?",
         'auex' => 'Automatically expire group membership when roles are removed?',          'auex' => "Automatically expire $gpterm membership when roles are removed?",
         'mapr' => 'Mapping of roles and sections affected by automatic group enrollment/disenrollment follows scheme chosen below.',          'mapr' => "Mapping of roles and sections affected by automatic $gpterm enrollment/disenrollment follows scheme chosen below.",
     );      );
     &automapping($r,$action,$tabcol,$stored,\%lt,$img1);      &automapping($r,$action,$stored,\%lt,$img1);
     $r->print('      &mapping_settings($r,$sectioncount,\%lt,$stored,$img2,$crstype,$cdom,$cnum,
    <tr>                        $action);
     <td colspan="4">&nbsp;</td>  
    </tr>');  
     &mapping_settings($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,\%lt,  
                                                        $stored,$img2);  
     return;      return;
 }  }
   
 sub automapping {  sub automapping {
     my ($r,$action,$tabcol,$stored,$lt,$image) = @_;      my ($r,$action,$stored,$lt,$image) = @_;
     my $add = 'off';      my $add = 'off';
     my $drop = 'off';      my $drop = 'off';
     if (exists($$stored{'autoadd'})) {      if (exists($$stored{'autoadd'})) {
Line 3195  sub automapping { Line 3134  sub automapping {
     if (exists($$stored{'autodrop'})) {      if (exists($$stored{'autodrop'})) {
         $drop = $$stored{'autodrop'};          $drop = $$stored{'autodrop'};
     }      }
     &topic_bar($r,$tabcol,$image,$$lt{'endi'});      &topic_bar($r,$image,$$lt{'endi'});
     $r->print('      $r->print('
   <tr>      <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br /><br />
    <td>&nbsp;</td>  
    <td colspan="3">  
     <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br />  
    </td>  
   </tr>  
   <tr>  
    <td colspan="4">&nbsp;</td>  
   </tr>  
   <tr>  
    <td>&nbsp;</td>  
    <td colspan="3">  
    <nobr>'.$$lt{'auad'}.':&nbsp;     <nobr>'.$$lt{'auad'}.':&nbsp;
     <label><input type="radio" name="autoadd" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autoadd" value="off" checked="checked" />off</label>');      <label><input type="radio" name="autoadd" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autoadd" value="off" checked="checked" />off</label>');
     if ($action eq 'modify') {      if ($action eq 'modify') {
         $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');          $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');
     }      }
     $r->print('      $r->print('
     </nobr>      </nobr><br />
    </td>  
   </tr>  
   <tr>  
    <td>&nbsp;</td>  
    <td colspan="3">  
     <nobr>'.$$lt{'auex'}.':&nbsp;      <nobr>'.$$lt{'auex'}.':&nbsp;
     <label><input type="radio" name="autodrop" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autodrop" value="off" checked="checked" />off</label>');      <label><input type="radio" name="autodrop" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autodrop" value="off" checked="checked" />off</label>');
     if ($action eq 'modify') {      if ($action eq 'modify') {
         $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');          $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');
     }      }
     $r->print('</nobr>      $r->print('</nobr><br /><br />'.$$lt{'mapr'});
    </td>  
   </tr>  
   <tr>  
    <td colspan="4">&nbsp;</td>  
   </tr>  
   <tr>  
    <td>&nbsp;</td>  
    <td colspan="3">'.$$lt{'mapr'}.'  
    </td>  
   </tr>  
 ');  
 }  }
   
 sub mapping_settings {  sub mapping_settings {
     my ($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,$lt,$stored,$image) = @_;      my ($r,$sectioncount,$lt,$stored,$image,$crstype,$cdom,$cnum,$action) = @_;
     my @sections = keys(%{$sectioncount});      my @sections = keys(%{$sectioncount});
     if (@sections > 0) {      if (@sections > 0) {
         @sections = sort {$a cmp $b} @sections;          @sections = sort {$a cmp $b} @sections;
         unshift(@sections,'none'); # Put 'no sections' next          unshift(@sections,'none'); # Put 'no sections' next
         unshift(@sections,'all'); # Put 'all' at the front of the list          unshift(@sections,'all'); # Put 'all' at the front of the list
       } else {
           @sections = ('all','none');
     }      }
     &topic_bar($r,$tabcol,$image,$$lt{'pirs'});      &topic_bar($r,$image,$$lt{'pirs'});
     $r->print('  
    <tr>  
     <td>&nbsp;</td>  
     <td colspan="3">  
 ');  
     my @roles = &standard_roles();      my @roles = &standard_roles();
     my %customroles = &my_custom_roles();      my %customroles = &Apache::lonhtmlcommon::course_custom_roles($cdom,$cnum);
     $r->print(&Apache::lonhtmlcommon::start_pick_box());      $r->print(&Apache::loncommon::start_data_table().
         &Apache::loncommon::start_data_table_header_row());
     $r->print('      $r->print('
                 <tr bgcolor="'.$tabcol.'">  
                  <th>'.&mt('Active?').'</th>                   <th>'.&mt('Active?').'</th>
                  <th>'.&mt('Role').'</th>');                   <th>'.&mt('Role').'</th>');
     if (@sections > 0) {      if (@sections > 0) {
         $r->print('<th>'.&mt('Sections').'</th></tr>'."\n");          $r->print('<th>'.&mt('Sections').'</th>');
     }      }
     my $rowNum = 0;      $r->print(&Apache::loncommon::end_data_table_header_row()."\n");
     my $rowColor;  
     foreach my $role (@roles) {      foreach my $role (@roles) {
         my $plrole=&Apache::lonnet::plaintext($role);          my $roletitle=&Apache::lonnet::plaintext($role,$crstype);
         my $sections_sel;          $r->print(&print_autorole_item($role,$roletitle,\@sections));
         if (@sections > 0) {  
             if ($role eq 'cc') {  
                 $sections_sel = '<td align="right">'.  
                                 &mt('all sections').'<input type="hidden" '.   
                                 'name="sec_cc" value="all" /></td>';  
             } else {   
                 $sections_sel='<td align="right">'.  
                               &sections_selection(\@sections,'sec_'.$role).  
                               '</td>';  
             }  
         }  
         if ($rowNum %2 == 1) {  
             $rowColor = $rowColor1;  
         } else {  
             $rowColor = $rowColor2;  
         }  
         $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.  
                   'name="autorole" value="'.$role.'"></td><td>'.$plrole.  
                   '</td>'.$sections_sel.'</tr>');  
         $rowNum ++;  
     }      }
       my @customs;
     foreach my $role (sort(keys(%customroles))) {      foreach my $role (sort(keys(%customroles))) {
         my $sections_sel;          my ($roletitle) = ($role =~ m|^cr/[^/]+/[^/]+/(.+)$|);
         if (@sections > 0) {          push (@customs,$role);
             $sections_sel = '<td>'.&sections_selection(\@sections,'sec_'.$role).          $r->print(&print_autorole_item($role,$roletitle,\@sections));
                                                                         '</td>';      }
         }      if ($action eq 'modify') {
         if ($rowNum %2 == 1) {          foreach my $role (@{$$stored{'autorole'}}) {
             $rowColor = $rowColor1;              if ((!grep(/^\Q$role\E$/,@customs)) && 
         } else {                  (!grep(/^\Q$role\E$/,@roles))) {
             $rowColor = $rowColor2;                  my $roletitle;
                   if ($role =~ /^cr/) {
                       ($roletitle) = ($role =~ m|_([^_]+)$|);
                   } else {
                       $roletitle = &Apache::lonnet::plaintext($role,$crstype);
                   }
                   $r->print(&print_autorole_item($role,$roletitle,\@sections));
               }
         }          }
         $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.  
                   'value="'.$role.'"></td><td>'.$role.'</td>'.  
                   $sections_sel.'</tr>');  
         $rowNum ++;  
     }      }
     $r->print(&Apache::lonhtmlcommon::end_pick_box());      $r->print(&Apache::loncommon::end_data_table());
     return;      return;
 }  }
   
   sub print_autorole_item {
       my ($role,$roletitle,$sections) = @_;
       my $sections_sel;
       if (@{$sections} > 0) {
           if ($role eq 'cc') {
               $sections_sel = '<td align="right">'.
                               &mt('all sections').'<input type="hidden" '.
                               'name="sec_cc" value="all" /></td>';
           } else {
               $sections_sel='<td align="right">'.
                             &sections_selection($sections,'sec_'.$role).
                             '</td>';
           }
       }
       my $output = &Apache::loncommon::start_data_table_row().
                    '<td><input type="checkbox" '.
                    'name="autorole" value="'.$role.'" />'.
                    '</td><td>'.$roletitle.'</td>'.$sections_sel.
                    &Apache::loncommon::end_data_table_row();
       return $output;
   } 
   
 sub standard_roles {  sub standard_roles {
     my @roles = ('cc','in','ta','ep','st');      my @roles = ('cc','in','ta','ep','st');
     return @roles;      return @roles;
 }  }
   
 sub my_custom_roles {  
     my %returnhash=();  
     my %rolehash=&Apache::lonnet::dump('roles');  
     foreach (keys %rolehash) {  
         if ($_=~/^rolesdef\_(\w+)$/) {  
             $returnhash{$1}=$1;  
         }  
     }  
     return %returnhash;  
 }  
   
 sub modify_menu {  sub modify_menu {
     my ($r,$groupname,$page) = @_;      my ($r,$groupname,$page,$gpterm) = @_;
     my @menu =      my @menu =
         (          (
           { text => 'Modify default group settings',            { text => "Modify default $gpterm settings",
             help => 'Course_Modify_Group',              help => 'Course_Modify_Group',
             state => 'change_settings',              state => 'change_settings',
             branch => 'settings',              branch => 'settings',
Line 3341  sub modify_menu { Line 3244  sub modify_menu {
             state => 'change_members',              state => 'change_members',
             branch => 'members',              branch => 'members',
             },              },
           { text => 'Add member(s) to the group',            { text => "Add member(s) to the $gpterm",
             help => 'Course_Group_Add_Members',              help => 'Course_Group_Add_Members',
             state => 'add_members',              state => 'add_members',
             branch => 'adds',              branch => 'adds',
Line 3363  sub modify_menu { Line 3266  sub modify_menu {
 }  }
   
 sub member_privs_entries {  sub member_privs_entries {
     my ($r,$tabcol,$rowColor1,$rowColor2,$usertools,$toolprivs,      my ($r,$usertools,$toolprivs,$fixedprivs,$userdata,$idx,$showtools,
         $fixedprivs,$userdata,$idx,$showtools,$defprivs,$excluded) = @_;   $defprivs,$excluded) = @_;
     my $rowColor;  
     my $rowNum = 0;  
     foreach my $user (sort(keys(%{$usertools}))) {      foreach my $user (sort(keys(%{$usertools}))) {
         if (defined($excluded)) {          if (defined($excluded)) {
             if (ref($excluded) eq 'ARRAY') {              if (ref($excluded) eq 'ARRAY') {
Line 3376  sub member_privs_entries { Line 3277  sub member_privs_entries {
             }              }
         }          }
         my ($uname,$udom) = split(/:/,$user);          my ($uname,$udom) = split(/:/,$user);
         if ($rowNum %2 == 1) {          $r->print(&Apache::loncommon::start_data_table_row().'
             $rowColor = $rowColor1;  
         } else {  
             $rowColor = $rowColor2;  
         }  
         $r->print('<tr bgcolor="'.$rowColor.'">  
                 <td>'.$$userdata{$user}[$$idx{fullname}].'</td>                  <td>'.$$userdata{$user}[$$idx{fullname}].'</td>
                 <td>'.$uname.'</td>                  <td>'.$uname.'</td>
                 <td>'.$udom.'</td>                  <td>'.$udom.'</td>
                 <td valign="top"><table><tr><td><b>Function</b></td></tr><tr><td><b>Fixed</b></td></tr><tr><td><b>Optional</b></td></tr></table></td>');                  <td valign="top">
                     <table>
                      <tr>
                       <td><b>'.
                       &mt('Collaborative Tool').'</b></td>
                      </tr>
                      <tr>
                       <td><b>'.&mt('Fixed').'</b></td>
                      </tr>
                      <tr>
                       <td><b>'.&mt('Optional').'</b></td>
                      </tr>
                     </table>
                    </td>');
         foreach my $tool (@{$showtools}) {          foreach my $tool (@{$showtools}) {
             if (exists($$usertools{$user}{$tool})) {              if (exists($$usertools{$user}{$tool})) {
                 $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');                  $r->print('<td valign="top"><table><tr><th colspan="2">'.$tool.'</th></tr>');
                 my $privcount = 0;                  my $privcount = 0;
                 my $fixed = '';                  my $fixed = '';
                 my $dynamic = '';                  my $dynamic = '';
Line 3411  sub member_privs_entries { Line 3320  sub member_privs_entries {
                 }                  }
                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');                  $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');
             } else {              } else {
                 $r->print('<td valign="top"><table width="100%"><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr><tr><td>&nbsp;</td></tr><tr><td>&nbsp;</td></tr></table></td>');                  $r->print('<td valign="top"><table width="100%"><tr><th colspan="2">'.$tool.'</th></tr><tr><td>&nbsp;</td></tr><tr><td>&nbsp;</td></tr></table></td>');
             }              }
         }          }
         $rowNum ++;          $r->print(&Apache::loncommon::end_data_table_row());
     }      }
 }  }
   
Line 3435  sub date_setting_table { Line 3344  sub date_setting_table {
                                                       'startdate',$starttime);                                                        'startdate',$starttime);
     my $endform = &Apache::lonhtmlcommon::date_setter($formname,      my $endform = &Apache::lonhtmlcommon::date_setter($formname,
                                                       'enddate',$endtime);                                                        'enddate',$endtime);
     my $perpetual = '<nobr><label><input type="checkbox" name="no_end_date" />      my $perpetual = 
                                                 no ending date</label></nobr>';   '<nobr><label><input type="checkbox" name="no_end_date" />'.
     my $start_table = '';   &mt('None').'</label></nobr>';
     $start_table .= "<table>\n";      my $table = "<table class=\"LC_descriptive_input\">\n".
     $start_table .= '<tr><td align="right">Default starting date for    '<tr><td class="LC_description">'.&mt('Start:').'</td>'.
                                            member access</td>'.  
         '<td>'.$startform.'</td>'.          '<td>'.$startform.'</td>'.
         '<td>&nbsp;</td>'."</tr>\n";          '<td>&nbsp;</td>'."</tr>\n".
     $start_table .= "</table>";   '<tr><td class="LC_description">'.&mt('End:').'</td>'.
     my $end_table = '';  
     $end_table .= "<table>\n";  
     $end_table .= '<tr><td align="right">Default ending date for   
                                          member access</td>'.  
         '<td>'.$endform.'</td>'.          '<td>'.$endform.'</td>'.
         '<td>'.$perpetual.'</td>'."</tr>\n";          '<td>'.$perpetual.'</td>'."</tr>\n".
     $end_table .= "</table>\n";   "</table>\n";
     return ($start_table, $end_table);      return $table;
   }
   
   sub add_group_folder {
       my ($cdom,$cnum,$now,$groupname,$action,$description,$tools,$groupinfo,
           $gpterm,$ucgpterm,$crstype) = @_;
       if ($cdom eq '' || $cnum eq '') {
           return &mt('Error: invalid course domain or number - group folder creation failed');  
       }
       my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage);
       my $navmap = Apache::lonnavmaps::navmap->new();
       my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
       $allgrpsmap = $crspath.'group_allfolders.sequence';
       my $topmap = $navmap->getResourceByUrl($allgrpsmap);
       undef($navmap);
       if ($action eq 'create') {
       # check if group_allfolders.sequence exists.
           if (!$topmap) {
               my $grpstitle = &mt('[_1] [_2]s',$crstype,$ucgpterm);
               my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'};
               $topmap_url =~ s|/+|/|g;
               if ($topmap_url =~ m|^/uploaded|) {
                   $outcome = &map_updater($cdom,$cnum,'group_allfolders.sequence',
                                           'toplevelgroup',$grpstitle,$topmap_url);
                   if ($outcome ne 'ok') {
                       return $outcome;
                   }
               } else {
                   $outcome = &mt('Non-standard course - folder for all groups not added.');
                   return $outcome;
               }
           }
           my $grpfolder = &mt('[_1] Folder -',$ucgpterm,).$description;
           $grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/smppg';
           my $grptitle = &mt('Group homepage').' - '.$description;
           my ($discussions,$disctitle);
           my $outcome = &map_updater($cdom,$cnum,'group_folder_'.$groupname.'.sequence',
                                      'grpseq',$grpfolder,$allgrpsmap,$grppage,
                                      $grptitle);
           if ($outcome ne 'ok') {
               return $outcome;
           }
           my $pageout = &create_homepage($cdom,$cnum,$groupname,$groupinfo,
                                          $tools,$gpterm,$ucgpterm,$now);
           # Link to folder for bulletin boards
           $grpmap = $crspath.'group_folder_'.$groupname.'.sequence';
           if (grep/^discussion$/,@{$tools}) {
               $disctitle = &mt('Discussion Boards');
               my $outcome = &map_updater($cdom,$cnum,'group_boards_'.$groupname.
                                          '.sequence','bbseq',$disctitle,$grpmap);
               if ($outcome ne 'ok') {
                   return $outcome;
               }
               $boardsmap = $crspath.'group_boards_'.$groupname.'.sequence';
           }
       } else {
           #modify group folder if status of discussions tools is changed
       }
       my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
       $navmap = Apache::lonnavmaps::navmap->new();
       # modify parameters
       my $parm_result;
       if ($action eq 'create') {
           if ($grpmap) {
               $parm_result .= &parm_setter($navmap,$cdom,$grpmap,$groupname);
           }
           if ($grppage) {
               $parm_result .= &parm_setter($navmap,$cdom,$grppage,$groupname);
           }
           if ($boardsmap) {
               $parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname);
           }
       }
       if ($parm_result) {
           return $parm_result;
       } else {
           return 'ok';
       }
   }
   
   sub map_updater {
       my ($cdom,$cnum,$newfile,$itemname,$itemtitle,$parentmap,$startsrc,
           $starttitle,$endsrc,$endtitle) = @_;
       my $outcome;
       $env{'form.'.$itemname} = &new_map($startsrc,$starttitle,$endsrc,
                                          $endtitle);
       my $newmapurl=&Apache::lonnet::finishuserfileupload($cnum,$cdom,$itemname,
                                                           $newfile);
       if ($newmapurl !~ m|^/uploaded|) {
           $outcome = &mt('Error uploading new folder.')." ($newfile): $newmapurl".'<br />';
           return $outcome;
       } 
       my ($errtext,$fatal)=&Apache::lonratedt::mapread($parentmap);
       if ($fatal) {
           $outcome = &mt('Error reading contents of parent folder')." ($parentmap): $errtext".'<br />';
           return $outcome;
       } else {
           my $newidx=&Apache::lonratedt::getresidx($newmapurl);
           $Apache::lonratedt::resources[$newidx] = $itemtitle.':'.$newmapurl.
                                                    ':false:normal:res';
           $Apache::lonratedt::order[1+$#Apache::lonratedt::order]=$newidx;
           my ($outtext,$errtext) = &Apache::lonratedt::storemap($parentmap,1);
           if ($errtext) {
               $outcome = &mt('Error storing updated parent folder')." ($parentmap):  $errtext".'<br />';
               return $outcome;
           }
       }
       return 'ok';
   }
   
   sub new_map {
       my ($startsrc,$starttitle,$endsrc,$endtitle) = @_;
       my $newmapstr = '
   <map>
    <resource id="1" src="'.$startsrc.'" type="start" title="'.$starttitle.'"></resource>
    <link from="1" to="2" index="1"></link>
    <resource id="2" src="'.$endsrc.'" type="finish" title="'.$endtitle.'"></resource>
   </map>
   ';
       return $newmapstr;
   }
   
   sub parm_setter {
       my ($navmap,$cdom,$url,$groupname) = @_;
       my $allresults;
       my %hide_settings = (
                              'course' =>  {
                                             'num' => 13,
                                             'set' => 'yes',
                                           },
                               'group' =>  {
                                             'num' => 5,
                                             'set' => 'no',
                                             'extra' => $groupname,
                                           },
                           );
       my $res = $navmap->getResourceByUrl($url);
       my $symb = $res->symb();
       foreach my $level (keys(%hide_settings)) {
           my $parmresult =  &Apache::lonparmset::storeparm_by_symb($symb,
                                                    '0_hiddenresource',
                                                    $hide_settings{$level}{'num'},
                                                    $hide_settings{$level}{'set'},
                                                    'string_yesno',undef,$cdom,
                                                    undef,undef,
                                                    $hide_settings{$level}{'extra'});
           if ($parmresult) {
               $allresults .= $level.': '.$parmresult;
           }
       }
       return $allresults;
 }  }
   
 sub create_homepage {  sub create_homepage {
     my ($cdom,$cnum,$name,$groupinfo,$tools) = @_;      my ($cdom,$cnum,$name,$groupinfo,$tools,$gpterm,$ucgpterm,$now) = @_;
     my $functionality = join(',',@{$tools});      my $functionality = join(',',@{$tools});
     my $content = &unescape($$groupinfo{description});      my $content = &unescape($$groupinfo{description});
     $content=~s/\s+$//s;      $content=~s/\s+$//s;
Line 3464  sub create_homepage { Line 3518  sub create_homepage {
     $content=&Apache::lonfeedback::clear_out_html($content,1);      $content=&Apache::lonfeedback::clear_out_html($content,1);
   
     my %pageinfo = (      my %pageinfo = (
                      'aaa_title' => 'Group: '.$name,                       'aaa_title' => "$ucgpterm: $name",
                      'abb_links' => $functionality,                       'abb_links' => $functionality,
                      'bbb_content' => $content,                       'bbb_content' => $content,
                      'ccc_webreferences' => '',                       'ccc_webreferences' => '',
                      'uploaded.lastmodified' => time,                       'uploaded.lastmodified' => $now,
                    );                     );
    my $putresult = &Apache::lonnet::put('grppage_'.$name,\%pageinfo,$cdom,$cnum);     my $putresult = &Apache::lonnet::put('grppage_'.$name,\%pageinfo,$cdom,$cnum);
    return $putresult;     return $putresult;
Line 3510  function toggleTools(field,caller) { Line 3564  function toggleTools(field,caller) {
 }  }
   
 sub validate_groupname {  sub validate_groupname {
     my ($groupname,$action,$cdom,$cnum) = @_;      my ($groupname,$action,$cdom,$cnum,$gpterm,$ucgpterm,$crstype) = @_;
     my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);      my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
     my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);      my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
   
     my %lt = &Apache::lonlocal::texthash (      my %lt = &Apache::lonlocal::texthash (
                       igna => 'Invalid group name',                        igna => "Invalid $gpterm name",
                       tgne => 'The group name entered ',                        tgne => "The $gpterm name entered ",
                       grna => 'Group names and section names used in a course '.                        grna => "$ucgpterm names and section names used in a ".
                               'must be unique.',                                 "$crstype must be unique.",
                       isno => 'is not a valid name.',                        isno => "is not a valid name.",
                       gnmo => 'Group names may only contain letters, numbers '.                        gnmo => "$ucgpterm names may only contain letters, ". 
                               'or underscores.',                                "numbers or underscores.",
                       cnnb => 'can not be used as it is the name of ',                        cnnb => "can not be used as it is the name of ",
                       inth => ' in this course.',                        inth => " in this $crstype", 
                       thgr => '- does not correspond to the name of an existing'.                          thgr => "- does not correspond to the name of an ".
                               ' group ',                                    "existing $gpterm",    
     );      );
   
     my $exitmsg = '<b>'.$lt{'igna'}.'</b><br /><br />'.$lt{'tgne'}.' "'.      my $exitmsg = '<span class="LC_error">'.$lt{'igna'}.'</span><br /><br />'.
                   $groupname.'" ';   $lt{'tgne'}.' "'.$groupname.'" ';
     my $dupmsg = $lt{'grna'};      my $dupmsg = $lt{'grna'};
     my $earlyout;      my $earlyout;
     if (($groupname eq '') || ($groupname =~ /\W/)) {      if (($groupname eq '') || ($groupname =~ /\W/)) {
Line 3543  sub validate_groupname { Line 3597  sub validate_groupname {
     if ($action eq 'create'       if ($action eq 'create' 
  && exists($curr_groups{$groupname})) {   && exists($curr_groups{$groupname})) {
   
  return $exitmsg.$lt{'cnnb'}.&mt('an existing group').   return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm).
     $lt{'inth'}.'<br />'.$lt{'grna'};      $lt{'inth'}.'<br />'.$lt{'grna'};
   
     } elsif ($action eq 'modify') {      } elsif ($action eq 'modify') {
         unless(exists($curr_groups{$groupname})) {          unless(exists($curr_groups{$groupname})) {
             $earlyout = &mt('Group name:').' '.$groupname.$lt{'thgr'}.$lt{'inth'};              $earlyout = &mt('[_1] name:',$ucgpterm).' '.$groupname.$lt{'thgr'}.
                           $lt{'inth'};
             return $earlyout;              return $earlyout;
         }          }
     }      }
Line 3556  sub validate_groupname { Line 3611  sub validate_groupname {
 }  }
   
 sub topic_bar {  sub topic_bar {
     my ($r,$tabcol,$imgnum,$title) = @_;      my ($r,$imgnum,$title) = @_;
     $r->print('      $r->print('
  <tr bgcolor="'.$tabcol.'">  <div class="LC_topic_bar">
   <td>&nbsp;</td>      <img alt="'.&mt('Step [_1]',$imgnum).
   <td valign="middle" align="left">        '"src="/res/adm/pages/bl_step'.$imgnum.'.gif" />&nbsp;
    <nobr>      <span>'.$title.'</span>
     <img src="/res/adm/pages/bl_step'.$imgnum.'.gif" valign="middle">&nbsp;  </div>
    </nobr>  
   </td>  
   <th align="left"><nobr>'.$title.'<nobr>  
   </th>  
   <td width="100%">&nbsp;</td>  
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
 ');  ');
     return;      return;
 }  }

Removed from v.1.26  
changed lines
  Added in v.1.61


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>