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

version 1.3, 2005/11/15 22:03:05 version 1.105, 2009/11/16 14:07:57
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 26  package Apache::loncoursegroups; Line 29  package Apache::loncoursegroups;
   
 use strict;  use strict;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::loncommon;  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 LONCAPA::map();
   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 46  sub handler { Line 54  sub handler {
     if (! ($env{'request.course.fn'})) {      if (! ($env{'request.course.fn'})) {
         # Not in a course          # Not in a course
         $env{'user.error.msg'}=          $env{'user.error.msg'}=
      "/adm/coursegroups:mdg:0:0:Cannot edit or view course groups";       "/adm/coursegroups:mdg:0:0:Cannot edit or view course/community groups";
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
   
     &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 => 'Send Messages', 
                       discussion => 'Discussion boards',                        discussion => 'Discussion Boards',
                       chat => 'Chat',                        chat => 'Chat Room',
                       files => 'File repository',                        files => 'Group Portfolio',
                       roster => 'Membership roster',                        roster => 'Membership Roster',
                       homepage => 'Group home page',                        homepage => $ucgpterm.' home page',
                     );                      );
   
     my %idx = ();      my %idx = ();
Line 79  sub handler { Line 88  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'};
     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') {       my $state = $env{'form.state'};
       if ((!defined($action)) || ($action eq 'view') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) {
           if (!defined($state)) {
               $state = 'view';
           }
       }
       if ($action eq 'create' || $action eq 'modify' || $action eq 'view' || 
           $action eq 'delete' || $action eq 'reenable') { 
         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('<div class="LC_warning">'
                       'privileges in this course');                       .&mt('You do not have '.$gpterm.' administration '
                            .'privileges in this '.lc($crstype).'.')
                        .'</div>');
         }          }
     } 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();
   }
   function openGroupRoster(group,status) {
       var url = '/adm/grouproster?';
       url += 'group='+group+'&status='+status+'&ref=popup';
       var title = 'Group Membership';
       var options = 'scrollbars=1,resizable=1,menubar=0';
       options += ',width=700,height=600';
       rosterbrowser = open(url,title,options,'1');
       rosterbrowser.focus();
   }\n|;
       $r->print(&header('My Space',$jscript,$action,$state));
       if ($env{'form.refpage'} eq 'cusr') {
           &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>"/adm/createuser",
                 text=>"User Management"});
       }
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/coursegroups",          ({href=>"/adm/coursegroups",
           text=>"Course Groups",});            text=>"Groups"});
     $r->print(&Apache::lonhtmlcommon::breadcrumbs      my $helpitem;
                 (undef,'Course Groups'));      if ($manage_permission) {
     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,          $helpitem = 'Creating_Groups';
                                           $view_permission,$manage_permission);      }
       $r->print(&Apache::lonhtmlcommon::breadcrumbs('Groups',$helpitem));
       &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
       $manage_permission,$action,$state,$gpterm,$ucgpterm,
       $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'}.'&state=verify&groupname=',
         reenable => '<a href="/adm/coursegroups?action=reenable&refpage='.
                            $env{'form.refpage'}.'&state=verify&groupname=',
       );
       my %lt = &Apache::lonlocal::texthash( 
                             modify => 'Modify',
                             view   => 'View',
                             delete => 'Delete',
                             reenable => 'Re-enable',
                             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',
                             redg   => 'Re-enable a deleted 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 ($status,$reenable_link);
       <table border="0" cellpadding="4" cellspacing="1">          if ($action eq 'reenable') {
        <tr bgcolor="$tabcol" align="center">              $status = 'deleted_groups';
         <td><b>Action</b></td>          } else {
         <td><b><a href="javascript:changeSort('groupname')">Group Name</a></b></td>              if ($manage_permission) {
         <td><b><a href="javascript:changeSort('description')">Description</a></b></td>                  my %deleted_groups = 
         <td><b><a href="javascript:changeSort('creator')">Creator</a></b>                      &Apache::longroup::coursegroups($cdom,$cnum,undef,'deleted_groups');
         </td>                  if (keys(%deleted_groups) > 0) {
         <td><b><a href="javascript:changeSort('creation')">Created</a></b>                      $reenable_link = '&nbsp;&nbsp;&nbsp;&nbsp;<a href="/adm/coursegroups?action=reenable&amp;refpage='.$env{'form.refpage'}.'">'.$lt{'redg'}.'</a>';
         </td>                  }
         <td><b><a href="javascript:changeSort('modified')">Last Modified</a></b>              }
         </td>          }
         <td><b>Functionality</b>          my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef,
         </td>                                                            $status);
         <td><b><a href="javascript:changeSort('quota')">Quota (Mb)</a></b></td>  
         <td><b><a href="javascript:changeSort('totalmembers)">Members</a></b></td>          if (%curr_groups) {
         <td><b><a href="javascript:changeSort('totalfiles')">Files</a></b></td>              if ($manage_permission) {
         <td><b><a href="javascript:changeSort('boards')">Discussion boards</a></b></td>                  if ($action ne 'reenable') {
         <td><b><a href="javascript:changeSort('diskuse')">Disk use</a></b></td>                      $r->print('<br /><a href="/adm/coursegroups?action=create&amp;refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');
        </tr>                  }
                   if ($reenable_link) {
                       $r->print($reenable_link);
                   }
               }
               $r->print('<br /><br />');
       $r->print(&Apache::loncommon::start_data_table().
         &Apache::loncommon::start_data_table_header_row());
         
               $r->print(<<"END");
           <th>$lt{'act'}</th>
           <th><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></th>
           <th><a href="javascript:changeSort('description')">$lt{'desc'}</a></th>
           <th><a href="javascript:changeSort('creator')">$lt{'crea'}</a></th>
           <th><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></th>
           <th><a href="javascript:changeSort('modified')">$lt{'last'}</a></th>
           <th>$lt{'func'}</b></td>
           <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 $totaldirs = 0;
                     } elsif ($env{'form.sortby'} eq 'description') {                  my $totalfiles = 0;
                         push(@{$Sortby{$grp_info{$group}{'description'}}},                  &group_files($group,$port_path,\$totalfiles,\$totaldirs);
                                                                      $group);                  $grp_info{$group}{'totalfiles'} = $totalfiles;
                     } elsif ($env{'form.sortby'} eq 'creator') {                  $grp_info{$group}{'totaldirs'} = $totaldirs;
                         push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);                  my $getpropath = 1;  
                     } elsif ($env{'form.sortby'} eq 'creation') {                  my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_path,                                                         $getpropath);
                         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'};                          $action eq 'reenable') {
                         my $totalfiles = $grp_info{$group}{'totalfiles'};                          $link .= $group;
                         my $boards = $grp_info{$group}{'boards'};                      } else {
                         my $diskuse = $grp_info{$group}{'diskuse'};                          $link .= $group.'/smppg?ref=grouplist';
                         my $functionality;                          if (exists($env{'form.refpage'})) {
                         foreach my $tool (sort keys(%{$functions})) {                              $link .= '&amp;refpage='.$env{'form.refpage'};
                             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) { 
                               $link .= '&nbsp;&nbsp;'.$actionlinks{'modify'}.
                                         $group.'">'.$lt{'modify'}.'</a>'.
                                        '&nbsp;&nbsp;'.$actionlinks{'delete'}.
                                         $group.'">'.$lt{'delete'}.'</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">'.
                                     '<span class="LC_nobreak">'.&mt('Files: [_1]',$totalfiles).'</span><br />'.
                                     '<span class="LC_nobreak">'.&mt('Folders: [_1]',$totaldirs).'</span>'.
                                     '</td>'.
         '<td align="right">'.$boards.'</td>'.
         '<td align="right">'.$diskuse.'</td>'.
         &Apache::loncommon::end_data_table_row());
                 }                  }
                 $r->print('</table>');              }
                 $r->print(&Apache::lonhtmlcommon::end_pick_box());              $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('<input type="hidden" name="state" value="'.
                         $state.'" />');
               }
         } else {          } else {
             $r->print('No groups exist');              $r->print($lt{'nogr'});
               if ($manage_permission) {
                   $r->print('<br /><br /><a href="/adm/coursegroups?action=create&amp;refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');
                   if ($action ne 'reenable') {
                       if ($reenable_link) {
                           $r->print($reenable_link);
                       }
                   }
               } 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 '.$gpterm.'s in this '.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 = ();
Line 238  sub group_administration { Line 413  sub group_administration {
     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);
   
       if (defined($env{'form.groupname'})) {
           $groupname = $env{'form.groupname'};
       }
   
       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}} = ();
               }
           }
       }
   
     my $state = $env{'form.state'};      if ($action eq 'modify') {
     my ($groupname,$description,$startdate,$enddate);  
   
     if ($action eq 'create') {  
         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'})) {          } else {
                 $description = $env{'form.description'};              %stored = &retrieve_settings($cdom,$cnum,$groupname,$action);
               if (ref($stored{'types'}) eq 'ARRAY') {
                   @types = @{$stored{'types'}};
             }              }
             if (defined($env{'form.tool'})) {              if (ref($stored{'roles'}) eq 'ARRAY') {
                 @tools=&Apache::loncommon::get_env_multiple('form.tool');                  @roles = @{$stored{'roles'}};
             }              }
             if (defined($env{'form.member'})) {              if (ref($stored{'sectionpick'}) eq 'ARRAY') {
                 @members = &Apache::loncommon::get_env_multiple('form.member');                  @sections = @{$stored{'sectionpick'}};
                 foreach my $user (@members) {              }
                     %{$usertools{$user}} = ();              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 = ();      my $toolprivs = &Apache::longroup::get_tool_privs($gpterm);
     %{$toolprivs{'email'}} = (  
                                  sgm => 'Send group mail',      my $fixedprivs = &Apache::longroup::get_fixed_privs();
                                  sgb => 'Broadcast mail',  
                              );      my %elements = 
     %{$toolprivs{'discussion'}} =  (   (
                                      cgb => 'Create boards',   create => {
                                      pgd => 'Post',       pick_name => {
                                      pag => 'Anon. posts',   startdate_month  => 'selectbox',
                                      rgi => 'Get identities',    startdate_hour   => 'selectbox',
                                      vgb => 'View boards',   enddate_month    => 'selectbox',
                                    );   enddate_hour     => 'selectbox',
     %{$toolprivs{'chat'}} =  (   startdate_day    => 'text',
                                 pgc => 'Chat',   startdate_year   => 'text',
                              );   startdate_minute => 'text',
     %{$toolprivs{'files'}} =  (   startdate_second => 'text',
                                  rgf => 'Retrieve',   enddate_day      => 'text',
                                  ugf => 'Upload',   enddate_year     => 'text',
                                  dgf => 'Delete',   enddate_minute   => 'text',
                               );   enddate_second   => 'text',
     %{$toolprivs{'roster'}} = (   groupname        => 'text',
                                  vgm => 'View',   description      => 'text',
                               );                   quota            => 'text',
     %{$toolprivs{'homepage'}} = (   tool             => 'checkbox',
                                 vgh => 'View page',   granularity      => 'radio',
                                 mgh => 'Modify page',   no_end_date      => 'checkbox',
                               );       },
     my %fixedprivs = ();       pick_members => {
     %{$fixedprivs{'email'}} = ('sgm' => 1);   member          => 'checkbox',
     %{$fixedprivs{'discussion'}} = ('vgb' => 1);   defpriv         => 'checkbox',
     %{$fixedprivs{'chat'}} = ('pgc' => 1);       },
     %{$fixedprivs{'files'}} = ('rgf' => 1);   },
     %{$fixedprivs{'roster'}} = ('vgm' => 1);   );
     %{$fixedprivs{'homepage'}} = ('vgh' => 1);      
       $elements{'modify'} = {
     my %elements = ();   change_settings => {
     %{$elements{'create'}} = ();      %{$elements{'create'}{'pick_name'}},
     %{$elements{'modify'}} = ();      specificity => 'radio',
     %{$elements{'create'}{'pick_name'}} = (      defpriv     => 'checkbox',
         startdate_month => 'selectbox',      autorole    => 'checkbox',
         startdate_hour => 'selectbox',      autoadd     => 'radio',
         enddate_month => 'selectbox',      autodrop    => 'radio',
         enddate_hour => 'selectbox',   },
         types => 'selectbox',   add_members => {
         roles => 'selectbox',      types       => 'selectbox',
         startdate_day => 'text',      roles       => 'selectbox',
         startdate_year => 'text',   },
         startdate_minute => 'text',      };
         startdate_second => 'text',  
         enddate_day => 'text',      if (ref($stored{'autorole'}) eq 'ARRAY') {
         enddate_year => 'text',          foreach my $role (@{$stored{'autorole'}}) {
         enddate_minute => 'text',              unless (($role eq 'cc') || ($role eq 'co')) {
         enddate_second => 'text',                  $elements{'modify'}{'change_settings'}{'sec_'.$role} = 
         groupname => 'text',                                                                     'selectbox';
         description => 'text',              }
         tool => 'checkbox',  
         granularity => 'radio',  
         no_end_date => 'checkbox',  
     );  
     %{$elements{'create'}{'pick_members'}} = (  
         member => 'checkbox',  
     );  
     if (($action eq 'create') && ($state eq 'pick_name')) {  
         my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,  
                            \%sectioncount);  
         if ($numsections > 0) {  
             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';  
         }          }
     }      }
                                                                                         
     if (($action eq 'create') && (($state eq 'pick_members') ||      if (($action eq 'create') && ($state eq 'pick_name')) {
                                   ($state eq 'pick_privs'))) {          $elements{'create'}{'pick_name'}{'types'} = 'selectbox';
           $elements{'create'}{'pick_name'}{'roles'} = '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') || 
           ($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 568  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) {  
                 @sections = sort {$a cmp $b} keys(%sectioncount);  
             }  
         }          }
         &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,\@sections,\%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) {              foreach my $tool (@tools) {
                 if ($env{'form.granularity'} eq 'Yes') {                  if ($granularity eq 'Yes') {
                     $elements{'create'}{'pick_members'}{'user_'.$tool} = 'checkbox';                      $elements{$action}{'pick_members'}{'user_'.$tool} = 'checkbox';
                 }                  }
             }              }
             $elements{'create'}{'pick_members'}{'specificity'} = 'radio';              $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) {
                   if ($granularity eq 'Yes') {
                       $elements{$action}{'change_members'}{'user_'.$tool} = 'checkbox';
                   }
               }
               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 group portfolio 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 group portfolio 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');
       @{$states{'delete'}} = ('verify','result');
       @{$states{'reenable'}} = ('verify','result');
       @{$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') || ($action eq 'delete') || ($action eq 'reenable')) {
           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 'cusr') {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/dropadd",          ({href=>"/adm/createuser",
           text=>"Enrollment Manager",            text=>"User Management",
           faq=>9,bug=>'Instructor Interface',});            faq=>9,bug=>'Instructor Interface',});
     } else {          if ($action eq 'modify' || $action eq 'delete') {
               &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>"/adm/coursegroups?refpage=cusr&action=$action",
                 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',
     if ((($action eq 'create') || ($action eq 'modify')) &&                              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',
                             );
       %{$trail{'delete'}} = &Apache::lonlocal::texthash(
                               verify => 'Verify deletion',
                               result => 'Deletion Complete'
                             );
       %{$trail{'reenable'}} = &Apache::lonlocal::texthash(
                               verify => 'Verify Re-enable',
                               result => 'Re-enabled'
                             );
       my %navbuttons = &Apache::lonlocal::texthash(
                                gtns => 'Next',#'Go to next step',
                                gtps => 'Back',#'Go to previous step',
                                crgr => 'Create '.$gpterm,
                                mose => 'Save',#'Modify settings',
                                gtpp => 'Back',#'Go to previous page',
                                adme => 'Add members',
       );
       if ((($action eq 'create') || ($action eq 'modify') || ($action eq 'delete') || ($action eq 'reenable')) &&
               ($manage_permission)) {                ($manage_permission)) {
         for (my $i=0; $i<@{$states{$action}}; $i++) {          for (my $i=0; $i<@{$states{$action}}; $i++) {
             if ($state eq $states{$action}[$i]) {              if ($state eq $states{$action}[$i]) {
                 &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","Creating_Groups"));
                 &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 (($action eq 'create') || ($action eq 'modify')) {
                     &Apache::lonhtmlcommon::add_breadcrumb(                      if (($state eq 'result') && ($i > 0)) {
                           &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]}"});
                 } else {                       } else { 
                     &Apache::lonhtmlcommon::add_breadcrumb(                          &Apache::lonhtmlcommon::add_breadcrumb(
      {href=>"javascript:backPage(document.$state,'$states{$action}[$i]')",       {href=>"javascript:backPage(document.$state,'$states{$action}[$i]')",
       text=>"$trail{$action}{$states{$action}[$i]}"});        text=>"$trail{$action}{$states{$action}[$i]}"});
                       }
                 }                  }
             }              }             
         }          }
     } 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,$action) = @_;
       my %curr_groups;
       my $namespace;
       if ($action eq 'reenable') {
           $namespace = 'deleted_groups';
       } else {
           $namespace = 'coursegroups';
       }
       %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname,
                                                      $namespace);
   
       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,$cdom,$cnum,$action,$state,$page,$startdate,
                                 $enddate,$groupname,$description,$granularity,
                                 $quota,$sectioncount,$tools,$functions,$stored,
                                 $states,$navbuttons,$gpterm,$ucgpterm,$crstype);
           } 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);
           }
       } elsif ($action eq 'delete') {
           my %stored = &retrieve_settings($cdom,$cnum,$groupname,$action);
           if ($state eq 'verify') {
               &verify_delete($r,$groupname,$state,$action,$page,$states,
                              \%stored,$crstype);
           } elsif ($state eq 'result') {
               &delete_group($r,$cdom,$cnum,$groupname,$crstype);
           }
       } elsif ($action eq 'reenable') {
           my %stored = &retrieve_settings($cdom,$cnum,$groupname,$action);
           if ($state eq 'verify') {
               &verify_reenable($r,$groupname,$state,$action,$page,$states,
                              \%stored,$crstype);
           } elsif ($state eq 'result') {
               &reenable_group($r,$cdom,$cnum,$groupname,$crstype);
         }          }
     }      }
 }  }
   
   sub verify_delete {
       my ($r,$groupname,$formname,$action,$page,$states,$stored,$crstype) = @_;
       $r->print(&Apache::lonhtmlcommon::echo_form_input([]));
       $r->print(&mt('You have requested deletion of the group [_1].'
                    ,'<i>'.$stored->{'description'}.'</i>').
                 '<br /><br />'.&mt('When a group is deleted the following occurs:').'<ul>'.
                 '<li>'.&mt('All group membership is terminated.').'</li>'.
                 '<li>'.&mt('The group ceases to be available either for viewing or for modification of group settings and membership.').'</li>');
       if ($crstype eq 'Community') {
           $r->print( '<li>'.&mt("The group folder is removed from the folder containing it - normally this is the 'Community Groups' folder which contains folders for all groups in the community.").'</li>'.
                      '</ul>'.&mt("Although a deleted group is no longer accessible, the group name used for the group will be reserved, and will not be available for assignment to a new group in the same community in the future."));
       } else { 
           $r->print( '<li>'.&mt("The group folder is removed from the folder containing it - normally this is the 'Course Groups' folder which contains folders for all groups in the course.").'</li>'.
                      '</ul>'.&mt("Although a deleted group is no longer accessible, the group name used for the group will be reserved, and will not be available for assignment to a new group in the same course in the future."));
       }
       my $prevtext = &mt('Go back');
       my $nexttext = &mt('Delete group');
       my $prev;
       if ($env{'form.refpage'} eq 'cusr')  {
           $prev = 'view';
       }
       &display_navbuttons($r,$formname,$prev,$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
   sub delete_group {
       my ($r,$cdom,$cnum,$groupname,$crstype) = @_;
       my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                              $groupname);
       my $now = time;
       my $num_users = 0;
       my $num_fail = 0;
       my $num_ok = 0;
       my @deleted;
       my @undeleted;
       my %usersettings;
       my $context = 'deletegroup';
       foreach my $key (sort(keys(%membership))) {
           if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
               my $user = $1;
               my($end,$start,$userprivs) = split(/:/,$membership{$key},3);
               if ($start != -1) {
                   $num_users ++;
                   $usersettings{$groupname.':'.$user} = $now.':-1:'.$userprivs;
                   if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
                                                           $groupname,$user,
                                                           $now,'-1',$userprivs,
                                                           '',$context)
                       eq 'ok') {
                       $num_ok ++;
                       push(@deleted,$user);
                   } else {
                       push(@undeleted,$user);
                       $num_fail ++;
                   }
               }
           }
       }
       if ($num_ok > 0) {
           my $roster_result = 
               &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum,
                                                              \%usersettings);
       }
       if ($num_fail > 0) {
           $r->print('<div class="LC_error">'
                    .&mt('Group deletion failed because deletion of [_1] out of [_2] members failed.'
                        ,$num_fail,$num_users)
                    .'</div>');
       } else {
           my ($result,$message) = 
                &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,
                                                           $groupname,'delete');
           if ($result eq 'ok') {
               my $outcome = &modify_folders($cdom,$cnum,$groupname,$crstype);
               if ($outcome eq '') {
                   $r->print('<div class="LC_success">'
                            .&mt('Group successfully deleted.')
                            .'</div>');
               } else {
                   $r->print('<div class="LC_error">');
                   if ($crstype eq 'Community') {
                       $r->print(&mt("Although the group was deleted, an error occurred when removing the group's folder from the 'Community Groups' folder: [_1]",$outcome));
                   } else {
                       $r->print(&mt("Although the group was deleted, an error occurred when removing the group's folder from the 'Course Groups' folder: [_1]",$outcome));
                   }
                   $r->print('</div>');
               }
           } else {
               $r->print('<div class="LC_error">'
                        .&mt('Group deletion failed.')
                        .'</div>');
           }
       }
       return;
   }
   
   sub reenable_folder {
       my ($cdom,$cnum,$groupname,$description,$crstype) = @_;
       my $outcome;
       my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
       my $allgrpsmap = $crspath.'group_allfolders.sequence';
       my $foldertitle;
       if ($crstype eq 'Community') {
           $foldertitle = &mt("Community Folder -[_1]",$description);
       } else {
           $foldertitle = &mt("Course Folder -[_1]",$description);
       }
       my $mapurl = $crspath.'group_folder_'.
                      $groupname.'.sequence';
       my ($errtext,$fatal)=&LONCAPA::map::mapread($allgrpsmap);
       if ($fatal) {
           $outcome='<div class="LC_error">'
                   .&mt('An error occurred when reading contents of parent folder to group:')
                   ."<br />($allgrpsmap): $errtext"
                   .'</div>';
       } else {
           my $idx=&LONCAPA::map::getresidx($mapurl);
           $LONCAPA::map::resources[$idx] = $foldertitle.':'.$mapurl.
                                            ':false:normal:res';
           $LONCAPA::map::order[1+$#LONCAPA::map::order]=$idx;
           my ($outtext,$errtext) = &LONCAPA::map::storemap($allgrpsmap,1);
           if ($errtext) {
               $outcome='<div class="LC_error">'
                       .&mt('An error occurred when saving updated parent folder to group:'
                           ,"<br />$allgrpsmap - $errtext")
                       .'</div>';
           } else {
               my ($furl,$ferr) =
                        &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
           }
       }
       return $outcome;
   }
   
   sub modify_folders {
       my ($cdom,$cnum,$groupname,$crstype) = @_;
       my ($outcome,$groupmap,$groupmapres,$map,$id,$src);
       my $navmap = Apache::lonnavmaps::navmap->new();
       if (!defined($navmap)) {
           $outcome = '<div class="LC_error">';
           if ($crstype eq 'Community') {
               $outcome .= &mt("Error reading community contents.").' '.
                      &mt("You need to re-initialize the community.");
           } else {
               $outcome .= &mt("Error reading course contents.").' '.
                      &mt("You need to re-initialize the course.");
           }
           $outcome .= '</div>';
           return $outcome;
       }
       $groupmap = '/uploaded/'.$cdom.'/'.$cnum.'/'.'group_folder_'.
                      $groupname.'.sequence';
       $groupmapres = $navmap->getResourceByUrl($groupmap);
       if ($groupmapres) {
           ($map,$id,$src)=&Apache::lonnet::decode_symb($groupmapres->symb());
       }
       undef($navmap);
       if ($map) {
           $map = '/'.$map;
           my ($errtext,$fatal) = &LONCAPA::map::mapread($map);
           if ($fatal) {
               $outcome='<div class="LC_error">'
                       .&mt('An error occurred when reading contents of parent folder to group:')
                       ."<br />($map): $errtext"
                       .'</div>';
           } else {
               my $idx = 0;
               my $grpidx;
               foreach my $item (@LONCAPA::map::order) {
                   my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$item]);
                   $url=&LONCAPA::map::qtescape($url);
                   if ($url eq $groupmap) {
                       $grpidx = $idx;
                       last;
                   } else {
                       $idx++;
                   }
               }
   
               if ($grpidx ne '') {
                   &LONCAPA::map::makezombie($LONCAPA::map::order[$grpidx]);
                   for (my $i=$grpidx;$i<$#LONCAPA::map::order;$i++) {
                       $LONCAPA::map::order[$i] = $LONCAPA::map::order[$i+1];
                   }
                   $#LONCAPA::map::order--;
                   my ($outtext,$errtext) = &LONCAPA::map::storemap($map,1);
                   if ($errtext) {
                       $outcome='<div class="LC_error">'
                               .&mt('An error occurred when saving updated parent folder to group:')
                               ."<br />$map - $errtext"
                               .'</div>';
                   } else {
                       my ($furl,$ferr) =
                           &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
                   }  
               }
           }
       }
       return $outcome;
   }
   
   sub verify_reenable {
       my ($r,$groupname,$formname,$action,$page,$states,$stored,$crstype) = @_;
       $r->print(&Apache::lonhtmlcommon::echo_form_input([]));
       $r->print(&mt('You have requested enabling the previously deleted group [_1].'
                    ,'<i>'.$stored->{'description'}.'</i>').
                 '<br /><br />'.&mt('When a deleted group is re-enabled the following occurs:').'<ul>'.
                 '<li>'.&mt('Group settings and membership at the time the group was deleted are reinstated.').'</li><li>');
       if ($crstype eq 'Community') {
           $r->print(&mt("A group folder is added to the 'Community Groups' folder which contains folders for all groups in the community."));
       } else {
           $r->print(&mt("A group folder is added to the 'Course Groups' folder which contains folders for all groups in the course."));
       }
       $r->print('</li></ul>');
       my $prevtext = &mt('Go back');
       my $nexttext = &mt('Reenable group');
       my $prev;
       if ($env{'form.refpage'} eq 'cusr')  {
           $prev = 'view';
       }
       &display_navbuttons($r,$formname,$prev,$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
   sub reenable_group {
       my ($r,$cdom,$cnum,$groupname,$crstype) = @_;
       my %groups = 
           &Apache::longroup::coursegroups($cdom,$cnum,$groupname,
                                           'deleted_groups');
       if (keys(%groups) == 0) {
           $r->print(&mt('The group [_1] was not re-enabled, because it is not a deleted group.[_2]Perhaps it has already been re-enabled?','<i>'.$groupname.'</i>'),'<br />');
           return;
       }
       my %groupinfo = 
           &Apache::longroup::get_group_settings($groups{$groupname});
       my $defstart = $groupinfo{'startdate'};
       my $defend = $groupinfo{'enddate'};
       my $showstart = &Apache::lonlocal::locallocaltime($defstart);
       my $showend;
       if ($defend == 0) {
           $showend = &mt('No end date set');
       } else {
           $showend = &Apache::lonlocal::locallocaltime($defend);
       }
       my $description = &unescape($groupinfo{'description'});
       my $num_users = 0;
       my $num_ok = 0;
       my $num_fail = 0;
       my $context = 'reenablegroup';
       my (%usersettings,@enabled,@unenabled);
       my ($result,$message) =
             &Apache::lonnet::toggle_coursegroup_status($cdom,$cnum,$groupname,
                                                        'reenable');
       if ($result eq 'ok') {
           my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                              $groupname);
           foreach my $key (sort(keys(%membership))) {
               if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                   my $user = $1;
                   my($end,$start,$userprivs) = split(/:/,$membership{$key},3);
                   if (($start == -1) && ($end == $groupinfo{'modified'})) {
                       $num_users ++;
                       $usersettings{$groupname.':'.$user} = $defend.':'.
                                                             $defstart.':'.
                                                             $userprivs;
                       if (&Apache::lonnet::modify_group_roles($cdom,$cnum,
                                                               $groupname,$user,
                                                               $defend,$defstart,
                                                               $userprivs,'',
   $context) eq 'ok') {
                           $num_ok ++;
                           push(@enabled,$user);
                       } else {
                           push(@unenabled,$user);
                           $num_fail ++;
                       }
                   }
               }
           }
           if ($num_users > 0) {
               if ($num_ok > 0) {
                   my $roster_result =
           &Apache::lonnet::modify_coursegroup_membership($cdom,$cnum,
                                                          \%usersettings);
                   if ($roster_result eq 'ok') {
                       $r->print('<div class="LC_success">'
                                .&mt('Membership reinstated for [quant,_1,user], each with start and end dates for group access set to defaults: [_2] and [_3]',$num_ok,$showstart,$showend)
                                .'</div>');
                   }
               } else {
                   $r->print('<div class="LC_error">'
                            .&mt('A problem occurred when trying to reinstate [_1] of the [_2] members of the pre-existing group.',$num_fail,$num_users)
                            .'</div>');
               }
           } else {
               $r->print('<div class="LC_info">'
                        .&mt('There were no group members to reinstate, as none were removed when the group was deleted.')
                        .'</div>');
           }
           my $outcome = &reenable_folder($cdom,$cnum,$groupname,$description,$crstype);
           if ($outcome eq '') {
               $r->print('<div class="LC_success">'
                        .&mt('Group successfully re-enabled.')
                        .'</div>');
           } else {
               $r->print('<div class="LC_error">');
               if ($crstype eq 'Community') {
                   $r->print(&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Community Groups' folder: [_1]",$outcome));
               } else {
                   $r->print(&mt("Although the group was re-enabled, an error occurred when adding the group's folder to the 'Course Groups' folder: [_1]",$outcome));
               }
               $r->print('</div>');
           }
       } else {
           $r->print('<div class="LC_error">'
                    .&mt('Re-enabling group failed.')
                    .'</div>');
       }
       return;
   }
   
 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>  
 <title>$title</title>  
 <script type="text/javascript">  
 $jscript  
 </script>  
 </head>  
 $bodytag  
 <form method="post" name="$state">  <form method="post" name="$state">
   
 END  END
Line 517  END Line 1474  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 1482  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 1519  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,$portpath,$numfiles,$numdirs) = @_;
       my $dirptr=16384;
       my @dir_list=&Apache::portfolio::get_dir_list($portpath,undef,$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) {
                   $portpath .= '/'.$filename;
                   $$numdirs ++;
                   &group_files($group,$portpath,$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 %lt = &Apache::lonlocal::texthash (
 sub first_creation_form {                                            active => 'active',
     my ($r,$cdom,$cnum,$tabcol,$formname,$functions,$sectioncount) = @_;                                            previous => 'previous',
     my %lt = &Apache::lonlocal::texthash(                                            future => 'future',
         'gmem' => 'Group membership options',  
         'picr' => 'Pick the criteria to use to build a list of course users '.  
                   'from which you will select members of the new group',     
         'gdat' => 'Group open and close dates',  
         'sten' => 'Set a start date/time and end date/time for the group',  
         'acty' => 'Access types',  
         'coro' => 'Course roles',  
         'cose' => 'Course sections',  
         'gfun' => 'Group functionality',  
     );      );
       my %membercounts = (  
                            active => 0,
                            previous => 0,
                            future => 0,
                          );
       my $totalmembers = 0;
       foreach my $member (keys %memberhash) {
           $totalmembers ++;
           my ($end,$start) = split(/:/,$memberhash{$member});
           unless ($start == -1) {
               if (($end!=0) && ($end<$now)) {
                   $membercounts{previous} ++;
               } elsif (($start!=0) && ($start>$now)) {
                   $membercounts{future} ++;
               } else {
                   $membercounts{active} ++;
               }
           }
       }
       if ($totalmembers == 0) {
           $$group_info{$group}{'totalmembers'} = 'None';
       } else {
           foreach my $type ('active','previous','future') {
               $$group_info{$group}{'totalmembers'} .= 
                  &open_list_window($group,$type,$membercounts{$type},$lt{$type});
           }
       }
       return 'ok';
   }
   
     my %status_types = (  sub open_list_window {
                    active => &mt('Currently has access'),      my ($group,$status,$count,$text) = @_;
                    previous => &mt('Previously had access'),      my $entry;
                    future => &mt('Will have future access'),      if ($count > 0) {
                    );          $entry = '<span class="LC_nobreak"><a href="javascript:openGroupRoster('.
                    "'$group','$status'".')">'.$text.'</a>&nbsp;-&nbsp;'.$count.
                    '</span><br />';
       } else {
           $entry = '<span class="LC_nobreak">'.$text.'&nbsp;-&nbsp;'.$count.'</span><br />';
       }
       return $entry;
   }
   
     my @roles = ('st','cc','in','ta','ep','cr');  
   
     my $starttime = time;  sub general_settings_form {
     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx      my ($r,$cdom,$cnum,$action,$formname,$page,$functions,$tools,
     my ($start_table,$end_table) = &date_setting_table          $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
                                     ($starttime,$endtime,$formname);          $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,$cdom,$cnum,$action,$formname,$sectioncount,3,
                               $gpterm,$ucgpterm,$crstype);
           $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,$functions,$crstype);
           &mapping_options($r,$action,$formname,$page,$sectioncount,
                            $states,$stored,$navbuttons,4,5,
    $gpterm,$ucgpterm,$crstype,$cdom,$cnum);
           $nexttext = $$navbuttons{'mose'};
       }
       $prevtext = $$navbuttons{'gtpp'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       return;
   }
   
     my @sections = ();  sub groupsettings_options {
     my $section_sel = '';      my ($r,$functions,$action,$formname,$stored,$image,$gpterm,
     my $numvisible = 4;          $ucgpterm,$crstype) = @_;
       my %lt = &Apache::lonlocal::texthash(
           'gdat' => "Group access start and end dates",
           'gnde' => "Group name, title and available collaborative tools",
           'desc' => 'Group Title',
           'func' => 'Collaborative Tools',
           'gnam' => 'Group Name',
           'lett' => 'Letters, numbers and underscore only',
           'doyo' => 'Different subsets of the chosen collaborative tools '.
                     'for different group members?',
           'gran' => 'Granularity',
           'dquo' => 'Disk quota',
       );
       my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored);
       $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'gnde'}));
   
     @sections = sort {$a cmp $b} keys(%{$sectioncount});      # Group Name
     if (@sections > 0) {      $r->print(&Apache::lonhtmlcommon::start_pick_box()
         unshift(@sections,'_all'); # Put 'all' at the front of the list               .&Apache::lonhtmlcommon::row_title($lt{'gnam'})
         if (@sections < 4) {      );
             $numvisible = @sections;      if ($action eq 'create') {
         }          $r->print('<input type="text" name="groupname" size="25" />'
         foreach (@sections) {                   .' <span class="LC_nobreak">('
             if ($_ eq '_all') {                   .$lt{'lett'}.')</span>'
                 $section_sel .= '  <option value="'.$_.'" />all sections'."\n";          );
             } else {      } else {
                 $section_sel .= '  <option value="'.$_.'" />'.$_."\n";          $r->print('<input type="hidden" name="groupname" value="'.
             }                           $env{'form.groupname'}.'" />'.$env{'form.groupname'});
         }  
     }      }
       $r->print(&Apache::lonhtmlcommon::row_closure());
   
     $r->print(<<"END");      # Group Title
  <br />      $r->print(&Apache::lonhtmlcommon::row_title($lt{'desc'})
  <table width="100%" cellpadding="0" cellspacing="0" border="0">               .'<input type="text" name="description" size="40" value="" />'
    <tr bgcolor="$tabcol">               .&Apache::lonhtmlcommon::row_closure()
      <td>&nbsp;</td>      );
      <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step1.gif"   
          valign="bottom">&nbsp;&nbsp;</nobr>      # Collaborative Tools
      </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>  
       <tr>  
       <tr>  
        <td><b>Description:</b></td>  
        <td colspan="5"><input type="text" name="description" size="40" />  
        </td>  
       <tr>  
       <tr>  
        <td><b>Functionality:</b></td>  
 END  
     my $numitems = keys(%{$functions});      my $numitems = keys(%{$functions});
     my $halfnum = int($numitems/2);      my $halfnum = int($numitems/2);
     my $remnum = $numitems%2;      my $remnum = $numitems%2;
     if ($remnum) {      if ($remnum) {
         $halfnum ++;          $halfnum ++;
     }      }
     my @allfunctions = sort (keys (%{$functions}));      my @allfunctions = sort(keys (%{$functions}));
     for (my $i=0; $i<$halfnum; $i++) {  
         $r->print('<td><input type="checkbox" name="tool" value="'.      $r->print(&Apache::lonhtmlcommon::row_title($lt{'func'})
                   $allfunctions[$i].'" />&nbsp;'.               .'<div>'
                    $$functions{$allfunctions[$i]}.'</td>               .'<input type="button" value="'.&mt('check all').'"'
                    <td>&nbsp;</td><td>&nbsp;</td>');               .' onclick="javascript:checkAll(document.'.$formname.'.tool)" />'
     }               .'&nbsp;<input type="button" value="'.&mt('uncheck all').'"'
     $r->print('<td><input type="button" value="check all" '.               .' onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />'
               'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.               .'</div>'
               '</td></tr><tr><td>&nbsp;</td>');               .'<table cellpadding="5px"><tr>' # FIXME Get rid of inflexible table (-> float)
     for (my $j=$halfnum; $j<@allfunctions; $j++) {      );
         $r->print('<td><input type="checkbox" name="tool" value="'.      for (my $i=0; $i<@allfunctions; $i++) {
                   $allfunctions[$j].'" />&nbsp;'.          $r->print('<td><label><span class="LC_nobreak">'
                   $$functions{$allfunctions[$j]}.'</td>                   .'<input type="checkbox" name="tool" value="'
                   <td>&nbsp;</td><td>&nbsp;</td>');                   .$allfunctions[$i].'" /> '
                    .&mt($$functions{$allfunctions[$i]})
                    .'</span></label></td>'
           );
           if ($i == $halfnum - 1) {
               $r->print('</tr><tr>');
           }
     }      }
     if ($remnum) {      $r->print('</tr></table>'
         $r->print('<td>&nbsp;</td>');               .&Apache::lonhtmlcommon::row_closure()
       );
   
       # Granularity
       $r->print(&Apache::lonhtmlcommon::row_title($lt{'gran'})
                .$lt{'doyo'}.'<br />'
                .'<label>'
                .'<input type="radio" name="granularity" value="Yes" />'.&mt('Yes')
                .'</label>&nbsp;<label>'
                .'<input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No')
                .'</label>'
       );
       if ($action eq 'modify') {
           $r->print(' <span class="LC_nobreak">('
                    .&mt('Currently set to [_1].'
                        ,'"'.&mt($$stored{'granularity'}).'"')
                    .')</span>'
           );
     }      }
     $r->print(<<"END");       $r->print(&Apache::lonhtmlcommon::row_closure());
        <td>  
         <input type="button" value="uncheck all"       # Disk Quota
           onclick="javascript:uncheckAll(document.$formname.tool)" />      $r->print(&Apache::lonhtmlcommon::row_title($lt{'dquo'}));
        </td>      if ($action eq 'create') {
       </tr>          $r->print('<span class="LC_info">'
       <tr>                   .&mt('If you enable the group portfolio for the '.$gpterm
        <td><b>Granularity:</b></td>                       .', allocate a disk quota.')
        <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>                   .'</span>'
       </tr>           );
      </table>      } else {
     </td>          $r->print(&mt('Quota allocated to group portfolio:'));
    </tr>      } 
    <tr>      $r->print(' '.&mt('[_1] Mb','<input type="text" name="quota" size="4" />'));
     <td colspan="4">&nbsp;</td>      if ($action eq 'create') {
    </tr>          $r->print('<br />'
    <tr bgcolor="$tabcol">                   .&mt('A total of [_1] Mb can be divided amongst all '.$gpterm.'s in the '
     <td>&nbsp;</td>                       .lc($crstype).', and [_2] Mb are currently unallocated.'
     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step2.gif"                        ,$crsquota,sprintf("%.2f",$freespace))
         valign="bottom">&nbsp;&nbsp;</nobr>                   );
     </td>      } else {
     <td align="left"><nobr>          $r->print('&nbsp;&nbsp;('.&mt('The quota is currently [_1] Mb',
       <font face="arial,helvetica,sans-serif"><b>Start and end dates for group                                        $$stored{'quota'}).').');
                                                   access</b></font></nobr>  
     </td>          $r->print('<br />'
     <td width="100%">&nbsp;</td>                   .&mt('The quota can be increased to [_1] Mb, '
    </tr>                   .'by adding all unallocated space for '.$gpterm.'s in the '.lc($crstype).'.'
    <tr>                    ,sprintf("%.2f",$maxposs)));
     <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>  
        <td><b>$lt{'acty'}</b></td>  
        <td>&nbsp;</td>  
        <td><b>$lt{'coro'}</b></td>  
 END  
     if (@sections >0) {  
          $r->print('  
        <td>&nbsp;</td>  
        <td><b>'.$lt{'cose'}.'</b></td>  
        <td>&nbsp;</td>');  
     }      }
     $r->print('</tr><tr>');      $r->print(&Apache::lonhtmlcommon::row_closure(1));
   
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
   
       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,$cdom,$cnum,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm,$crstype)=@_;
       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 course users from which you will select members of the new group.',
                   'pica' => 'Pick the criteria to use to build a list of course users from which you will select 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' => 'Course roles',
                   'cose' => 'Course sections',
                );
       if ($crstype eq 'Community') {
           $lt{'picr'} = &mt('Pick the criteria to use to build a list of community participants from which you will select ');
           $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','<i>','</i>');
           $lt{'coro'} = &mt('Community roles');
           $lt{'cose'} = &mt('Community sections');
       } else {
           $lt{'asub'} = &mt('A subsequent step will also allow you to specify automatic adding/dropping of group members triggered by specified user role and section [_1]changes[_2] in the course.','<i>','</i>');
       }
       my %status_types = (
                      active => &mt('Currently has access'),
                      previous => &mt('Previously had access'),
                      future => &mt('Will have future access'),
                      );
   
       my @roles = ('st');
       if ($crstype eq 'Community') {
           push(@roles,'co');
       } else {
           push(@roles,'cc');
       }
       push (@roles,('in','ta','ep','ad','cr'));
   
       my @sections = keys(%{$sectioncount});
   
       $r->print(&Apache::lonhtmlcommon::topic_bar($image,$lt{'pipa'}).'
        <b>'.$lt{'gmem'}.'</b><br />');
       if ($action eq 'create') {
           $r->print($lt{'picr'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'});
       } else {
           $r->print($lt{'pica'});
       }
       $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,undef,undef,1,$cdom,$cnum));
     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;  
         }          }
     }      }
       my $output = '
           <select name="'.$elementname.'" multiple="multiple" size="'.$numvisible.'">
             '.$section_sel.'
           </select>';
       return $output;
   }
   
   sub access_date_settings {
       my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_;
       my $sten = &mt("Default start and end dates for $gpterm access");
       my $starttime = time;
       my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
       if ($action eq 'modify') {
           $starttime = $$stored{'startdate'};
           unless ($$stored{'enddate'} == 0) {
               $endtime = $$stored{'enddate'};
           }
       }
       my ($table) = &date_setting_table($starttime,$endtime,$formname);
       $r->print(&Apache::lonhtmlcommon::topic_bar($image,$sten).'
       '.$table.'
       ');
       return;
   }
   
   sub choose_members_form {
       my ($r,$cdom,$cnum,$action,$formname,$page,$groupname,$description,
           $granularity,$quota,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
           $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
           $gpterm,$ucgpterm,$crstype) = @_;
       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) {      if ($earlyout) {
         $r->print('<table border="0" cellpadding="2" cellspacing="2">   $r->print($earlyout);
  <tr>          &display_navbuttons($r,$formname,$$states{$action}[$page-1],
   <td>&nbsp;</td>                             $$navbuttons{'gtps'});
   <td>'.$earlyout.'</td>  
  </tr>  
  <tr>  
   <td colspan="2">&nbsp;</td>  
  </tr>  
  <tr>  
   <td>&nbsp;</td>  
   <td align="left">  
    <input type="button" name="previous" value = "Go to previous page"  
     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>  
   </td>  
  </tr>  
 </table>  
         ');  
         return;          return;
     }      } 
     my $rowColor1 = "#dddddd";      my ($specimg,$memimg);
     my $rowColor2 = "#eeeeee";  
     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('  
 <table cellspacing="1" cellpadding="4">  
  <tr bgcolor="'.$tabcol.'" align="center">  
   <td><b>Group Name</b></td>  
   <td><b>Description</b></td>  
   <td><b>Group Functionality</b></td>  
   <td><b>Default access dates</b></td>  
  </tr>  
  <tr bgcolor="'.$rowColor2.'">  
   <td valign="top"><small>'.$groupname.'</small></td>  
   <td valign="top"><small>'.$description.'</small></td>  
   <td>  
 ');  
     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,
                             $functions,$crstype);
       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;');
       } elsif ($prevtext) {
           $r->print('
         <input type="button" name="previous" value = "'.$prevtext.'"
       onclick="javascript:history.back()"/>
      &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) = @_;
                 if ($i==$rowcell) {  
                     $r->print('</tr><tr>');      my %lt = &Apache::lonlocal::texthash(
                 }          grna => 'Group Name',
             }          desc => 'Group Title',
             $r->print('<td><small>'.$$functions{$available[$i]}.          grfn => "Collaborative Tools",
                                           '</small></td><td>&nbsp;</td>');          gran => 'Granularity',
         }          quot => 'File quota',
         if ((@available > 3) && (@available%2)) {          dfac => 'Default access dates',
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');          ygrs => "Your group selections - ",
         }          tfwa => "The following settings will apply to the group:",
         $r->print('</tr></table><br />');          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 (@unavailable > 0) {      if ($action eq 'create') {
         $r->print('<small><b>Unavailable:</b></small>          $r->print('
                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');  <div><span style="font-size: larger">'.$lt{'ygrs'}.'</span>
         my $rowcell = int(@unavailable/2) + @unavailable%2;  <br />'.$lt{'tfwa'}.'
         for (my $j=0; $j<@unavailable; $j++) {  </div>');
             if (@unavailable > 3) {      }
                 if ($j==$rowcell) {      $r->print(&Apache::loncommon::start_data_table('LC_course_group_status').
                     $r->print('</tr><tr>');        &Apache::loncommon::start_data_table_header_row());
                 }      $r->print('
             }    <th>'.$lt{'grna'}.'</th>
             $r->print('<td><small>'.$$functions{$unavailable[$j]}.    <th>'.$lt{'desc'}.'</th>
                                               '</small></td><td>&nbsp;</td>');    <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('<b>'.&mt('Available for assignment to members:').'</b>');
           $r->print('<ul>');
           for (my $i=0; $i<@{$available}; $i++) {
               $r->print('<li>'.&mt($$functions{$$available[$i]}).'</li>');
         }          }
         if ((@unavailable > 3) && (@unavailable%2)) {          $r->print('</ul>');
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');      }
   
       if (@{$unavailable} > 0) {
           $r->print('<b>'.&mt('Unavailable for assignment:').'</b>');
           $r->print('<ul>');
           for (my $i=0; $i<@{$unavailable}; $i++) {
               $r->print('<li>'.&mt($$functions{$$unavailable[$i]}).'</li>');
         }          }
         $r->print('</tr></table>');          $r->print('</ul>');
     }      }
   
       my $quota_text=&mt('[_1] Mb',$quota);
       my $granu_text=&mt($granularity);
     $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> $granu_text</td>
       <b>End date:</b> $showend</small>    <td valign="top">$quota_text</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) {      }
 ');      $r->print(&Apache::lonhtmlcommon::topic_bar($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>'.$lt{'setf'}.'</legend>
        onclick="javascript:checkAll(document.$formname.member)" />        <span class="LC_nobreak">
       &nbsp;&nbsp;        <input type="button" value="'.&mt('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="'.&mt('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>');        </span>
        </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"><span class="LC_nobreak"><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('</span></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 2152  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"><span class="LC_nobreak">'.
                                 '&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 2184  END
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');                            $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         }                          }
                     }                      }
                     $r->print('</small></td>');                      $r->print('</span></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,$functions,$crstype) = @_;
       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:', 
       );
       if ($crstype eq 'Community') {
           $lt{'thes'} = &mt('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 community '); 
       }
       my $totaloptionalprivs = 0;
       foreach my $tool (@{$tools}) {
           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (!exists($$fixedprivs{$tool}{$priv})) {
                   $totaloptionalprivs ++;
               }
           }
       }
       $r->print(&Apache::lonhtmlcommon::topic_bar($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><span class="LC_nobreak"><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</span></label><br />
   <td valign="middle" align="left">  <label><span class="LC_nobreak"><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</span></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,$functions);
   <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,$functions) = @_;
                $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'));
       my @tableHeader;
       foreach my $key (sort(keys(%{$functions}))){
           push (@tableHeader,&mt($functions->{$key}));
       }   
    $r->print(join('</td><td class="LC_groups_functionality">', @tableHeader));
       $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.'" />'
                            .'<span class="LC_nobreak">'.&mt($$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 .= '</span>';
               } else {
                   $privcount++;
                   if ($privcount == 3) {
                       $dynamic .= '</tr>
                                    <tr>'."\n";
                   }
                   $dynamic .= '<td><span class="LC_nobreak"><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.&mt($$toolprivs{$tool}{$priv}).'</label></span></td>'."\n";
               }
           }
           if ($privcount == 0) {
               $dynamic .= '<td>'.&mt('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 />
   ');
       $r->print(&Apache::lonhtmlcommon::topic_bar(1,$lt{'grse'}));
       &print_current_settings($r,$action,$functions,$startdate,$enddate,
       $groupname,$description,$granularity,$quota,
       \@available,\@unavailable,$gpterm,$ucgpterm);
       $r->print(&Apache::lonhtmlcommon::topic_bar(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>
         <span class="LC_nobreak">
          <fieldset><legend>'.$lt{'curf'}.'</legend>
          <input type="button" value="'.&mt('check all').'"
          onclick="javascript:checkAllTools(document.'.$formname.')" />
          &nbsp;&nbsp;
          <input type="button" value="'.&mt('uncheck all').'"
           onclick="javascript:uncheckAllTools(document.'.$formname.')" />
         </fieldset>
        </span>
       </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"><span class="LC_nobreak"><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('</span></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('<span class="LC_nobreak"><label>'. 
      '<input type="checkbox" name="reenable" value="'.$user.'" />'.
      $lt{'reen'}.'</label></span><br />');
                   } elsif ($$current{$user}{changestate} eq 'expire') {
                       $r->print('<span class="LC_nobreak"><label>'.
      '<input type="checkbox" name="expire" value="'.$user.'" />'.
      $lt{'expi'}.'</label></span><br />');
                   } elsif ($$current{$user}{changestate} eq 'activate') {
                       $r->print('<span class="LC_nobreak"><label>'.
      '<input type="checkbox" name="activate" value="'.$user.'" />'.
      $lt{'acti'}.'</label></span><br />');
                   }
                   $r->print('<span class="LC_nobreak"><label>'.
      '<input type="checkbox" name="deletion" value="'.$user.'" />'.
      $lt{'dele'}.'</label></span>');
                   if ($specificity eq 'Yes') {
                       $r->print('<br /><span class="LC_nobreak"><label>'.
      '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
      '</label></span>');
                   }
                   $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"><span class="LC_nobreak">'.
                                     '&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('</span></td>');
                   }
                   if ($addtools) {
                       $r->print('<td align="left">');
                       if ($granularity eq 'Yes') {
                           foreach my $tool (@{$$current{$user}{newtools}}) {
                               $r->print('<span class="LC_nobreak"><label><input type="checkbox"
                                             name="user_'.$tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</label></span>&nbsp;&nbsp;&nbsp;');
                           }
                       } else {
                           foreach my $tool (@{$$current{$user}{newtools}}) {
                               $r->print('<span class="LC_nobreak"><input type="hidden" 
                                             name="user_'. $tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</span>&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('  }
 <script type="text/javascript">  
 function checkAllTools(formname) {  sub check_uncheck_buttons {
       my ($r,$formname,$field,$title,$colspan) = @_;
       $r->print('
        <td '.$colspan.'>
          <fieldset>
          <legend>'.$title.'</legend>
         <span class="LC_nobreak">
          <input type="button" value="'.&mt('check all').'"
          onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
          &nbsp;&nbsp;
          <input type="button" value="'.&mt('uncheck all').'"
          onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
         </span>
          </fieldset>
        </td>
 ');  ');
         foreach my $tool (sort(keys(%showboxes))) {  }
             foreach my $priv (@{$showboxes{$tool}}) {  
                 $r->print('  checkAll(formname.userpriv_'.$priv.');'."\n");  
   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'};
       }
       $r->print(&Apache::lonhtmlcommon::topic_bar(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'}};
         }          }
         $r->print('      }
       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 />');
       }
       
       $r->print(&Apache::lonhtmlcommon::topic_bar(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,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,$groupname,
           $description,$granularity,$quota,$sectioncount,$tools,$functions,
           $stored,$states,$navbuttons,$gpterm,$ucgpterm,$crstype)=@_;
       $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,$cdom,$cnum,$action,$formname,$sectioncount,1,$gpterm,
                           $ucgpterm,$crstype);
       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'};
       }
   
       $r->print(&Apache::lonhtmlcommon::topic_bar(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,$cdom,$cnum);
       }
       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">
   function checkAllTools(formname) {
   ');
                   foreach my $tool (sort(keys(%{$showboxes}))) {
                       foreach my $priv (@{$$showboxes{$tool}}) {
                           $r->print('  checkAll(formname.'.$prefix.$priv.');'."\n");
                       }
                   }
                   $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.',
   </th>              'ifex' => 'If previously expired members are being re-enabled, or '.
   <td width="100%">&nbsp;</td>                        'if access for future members is being activated now, '.
  </tr>                        'previously set privileges will be preserved.',
  <tr>              'asno' => 'As no group members are being added, '.
   <td colspan="4">&nbsp;</td>                        'there are no specific user privileges to set.',
  </tr>              'asng' => 'As no group tools will be made available to users, '.
  <tr>                        'there are no specific user privileges to set.',
   <td>&nbsp;</td>              'nogm' => 'No group member privileges to display or set, '.
   <td colspan="3">                        'as you have not indicated that you will be activating,'.
 END                        ' re-enabling, changing privileges, or adding/removing '.
     if ($env{'form.specificity'} eq 'Yes') {                        'tools for any current members.',
         $r->print('              'full' => 'Fullname',
    <table border="0" cellspacing="2" cellpadding="2" border="0">              'user' => 'Username',
               '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('<fieldset><legend>'.&mt($tool).'</legend>');
     <th><b>Username</th>                              $r->print('<table><tr>');
     <th>Domain</th>                              my $privcount = 0;
     <th colspan="$numtools">Additional Privileges</th>                              foreach my $priv (@{$showboxes{$tool}}) {
   </tr>                                  $privcount ++;
 END                                  if (($privcount == @{$showboxes{$tool}}) && 
     }                                      ($privcount > 1)) {
     if ($env{'form.specificity'} eq 'Yes') {                                      if ($privcount%$numcells) {
         &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,                                          $r->print('<td colspan="'.$colspan.'">');
                              $usertools,$toolprivs,$fixedprivs,$userdata,$idx);                                      } else {
     }                                          $r->print('<td>');
     if ($env{'form.specificity'} eq 'Yes') {                                      }
         $r->print('</td>');                                  } else {
         $r->print(&Apache::lonhtmlcommon::end_pick_box());                                      $r->print('<td>');
         $r->print('<td>&nbsp;</td>                                  }
                <td>&nbsp;</td><td valign="top">');                                  $r->print(
         my @toolboxes = sort(keys(%showboxes));   '<fieldset><legend>'.&mt($$toolprivs{$tool}{$priv}).'</legend>'
         foreach my $tool (@{$tools}) {  .'<span class="LC_nobreak">'
             if (@{$showboxes{$tool}} > 0) {   .' <input type="button" value="'.&mt('check all').'"'
                 $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.  .' onclick="javascript:checkAll(document.'.$formname.'.userpriv_'.$priv.')" />'
                       '"><th>'.$tool.'</th></tr>');  .'&nbsp;'
                 foreach my $priv (@{$showboxes{$tool}}) {  .'<input type="button" value="'.&mt('uncheck all').'"'
                     $r->print(qq|  .' onclick="javascript:uncheckAll(document.'.$formname.'.userpriv_'.$priv.')" />'
        <tr><td>  .'</span></fieldset><br />'
        <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>                                  );
        <input type="button" value="check all"                                  $r->print('</td>');
          onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />                                  if ($privcount < @{$showboxes{$tool}}) {
        &nbsp;                                       if (@{$showboxes{$tool}} > 2) {
        <input type="button" value="uncheck all"                                          if ($privcount%$numcells == 0) {
         onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />                                              $r->print('</tr><tr>');
       </nobr></fieldset></td></tr>|);                                          }
                 }                                      } else {
                 $r->print('</table><br /><br />');                                          $r->print('<tr></tr>');
             }                                      }
         }                                  }
         $r->print('</td></tr></table>');                              }
     } else {                              $r->print('</tr></table></fieldset></td><td>&nbsp;</td>');
         $r->print(&Apache::lonhtmlcommon::start_pick_box());                          }
         $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>'.  
                   '</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>');  
             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,$crstype);
       }
     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('<div class="LC_warning">'
                    .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm
                    .' contained invalid characters, so it has been set to 0 Mb. You can change this by'
                    .' modifying the '.$gpterm.' settings.')
                    .'</div>');
       }
       if ($quota > $maxposs) {
           $quota = $maxposs;
           $r->print('<div class="LC_warning">'
                    .&mt('The value you entered for the quota for the group portfolio in this '.$gpterm
                    .' exceeded the maximum possible value, so it has been set to [_1] Mb '
                    .'(the maximum possible value).',sprintf("%.2f",$maxposs))
                    .'</div>');
       }
       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 eq 'ok') {
                   $r->print('<div class="LC_success">'
                            .&mt($ucgpterm.' [_1] was created.','<i>'.$groupname.'</i>')
                            .'</div>');
               } else {
                   $r->print('<div class="LC_error">'
                            .&mt('A problem occurred when creating folders for the new '.$gpterm.' [_1]:'
                                ,'<i>'.$groupname.'</i>')
                            .'<br />'.$result
                            .'</div>');
               }
           } 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,$error);
                   if (defined($navmap)) {
                       $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);
                           # modify parameter
                           if ($outcome eq 'ok') {
                               $navmap = Apache::lonnavmaps::navmap->new();
                               if (defined($navmap)) {
                                   my $parm_result = &parm_setter($navmap,$cdom,$boardsmap,
                                                                  $groupname);
                                   if ($parm_result) {
                                       $error = &mt('An error occurred while setting parameters '
                                                .'for Discussion Boards folder: '
                                                .'[_1]',$parm_result);
                                   } else {
                                       $r->print('<div class="LC_success">'.
                                                 &mt('Discussion Boards Folder created.')
                                                 .'</div>');
                                   }
                                   undef($navmap);
                               } else {
                                   if ($crstype eq 'Community') {
                                       $error = &mt("An error occurred while setting parameters '.
                                                'for Discussion Boards folder: '.
                                                'Could not retrieve community information");
                                   } else {
                                       $error = &mt("An error occurred while setting parameters '.
                                                'for Discussion Boards folder: '.
                                                'Could not retrieve course information");
                                   }
                               }
                           } else {
                               $r->print($outcome);
                           }
                       }
                   } else {
                       $error = &mt("An error occurred while retrieving the contents of the group's folder.").'<br />';
                       if ($crstype eq 'Community') {
                           $error .= &mt("You need to re-initialize the community.");
   
                       } else {
                           $error .= &mt("You need to re-initialize the course.");
                       }
                   }
                   if ($error ne '') {
                       $r->print('<div class="LC_error">'.$error.'</div>');
                   }
               }
               $r->print('<div class="LC_success">'
                        .&mt($ucgpterm.' [_1] was updated.','<i>'.$groupname.'</i>')
                        .'</div>');
           }
       } else {
           my %actiontype = (
                             'create' => 'creating',
                             'modify' => 'modifying',
                            );
           &Apache::lonnet::logthis("Failed to store $gpterm $groupname ".
                                    'in '.lc($crstype).': '.$cnum.
                                    ' in domain: '.$cdom);
           $r->print('<div class="LC_error">'
                    .&mt('An error occurred when [_1] the '.$gpterm.'. '
                    .'Please try again.',$actiontype{$action})
                    .'</div>');
       }
       return $result;
   }
   
   sub process_membership {
       my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,
           $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg,
           $gpterm,$ucgpterm,$crstype)=@_;
       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 = ();
       my $context = 'processgroupmembership';
   
     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 3389  $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},'',$context) 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','','',$context)
                                                            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},'',$context) 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('<div class="LC_error">'
         if (@added > 0) {                       .&mt("The following users could not be $type, because an error occurred:")
             $r->print('Users were added with following privileges:<br />');                       .'</div>');
             foreach my $user (@added) {              foreach my $user (@{$failed{$type}}) {
                 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('<div class="LC_success">'
                    .&mt($ucgpterm.' membership list updated.')
                    .'</div>');
    $r->print('<p class="LC_info">');
           if ($crstype eq 'Community') {
               $r->print(&mt("Any currently logged in community 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.'
                        ,'<i>'.$groupname.'</i>'));
   
           } else {  
               $r->print(&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.'
                        ,'<i>'.$groupname.'</i>'));
         }           } 
           $r->print('</p>');
     } else {      } else {
         &Apache::lonnet::logthis('Failed to create group '.$groupname.           $r->print('<div class="LC_error">'
                                  'in course: '.$cnum.' in domain: '.$cdom);                   .&mt("An error occurred while updating the $gpterm membership list:")
                    .'<br />'.$roster_result
                    .'</div>');
       }
       return;
   }
   
   sub mapping_options {
       my ($r,$action,$formname,$page,$sectioncount,$states,$stored,
           $navbuttons,$img1,$img2,$gpterm,$ucgpterm,$crstype,$cdom,$cnum) = @_;
       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",
           '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,$cdom,$cnum,
                         $action);
       return;
   }
   
         $r->print('An error occurred when creating the new group. '.  sub automapping {
                                                       'Please try again.');      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'};
       }
       $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'endi'}).'
       <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br /><br />
      <span class="LC_nobreak">'.$$lt{'auad'}.':&nbsp;
       <label><input type="radio" name="autoadd" value="on" />'.&mt('on').'&nbsp;&nbsp;</label><label><input type="radio" name="autoadd" value="off" checked="checked" />'.&mt('off').'</label>');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.&mt('Currently set to [_1].','<b>'.$$lt{$add}.'</b>').')');
     }      }
       $r->print('
       </span><br />
       <span class="LC_nobreak">'.$$lt{'auex'}.':&nbsp;
       <label><input type="radio" name="autodrop" value="on" />'.&mt('on').'&nbsp;&nbsp;</label><label><input type="radio" name="autodrop" value="off" checked="checked" />'.&mt('off').'</label>');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.&mt('Currently set to [_1].','<b>'.$$lt{$drop}.'</b>').')');
       }
       $r->print('</span><br /><br />'.$$lt{'mapr'});
   }
   
   sub mapping_settings {
       my ($r,$sectioncount,$lt,$stored,$image,$crstype,$cdom,$cnum,$action) = @_;
       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 {
           @sections = ('all','none');
       }
       $r->print(&Apache::lonhtmlcommon::topic_bar($image,$$lt{'pirs'}));
       my @roles = &standard_roles($crstype);
       my %customroles = &Apache::lonhtmlcommon::course_custom_roles($cdom,$cnum);
       $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 $roletitle=&Apache::lonnet::plaintext($role,$crstype);
           $r->print(&print_autorole_item($role,$roletitle,\@sections));
       }
       my @customs;
       foreach my $role (sort(keys(%customroles))) {
           my ($roletitle) = ($role =~ m|^cr/[^/]+/[^/]+/(.+)$|);
           push (@customs,$role);
           $r->print(&print_autorole_item($role,$roletitle,\@sections));
       }
       if ($action eq 'modify') {
           foreach my $role (@{$$stored{'autorole'}}) {
               if ((!grep(/^\Q$role\E$/,@customs)) && 
                   (!grep(/^\Q$role\E$/,@roles))) {
                   my $roletitle;
                   if ($role =~ /^cr/) {
                       ($roletitle) = ($role =~ m|_([^_]+)$|);
                   } else {
                       $roletitle = &Apache::lonnet::plaintext($role,$crstype);
                   }
                   $r->print(&print_autorole_item($role,$roletitle,\@sections));
               }
           }
       }
       $r->print(&Apache::loncommon::end_data_table());
     return;      return;
 }  }
   
 sub member_privs_entries {  sub print_autorole_item {
     my ($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,$usertools,$toolprivs,      my ($role,$roletitle,$sections) = @_;
                                               $fixedprivs,$userdata,$idx) = @_;      my $sections_sel;
     my $rowColor;      if (@{$sections} > 0) {
     my $rowNum = 0;          if (($role eq 'cc') || ($role eq 'co')) {
     foreach my $member (@{$members}) {              $sections_sel = '<td align="right">'.
         my ($uname,$udom) = split(/:/,$member);                              &mt('all sections').'<input type="hidden" '.
         if ($rowNum %2 == 1) {                              'name="sec_'.$role.'" value="all" /></td>';
             $rowColor = $rowColor1;  
         } else {          } else {
             $rowColor = $rowColor2;              $sections_sel='<td align="right">'.
                             &sections_selection($sections,'sec_'.$role).
                             '</td>';
         }          }
         $r->print('<tr bgcolor="'.$rowColor.'">      }
                 <td>'.$$userdata{$member}[$$idx{fullname}].'</td>      my $output = &Apache::loncommon::start_data_table_row().
                    '<td><input type="checkbox" '.
                    'name="autorole" value="'.$role.'" />'.
                    '</td><td>'.$roletitle.'</td>'.$sections_sel.
                    &Apache::loncommon::end_data_table_row();
       return $output;
   } 
   
   sub standard_roles {
       my ($crstype) = @_;
       my @roles = qw(in ta ep ad st);
       if ($crstype eq 'Community') {
           unshift(@roles,'co');
       } else {
           unshift(@roles,'cc');
       }
       return @roles;
   }
   
   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;
   }
   
   sub member_privs_entries {
       my ($r,$usertools,$toolprivs,$fixedprivs,$userdata,$idx,$showtools,
    $defprivs,$excluded) = @_;
       foreach my $user (sort(keys(%{$usertools}))) {
           if (defined($excluded)) {
               if (ref($excluded) eq 'ARRAY') {
                   if (grep/^$user$/,@{$excluded}) {
                       next;
                   }
               }
           }
           my ($uname,$udom) = split(/:/,$user);
           $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><span class="LC_nobreak"><label><input type="checkbox" '.
                                  'name="userpriv_'.$priv.'" value="'.$user.'"';
                           if (grep/^\Q$priv\E$/,@{$defprivs}) {
                               $dynamic .= ' checked="checked" ';
                           }
                           $dynamic .= ' />'.$$toolprivs{$tool}{$priv}.
                                       '</label></span></td>';
                     }                      }
                 }                  }
                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');                  $r->print('<tr><td colspan="2"><span class="LC_nobreak">'.$fixed.'</span></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 3814  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 = ' <span class="LC_nobreak"><label>'
                                                   no ending date</nobr>';                     .'<input type="checkbox" name="no_end_date" />'
     my $start_table = '';                     .&mt('No end date')
     $start_table .= "<table>\n";                     .'</label></span>';
     $start_table .= '<tr><td align="right">Default starting date for       my $table = &Apache::lonhtmlcommon::start_pick_box()
                                            member access</td>'.                 .&Apache::lonhtmlcommon::row_title(&mt('Start Date'))
         '<td>'.$startform.'</td>'.                 .$startform
         '<td>&nbsp;</td>'."</tr>\n";                 .&Apache::lonhtmlcommon::row_closure()
     $start_table .= "</table>";                 .&Apache::lonhtmlcommon::row_title(&mt('End Date'))
     my $end_table = '';                 .$endform
     $end_table .= "<table>\n";                 .$perpetual
     $end_table .= '<tr><td align="right">Default ending date for                  .&Apache::lonhtmlcommon::row_closure(1)
                                          member access</td>'.                 .&Apache::lonhtmlcommon::end_pick_box();
         '<td>'.$endform.'</td>'.      return $table;
         '<td>'.$perpetual.'</td>'."</tr>\n";  }
     $end_table .= "</table>\n";  
     return ($start_table, $end_table);  sub add_group_folder {
       my ($cdom,$cnum,$now,$groupname,$action,$description,$tools,$groupinfo,
           $gpterm,$ucgpterm,$crstype) = @_;
       if ($cdom eq '' || $cnum eq '') {
           my $error = '<span class="LC_error">';
           if ($crstype eq 'Community') { 
               $error .= &mt("Error: invalid community domain or number - group folder creation failed.");
           } else {
               $error .= &mt("Error: invalid course domain or number - group folder creation failed.");
           }
           $error .= '</span>';
           return $error;
       }
       my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage,$warning);
       my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
       $allgrpsmap = $crspath.'group_allfolders.sequence';
       if ($action eq 'create') {
           if (&get_folder_lock($cdom,$cnum,'group_allfolders',$now) eq 'ok') {
               # check if group_allfolders.sequence exists.
               my $mapcontents = &Apache::lonnet::getfile($allgrpsmap);
               if ($mapcontents eq '-1') { #file does not exist;
                   my $grpstitle = &mt("$crstype $ucgpterm".'s');
                   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);
                   } else {
                       $outcome = '<span class="LC_warning">'
                                 .&mt('Non-standard course - folder for all groups not added.')
                                 .'</span>';
                   }
                   if ($outcome ne 'ok') {
                       my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders');
                       if ($delresult ne 'ok') {
                           $warning = $delresult;
                       }
                       return $outcome.$warning;
                   }
               }
               my $delresult = &release_folder_lock($cdom,$cnum,'group_allfolders');
               if ($delresult ne 'ok') {
                   $warning = $delresult ;
               }
           } else {
               $outcome = '<span class="LC_error">'
                         .&mt('Could not obtain exclusive lock to check status of the folder for all groups. No group folder added.')
                         .'</span>';
               return $outcome;
           }
           my $grpfolder = &mt($ucgpterm.' Folder - [_1]',$description);
           $grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/smppg';
           my $grptitle = &mt('Group homepage - [_1]',$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.$warning;
           }
           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.$warning;
               }
               $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);
       my $navmap = Apache::lonnavmaps::navmap->new();
       if (!defined($navmap)) {
           $warning .= '<span class="LC_error">';
           if ($crstype eq 'Community') {
               $warning .= &mt("Error retrieving community contents").
                           ' '.&mt("You need to re-initialize the community.");
           } else {
               $warning  .= &mt("Error retrieving course contents").
                            ' '.&mt("You need to re-initialize the course.");
           }
           $warning .= '</span>';
           return $warning;
       }
       # modify parameters
       my $parm_result;
       if ($action eq 'create') {
           if ($grpmap) {
               $parm_result .= &parm_setter($navmap,$cdom,$grpmap,$groupname);
           }
           if ($grppage) {
               $parm_result .= &parm_setter($navmap,$cdom,$grppage,$groupname);
           }
           if ($boardsmap) {
               $parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname);
           }
       }
       undef($navmap);
       if ($parm_result) {
           return $warning.$parm_result;
       } else {
           return 'ok';
       }
   }
   
   sub get_folder_lock {
       my ($cdom,$cnum,$folder_name,$now) = @_;  
       # get lock for folder being edited.
       my $lockhash = {
                     $folder_name."\0".'locked_folder' => $now.':'.$env{'user.name'}.
                                                        ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum);
   
       while (($gotlock ne 'ok') && $tries <3) {
           $tries ++;
           sleep(1);
           $gotlock = &Apache::lonnet::newput('coursegroups',$lockhash,$cdom,$cnum);
       }
       return $gotlock;
   }
   
   sub release_folder_lock {
       my ($cdom,$cnum,$folder_name) = @_;  
       #  remove lock
       my @del_lock = ($folder_name."\0".'locked_folder');
       my $dellockoutcome=&Apache::lonnet::del('coursegroups',\@del_lock,$cdom,$cnum);
       if ($dellockoutcome ne 'ok') {
           return ('<div class="LC_error">'
                  .&mt('Warning: failed to release lock for folder: [_1].','<tt>'.$folder_name.'</tt>')
                  .'</div>'
                  );
       } 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 = '<div class="LC_error">'
                     .&mt('Error uploading new folder.')." ($newfile): $newmapurl"
                     .'</div>';
           return $outcome;
       }
       my ($errtext,$fatal)=&LONCAPA::map::mapread($parentmap);
       if ($fatal) {
           $outcome = '<div class="LC_error">'
                     .&mt('Error reading contents of parent folder.')." ($parentmap): $errtext"
                     .'</div>';
           return $outcome;
       } else {
           my $newidx=&LONCAPA::map::getresidx($newmapurl);
           $LONCAPA::map::resources[$newidx] = $itemtitle.':'.$newmapurl.
                                                    ':false:normal:res';
           $LONCAPA::map::order[1+$#LONCAPA::map::order]=$newidx;
           my ($outtext,$errtext) = &LONCAPA::map::storemap($parentmap,1);
           if ($errtext) {
               $outcome = '<div class="LC_error">'
                         .&mt('Error saving updated parent folder.')." ($parentmap):  $errtext"
                         .'</div>';
               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,$crstype) = @_;
       if (!defined($navmap)) {
           my $allresults;
           if ($crstype eq 'Community') { 
               $allresults = &mt("Parameters not set for [_1] because the contents of the community could not be retrieved.",$url).' '.
                             &mt("You need to reinitialize the community.");
           } else {
               $allresults = &mt("Parameters not set for [_1] because the contents of the course could not be retrieved.",$url).' '.
                             &mt("You need to reinitialize the course.");
   
           }
           return '<div class="LC_warning">'.$allresults.'</div>';
       }
       my %hide_settings = (
                              'course' =>  {
                                             'num' => 13,
                                             'set' => 'yes',
                                           },
                               'group' =>  {
                                             'num' => 5,
                                             'set' => 'no',
                                             'extra' => $groupname,
                                           },
                           );
       my $res = $navmap->getResourceByUrl($url);
       my $allresults;
       if ($res) {
           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;
               }
           }
       } else {
           $allresults = '<div class="LC_warning">';
           if ($crstype eq 'Community') {
               $allresults .= &mt("Parameters not set for [_1] because the resource was not recognized as part of the community.",'<tt>'.$url.'</tt>');
           } else {
               $allresults .= &mt('Parameters not set for [_1] because the resource was not recognized as part of the course.','<tt>'.$url.'</tt>');
           }
           $allresults .= '</div>';
       }
       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 %deleted_groups = &Apache::longroup::coursegroups($cdom,$cnum,undef,
                                                            'deleted_groups');
       if (my $tmp = &Apache::lonnet::error(%deleted_groups)) {
           undef(%deleted_groups);
           &Apache::lonnet::logthis('Error retrieving groups: '.$tmp.' in '.$cnum.':'.$cdom);
       }
       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') { 
    if (exists($curr_groups{$groupname})) {
       return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm).
              $lt{'inth'}.'.<br />'.$lt{'grna'};
           } elsif (exists($deleted_groups{$groupname})) {
               return $exitmsg.$lt{'cnnb'}.&mt('a [_1] which previously existed',$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 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.105


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