Diff for /loncom/interface/loncoursegroups.pm between versions 1.3 and 1.56

version 1.3, 2005/11/15 22:03:05 version 1.56, 2006/07/21 02:46:51
Line 1 Line 1
   # The LearningOnline Network with CAPA
   #
   # $Id$
 #  #
 # Copyright Michigan State University Board of Trustees  # Copyright Michigan State University Board of Trustees
 #  #
Line 30  use Apache::loncommon; Line 33  use Apache::loncommon;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnavmaps;  use Apache::lonnavmaps;
   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 LONCAPA;
   
 sub handler {  sub handler {
     my ($r) = @_;      my ($r) = @_;
   
     &Apache::loncommon::content_type($r,'text/html');      &Apache::loncommon::content_type($r,'text/html');
     $r->send_http_header;      $r->send_http_header;
                                                                                   
     if ($r->header_only) {      if ($r->header_only) {
         return OK;          return OK;
     }      }
Line 51  sub handler { Line 58  sub handler {
     }      }
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['action','refpage']);                          ['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 79  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 $action = $env{'form.action'};      my $action = $env{'form.action'};
       my $state = $env{'form.state'};
       if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify')) {
           if (!defined($state)) {
               $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,$cdom,$cnum,$function,$tabcol,              if ($state eq 'view') {
                         \%functions,\%idx,$view_permission,$manage_permission);                  &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,
                                    $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('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);   $manage_permission,$action,$state,$gpterm,$ucgpterm,
    $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,$gpterm,$ucgpterm,$crstype) = @_;
                                                                           = @_;      my $jscript = qq|
     $r->print(&header('Course Groups',&mt('LON-CAPA Course Groups'),  function changeSort(caller) {
                                                  undef,undef,undef,$function));      document.$state.sortby.value = caller;
       document.$state.submit();
   }\n|;
       $r->print(&header('Groups',$jscript,$action,$state));
       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      $r->print(&Apache::lonhtmlcommon::breadcrumbs('Groups'));
                 (undef,'Course Groups'));      &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,      $manage_permission,$action,$state,$gpterm,$ucgpterm,
                                           $view_permission,$manage_permission);      $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) = @_;          $manage_permission,$action,$state,$gpterm,$ucgpterm,$crstype) = @_;
     my %curr_groups = ();      my %curr_groups = ();
     my %grp_info = ();      my %grp_info = ();
     my $rowColor1 = "#dddddd";      my %actionlinks = (
     my $rowColor2 = "#eeeeee";        modify => '<a href="/adm/coursegroups?action=modify&refpage='.
                            $env{'form.refpage'}.'&state=pick_task&groupname=',
     $r->print('<br /><br />');        view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',
         delete => '<a href="/adm/coursegroups?action=delete&refpage='.
                            $env{'form.refpage'}.'&groupname=',
       );
       my %lt = &Apache::lonlocal::texthash( 
                             modify => 'Modify',
                             view   => 'View',
                             delete => 'Delete',
                             act    => 'Action',
                             gname  => 'Group Name',
                             desc   => 'Group Title',
                             crea   => 'Creator',
                             crtd   => 'Created',
                             last   => 'Last Modified',
                             func   => 'Collaborative Tools',
                             quot   => 'Quota (Mb)',
                             memb   => 'Members',
                             file   => 'Files',
                             dibd   => 'Discussion Boards',
                             dius   => 'Disk Use (%)',
                             nogr   => 'No groups exist.',
                             crng   => 'Create a new group',
                             alth   => 'Although your current role has privileges'.
                                       ' to view any existing groups in this'.
                                       lc($crstype).', you do not have privileges'.
                                       'to create new groups.',
                        );
     if ($view_permission) {      if ($view_permission) {
         if (&Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups) > 0) {          if (!defined($action)) {
             $r->print(&Apache::lonhtmlcommon::start_pick_box());              $action = 'view';
             if (keys(%curr_groups) > 0) {          }
                 $r->print(<<"END");          my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
       <table border="0" cellpadding="4" cellspacing="1">          if (%curr_groups) {
        <tr bgcolor="$tabcol" align="center">              if ($manage_permission) {
         <td><b>Action</b></td>                  if (!exists($env{'form.refpage'})) { 
         <td><b><a href="javascript:changeSort('groupname')">Group Name</a></b></td>                      $r->print('<br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>');
         <td><b><a href="javascript:changeSort('description')">Description</a></b></td>                  }
         <td><b><a href="javascript:changeSort('creator')">Creator</a></b>              }
         </td>              $r->print('<br /><br />');
         <td><b><a href="javascript:changeSort('creation')">Created</a></b>      $r->print(&Apache::loncommon::start_data_table().
         </td>        &Apache::loncommon::start_data_table_header_row());
         <td><b><a href="javascript:changeSort('modified')">Last Modified</a></b>        
         </td>              $r->print(<<"END");
         <td><b>Functionality</b>          <th>$lt{'act'}</th>
         </td>          <th><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></th>
         <td><b><a href="javascript:changeSort('quota')">Quota (Mb)</a></b></td>          <th><a href="javascript:changeSort('description')">$lt{'desc'}</a></th>
         <td><b><a href="javascript:changeSort('totalmembers)">Members</a></b></td>          <th><a href="javascript:changeSort('creator')">$lt{'crea'}</a></th>
         <td><b><a href="javascript:changeSort('totalfiles')">Files</a></b></td>          <th><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></th>
         <td><b><a href="javascript:changeSort('boards')">Discussion boards</a></b></td>          <th><a href="javascript:changeSort('modified')">$lt{'last'}</a></th>
         <td><b><a href="javascript:changeSort('diskuse')">Disk use</a></b></td>          <th>$lt{'func'}</b></td>
        </tr>          <th><a href="javascript:changeSort('quota')">$lt{'quot'}</a></th>
           <th><a href="javascript:changeSort('totalmembers')">$lt{'memb'}</a></th>
           <th><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></th>
           <th><a href="javascript:changeSort('boards')">$lt{'dibd'}</a></th>
           <th><a href="javascript:changeSort('diskuse')">$lt{'dius'}</a></th>
 END  END
                 my %Sortby = ();      $r->print(&Apache::loncommon::end_data_table_header_row());
                 foreach my $group (sort(keys(%curr_groups))) {              my %Sortby = ();
                     %{$grp_info{$group}} =               foreach my $group (sort(keys(%curr_groups))) {
                                       &Apache::loncommon::get_group_settings(                  %{$grp_info{$group}} = 
                                     &Apache::longroup::get_group_settings(
                                                          $curr_groups{$group});                                                           $curr_groups{$group});
                     my $members_result = &group_members($group,\%grp_info);                  my $members_result = &group_members($cdom,$cnum,$group,
                     my $files_result = &group_files($group,\%grp_info);                                                       \%grp_info);
                     if ($env{'form.sortby'} eq 'groupname') {                  my $port_path = '/userfiles/groups/'.$group.'/portfolio';
                         push(@{$Sortby{$group}},$group);                  my $port_dir = &Apache::loncommon::propath($cdom,$cnum).$port_path;
                     } elsif ($env{'form.sortby'} eq 'description') {                  my $totaldirs = 0;
                         push(@{$Sortby{$grp_info{$group}{'description'}}},                  my $totalfiles = 0;
                                                                      $group);                  &group_files($group,$port_dir,\$totalfiles,\$totaldirs);
                     } elsif ($env{'form.sortby'} eq 'creator') {                  $grp_info{$group}{'totalfiles'} = $totalfiles;
                         push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);                  $grp_info{$group}{'totaldirs'} = $totaldirs;
                     } elsif ($env{'form.sortby'} eq 'creation') {                  my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_dir);
                         push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);                  if ($grp_info{$group}{'quota'} > 0) {
                     } elsif ($env{'form.sortby'} eq 'modified') {                      my $pct_use = 0.1 * $diskuse/$grp_info{$group}{'quota'};
                         push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);                      $grp_info{$group}{'diskuse'} = sprintf("%.0f",$pct_use);
                     } elsif ($env{'form.sortby'} eq 'quota') {                  } else {
                         push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);                      $grp_info{$group}{'diskuse'} = 'N/A';
                     } elsif ($env{'form.sortby'} eq 'totalmembers') {                  }
                         push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},                  my ($groupboards,$boardshash)=&Apache::longroup::get_group_bbinfo(
                                                                        $group);                                                                 $cdom,$cnum,$group);
                     } elsif ($env{'form.sortby'} eq 'totalfiles') {                  $grp_info{$group}{'boards'} = scalar(@{$groupboards});
                         push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},                  if ($env{'form.sortby'} eq 'groupname') {
                       push(@{$Sortby{$group}},$group);
                   } elsif ($env{'form.sortby'} eq 'description') {
                       push(@{$Sortby{$grp_info{$group}{'description'}}},$group);
                   } elsif ($env{'form.sortby'} eq 'creator') {
                       push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);
                   } elsif ($env{'form.sortby'} eq 'creation') {
                       push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);
                   } elsif ($env{'form.sortby'} eq 'modified') {
                       push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);
                   } elsif ($env{'form.sortby'} eq 'quota') {
                       push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);
                   } elsif ($env{'form.sortby'} eq 'totalmembers') {
                       push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},
                                                                        $group);                                                                         $group);
                     } elsif ($env{'form.sortby'} eq 'boards') {                  } elsif ($env{'form.sortby'} eq 'totalfiles') {
                         push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},$group);
                     } elsif ($env{'form.sortby'} eq 'diskuse') {                  } elsif ($env{'form.sortby'} eq 'boards') {
                         push(@{$Sortby{$grp_info{$group}{'diskuse'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);
                     } else {                  } elsif ($env{'form.sortby'} eq 'diskuse') {
                         push(@{$Sortby{$group}},$group);                      push(@{$Sortby{$grp_info{$group}{'diskuse'}}},$group);
                     }                  } else {
                       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}}) {                      my $description = 
                         if ($rowNum %2 == 1) {   &unescape($grp_info{$group}{'description'});
                             $rowColor = $rowColor1;                      my $creator = $grp_info{$group}{'creator'};
                         } else {                      my $creation = $grp_info{$group}{'creation'};
                             $rowColor = $rowColor2;                      my $modified = $grp_info{$group}{'modified'}; 
                       my $quota = $grp_info{$group}{'quota'};
                       my $totalmembers = $grp_info{$group}{'totalmembers'};
                       my $totalfiles = $grp_info{$group}{'totalfiles'};
                       my $totaldirs = $grp_info{$group}{'totaldirs'};
                       my $boards = $grp_info{$group}{'boards'};
                       my $diskuse = $grp_info{$group}{'diskuse'};
                       my $functionality;
                       foreach my $tool (sort(keys(%{$functions}))) {
                           if ($grp_info{$group}{functions}{$tool} eq 'on') {
                               $functionality .= ' '.$tool;
                         }                          }
                         my $description =                       }
                    &Apache::lonnet::unescape($grp_info{$group}{'description'});                      if (!$functionality) {
                         my $creator = $grp_info{$group}{'creator'};                          $functionality = &mt('None available');
                         my $creation = $grp_info{$group}{'creation'};                      }
                         my $modified = $grp_info{$group}{'modified'};                       my $link = $actionlinks{$action};
                         my $quota = $grp_info{$group}{'quota'};                      if ($action eq 'modify' || $action eq 'delete') {
                         my $totalmembers = $grp_info{$group}{'totalmembers'};                          $link .= $group;
                         my $totalfiles = $grp_info{$group}{'totalfiles'};                      } else {
                         my $boards = $grp_info{$group}{'boards'};                          $link .= $group.'/smppg?ref=grouplist';
                         my $diskuse = $grp_info{$group}{'diskuse'};                          if (exists($env{'form.refpage'})) {
                         my $functionality;                              $link .= '&amp;refpage='.$env{'form.refpage'};
                         foreach my $tool (sort keys(%{$functions})) {  
                             if (defined($grp_info{$group}{functions}{$tool})) {  
                                 $functionality .= ' '.$tool;  
                             }  
                         }                          }
                         if (!$functionality) {                      }
                             $functionality = 'None available';                      $link .= '">'.$lt{$action}.'</a>';
                       if ($action eq 'view') { 
                           if (($manage_permission) && 
                               ($env{'form.refpage'} ne 'enrl')) {
                               $link .= '&nbsp;&nbsp;'.$actionlinks{'modify'}.
                                         $group.'">'.$lt{'modify'}.'</a>';
                         }                          }
                         $r->print('<tr bgcolor="'.$rowColor.'"><td align="right">  
    <a href="/adm/entergroup?group='.$group.'"/>View</a>&nbsp;<a href="/adm/coursegroups?action=modify&group='.$group.'">Modify</a></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>');  
                         $rowNum ++;  
                     }                      }
                       $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').
         '<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(&Apache::loncommon::end_data_table());
               $r->print('<input type="hidden" name="refpage" '.
                         'value="'.$env{'form.refpage'}.'" />');
               if ($action eq 'view') {
                   if (!defined($state)) {
                       $state = 'view';
                 }                  }
                 $r->print('</table>');                  $r->print('<input type="hidden" name="state" value="'.
                 $r->print(&Apache::lonhtmlcommon::end_pick_box());                        $state.'" />');
             }                             }
         } else {          } else {
             $r->print('No groups exist');              $r->print($lt{'nogr'});
               if ($manage_permission) {
                   if (!exists($env{'form.refpage'})) {
                       $r->print('<br /><br /><a href="/adm/coursegroups?action=create">'.$lt{'crng'}.'</a>');
                   }
               } else {
                   $r->print('<br /><br />'.$lt{'alth'});
   
               }
         }          }
     } else {      } else {
         $r->print('You do not have sufficient privileges to allow you to display course groups');          my @coursegroups = split(/:/,$env{'request.course.groups'});
           if (@coursegroups > 0) {
               $r->print('<br /><br />');
               my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
               if (%curr_groups) {
                   foreach my $group (@coursegroups) {
                       my %group_info =  &Apache::longroup::get_group_settings(
                                           $curr_groups{$group});
                       my $description = &unescape(
                                           $group_info{description});
                       $r->print('<font size="+1"><a href="/adm/'.$cdom.'/'.$cnum.'/'.$group.'/smppg?ref=grouplist">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');
                   }
               }
           } else {
               $r->print(&mt('You are not currently a member of any '.
                             'active [_1]s in this [_2]',$gpterm,
                             lc($crstype)));
           }
     }      }
     return;      return;
 }  }
   
 sub group_administration {  sub group_administration {
     my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx,      my ($r,$action,$state,$cdom,$cnum,$functions,$idx,$view_permission,
                                      $view_permission,$manage_permission) = @_;   $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 = ();
     my %usertools = ();      my %usertools = ();
       my %stored = ();
       my %memchg;
       my @member_changes = ('deletion','expire','activate','reenable',
                             'changefunc','changepriv');
       my ($groupname,$description,$startdate,$enddate,$granularity,$specificity,
           $quota,$validate_script);
   
     my $state = $env{'form.state'};      if (defined($env{'form.groupname'})) {
     my ($groupname,$description,$startdate,$enddate);          $groupname = $env{'form.groupname'};
       }
   
     if ($action eq 'create') {      if (($action eq 'create') && ($state eq '')) {
           $state = 'pick_name';
       }
       if (($action eq 'create') || 
           (($action eq 'modify') && ($state eq 'chgresult'))) { 
           ($startdate,$enddate) = &get_dates_from_form();
           if (defined($env{'form.description'})) {
               $description = $env{'form.description'};
           }
           if (defined($env{'form.tool'})) {
               @tools=&Apache::loncommon::get_env_multiple('form.tool');
           }
           if (defined($env{'form.granularity'})) {
               $granularity=$env{'form.granularity'};
           }
           if (defined($env{'form.specificity'})) {
               $specificity=$env{'form.specificity'};
           }
           if (defined($env{'form.quota'})) {
               $quota=$env{'form.quota'};
           }
       }
       if (($action eq 'create') || (($action eq 'modify') 
           && (($state eq 'pick_privs') || ($state eq 'addresult')))) {
           if (defined($env{'form.member'})) {
               @members = &Apache::loncommon::get_env_multiple('form.member');
               foreach my $user (@members) {
                   %{$usertools{$user}} = ();
               }
           }
       }
   
       if ($action eq 'modify') {
         if ($state eq '') {          if ($state eq '') {
             $state = 'pick_name';  
         } else {  
             ($startdate,$enddate) = &get_dates_from_form();  
             if (defined($env{'form.groupname'})) {              if (defined($env{'form.groupname'})) {
                 $groupname = $env{'form.groupname'};                  $state = 'pick_task';
             }  
             if (defined($env{'form.description'})) {  
                 $description = $env{'form.description'};  
             }  
             if (defined($env{'form.tool'})) {  
                 @tools=&Apache::loncommon::get_env_multiple('form.tool');  
             }              }
             if (defined($env{'form.member'})) {          } else {
                 @members = &Apache::loncommon::get_env_multiple('form.member');              %stored = &retrieve_settings($cdom,$cnum,$groupname);
                 foreach my $user (@members) {              if (ref($stored{'types'}) eq 'ARRAY') {
                     %{$usertools{$user}} = ();                  @types = @{$stored{'types'}};
               }
               if (ref($stored{'roles'}) eq 'ARRAY') {
                   @roles = @{$stored{'roles'}};
               }
               if (ref($stored{'sectionpick'}) eq 'ARRAY') {
                   @sections = @{$stored{'sectionpick'}};
               }
               unless ($state eq 'chgresult') {
                   if (ref($stored{'tool'}) eq 'ARRAY') { 
                       @tools = @{$stored{'tool'}};
                 }                  }
                   $startdate = $stored{'startdate'};
                   $enddate = $stored{'enddate'};
                   $description = $stored{'description'};
                   $granularity = $stored{'granularity'};
                   $specificity =  $stored{'specificity'};
                   $quota = $stored{'quota'};
               }
           }
       }
   
       my $toolprivs = &Apache::longroup::get_tool_privs($gpterm);
   
       my $fixedprivs = &Apache::longroup::get_fixed_privs();
   
       my %elements = 
    (
    create => {
        pick_name => {
    startdate_month  => 'selectbox',
    startdate_hour   => 'selectbox',
    enddate_month    => 'selectbox',
    enddate_hour     => 'selectbox',
    startdate_day    => 'text',
    startdate_year   => 'text',
    startdate_minute => 'text',
    startdate_second => 'text',
    enddate_day      => 'text',
    enddate_year     => 'text',
    enddate_minute   => 'text',
    enddate_second   => 'text',
    groupname        => 'text',
    description      => 'text',
                    quota            => 'text',
    tool             => 'checkbox',
    granularity      => 'radio',
    no_end_date      => 'checkbox',
        },
        pick_members => {
    member          => 'checkbox',
    defpriv         => 'checkbox',
        },
    },
    );
       
       $elements{'modify'} = {
    change_settings => {
       %{$elements{'create'}{'pick_name'}},
       specificity => 'radio',
       defpriv     => 'checkbox',
       autorole    => 'checkbox',
       autoadd     => 'radio',
       autodrop    => 'radio',
    },
    add_members => {
       types       => 'selectbox',
       roles       => 'selectbox',
    },
       };
   
       if (ref($stored{'autorole'}) eq 'ARRAY') {
           foreach my $role (@{$stored{'autorole'}}) {
               unless ($role eq 'cc') {
                   $elements{'modify'}{'change_settings'}{'sec_'.$role} = 
                                                                      'selectbox';
             }              }
         }          }
     }      }
   
     my %toolprivs = ();  
     %{$toolprivs{'email'}} = (  
                                  sgm => 'Send group mail',  
                                  sgb => 'Broadcast mail',  
                              );  
     %{$toolprivs{'discussion'}} =  (  
                                      cgb => 'Create boards',  
                                      pgd => 'Post',  
                                      pag => 'Anon. posts',  
                                      rgi => 'Get identities',   
                                      vgb => 'View boards',  
                                    );  
     %{$toolprivs{'chat'}} =  (  
                                 pgc => 'Chat',  
                              );  
     %{$toolprivs{'files'}} =  (  
                                  rgf => 'Retrieve',  
                                  ugf => 'Upload',  
                                  dgf => 'Delete',  
                               );  
     %{$toolprivs{'roster'}} = (  
                                  vgm => 'View',  
                               );  
     %{$toolprivs{'homepage'}} = (  
                                 vgh => 'View page',  
                                 mgh => 'Modify page',  
                               );  
     my %fixedprivs = ();  
     %{$fixedprivs{'email'}} = ('sgm' => 1);  
     %{$fixedprivs{'discussion'}} = ('vgb' => 1);  
     %{$fixedprivs{'chat'}} = ('pgc' => 1);  
     %{$fixedprivs{'files'}} = ('rgf' => 1);  
     %{$fixedprivs{'roster'}} = ('vgm' => 1);  
     %{$fixedprivs{'homepage'}} = ('vgh' => 1);  
   
     my %elements = ();  
     %{$elements{'create'}} = ();  
     %{$elements{'modify'}} = ();  
     %{$elements{'create'}{'pick_name'}} = (  
         startdate_month => 'selectbox',  
         startdate_hour => 'selectbox',  
         enddate_month => 'selectbox',  
         enddate_hour => 'selectbox',  
         types => 'selectbox',  
         roles => 'selectbox',  
         startdate_day => 'text',  
         startdate_year => 'text',  
         startdate_minute => 'text',  
         startdate_second => 'text',  
         enddate_day => 'text',  
         enddate_year => 'text',  
         enddate_minute => 'text',  
         enddate_second => 'text',  
         groupname => 'text',  
         description => 'text',  
         tool => 'checkbox',  
         granularity => 'radio',  
         no_end_date => 'checkbox',  
     );  
     %{$elements{'create'}{'pick_members'}} = (  
         member => 'checkbox',  
     );  
     if (($action eq 'create') && ($state eq 'pick_name')) {      if (($action eq 'create') && ($state eq 'pick_name')) {
         my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,          $elements{'create'}{'pick_name'}{'types'} = 'selectbox';
                            \%sectioncount);          $elements{'create'}{'pick_name'}{'roles'} = 'selectbox';
         if ($numsections > 0) {      }
             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';      if ((($action eq 'create') &&  
         }          (($state eq 'pick_name') || ($state eq 'pick_privs'))) ||
          (($action eq 'modify') && (($state eq 'change_settings') ||
                                     ($state eq 'add_members')))) {
           %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
           $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
           $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';
           $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';
     }      }
                                                                                         
     if (($action eq 'create') && (($state eq 'pick_members') ||      if (($action eq 'create') || 
                                   ($state eq 'pick_privs'))) {          ($action eq 'modify' && $state eq 'pick_members')) {
         if (defined($env{'form.types'})) {          if (defined($env{'form.types'})) {
             @types=&Apache::loncommon::get_env_multiple('form.types');              @types=&Apache::loncommon::get_env_multiple('form.types');
         }          }
Line 345  sub group_administration { Line 526  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;
             }              }
         }          }
         &build_members_list($cdom,$cnum,\@types,\@roles,      }
                         \@sections,\%users,\%userdata);  
       if (($state eq 'pick_members') || ($state eq 'pick_privs') || ($state eq 'change_privs')) {
           &build_members_list($cdom,$cnum,\@types,\@roles,\@buildsections,\%users,
                               \%userdata);
       }
       if ($state eq 'pick_members') {
         if ((keys(%users) > 0) && (@tools > 0)) {          if ((keys(%users) > 0) && (@tools > 0)) {
               if ($granularity eq 'Yes') {
                   $elements{$action}{'pick_members'}{'togglefunc'} = 'checkbox';
               }
               foreach my $tool (@tools) {
                   if ($granularity eq 'Yes') {
                       $elements{$action}{'pick_members'}{'user_'.$tool} = 'checkbox';
                   }
               }
               $elements{$action}{'pick_members'}{'specificity'} = 'radio';
           }
       }
       if ($state eq 'change_members') {
           my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                  $groupname);
           my $now = time;
           my $num_expire = 0;
           my $num_activate = 0;
           my $num_reenable = 0;
           my $num_deletion = 0;
           my $numusers = 0;
           foreach my $key (sort(keys(%membership))) {
               if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                   my $user = $1;
                   my($end,$start,@userprivs) = split(/:/,$membership{$key});
                   unless ($start == -1) {
                       $numusers ++;
                       $num_deletion ++;
                       if (($end > 0) && ($end < $now)) {
                           $num_reenable ++;
                           next;
                       } elsif (($start > $now)) {
                           $num_activate ++;
                           next;
                       } else {
                           $num_expire ++;
                           next;
                       }
                       next;
                   }
                   if ($num_reenable && $num_activate && $num_expire) {
                       last;
                   }
               }
           }
           if ($num_deletion) {
               $elements{$action}{'change_members'}{'deletion'} = 'checkbox';
           }
           if ($num_expire) {
               $elements{$action}{'change_members'}{'expire'} = 'checkbox';
           }
           if ($num_activate) {
               $elements{$action}{'change_members'}{'activate'} = 'checkbox';
           }
           if ($num_reenable) {
               $elements{$action}{'change_members'}{'reenable'} = 'checkbox';
           }
           if ($numusers) {
               if ($granularity eq 'Yes') {
                   $elements{$action}{'change_members'}{'togglefunc'} = 'checkbox';
               }
             foreach my $tool (@tools) {              foreach my $tool (@tools) {
                 if ($env{'form.granularity'} eq 'Yes') {                  if ($granularity eq 'Yes') {
                     $elements{'create'}{'pick_members'}{'user_'.$tool} = 'checkbox';                      $elements{$action}{'change_members'}{'user_'.$tool} = 'checkbox';
                 }                  }
             }              }
             $elements{'create'}{'pick_members'}{'specificity'} = 'radio';              if ($specificity eq 'Yes') {
                   $elements{$action}{'change_members'}{'changepriv'} = 'checkbox';
               }
         }          }
     }      }
   
     if (($action eq 'create') && (($state eq 'pick_privs') || (($state eq 'result') &&      if (($state eq 'pick_privs') || ($state eq 'change_privs') ||
          ($env{'form.specificity'} eq 'No')))) {           (($specificity eq 'No') && 
             ($state eq 'memresult' || $state eq 'result' || $state eq 'addresult'))) { 
         foreach my $tool (@tools) {          foreach my $tool (@tools) {
             my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool);              my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool);
             foreach my $user (@values) {              foreach my $user (@values) {
                   if ($state eq 'pick_privs' || $state eq 'result' 
                       || $state eq 'addresult') {
                       if (!grep(/^\Q$user\E$/,@members)) {
                           next;
                       }
                   }
                 unless(exists($usertools{$user}{$tool})) {                  unless(exists($usertools{$user}{$tool})) {
                     $usertools{$user}{$tool} = 1;                      $usertools{$user}{$tool} = 1;
                 }                  }
             }              }
         }          }
         if (($state eq 'pick_privs') && ($env{'form.specificity'} eq 'Yes')) {      }
             foreach my $member (@members) {  
                 foreach my $tool (keys(%{$usertools{$member}})) {      if (($action eq 'modify') && (($state eq 'change_privs') || ($state eq 'memresult'))) {
                     foreach my $priv (keys(%{$toolprivs{$tool}})) {          foreach my $chg (@member_changes) {
                         unless (exists($fixedprivs{$tool}{$priv})) {              if (defined($env{'form.'.$chg})) {
                             $elements{'create'}{'pick_privs'}{'userpriv_'.$priv} =                  @{$memchg{$chg}} = &Apache::loncommon::get_env_multiple('form.'.$chg);
                                                                    'checkbox';              }
           }
                                                                                 
           if ($state eq 'change_privs') {
               my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                      $groupname);
               my $now = time;
               foreach my $key (sort(keys(%membership))) {
                   if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                       my $user = $1;
                       my $changefunc = 0;
                       my ($end,$start,@userprivs) = split(/:/,$membership{$key});
                       unless ($start == -1) {
                           if (($end > 0) && ($end < $now)) {
                               unless (grep/^$user$/,$memchg{'reenable'}) {
                                   next;
                               }
                           }
                           my @currtools = ();
                           if (@userprivs > 0) {
                               foreach my $tool (sort(keys(%{$fixedprivs}))) {
                                   foreach my $priv (keys(%{$$fixedprivs{$tool}})) {
                                       if (grep/^$priv$/,@userprivs) {
                                           push(@currtools,$tool);
                                           last;
                                       }
                                   }
                               }
                           }
                           foreach my $tool (@currtools) {
                               if (keys(%{$usertools{$user}}) > 0) {
                                   if (!$usertools{$user}{$tool}) {
                                       push(@{$memchg{'changefunc'}},$user);
                                       $changefunc = 1;
                                       last;
                                   }
                               } else {
                                   push(@{$memchg{'changefunc'}},$user);
                                   $changefunc = 1;
                               }
                           }
                           if ($changefunc) {
                               next;
                           }
                           if (keys(%{$usertools{$user}}) > 0) {
                               foreach my $tool (keys(%{$usertools{$user}})) {
                                   if (!grep/^$tool$/,@currtools) {
                                       push(@{$memchg{'changefunc'}},$user);
                                       $changefunc = 1;
                                       last;
                                   }
                               }
                           }
                       }
                   }
               }
               &check_changes(\@member_changes,\%memchg);
               my %temptools;
               foreach my $change (@member_changes) {
                   if (($change eq 'deletion') || ($change eq 'expire')) {
                       next;
                   }
                   foreach my $user (@{$memchg{$change}}) {
                       unless (exists($usertools{$user})) {
                           %{$usertools{$user}} = ();
                       }
                       %{$temptools{$user}} = %{$usertools{$user}}; 
                   }
               }
               %usertools = %temptools;
           } elsif ($state eq 'memresult') {
               foreach my $change (@member_changes) {
                   if ($change eq 'expire' || $change eq 'deletion') {
                       next;
                   }
                   if (ref($memchg{$change}) eq 'ARRAY') { 
                       my @users = @{$memchg{$change}};
                       foreach my $user (@users) {
                           unless (exists($usertools{$user})) {
                               %{$usertools{$user}} = ();
                         }                          }
                     }                      }
                 }                  }
             }              }
         }          }
     }      }
    
     my $jscript;      if ((($state eq 'pick_privs') || ($state eq 'change_privs'))
     if ($env{'form.action'} eq 'create') {          && ($specificity eq 'Yes')) {
         $jscript = &Apache::loncommon::check_uncheck_jscript();          foreach my $user (sort(keys(%usertools))) {
               foreach my $tool (keys(%{$usertools{$user}})) {
                   foreach my $priv (keys(%{$$toolprivs{$tool}})) {
                       unless (exists($$fixedprivs{$tool}{$priv})) {
                           $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();
     $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) {
     formname.state.value = prevstate;      formname.state.value = prevstate;
     formname.submit();      formname.submit();
 }  }
                                                                                         function changeSort(caller) {
       document.$state.state.value = '$state';
       document.$state.sortby.value = caller;
       document.$state.submit();
   } 
   
 |;  |;
                                                                                         
     $jscript .= &Apache::lonhtmlcommon::set_form_elements(      $jscript .= &Apache::lonhtmlcommon::set_form_elements(
                            \%{$elements{$action}{$state}});                             \%{$elements{$action}{$state}},\%stored);
       my $page = 0;
       my %states = ();
       my %branchstates = ();
       @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
       @{$states{'modify'}} = ('pick_task');
       @{$branchstates{'noprivs'}} = ('result');
       @{$branchstates{'settings'}} = ('change_settings','chgresult');
       @{$branchstates{'members'}} = ('change_members','change_privs','memresult');
       @{$branchstates{'adds'}} = ('add_members','pick_members','pick_privs',
                                   'addresult');
   
       if (defined($env{'form.branch'})) {
           push (@{$states{$action}},@{$branchstates{$env{'form.branch'}}});
       }
   
       if (($action eq 'create') || ($action eq 'modify')) {
           my $done = 0;
           my $i=0;
           while ($i<@{$states{$action}} && !$done) {
               if ($states{$action}[$i] eq $state) {
                   $page = $i;
                   $done = 1;
               }
               $i++;
           }
       }
   
     my $loaditems =  &onload_action($action,$state);      my $loaditems =  &onload_action($action,$state);
     $r->print(&header('Course Groups Manager',&mt('LON-CAPA Groups Manager'),      $r->print(&header("Groups Manager",
                                $jscript,$action,$state,$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 %states = ();  
     @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');  
     @{$states{'modify'}} = ();  
                                                                                         
     my %trail = ();      my %trail = ();
     %{$trail{'create'}} = (      %{$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'}} = ();      %{$trail{'modify'}} = &Apache::lonlocal::texthash(
                                                                                                                     pick_task => 'Choose Task',
                               change_settings => "$ucgpterm Settings",
                               change_members => 'Modify/Delete Members',
                               change_privs => 'Change Privileges',
                               change_mapping => 'Membership Mapping',
                               add_members => 'Add Members',
                               pick_members => 'Select Members',
                               pick_privs => 'Choose Privileges',
                               chgresult => 'Setting Changes Complete',
                               memresult => 'Modifications Complete',
                               addresult => 'Additions Complete',
                             );
       my %navbuttons = &Apache::lonlocal::texthash(
                                gtns => 'Go to next step',
                                gtps => 'Go to previous step',
                                crgr => 'Create '.$gpterm,
                                mose => 'Modify settings',
                                gtpp => 'Go to previous page',
                                adme => 'Add members',
       );
     if ((($action eq 'create') || ($action eq 'modify')) &&      if ((($action eq 'create') || ($action eq 'modify')) &&
               ($manage_permission)) {                ($manage_permission)) {
         for (my $i=0; $i<@{$states{$action}}; $i++) {          for (my $i=0; $i<@{$states{$action}}; $i++) {
Line 441  function backPage(formname,prevstate) { Line 882  function backPage(formname,prevstate) {
                 &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
                      (undef,'Course Groups Manager'));    ("Groups Manager"));
                 &display_control($r,$cdom,$cnum,$tabcol,$action,$state,                  &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,\@members,\%usertools);                         \%users,\%userdata,$idx,\%memchg,\%usertools,
                          $view_permission,$manage_permission,
                          \%stored,$granularity,$quota,$specificity,\@types,\@roles,
                          \@sections,\%states,\%navbuttons,$gpterm,$ucgpterm,
    $crstype);
                 last;                  last;
             } else {              } else {
                 if ($state eq 'result' && $i > 0) {                  if (($state eq 'result') && ($i > 0)) {
                     &Apache::lonhtmlcommon::add_breadcrumb(                      &Apache::lonhtmlcommon::add_breadcrumb(
     {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",      {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",
       text=>"$trail{$action}{$states{$action}[$i]}"});        text=>"$trail{$action}{$states{$action}[$i]}"});
Line 461  function backPage(formname,prevstate) { Line 906  function backPage(formname,prevstate) {
         }          }
     } 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
                      (undef,'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);   $manage_permission,$action,$state,$gpterm,$ucgpterm,
    $crstype);
   
     }      }
     $r->print(&footer());      $r->print(&footer());
     return;      return;
 }  }
   
   sub retrieve_settings {
       my ($cdom,$cnum,$groupname) = @_;
       my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname);
   
       return if (!%curr_groups);
   
       my %groupinfo = 
    &Apache::longroup::get_group_settings($curr_groups{$groupname});
   
       my %stored;
   
       $stored{'description'} = 
    &unescape($groupinfo{'description'});
       $stored{'startdate'} = $groupinfo{'startdate'};
       $stored{'enddate'} = $groupinfo{'enddate'};
       if ($stored{'enddate'} == 0) {
    $stored{'no_end_date'} = 1;
       }
       $stored{'granularity'} = $groupinfo{'granularity'};
       $stored{'specificity'} = $groupinfo{'specificity'};
       $stored{'creation'} = $groupinfo{'creation'};
       $stored{'creator'} = $groupinfo{'creator'};
       $stored{'quota'} = $groupinfo{'quota'};
   
       foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) {
    if ($groupinfo{functions}{$tool} eq 'on') {
       push(@{$stored{tool}},$tool);
    }
       }
       foreach my $role (@{$groupinfo{'roles'}}) {
    push(@{$stored{roles}},$role);
       }
       foreach my $type (@{$groupinfo{'types'}}) {
    push(@{$stored{types}},$type);
       }
       foreach my $section (@{$groupinfo{'sectionpick'}}) {
    push(@{$stored{sectionpick}},$section);
       }
       foreach my $defpriv (@{$groupinfo{'defpriv'}}) {
    push(@{$stored{defpriv}},$defpriv);
       }
       $stored{'autoadd'} = $groupinfo{'autoadd'};
       $stored{'autodrop'} = $groupinfo{'autodrop'};
       if (exists($groupinfo{'autosec'})) {
    foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) {
               if (ref($groupinfo{'autosec'}{$role}) eq 'ARRAY') {
           foreach my $section (@{$groupinfo{'autosec'}{$role}}) {
               push (@{$stored{'sec_'.$role}},$section);
           }
           if (@{$groupinfo{'autosec'}{$role}} > 0) {
       push(@{$stored{'autorole'}},$role);
           }
               }
    }
       }
       return %stored;
   }
   
 sub display_control {  sub display_control {
     my ($r,$cdom,$cnum,$tabcol,$action,$state,$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,$members,$usertools) = @_;          $enddate,$users,$userdata,$idx,$memchg,$usertools,
           $view_permission,$manage_permission,$stored,$granularity,$quota,
           $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') {
             &first_creation_form($r,$cdom,$cnum,$tabcol,$state,$functions,              &general_settings_form($r,$cdom,$cnum,$action,$state,$page,
                                                                 $sectioncount);                                     $functions,$tools,$toolprivs,$fixedprivs,
                                      $sectioncount,$stored,$states,$navbuttons,
                                      $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'pick_members') {          } elsif ($state eq 'pick_members') {
             &second_creation_form($r,$cdom,$cnum,$tabcol,$state,$groupname,              &choose_members_form($r,$cdom,$cnum,$action,$state,$page,
                                   $description,$startdate,$enddate,$tools,                                   $groupname,$description,$granularity,$quota,
                                              $functions,$users,$userdata,$idx);                                   $startdate,$enddate,$tools,$fixedprivs,
                                    $toolprivs,$functions,$users,$userdata,$idx,
                                    $stored,$states,$navbuttons,$gpterm,$ucgpterm,
    $crstype);
         } elsif ($state eq 'pick_privs') {          } elsif ($state eq 'pick_privs') {
             &third_creation_form($r,$cdom,$cnum,$tabcol,$state,$startdate,              &choose_privs_form($r,$cdom,$cnum,$action,$state,$page,
                            $enddate,$tools,$functions,$toolprivs,$fixedprivs,                                 $startdate,$enddate,$tools,$functions,
                                            $userdata,$members,$usertools,$idx);                                 $toolprivs,$fixedprivs,$userdata,$usertools,
                                  $idx,$states,$stored,$sectioncount,$navbuttons,
                                  $gpterm,$ucgpterm,$crstype);
         } elsif ($state eq 'result') {          } elsif ($state eq 'result') {
             &completed_creation($r,$cdom,$cnum,$tabcol,$state,$groupname,              &process_request($r,$cdom,$cnum,$action,$state,$page,
                             $description,$userdata,$startdate,$enddate,$tools,                               $groupname,$description,$specificity,$userdata,
                                $functions,$toolprivs,$members,$usertools,$idx);                               $startdate,$enddate,$tools,$functions,
                                $toolprivs,$usertools,$idx,$types,$roles,
                                $sections,$states,$navbuttons,$memchg,
                                $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
           }
       } elsif ($action eq 'modify') {
           my $groupname = $env{'form.groupname'};
           if ($state eq 'pick_task') {
               &modify_menu($r,$groupname,$page,$gpterm);
           } elsif ($state eq 'change_settings') {
               &general_settings_form($r,$cdom,$cnum,$action,$state,$page,
                                      $functions,$tools,$toolprivs,$fixedprivs,
                                      $sectioncount,$stored,$states,$navbuttons,
                                      $gpterm,$ucgpterm,$crstype);
           } elsif ($state eq 'change_members') {
               &change_members_form($r,$cdom,$cnum,$action,$state,$page,
                                    $groupname,$description,$startdate,$enddate,
                                    $tools,$fixedprivs,$functions,$users,
                                    $userdata,$granularity,$quota,$specificity,
                                    $idx,$states,$navbuttons,$gpterm,$ucgpterm);
           } elsif ($state eq 'add_members') {
               &add_members_form($r,$action,$state,$page,$startdate,
                                 $enddate,$groupname,$description,$granularity,
                                 $quota,$sectioncount,$tools,$functions,$stored,
                                 $states,$navbuttons,$gpterm,$ucgpterm);
           } elsif ($state eq 'pick_members') {
               &choose_members_form($r,$cdom,$cnum,$action,$state,$page,
                                    $groupname,$description,$granularity,$quota,
                                    $startdate,$enddate,$tools,$fixedprivs,
                                    $toolprivs,$functions,$users,$userdata,$idx,
                                    $stored,$states,$navbuttons,$gpterm,$ucgpterm,
    $crstype);
           } elsif ($state eq 'pick_privs') {
               &choose_privs_form($r,$cdom,$cnum,$action,$state,$page,
                                  $startdate,$enddate,$tools,$functions,
                                  $toolprivs,$fixedprivs,$userdata,$usertools,
                                  $idx,$states,$stored,$sectioncount,$navbuttons,
                                  $gpterm,$ucgpterm,$crstype);
           } elsif ($state eq 'change_privs') {
               &change_privs_form($r,$cdom,$cnum,$action,$state,$page,
                                  $startdate,$enddate,$tools,$functions,
                                  $toolprivs,$fixedprivs,$userdata,$usertools,
                                  $memchg,$idx,$states,$stored,$sectioncount,
                                  $navbuttons,$gpterm,$ucgpterm);
           } elsif ($state eq 'chgresult' || $state eq 'memresult' || 
                    $state eq 'addresult') {
               &process_request($r,$cdom,$cnum,$action,$state,$page,
                                $groupname,$description,$specificity,$userdata,
                                $startdate,$enddate,$tools,$functions,
                                $toolprivs,$usertools,$idx,$types,$roles,
                                $sections,$states,$navbuttons,$memchg,
                                $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
         }          }
     }      }
 }  }
   
 sub header {  sub header {
     my ($bodytitle,$title,$jscript,$action,$state,$function,$loaditems) = @_;      my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_;
     my $html=&Apache::lonxml::xmlbegin();      my $start_page=
     my $bodytag=&Apache::loncommon::bodytag($bodytitle,$function,$loaditems);   &Apache::loncommon::start_page($bodytitle,
          '<script type="text/javascript">'.
          $jscript.'</script>',
          {'add_entries' => $loaditems,});
     my $output = <<"END";      my $output = <<"END";
 $html  $start_page
 <head>  <form method="POST" name="$state">
 <title>$title</title>  
 <script type="text/javascript">  
 $jscript  
 </script>  
 </head>  
 $bodytag  
 <form method="post" name="$state">  
   
 END  END
     if ($action eq 'create' || $action eq 'modify') {      if ($action eq 'create' || $action eq 'modify') {
Line 517  END Line 1078  END
  <input type="hidden" name="action" value="$action" />   <input type="hidden" name="action" value="$action" />
  <input type="hidden" name="state" value="" />   <input type="hidden" name="state" value="" />
  <input type="hidden" name="origin" value="$state" />   <input type="hidden" name="origin" value="$state" />
    <input type="hidden" name="page" value="$page" />
 END  END
     }      }
     return $output;      return $output;
Line 524  END Line 1086  END
   
 sub onload_action {  sub onload_action {
     my ($action,$state) = @_;      my ($action,$state) = @_;
     my $loaditems;      my %loaditems;
     if ((defined($env{'form.origin'})) && ($action eq 'create') &&      if ((defined($env{'form.origin'})) && ($action eq 'create') &&
                 ($state eq 'pick_name' || $state eq 'pick_members' ||                   ($state eq 'pick_name' || $state eq 'pick_members' || 
                  $state eq 'pick_privs')) {                   $state eq 'pick_privs')) {
         unless ($env{'form.origin'} eq '') {          unless ($env{'form.origin'} eq '') {
             $loaditems =       $loaditems{'onload'} = 
              'onload="javascript:setFormElements(document.'.$state.')"';   'javascript:setFormElements(document.'.$state.')';
         }          }
     }      }
     return $loaditems;      if (($action eq 'modify') &&
                   ($state eq 'change_settings' || $state eq 'change_members' ||
                    $state eq 'change_privs' || $state eq 'add_members')) {
    $loaditems{'onload'} = 
       'javascript:setFormElements(document.'.$state.')';
       }
       return \%loaditems;
 }  }
   
 sub footer {  sub footer {
       my $end_page = &Apache::loncommon::end_page();
        return(<<ENDFOOT);         return(<<ENDFOOT);
      <input type="hidden" name="sortby" value="$env{'form.sortby'}" />
   </form>    </form>
  </body>  $end_page
 </html>  
 ENDFOOT  ENDFOOT
 }  }
   
Line 554  sub build_members_list { Line 1123  sub build_members_list {
         $access{$type} = $type;          $access{$type} = $type;
     }      }
     &Apache::loncommon::get_course_users($cdom,$cnum,\%access,$roles,      &Apache::loncommon::get_course_users($cdom,$cnum,\%access,$roles,
                                           $sections,$users,$userdata);                                           $sections,$users,$userdata);
     return;      return;
 }  }
   
 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;
 }  }
   
 sub group_members {  sub group_members {
     return;      my ($cdom,$cnum,$group,$group_info) = @_;
       my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);
       my $now = time;
       my ($tmp)=keys(%memberhash);
       if ($tmp=~/^error:/) {
           $$group_info{'totalmembers'} = 'Unknown - an error occurred';
           return $tmp;
       }
       my $totalmembers = 0;
       my $active = 0;
       my $previous = 0;
       my $future = 0;
       foreach my $member (keys %memberhash) {
           $totalmembers ++;
           my ($end,$start) = split(/:/,$memberhash{$member});
           unless ($start == -1) {
               if (($end!=0) && ($end<$now)) {
                   $previous ++;
               } elsif (($start!=0) && ($start>$now)) {
                   $future ++;
               } else {
                  $active ++;
               }
           }
       }
       if ($totalmembers == 0) {
           $$group_info{$group}{'totalmembers'} = 'None';
       } else {
           $$group_info{$group}{'totalmembers'} = '<nobr>'.$active.
               '&nbsp;-&nbsp;active</nobr><br /><nobr>'.$previous.
               '&nbsp;-&nbsp;previous</nobr><br /><nobr>'.$future.
               '&nbsp;-&nbsp;future</nobr>';
       }
       return 'ok';
 }  }
   
   
 sub first_creation_form {  sub general_settings_form {
     my ($r,$cdom,$cnum,$tabcol,$formname,$functions,$sectioncount) = @_;      my ($r,$cdom,$cnum,$action,$formname,$page,$functions,$tools,
           $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
           $gpterm,$ucgpterm,$crstype) = @_;
       my ($nexttext,$prevtext);
       &groupsettings_options($r,$functions,$action,$formname,$stored,1,
                              $gpterm,$ucgpterm,$crstype);
       &access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm);
       if ($action eq 'create') {
           &membership_options($r,$action,$formname,$sectioncount,3,$gpterm,
       $ucgpterm);
           $nexttext = $$navbuttons{'gtns'};
       } else {
           my @available = ();
           my @unavailable = ();
           &check_tools($functions,$tools,\@available,\@unavailable);
           @{$tools} = sort(keys(%{$functions}));
           &privilege_specificity($r,$action,3,$tools,$stored,$toolprivs,
          $fixedprivs,\@available,$formname,
          $gpterm,$ucgpterm);
           &mapping_options($r,$action,$formname,$page,$sectioncount,
                            $states,$stored,$navbuttons,4,5,
    $gpterm,$ucgpterm,$crstype);
           $nexttext = $$navbuttons{'mose'};
       }
       $prevtext = $$navbuttons{'gtpp'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
   sub groupsettings_options {
       my ($r,$functions,$action,$formname,$stored,$image,$gpterm,
           $ucgpterm,$crstype) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         'gmem' => 'Group membership options',          'gdat' => "Group access start and end dates",
         'picr' => 'Pick the criteria to use to build a list of course users '.          'gnde' => "Group name, title and available collaborative tools",
                   'from which you will select members of the new group',             'desc' => 'Group Title',
         'gdat' => 'Group open and close dates',          'func' => 'Collaborative Tools',
         'sten' => 'Set a start date/time and end date/time for the group',          'gnam' => 'Group Name',
         'acty' => 'Access types',          'lett' => 'Letters, numbers and underscore only',
         'coro' => 'Course roles',          'doyo' => 'Different subsets of the chosen collaborative tools '.
         'cose' => 'Course sections',                    'for different group members?',
         'gfun' => 'Group functionality',  
     );      );
       my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored);
     my %status_types = (      &topic_bar($r,$image,$lt{'gnde'});
                    active => &mt('Currently has access'),      $r->print('
                    previous => &mt('Previously had access'),       <table class="LC_descriptive_input">
                    future => &mt('Will have future access'),        <tr>
                    );         <td class="LC_description">'.$lt{'gnam'}.':</td>
          <td colspan="5">
     my @roles = ('st','cc','in','ta','ep','cr');  ');
       if ($action eq 'create') {
     my $starttime = time;          $r->print('<input type="text" name="groupname" size="25" />&nbsp;('.
     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx                    $lt{'lett'}.')');
     my ($start_table,$end_table) = &date_setting_table      } else {
                                     ($starttime,$endtime,$formname);          $r->print('<input type="hidden" name="groupname" value="'.
                            $env{'form.groupname'}.'" />'.$env{'form.groupname'});
     my @sections = ();  
     my $section_sel = '';  
     my $numvisible = 4;  
   
     @sections = sort {$a cmp $b} keys(%{$sectioncount});  
     if (@sections > 0) {  
         unshift(@sections,'_all'); # Put 'all' at the front of the list  
         if (@sections < 4) {  
             $numvisible = @sections;  
         }  
         foreach (@sections) {  
             if ($_ eq '_all') {  
                 $section_sel .= '  <option value="'.$_.'" />all sections'."\n";  
             } else {  
                 $section_sel .= '  <option value="'.$_.'" />'.$_."\n";  
             }  
         }  
     }      }
   
     $r->print(<<"END");      $r->print(<<"END");
  <br />  
  <table width="100%" cellpadding="0" cellspacing="0" border="0">  
    <tr bgcolor="$tabcol">  
      <td>&nbsp;</td>  
      <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step1.gif"   
          valign="bottom">&nbsp;&nbsp;</nobr>  
      </td>  
      <td align="left"><nobr>  
        <font face="arial,helvetica,sans-serif"><b>Group name, description  
          and available functionality</b></font></nobr>   
      </td>  
      <td width="100%">&nbsp;</td>  
    </tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>  
     <td>&nbsp;</td>  
     <td colspan="3">  
      <table border="0" cellpadding="2" cellspacing="2">  
       <tr>  
        <td><b>Group Name:</b></td>  
        <td colspan="5"><input type="text" name="groupname" size="25" />  
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>Description:</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="" />
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>Functionality:</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 653  END Line 1261  END
     if ($remnum) {      if ($remnum) {
         $halfnum ++;          $halfnum ++;
     }      }
     my @allfunctions = sort (keys (%{$functions}));      my @allfunctions = sort(keys (%{$functions}));
     for (my $i=0; $i<$halfnum; $i++) {      for (my $i=0; $i<$halfnum; $i++) {
         $r->print('<td><input type="checkbox" name="tool" value="'.          $r->print('<td><label><input type="checkbox" name="tool" value="'.
                   $allfunctions[$i].'" />&nbsp;'.                    $allfunctions[$i].'" />&nbsp;'.
                    $$functions{$allfunctions[$i]}.'</td>                     $$functions{$allfunctions[$i]}.'</label></td>
                    <td>&nbsp;</td><td>&nbsp;</td>');                     <td>&nbsp;</td><td>&nbsp;</td>');
     }      }
     $r->print('<td><input type="button" value="check all" '.      $r->print('<td><input type="button" value="check all" '.
               'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.                'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.
               '</td></tr><tr><td>&nbsp;</td>');                '</td></tr><tr><td>&nbsp;</td>');
     for (my $j=$halfnum; $j<@allfunctions; $j++) {      for (my $j=$halfnum; $j<@allfunctions; $j++) {
         $r->print('<td><input type="checkbox" name="tool" value="'.          $r->print('<td><label><input type="checkbox" name="tool" value="'.
                   $allfunctions[$j].'" />&nbsp;'.                    $allfunctions[$j].'" />&nbsp;'.
                   $$functions{$allfunctions[$j]}.'</td>                    $$functions{$allfunctions[$j]}.'</label></td>
                   <td>&nbsp;</td><td>&nbsp;</td>');                    <td>&nbsp;</td><td>&nbsp;</td>');
     }      }
     if ($remnum) {      if ($remnum) {
         $r->print('<td>&nbsp;</td>');          $r->print('<td>&nbsp;</td>');
     }      }
     $r->print(<<"END");       $r->print('
        <td>         <td>
         <input type="button" value="uncheck all"           <input type="button" value="uncheck all"
           onclick="javascript:uncheckAll(document.$formname.tool)" />            onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />
        </td>         </td>
       </tr>        </tr>
       <tr>        <tr>
        <td><b>Granularity:</b></td>         <td class="LC_description">'.&mt('Granularity:').'</td>
        <td colspan="9">Do you want to assign different functionality to different group members?&nbsp;<input type="radio" name="granularity" value="Yes" />Yes&nbsp;<input type="radio" name="granularity" value="No" checked="checked" />No</td>         <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>');
       </tr>       if ($action eq 'modify') {
      </table>          $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',
     </td>                                        $$stored{'granularity'}).')');
    </tr>      }
    <tr>      $r->print('
     <td colspan="4">&nbsp;</td>         </td>
    </tr>        </tr>
    <tr bgcolor="$tabcol">  
     <td>&nbsp;</td>  
     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step2.gif"   
         valign="bottom">&nbsp;&nbsp;</nobr>  
     </td>  
     <td align="left"><nobr>  
       <font face="arial,helvetica,sans-serif"><b>Start and end dates for group  
                                                   access</b></font></nobr>  
     </td>  
     <td width="100%">&nbsp;</td>  
    </tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>  
     <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>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr bgcolor="$tabcol">  
     <td>&nbsp;</td>  
     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step3.gif"   
         valign="bottom">&nbsp;&nbsp;</nobr>  
     </td>  
     <td align="left"><nobr>  
      <font face="arial,helvetica,sans-serif"><b>Pick parameters to generate   
          membership list</b></nobr>  
      </font>  
     </td>  
     <td width="100%">&nbsp;</td>  
    </tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>  
     <td>&nbsp;</td>  
     <td colspan="3">  
      <b>$lt{'gmem'}</b><br/> $lt{'picr'}  
      <br /><br />  
      <table border="0">  
       <tr>        <tr>
        <td><b>$lt{'acty'}</b></td>         <td class="LC_description">'.&mt('Disk quota: ').'</td><td colspan="10">');
        <td>&nbsp;</td>      if ($action eq 'create') {
        <td><b>$lt{'coro'}</b></td>          $r->print(&mt('If you enable the file repository for the [_1], allocate a disk quota.',$gpterm));
 END      } else {
     if (@sections >0) {          $r->print(&mt('Quota allocated to file repository:'));
          $r->print('      } 
        <td>&nbsp;</td>      $r->print('&nbsp;<input type="text" name="quota" size="4" />Mb');
        <td><b>'.$lt{'cose'}.'</b></td>      if ($action eq 'create') {
        <td>&nbsp;</td>');          $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>
   ');
       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 {
       my ($r,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm) = @_;
       my $crstype = &Apache::loncommon::course_type();
       my %lt = &Apache::lonlocal::texthash(
                   'pipa' => 'Build a list of users for selection of group members',
                   'gmem' => "Group membership selection list criteria:",
                   'picr' => 'Pick the criteria to use to build a list of '.
                             lc($crstype).' users from which you will select ',
                   'meof' => "members of the new group.",
                   'admg' => "additional members of the group.",
                   'ifno' => "If you do not wish to add members when you first ".
                             "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 user role and section <i>changes</i> in the course.",
                   'acty' => 'Access types',
                   'coro' => $crstype.' roles',
                   'cose' => $crstype.' sections',
                );
       my %status_types = (
                      active => &mt('Currently has access'),
                      previous => &mt('Previously had access'),
                      future => &mt('Will have future access'),
                      );
   
       #FIXME need to plumb around for the various cr roles defined by the user
       my @roles = ('st','cc','in','ta','ep');
   
       my @sections = keys(%{$sectioncount});
   
       &topic_bar($r,$image,$lt{'pipa'});
       $r->print('
        <b>'.$lt{'gmem'}.'</b><br />'.$lt{'picr'});
       if ($action eq 'create') {
           $r->print($lt{'meof'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'});
       } else {
           $r->print($lt{'admg'});
     }      }
     $r->print('</tr><tr>');      $r->print('
        <br />
        <br />
        <table class="LC_status_selector">
         <tr>
          <th>'.$lt{'acty'}.'</th>
          <th>'.$lt{'coro'}.'</th>
          <th>'.$lt{'cose'}.'</th>
         </tr><tr><td>');
     $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));
     if (@sections > 0) {      if (@sections > 0) {
         $r->print('          @sections = sort {$a cmp $b} @sections;
        <td>&nbsp;</td>          unshift(@sections,'none'); # Put 'no sections' next
        <td colspan="3" align="center" valign="top">          unshift(@sections,'all'); # Put 'all' at the front of the list
         <select name="sectionpick" multiple="true" size="'.$numvisible.'">      } else {
           '.$section_sel.'          @sections = ('all','none');
         </select>  
        </td>');  
     }      }
     $r->print('      $r->print('</td><td>'.
                 &sections_selection(\@sections,'sectionpick').'</td>
       </tr>        </tr>
      </table>       </table>');
     </td>  
    </tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>  
     <td>&nbsp;</td>  
     <td colspan="3" align="left">  
      <input type="button" value="Go to next step"    
      onclick="javascript:nextPage(document.'.$formname.','."'pick_members'".')>  
     </td>  
    </tr>  
 </table>  
 ');  
     return;      return;
 }  }
   
 sub second_creation_form {  sub sections_selection {
     my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$startdate,      my ($sections,$elementname) = @_;
                         $enddate,$tools,$functions,$users,$userdata,$idx) = @_;      my $section_sel;
     my @regexps = ('user_','userpriv_');      my $numvisible = 4;
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      if (@{$sections} < 4) {
                 ['origin','action','state','member','specificity'],\@regexps));          $numvisible = @{$sections};
     my %sectioncount = ();      }
     my $numsec = &Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);      foreach my $sec (@{$sections}) {
     my %curr_groups = ();          if ($sec eq 'all') {
     my $numgroups = &Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups);              $section_sel .= '  <option value="'.$sec.'">'.&mt('all sections').'</option>'."\n";
     my $earlyout = '';          } elsif ($sec eq 'none') {
     my $exitmsg = '<b>Invalid group name</b><br /><br />The group name entered "'.              $section_sel .= '  <option value="'.$sec.'">'.&mt('no section').'</option>'."\n"; 
                   $groupname.'" ';          } else {
     my $dupmsg = 'Group names and section names used in a course must be unique.';               $section_sel .= '  <option value="'.$sec.'">'.$sec."</option>\n";
     if ($groupname =~ /\W/) {  
         $earlyout = $exitmsg.'is not a valid name.<br />Group names may only contain letters, numbers or underscores';  
     }  
     if ($numsec) {  
         if (exists($sectioncount{$groupname})) {  
             $earlyout = $exitmsg.'can not be used as it is the name of a section   
                                                 in this course.<br />'.$dupmsg;  
         }  
     }  
     if ($numgroups) {  
         if (exists($curr_groups{$groupname})) {  
             $earlyout = $exitmsg.'can not be used as it is the name of an   
                                  existing group in this course.<br />'.$dupmsg;  
         }          }
     }      }
     if ($earlyout) {      my $output = '
         $r->print('<table border="0" cellpadding="2" cellspacing="2">          <select name="'.$elementname.'" multiple="true" size="'.$numvisible.'">
  <tr>            '.$section_sel.'
   <td>&nbsp;</td>          </select>';
   <td>'.$earlyout.'</td>      return $output;
  </tr>  }
  <tr>  
   <td colspan="2">&nbsp;</td>  sub access_date_settings {
  </tr>      my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_;
  <tr>      my %lt = &Apache::lonlocal::texthash(
   <td>&nbsp;</td>                  'sten' => "Default start and end dates for $gpterm access",
   <td align="left">               );
    <input type="button" name="previous" value = "Go to previous page"      my $starttime = time;
     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>      my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
   </td>      if ($action eq 'modify') {
  </tr>          $starttime = $$stored{'startdate'};
 </table>          unless ($$stored{'enddate'} == 0) {
         ');              $endtime = $$stored{'enddate'};
         return;          }
     }      }
     my $rowColor1 = "#dddddd";      my ($table) = &date_setting_table($starttime,$endtime,$formname);
     my $rowColor2 = "#eeeeee";      &topic_bar($r,$image,$lt{'sten'});
     my $showstart = &Apache::lonlocal::locallocaltime($startdate);  
     my $showend = &Apache::lonlocal::locallocaltime($enddate);  
     $r->print('<table border="0" cellpadding="0" cellspacing="20">  
 <tr>  
  <td><font face="arial,helvetica,sans-serif"><b>New group selections</b></font>  
 <br />When you create the new group, the following settings will apply:  
  </td>  
 </tr>  
 <tr>  
  <td>');  
     $r->print(&Apache::lonhtmlcommon::start_pick_box());  
     $r->print('      $r->print('
 <table cellspacing="1" cellpadding="4">      '.$table.'
  <tr bgcolor="'.$tabcol.'" align="center">      ');
   <td><b>Group Name</b></td>      return;
   <td><b>Description</b></td>  }
   <td><b>Group Functionality</b></td>  
   <td><b>Default access dates</b></td>  sub choose_members_form {
  </tr>      my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description,
  <tr bgcolor="'.$rowColor2.'">          $granularity,$quota,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
   <td valign="top"><small>'.$groupname.'</small></td>          $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
   <td valign="top"><small>'.$description.'</small></td>          $gpterm,$ucgpterm,$crstype) = @_;
   <td>      my @regexps = ('user_','userpriv_','sec_');
 ');      my %origmembers;
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
            ['origin','action','state','page','member','specificity','branch',
             'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'],
            \@regexps));
       my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
                                          $ucgpterm,$crstype);
       if ($earlyout) {
    $r->print($earlyout);
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                              $$navbuttons{'gtps'});
           return;
       } 
       my ($specimg,$memimg);
     my @available = ();      my @available = ();
     my @unavailable = ();      my @unavailable = ();
       &check_tools($functions,$tools,\@available,\@unavailable);
       if ($action eq 'create') {
           &print_current_settings($r,$action,$functions,$startdate,$enddate,
    $groupname,$description,$granularity,$quota,
    \@available,\@unavailable,$gpterm,$ucgpterm);
           $specimg = 4;
           $memimg = 5;
       } else {
           $specimg = 2;
           $memimg = 3;
           my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                  $groupname);
           foreach my $key (sort(keys(%membership))) {
               if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {
                   my ($end,$start,@userprivs) = split(/:/,$membership{$key});
                   unless ($start == -1) {  
                       my $uname = $1;
                       my $udom = $2;
                       my $user = $uname.':'.$udom;
                       $origmembers{$user} = 1; 
                   }
               }
           }
       }
       &privilege_specificity($r,$action,$specimg,$tools,$stored,$toolprivs,
                             $fixedprivs,\@available,$formname,$gpterm,$ucgpterm);
       my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx,
        $stored,$memimg,$users,$userdata,
        $granularity,\%origmembers,$gpterm,
        $ucgpterm);
       if ($newusers || $action eq 'create') {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                               $$navbuttons{'gtps'},$$states{$action}[$page+1],
                               $$navbuttons{'gtns'});
       } else {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                               $$navbuttons{'gtps'});
       }
       return;
   }
   
   sub display_navbuttons {
       my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
       $r->print('<div class="LC_navbuttons">');
       if ($prev) {
           $r->print('
         <input type="button" name="previous" value = "'.$prevtext.'"
       onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
      &nbsp;&nbsp;&nbsp;');
       }
       if ($next) {
           $r->print('
         <input type="button" name="next" value="'.$nexttext.'"
    onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
       }
       $r->print('</div>');
   }
   
   sub check_tools {
       my ($functions,$tools,$available,$unavailable) = @_;
     foreach my $item (sort(keys(%{$functions}))) {      foreach my $item (sort(keys(%{$functions}))) {
         if (grep/^$item$/,@{$tools}) {          if (grep/^$item$/,@{$tools}) {
             push(@available,$item);              push(@{$available},$item);
         } else {          } else {
             push(@unavailable,$item);              push(@{$unavailable},$item);
         }          }
     }      }
     if (@available > 0) {      return;
         $r->print('<small><b>Available:</b></small>  }
                     <table cellpadding="" cellspacing="1"><tr>');  
         my $rowcell = int(@available/2) + @available%2;  sub print_current_settings {
         for (my $i=0; $i<@available; $i++) {      my ($r,$action,$functions,$startdate,$enddate,$groupname,$description,
             if (@available > 3) {   $granularity,$quota,$available,$unavailable,$gpterm,$ucgpterm) = @_;
   
       my %lt = &Apache::lonlocal::texthash(
           grna => 'Group Name',
           desc => 'Group Title',
           grfn => "Collaborative Tools",
           gran => 'Granularity',
           quot => 'File quota',
           dfac => 'Default access dates',
           ygrs => "Your group selections - ",
           tfwa => "The following settings will apply to the group:",
           difn => 'Different collaborative tools<br />for different members:',
           stda => 'Start date',
           enda => 'End date:',
       );
       my $showstart = &Apache::lonlocal::locallocaltime($startdate);
       my $showend;
       if ($enddate == 0) {
           $showend = &mt('No end date set'); 
       } else {
           $showend = &Apache::lonlocal::locallocaltime($enddate);
       }
       if ($action eq 'create') {
           $r->print('
   <div><span style="font-size: larger">'.$lt{'ygrs'}.'</span>
   <br />'.$lt{'tfwa'}.'
   </div>');
       }
       $r->print(&Apache::loncommon::start_data_table('LC_course_group_status').
         &Apache::loncommon::start_data_table_header_row());
       $r->print('
     <th>'.$lt{'grna'}.'</th>
     <th>'.$lt{'desc'}.'</th>
     <th>'.$lt{'grfn'}.'</th>
     <th>'.$lt{'gran'}.'</th>
     <th>'.$lt{'quot'}.'</th>
     <th>'.$lt{'dfac'}.'</th>
   ');
       $r->print(&Apache::loncommon::end_data_table_header_row().
         &Apache::loncommon::start_data_table_row('LC_data_table_dense'));
       $r->print('
     <td valign="top">'.$groupname.'</td>
     <td valign="top">'.$description.'</td>
     <td>
   ');
       if (@{$available} > 0) {
           $r->print(&mt('<b>Available for assignment to members:</b>').
                       '<table class="LC_group_priv"><tr>');
           my $rowcell = int(@{$available}/2) + @{$available}%2;
           for (my $i=0; $i<@{$available}; $i++) {
               if (@{$available} > 3) {
                 if ($i==$rowcell) {                  if ($i==$rowcell) {
                     $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>');
         }          }
         $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) {
                 if ($j==$rowcell) {                  if ($j==$rowcell) {
                     $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>');
         }          }
         $r->print('</tr></table>');          $r->print('</tr></table>');
     }      }
     $r->print(<<"END");      $r->print(<<"END");
   </td>    </td>
   <td valign="top"><small><b>Start date:</b> $showstart<br />    <td valign="top"><b>$lt{'difn'}</b> $granularity</td>
       <b>End date:</b> $showend</small>    <td valign="top">$quota Mb</td> 
     <td valign="top"><b>$lt{'stda'}</b> $showstart<br />
         <b>$lt{'enda'}</b> $showend
   </td>    </td>
  </tr>  
 </table>  
 END  END
     $r->print(&Apache::lonhtmlcommon::end_pick_box());      $r->print(&Apache::loncommon::end_data_table_row().
     my %members = ();        &Apache::loncommon::end_data_table());
       return;
   }
   
   sub pick_new_members {
       my ($r,$action,$formname,$available,$idx,$stored,$img,$users,$userdata,
    $granularity,$origmembers,$gpterm,$ucgpterm) = @_;
       my %lt = &Apache::lonlocal::texthash(
             'gpme' => "Group membership",
             'addm' => 'Add members',
             'setf' => 'Assign collaborative tools', 
             'func' => 'Tools',
             'nome' => 'No members to add at this time, as there are no users '.
                        'matching the specified type(s), role(s) and section(s).',
             'nnew' => "There are no users to add as new members, as all users".
                       " 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 '.
                        'future members'."'".' page if you need to re-enable '.
                        'or activate access for previous or future members.',
       );
       my %members;
       my $totalusers = 0;
       my $newusers = 0;
     foreach my $role (keys(%{$users})) {      foreach my $role (keys(%{$users})) {
         foreach my $user (keys(%{$$users{$role}})) {          foreach my $user (keys(%{$$users{$role}})) {
               $totalusers ++;
               if (ref($origmembers) eq 'HASH') {
                   if (exists($$origmembers{$user})) {
                       next;
                   }
               }    
             unless (defined($members{$user})) {              unless (defined($members{$user})) {
                 @{$members{$user}} = @{$$userdata{$user}};                  @{$members{$user}} = @{$$userdata{$user}};
                   $newusers ++;
             }              }
         }          }
     }      }
     $r->print('</td></tr></table><br />');  
     if (keys(%members) > 0) {      if (keys(%members) > 0) {
         if ($env{'form.granularity'} eq 'Yes') {          if (@{$available} > 0 && $granularity eq 'Yes') {
             $r->print('              $r->print(&check_uncheck_tools($r,$available));
 <script type="text/javascript">          }
 function checkAllTools(formname) {      }
 ');      &topic_bar($r,$img,$lt{'gpme'});
             foreach my $tool (@available) {      if (keys(%members) > 0) {
                 $r->print('  checkAll(formname.user_'.$tool.');'."\n");          $r->print('
             }  
             $r->print('  
 }  
 function uncheckAllTools(formname) {  
 ');  
             foreach my $tool (@available) {  
                 $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");  
             }  
             $r->print('  
 }  
 </script>  
             ');  
        }  
        $r->print(<<"END");  
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  
  <tr bgcolor="$tabcol">  
   <td>&nbsp;</td>  
   <td valign="top" align="left">  
    <nobr><img src="/res/adm/pages/bl_step4.gif" valign="middle">&nbsp;</nobr>  
   </td>  
   <td alin="left">  
    <nobr>  
    <font face="arial,helvetica,sans-serif">  
     <b>Select group members</b>  
    </font></nobr>  
   </td>  
   <td width="100%">&nbsp;</td>  
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
  <tr>  
   <td>&nbsp;</td>  
   <td colspan="2">  
     <table>      <table>
      <tr>       <tr>');
       <td>          &check_uncheck_buttons($r,$formname,'member',$lt{'addm'});
    <nobr>          if (@{$available} > 0 && $granularity eq 'Yes') {
     <fieldset><legend><b>Add members</b></legend>              $r->print('<td>
      <input type="button" value="check all"        <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>
        onclick="javascript:checkAll(document.$formname.member)" />        <nobr>
       &nbsp;&nbsp;        <input type="button" value="check all"
      <input type="button" value="uncheck all"           onclick="javascript:checkAllTools(document.'.$formname.')" />
       onclick="javascript:uncheckAll(document.$formname.member)" />          &nbsp;&nbsp;
     </fieldset></nobr></td>        <input type="button" value="uncheck all"
 END  
         if (@available > 0 && $env{'form.granularity'} eq 'Yes') {  
             $r->print('<td><nobr><fieldset><legend><b>   
                                       Set functionality</b></legend>  
      <input type="button" value="check all"   
        onclick="javascript:checkAllTools(document.'.$formname.')" />  
        &nbsp;&nbsp;  
      <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>  
   <td width="100%">&nbsp;</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().
         $r->print(<<"END");    &Apache::loncommon::start_data_table_header_row());
    <table border="0" cellpadding="4" cellspacing="1">          $r->print('
     <tr bgcolor="$tabcol" align="center">       <th>'.&mt('Add?').'</b></td>
      <td><b>Add?</b></td>       <th><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></td>
      <td><b><a href="javascript:changeSort('fullname')">Name</a></b></td>       <th><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></td>
      <td><b><a href="javascript:changeSort('username')">Username</a></b>       <th><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></td>
      </td>       <th><a href="javascript:changeSort('."'id'".')">'.&mt('ID').'</a></td>
      <td><b><a href="javascript:changeSort('domain')">Domain</a></b></td>       <th><a href="javascript:changeSort('."'section'".')">'.&mt('Section').'</a></td>
      <td><b><a href="javascript:changeSort('id')">ID</a></b></td>  ');
 END          if (@{$available} > 0) {
         if (@available > 0) {              $r->print('<th>'.$lt{'func'}.'</th>');
             $r->print('<td><b>Functionality</b></td>');          }
           $r->print(&Apache::loncommon::end_data_table_header_row());
           if (@{$available} > 0) {
               if ($granularity eq 'Yes') {
                   $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').'
    <td colspan="6">&nbsp;</td>
    <td align="center"><nobr><b>'.&mt('All:').'</b>&nbsp;');
                   foreach my $tool (@{$available}) {
                       $r->print('<label><input type="checkbox" name="togglefunc" '.
      'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
      ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
                   }
                   $r->print('</nobr></td></tr>');
               }
         }          }
         $r->print('</tr>');  
         my %Sortby = ();          my %Sortby = ();
         foreach my $user (sort(keys(%members))) {          foreach my $user (sort(keys(%members))) {
             if ($env{'form.sortby'} eq 'fullname') {              if ($env{'form.sortby'} eq 'fullname') {
Line 1019  END Line 1731  END
                 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>'.
                 if (@available > 0) {    '<td>'.$uname.'</td>'.
                     $r->print('<td align="center"><small>');     '<td>'.$udom.'</td>'.
                     foreach my $tool (@available) {    '<td>'.$id.'</td>'.
                         if ($env{'form.granularity'} eq 'Yes') {    '<td>'.$section.'</td>');
                   if (@{$available} > 0) {
                       $r->print('<td align="center"><nobr>'.
                                 '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                       foreach my $tool (@{$available}) {
                           if ($granularity eq 'Yes') {
                             $r->print('<input type="checkbox" name="user_'.                              $r->print('<input type="checkbox" name="user_'.
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');                            $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         } else {                          } else {
Line 1051  END Line 1763  END
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');                            $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         }                          }
                     }                      }
                     $r->print('</small></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('      } else {
   </td>          if ($totalusers > 0) {
  </tr>              $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});
  <tr>          } else { 
   <td colspan="4">&nbsp;</td>              $r->print($lt{'nome'});
  </tr>');          }
         if (@available > 0) {      }
       return $newusers;
   }
   
   sub privilege_specificity {
       my ($r,$action,$img,$tools,$stored,$toolprivs,$fixedprivs,$available,
    $formname,$gpterm,$ucgpterm) = @_;
       my %lt = &Apache::lonlocal::texthash (
         'uprv' => 'User privileges for collaborative tools',
         'frty' => 'For each collaborative tool you have chosen to include, '.
                   'there is a set of core privileges which all group members '.
                   'assigned use of the tool will receive.',
         'thar' => 'For some tools there are also additional optional '.
                    'privileges which can be set.',
         'plch' => 'Choose one of the following:',
         'fort' => 'For the collaborative tools you have chosen to include '.
                   'only core privileges are available, '.
                   'so there are no optional privileges to assign.',
         'eaty' => 'Each collaborative tool includes core '.
                   'privileges assigned to all members with access to the '.
                   'tool. Some tools may also feature additional privileges '.
                   'which can be set for specific members.',
         'cutg' => 'Currently the group is configured ',
         'sdif' => 'so different members can receive different optional privileges for a particular tool.',
         'sall' => 'so all members will receive the same optional privileges for a particular tool.',
         'algm' => 'All group members will receive the same privileges for any tool assigned to them, including the default set of optional privileges.',
         'smgp' => 'Different group members may receive different privileges from '.
                   'others for the tools they have been assigned.',
         'thwi' => 'These will be the privileges all group members receive for a particular assigned tool, '. 
                   'if you selected the first option above.',
         'thes' => "These will be the privileges given to members assigned ".   
                   "in the future via automatic group assignment ".
                   "for users who receive specific sections/roles in the course ",
         'asyo' => "As you have chosen not to include any collaborative tools ".
                   "in the group, no default optional privileges need to be set.",
         'plin' => 'Indicate which <b>optional</b> privileges members '.
                   'will receive by default for a specific tool.',
         'oppr' => 'Optional privileges',
         'defp' => 'The default privileges new members will receive are:', 
       );
       my $totaloptionalprivs = 0;
       foreach my $tool (@{$tools}) {
           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (!exists($$fixedprivs{$tool}{$priv})) {
                   $totaloptionalprivs ++;
               }
           }
       }
       &topic_bar($r,$img,$lt{'uprv'});
       if ((($action eq 'create') && (@{$available} > 0)) || 
           (($action eq 'modify') && ($formname eq 'change_settings'))) {
           my %specific = (
                         'No'  => 'checked="checked"',
                         'Yes' => '',
                     );
           if ($action eq 'create') {
               $r->print($lt{'frty'}.'<br />');
               if ($totaloptionalprivs) {
                   $r->print($lt{'thar'}.'<br /><br />'.$lt{'plch'});
               } else {
                   $r->print($lt{'fort'});
               }
           } else {
               $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
               if ($$stored{'specificity'} eq 'Yes') {
                   $r->print($lt{'sdif'});
                   $specific{'Yes'} = $specific{'No'};
                   $specific{'No'} = '';
               } else {
                   $r->print($lt{'sall'});
               }
           }
           if ($totaloptionalprivs) {
             $r->print('              $r->print('
  <tr bgcolor="'.$tabcol.'">  <br />
   <td>&nbsp;</td>  <label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr></label><br />
   <td valign="middle" align="left">  <label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr></label><br /><br />');
    <nobr><img src="/res/adm/pages/bl_step5.gif" valign="middle">&nbsp;</nobr>          } else {
   </td>              $r->print('<input type="hidden" name="specificity" value="No" />');
   <td align="left"><nobr>          }
    <font face="arial,helvetica,sans-serif">          if ($totaloptionalprivs) {
     <b>User privileges</b>              $r->print($lt{'plin'});
    </font></nobr>              if ($action eq 'create') {
   </td>                  $r->print('<br />'.$lt{'thwi'});
   <td width="100%">&nbsp;</td>              }
  </tr>              $r->print('<br />'.$lt{'thes'});
  <tr>              if ($action eq 'create') {
   <td>&nbsp;</td>                  $r->print('('.&mt('if enabled on the next page').').');
   <td colspan="3">              } else {
                   $r->print('('.&mt('if enabled below').').');
               }
               $r->print('<br /><br />
     <table><tr>');
           &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});
           $r->print('
       </tr>
      </table>
    <br />     <br />
    For each type of functionality you have chosen to include, there is a   
 set of standard privileges which apply to all of those for whom the functionality is enabled.<br />There are also additional privileges which can be set for some, or all, members. Please choose one of the following:<br />  
 <br /><input type="radio" name="specificity" value="No" checked="checked" />&nbsp;All group members will receive the same privileges.<br/><input type="radio" name="specificity" value="Yes" />&nbsp;Some group members will receive different privileges from others.  
   </td>  
  </tr>  
  <tr>  
   <td colspan="4">&nbsp;</td>  
  </tr>  
 ');  ');
           } else {
               $r->print($lt{'algm'}.'<br /><br />');
         }          }
         $r->print('              &default_privileges($r,$action,$tools,$toolprivs,$fixedprivs,
  <tr>      $available);
   <td>&nbsp;</td>  
   <td colspan="3">  
    <input type="button" name="previous" value = "Go to previous page"   
     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>  
    &nbsp;&nbsp;&nbsp;  
    <input type="button" name="next" value="Go to next page"   
  onclick="javascript:nextPage(document.'.$formname.','."'pick_privs'".')" />  
   </td>  
  </tr>  
         ');  
     } else {      } else {
         $r->print('No members to add');          if ($action eq 'create') {
               $r->print($lt{'asyo'});
               $r->print('<input type="hidden" name="specificity" value="No" />');
           } elsif ($action eq 'modify' && $formname eq 'pick_members') {
               my @defprivs;
               if (ref($$stored{'defpriv'}) eq 'ARRAY') {
                   @defprivs = @{$$stored{'defpriv'}};
               }
               $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
               if ($$stored{'specificity'} eq 'Yes') {
                   $r->print($lt{'sdif'});
               } else {
                   $r->print($lt{'sall'});
               }
               $r->print(' '.$lt{'defp'}.'<br /><br />');
               &display_defprivs($r,$tools,$toolprivs,\@defprivs);
           }
     }      }
     $r->print('  
    </table>  
   </td>  
  </tr>  
 </table>');  
     return;      return;
 }  }
   
 sub third_creation_form {  sub default_privileges {
     my ($r,$cdom,$cnum,$tabcol,$formname,$startdate,$enddate,$tools,$functions,      my ($r,$action,$tools,$toolprivs,$fixedprivs,$available) = @_;
                $toolprivs,$fixedprivs,$userdata,$members,$usertools,$idx) = @_;      my %lt = &Apache::lonlocal::texthash(
     my @regexps = ('userpriv_','allpriv_');                                  'addp' => 'Additional privileges',
     $r->print(&Apache::lonhtmlcommon::echo_form_input(                                  'fixp' => 'Fixed privileges',
                              ['origin','action','state'],\@regexps));                                  'oppr' => 'Optional privileges',
     my %possibles = ();                                  'func' => 'Collaborative Tool',
     my %showboxes = ();      );
     my $totalboxes = 0;      $r->print(&Apache::lonhtmlcommon::start_pick_box('LC_group_priv_box').
         &Apache::lonhtmlcommon::row_title($lt{'func'},undef,
    'LC_groups_functionality'));
       $r->print(join('</td><td class="LC_groups_functionality">',@{$tools}));
       $r->print(&Apache::lonhtmlcommon::row_closure(1));
       my $fixed = '';
       my $dynamic = '';
       foreach my $tool (@{$tools}) {
           my $privcount = 0;
    if ($dynamic ne '') {
       $dynamic .= '</td><td class="LC_groups_optional">';
    }
    $dynamic .= '<table class="LC_group_priv"><tr>';
           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (exists($$fixedprivs{$tool}{$priv})) {
    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 (grep(/^$tool$/,@{$available})) {
                           $fixed .= '<small>'.&mt('(on)').'<small>&nbsp;';
                       } else {
                           $fixed .= '<small>'.&mt('(off)').'<small>&nbsp;';
                       }
                   }
                   $fixed .= '</nobr>';
               } else {
                   $privcount++;
                   if ($privcount == 3) {
                       $dynamic .= '</tr>
                                    <tr>'."\n";
                   }
                   $dynamic .= '<td><nobr><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></nobr></td>'."\n";
               }
           }
           if ($privcount == 0) {
               $dynamic .= '<td>None</td>'."\n";
           }
           if ($privcount < 3) {
               $dynamic .= '<td>&nbsp;</td>'."\n";
           } elsif ($privcount%2) {
               $dynamic = '<td>&nbsp;</td>'."\n";
           }
    $dynamic .= '</tr></table>';
       }
       $r->print(&Apache::lonhtmlcommon::row_title($lt{'fixp'},undef,
    '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 />');
       return;
   
   }
   
   sub display_defprivs {
       my ($r,$tools,$toolprivs,$defprivs) = @_;
       my $function = &Apache::loncommon::get_users_function();
       my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
     my $rowColor1 = "#dddddd";      my $rowColor1 = "#dddddd";
     my $rowColor2 = "#eeeeee";      my $rowColor2 = "#eeeeee";
     my $numtools = 1 + @{$tools};      my %lt = &Apache::lonlocal::texthash(
                                   'priv' => 'Privileges',
                                   'func' => 'Collaborative Tool',
       );
       $r->print(&Apache::lonhtmlcommon::start_pick_box());
       $r->print('<tr>');
       my $numrows = 0;
       my %currprivs;
     foreach my $tool (@{$tools}) {      foreach my $tool (@{$tools}) {
         @{$showboxes{$tool}} = ();          @{$currprivs{$tool}} = ();
         foreach my $user (@{$members}) {          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
             if (exists($$usertools{$user}{$tool})) {              if (ref($defprivs) eq 'ARRAY') {
                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {                  if (grep(/^\Q$priv\E$/,@{$defprivs})) {
                     unless (exists($$fixedprivs{$tool}{$priv})) {                      push(@{$currprivs{$tool}},$priv);
                         push(@{$possibles{$user}},$priv);                  }
                         unless(grep(/^$priv$/,@{$showboxes{$tool}})) {              }
                             push(@{$showboxes{$tool}},$priv);          }
                             $totalboxes ++;          my $rowcount = int(@{$currprivs{$tool}}/3);
           if (@{$currprivs{$tool}}%3 > 0) {
               $rowcount ++;
           }
           if ($rowcount > $numrows) {
               $numrows = $rowcount;
           }
       }
       my @rowCols = ($rowColor1,$rowColor2);
       foreach my $tool (@{$tools}) {
           $r->print('<td align="center" valign="top">
                       <table cellspacing="0" cellpadding="5">
                        <tr bgcolor="#cccccc">
                         <td colspan="3" align="center"><b>'.$tool.'</b></td>
                        </tr>
           ');
           my $rownum = 1;
           my $privcount = 0;
           $r->print('<tr bgcolor="'.$rowColor1.'">');
           foreach my $priv (@{$currprivs{$tool}}) {
               $privcount ++;
               if ($privcount%4 == 0) {
                   $rownum ++;
                   my $bgcol = $rownum%2; 
                   $r->print('</tr>
                                <tr bgcolor="'.$rowCols[$bgcol].'">'."\n");
               }
               $r->print('<td>'.$$toolprivs{$tool}{$priv}.'</td>'."\n");
           }
           if ($privcount%3 > 0) {
               my $emptycells = 3-($privcount%3);
               while($emptycells > 0) {
                   $r->print('<td>&nbsp;</td>'."\n");
                   $emptycells --;
               }
           }
           while ($rownum < $numrows) {
               $rownum ++;
               my $bgcol = $rownum%2;
               $r->print('<tr bgcolor="'.$rowCols[$bgcol].'"><td colspan="3">&nbsp;</td></tr>');
           }
           $r->print('</table>'."\n".'</td>');
       }
       $r->print('</tr>'."\n");
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
       $r->print('<br />');
       return;
   }
   
   
   sub change_members_form {
       my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description,
           $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,
           $granularity,$quota,$specificity,$idx,$states,$navbuttons,$gpterm,
    $ucgpterm) = @_;
       my %lt = &Apache::lonlocal::texthash(
                                            grse => "$ucgpterm settings",
                                            mogm => "Modify $gpterm membership",
                                           );
       my @regexps = ('user_','userpriv_');
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
                            ['origin','action','state','page','expire','deletion',
                             'reenable','activate','changepriv','sortby',
                             'togglefunc'],\@regexps));
       my $rowimg = 1;
       my @available = ();
       my @unavailable = ();
       &check_tools($functions,$tools,\@available,\@unavailable);
       my $nexttext = $$navbuttons{'gtns'};
       my $prevtext = $$navbuttons{'gtpp'};
       $r->print('
   <br />
   ');
       &topic_bar($r,1,$lt{'grse'});
       &print_current_settings($r,$action,$functions,$startdate,$enddate,
       $groupname,$description,$granularity,$quota,
       \@available,\@unavailable,$gpterm,$ucgpterm);
       &topic_bar($r,2,$lt{'mogm'});
       my $numcurrent = &current_membership($r,$cdom,$cnum,$formname,$groupname,
                                            \@available,\@unavailable,$fixedprivs,
                    $granularity,$specificity);
       if ($numcurrent > 0) {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                               $$states{$action}[$page+1],$nexttext);
       } else {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);
       }
       return;
   }
   
   sub current_membership {
       my ($r,$cdom,$cnum,$formname,$groupname,$available,$unavailable,
    $fixedprivs,$granularity,$specificity) = @_;
       my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                      $groupname);
       my %lt = &Apache::lonlocal::texthash(
                                             'actn' => 'Action?',
                                             'name' => 'Name',
                                             'usnm' => 'Username',
                                             'doma' => 'Domain',
                                             'stda' => 'Start Date',
                                             'enda' => 'End Date',
                                             'expi' => 'Expire',
                                             'reen' => 'Re-enable',
                                             'acti' => 'Activate',
                                             'dele' => 'Delete',
                                             'curf' => 'Current Tool Set',
                                             'chpr' => 'Change Privileges' 
                                           );
       my ($current,$num_items,$hastools,$addtools) =
           &Apache::longroup::group_memberlist($cdom,$cnum,$groupname,$fixedprivs,
                                               $available);
       my $numcurrent = scalar(keys(%{$current}));
       if ($numcurrent > 0) {
           $r->print('
      <table>
       <tr>');
           if ($num_items->{'active'}) {
               &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});
           }
           if ($num_items->{'previous'}) {
               &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});
           }
           if ($num_items->{'future'}) {
               &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'});
               }
               if ($granularity eq 'Yes') {
                   $r->print(&check_uncheck_tools($r,$available));
                   $r->print('
        <td>
         <nobr>
          <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>
          <input type="button" value="check all"
          onclick="javascript:checkAllTools(document.'.$formname.')" />
          &nbsp;&nbsp;
          <input type="button" value="uncheck all"
           onclick="javascript:uncheckAllTools(document.'.$formname.')" />
         </fieldset>
        </nobr>
       </td>
   ');
               }
           }
           $r->print(<<"END");
      </tr>
     </table>
     <br />
   END
           $r->print(&Apache::loncommon::start_data_table().
     &Apache::loncommon::start_data_table_header_row());
           $r->print(<<"END");
        <th>$lt{'actn'}</th>
        <th><a href="javascript:changeSort('fullname')">$lt{'name'}</a></th>
        <th><a href="javascript:changeSort('username')">$lt{'usnm'}</a></th>
        <th><a href="javascript:changeSort('domain')">$lt{'doma'}</a></th>
        <th><a href="javascript:changeSort('id')">ID</a></th>
        <th><a href="javascript:changeSort('start')">$lt{'stda'}</a></th>
        <th><a href="javascript:changeSort('end')">$lt{'enda'}</a></th>
   END
           my $colspan = 0;
           if ($hastools) {
               $r->print('<th>'.$lt{'curf'}.'</th>');
               $colspan++;  
           }
           if ($addtools) {
               $r->print('<th>'.&mt('Additional Tools').'</th>');
               $colspan++;
           }
           $r->print(&Apache::loncommon::end_data_table_header_row());
           if ($colspan) {
               if ($granularity eq 'Yes') {
                   $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').'
    <td colspan="7">&nbsp;</td>
    <td colspan="'.$colspan.'" align="center"><nobr><b>'.&mt('All:').
     '</b>&nbsp;');
                   foreach my $tool (@{$available}) {
                       $r->print('<label><input type="checkbox" name="togglefunc"'.
      ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
      ' value="'.$tool.'" />'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
                   }
                   $r->print('</nobr></td></tr>');
               }
           }
           my %Sortby = ();
           foreach my $user (sort(keys(%{$current}))) {
               if ($env{'form.sortby'} eq 'fullname') {
                   push(@{$Sortby{$$current{$user}{fullname}}},$user);
               } elsif ($env{'form.sortby'} eq 'username') {
                   push(@{$Sortby{$$current{$user}{uname}}},$user);
               } elsif ($env{'form.sortby'} eq 'domain') {
                   push(@{$Sortby{$$current{$user}{udom}}},$user);
               } elsif ($env{'form.sortby'} eq 'id') {
                   push(@{$Sortby{$$current{$user}{id}}},$user);
               } else {
                   push(@{$Sortby{$$current{$user}{fullname}}},$user);
               }
           }
           foreach my $key (sort(keys(%Sortby))) {
               foreach my $user (@{$Sortby{$key}}) {
                   my $id = $$current{$user}{id};
                   my $fullname = $$current{$user}{fullname};
                   my $udom = $$current{$user}{udom};
                   my $uname = $$current{$user}{uname};
                   my $start = $$current{$user}{start};
                   my $end = $$current{$user}{end};
                   $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').'
                               <td>');
                   if ($$current{$user}{changestate} eq 'reenable') {
                       $r->print('<nobr><label>'. 
      '<input type="checkbox" name="reenable" value="'.$user.'" />'.
      $lt{'reen'}.'</label></nobr><br />');
                   } elsif ($$current{$user}{changestate} eq 'expire') {
                       $r->print('<nobr><label>'.
      '<input type="checkbox" name="expire" value="'.$user.'" />'.
      $lt{'expi'}.'</label></nobr><br />');
                   } elsif ($$current{$user}{changestate} eq 'activate') {
                       $r->print('<nobr><label>'.
      '<input type="checkbox" name="activate" value="'.$user.'" />'.
      $lt{'acti'}.'</label></nobr><br />');
                   }
                   $r->print('<nobr><label>'.
      '<input type="checkbox" name="deletion" value="'.$user.'" />'.
      $lt{'dele'}.'</label></nobr>');
                   if ($specificity eq 'Yes') {
                       $r->print('<br /><nobr><label>'.
      '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
      '</label></nobr>');
                   }
                   $r->print('
      </td>'.
      '<td>'.$fullname.'</td>'.
      '<td>'.$uname.'</td>'.
      '<td>'. $udom.'</td>'.
      '<td>'.$id.'</td>'.
      '<td>'.$start.'</td>'.
      '<td>'.$end.'</td>');
                   if ($hastools) {
                       $r->print('<td align="left"><nobr>'.
                                     '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                       foreach my $tool (@{$$current{$user}{currtools}}) {
                           if ($granularity eq 'Yes') {
                               $r->print('<label><input type="checkbox" '. 
                                          'checked="checked" '. 
                                          'name="user_'.$tool.'" value="'.
                                          $user.'" />'.$tool.'</label>');
                            } else {
                                $r->print('<input type="hidden" '.
                                          'checked="checked" '.
                                          'name="user_'.$tool.'" value="'.
                                          $user.'" />'.$tool);
                            }
                            $r->print('&nbsp;&nbsp;&nbsp;');
                       }
                       $r->print('</nobr></td>');
                   }
                   if ($addtools) {
                       $r->print('<td align="left">');
                       if ($granularity eq 'Yes') {
                           foreach my $tool (@{$$current{$user}{newtools}}) {
                               $r->print('<nobr><label><input type="checkbox"
                                             name="user_'.$tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</label></nobr>&nbsp;&nbsp;&nbsp;');
                           }
                       } else {
                           foreach my $tool (@{$$current{$user}{newtools}}) {
                               $r->print('<nobr><input type="hidden" 
                                             name="user_'. $tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</nobr>&nbsp;&nbsp;&nbsp;');
                         }                          }
                     }                      }
                       $r->print('</td>');
                 }                  }
                   $r->print(&Apache::loncommon::end_data_table_row()."\n");
             }              }
         }          }
           $r->print(&Apache::loncommon::end_data_table());
       } else {
           $r->print(&mt('There are no active, future or previous group members to modify.'));
     }      }
     if ($totalboxes > 0) {      return $numcurrent;
         $r->print('  }
   
   sub check_uncheck_buttons {
       my ($r,$formname,$field,$title,$colspan) = @_;
       $r->print('
        <td '.$colspan.'>
          <fieldset>
          <legend><b>'.$title.'</b></legend>
         <nobr>
          <input type="button" value="check all"
          onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
          &nbsp;&nbsp;
          <input type="button" value="uncheck all"
          onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
         </nobr>
          </fieldset>
        </td>
   ');
   }
   
   
   sub change_privs_form {
       my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
    $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,
    $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$gpterm,
    $ucgpterm) = @_;
       my @regexps = ('userpriv_');
       my $nexttext;
       my %lt = &Apache::lonlocal::texthash(
                  'tode' => 'To be deleted',
                  'toex' => 'To be expired',
                  'nome' => "No members to be deleted or expired from the $gpterm.",
       );
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
            ['origin','action','state','page','sortby'],\@regexps));
       if ($env{'form.branch'} eq 'adds') {
           $nexttext = $$navbuttons{'adme'};
       } else {
           $nexttext = $$navbuttons{'mose'};
       }
       &topic_bar($r,3,&mt('Members to delete or expire'));
       my $exp_or_del = 0;
       if (ref($$memchg{'deletion'}) eq 'ARRAY') {
           if (@{$$memchg{'deletion'}} > 0) {
               $r->print('<b>'.$lt{'tode'}.':</b><br /><ul>');
               foreach my $user (@{$$memchg{'deletion'}}) {
                   $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                             '&nbsp;('.$user.')</li>');
               }
               $r->print('</ul>');
               $exp_or_del += @{$$memchg{'deletion'}};
           }
       }
       if (ref($$memchg{'expire'}) eq 'ARRAY') {
           if (@{$$memchg{'expire'}} > 0) {
               $r->print('<b>'.$lt{'toex'}.':</b><br /><ul>');
               foreach my $user (@{$$memchg{'expire'}}) {
                   $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                             '&nbsp;('.$user.')</li>');
               }
               $r->print('</ul>');
               $exp_or_del += @{$$memchg{'expire'}};
           }
       }
       if (!$exp_or_del) {
           $r->print($lt{'nome'}.'<br />');
       }
       
       &topic_bar($r,4,&mt('Setting optional privileges for specific group members'));
   
       my $numchgs = &member_privileges_form($r,$action,$formname,$tools,
                                             $toolprivs,$fixedprivs,$userdata,
                                             $usertools,$idx,$memchg,$states,
                                             $stored,$gpterm);
       my $prevtext = $$navbuttons{'gtps'};
       if ($numchgs || $exp_or_del) {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                               $$states{$action}[$page+1],$nexttext);
       } else {
           &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);
       }
       return;
   }
   
   sub add_members_form {
       my ($r,$action,$formname,$page,$startdate,$enddate,$groupname,
           $description,$granularity,$quota,$sectioncount,$tools,$functions,
           $stored,$states,$navbuttons,$gpterm,$ucgpterm)=@_; 
       $r->print(' <br />');
       my @available = ();
       my @unavailable = ();
       &check_tools($functions,$tools,\@available,\@unavailable);
       &print_current_settings($r,$action,$functions,$startdate,$enddate,
       $groupname,$description,$granularity,$quota,
       \@available,\@unavailable,$gpterm,$ucgpterm);
       &membership_options($r,$action,$formname,$sectioncount,1,$gpterm,$ucgpterm);
       my $nexttext = $$navbuttons{'gtns'};
       my $prevtext = $$navbuttons{'gtpp'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
   sub choose_privs_form {
       my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
    $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,
    $states,$stored,$sectioncount,$navbuttons,$gpterm,$ucgpterm,
    $crstype) = @_;
   
       my @regexps = ('userpriv_');
       my $nexttext;
       
       if ($action eq 'create') {
           push(@regexps,'sec_');
           $r->print(&Apache::lonhtmlcommon::echo_form_input(
            ['origin','action','state','page','sortby','autoadd','autodrop'],
            \@regexps));
           $nexttext = $$navbuttons{'crgr'};
       } else {
           $r->print(&Apache::lonhtmlcommon::echo_form_input(
            ['origin','action','state','page','sortby'],\@regexps));
           $nexttext = $$navbuttons{'adme'};
       }
   
       &topic_bar($r,6,&mt('Setting optional privileges for specific group members'));
   
       &member_privileges_form($r,$action,$formname,$tools,$toolprivs,
                               $fixedprivs,$userdata,$usertools,$idx,undef,
                               $states,$stored,$gpterm);
   
       if ($action eq 'create') {
           my $img1 = 7;
           my $img2 = 8;
           &mapping_options($r,$action,$formname,$page,$sectioncount,
                            $states,$stored,$navbuttons,$img1,$img2,
                            $gpterm,$ucgpterm,$crstype);
       }
       my $prevtext = $$navbuttons{'gtps'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
   sub build_boxes {
       my ($r,$tools,$usertools,$fixedprivs,$toolprivs,$showtools,
           $showboxes,$prefix,$specificity,$excluded) = @_;
       my $totalboxes = 0;
       if (@{$tools} > 0) {
           if ($specificity eq 'Yes') {
               foreach my $tool (@{$tools}) {
                   @{$$showboxes{$tool}} = ();
                   foreach my $user (sort(keys(%{$usertools}))) {
                       if (ref($excluded) eq 'ARRAY') {
                           if (grep/^$user$/,@{$excluded}) {
                               next;
                           }
                       }
                       if ($$usertools{$user}{$tool}) {
                           unless (grep/^$tool$/,@{$showtools}) {
                               push(@{$showtools},$tool);
                           }
                           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                               unless (exists($$fixedprivs{$tool}{$priv})) {
                                   unless(grep(/^$priv$/,@{$$showboxes{$tool}})) {
                                       push(@{$$showboxes{$tool}},$priv);
                                       $totalboxes ++;
                                   }
                               }
                           }
                       }
                   }
               }
               if ($totalboxes > 0) {
                   $r->print('
 <script type="text/javascript">  <script type="text/javascript">
 function checkAllTools(formname) {  function checkAllTools(formname) {
 ');  ');
         foreach my $tool (sort(keys(%showboxes))) {                  foreach my $tool (sort(keys(%{$showboxes}))) {
             foreach my $priv (@{$showboxes{$tool}}) {                      foreach my $priv (@{$$showboxes{$tool}}) {
                 $r->print('  checkAll(formname.userpriv_'.$priv.');'."\n");                          $r->print('  checkAll(formname.'.$prefix.$priv.');'."\n");
             }                      }
         }                  }
         $r->print('                  $r->print('
 }  }
 function uncheckAllTools(formname) {  function uncheckAllTools(formname) {
 ');  ');
         foreach my $tool (sort(keys(%showboxes))) {                  foreach my $tool (sort(keys(%{$showboxes}))) {
             foreach my $priv (@{$showboxes{$tool}}) {                      foreach my $priv (@{$$showboxes{$tool}}) {
                 $r->print('  uncheckAll(formname.userpriv_'.$priv.');'."\n");                          $r->print('  uncheckAll(formname'.$prefix.$priv.');'."\n");
                       }
                   }
                   $r->print('
   }
   </script>
                   ');
             }              }
         }          }
         $r->print('      }
       return $totalboxes;
 }  }
 </script>  
        ');  sub member_privileges_form {
    }      my ($r,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,
    $r->print(<<"END");          $usertools,$idx,$memchg,$states,$stored,$gpterm) = @_;
 <br />      my %lt = &Apache::lonlocal::texthash(
 <table width="100%" cellpadding="0" cellspacing="0" border="0">              'addp' => 'Additional privileges',
  <tr bgcolor="$tabcol">              'fixp' => 'Core privileges',
   <td>&nbsp;</td>              'oppr' => 'Optional privileges',
   <td valign="middle" align="left">              'func' => 'Tool',
    <nobr><img src="/res/adm/pages/bl_step6.gif" valign="middle">&nbsp;</nobr>              'forf' => 'For the collaborative tools included for group '.
   </td>                        'members being added or modified, '. 
   <th align="left"><nobr>                        'there are no optional privileges to set '.
     Group member privileges                        'for specific members.',
    </nobr>              'algr' => 'All new group members will receive the same privileges.',            'ifex' => 'If previously expired members are being re-enabled, or '.
   </th>                        'if access for future members is being activated now, '.
   <td width="100%">&nbsp;</td>                        'previously set privileges will be preserved.',
  </tr>              'asno' => 'As no group members are being added, '.
  <tr>                        'there are no specific user privileges to set.',
   <td colspan="4">&nbsp;</td>              'asng' => 'As no group tools will be made available to users, '.
  </tr>                        'there are no specific user privileges to set.',
  <tr>              'nogm' => 'No group member privileges to display or set, '.
   <td>&nbsp;</td>                        'as you have not indicated that you will be activating,'.
   <td colspan="3">                        ' re-enabling, changing privileges, or adding/removing '.
 END                        'tools for any current members.',
     if ($env{'form.specificity'} eq 'Yes') {              'full' => 'Fullname',
         $r->print('              'user' => 'Username',
    <table border="0" cellspacing="2" cellpadding="2" border="0">              'doma' => 'Domain',
       );
       my @defprivs;
       my $specificity;
       if ($action eq 'create') {
           if (defined($env{'form.defpriv'})) {
               @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
           }
           $specificity = $env{'form.specificity'};
       } else {
           if (defined($$stored{'defpriv'})) {
               @defprivs = @{$$stored{'defpriv'}};
           }
           $specificity = $$stored{'specificity'};
       }
       my @showtools;
       my %showboxes = ();
       my $numtools = 1 + @{$tools};
   
       my @excluded = ();
       my $numchgs = 0;
       if ($formname eq 'change_privs') {
           my @currmembers = ();
           if (ref($$memchg{'deletion'}) eq 'ARRAY') {
               push(@excluded,@{$$memchg{'deletion'}});
           }
           if (ref($$memchg{'expire'}) eq 'ARRAY') {
               push(@excluded,@{$$memchg{'expire'}});
           }
           if (@excluded > 0) {
               foreach my $user (sort(keys(%{$usertools}))) {
                   if (grep/^$user$/,@excluded) {
                       next;
                   }
                   push(@currmembers,$user);
               }
           } else {
               @currmembers = sort(keys(%{$usertools}));
           }
           $numchgs = @currmembers;
           if (!$numchgs) {
               $r->print($lt{'nogm'}); 
               return $numchgs;
           }
       }
    
       my $totalboxes = &build_boxes($r,$tools,$usertools,$fixedprivs,
                                      $toolprivs,\@showtools,\%showboxes,
                                      'userpriv_',$specificity,\@excluded);
       if (@{$tools} > 0) {
           if ($specificity eq 'Yes') {
               if ($totalboxes > 0) {
                   my $numcells = 2;
                   my $colspan = $numcells + 1;
                   my %total;
                   if (keys(%{$usertools}) > 1) {
                       $r->print('
      <table border="0" cellspacing="2" cellpadding="2">
     <tr>      <tr>
      <td valign="top">  
 ');  ');
         $r->print(&Apache::lonhtmlcommon::start_pick_box());                      foreach my $tool (@{$tools}) {
         $r->print(<<"END");                          if (@{$showboxes{$tool}} > 0) {
    <tr bgcolor="$tabcol">                              $r->print('<td valign="top">');
     <th><b>Fullname</th>                              $r->print('<table class="thinborder"><tr>'.
     <th><b>Username</th>        '<th colspan="'.$colspan.'">'.
     <th>Domain</th>                                        $tool.'</th></tr><tr>');
     <th colspan="$numtools">Additional Privileges</th>                              my $privcount = 0;
   </tr>                              foreach my $priv (@{$showboxes{$tool}}) {
 END                                  $privcount ++;
     }                                  if (($privcount == @{$showboxes{$tool}}) && 
     if ($env{'form.specificity'} eq 'Yes') {                                      ($privcount > 1)) {
         &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,                                      if ($privcount%$numcells) {
                              $usertools,$toolprivs,$fixedprivs,$userdata,$idx);                                          $r->print('<td colspan="'.$colspan.'">');
     }                                      } else {
     if ($env{'form.specificity'} eq 'Yes') {                                          $r->print('<td>');
         $r->print('</td>');                                      }
         $r->print(&Apache::lonhtmlcommon::end_pick_box());                                  } else {
         $r->print('<td>&nbsp;</td>                                      $r->print('<td>');
                <td>&nbsp;</td><td valign="top">');                                  }
         my @toolboxes = sort(keys(%showboxes));                                  $r->print(qq|
         foreach my $tool (@{$tools}) {  
             if (@{$showboxes{$tool}} > 0) {   
                 $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.  
                       '"><th>'.$tool.'</th></tr>');  
                 foreach my $priv (@{$showboxes{$tool}}) {  
                     $r->print(qq|  
        <tr><td>  
        <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>         <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
          <nobr>
        <input type="button" value="check all"         <input type="button" value="check all"
          onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />           onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
        &nbsp;          &nbsp;
        <input type="button" value="uncheck all"         <input type="button" value="uncheck all"
         onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />          onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
       </nobr></fieldset></td></tr>|);        </nobr></fieldset><br />|);
                 }                                  $r->print('</td>');
                 $r->print('</table><br /><br />');                                  if ($privcount < @{$showboxes{$tool}}) {
             }                                      if (@{$showboxes{$tool}} > 2) {
         }                                          if ($privcount%$numcells == 0) {
         $r->print('</td></tr></table>');                                              $r->print('</tr><tr>');
     } else {                                          }
         $r->print(&Apache::lonhtmlcommon::start_pick_box());                                      } else {
         $r->print('<tr><td bgcolor="'.$tabcol.'" valign="top"><table cellspacing="0" cellpadding="1"><tr><td valign="top"><b>Function</b></td></tr><tr><td valign="top"><b>Fixed privileges</b>'.                                          $r->print('<tr></tr>');
                   '</td></tr><tr><td valign="top"><b>Optional privileges</b></td></tr></table></td>');                                      }
         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>');                              $r->print('</tr></table></td><td>&nbsp;</td>');
             my $privcount = 0;                          }
             my $fixed = '';  
             my $dynamic = '';  
             foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {  
                 if (exists($$fixedprivs{$tool}{$priv})) {  
                     $fixed .= '<input type="hidden" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';  
                 } else {  
                     $privcount ++;  
                     if ($privcount == 3) {  
                         $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'">';  
                     }                      }
                     $dynamic .= '<td><input type="checkbox" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'</td>';                      $r->print('</tr></table>');
                 }                  }
                   $r->print(&Apache::loncommon::start_data_table().
     &Apache::loncommon::start_data_table_header_row());
                   $r->print(<<"END");
       <th>$lt{'full'}</th>
       <th>$lt{'user'}</th>
       <th>$lt{'doma'}</th>
       <th colspan="$numtools">$lt{'addp'}</th>
   END
                   $r->print(&Apache::loncommon::end_data_table_header_row());
                   &member_privs_entries($r,$usertools,$toolprivs,$fixedprivs,
                                         $userdata,$idx,\@showtools,\@defprivs,
                                         \@excluded);
                   $r->print(&Apache::loncommon::end_data_table());
               } else {
                   $r->print($lt{'forf'}.'<br />');
                   &display_defprivs($r,$tools,$toolprivs,\@defprivs);
             }              }
             if ($dynamic eq '') {          } else {
                 $dynamic = '<td>None</td>';               if (keys(%{$usertools}) > 0) {
             }                  $r->print($lt{'algr'}.'<br />'.$lt{'ifex'}.'<br /><br />');
             if ($privcount < 3) {                  &display_defprivs($r,$tools,$toolprivs,\@defprivs);
                 $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'"><td colspan="2">&nbsp;</td>';              } else {
             } elsif ($privcount%2) {                  $r->print($lt{'asno'}.'<br />');
                 $dynamic = '<td>&nbsp;</td>';  
             }              }
             $r->print('<tr bgcolor="'.$rowColor2.'"><td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td></tr><tr bgcolor="'.$rowColor1.'">'.$dynamic.'</tr></table></td>');  
         }          }
         $r->print('</tr>');      } else {
         $r->print(&Apache::lonhtmlcommon::end_pick_box());          $r->print($lt{'asng'});
     }      }
     $r->print('</td></tr>      return $numchgs;
  <tr>  }
   <td colspan="4">&nbsp;</td>  
  </tr>  sub process_request {
       my ($r,$cdom,$cnum,$action,$state,$page,$groupname,$description,
           $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,
           $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,
           $sectioncount,$stored,$gpterm,$ucgpterm,$crstype) = @_;
   
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
                                    ['origin','action','state','page','sortby']));
   
       my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
                                          $ucgpterm,$crstype);
       if ($earlyout) {
           $r->print('
   <table width="100%" cellpadding="0" cellspacing="0" border="0">
  <tr>   <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td colspan="3">    <td colspan="3">
    <input type="button" name="previous" value = "Go to previous page"  '.$earlyout.'</td></tr>');
     onclick="javascript:backPage(document.'.$formname.','."'pick_members'".')"/>          &display_navbuttons($r,$state,$$states{$action}[$page-1],
    &nbsp;&nbsp;                              $$navbuttons{'gtps'});
    <input type="button" name="next" value="Create group"          $r->print('</table>');
  onclick="javascript:nextPage(document.'.$formname.','."'result'".')" />          return;
   </td>      }
  </tr>  
     ');  
     $r->print('  
 </table>');  
   
       my @defprivs = ();
       if ($action eq 'create' || $state eq 'chgresult') { 
           if (defined($env{'form.defpriv'})) {
               @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
           }
           if ($state eq 'chgresult') {
               my @okprivs = ();
               foreach my $tool (@{$tools}) {
                   foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                       push(@okprivs,$priv);
                   }
               }
               my @temp = ();
               foreach my $defpriv (@defprivs) {
                   if (grep/^$defpriv$/,@okprivs) {
                       push(@temp,$defpriv);
                   }
               }
               @defprivs = @temp; 
           }
       } else {
           if (defined($$stored{'defpriv'})) {
               @defprivs = @{$$stored{'defpriv'}};
           }
       }
   
       my $outcome;
       if ($action eq 'create' || $state eq 'chgresult') {
           $outcome = &write_group_data($r,$cdom,$cnum,$action,$state,$groupname,
                                        $description,$startdate,$enddate,
                                        $specificity,$functions,$tools,
                                        $sectioncount,$roles,$types,$sections,
                                        \@defprivs,$stored,$gpterm,$ucgpterm,
                                        $crstype); 
       }
       if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') && 
          (($state eq 'memresult') || ($state eq 'addresult')))) {
           &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools,
                               $enddate,$startdate,$userdata,$idx,$toolprivs,
                               $usertools,$specificity,\@defprivs,$memchg,$gpterm,
                               $ucgpterm);
       }
     return;      return;
 }  }
   
 sub completed_creation {  sub write_group_data {
     my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$userdata,      my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate,
 $startdate,$enddate,$tools,$functions,$toolprivs,$members,$usertools,$idx) = @_;          $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types,
           $sections,$defprivs,$stored,$gpterm,$ucgpterm,$crstype) = @_;
     $r->print(&Apache::lonhtmlcommon::echo_form_input(  
                                         ['origin','action','state']));  
     my @added= ();  
     my @failed = ();  
     my $now = time;      my $now = time;
       my $creation = $now;
       my $creator = $env{'user.name'}.':'.$env{'user.domain'};
       if ($state eq 'chgresult') {
           $creation = $$stored{'creation'};
           $creator = $$stored{'creator'};
       }
       my $esc_description = &escape($description);
       my @single_attributes = ('description','functions','startdate','enddate',
                                'creation','modified','creator','granularity',
                                'specificity','autoadd','autodrop','quota');
       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 = (
                        description => $esc_description,
                        startdate => $startdate,
                        enddate => $enddate,
                        creation => $creation,
                        modified => $now,
                        creator => $creator,
                        granularity => $env{'form.granularity'},
                        specificity => $specificity,
                        autoadd => $env{'form.autoadd'},
                        autodrop => $env{'form.autodrop'},
                        quota => $quota,
                      );
   
       foreach my $func (keys(%{$functions})) {
           my $status;
           if (grep(/^$func$/,@{$tools})) {
               $status = 'on';
           } else {
               $status = 'off';
           }
           $groupinfo{'functions'} .=  qq|<name id="$func">$status</name>|;
       }
   
       $groupinfo{'roles'} = $roles;
       $groupinfo{'types'} = $types;
       $groupinfo{'sectionpick'} = $sections;
       $groupinfo{'defpriv'} = $defprivs;
   
       my %groupsettings = ();
       foreach my $item (@single_attributes) {
           $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;
       }
       foreach my $item (@mult_attributes) {
           foreach my $entry (@{$groupinfo{$item}}) {
               $groupsettings{$groupname} .= qq|<$item>$entry</$item>|;
           }
       }
       my $autosec;
       my @autorole = &Apache::loncommon::get_env_multiple('form.autorole');
   
       foreach my $role (@autorole) {
           if (defined($env{'form.sec_'.$role})) {
               my @autosections=&Apache::loncommon::get_env_multiple('form.sec_'.
                                                                     $role);
               $autosec .= '<role id="'.$role.'">';
               foreach my $sec (@autosections) {
                   $autosec .= '<section>'.$sec.'</section>';
               }
               $autosec .= '</role>';
           }
       }
       if ($autosec) {
           $groupsettings{$groupname} .= qq|<autosec>$autosec</autosec>|;
       }
       my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,
                                                        \%groupsettings);
   
       if ($result eq 'ok') {
           if ($action eq 'create') {
               my $result = &add_group_folder($cdom,$cnum,$now,$groupname,$action,
                                              $description,$tools,\%groupinfo,
                                              $gpterm,$ucgpterm,$crstype);
               if ($result ne 'ok') {
                   $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 {
           my %actiontype = (
                             'create' => 'creating',
                             'modify' => 'modifying',
                            );
           &Apache::lonnet::logthis("Failed to store $gpterm $groupname ".
                                    'in '.lc($crstype).': '.$cnum.
                                    ' in domain: '.$cdom);
           $r->print(&mt('An error occurred when [_1] the [_2]. '.
                         'Please try again.',$actiontype{$action},$gpterm));
       }
       return $result;
   }
   
   sub process_membership {
       my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,
           $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg,
           $gpterm,$ucgpterm)=@_;
       my %usersettings = ();
       my %added= ();
       my %failed = ();
       my $num_ok = 0;
       my $num_fail = 0;
     my %group_privs = ();      my %group_privs = ();
       my %curr_privs = ();
       my %curr_start = ();
       my %curr_end = ();
     my %tooltype = ();      my %tooltype = ();
   
     foreach my $tool (@{$tools}) {      foreach my $tool (@{$tools}) {
         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
             $tooltype{$priv} = $tool;              $tooltype{$priv} = $tool;
             if ($env{'form.specificity'} eq 'Yes') {              if ($specificity eq 'Yes') {
                 my @users =                  my @users =
                   &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);                    &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
                 foreach my $user (@users) {                  foreach my $user (@users) {
                     $group_privs{$user} .= $priv.':';                      $group_privs{$user} .= $priv.':';
                       if ($state eq 'memresult') { 
                           unless (exists($$usertools{$user}{$tool})) {
                               $$usertools{$user}{$tool} = 1;
                           }
                       }
                 }                  }
             } else {              } else {
                 if (defined($env{'form.allpriv_'.$priv})) {                  if (@{$defprivs} > 0) {
                     foreach my $user (@{$members}) {                      if (grep/^\Q$priv\E$/,@{$defprivs}) {
                         if ($$usertools{$user}{$tool}) {                          foreach my $user (sort(keys(%{$usertools}))) {
                             $group_privs{$user} .= $priv.':';                              if ($$usertools{$user}{$tool}) {
                                   $group_privs{$user} .= $priv.':';
                               }
                         }                          }
                     }                      }
                 }                  }
Line 1322  $startdate,$enddate,$tools,$functions,$t Line 2910  $startdate,$enddate,$tools,$functions,$t
     foreach my $user (keys(%group_privs)) {      foreach my $user (keys(%group_privs)) {
         $group_privs{$user} =~ s/:$//;          $group_privs{$user} =~ s/:$//;
     }      }
     my $esc_description = &Apache::lonnet::escape($description);  
     my @attributes = ('description','functions','startdate','enddate','creation','modified','creator');  
           
     my %groupinfo = (  
                       description => $esc_description,  
                       startdate => $startdate,  
                       enddate => $enddate,  
                       creation => $now,  
                       modified => $now,  
                       creator => $env{'user.name'}.':'.$env{'user.domain'},   
                     );  
     foreach my $func (keys(%{$functions})) {  
         my $status;  
         if (grep(/^$func$/,@{$tools})) {  
             $status = 'on';  
         } else {  
             $status = 'off';  
         }   
         $groupinfo{'functions'} .=  qq|<name id="$func">$status</name>|;  
     }  
   
     my %curr_groups = ();      my $now = time;
     my %groupsettings = ();      my @activate = ();
     my %usersettings = ();      my @expire = ();
     if (&Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups) > 0) {      my @deletion = ();
         if (exists($curr_groups{$groupname})) {      my @reenable = ();
             $r->print('Non-unique name -please choose another');      my @unchanged = ();
             return;       if ($state eq 'memresult') {
           if (ref($$memchg{'activate'}) eq 'ARRAY') {
               @activate = @{$$memchg{'activate'}};
           }
           if (ref($$memchg{'expire'}) eq 'ARRAY') {
               @expire = @{$$memchg{'expire'}};
           }
           if (ref($$memchg{'deletion'}) eq 'ARRAY') {
               @deletion = @{$$memchg{'deletion'}};
           }
           if (ref($$memchg{'reenable'}) eq 'ARRAY') {
               @reenable = @{$$memchg{'reenable'}};
           }
           my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                    $groupname);
           foreach my $key (sort(keys(%membership))) {
               if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                   ($curr_end{$1},$curr_start{$1},$curr_privs{$1}) = 
                                                   split(/:/,$membership{$key},3);
               }
           }
           if (@expire + @deletion > 0) {
               foreach my $user (@expire) {
                   my $savestart = $curr_start{$user};
                   if ($savestart > $now) {
                       $savestart = $now;
                   }
                   $usersettings{$groupname.':'.$user} = $now.':'.$savestart.':'.
                                                         $curr_privs{$user};
                   if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                          $user,$now,$savestart,
                                                          $curr_privs{$user}) eq 'ok') {
                       push(@{$added{'expired'}},$user);
                       $num_ok ++;
                   } else {
                       push(@{$failed{'expired'}},$user);
                       $num_fail ++;
                   }
               }
               foreach my $user (@deletion) {
                   $usersettings{$groupname.':'.$user} = $now.':-1:';
                   if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                          $user,$now,'-1','')
                                                            eq 'ok') {
                       push(@{$added{'deleted'}},$user);
                       $num_ok ++;
                   } else {
                       push(@{$failed{'deleted'}},$user);
                       $num_fail ++;
                   }
               }
         }          }
     }      }
     my $groupentry;  
     foreach my $item (@attributes) {      foreach my $user (sort(keys(%{$usertools}))) {
         $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;          if ((grep(/^$user$/,@expire)) || (grep(/^$user$/,@deletion))) {
               next;
           }
           my $type;
           my $start = $startdate;
           my $end = $enddate;
           if ($state eq 'memresult') {
               if (@activate > 0) {
                   if (grep/^$user$/,@activate) {
                       $start = $now;
                       $end = $enddate;
                       $type = 'activated';
                   }
               }
               if (@reenable > 0) {
                   if (grep/^$user$/,@reenable) {
                       $start = $startdate;
                       $end = $enddate;
                       $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 {
               $type = 'added';
           }
           $usersettings{$groupname.':'.$user} = $end.':'.$start.':'.
                                                 $group_privs{$user};
           if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                   $user,$end,$start,
                                                   $group_privs{$user}) eq 'ok') {
               push(@{$added{$type}},$user);
               $num_ok ++;
           } else {
               push(@{$failed{$type}},$user);
               $num_fail ++;
           }
     }      }
     my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,      my $roster_result = &Apache::lonnet::modify_coursegroup_membership($cdom,
                                                           \%groupsettings);                                                         $cnum,\%usersettings);
     if ($result eq 'ok') {      if ($num_ok) {
         my $put_result = &create_homepage($cdom,$cnum,$groupname,\%groupinfo,$tools);          foreach my $type (sort(keys(%added))) { 
         foreach my $user (sort(@{$members})) {              $r->print(&mt('The following users were successfully [_1]',$type));
             $usersettings{$groupname.':'.$user} = $enddate.':'.$startdate.':'.$group_privs{$user};              if (!($type eq 'deleted' || $type eq 'expired')) {   
             if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,                  $r->print(&mt(' with the following privileges'));
                   $user,$enddate,$startdate,$group_privs{$user}) eq 'ok') {              }
                 push(@added,$user);              $r->print(':<br />');
             } else {              foreach my $user (@{$added{$type}}) {
                 push(@failed,$user);                  my $privlist = '';
                   if (!($type eq 'deleted' ||  $type eq 'expired')) {
                       $privlist = ': ';
                       my @privs = split(/:/,$group_privs{$user});
                       my $curr_tool = '';
                       foreach my $priv (@privs) {
                           unless ($curr_tool eq $tooltype{$priv}) {
                               $curr_tool = $tooltype{$priv};
                               $privlist .= '<b>'.$curr_tool.'</b>: ';
                           }
                           $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
                       }
                       $privlist =~ s/, $//;
                   }
                   $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.$privlist.'<br />');
             }              }
               $r->print('<br />');
         }          }
         my $roster_result = &Apache::lonnet::modify_coursegroup_membership(      }
              $cdom,$cnum,\%usersettings);      if ($num_fail) {
         $r->print('          foreach my $type (sort(keys(%failed))) {
 Group '.$groupname.' was created.<br />');              $r->print(&mt('The following users could not be [_1], because an error occurred:<br />',$type));
         if (@added > 0) {              foreach my $user (@{$failed{$type}}) {
             $r->print('Users were added with following privileges:<br />');  
             foreach my $user (@added) {  
                 my @privs = split(/:/,$group_privs{$user});  
                 my $privlist= '';  
                 my $curr_tool = '';  
                 foreach my $priv (@privs) {  
                     unless ($curr_tool eq $tooltype{$priv}) {  
                         $curr_tool = $tooltype{$priv};  
                         $privlist .= '<b>'.$curr_tool.'</b>: ';  
                     }  
                     $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';  
                 }  
                 $privlist =~ s/, $//;  
                 $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.': '.$privlist.'<br />');  
             }  
         }  
         if (@failed > 0) {  
             $r->print('Addition of the following users was unsuccessful:<br />');  
             foreach my $user (@failed) {  
                 $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');                  $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
             }              }
         }          }
         if ($roster_result eq 'ok') {          $r->print('<br />');
             $r->print('<br />Group membership list updated.');      }
         } else {      if (@unchanged > 0) {
             $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');          $r->print(&mt('No change occurred for the following users:<br />'));
         }           foreach my $user (sort(@unchanged)) {
               $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
           }
           $r->print('<br />');
       }
       if ($roster_result eq 'ok') {
           $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 {
           $r->print('<br />'.&mt('An error occurred while updating the [_1] membership list -',$gpterm).$roster_result.'<br />');
       }
       return;
   }
   
   sub mapping_options {
       my ($r,$action,$formname,$page,$sectioncount,$states,$stored,
           $navbuttons,$img1,$img2,$gpterm,$ucgpterm,$crstype) = @_;
       my %lt = &Apache::lonlocal::texthash(
           'auto' => "Settings for automatic $gpterm enrollment",
           'gmma' => "$ucgpterm membership mapping to specific sections/roles",
           'endi' => "Enable/disable automatic $gpterm enrollment for ".
                             "users in specified roles and sections",
           '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 $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 $gpterm enrollment",
           'curr' => 'Currently set to',
           'on' => 'on',
           'off' => 'off',
           'auad' => "Automatically enable $gpterm membership when roles are added?",
           'auex' => "Automatically expire $gpterm membership when roles are removed?",
           'mapr' => "Mapping of roles and sections affected by automatic $gpterm enrollment/disenrollment follows scheme chosen below.",
       );
       &automapping($r,$action,$stored,\%lt,$img1);
       &mapping_settings($r,$sectioncount,\%lt,$stored,$img2,$crstype);
       return;
   }
   
   sub automapping {
       my ($r,$action,$stored,$lt,$image) = @_;
       my $add = 'off';
       my $drop = 'off';
       if (exists($$stored{'autoadd'})) {
           $add = $$stored{'autoadd'};
       }
       if (exists($$stored{'autodrop'})) {
           $drop = $$stored{'autodrop'};
       }
       &topic_bar($r,$image,$$lt{'endi'});
       $r->print('
       <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br /><br />
      <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>');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');
       }
       $r->print('
       </nobr><br />
       <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>');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');
       }
       $r->print('</nobr><br /><br />'.$$lt{'mapr'});
   }
   
   sub mapping_settings {
       my ($r,$sectioncount,$lt,$stored,$image,$crstype) = @_;
       my @sections = keys(%{$sectioncount});
       if (@sections > 0) {
           @sections = sort {$a cmp $b} @sections;
           unshift(@sections,'none'); # Put 'no sections' next
           unshift(@sections,'all'); # Put 'all' at the front of the list
     } else {      } else {
         &Apache::lonnet::logthis('Failed to create group '.$groupname.           @sections = ('all','none');
                                  'in course: '.$cnum.' in domain: '.$cdom);      }
       &topic_bar($r,$image,$$lt{'pirs'});
       my @roles = &standard_roles();
       my %customroles = &my_custom_roles();
       $r->print(&Apache::loncommon::start_data_table().
         &Apache::loncommon::start_data_table_header_row());
       $r->print('
                    <th>'.&mt('Active?').'</th>
                    <th>'.&mt('Role').'</th>');
       if (@sections > 0) {
           $r->print('<th>'.&mt('Sections').'</th>');
       }
       $r->print(&Apache::loncommon::end_data_table_header_row()."\n");
       foreach my $role (@roles) {
           my $plrole=&Apache::lonnet::plaintext($role,$crstype);
           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>';
               }
           }
           $r->print(&Apache::loncommon::start_data_table_row().
     '<td><input type="checkbox" '.
                     'name="autorole" value="'.$role.'" /></td><td>'.$plrole.
                     '</td>'.$sections_sel.
     &Apache::loncommon::end_data_table_row());
       }
       foreach my $role (sort(keys(%customroles))) {
           my $sections_sel;
           if (@sections > 0) {
               $sections_sel = 
    '<td>'.&sections_selection(\@sections,'sec_'.$role).'</td>';
           }
           $r->print(&Apache::loncommon::start_data_table_row().
     '<td><input type="checkbox" '.
                     'value="'.$role.'" /></td><td>'.&mt('Custom role: ').
                     '<i>'.$role.'</i></td>'.$sections_sel.
     &Apache::loncommon::end_data_table_row());
       }
       $r->print(&Apache::loncommon::end_data_table());
       return;
   }
   
         $r->print('An error occurred when creating the new group. '.  sub standard_roles {
                                                       'Please try again.');      my @roles = ('cc','in','ta','ep','st');
       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 {
       my ($r,$groupname,$page,$gpterm) = @_;
       my @menu =
           (
             { text => "Modify default $gpterm settings",
               help => 'Course_Modify_Group',
               state => 'change_settings',
               branch => 'settings',
               },
             { text => 'Modify access, tools and/or privileges for previous, '.
                       'future, or current members',
               help => 'Course_Modify_Group_Membership',
               state => 'change_members',
               branch => 'members',
               },
             { text => "Add member(s) to the $gpterm",
               help => 'Course_Group_Add_Members',
               state => 'add_members',
               branch => 'adds',
               },
             );
       my $menu_html = '';
       foreach my $menu_item (@menu) {
           $menu_html .=
           '<p><font size="+1"><a href="/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state='.$menu_item->{'state'}.'&branch='.$menu_item->{'branch'}.'">';
           $menu_html.= &mt($menu_item->{'text'}).'</a></font>';
           if (exists($menu_item->{'help'})) {
               $menu_html.=
                   &Apache::loncommon::help_open_topic($menu_item->{'help'});
           }
           $menu_html.='</p>'.$/;
     }      }
       $r->print($menu_html);
     return;      return;
 }  }
   
 sub member_privs_entries {  sub member_privs_entries {
     my ($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,$usertools,$toolprivs,      my ($r,$usertools,$toolprivs,$fixedprivs,$userdata,$idx,$showtools,
                                               $fixedprivs,$userdata,$idx) = @_;   $defprivs,$excluded) = @_;
     my $rowColor;      foreach my $user (sort(keys(%{$usertools}))) {
     my $rowNum = 0;          if (defined($excluded)) {
     foreach my $member (@{$members}) {              if (ref($excluded) eq 'ARRAY') {
         my ($uname,$udom) = split(/:/,$member);                  if (grep/^$user$/,@{$excluded}) {
         if ($rowNum %2 == 1) {                      next;
             $rowColor = $rowColor1;                  }
         } else {              }
             $rowColor = $rowColor2;  
         }          }
         $r->print('<tr bgcolor="'.$rowColor.'">          my ($uname,$udom) = split(/:/,$user);
                 <td>'.$$userdata{$member}[$$idx{fullname}].'</td>          $r->print(&Apache::loncommon::start_data_table_row().'
                   <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">
         foreach my $tool (@{$tools}) {                    <table>
             if (exists($$usertools{$member}{$tool})) {                     <tr>
                 $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></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}) {
               if (exists($$usertools{$user}{$tool})) {
                   $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 = '';
                 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="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';                          $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$user.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
                     } else {                      } else {
                         $privcount ++;                          $privcount ++;
                         if ($privcount == 3) {                          if ($privcount == 3) {
                             $dynamic .= '</tr><tr>';                              $dynamic .= '</tr><tr>';
                         }                          }
                         $dynamic .= '<td><input type="checkbox" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'</td>';                          $dynamic .='<td><nobr><label><input type="checkbox" '.
                                  'name="userpriv_'.$priv.'" value="'.$user.'"';
                           if (grep/^\Q$priv\E$/,@{$defprivs}) {
                               $dynamic .= ' checked="checked" ';
                           }
                           $dynamic .= ' />'.$$toolprivs{$tool}{$priv}.
                                       '</label></nobr></td>';
                     }                      }
                 }                  }
                 $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>&nbsp;</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());
     }      }
 }  }
   
   
 sub get_dates_from_form {  sub get_dates_from_form {
     my $startdate;      my $startdate;
     my $enddate;      my $enddate;
Line 1464  sub get_dates_from_form { Line 3307  sub get_dates_from_form {
         $enddate = 0;          $enddate = 0;
     }      }
     return ($startdate,$enddate);      return ($startdate,$enddate);
 }                                                                                       }
   
 sub date_setting_table {  sub date_setting_table {
     my ($starttime,$endtime,$formname) = @_;      my ($starttime,$endtime,$formname) = @_;
     my $startform = &Apache::lonhtmlcommon::date_setter($formname,      my $startform = &Apache::lonhtmlcommon::date_setter($formname,
                                                       '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><input type="checkbox" name="no_end_date" />      my $perpetual = 
                                                   no ending date</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 ($allgrpsmap) { 
               $parm_result .= &parm_setter($navmap,$cdom,$allgrpsmap,$groupname);
           }
           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 = &Apache::lonnet::unescape($$groupinfo{description});      my $content = &unescape($$groupinfo{description});
     $content=~s/\s+$//s;      $content=~s/\s+$//s;
     $content=~s/^\s+//s;      $content=~s/^\s+//s;
     $content=~s/\<br\s*\/*\>$//s;      $content=~s/\<br\s*\/*\>$//s;
     $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;
 }  }
   
   sub check_uncheck_tools {
       my ($r,$available) = @_;
       if (ref($available) eq 'ARRAY') { 
           $r->print('
   <script type="text/javascript">
   function checkAllTools(formname) {
   ');
           foreach my $tool (@{$available}) {
               $r->print('  checkAll(formname.user_'.$tool.');'."\n");
           }
           $r->print(' checkAll(formname.togglefunc);'."\n");
           $r->print('
   }
   function uncheckAllTools(formname) {
   ');
           foreach my $tool (@{$available}) {
               $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");
           }
           $r->print(' uncheckAll(formname.togglefunc);'."\n");
           $r->print('
   }
   function toggleTools(field,caller) {
        if (caller.checked) {
            checkAll(field);
        } else {
            uncheckAll(field);
        }
        return;   
   }
   </script>
   ');
       }
       return;
   }
   
   sub validate_groupname {
       my ($groupname,$action,$cdom,$cnum,$gpterm,$ucgpterm,$crstype) = @_;
       my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
       my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
   
       my %lt = &Apache::lonlocal::texthash (
                         igna => "Invalid $gpterm name",
                         tgne => "The $gpterm name entered ",
                         grna => "$ucgpterm names and section names used in a ".
                                  "$crstype must be unique.",
                         isno => "is not a valid name.",
                         gnmo => "$ucgpterm names may only contain letters, ". 
                                 "numbers or underscores.",
                         cnnb => "can not be used as it is the name of ",
                         inth => " in this $crstype", 
                         thgr => "- does not correspond to the name of an ".
                                 "existing $gpterm",    
       );
   
       my $exitmsg = '<span class="LC_error">'.$lt{'igna'}.'</span><br /><br />'.
    $lt{'tgne'}.' "'.$groupname.'" ';
       my $dupmsg = $lt{'grna'};
       my $earlyout;
       if (($groupname eq '') || ($groupname =~ /\W/)) {
           $earlyout = $exitmsg.$lt{'isno'}.'<br />'.$lt{'gnmo'};
           return $earlyout;
       }
       if (exists($sectioncount{$groupname})) {
    return $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}.
       '<br />'.$lt{'grna'};
       }
       if ($action eq 'create' 
    && exists($curr_groups{$groupname})) {
   
    return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm).
       $lt{'inth'}.'<br />'.$lt{'grna'};
   
       } elsif ($action eq 'modify') {
           unless(exists($curr_groups{$groupname})) {
               $earlyout = &mt('[_1] name:',$ucgpterm).' '.$groupname.$lt{'thgr'}.
                           $lt{'inth'};
               return $earlyout;
           }
       }
       return;
   }
   
   sub topic_bar {
       my ($r,$imgnum,$title) = @_;
       $r->print('
   <div class="LC_topic_bar">
       <img alt="'.&mt('Step [_1]',$imgnum).
         '"src="/res/adm/pages/bl_step'.$imgnum.'.gif" />&nbsp;
       <span>'.$title.'</span>
   </div>
   ');
       return;
   }
   
   sub check_changes {
       my ($member_changes,$memchg) = @_;
       my %exclusions;
       @{$exclusions{'changefunc'}} = ('expire');
       @{$exclusions{'changepriv'}} = ('expire','changefunc');
   
       foreach my $change (@{$member_changes}) {
           if ($change eq 'deletion') {
               next;
           }
           my @checks = ('deletion');
           if (exists($exclusions{$change})) {
               push(@checks,@{$exclusions{$change}});
           }
           my @temp = ();
           foreach my $item (@{$$memchg{$change}}) {
               my $match = 0;
               foreach my $check (@checks) {
                   if (defined($$memchg{$check})) { 
                       if (ref(@{$$memchg{$check}}) eq 'ARRAY') {
                           if (@{$$memchg{$check}} > 0) {
                               if (grep/^$item$/,@{$$memchg{$check}}) {
                                   $match = 1;
                                   last;
                               }
                           }
                       }
                   }
               }
               if ($match) {
                   next;
               }
               push(@temp,$item);
           }
           @{$$memchg{$change}} = @temp;
       }
   }
   
 1;  1;

Removed from v.1.3  
changed lines
  Added in v.1.56


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