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

version 1.3, 2005/11/15 22:03:05 version 1.12, 2006/03/29 16:22:46
Line 51  sub handler { Line 51  sub handler {
     }      }
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                             ['action','refpage']);                          ['action','refpage','state','groupname','branch']);
                                                                                         
     my $function = &Apache::loncommon::get_users_function();      my $function = &Apache::loncommon::get_users_function();
     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');      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'};
Line 62  sub handler { Line 61  sub handler {
           &Apache::lonnet::allowed('vcg',$env{'request.course.id'});            &Apache::lonnet::allowed('vcg',$env{'request.course.id'});
     my $manage_permission =      my $manage_permission =
           &Apache::lonnet::allowed('mdg',$env{'request.course.id'});            &Apache::lonnet::allowed('mdg',$env{'request.course.id'});
   
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
   
     my %functions = (      my %functions = (
Line 80  sub handler { Line 78  sub handler {
     $idx{udom} = &Apache::loncoursedata::CL_SDOM();      $idx{udom} = &Apache::loncoursedata::CL_SDOM();
     $idx{uname} = &Apache::loncoursedata::CL_SNAME();      $idx{uname} = &Apache::loncoursedata::CL_SNAME();
   
       my $rowColor1 = "#dddddd";
       my $rowColor2 = "#eeeeee";
   
     my $action = $env{'form.action'};      my $action = $env{'form.action'};
     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') {       if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { 
         if ($view_permission || $manage_permission) {          if ($view_permission || $manage_permission) {
             &group_administration($r,$action,$cdom,$cnum,$function,$tabcol,              &group_administration($r,$action,$cdom,$cnum,$function,$tabcol,
                         \%functions,\%idx,$view_permission,$manage_permission);                                    \%functions,\%idx,$view_permission,
                                     $manage_permission,$rowColor1,$rowColor2);
         } else {          } else {
             $r->print('You do not have group administration '.              $r->print(&mt('You do not have group administration '.
                       'privileges in this course');                            'privileges in this course'));
         }          }
     } else {      } else {
         &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx,          &print_main_menu($r,$cdom,$cnum,$function,$tabcol,\%functions,\%idx,
                                           $view_permission,$manage_permission);                           $view_permission,$manage_permission,$action,
                            $rowColor1,$rowColor2);
     }      }
     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,$function,$tabcol,$functions,$idx,$view_permission,
                                                           $manage_permission)          $manage_permission,$action,$rowColor1,$rowColor2) = @_;
                                                                           = @_;      $r->print(&header('Course Groups',undef,undef,undef,undef,$function));
     $r->print(&header('Course Groups',&mt('LON-CAPA Course Groups'),  
                                                  undef,undef,undef,$function));  
     &Apache::lonhtmlcommon::add_breadcrumb      &Apache::lonhtmlcommon::add_breadcrumb
         ({href=>"/adm/coursegroups",          ({href=>"/adm/coursegroups",
           text=>"Course Groups",});            text=>"Course Groups",});
     $r->print(&Apache::lonhtmlcommon::breadcrumbs      $r->print(&Apache::lonhtmlcommon::breadcrumbs
                 (undef,'Course Groups'));                (undef,'Course Groups'));
     &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,      &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
                                           $view_permission,$manage_permission);                      $view_permission,$manage_permission,$action,$rowColor1,
                       $rowColor2);
     $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,$function,$tabcol,$functions,$idx,$view_permission,
                                                           $manage_permission) = @_;          $manage_permission,$action,$rowColor1,$rowColor2) = @_;
     my %curr_groups = ();      my %curr_groups = ();
     my %grp_info = ();      my %grp_info = ();
     my $rowColor1 = "#dddddd";  
     my $rowColor2 = "#eeeeee";  
   
     $r->print('<br /><br />');      my %actionlinks = (
         modify => '<a href="/adm/coursegroups?action=modify&state=pick_task&refpage='.
                   $env{'form.refpage'}.'&groupname=',
         view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',
         delete => '<a href="/adm/coursegroups?action=delete&refpage='.
                   $env{'form.refpage'}.'&groupname=',
       );
       my %lt = &Apache::lonlocal::texthash( 
                             modify => 'Modify',
                             view   => 'View',
                             delete => 'Delete',
                             act    => 'Action',
                             gname  => 'Group Name',
                             desc   => 'Description',
                             crea   => 'Creator',
                             crtd   => 'Created',
                             last   => 'Last Modified',
                             func   => 'Functionality',
                             quot   => 'Quota (Mb)',
                             memb   => 'Members',
                             file   => 'Files',
                             dibd   => 'Discussion Boards',
                             dius   => 'Disk Use',
                             nogr   => 'No groups exist.',
                             crng   => 'Create a new group',
                             alth   => 'Although your current role has privileges'.
                                       ' to view any existing groups in this course,'.
                                       ' 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)) {
               $action = 'view';
           }
           my %curr_groups;
           if (&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum)) {
               $r->print('<br /><br />');
             $r->print(&Apache::lonhtmlcommon::start_pick_box());              $r->print(&Apache::lonhtmlcommon::start_pick_box());
             if (keys(%curr_groups) > 0) {              $r->print(<<"END");
                 $r->print(<<"END");  
       <table border="0" cellpadding="4" cellspacing="1">        <table border="0" cellpadding="4" cellspacing="1">
        <tr bgcolor="$tabcol" align="center">         <tr bgcolor="$tabcol" align="center">
         <td><b>Action</b></td>          <td><b>$lt{'act'}</b></td>
         <td><b><a href="javascript:changeSort('groupname')">Group Name</a></b></td>          <td><b><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></b></td>
         <td><b><a href="javascript:changeSort('description')">Description</a></b></td>          <td><b><a href="javascript:changeSort('description')">$lt{'desc'}</a></b></td>
         <td><b><a href="javascript:changeSort('creator')">Creator</a></b>          <td><b><a href="javascript:changeSort('creator')">$lt{'crea'}</a></b>
         </td>          </td>
         <td><b><a href="javascript:changeSort('creation')">Created</a></b>          <td><b><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></b>
         </td>          </td>
         <td><b><a href="javascript:changeSort('modified')">Last Modified</a></b>          <td><b><a href="javascript:changeSort('modified')">$lt{'last'}</a></b>
         </td>          </td>
         <td><b>Functionality</b>          <td><b>$lt{'func'}</b>
         </td>          </td>
         <td><b><a href="javascript:changeSort('quota')">Quota (Mb)</a></b></td>          <td><b><a href="javascript:changeSort('quota')">$lt{'quot'}</a></b></td>
         <td><b><a href="javascript:changeSort('totalmembers)">Members</a></b></td>          <td><b><a href="javascript:changeSort('totalmembers)">$lt{'memb'}</a></b></td>
         <td><b><a href="javascript:changeSort('totalfiles')">Files</a></b></td>          <td><b><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></b></td>
         <td><b><a href="javascript:changeSort('boards')">Discussion boards</a></b></td>          <td><b><a href="javascript:changeSort('boards')">$lt{'dibd'}</a></b></td>
         <td><b><a href="javascript:changeSort('diskuse')">Disk use</a></b></td>          <td><b><a href="javascript:changeSort('diskuse')">$lt{'dius'}</a></b></td>
        </tr>         </tr>
 END  END
                 my %Sortby = ();              my %Sortby = ();
                 foreach my $group (sort(keys(%curr_groups))) {              foreach my $group (sort(keys(%curr_groups))) {
                     %{$grp_info{$group}} =                   %{$grp_info{$group}} = 
                                       &Apache::loncommon::get_group_settings(                                    &Apache::loncommon::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 $files_result = &group_files($group,\%grp_info); 
                         push(@{$Sortby{$group}},$group);                  if ($env{'form.sortby'} eq 'groupname') {
                     } elsif ($env{'form.sortby'} eq 'description') {                      push(@{$Sortby{$group}},$group);
                         push(@{$Sortby{$grp_info{$group}{'description'}}},                  } elsif ($env{'form.sortby'} eq 'description') {
                       push(@{$Sortby{$grp_info{$group}{'description'}}},
                                                                      $group);                                                                       $group);
                     } elsif ($env{'form.sortby'} eq 'creator') {                  } elsif ($env{'form.sortby'} eq 'creator') {
                         push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);
                     } elsif ($env{'form.sortby'} eq 'creation') {                  } elsif ($env{'form.sortby'} eq 'creation') {
                         push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);
                     } elsif ($env{'form.sortby'} eq 'modified') {                  } elsif ($env{'form.sortby'} eq 'modified') {
                         push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);
                     } elsif ($env{'form.sortby'} eq 'quota') {                  } elsif ($env{'form.sortby'} eq 'quota') {
                         push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);                      push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);
                     } elsif ($env{'form.sortby'} eq 'totalmembers') {                  } elsif ($env{'form.sortby'} eq 'totalmembers') {
                         push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},                      push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},
                                                                        $group);                                                                         $group);
                     } elsif ($env{'form.sortby'} eq 'totalfiles') {                  } elsif ($env{'form.sortby'} eq 'totalfiles') {
                         push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},                      push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},$group);
                                                                        $group);                  } elsif ($env{'form.sortby'} eq 'boards') {
                     } elsif ($env{'form.sortby'} eq 'boards') {                      push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);
                         push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);                  } elsif ($env{'form.sortby'} eq 'diskuse') {
                     } elsif ($env{'form.sortby'} eq 'diskuse') {                      push(@{$Sortby{$grp_info{$group}{'diskuse'}}},$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 $group (@{$Sortby{$key}}) {
                       if ($rowNum %2 == 1) {
                           $rowColor = $rowColor1;
                     } else {                      } else {
                         push(@{$Sortby{$group}},$group);                          $rowColor = $rowColor2;
                     }                      }
                 }                      my $description = 
                 my $rowNum = 0;  
                 my $rowColor;  
                 foreach my $key (sort(keys(%Sortby))) {  
                     foreach my $group (@{$Sortby{$key}}) {  
                         if ($rowNum %2 == 1) {  
                             $rowColor = $rowColor1;  
                         } else {  
                             $rowColor = $rowColor2;  
                         }  
                         my $description =   
                    &Apache::lonnet::unescape($grp_info{$group}{'description'});                     &Apache::lonnet::unescape($grp_info{$group}{'description'});
                         my $creator = $grp_info{$group}{'creator'};                      my $creator = $grp_info{$group}{'creator'};
                         my $creation = $grp_info{$group}{'creation'};                      my $creation = $grp_info{$group}{'creation'};
                         my $modified = $grp_info{$group}{'modified'};                       my $modified = $grp_info{$group}{'modified'}; 
                         my $quota = $grp_info{$group}{'quota'};                      my $quota = $grp_info{$group}{'quota'};
                         my $totalmembers = $grp_info{$group}{'totalmembers'};                      my $totalmembers = $grp_info{$group}{'totalmembers'};
                         my $totalfiles = $grp_info{$group}{'totalfiles'};                      my $totalfiles = $grp_info{$group}{'totalfiles'};
                         my $boards = $grp_info{$group}{'boards'};                      my $boards = $grp_info{$group}{'boards'};
                         my $diskuse = $grp_info{$group}{'diskuse'};                      my $diskuse = $grp_info{$group}{'diskuse'};
                         my $functionality;                      my $functionality;
                         foreach my $tool (sort keys(%{$functions})) {                      foreach my $tool (sort(keys(%{$functions}))) {
                             if (defined($grp_info{$group}{functions}{$tool})) {                          if ($grp_info{$group}{functions}{$tool} eq 'on') {
                                 $functionality .= ' '.$tool;                              $functionality .= ' '.$tool;
                             }  
                         }                          }
                         if (!$functionality) {  
                             $functionality = 'None available';  
                         }  
                         $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 ++;  
                     }                      }
                       if (!$functionality) {
                           $functionality = &mt('None available');
                       }
                       my $link = $actionlinks{$action};
                       if ($action eq 'modify' || $action eq 'delete') {
                           $link .= $group;
                       } else {
                           $link .= $group.'/grppg?register=1';
                       }
                       $link .= '">'.$lt{$action}.'</a>';  
                       $r->print('<tr bgcolor="'.$rowColor.'"><td><small>'.$link.'</small></td><td><small>'.$group.'</small></td><td><small>'.$description.'</small></td><td><small>'.$creator.'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($creation).'</small></td><td><small>'. &Apache::lonnavmaps::timeToHumanString($modified).'</small></td><td><small>'.$functionality.'</small></td><td><small>'.$quota.'</small></td><td><small>'.$totalmembers.'</small></td><td><small>'.$totalfiles.'</small></td><td><small>'.$boards.'</small></td><td><small>'.$diskuse.'</small></td></tr>');
                       $rowNum ++;
                 }                  }
                 $r->print('</table>');              }
                 $r->print(&Apache::lonhtmlcommon::end_pick_box());              $r->print('</table>');
             }                             $r->print(&Apache::lonhtmlcommon::end_pick_box());
         } else {          } else {
             $r->print('No groups exist');              $r->print($lt{'nogr'});
               if ($manage_permission) {
                   $r->print('<br /><br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');
               } else {
                   $r->print('<br /><br />'.$lt{'crng'});
   
               }
         }          }
     } 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;
               if (&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum)) {
                   foreach my $group (@coursegroups) {
                       my %group_info =  &Apache::loncommon::get_group_settings(
                                           $curr_groups{$group});
                       my $description = &Apache::lonnet::unescape(
                                           $group_info{description});
                       my ($uname,$udom) = split(/:/,$group_info{creator});
                       $r->print('<font size="+1"><a href="/adm/'.$udom.'/'.$uname.'/'.$group.'/grppg?register=1">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');
                   }
               }
           } else {
               $r->print(&mt('You are not currently a member of any '.
                             'active groups in this course'));
           }
     }      }
     return;      return;
 }  }
   
 sub group_administration {  sub group_administration {
     my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx,      my ($r,$action,$cdom,$cnum,$function,$tabcol,$functions,$idx,
                                      $view_permission,$manage_permission) = @_;          $view_permission,$manage_permission,$rowColor1,$rowColor2) = @_;
     my %sectioncount = ();      my %sectioncount = ();
     my @tools = ();      my @tools = ();
     my @types = ();      my @types = ();
Line 238  sub group_administration { Line 299  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 $state = $env{'form.state'};      my $state = $env{'form.state'};
     my ($groupname,$description,$startdate,$enddate);      my ($groupname,$description,$startdate,$enddate,$granularity,$specificity);
   
     if ($action eq 'create') {      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 (($action eq 'create') || (($action eq 'modify') 
           && (($state eq 'pick_privs') || ($state eq 'addresult')))) {
           if (defined($env{'form.member'})) {
               @members = &Apache::loncommon::get_env_multiple('form.member');
               foreach my $user (@members) {
                   %{$usertools{$user}} = ();
               }
           }
       }
   
       if ($action eq 'modify') {
         if ($state eq '') {          if ($state eq '') {
             $state = 'pick_name';              $state = 'pick_group';
         } else {          } else {
             ($startdate,$enddate) = &get_dates_from_form();              %stored = &retrieve_settings($cdom,$cnum,$groupname);
             if (defined($env{'form.groupname'})) {              if (ref($stored{'types'}) eq 'ARRAY') {
                 $groupname = $env{'form.groupname'};                  @types = @{$stored{'types'}};
             }              }
             if (defined($env{'form.description'})) {              if (ref($stored{'roles'}) eq 'ARRAY') {
                 $description = $env{'form.description'};                  @roles = @{$stored{'roles'}};
             }              }
             if (defined($env{'form.tool'})) {              if (ref($stored{'sectionpick'}) eq 'ARRAY') {
                 @tools=&Apache::loncommon::get_env_multiple('form.tool');                  @sections = @{$stored{'sectionpick'}};
             }              }
             if (defined($env{'form.member'})) {              unless ($state eq 'chgresult') {
                 @members = &Apache::loncommon::get_env_multiple('form.member');                  if (ref($stored{'tool'}) eq 'ARRAY') { 
                 foreach my $user (@members) {                      @tools = @{$stored{'tool'}};
                     %{$usertools{$user}} = ();  
                 }                  }
                   $startdate = $stored{'startdate'};
                   $enddate = $stored{'enddate'};
                   $description = $stored{'description'};
                   $granularity = $stored{'granularity'};
                   $specificity =  $stored{'specificity'};
             }              }
         }          }
     }      }
Line 308  sub group_administration { Line 410  sub group_administration {
         startdate_hour => 'selectbox',          startdate_hour => 'selectbox',
         enddate_month => 'selectbox',          enddate_month => 'selectbox',
         enddate_hour => 'selectbox',          enddate_hour => 'selectbox',
         types => 'selectbox',  
         roles => 'selectbox',  
         startdate_day => 'text',          startdate_day => 'text',
         startdate_year => 'text',          startdate_year => 'text',
         startdate_minute => 'text',          startdate_minute => 'text',
Line 324  sub group_administration { Line 424  sub group_administration {
         granularity => 'radio',          granularity => 'radio',
         no_end_date => 'checkbox',          no_end_date => 'checkbox',
     );      );
       %{$elements{'modify'}{'change_settings'}} = (
                                      %{$elements{'create'}{'pick_name'}},
                                                   specificity => 'radio',
                                                   defpriv => 'checkbox',
                                                   autorole => 'checkbox',
                                                   autoadd => 'radio',
                                                   autodrop => 'radio',
                                      );
       if (ref($stored{'autorole'}) eq 'ARRAY') {
           foreach my $role (@{$stored{'autorole'}}) {
               $elements{'modify'}{'change_settings'}{'sec_'.$role} = 'selectbox'; 
           }
       }
     %{$elements{'create'}{'pick_members'}} = (      %{$elements{'create'}{'pick_members'}} = (
         member => 'checkbox',          member => 'checkbox',
           defpriv => 'checkbox',
     );      );
   
       %{$elements{'modify'}{'add_members'}} = (
           types => 'selectbox',
           roles => 'selectbox',
       );
   
     if (($action eq 'create') && ($state eq 'pick_name')) {      if (($action eq 'create') && ($state eq 'pick_name')) {
           $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')))) {
         my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,          my $numsections = &Apache::loncommon::get_sections($cdom,$cnum,
                            \%sectioncount);                                                             \%sectioncount);
         if ($numsections > 0) {          if ($numsections > 0) {
             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';              $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
               $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';
               $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';
         }          }
     }      }
                                                                                         
     if (($action eq 'create') && (($state eq 'pick_members') ||      if (($action eq 'create') || 
                                   ($state eq 'pick_privs'))) {          ($action eq 'modify' && $state eq 'pick_members')) {
         if (defined($env{'form.types'})) {          if (defined($env{'form.types'})) {
             @types=&Apache::loncommon::get_env_multiple('form.types');              @types=&Apache::loncommon::get_env_multiple('form.types');
         }          }
Line 349  sub group_administration { Line 478  sub group_administration {
                 @sections = sort {$a cmp $b} keys(%sectioncount);                  @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 = 1;
                           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 'result') || ($state eq 'memresult')))) {
         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) {
Line 371  sub group_administration { Line 568  sub group_administration {
                 }                  }
             }              }
         }          }
         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';
                       }
                   }
               }
           }
     }      }
    
       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;
Line 398  function backPage(formname,prevstate) { Line 684  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_group','pick_task');
       @{$branchstates{'noprivs'}} = ('result');
       @{$branchstates{'settings'}} = ('change_settings','chgresult');
       @{$branchstates{'members'}} = ('change_members','change_privs','memresult');
       @{$branchstates{'adds'}} = ('add_members','pick_members','pick_privs',
                                   'addresult');
       
       if (defined($env{'form.branch'})) {
           push (@{$states{$action}},@{$branchstates{$env{'form.branch'}}});
       }
   
       if (($action eq 'create') || ($action eq 'modify')) {
           my $done = 0;
           my $i=0;
           while ($i<@{$states{$action}} && !$done) {
               if ($states{$action}[$i] eq $state) {
                   $page = $i;
                   $done = 1;
               }
               $i++;
           }
       }
   
     my $loaditems =  &onload_action($action,$state);      my $loaditems =  &onload_action($action,$state);
     $r->print(&header('Course Groups Manager',&mt('LON-CAPA Groups Manager'),      $r->print(&header('Course Groups Manager',
                                $jscript,$action,$state,$function,$loaditems));        $jscript,$action,$state,$page,$function,$loaditems));
   
     if ($env{'form.refpage'} eq 'enrl') {      if ($env{'form.refpage'} eq 'enrl') {
         &Apache::lonhtmlcommon::add_breadcrumb          &Apache::lonhtmlcommon::add_breadcrumb
Line 421  function backPage(formname,prevstate) { Line 736  function backPage(formname,prevstate) {
           faq=>9,bug=>'Instructor Interface',});            faq=>9,bug=>'Instructor Interface',});
     }      }
   
     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 => 'Group 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_group => 'Groups',
                               pick_task => 'Choose Task',
                               change_settings => 'Group Settings',
                               change_members => 'Modify/Delete Members',
                               change_privs => 'Change Privileges',
                               change_mapping => 'Membership Mapping',
                               add_members => 'Add Members',
                               pick_members => 'Select Members',
                               pick_privs => 'Choose Privileges',
                               chgresult => 'Setting Changes Complete',
                               memresult => 'Modifications Complete',
                               addresult => 'Additions Complete',
                             );
       my %navbuttons = &Apache::lonlocal::texthash(
                                gtns => 'Go to next step',
                                gtps => 'Go to previous step',
                                crgr => 'Create group',
                                mose => 'Modify settings',
                                gtpp => 'Go to previous page',
                                adme => 'Add members',
       );
     if ((($action eq 'create') || ($action eq 'modify')) &&      if ((($action eq 'create') || ($action eq 'modify')) &&
               ($manage_permission)) {                ($manage_permission)) {
         for (my $i=0; $i<@{$states{$action}}; $i++) {          for (my $i=0; $i<@{$states{$action}}; $i++) {
Line 442  function backPage(formname,prevstate) { Line 773  function backPage(formname,prevstate) {
                    {text=>"$trail{$action}{$state}"});                     {text=>"$trail{$action}{$state}"});
                 $r->print(&Apache::lonhtmlcommon::breadcrumbs                  $r->print(&Apache::lonhtmlcommon::breadcrumbs
                      (undef,'Course Groups Manager'));                       (undef,'Course Groups Manager'));
                 &display_control($r,$cdom,$cnum,$tabcol,$action,$state,                  &display_control($r,$cdom,$cnum,$tabcol,$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,
                          $function,$view_permission,$manage_permission,
                          \%stored,$granularity,$specificity,\@types,\@roles,
                          \@sections,\%states,\%navbuttons,$rowColor1,$rowColor2);
                 last;                  last;
             } else {              } else {
                 if ($state eq 'result' && $i > 0) {                  if (($state eq 'result') && ($i > 0)) {
                     &Apache::lonhtmlcommon::add_breadcrumb(                      &Apache::lonhtmlcommon::add_breadcrumb(
     {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",      {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",
       text=>"$trail{$action}{$states{$action}[$i]}"});        text=>"$trail{$action}{$states{$action}[$i]}"});
Line 465  function backPage(formname,prevstate) { Line 799  function backPage(formname,prevstate) {
         $r->print(&Apache::lonhtmlcommon::breadcrumbs          $r->print(&Apache::lonhtmlcommon::breadcrumbs
                      (undef,'Course Groups Manager'));                       (undef,'Course Groups Manager'));
         &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,          &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
                                         $view_permission,$manage_permission);                          $view_permission,$manage_permission,$action,
                           $rowColor1,$rowColor2);
   
     }      }
     $r->print(&footer());      $r->print(&footer());
     return;      return;
 }  }
   
   sub retrieve_settings {
       my ($cdom,$cnum,$groupname) = @_;
       my %groupinfo;
       my %stored;
       my %curr_groups;
       my $numgroups = &Apache::loncommon::coursegroups(\%curr_groups,$cdom,
                                                                $cnum,$groupname);
       if ($numgroups > 0) {
           %groupinfo = &Apache::loncommon::get_group_settings(
                                                        $curr_groups{$groupname});
           $stored{'description'} = &Apache::lonnet::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'};
   
           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'}}))) {
                   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,$tabcol,$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,$function,
           $view_permission,$manage_permission,$stored,$granularity,$specificity,
           $types,$roles,$sections,$states,$navbuttons,$rowColor1,$rowColor2)=@_;
     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,$tabcol,$state,$page,
                                                                 $sectioncount);                                     $functions,$tools,$toolprivs,$fixedprivs,
                                      $sectioncount,$stored,$states,$navbuttons,
                                      $rowColor1,$rowColor2);
         } 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,$tabcol,$action,$state,$page,
                                   $description,$startdate,$enddate,$tools,                                   $groupname,$description,$granularity,
                                              $functions,$users,$userdata,$idx);                                   $startdate,$enddate,$tools,$fixedprivs,
                                    $toolprivs,$functions,$users,$userdata,$idx,
                                    $stored,$states,$navbuttons,$rowColor1,
                                    $rowColor2);
         } 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,$tabcol,$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,
                                  $rowColor1,$rowColor2);
         } elsif ($state eq 'result') {          } elsif ($state eq 'result') {
             &completed_creation($r,$cdom,$cnum,$tabcol,$state,$groupname,              &process_request($r,$cdom,$cnum,$tabcol,$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,$rowColor1,$rowColor2);
           }
       } elsif ($action eq 'modify') {
           my $groupname = $env{'form.groupname'};
           if ($state eq 'pick_group') {
               &display_groups($r,$cdom,$cnum,$function,$tabcol,$functions,$idx,
                               $view_permission,$manage_permission,$action,
                               $rowColor1,$rowColor2);
           } elsif ($state eq 'pick_task') {
               &modify_menu($r,$groupname,$page);
           } elsif ($state eq 'change_settings') {
               &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,
                                      $functions,$tools,$toolprivs,$fixedprivs,
                                      $sectioncount,$stored,$states,$navbuttons,
                                      $rowColor1,$rowColor2);
           } elsif ($state eq 'change_members') {
               &change_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                                    $groupname,$description,$startdate,$enddate,
                                    $tools,$fixedprivs,$functions,$users,
                                    $userdata,$granularity,$specificity,$idx,
                                    $states,$navbuttons,$rowColor1,$rowColor2);
           } elsif ($state eq 'add_members') {
               &add_members_form($r,$tabcol,$action,$state,$page,$startdate,
                                 $enddate,$groupname,$description,$granularity,
                                 $sectioncount,$tools,$functions,$stored,$states,
                                 $navbuttons,$rowColor1,$rowColor2);
           } elsif ($state eq 'pick_members') {
               &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                                    $groupname,$description,$granularity,
                                    $startdate,$enddate,$tools,$fixedprivs,
                                    $toolprivs,$functions,$users,$userdata,$idx,
                                    $stored,$states,$navbuttons,$rowColor1,
                                    $rowColor2);
           } elsif ($state eq 'pick_privs') {
               &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                                  $startdate,$enddate,$tools,$functions,
                                  $toolprivs,$fixedprivs,$userdata,$usertools,
                                  $idx,$states,$stored,$sectioncount,$navbuttons,
                                  $rowColor1,$rowColor2);
           } elsif ($state eq 'change_privs') {
               &change_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                                  $startdate,$enddate,$tools,$functions,
                                  $toolprivs,$fixedprivs,$userdata,$usertools,
                                  $memchg,$idx,$states,$stored,$sectioncount,
                                  $navbuttons,$rowColor1,$rowColor2);
           } elsif ($state eq 'chgresult' || $state eq 'memresult' || 
                    $state eq 'addresult') {
               &process_request($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                                $groupname,$description,$specificity,$userdata,
                                $startdate,$enddate,$tools,$functions,
                                $toolprivs,$usertools,$idx,$types,$roles,
                                $sections,$states,$navbuttons,$memchg,
                                $sectioncount,$stored,$rowColor1,$rowColor2);
         }          }
     }      }
 }  }
   
 sub header {  sub header {
     my ($bodytitle,$title,$jscript,$action,$state,$function,$loaditems) = @_;      my ($bodytitle,$jscript,$action,$state,$page,$function,$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>',
          {'function'    => $function,
    'add_entries' => $loaditems,});
     my $output = <<"END";      my $output = <<"END";
 $html  $start_page
 <head>  <form method="POST" name="$state">
 <title>$title</title>  
 <script type="text/javascript">  
 $jscript  
 </script>  
 </head>  
 $bodytag  
 <form method="post" name="$state">  
   
 END  END
     if ($action eq 'create' || $action eq 'modify') {      if ($action eq 'create' || $action eq 'modify') {
Line 517  END Line 968  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 533  sub onload_action { Line 985  sub onload_action {
              'onload="javascript:setFormElements(document.'.$state.')"';               'onload="javascript:setFormElements(document.'.$state.')"';
         }          }
     }      }
       if (($action eq 'modify') &&
                   ($state eq 'change_settings' || $state eq 'change_members' ||
                    $state eq 'change_privs' || $state eq 'add_members' ||
                    $state eq 'pick_members')) {
               $loaditems =
                'onload="javascript:setFormElements(document.'.$state.')"';
       }
     return $loaditems;      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 1014  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;
 }  }
   
Line 563  sub group_files { Line 1023  sub group_files {
 }  }
   
 sub group_members {  sub group_members {
     return;      my ($cdom,$cnum,$group,$group_info) = @_;
       my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);
       my $now = time;
       my ($tmp)=keys(%memberhash);
       if ($tmp=~/^error:/) {
           $$group_info{'totalmembers'} = 'Unknown - an error occurred';
           return $tmp;
       }
       my $now = time;
       my $totalmembers = 0;
       my $active = 0;
       my $previous = 0;
       my $future = 0;
       foreach my $member (keys %memberhash) {
           $totalmembers ++;
           my ($end,$start) = split(/:/,$memberhash{$member});
           unless ($start == -1) {
               if (($end!=0) && ($end<$now)) {
                   $previous ++;
               } elsif (($start!=0) && ($start>$now)) {
                   $future ++;
               } else {
                  $active ++;
               }
           }
       }
       if ($totalmembers == 0) {
           $$group_info{$group}{'totalmembers'} = 'None';
       } else {
           $$group_info{$group}{'totalmembers'} = $active.' - active<br />'.$previous.' -previous<br />'.$future.' -future';
       }
       return 'ok';
 }  }
   
   
 sub first_creation_form {  sub general_settings_form {
     my ($r,$cdom,$cnum,$tabcol,$formname,$functions,$sectioncount) = @_;      my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools,
           $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
           $rowColor1,$rowColor2) = @_;
       my ($nexttext,$prevtext);
       $r->print(' <br />
    <table width="100%" cellpadding="0" cellspacing="0" border="0">
   ');
       &groupsettings_options($r,$tabcol,$functions,$action,$formname,$stored,1);
       $r->print(' 
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>');
       &access_date_settings($r,$tabcol,$action,$formname,$stored,2);
       $r->print('
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>');
       if ($action eq 'create') {
           &membership_options($r,$action,$formname,$tabcol,$sectioncount,3);
           $nexttext = $$navbuttons{'gtns'};
       } else {
           my @available = ();
           my @unavailable = ();
           &check_tools($functions,$tools,\@available,\@unavailable);
           @{$tools} = sort(keys(%{$functions}));
           &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
                                  3,$tools,$stored,$toolprivs,$fixedprivs,
                                  \@available,$formname);
           $r->print('
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>');
           &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,
                            $states,$stored,$navbuttons,4,5,$rowColor1,
                            $rowColor2);
           $nexttext = $$navbuttons{'mose'};
       }
       $prevtext = $$navbuttons{'gtpp'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       $r->print('
    </table>');
       return;
   }
   
   sub groupsettings_options {
       my ($r,$tabcol,$functions,$action,$formname,$stored,$image) = @_;
     my %lt = &Apache::lonlocal::texthash(      my %lt = &Apache::lonlocal::texthash(
         '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',          'gdat' => 'Group open and close dates',
         'sten' => 'Set a start date/time and end date/time for the group',          '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',          'gfun' => 'Group functionality',
           'gnde' => 'Group name, description and available functionality',
           'desc' => 'Description',
           'func' => 'Functionality',
           'gnam' => 'Group Name',
           'doyo' => 'Do you want to assign different functionality '.
                     'to different group members?',
     );      );
       &topic_bar($r,$tabcol,$image,$lt{'gnde'});
     my %status_types = (      $r->print('
                    active => &mt('Currently has access'),  
                    previous => &mt('Previously had access'),  
                    future => &mt('Will have future access'),  
                    );  
   
     my @roles = ('st','cc','in','ta','ep','cr');  
   
     my $starttime = time;  
     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx  
     my ($start_table,$end_table) = &date_setting_table  
                                     ($starttime,$endtime,$formname);  
   
     my @sections = ();  
     my $section_sel = '';  
     my $numvisible = 4;  
   
     @sections = sort {$a cmp $b} keys(%{$sectioncount});  
     if (@sections > 0) {  
         unshift(@sections,'_all'); # Put 'all' at the front of the list  
         if (@sections < 4) {  
             $numvisible = @sections;  
         }  
         foreach (@sections) {  
             if ($_ eq '_all') {  
                 $section_sel .= '  <option value="'.$_.'" />all sections'."\n";  
             } else {  
                 $section_sel .= '  <option value="'.$_.'" />'.$_."\n";  
             }  
         }  
     }  
   
     $r->print(<<"END");  
  <br />  
  <table width="100%" cellpadding="0" cellspacing="0" border="0">  
    <tr bgcolor="$tabcol">  
      <td>&nbsp;</td>  
      <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step1.gif"   
          valign="bottom">&nbsp;&nbsp;</nobr>  
      </td>  
      <td align="left"><nobr>  
        <font face="arial,helvetica,sans-serif"><b>Group name, description  
          and available functionality</b></font></nobr>   
      </td>  
      <td width="100%">&nbsp;</td>  
    </tr>  
    <tr>  
     <td colspan="4">&nbsp;</td>  
    </tr>  
    <tr>     <tr>
     <td>&nbsp;</td>      <td>&nbsp;</td>
     <td colspan="3">      <td colspan="3">
      <table border="0" cellpadding="2" cellspacing="2">       <table border="0" cellpadding="2" cellspacing="2">
       <tr>        <tr>
        <td><b>Group Name:</b></td>         <td><b>'.$lt{'gnam'}.':</b></td>
        <td colspan="5"><input type="text" name="groupname" size="25" />         <td colspan="5">
   ');
       if ($action eq 'create') {
           $r->print('<input type="text" name="groupname" size="25" />');
       } else {
           $r->print('<input type="hidden" name="groupname" value="'.
                            $env{'form.groupname'}.'" />'.$env{'form.groupname'});
       }
       $r->print(<<"END");
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>Description:</b></td>         <td><b>$lt{'desc'}:</b></td>
        <td colspan="5"><input type="text" name="description" size="40" />         <td colspan="5"><input type="text" name="description" size="40"
                                                       value="" />
        </td>         </td>
       <tr>        <tr>
       <tr>        <tr>
        <td><b>Functionality:</b></td>         <td><b>$lt{'func'}:</b></td>
 END  END
     my $numitems = keys(%{$functions});      my $numitems = keys(%{$functions});
     my $halfnum = int($numitems/2);      my $halfnum = int($numitems/2);
Line 653  END Line 1151  END
     if ($remnum) {      if ($remnum) {
         $halfnum ++;          $halfnum ++;
     }      }
     my @allfunctions = sort (keys (%{$functions}));      my @allfunctions = sort(keys (%{$functions}));
     for (my $i=0; $i<$halfnum; $i++) {      for (my $i=0; $i<$halfnum; $i++) {
         $r->print('<td><input type="checkbox" name="tool" value="'.          $r->print('<td><label><input type="checkbox" name="tool" value="'.
                   $allfunctions[$i].'" />&nbsp;'.                    $allfunctions[$i].'" />&nbsp;'.
                    $$functions{$allfunctions[$i]}.'</td>                     $$functions{$allfunctions[$i]}.'</label></td>
                    <td>&nbsp;</td><td>&nbsp;</td>');                     <td>&nbsp;</td><td>&nbsp;</td>');
     }      }
     $r->print('<td><input type="button" value="check all" '.      $r->print('<td><input type="button" value="check all" '.
               'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.                'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.
               '</td></tr><tr><td>&nbsp;</td>');                '</td></tr><tr><td>&nbsp;</td>');
     for (my $j=$halfnum; $j<@allfunctions; $j++) {      for (my $j=$halfnum; $j<@allfunctions; $j++) {
         $r->print('<td><input type="checkbox" name="tool" value="'.          $r->print('<td><label><input type="checkbox" name="tool" value="'.
                   $allfunctions[$j].'" />&nbsp;'.                    $allfunctions[$j].'" />&nbsp;'.
                   $$functions{$allfunctions[$j]}.'</td>                    $$functions{$allfunctions[$j]}.'</label></td>
                   <td>&nbsp;</td><td>&nbsp;</td>');                    <td>&nbsp;</td><td>&nbsp;</td>');
     }      }
     if ($remnum) {      if ($remnum) {
         $r->print('<td>&nbsp;</td>');          $r->print('<td>&nbsp;</td>');
     }      }
     $r->print(<<"END");       $r->print('
        <td>         <td>
         <input type="button" value="uncheck all"           <input type="button" value="uncheck all"
           onclick="javascript:uncheckAll(document.$formname.tool)" />            onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />
        </td>         </td>
       </tr>        </tr>
       <tr>        <tr>
        <td><b>Granularity:</b></td>         <td><b>Granularity:</b></td>
        <td colspan="9">Do you want to assign different functionality to different group members?&nbsp;<input type="radio" name="granularity" value="Yes" />Yes&nbsp;<input type="radio" name="granularity" value="No" checked="checked" />No</td>         <td colspan="9">'.$lt{'doyo'}.'&nbsp;<label><input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'</label>&nbsp;<label><input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No').'</label>');
       </tr>       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',
                                         $$stored{'granularity'}).')');
       }
       $r->print('
          </td>
         </tr>
      </table>       </table>
     </td>      </td>
    </tr>     </tr>
    <tr>  ');
     <td colspan="4">&nbsp;</td>      return;
    </tr>  }
    <tr bgcolor="$tabcol">  
     <td>&nbsp;</td>  sub membership_options {
     <td valign="bottom"><nobr><img src="/res/adm/pages/bl_step2.gif"       my ($r,$action,$state,$tabcol,$sectioncount,$image) = @_;
         valign="bottom">&nbsp;&nbsp;</nobr>      my %lt = &Apache::lonlocal::texthash(
     </td>                  'pipa' => 'Pick parameters to generate membership list',
     <td align="left"><nobr>                  'gmem' => 'Group membership options',
       <font face="arial,helvetica,sans-serif"><b>Start and end dates for group                  'picr' => 'Pick the criteria to use to build a list of '.
                                                   access</b></font></nobr>                            'course users from which you will select ',
     </td>                  'meof' => 'members of the new group.',
     <td width="100%">&nbsp;</td>                  'admg' => 'additional members of the group.',
    </tr>                  'ifno' => 'If you do not wish to add members when you first '.
    <tr>                            'create the group, do not make any selections',  
     <td colspan="4">&nbsp;</td>                  'acty' => 'Access types',
    </tr>                  'coro' => 'Course roles',
    <tr>                  'cose' => 'Course sections',
     <td>&nbsp;</td>               );
     <td colspan="3">$start_table</td>      my %status_types = (
    <tr>                     active => &mt('Currently has access'),
    <tr>                     previous => &mt('Previously had access'),
     <td colspan="4">&nbsp;</td>                     future => &mt('Will have future access'),
    </tr>                     );
    <tr>                                                                                   
     <td>&nbsp;</td>      my @roles = ('st','cc','in','ta','ep','cr');
     <td colspan="3">$end_table</td>  
    <tr>      my @sections = keys(%{$sectioncount});
    <tr>  
     <td colspan="4">&nbsp;</td>      &topic_bar($r,$tabcol,$image,$lt{'pipa'});
    </tr>      $r->print('
    <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>     <tr>
     <td>&nbsp;</td>      <td>&nbsp;</td>
     <td colspan="3">      <td colspan="3">
      <b>$lt{'gmem'}</b><br/> $lt{'picr'}       <b>'.$lt{'gmem'}.'</b><br/>'.$lt{'picr'});
      <br /><br />      if ($action eq 'create') {
           $r->print($lt{'meof'}.'<br />'.$lt{'ifno'});
       } else {
           $r->print($lt{'admg'});
       }
       $r->print('
        <br />
        <br />
      <table border="0">       <table border="0">
       <tr>        <tr>
        <td><b>$lt{'acty'}</b></td>         <td><b>'.$lt{'acty'}.'</b></td>
        <td>&nbsp;</td>         <td>&nbsp;</td>
        <td><b>$lt{'coro'}</b></td>         <td><b>'.$lt{'coro'}.'</b></td>');
 END  
     if (@sections >0) {      if (@sections >0) {
          $r->print('          $r->print('
        <td>&nbsp;</td>         <td>&nbsp;</td>
        <td><b>'.$lt{'cose'}.'</b></td>         <td><b>'.$lt{'cose'}.'</b></td>
        <td>&nbsp;</td>');         <td>&nbsp;</td>');
Line 753  END Line 1248  END
     $r->print('<td>&nbsp;</td>');      $r->print('<td>&nbsp;</td>');
     $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));      $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));
     if (@sections > 0) {      if (@sections > 0) {
         $r->print('          @sections = sort {$a cmp $b} @sections;
        <td>&nbsp;</td>          unshift(@sections,'_all'); # Put 'all' at the front of the list
        <td colspan="3" align="center" valign="top">          unshift(@sections,'_nosec'); # Put 'no sections' next
         <select name="sectionpick" multiple="true" size="'.$numvisible.'">          $r->print('<td>&nbsp;</td>
           '.$section_sel.'                     <td colspan="3" align="center" valign="top">'.
         </select>          &sections_selection(\@sections,'sectionpick').'</td>');
        </td>');  
     }      }
     $r->print('      $r->print('
       </tr>        </tr>
      </table>       </table>
     </td>      </td>
    </tr>     </tr>');
       return;
   }
   
   sub sections_selection {
       my ($sections,$elementname) = @_;
       my $section_sel;
       my $numvisible = 4;
       if (@{$sections} < 4) {
           $numvisible = @{$sections};
       }
       foreach my $sec (@{$sections}) {
           if ($sec eq '_all') {
               $section_sel .= '  <option value="'.$sec.'" />all sections'."\n";
           } elsif ($sec eq '_nosec') {
               $section_sel .= '  <option value="'.$sec.'" />no section'."\n"; 
           } else {
               $section_sel .= '  <option value="'.$sec.'" />'.$sec."\n";
           }
       }
       my $output = '
           <select name="'.$elementname.'" multiple="true" size="'.$numvisible.'">
             '.$section_sel.'
           </select>';
       return $output;
   }
   
   sub access_date_settings {
       my ($r,$tabcol,$action,$formname,$stored,$image) = @_;
       my %lt = &Apache::lonlocal::texthash(
                   'sten' => 'Default start and end dates for group 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 ($start_table,$end_table) = &date_setting_table
                                       ($starttime,$endtime,$formname);
       &topic_bar($r,$tabcol,$image,$lt{'sten'});
       $r->print('
      <tr>
       <td>&nbsp;</td>
       <td colspan="3">'.$start_table.'</td>
      <tr>
    <tr>     <tr>
     <td colspan="4">&nbsp;</td>      <td colspan="4">&nbsp;</td>
    </tr>     </tr>
    <tr>     <tr>
     <td>&nbsp;</td>      <td>&nbsp;</td>
     <td colspan="3" align="left">      <td colspan="3">'.$end_table.'</td>
      <input type="button" value="Go to next step"       <tr>');
      onclick="javascript:nextPage(document.'.$formname.','."'pick_members'".')>  
     </td>  
    </tr>  
 </table>  
 ');  
     return;      return;
 }  }
   
 sub second_creation_form {  sub choose_members_form {
     my ($r,$cdom,$cnum,$tabcol,$formname,$groupname,$description,$startdate,      my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
                         $enddate,$tools,$functions,$users,$userdata,$idx) = @_;          $granularity,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
     my @regexps = ('user_','userpriv_');          $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
           $rowColor1,$rowColor2) = @_;
       my @regexps = ('user_','userpriv_','sec_');
       my %origmembers;
     $r->print(&Apache::lonhtmlcommon::echo_form_input(      $r->print(&Apache::lonhtmlcommon::echo_form_input(
                 ['origin','action','state','member','specificity'],\@regexps));           ['origin','action','state','page','member','specificity','branch',
     my %sectioncount = ();            'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'],
     my $numsec = &Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);           \@regexps));
     my %curr_groups = ();      my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);
     my $numgroups = &Apache::lonnet::get_coursegroups($cdom,$cnum,\%curr_groups);      $r->print('
     my $earlyout = '';  <table width="100%" cellpadding="0" cellspacing="0" border="0">
     my $exitmsg = '<b>Invalid group name</b><br /><br />The group name entered "'.  
                   $groupname.'" ';  
     my $dupmsg = 'Group names and section names used in a course must be unique.';   
     if ($groupname =~ /\W/) {  
         $earlyout = $exitmsg.'is not a valid name.<br />Group names may only contain letters, numbers or underscores';  
     }  
     if ($numsec) {  
         if (exists($sectioncount{$groupname})) {  
             $earlyout = $exitmsg.'can not be used as it is the name of a section   
                                                 in this course.<br />'.$dupmsg;  
         }  
     }  
     if ($numgroups) {  
         if (exists($curr_groups{$groupname})) {  
             $earlyout = $exitmsg.'can not be used as it is the name of an   
                                  existing group in this course.<br />'.$dupmsg;  
         }  
     }  
     if ($earlyout) {  
         $r->print('<table border="0" cellpadding="2" cellspacing="2">  
  <tr>  
   <td>&nbsp;</td>  
   <td>'.$earlyout.'</td>  
  </tr>  
  <tr>  
   <td colspan="2">&nbsp;</td>  
  </tr>  
  <tr>   <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td align="left">    <td colspan="3">
    <input type="button" name="previous" value = "Go to previous page"  ');
     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>      if ($earlyout) {
   </td>          $r->print($earlyout.'</td></tr>');
  </tr>          &display_navbuttons($r,$formname,$$states{$action}[$page-1],
 </table>                             $$navbuttons{'gtps'});
         ');          $r->print('</table>');
         return;          return;
       } 
       my ($specimg,$memimg);
       my @available = ();
       my @unavailable = ();
       &check_tools($functions,$tools,\@available,\@unavailable);
       if ($action eq 'create') {
           &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
                                   $functions,$startdate,$enddate,$groupname,
                                   $description,$granularity,\@available,
                                   \@unavailable);
           $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; 
                   }
               }
           }
     }      }
     my $rowColor1 = "#dddddd";      &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
     my $rowColor2 = "#eeeeee";                            $specimg,$tools,$stored,$toolprivs,
                             $fixedprivs,\@available,$formname);
       my $newusers = &pick_new_members($r,$action,$formname,$tabcol,$rowColor1,
                                       $rowColor2,\@available,$idx,$stored,
                                       $memimg,$users,$userdata,$granularity,
                                       \%origmembers);
       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'});
       }
       $r->print('</table>');
       return;
   }
   
   sub display_navbuttons {
       my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
       $r->print('
       <tr>
        <td colspan="4">&nbsp;</td>
       </tr>
       <tr>
        <td>&nbsp;</td>
        <td colspan="3">');
       if ($prev) {
           $r->print('
         <input type="button" name="previous" value = "'.$prevtext.'"
       onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
      &nbsp;&nbsp;&nbsp;');
       }
       if ($next) {
           $r->print('
         <input type="button" name="next" value="'.$nexttext.'"
    onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
       }
       $r->print('
        </td>
       </tr>
   ');
   }
   
   sub check_tools {
       my ($functions,$tools,$available,$unavailable) = @_;
       foreach my $item (sort(keys(%{$functions}))) {
           if (grep/^$item$/,@{$tools}) {
               push(@{$available},$item);
           } else {
               push(@{$unavailable},$item);
           }
       }
       return;
   }
   
   sub print_current_settings {
       my ($r,$action,$tabcol,$rowColor1,$rowColor2,$functions,$startdate,$enddate,
              $groupname,$description,$granularity,$available,$unavailable) =@_;
   
       my %lt = &Apache::lonlocal::texthash(
           grna => 'Group Name',
           desc => 'Description',
           grfn => 'Group Functions',
           gran => 'Granularity',
           dfac => 'Default access dates',
           ygrs => 'Your group selections',
           tfwa => 'The following settings will apply to the group:',
           difn => 'Different functionality<br />for different users:',
           stda => 'Start date',
           enda => 'End date:',
       );
     my $showstart = &Apache::lonlocal::locallocaltime($startdate);      my $showstart = &Apache::lonlocal::locallocaltime($startdate);
     my $showend = &Apache::lonlocal::locallocaltime($enddate);      my $showend;
     $r->print('<table border="0" cellpadding="0" cellspacing="20">      if ($enddate == 0) {
           $showend = &mt('No end date set'); 
       } else {
           $showend = &Apache::lonlocal::locallocaltime($enddate);
       }
       $r->print('<table border="0" cellpadding="0" cellspacing="20">');
       if ($action eq 'create') {
           $r->print('
 <tr>  <tr>
  <td><font face="arial,helvetica,sans-serif"><b>New group selections</b></font>   <td><font face="arial,helvetica,sans-serif"><b>'.$lt{'ygrs'}.'</b></font>
 <br />When you create the new group, the following settings will apply:  <br />'.$lt{'tfwa'}.'
  </td>   </td>
 </tr>  </tr>');
 <tr>      }
  <td>');      $r->print('<tr><td>');
     $r->print(&Apache::lonhtmlcommon::start_pick_box());      $r->print(&Apache::lonhtmlcommon::start_pick_box());
     $r->print('      $r->print('
   <tr>
    <td>
 <table cellspacing="1" cellpadding="4">  <table cellspacing="1" cellpadding="4">
  <tr bgcolor="'.$tabcol.'" align="center">   <tr bgcolor="'.$tabcol.'" align="center">
   <td><b>Group Name</b></td>    <td><b>'.$lt{'grna'}.'</b></td>
   <td><b>Description</b></td>    <td><b>'.$lt{'desc'}.'</b></td>
   <td><b>Group Functionality</b></td>    <td><b>'.$lt{'grfn'}.'</b></td>
   <td><b>Default access dates</b></td>    <td><b>'.$lt{'gran'}.'</b></td>
     <td><b>'.$lt{'dfac'}.'</b></td>
  </tr>   </tr>
  <tr bgcolor="'.$rowColor2.'">   <tr bgcolor="'.$rowColor2.'">
   <td valign="top"><small>'.$groupname.'</small></td>    <td valign="top"><small>'.$groupname.'</small></td>
   <td valign="top"><small>'.$description.'</small></td>    <td valign="top"><small>'.$description.'</small></td>
   <td>    <td>
 ');  ');
     my @available = ();      if (@{$available} > 0) {
     my @unavailable = ();  
     foreach my $item (sort(keys(%{$functions}))) {  
         if (grep/^$item$/,@{$tools}) {  
             push(@available,$item);  
         } else {  
             push(@unavailable,$item);  
         }  
     }  
     if (@available > 0) {  
         $r->print('<small><b>Available:</b></small>          $r->print('<small><b>Available:</b></small>
                     <table cellpadding="" cellspacing="1"><tr>');                      <table cellpadding="" cellspacing="1"><tr>');
         my $rowcell = int(@available/2) + @available%2;          my $rowcell = int(@{$available}/2) + @{$available}%2;
         for (my $i=0; $i<@available; $i++) {          for (my $i=0; $i<@{$available}; $i++) {
             if (@available > 3) {              if (@{$available} > 3) {
                 if ($i==$rowcell) {                  if ($i==$rowcell) {
                     $r->print('</tr><tr>');                      $r->print('</tr><tr>');
                 }                  }
             }              }
             $r->print('<td><small>'.$$functions{$available[$i]}.              $r->print('<td><small>'.$$functions{$$available[$i]}.
                                           '</small></td><td>&nbsp;</td>');                                            '</small></td><td>&nbsp;</td>');
         }          }
         if ((@available > 3) && (@available%2)) {          if ((@{$available} > 3) && (@{$available}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');              $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
         }          }
         $r->print('</tr></table><br />');          $r->print('</tr></table><br />');
     }      }
     if (@unavailable > 0) {      if (@{$unavailable} > 0) {
         $r->print('<small><b>Unavailable:</b></small>          $r->print('<small><b>Unavailable:</b></small>
                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');                      <table cellpadding="0" cellspacing="1"  border="0"><tr>');
         my $rowcell = int(@unavailable/2) + @unavailable%2;          my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2;
         for (my $j=0; $j<@unavailable; $j++) {          for (my $j=0; $j<@{$unavailable}; $j++) {
             if (@unavailable > 3) {              if (@{$unavailable} > 3) {
                 if ($j==$rowcell) {                  if ($j==$rowcell) {
                     $r->print('</tr><tr>');                      $r->print('</tr><tr>');
                 }                  }
             }              }
             $r->print('<td><small>'.$$functions{$unavailable[$j]}.              $r->print('<td><small>'.$$functions{$$unavailable[$j]}.
                                               '</small></td><td>&nbsp;</td>');                                                '</small></td><td>&nbsp;</td>');
         }          }
         if ((@unavailable > 3) && (@unavailable%2)) {          if ((@{$unavailable} > 3) && (@{$unavailable}%2)) {
             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');              $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
         }          }
         $r->print('</tr></table>');          $r->print('</tr></table>');
     }      }
     $r->print(<<"END");      $r->print(<<"END");
   </td>    </td>
   <td valign="top"><small><b>Start date:</b> $showstart<br />    <td valign="top"><small><b>$lt{'difn'}
       <b>End date:</b> $showend</small>    </b> $granularity</small> 
     <td valign="top"><small><b>$lt{'stda'}</b> $showstart<br />
         <b>$lt{'enda'}</b> $showend</small>
   </td>    </td>
  </tr>   </tr>
 </table>  </table>
   </td>
   </tr>
 END  END
     $r->print(&Apache::lonhtmlcommon::end_pick_box());      $r->print(&Apache::lonhtmlcommon::end_pick_box());
     my %members = ();      $r->print('</td></tr></table><br />');
       return;
   }
   
   sub pick_new_members {
       my ($r,$action,$formname,$tabcol,$rowColor1,$rowColor2,$available,$idx,
           $stored,$img,$users,$userdata,$granularity,$origmembers) = @_;
       my %lt = &Apache::lonlocal::texthash(
             'gpme' => 'Group membership',
             'addm' => 'Add members',
             'setf' => 'Set functionality',
             'func' => 'Functionality',
             'nome' => 'No members to add at this time.',
             'nnew' => 'There are no users to add as new members, as all users'.
                       ' matching the specified type(s), role(s), and/or '.
                       'section(s) are already affiliated with this group.',
             'yoma' =>  'You may need to use the '."'".'modify existing, past or '.
                        'future members'."'".' page if you need to re-enable '.
                        'or activate access for previous or future members.',
       );
       my %members;
       my $totalusers = 0;
       my $newusers = 0;
     foreach my $role (keys(%{$users})) {      foreach my $role (keys(%{$users})) {
         foreach my $user (keys(%{$$users{$role}})) {          foreach my $user (keys(%{$$users{$role}})) {
               $totalusers ++;
               if (ref($origmembers) eq 'HASH') {
                   if (exists($$origmembers{$user})) {
                       next;
                   }
               }    
             unless (defined($members{$user})) {              unless (defined($members{$user})) {
                 @{$members{$user}} = @{$$userdata{$user}};                  @{$members{$user}} = @{$$userdata{$user}};
                   $newusers ++;
             }              }
         }          }
     }      }
     $r->print('</td></tr></table><br />');  
     if (keys(%members) > 0) {      if (keys(%members) > 0) {
         if ($env{'form.granularity'} eq 'Yes') {          if (@{$available} > 0 && $granularity eq 'Yes') {
             $r->print('              $r->print(&check_uncheck_tools($r,$available));
 <script type="text/javascript">          }
 function checkAllTools(formname) {      }
 ');      &topic_bar($r,$tabcol,$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>   <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td colspan="2">    <td colspan="3">
     <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><nobr>
      <input type="button" value="check all"        <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>
        onclick="javascript:checkAll(document.$formname.member)" />        <input type="button" value="check all"
       &nbsp;&nbsp;          onclick="javascript:checkAllTools(document.'.$formname.')" />
      <input type="button" value="uncheck all"           &nbsp;&nbsp;
       onclick="javascript:uncheckAll(document.$formname.member)" />        <input type="button" value="uncheck all"
     </fieldset></nobr></td>  
 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>');       </fieldset></nobr></td>');
         }          }
         $r->print('</tr></table>          $r->print('</tr></table>
   </td>    </td>
   <td width="100%">&nbsp;</td>  
  </tr>   </tr>
  <tr>   <tr>
   <td colspan="4">&nbsp;</td>    <td colspan="4">&nbsp;</td>
Line 995  END Line 1598  END
   <td colspan="3">    <td colspan="3">
         ');          ');
         $r->print(&Apache::lonhtmlcommon::start_pick_box());          $r->print(&Apache::lonhtmlcommon::start_pick_box());
         $r->print(<<"END");          $r->print('
    <table border="0" cellpadding="4" cellspacing="1">     <table border="0" cellpadding="4" cellspacing="1">
     <tr bgcolor="$tabcol" align="center">      <tr bgcolor="'.$tabcol.'" align="center">
      <td><b>Add?</b></td>       <td><b>'.&mt('Add?').'</b></td>
      <td><b><a href="javascript:changeSort('fullname')">Name</a></b></td>       <td><b><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></b></td>
      <td><b><a href="javascript:changeSort('username')">Username</a></b>       <td><b><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></b>
      </td>       </td>
      <td><b><a href="javascript:changeSort('domain')">Domain</a></b></td>       <td><b><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></b></td>
      <td><b><a href="javascript:changeSort('id')">ID</a></b></td>       <td><b><a href="javascript:changeSort('."'id'".')">ID</a></b></td>
 END  ');
         if (@available > 0) {          if (@{$available} > 0) {
             $r->print('<td><b>Functionality</b></td>');              $r->print('<td><b>'.$lt{'func'}.'</b></td>');
         }          }
         $r->print('</tr>');          $r->print('</tr>');
           if (@{$available} > 0) {
               if ($granularity eq 'Yes') {
                   $r->print('<tr bgcolor="#cccccc">
    <td colspan="5">&nbsp;</td>
    <td align="center"><small><nobr><b>'.&mt('All:').'</b>&nbsp;');
                   foreach my $tool (@{$available}) {
                       $r->print('<label><input type="checkbox" name="togglefunc" '.
      'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
      ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
                   }
                   $r->print('</nobr></small></td></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 1040  END Line 1656  END
    <input type="checkbox" name="member" value="'.$user.'" /></td><td><small>'.     <input type="checkbox" name="member" value="'.$user.'" /></td><td><small>'.
     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.      $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
     $udom.'</small></td><td><small>'.$id.'</small></td>');      $udom.'</small></td><td><small>'.$id.'</small></td>');
                 if (@available > 0) {                  if (@{$available} > 0) {
                     $r->print('<td align="center"><small>');                       $r->print('<td align="center"><nobr><small>'.
                     foreach my $tool (@available) {                                '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                         if ($env{'form.granularity'} eq 'Yes') {                      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 1668  END
                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');                            $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                         }                          }
                     }                      }
                     $r->print('</small></td>');                      $r->print('</small></nobr></td>');
                 }                  }
                 $r->print('</tr>'."\n");                  $r->print('</tr>'."\n");
                 $rowNum ++;                  $rowNum ++;
Line 1059  END Line 1676  END
         }          }
         $r->print(&Apache::lonhtmlcommon::end_pick_box());          $r->print(&Apache::lonhtmlcommon::end_pick_box());
         $r->print('          $r->print('
        </td>
       </tr>');
       } else {
           $r->print('
       <tr>
        <td>&nbsp;</td>
        <td colspan="3">
   ');
           if ($totalusers > 0) {
               $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});
           } else { 
               $r->print($lt{'nome'});
           }
           $r->print('
        </td>
       </tr>');
       }
       return $newusers;
   }
   
   sub privilege_specificity {
       my ($r,$tabcol,$rowColor1,$rowColor2,$action,$img,$tools,$stored,
           $toolprivs,$fixedprivs,$available,$formname) = @_;
       my %lt = &Apache::lonlocal::texthash (
         'uprv' => 'User privileges',
         'frty' => '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.',
         'thar' => 'There are also additional privileges which can be set for '.
                   'some, or all, members. Please choose one of the following:',
         'fort' => 'For the types of functionality you have chosen to include '.
                   'there are no additional privileges which can be set for some '.
                   'or all members.',
         'eaty' => 'Each of the types of functionality includes standard '.
                   'privileges which apply to members with access to that '.
                   'functionality, and may also include additional privileges '.
                   'which can be set for specific members.',
         'cutg' => 'Currently the group is configured ',
         'sdif' => 'so different group members can receive different privileges.',
         'sall' => 'so all group members will receive the same privileges.',
         'algm' => 'All group members will receive the same privileges.',
         'smgp' => 'Some group members will receive different privileges from '.
                   'others.',
         'thwi' => 'These will be the privileges all group members receive, '. 
                   'if you selected the first option above.',
         'thes' => 'These will be the privileges given to members assigned '.   
                   'in the future, including via automatic group assignment '.
                   'for specific sections/roles ',
         'asyo' => 'As you have chosen not to include any functionality in the '.
                   'group, no default user privileges settings need to be set.',
         'plin' => 'Please indicate which <b>optional</b> privileges members '.
                   'will receive by default.',
         'oppr' => 'Optional privileges',
         'defp' => 'The default privileges new members will receive are:', 
       );
       my $totaloptionalprivs = 0;
       foreach my $tool (@{$tools}) {
           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (!exists($$fixedprivs{$tool}{$priv})) {
                   $totaloptionalprivs ++;
               }
           }
       }
       &topic_bar($r,$tabcol,$img,$lt{'uprv'});
       $r->print('
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
     ');
       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'});
               } 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('
   <br /><br /><label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr></label><br/>
   <label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr></label>
   </td>    </td>
  </tr>   </tr>
  <tr>   <tr>
   <td colspan="4">&nbsp;</td>    <td colspan="4">&nbsp;</td>
  </tr>');   </tr>');
         if (@available > 0) {          } else {
               $r->print('<input type="hidden" name="specificity" value="No" />');
           }
           if ($totaloptionalprivs) {
             $r->print('              $r->print('
  <tr bgcolor="'.$tabcol.'">   <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td valign="middle" align="left">    <td colspan="3">'.$lt{'plin'});
    <nobr><img src="/res/adm/pages/bl_step5.gif" valign="middle">&nbsp;</nobr>              if ($action eq 'create') {
   </td>                  $r->print(' '.$lt{'thwi'});
   <td align="left"><nobr>              }
    <font face="arial,helvetica,sans-serif">              $r->print('<br />'.$lt{'thes'});
     <b>User privileges</b>              if ($action eq 'create') {
    </font></nobr>                  $r->print('('.&mt('if enabled on the next page').').');
               } else {
                   $r->print('('.&mt('if enabled below').').');
               }
               $r->print('<br /><br />
   </td>    </td>
   <td width="100%">&nbsp;</td>  
  </tr>   </tr>
  <tr>   <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
     <td colspan="2"><table><tr>');
           &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});
           $r->print('
       </tr>
      </table>
     </td>
     <td width="100%">&nbsp;</td>
    </tr><tr>
     <td>&nbsp;</td>
   <td colspan="3">    <td colspan="3">
    <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('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algm'}.'<br /><br />');
         }          }
         $r->print('              &default_privileges($r,$action,$tabcol,$rowColor1,$rowColor2,
  <tr>                              $tools,$toolprivs,$fixedprivs,$available);
   <td>&nbsp;</td>  
   <td colspan="3">  
    <input type="button" name="previous" value = "Go to previous page"   
     onclick="javascript:backPage(document.'.$formname.','."'pick_name'".')"/>  
    &nbsp;&nbsp;&nbsp;  
    <input type="button" name="next" value="Go to next page"   
  onclick="javascript:nextPage(document.'.$formname.','."'pick_privs'".')" />  
   </td>  
  </tr>  
         ');  
     } else {      } else {
         $r->print('No members to add');          if ($action eq 'create') {
               $r->print($lt{'asyo'});
           } 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,$tabcol,$rowColor1,$rowColor2,$tools,
                                 $toolprivs,\@defprivs);
           }
     }      }
     $r->print('      $r->print('
    </table>  
   </td>    </td>
  </tr>   </tr>
 </table>');  ');
     return;      return;
 }  }
   
 sub third_creation_form {  sub default_privileges {
     my ($r,$cdom,$cnum,$tabcol,$formname,$startdate,$enddate,$tools,$functions,      my ($r,$action,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,
                $toolprivs,$fixedprivs,$userdata,$members,$usertools,$idx) = @_;          $fixedprivs,$available) = @_;
     my @regexps = ('userpriv_','allpriv_');      my %lt = &Apache::lonlocal::texthash(
     $r->print(&Apache::lonhtmlcommon::echo_form_input(                                  'addp' => 'Additional privileges',
                              ['origin','action','state'],\@regexps));                                  'fixp' => 'Fixed privileges',
     my %possibles = ();                                  'oppr' => 'Optional privileges',
     my %showboxes = ();                                  'func' => 'Function',
     my $totalboxes = 0;      );
     my $rowColor1 = "#dddddd";      $r->print(&Apache::lonhtmlcommon::start_pick_box());
     my $rowColor2 = "#eeeeee";      $r->print('<tr>
     my $numtools = 1 + @{$tools};                  <td bgcolor="'.$tabcol.'" valign="top">
                    <table cellspacing="0" cellpadding="1">
                     <tr>
                      <td valign="top"><b>'.$lt{'func'}.'</b></td>
                     </tr>
                     <tr>
                      <td valign="top"><b>'.$lt{'fixp'}.'</b></td>
                     </tr>
                     <tr>
                      <td valign="top"><b>'.$lt{'oppr'}.'</b></td>
                     </tr>
                    </table>
                   </td>
       ');
     foreach my $tool (@{$tools}) {      foreach my $tool (@{$tools}) {
         @{$showboxes{$tool}} = ();          $r->print('<td align="center" valign="top">
         foreach my $user (@{$members}) {                      <table cellspacing="0" cellpadding="1">
             if (exists($$usertools{$user}{$tool})) {                       <tr bgcolor="#cccccc">
                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {                        <td colspan="2" align="center"><b>'.$tool.'</b></td>
                     unless (exists($$fixedprivs{$tool}{$priv})) {                       </tr>
                         push(@{$possibles{$user}},$priv);          ');
                         unless(grep(/^$priv$/,@{$showboxes{$tool}})) {          my $privcount = 0;
                             push(@{$showboxes{$tool}},$priv);          my $fixed = '';
                             $totalboxes ++;          my $dynamic = '';
                         }          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (exists($$fixedprivs{$tool}{$priv})) {
                   $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" />'.$$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;';
                     }                      }
                 }                  }
               } else {
                   $privcount ++;
                   if ($privcount == 3) {
                       $dynamic .= '</tr>
                                    <tr bgcolor="'.$rowColor1.'">'."\n";
                   }
                   $dynamic .= '<td><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></td>'."\n";
             }              }
         }          }
     }          if ($dynamic eq '') {
     if ($totalboxes > 0) {              $dynamic = '<td>None</td>'."\n";
         $r->print('  
 <script type="text/javascript">  
 function checkAllTools(formname) {  
 ');  
         foreach my $tool (sort(keys(%showboxes))) {  
             foreach my $priv (@{$showboxes{$tool}}) {  
                 $r->print('  checkAll(formname.userpriv_'.$priv.');'."\n");  
             }  
         }          }
         $r->print('          if ($privcount < 3) {
               $dynamic .= '</tr>
                            <tr bgcolor="'.$rowColor1.'">
                             <td colspan="2">&nbsp;</td>'."\n";
           } elsif ($privcount%2) {
               $dynamic = '<td>&nbsp;</td>'."\n";
           }
           $r->print('<tr bgcolor="'.$rowColor2.'">
                       <td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td>
                      </tr>
                      <tr bgcolor="'.$rowColor1.'">'."\n".$dynamic.'</tr>'."\n".'</table>'."\n".'</td>
           ');
       }
       $r->print('</tr>'."\n");
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
       $r->print('<br />');
       return;
 }  }
 function uncheckAllTools(formname) {  
 ');  sub display_defprivs {
         foreach my $tool (sort(keys(%showboxes))) {      my ($r,$tabcol,$rowColor1,$rowColor2,$tools,$toolprivs,$defprivs) = @_;
             foreach my $priv (@{$showboxes{$tool}}) {      my %lt = &Apache::lonlocal::texthash(
                 $r->print('  uncheckAll(formname.userpriv_'.$priv.');'."\n");                                  'priv' => 'Privileges',
                                   'func' => 'Function',
       );
       $r->print(&Apache::lonhtmlcommon::start_pick_box());
       $r->print('<tr>');
       my $numrows = 0;
       my %currprivs;
       foreach my $tool (@{$tools}) {
           @{$currprivs{$tool}} = ();
           foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
               if (ref($defprivs) eq 'ARRAY') {
                   if (grep/^\Q$priv\E$/,@{$defprivs}) {
                       push(@{$currprivs{$tool}},$priv);
                   }
             }              }
         }          }
         $r->print('          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;
 }  }
 </script>  
        ');  
    }  sub change_members_form {
    $r->print(<<"END");      my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
           $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,
           $granularity,$specificity,$idx,$states,$navbuttons,$rowColor1,
           $rowColor2) = @_;
       my %lt = &Apache::lonlocal::texthash(
                                            grse => 'Group settings',
                                            mogm => 'Modify group 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 />  <br />
 <table width="100%" cellpadding="0" cellspacing="0" border="0">  <table width="100%" cellpadding="0" cellspacing="0" border="0">
  <tr bgcolor="$tabcol">  ');
       &topic_bar($r,$tabcol,1,$lt{'grse'});
       $r->print('
    <tr>
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td valign="middle" align="left">    <td colspan="3">
    <nobr><img src="/res/adm/pages/bl_step6.gif" valign="middle">&nbsp;</nobr>  ');
       &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
                               $functions,$startdate,$enddate,$groupname,
                             $description,$granularity,\@available,\@unavailable);
   $r->print('
   </td></tr><tr><td colspan="4">&nbsp;</td></tr>');
       &topic_bar($r,$tabcol,2,$lt{'mogm'});
       $r->print('
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
   ');
       &current_membership($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,
                           $rowColor2,$groupname,\@available,\@unavailable,
                           $fixedprivs,$granularity,$specificity);
       $r->print('</td>');
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       $r->print('</table>');
       return;
   }
   
   sub current_membership {
       my ($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,$rowColor2,$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 Functionality',
                                             'chpr' => 'Change Privileges' 
                                           );
       if (keys(%membership) > 0) {
           my %current = ();
           my %allnames = ();
           my $hastools = 0;
           my $addtools = 0;
           my $num_reenable = 0;
           my $num_activate = 0;
           my $num_expire - 0;
           foreach my $key (sort(keys(%membership))) {
               if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {
                   my $uname = $1;
                   my $udom = $2;
                   my $user = $uname.':'.$udom;
                   my($end,$start,@userprivs) = split(/:/,$membership{$key});
                   unless ($start == -1) {
                       $allnames{$udom}{$uname} = 1;
                       %{$current{$user}} = ();
                       $current{$user}{uname} = $uname;
                       $current{$user}{udom} = $udom;
                       $current{$user}{start} = 
                                        &Apache::lonlocal::locallocaltime($start);
                       if ($end == 0) {
                           $current{$user}{end} =  'No end date';
                       } else {
                           $current{$user}{end} = 
                                        &Apache::lonlocal::locallocaltime($end);
                       }
                       my $now = time;
                       if (($end > 0) && ($end < $now)) {
                           $current{$user}{changestate} = 'reenable';
                           $num_reenable++;
                       } elsif (($start > $now)) {
                           $current{$user}{changestate} = 'activate';
                           $num_activate ++;
                       } else {
                           $current{$user}{changestate} = 'expire';
                           $num_expire ++;
                       }
                       @{$current{$user}{currtools}} = ();
                       @{$current{$user}{newtools}} = ();
                       if (@userprivs > 0) {
                           foreach my $tool (sort(keys(%{$fixedprivs}))) {
                               foreach my $priv (keys(%{$$fixedprivs{$tool}})) {
                                   if (grep/^$priv$/,@userprivs) {
                                       push(@{$current{$user}{currtools}},$tool);
                                       last;
                                   }
                               }
                           }
                           $hastools = 1;
                       }
                       if (@{$available} > 0) {
                           if (@{$current{$user}{currtools}} > 0) {
                               if ("@{$available}" ne "@{$current{$user}{currtools}}") {
                                   foreach my $tool (@{$available}) {
                                       unless (grep/^$tool$/,@{$current{$user}{currtools}}) {
                                           push(@{$current{$user}{newtools}},$tool);
                                       }
                                   }
                               }
                           } else {
                               @{$current{$user}{newtools}} = @{$available};
                           }
                           if (@{$current{$user}{newtools}} > 0) {
                               $addtools = 1;
                           }
                       }
                   }
               }
           }
           if (keys(%current) > 0) {
               my %idhash;
               foreach my $udom (keys(%allnames)) {
                   %{$idhash{$udom}} = &Apache::lonnet::idrget($udom,
                                                   keys(%{$allnames{$udom}}));
                   foreach my $uname (keys(%{$idhash{$udom}})) {
                       $current{$uname.':'.$udom}{'id'} = $idhash{$udom}{$uname};
                   }
                   foreach my $uname (keys(%{$allnames{$udom}})) {
                       $current{$uname.':'.$udom}{'fullname'} =
                                   &Apache::loncommon::plainname($uname,$udom,
                                                                     'lastname');
                   }
               }
               $r->print('
    <tr>
     <td>&nbsp;</td>
     <td colspan="2">
      <table>
       <tr>');
               if ($num_expire) {
                   &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});
               }
               if ($num_reenable) {
                   &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});
               }
               if ($num_activate) {
                   &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'});
               }
               &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'});
               if (@{$available} > 0) {
                   if ($specificity eq 'Yes') {
                       &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'});
                   }
                   if ($granularity eq 'Yes') {
                       $r->print(&check_uncheck_tools($r,$available));
                       $r->print('
        <td>
         <nobr>
          <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>
          <input type="button" value="check all"
          onclick="javascript:checkAllTools(document.'.$formname.')" />
          &nbsp;&nbsp;
          <input type="button" value="uncheck all"
           onclick="javascript:uncheckAllTools(document.'.$formname.')" />
         </fieldset>
        </nobr>
       </td>
   ');
                   }
               }
               $r->print(<<"END");
      </tr>
     </table>
   </td>    </td>
   <th align="left"><nobr>  
     Group member privileges  
    </nobr>  
   </th>  
   <td width="100%">&nbsp;</td>    <td width="100%">&nbsp;</td>
  </tr>   </tr>
  <tr>   <tr>
Line 1188  function uncheckAllTools(formname) { Line 2191  function uncheckAllTools(formname) {
   <td>&nbsp;</td>    <td>&nbsp;</td>
   <td colspan="3">    <td colspan="3">
 END  END
     if ($env{'form.specificity'} eq 'Yes') {              $r->print(&Apache::lonhtmlcommon::start_pick_box());
         $r->print('              $r->print(<<"END");
    <table border="0" cellspacing="2" cellpadding="2" border="0">     <table border="0" cellpadding="4" cellspacing="1">
     <tr>      <tr bgcolor="$tabcol" align="center">
      <td valign="top">       <td><b>$lt{'actn'}</b></td>
 ');       <td><b><a href="javascript:changeSort('fullname')">$lt{'name'}</a></b></td>
         $r->print(&Apache::lonhtmlcommon::start_pick_box());       <td><b><a href="javascript:changeSort('username')">$lt{'usnm'}</a></b>
         $r->print(<<"END");       </td>
    <tr bgcolor="$tabcol">       <td><b><a href="javascript:changeSort('domain')">$lt{'doma'}</a></b></td>
     <th><b>Fullname</th>       <td><b><a href="javascript:changeSort('id')">ID</a></b></td>
     <th><b>Username</th>       <td><b><a href="javascript:changeSort('start')">$lt{'stda'}</a></b></td>
     <th>Domain</th>       <td><b><a href="javascript:changeSort('end')">$lt{'enda'}</a></b></td>
     <th colspan="$numtools">Additional Privileges</th>  
   </tr>  
 END  END
     }              my $colspan = 0;
     if ($env{'form.specificity'} eq 'Yes') {              if ($hastools) {
         &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,                  $r->print('<td><b>'.$lt{'curf'}.'</b></td>');
                              $usertools,$toolprivs,$fixedprivs,$userdata,$idx);                  $colspan ++;  
     }              }
     if ($env{'form.specificity'} eq 'Yes') {              if ($addtools) {
         $r->print('</td>');                  $r->print('<td><b>Additional Functionality</b></td>');
         $r->print(&Apache::lonhtmlcommon::end_pick_box());                  $colspan ++;
         $r->print('<td>&nbsp;</td>              }
                <td>&nbsp;</td><td valign="top">');              $r->print('</tr>');
         my @toolboxes = sort(keys(%showboxes));              if ($colspan) {
         foreach my $tool (@{$tools}) {                  if ($granularity eq 'Yes') {
             if (@{$showboxes{$tool}} > 0) {                       $r->print('<tr bgcolor="#cccccc">
                 $r->print('<table class="thinborder"><tr bgcolor="'.$tabcol.   <td colspan="7">&nbsp;</td>
                       '"><th>'.$tool.'</th></tr>');   <td colspan="'.$colspan.'" align="center"><small><nobr><b>'.&mt('All:').
                 foreach my $priv (@{$showboxes{$tool}}) {    '</b>&nbsp;');
                     $r->print(qq|                      foreach my $tool (@{$available}) {
        <tr><td>                          $r->print('<label><input type="checkbox" name="togglefunc"'.
        <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>     ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
        <input type="button" value="check all"     ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
          onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />                      }
        &nbsp;                       $r->print('</nobr></small></td></tr>');
        <input type="button" value="uncheck all"                  }
         onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />              }
       </nobr></fieldset></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);
                   }
               }
               my $rowNum = 0;
               my $rowColor;
               foreach my $key (sort(keys(%Sortby))) {
                   foreach my $user (@{$Sortby{$key}}) {
                       if ($rowNum %2 == 1) {
                           $rowColor = $rowColor1;
                       } else {
                           $rowColor = $rowColor2;
                       }
                       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('<tr bgcolor="'.$rowColor.'">
                                   <td><small>');
                       if ($current{$user}{changestate} eq 'reenable') {
                           $r->print('<nobr><label>'. 
      '<input type="checkbox" name="reenable" value="'.$user.'" />'.
      $lt{'reen'}.'</label></nobr><br />');
                       } elsif ($current{$user}{changestate} eq 'expire') {
                           $r->print('<nobr><label>'.
      '<input type="checkbox" name="expire" value="'.$user.'" />'.
      $lt{'expi'}.'</label></nobr><br />');
                       } elsif ($current{$user}{changestate} eq 'activate') {
                           $r->print('<nobr><label>'.
      '<input type="checkbox" name="activate" value="'.$user.'" />'.
      $lt{'acti'}.'</label></nobr><br />');
                       }
                       $r->print('<nobr><label>'.
      '<input type="checkbox" name="deletion" value="'.$user.'" />'.
      $lt{'dele'}.'</label></nobr>');
                       if ($specificity eq 'Yes') {
                           $r->print('<br /><nobr><label>'.
      '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
      '</label></nobr>');
                       }
                       $r->print('
      </td>
      <td><small>'.
       $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
       $udom.'</small></td><td><small>'.$id.'</small></td><td><small>'.$start.
       '</small></td><td><small>'.$end.'</small></td>');
                       if ($hastools) {
                           $r->print('<td align="left"><small><nobr>'.
                                     '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                           foreach my $tool (@{$current{$user}{currtools}}) {
                               if ($granularity eq 'Yes') {
                                   $r->print('<label><input type="checkbox" '. 
                                          'checked="checked" '. 
                                          'name="user_'.$tool.'" value="'.
                                          $user.'" />'.$tool.'</label>');
                                } else {
                                  $r->print('<input type="hidden" '.
                                          'checked="checked" '.
                                          'name="user_'.$tool.'" value="'.
                                          $user.'" />'.$tool);
                                }
                                $r->print('&nbsp;&nbsp;&nbsp;');
                           }
                           $r->print('</nobr></small></td>');
                       }
                       if ($addtools) {
                           $r->print('<td align="left"><small>');
                           if ($granularity eq 'Yes') {
                               foreach my $tool (@{$current{$user}{newtools}}) {
                                   $r->print('<nobr><label><input type="checkbox"  
                                             name="user_'.$tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</label></nobr>&nbsp;&nbsp;&nbsp;');
                               }
                           } else {
                               foreach my $tool (@{$current{$user}{newtools}}) {
                                   $r->print('<nobr><input type="hidden" 
                                             name="user_'. $tool.'" value="'.
                                             $user.'" />'.$tool.
                                             '</nobr>&nbsp;&nbsp;&nbsp;');
                               }
                           }
                           $r->print('</small></td>');
                       }
                       $r->print('</tr>'."\n");
                       $rowNum ++;
                 }                  }
                 $r->print('</table><br /><br />');  
             }              }
               $r->print(&Apache::lonhtmlcommon::end_pick_box());
               $r->print('
     </td>
    </tr>');
         }          }
         $r->print('</td></tr></table>');      }
       return;
   }
   
   sub check_uncheck_buttons {
       my ($r,$formname,$field,$title,$colspan) = @_;
       $r->print('
        <td '.$colspan.'>
         <nobr>
          <fieldset>
          <legend><b>'.$title.'</b></legend>
          <input type="button" value="check all"
          onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
          &nbsp;&nbsp;
          <input type="button" value="uncheck all"
          onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
          </fieldset>
         </nobr>
        </td>
   ');
   }
   
   
   sub change_privs_form {
       my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,
          $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,
          $memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$rowColor1,
          $rowColor2) = @_;
       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 group.',
       );
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
            ['origin','action','state','page','sortby'],\@regexps));
       if ($env{'form.branch'} eq 'adds') {
           $nexttext = $$navbuttons{'adme'};
     } else {      } else {
         $r->print(&Apache::lonhtmlcommon::start_pick_box());          $nexttext = $$navbuttons{'mose'};
         $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>');      $r->print('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');
         foreach my $tool (@{$tools}) {      &topic_bar($r,$tabcol,3,&mt('Members to delete or expire'));
             $r->print('<td align="center" valign="top"><table cellspacing="0" cellpadding="1"><tr bgcolor="#cccccc">'.      my $exp_or_del = 0;
                        '<td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');      if (ref($$memchg{'deletion'}) eq 'ARRAY') {
             my $privcount = 0;          if (@{$$memchg{'deletion'}} > 0) {
             my $fixed = '';              $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'tode'}.':</b><br /><ul>');
             my $dynamic = '';              foreach my $user (@{$$memchg{'deletion'}}) {
             foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {                  $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                 if (exists($$fixedprivs{$tool}{$priv})) {                            '&nbsp;('.$user.')</li>');
                     $fixed .= '<input type="hidden" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';              }
                 } else {              $r->print('</ul></td><tr><td colspan="4">&nbsp;</td></tr>');
                     $privcount ++;              $exp_or_del += @{$$memchg{'deletion'}};
                     if ($privcount == 3) {          }
                         $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'">';      }
       if (ref($$memchg{'expire'}) eq 'ARRAY') {
           if (@{$$memchg{'expire'}} > 0) {
               $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'toex'}.':</b><br /><ul>');
               foreach my $user (@{$$memchg{'expire'}}) {
                   $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                             '&nbsp;('.$user.')</li>');
               }
               $r->print('</ul></td><tr><td colspan="4">&nbsp;</td></tr>');
               $exp_or_del += @{$$memchg{'expire'}};
           }
       }
       if (!$exp_or_del) {
           $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'nome'}.
                     '</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
       }
       
       &topic_bar($r,$tabcol,4,&mt('Group member privileges'));
   
       my $numchgs = &member_privileges_form($r,$tabcol,$action,$formname,$tools,
                                             $toolprivs,$fixedprivs,$userdata,
                                             $usertools,$idx,$memchg,$states,
                                             $stored,$rowColor1,$rowColor2);
       $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
       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);
       }
       $r->print('</table>');
       return;
   }
   
   sub add_members_form {
       my ($r,$tabcol,$action,$formname,$page,$startdate,$enddate,$groupname,
           $description,$granularity,$sectioncount,$tools,$functions,$stored,
           $states,$navbuttons,$rowColor1,$rowColor2) = @_; 
       $r->print(' <br />
   <table width="100%" cellpadding="0" cellspacing="0" border="0">
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
   ');
       my @available = ();
       my @unavailable = ();
       &check_tools($functions,$tools,\@available,\@unavailable);
       &print_current_settings($r,$action,$tabcol,$rowColor1,$rowColor2,
                               $functions,$startdate,$enddate,$groupname,
                               $description,$granularity,\@available,\@unavailable);
       $r->print('
      </td>
     </tr>
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>');
   
       &membership_options($r,$action,$formname,$tabcol,$sectioncount,1);
       my $nexttext = $$navbuttons{'gtns'};
       my $prevtext = $$navbuttons{'gtpp'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       $r->print('
    </table>');
       return;
   }
   
   sub choose_privs_form {
       my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$startdate,$enddate,
          $tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,
          $states,$stored,$sectioncount,$navbuttons,$rowColor1,$rowColor2) = @_;
   
       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('<br /><table width="100%" cellpadding="0" cellspacing="0" border="0">');
       &topic_bar($r,$tabcol,6,&mt('Group member privileges'));
   
       &member_privileges_form($r,$tabcol,$action,$formname,$tools,$toolprivs,
                               $fixedprivs,$userdata,$usertools,$idx,undef,
                               $states,$stored,$rowColor1,$rowColor2);
   
       $r->print('</td></tr><tr><td colspan="4">&nbsp;</td></tr>');
       if ($action eq 'create') {
           if (keys(%{$sectioncount}) > 0) {
               my $img1 = 7;
               my $img2 = 8;
               &mapping_options($r,$action,$formname,$page,$tabcol,$sectioncount,
                                $states,$stored,$navbuttons,$img1,$img2,
                                $rowColor1,$rowColor2);
           }
       }
       my $prevtext = $$navbuttons{'gtps'};
       &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                           $$states{$action}[$page+1],$nexttext);
       $r->print('</table>');
       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 ++;
                                   }
                               }
                           }
                     }                      }
                     $dynamic .= '<td><input type="checkbox" name="allpriv_'.$priv.'" value="all" />'.$$toolprivs{$tool}{$priv}.'</td>';  
                 }                  }
             }              }
             if ($dynamic eq '') {              if ($totalboxes > 0) {
                 $dynamic = '<td>None</td>';                   $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) {
   ');
                   foreach my $tool (sort(keys(%{$showboxes}))) {
                       foreach my $priv (@{$$showboxes{$tool}}) {
                           $r->print('  uncheckAll(formname'.$prefix.$priv.');'."\n");
                       }
                   }
                   $r->print('
   }
   </script>
                   ');
             }              }
             if ($privcount < 3) {          }
                 $dynamic .= '</tr><tr bgcolor="'.$rowColor1.'"><td colspan="2">&nbsp;</td>';      }
             } elsif ($privcount%2) {      return $totalboxes;
                 $dynamic = '<td>&nbsp;</td>';  }
   
   sub member_privileges_form {
       my ($r,$tabcol,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,
           $usertools,$idx,$memchg,$states,$stored,$rowColor1,$rowColor2) = @_;
       my %lt = &Apache::lonlocal::texthash(
               'addp' => 'Additional privileges',
               'fixp' => 'Fixed privileges',
               'oppr' => 'Optional privileges',
               'func' => 'Function',
               'forf' => 'For the functionality you have chosen to include '.
                         'there are no optional privileges to set besides '.
                         'the standard privileges.',
               'algr' => 'All group members will receive the same privileges.',
               'asno' => 'As no group members are being added, '.
                         'there are no specific user privileges to set.',
               'asng' => 'As no group tools will be made available to users, '.
                         'there are no specific user privileges to set.',
               'nogm' => 'No group member privileges to display or set, '.
                         'as you have not indicated that you will be activating,'.
                         ' re-enabling, changing privileges, or adding/removing '.
                         'functionality for any current members ',
               'full' => 'Fullname',
               '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 {
           @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);
             }              }
             $r->print('<tr bgcolor="'.$rowColor2.'"><td colspan="2" align="center"><nobr>'.$fixed.'</nobr></td></tr><tr bgcolor="'.$rowColor1.'">'.$dynamic.'</tr></table></td>');          } else {
               @currmembers = sort(keys(%{$usertools}));
           }
           $numchgs = @currmembers;
           if (!$numchgs) {
               $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'nogm'}); 
               return $numchgs;
         }          }
         $r->print('</tr>');  
         $r->print(&Apache::lonhtmlcommon::end_pick_box());  
     }      }
     $r->print('</td></tr>   
       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('
    <tr>
     <td>&nbsp;</td>
     <td colspan="3">
      <table border="0" cellspacing="2" cellpadding="2" border="0">
       <tr>
   ');
                       foreach my $tool (@{$tools}) {
                           if (@{$showboxes{$tool}} > 0) {
                               $r->print('<td valign="top">');
                               $r->print('<table class="thinborder"><tr bgcolor="'.
                                         $tabcol.'"><th colspan="'.$colspan.'">'.
                                         $tool.'</th></tr><tr>');
                               my $privcount = 0;
                               foreach my $priv (@{$showboxes{$tool}}) {
                                   $privcount ++;
                                   if (($privcount == @{$showboxes{$tool}}) && 
                                       ($privcount > 1)) {
                                       if ($privcount%$numcells) {
                                           $r->print('<td colspan="'.$colspan.'">');
                                       } else {
                                           $r->print('<td>');
                                       }
                                   } else {
                                       $r->print('<td>');
                                   }
                                   $r->print(qq|
          <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
          <nobr>
          <input type="button" value="check all"
            onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
          &nbsp;
          <input type="button" value="uncheck all"
           onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
         </nobr></fieldset><br />|);
                                   $r->print('</td>');
                                   if ($privcount < @{$showboxes{$tool}}) {
                                       if (@{$showboxes{$tool}} > 2) {
                                           if ($privcount%$numcells == 0) {
                                               $r->print('</tr><tr>');
                                           }
                                       } else {
                                           $r->print('<tr></tr>');
                                       }
                                   }
                               }
                               $r->print('</tr></table></td><td>&nbsp;</td>');
                           }
                       }
                       $r->print('</tr></table></td></tr>');
                       $r->print('<tr><td colspan="4">&nbsp;</td></tr>');
                   }
                   $r->print('<tr><td>&nbsp;</td><td colspan="3">');
                   $r->print(&Apache::lonhtmlcommon::start_pick_box());
                   $r->print(<<"END");
      <tr bgcolor="$tabcol">
       <th><b>$lt{'full'}</th>
       <th><b>$lt{'user'}</th>
       <th>$lt{'doma'}</th>
       <th colspan="$numtools">$lt{'addp'}</th>
     </tr>
   END
                   &member_privs_entries($r,$tabcol,$rowColor1,$rowColor2,
                                         $usertools,$toolprivs,$fixedprivs,
                                         $userdata,$idx,\@showtools,\@defprivs,
                                         \@excluded);
                   $r->print('</td>');
                   $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   $r->print('</td></tr>
  <tr>   <tr>
   <td colspan="4">&nbsp;</td>    <td colspan="4">&nbsp;</td>
  </tr>   </tr>
   ');
               } else {
                   $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'forf'}.
                             '<br />');
                   &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,
                               $toolprivs,\@defprivs);
                                                                                         
               }
           } else {
               if (keys(%{$usertools}) > 0) {
                   $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'algr'}.
                             '<br /><br />');
                   &display_defprivs($r,$tabcol,$rowColor1,$rowColor2,$tools,
                               $toolprivs,\@defprivs);
               } else {
                   $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asno'}.
                             '<br />');
               }
           }
       } else {
           $r->print('<tr><td>&nbsp;</td><td colspan="3">'.$lt{'asng'});
       }
       return $numchgs;
   }
   
   sub process_request {
       my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$groupname,$description,
           $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,
           $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,
           $sectioncount,$stored,$rowColor1,$rowColor2) = @_;
   
       $r->print(&Apache::lonhtmlcommon::echo_form_input(
                                    ['origin','action','state','page','sortby']));
   
       my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum);
       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>  
     ');      my @defprivs = ();
     $r->print('      if ($action eq 'create' || $state eq 'chgresult') { 
 </table>');          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 {
           @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); 
       }
       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);
       }
     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) = @_;
     $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 = &Apache::lonnet::escape($description);
       my @single_attributes = ('description','functions','startdate','enddate',
                                'creation','modified','creator','granularity',
                                'specificity','autoadd','autodrop');
       my @mult_attributes = ('roles','types','sectionpick','defpriv');
                                                                                       
       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'},
                      );
       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);
               if (grep/^_all$/,@autosections) {
                   @autosections = sort {$a cmp $b} keys(%{$sectioncount});
               }
               $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 $put_result = &create_homepage($cdom,$cnum,$groupname,
                                                 \%groupinfo,$tools);
               $r->print('Group '.$groupname.' was created.<br />');
           } else {
               $r->print('Group '.$groupname.' was updated.<br />');
           }
       } else {
           my %actiontype = (
                             'create' => 'creating',
                             'modify' => 'modifying',
                            );
           &Apache::lonnet::logthis('Failed to store group '.$groupname.
                                    'in course: '.$cnum.' in domain: '.$cdom);
           $r->print(&mt('An error occurred when [_1] the new group. '.
                         'Please try again.',$actiontype{$action}));
       }
       return $result;
   }
   
   sub process_membership {
       my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,
           $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg)=@_;
       my %usersettings = ();
       my %added= ();
       my %failed = ();
       my $num_ok = 0;
       my $num_fail = 0;
     my %group_privs = ();      my %group_privs = ();
     my %tooltype = ();      my %tooltype = ();
   
     foreach my $tool (@{$tools}) {      foreach my $tool (@{$tools}) {
         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {          foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
             $tooltype{$priv} = $tool;              $tooltype{$priv} = $tool;
             if ($env{'form.specificity'} eq 'Yes') {              if ($specificity eq 'Yes') {
                 my @users =                  my @users =
                   &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);                    &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
                 foreach my $user (@users) {                  foreach my $user (@users) {
                     $group_privs{$user} .= $priv.':';                      $group_privs{$user} .= $priv.':';
                       if ($state eq 'memresult') { 
                           unless (exists($$usertools{$user}{$tool})) {
                               $$usertools{$user}{$tool} = 1;
                           }
                       }
                 }                  }
             } else {              } else {
                 if (defined($env{'form.allpriv_'.$priv})) {                  if (@{$defprivs} > 0) {
                     foreach my $user (@{$members}) {                      foreach my $priv (@{$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 2933  $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');      if ($state eq 'memresult') {
             return;           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'}};
           }
           if (@expire + @deletion > 0) {
               my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                                                                      $groupname);
               foreach my $user (@expire) {
                   my ($currend,$currstart,@userprivs) = 
                                     split(/:/,$membership{$groupname.':'.$user});
                   $group_privs{$user} = join(':',@userprivs); 
                   if ($currstart > $now) {
                       $currstart = $now;
                   }
                   $usersettings{$groupname.':'.$user} = $now.':'.$currstart.':'.
                                                         $group_privs{$user};
                   if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                          $user,$now,$currstart,
                                                          $group_privs{$user}) eq 'ok') {
                       push(@{$added{'expired'}},$user);
                       $num_ok ++;
                   } else {
                       push(@{$failed{'expired'}},$user);
                       $num_fail ++;
                   }
               }
               foreach my $user (@deletion) {
                   $usersettings{$groupname.':'.$user} = $now.':-1:';
                   if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                          $user,$now,'-1','')
                                                            eq 'ok') {
                       push(@{$added{'deleted'}},$user);
                       $num_ok ++;
                   } else {
                       push(@{$failed{'deleted'}},$user);
                       $num_fail ++;
                   }
               }
         }          }
     }      }
     my $groupentry;  
     foreach my $item (@attributes) {      foreach my $user (sort(keys(%{$usertools}))) {
         $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;          my $type;
           my $start = $startdate;
           my $end = $enddate;
           if ($state eq 'memresult') {
               $type = 'modified';
               if (@activate > 0) {
                   if (grep/^$user$/,@activate) {
                       $start = $now;
                       $type = 'activated';
                   }
               }
               if (@reenable > 0) {
                   if (grep/^$user$/,@reenable) {
                       $type = 'reenabled';
                   }
               }
           } else {
               $type = 'added';
           }
           $usersettings{$groupname.':'.$user} = $end.':'.$start.':'.
                                                 $group_privs{$user};
           if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                                                   $user,$end,$start,
                                                   $group_privs{$user}) eq 'ok') {
               push(@{$added{$type}},$user);
               $num_ok ++;
           } else {
               push(@{$failed{$type}},$user);
               $num_fail ++;
           }
     }      }
     my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,      my $roster_result = &Apache::lonnet::modify_coursegroup_membership($cdom,
                                                           \%groupsettings);                                                         $cnum,\%usersettings);
     if ($result eq 'ok') {      if ($num_ok) {
         my $put_result = &create_homepage($cdom,$cnum,$groupname,\%groupinfo,$tools);          foreach my $type (sort(keys(%added))) { 
         foreach my $user (sort(@{$members})) {              $r->print(&mt('The following users were successfully [_1]',$type));
             $usersettings{$groupname.':'.$user} = $enddate.':'.$startdate.':'.$group_privs{$user};              if (!($type eq 'deleted' ||  $type eq 'expired')) {   
             if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,                  $r->print(&mt(' with the following privileges'));
                   $user,$enddate,$startdate,$group_privs{$user}) eq 'ok') {              }
                 push(@added,$user);              $r->print(':<br />');
             } else {              foreach my $user (@{$added{$type}}) {
                 push(@failed,$user);                  my $privlist = '';
                   if (!($type eq 'deleted' ||  $type eq 'expired')) {
                       $privlist = ': ';
                       my @privs = split(/:/,$group_privs{$user});
                       my $curr_tool = '';
                       foreach my $priv (@privs) {
                           unless ($curr_tool eq $tooltype{$priv}) {
                               $curr_tool = $tooltype{$priv};
                               $privlist .= '<b>'.$curr_tool.'</b>: ';
                           }
                           $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
                       }
                       $privlist =~ s/, $//;
                   }
                   $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.$privlist.'<br />');
             }              }
         }          }
         my $roster_result = &Apache::lonnet::modify_coursegroup_membership(      }
              $cdom,$cnum,\%usersettings);      if ($num_fail) {
         $r->print('          foreach my $type (sort(keys(%failed))) {
 Group '.$groupname.' was created.<br />');              $r->print(&mt('The following users could not be [_1], because an error occurred:<br />',$type));
         if (@added > 0) {              foreach my $user (@{$failed{$type}}) {
             $r->print('Users were added with following privileges:<br />');  
             foreach my $user (@added) {  
                 my @privs = split(/:/,$group_privs{$user});  
                 my $privlist= '';  
                 my $curr_tool = '';  
                 foreach my $priv (@privs) {  
                     unless ($curr_tool eq $tooltype{$priv}) {  
                         $curr_tool = $tooltype{$priv};  
                         $privlist .= '<b>'.$curr_tool.'</b>: ';  
                     }  
                     $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';  
                 }  
                 $privlist =~ s/, $//;  
                 $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.': '.$privlist.'<br />');  
             }  
         }  
         if (@failed > 0) {  
             $r->print('Addition of the following users was unsuccessful:<br />');  
             foreach my $user (@failed) {  
                 $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');                  $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
             }              }
         }          }
         if ($roster_result eq 'ok') {      }
             $r->print('<br />Group membership list updated.');      if ($roster_result eq 'ok') {
         } else {          $r->print('<br />Group membership list updated.');
             $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');  
         }   
     } else {      } else {
         &Apache::lonnet::logthis('Failed to create group '.$groupname.           $r->print('<br />An error occurred while updating the group membership list -'.$roster_result.'<br />');
                                  'in course: '.$cnum.' in domain: '.$cdom);      }
       return;
   }
   
         $r->print('An error occurred when creating the new group. '.  sub mapping_options {
                                                       'Please try again.');      my ($r,$action,$formname,$page,$tabcol,$sectioncount,$states,$stored,
           $navbuttons,$img1,$img2,$rowColor1,$rowColor2) = @_;
       my %lt = &Apache::lonlocal::texthash(
           'auto' => 'Settings for automatic group enrollment',
           'gmma' => 'Group membership mapping to specific sections/roles',
           'endi' => 'Enable/disable automatic group enrollment for '.
                             'users in specified roles and sections',
           'adds'  => 'If automatic group enrollment is enabled, when a user is assigned a course-wide or section-specific role, he/she will automatically be added as a member of the group, with start and end access dates defined by the default dates set for the group, unless he/she is already a group member, with access dates that permit either current or future group access.',
           'drops'  => "If automatic group disenrollment is enabled, when a user's role is expired, access to the group will be terminated unless the user continues to have other course-wide or section-specific active or future roles which receive automatic membership in the group.",
           'pirs' => 'Pick roles and sections for automatic group enrollment',
           'curr' => 'Currently set to',
           'on' => 'on',
           'off' => 'off',
           'auad' => 'Automatically enable group membership when roles are added?',
           'auex' => 'Automatically expire group membership when roles are removed?',
           'mapr' => 'Mapping of roles and sections affected by automatic group enrollment/disenrollment follows scheme chosen below.',
       );
       &automapping($r,$action,$tabcol,$stored,\%lt,$img1);
       $r->print('
      <tr>
       <td colspan="4">&nbsp;</td>
      </tr>');
       &mapping_settings($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,\%lt,
                                                          $stored,$img2);
       return;
   }
   
   sub automapping {
       my ($r,$action,$tabcol,$stored,$lt,$image) = @_;
       my $add = 'off';
       my $drop = 'off';
       if (exists($$stored{'autoadd'})) {
           $add = $$stored{'autoadd'};
       }
       if (exists($$stored{'autodrop'})) {
           $drop = $$stored{'autodrop'};
       }
       &topic_bar($r,$tabcol,$image,$$lt{'endi'});
       $r->print('
     <tr>
      <td>&nbsp;</td>
      <td colspan="3">
       <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br />
      </td>
     </tr>
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>
     <tr>
      <td>&nbsp;</td>
      <td colspan="3">
      <nobr>'.$$lt{'auad'}.':&nbsp;
       <input type="radio" name="autoadd" value="on" />on&nbsp;&nbsp;<input type="radio" name="autoadd" value="off" />off');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');
     }      }
       $r->print('
       </nobr>
      </td>
     </tr>
     <tr>
      <td>&nbsp;</td>
      <td colspan="3">
       <nobr>'.$$lt{'auex'}.':&nbsp;
       <input type="radio" name="autodrop" value="on" />on&nbsp;&nbsp;<input type="radio" name="autodrop" value="off" />off');
       if ($action eq 'modify') {
           $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');
       }
       $r->print('</nobr>
      </td>
     </tr>
     <tr>
      <td colspan="4">&nbsp;</td>
     </tr>
     <tr>
      <td>&nbsp;</td>
      <td colspan="3">'.$$lt{'mapr'}.'
      </td>
     </tr>
   ');
   }
   
   sub mapping_settings {
       my ($r,$tabcol,$rowColor1,$rowColor2,$sectioncount,$lt,$stored,$image) = @_;
       my @sections = keys(%{$sectioncount});
       if (@sections > 0) {
           @sections = sort {$a cmp $b} @sections;
           unshift(@sections,'_nosec'); # Put 'no sections' next
           unshift(@sections,'_all'); # Put 'all' at the front of the list
       }
       &topic_bar($r,$tabcol,$image,$$lt{'pirs'});
       $r->print('
      <tr>
       <td>&nbsp;</td>
       <td colspan="3">
   ');
       my @roles = &standard_roles();
       my %customroles = &my_custom_roles();
       $r->print(&Apache::lonhtmlcommon::start_pick_box());
       $r->print('
                   <tr bgcolor="'.$tabcol.'">
                    <th>'.&mt('Active?').'</th>
                    <th>'.&mt('Role').'</th>');
       if (@sections > 0) {
           $r->print('<th>'.&mt('Sections').'</th></tr>'."\n");
       }
       my $rowNum = 0;
       my $rowColor;
       foreach my $role (@roles) {
           my $plrole=&Apache::lonnet::plaintext($role);
           my $sections_sel;
           if (@sections > 0) {
               $sections_sel='<td>'.&sections_selection(\@sections,'sec_'.$role).
                                                                          '</td>';
           }
           if ($rowNum %2 == 1) {
               $rowColor = $rowColor1;
           } else {
               $rowColor = $rowColor2;
           }
           $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.
                     'name="autorole" value="'.$role.'"></td><td>'.$plrole.
                     '</td>'.$sections_sel.'</tr>');
           $rowNum ++;
       }
       foreach my $role (sort(keys(%customroles))) {
           my $sections_sel;
           if (@sections > 0) {
               $sections_sel = '<td>'.&sections_selection(\@sections,'sec_'.$role).
                                                                           '</td>';
           }
           if ($rowNum %2 == 1) {
               $rowColor = $rowColor1;
           } else {
               $rowColor = $rowColor2;
           }
           $r->print('<tr bgcolor="'.$rowColor.'"><td><input type="checkbox" '.
                     'value="'.$role.'"></td><td>'.$role.'</td>'.
                     $sections_sel.'</tr>');
           $rowNum ++;
       }
       $r->print(&Apache::lonhtmlcommon::end_pick_box());
       return;
   }
   
   sub standard_roles {
       my @roles = ('st','ep','ta','in','cc');
       return @roles;
   }
   
   sub my_custom_roles {
       my %returnhash=();
       my %rolehash=&Apache::lonnet::dump('roles');
       foreach (keys %rolehash) {
           if ($_=~/^rolesdef\_(\w+)$/) {
               $returnhash{$1}=$1;
           }
       }
       return %returnhash;
   }
   
   sub modify_menu {
       my ($r,$groupname,$page) = @_;
       my @menu =
           (
             { text => 'Modify default group 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 group',
               help => 'Course_Group_Add_Members',
               state => 'add_members',
               branch => 'adds',
               },
             );
       my $menu_html = '';
       foreach my $menu_item (@menu) {
           $menu_html .=
           '<p><font size="+1"><a href="/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state='.$menu_item->{'state'}.'&branch='.$menu_item->{'branch'}.'">';
           $menu_html.= &mt($menu_item->{'text'}).'</a></font>';
           if (exists($menu_item->{'help'})) {
               $menu_html.=
                   &Apache::loncommon::help_open_topic($menu_item->{'help'});
           }
           $menu_html.='</p>'.$/;
       }
       $r->print($menu_html);
     return;      return;
 }  }
   
 sub member_privs_entries {  sub member_privs_entries {
     my ($r,$tabcol,$rowColor1,$rowColor2,$members,$tools,$usertools,$toolprivs,      my ($r,$tabcol,$rowColor1,$rowColor2,$usertools,$toolprivs,
                                               $fixedprivs,$userdata,$idx) = @_;          $fixedprivs,$userdata,$idx,$showtools,$defprivs,$excluded) = @_;
     my $rowColor;      my $rowColor;
     my $rowNum = 0;      my $rowNum = 0;
     foreach my $member (@{$members}) {      foreach my $user (sort(keys(%{$usertools}))) {
         my ($uname,$udom) = split(/:/,$member);          if (defined($excluded)) {
               if (ref($excluded) eq 'ARRAY') {
                   if (grep/^$user$/,@{$excluded}) {
                       next;
                   }
               }
           }
           my ($uname,$udom) = split(/:/,$user);
         if ($rowNum %2 == 1) {          if ($rowNum %2 == 1) {
             $rowColor = $rowColor1;              $rowColor = $rowColor1;
         } else {          } else {
             $rowColor = $rowColor2;              $rowColor = $rowColor2;
         }          }
         $r->print('<tr bgcolor="'.$rowColor.'">          $r->print('<tr bgcolor="'.$rowColor.'">
                 <td>'.$$userdata{$member}[$$idx{fullname}].'</td>                  <td>'.$$userdata{$user}[$$idx{fullname}].'</td>
                 <td>'.$uname.'</td>                  <td>'.$uname.'</td>
                 <td>'.$udom.'</td>                  <td>'.$udom.'</td>
                 <td valign="top"><table><tr><td><b>Function</b></td></tr><tr><td><b>Fixed</b></td></tr><tr><td><b>Optional</b></td></tr></table></td>');                  <td valign="top"><table><tr><td><b>Function</b></td></tr><tr><td><b>Fixed</b></td></tr><tr><td><b>Optional</b></td></tr></table></td>');
         foreach my $tool (@{$tools}) {          foreach my $tool (@{$showtools}) {
             if (exists($$usertools{$member}{$tool})) {              if (exists($$usertools{$user}{$tool})) {
                 $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');                  $r->print('<td valign="top"><table><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr>');
                 my $privcount = 0;                  my $privcount = 0;
                 my $fixed = '';                  my $fixed = '';
                 my $dynamic = '';                  my $dynamic = '';
                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {                  foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                     if (exists($$fixedprivs{$tool}{$priv})) {                      if (exists($$fixedprivs{$tool}{$priv})) {
                         $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';                          $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$user.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
                     } else {                      } else {
                         $privcount ++;                          $privcount ++;
                         if ($privcount == 3) {                          if ($privcount == 3) {
                             $dynamic .= '</tr><tr>';                              $dynamic .= '</tr><tr>';
                         }                          }
                         $dynamic .= '<td><input type="checkbox" name="userpriv_'.$priv.'" value="'.$member.'" />'.$$toolprivs{$tool}{$priv}.'</td>';                          $dynamic .='<td><nobr><label><input type="checkbox" '.
                                  'name="userpriv_'.$priv.'" value="'.$user.'"';
                           if (grep/^\Q$priv\E$/,@{$defprivs}) {
                               $dynamic .= ' checked="checked" ';
                           }
                           $dynamic .= ' />'.$$toolprivs{$tool}{$priv}.
                                       '</label></nobr></td>';
                     }                      }
                 }                  }
                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');                  $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');
             } else {              } else {
                 $r->print('<td>&nbsp;</td>');                  $r->print('<td valign="top"><table width="100%"><tr bgcolor="'.$tabcol.'"><td colspan="2" align="center"><b>'.$tool.'</b></td></tr><tr><td>&nbsp;</td></tr><tr><td>&nbsp;</td></tr></table></td>');
             }              }
         }          }
         $rowNum ++;          $rowNum ++;
     }      }
 }  }
   
   
 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 3328  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 = '<nobr><label><input type="checkbox" name="no_end_date" />
                                                   no ending date</nobr>';                                                  no ending date</label></nobr>';
     my $start_table = '';      my $start_table = '';
     $start_table .= "<table>\n";      $start_table .= "<table>\n";
     $start_table .= '<tr><td align="right">Default starting date for       $start_table .= '<tr><td align="right">Default starting date for 
Line 1510  sub create_homepage { Line 3375  sub create_homepage {
    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) = @_;
       my %sectioncount;
       my $numsec=&Apache::loncommon::get_sections($cdom,$cnum,\%sectioncount);
       my %curr_groups;
       my $numgroups=&Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum);
                                                                                            
       my %lt = &Apache::lonlocal::texthash (
                         igna => 'Invalid group name',
                         tgne => 'The group name entered ',
                         grna => 'Group names and section names used in a course '.
                                 'must be unique.',
                         isno => 'is not a valid name.',
                         gnmo => 'Group names may only contain letters, numbers '.
                                 'or underscores.',
                         cnnb => 'can not be used as it is the name of ',
                         inth => ' in this course.',
                         thgr => '- does not correspond to the name of an existing'.  
                                 ' group ',    
       );
                                                                                            
       my $exitmsg = '<b>'.$lt{'igna'}.'</b><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 ($numsec) {
           if (exists($sectioncount{$groupname})) {
               $earlyout = $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}.
                           '<br />'.$lt{'grna'};
               return $earlyout;
           }
       }
       if ($action eq 'create') {
           if ($numgroups) {
               if (exists($curr_groups{$groupname})) {
                   $earlyout = $exitmsg.$lt{'cnnb'}.&mt('an existing group').
                               $lt{'inth'}.'<br />'.$lt{'grna'};
                   return $earlyout;
               }
           }
       } elsif ($action eq 'modify') {
           unless(exists($curr_groups{$groupname})) {
               $earlyout = &mt('Group name:').' '.$groupname.$lt{'thgr'}.$lt{'inth'};
               return $earlyout;
           }
       }
       return;
   }
   
   sub topic_bar {
       my ($r,$tabcol,$imgnum,$title) = @_;
       $r->print('
    <tr bgcolor="'.$tabcol.'">
     <td>&nbsp;</td>
     <td valign="middle" align="left">
      <nobr>
       <img src="/res/adm/pages/bl_step'.$imgnum.'.gif" valign="middle">&nbsp;
      </nobr>
     </td>
     <th align="left"><nobr>'.$title.'<nobr>
     </th>
     <td width="100%">&nbsp;</td>
    </tr>
    <tr>
     <td colspan="4">&nbsp;</td>
    </tr>
   ');
       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.12


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