Annotation of loncom/interface/loncoursegroups.pm, revision 1.45

1.24      www         1: # The LearningOnline Network with CAPA
                      2: #
1.45    ! albertel    3: # $Id: loncoursegroups.pm,v 1.44 2006/07/07 19:50:21 albertel Exp $
1.1       raeburn     4: #
                      5: # Copyright Michigan State University Board of Trustees
                      6: #
                      7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      8: #
                      9: # LON-CAPA is free software; you can redistribute it and/or modify
                     10: # it under the terms of the GNU General Public License as published by
                     11: # the Free Software Foundation; either version 2 of the License, or
                     12: # (at your option) any later version.
                     13: #
                     14: # LON-CAPA is distributed in the hope that it will be useful,
                     15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     17: # GNU General Public License for more details.
                     18: #
                     19: # You should have received a copy of the GNU General Public License
                     20: # along with LON-CAPA; if not, write to the Free Software
                     21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     22: #
                     23: # /home/httpd/html/adm/gpl.txt
                     24: #
                     25: # http://www.lon-capa.org/
                     26: #
                     27: 
                     28: package Apache::loncoursegroups;
                     29: 
                     30: use strict;
                     31: use Apache::lonnet;
                     32: use Apache::loncommon;
                     33: use Apache::lonhtmlcommon;
                     34: use Apache::lonlocal;
1.3       raeburn    35: use Apache::lonnavmaps;
1.17      raeburn    36: use Apache::longroup;
1.29      raeburn    37: use Apache::portfolio;
1.1       raeburn    38: use Apache::Constants qw(:common :http);
1.24      www        39: use lib '/home/httpd/lib/perl/';
                     40: use LONCAPA;
1.1       raeburn    41: 
                     42: sub handler {
                     43:     my ($r) = @_;
1.3       raeburn    44: 
1.1       raeburn    45:     &Apache::loncommon::content_type($r,'text/html');
                     46:     $r->send_http_header;
1.15      albertel   47: 
1.1       raeburn    48:     if ($r->header_only) {
                     49:         return OK;
                     50:     }
                     51: 
                     52:     #  Needs to be in a course
                     53:     if (! ($env{'request.course.fn'})) {
                     54:         # Not in a course
                     55:         $env{'user.error.msg'}=
1.3       raeburn    56:      "/adm/coursegroups:mdg:0:0:Cannot edit or view course groups";
1.1       raeburn    57:         return HTTP_NOT_ACCEPTABLE;
                     58:     }
                     59: 
1.3       raeburn    60:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.5       raeburn    61:                         ['action','refpage','state','groupname','branch']);
1.3       raeburn    62:     my $function = &Apache::loncommon::get_users_function();
                     63:     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
                     64:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                     65:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                     66: 
1.1       raeburn    67:     my $view_permission =
1.3       raeburn    68:           &Apache::lonnet::allowed('vcg',$env{'request.course.id'});
1.1       raeburn    69:     my $manage_permission =
1.3       raeburn    70:           &Apache::lonnet::allowed('mdg',$env{'request.course.id'});
                     71:     &Apache::lonhtmlcommon::clear_breadcrumbs();
                     72: 
1.29      raeburn    73:     my $gpterm = &Apache::loncommon::group_term();
                     74:     my $ucgpterm = $gpterm;
                     75:     $ucgpterm =~ s/^(\w)/uc($1)/e;
                     76:     my $crstype = &Apache::loncommon::course_type();
                     77: 
1.3       raeburn    78:     my %functions = (
                     79:                       email => 'E-mail',
                     80:                       discussion => 'Discussion boards',
                     81:                       chat => 'Chat',
                     82:                       files => 'File repository',
                     83:                       roster => 'Membership roster',
1.29      raeburn    84:                       homepage => $ucgpterm.' home page',
1.3       raeburn    85:                     );
                     86: 
                     87:     my %idx = ();
                     88:     $idx{id} = &Apache::loncoursedata::CL_ID();
                     89:     $idx{fullname} = &Apache::loncoursedata::CL_FULLNAME();
                     90:     $idx{udom} = &Apache::loncoursedata::CL_SDOM();
                     91:     $idx{uname} = &Apache::loncoursedata::CL_SNAME();
1.31      albertel   92:     $idx{section} = &Apache::loncoursedata::CL_SECTION();
1.3       raeburn    93: 
1.5       raeburn    94:     my $rowColor1 = "#dddddd";
                     95:     my $rowColor2 = "#eeeeee";
                     96: 
1.3       raeburn    97:     my $action = $env{'form.action'};
1.21      raeburn    98:     my $state = $env{'form.state'};
                     99:     if ((!defined($action)) || ($action eq 'view')) {
                    100:         if (!defined($state)) {
                    101:             $state = 'view';
                    102:         }
                    103:     }
1.3       raeburn   104:     if ($action eq 'create' || $action eq 'modify' || $action eq 'view') { 
                    105:         if ($view_permission || $manage_permission) {
1.45    ! albertel  106:             &group_administration($r,$action,$state,$cdom,$cnum,
1.21      raeburn   107:                                   $tabcol,\%functions,\%idx,$view_permission,
1.29      raeburn   108:                                   $manage_permission,$rowColor1,$rowColor2,
                    109:                                   $gpterm,$ucgpterm,$crstype);
1.3       raeburn   110:         } else {
1.29      raeburn   111:             $r->print(&mt('You do not have [_1] administration '.
                    112:                           'privileges in this [_2]',$gpterm,lc($crstype)));
1.3       raeburn   113:         }
                    114:     } else {
1.39      albertel  115:         &print_main_menu($r,$cdom,$cnum,\%functions,\%idx,$view_permission,
                    116: 			 $manage_permission,$action,$state,$gpterm,$ucgpterm,
                    117: 			 $crstype);
1.3       raeburn   118:     }
                    119:     return OK;
                    120: }
                    121: 
                    122: sub print_main_menu {
1.39      albertel  123:     my ($r,$cdom,$cnum,$functions,$idx,$view_permission,$manage_permission,
                    124: 	$action,$state,$gpterm,$ucgpterm,$crstype) = @_;
1.29      raeburn   125:     my $pagename = "$crstype $ucgpterm".'s';
1.21      raeburn   126:     my $jscript = qq|
                    127: function changeSort(caller) {
                    128:     document.$state.sortby.value = caller;
                    129:     document.$state.submit();
                    130: }\n|;
1.39      albertel  131:     $r->print(&header($pagename,$jscript,$action,$state));
1.3       raeburn   132:     &Apache::lonhtmlcommon::add_breadcrumb
                    133:         ({href=>"/adm/coursegroups",
1.29      raeburn   134:           text=>"$pagename"});
                    135:     $r->print(&Apache::lonhtmlcommon::breadcrumbs($pagename));
1.39      albertel  136:     &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
                    137: 		    $manage_permission,$action,$state,$gpterm,$ucgpterm,
                    138: 		    $crstype);
1.3       raeburn   139:     $r->print(&footer());
                    140:     return;
                    141: }
                    142: 
                    143: sub display_groups {
1.39      albertel  144:     my ($r,$cdom,$cnum,$functions,$idx,$view_permission,
                    145:         $manage_permission,$action,$state,$gpterm,$ucgpterm,$crstype) = @_;
1.3       raeburn   146:     my %curr_groups = ();
                    147:     my %grp_info = ();
1.5       raeburn   148:     my %actionlinks = (
1.21      raeburn   149:       modify => '<a href="/adm/coursegroups?action=modify&refpage='.
                    150:                          $env{'form.refpage'}.'&groupname=',
1.5       raeburn   151:       view => '<a href="/adm/'.$cdom.'/'.$cnum.'/',
                    152:       delete => '<a href="/adm/coursegroups?action=delete&refpage='.
1.21      raeburn   153:                          $env{'form.refpage'}.'&groupname=',
1.5       raeburn   154:     );
1.6       raeburn   155:     my %lt = &Apache::lonlocal::texthash( 
1.5       raeburn   156:                           modify => 'Modify',
1.6       raeburn   157:                           view   => 'View',
1.5       raeburn   158:                           delete => 'Delete',
1.6       raeburn   159:                           act    => 'Action',
1.29      raeburn   160:                           gname  => "$ucgpterm Name",
1.6       raeburn   161:                           desc   => 'Description',
                    162:                           crea   => 'Creator',
                    163:                           crtd   => 'Created',
                    164:                           last   => 'Last Modified',
                    165:                           func   => 'Functionality',
                    166:                           quot   => 'Quota (Mb)',
                    167:                           memb   => 'Members',
                    168:                           file   => 'Files',
                    169:                           dibd   => 'Discussion Boards',
1.29      raeburn   170:                           dius   => 'Disk Use (%)',
                    171:                           nogr   => 'No '.$gpterm.'s exist.',
                    172:                           crng   => 'Create a new '.$gpterm,
1.7       raeburn   173:                           alth   => 'Although your current role has privileges'.
1.29      raeburn   174:                                     ' to view any existing '.$gpterm.'s in this'.
                    175:                                     lc($crstype).', you do not have privileges'.
                    176:                                     'to create new '.$gpterm.'s.',
1.7       raeburn   177:                      );
1.3       raeburn   178:     if ($view_permission) {
1.5       raeburn   179:         if (!defined($action)) {
                    180:             $action = 'view';
                    181:         }
1.17      raeburn   182:         my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
1.15      albertel  183:         if (%curr_groups) {
1.29      raeburn   184:             if ($manage_permission) {
                    185:                 $r->print('<br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');
                    186:             }
1.7       raeburn   187:             $r->print('<br /><br />');
1.39      albertel  188: 	    $r->print(&Apache::loncommon::start_data_table().
                    189: 		      &Apache::loncommon::start_data_table_header_row());
                    190: 		      
1.4       raeburn   191:             $r->print(<<"END");
1.39      albertel  192:         <th>$lt{'act'}</th>
                    193:         <th><a href="javascript:changeSort('groupname')">$lt{'gname'}</a></th>
                    194:         <th><a href="javascript:changeSort('description')">$lt{'desc'}</a></th>
                    195:         <th><a href="javascript:changeSort('creator')">$lt{'crea'}</a></th>
                    196:         <th><a href="javascript:changeSort('creation')">$lt{'crtd'}</a></th>
                    197:         <th><a href="javascript:changeSort('modified')">$lt{'last'}</a></th>
                    198:         <th>$lt{'func'}</b></td>
                    199:         <th><a href="javascript:changeSort('quota')">$lt{'quot'}</a></th>
                    200:         <th><a href="javascript:changeSort('totalmembers')">$lt{'memb'}</a></th>
                    201:         <th><a href="javascript:changeSort('totalfiles')">$lt{'file'}</a></th>
                    202:         <th><a href="javascript:changeSort('boards')">$lt{'dibd'}</a></th>
                    203:         <th><a href="javascript:changeSort('diskuse')">$lt{'dius'}</a></th>
1.3       raeburn   204: END
1.39      albertel  205: 	    $r->print(&Apache::loncommon::end_data_table_header_row());
1.4       raeburn   206:             my %Sortby = ();
                    207:             foreach my $group (sort(keys(%curr_groups))) {
                    208:                 %{$grp_info{$group}} = 
1.17      raeburn   209:                                   &Apache::longroup::get_group_settings(
1.3       raeburn   210:                                                          $curr_groups{$group});
1.5       raeburn   211:                 my $members_result = &group_members($cdom,$cnum,$group,
                    212:                                                     \%grp_info);
1.29      raeburn   213:                 my $port_path = '/userfiles/groups/'.$group.'/portfolio';
                    214:                 my $port_dir = &Apache::loncommon::propath($cdom,$cnum).$port_path;
                    215:                 my $totaldirs = 0;
                    216:                 my $totalfiles = 0;
                    217:                 &group_files($group,$port_dir,\$totalfiles,\$totaldirs);
                    218:                 $grp_info{$group}{'totalfiles'} = $totalfiles;
                    219:                 $grp_info{$group}{'totaldirs'} = $totaldirs;
                    220:                 my $diskuse = &Apache::lonnet::diskusage($cdom,$cnum,$port_dir);
                    221:                 if ($grp_info{$group}{'quota'} > 0) {
                    222:                     my $pct_use = 0.1 * $diskuse/$grp_info{$group}{'quota'};
                    223:                     $grp_info{$group}{'diskuse'} = sprintf("%.0f",$pct_use);
                    224:                 } else {
                    225:                     $grp_info{$group}{'diskuse'} = 'N/A';
1.33      raeburn   226:                 }
                    227:                 my ($groupboards,$boardshash)=&Apache::longroup::get_group_bbinfo(
                    228:                                                                $cdom,$cnum,$group);
                    229:                 $grp_info{$group}{'boards'} = scalar(@{$groupboards});
1.4       raeburn   230:                 if ($env{'form.sortby'} eq 'groupname') {
                    231:                     push(@{$Sortby{$group}},$group);
                    232:                 } elsif ($env{'form.sortby'} eq 'description') {
1.29      raeburn   233:                     push(@{$Sortby{$grp_info{$group}{'description'}}},$group);
1.4       raeburn   234:                 } elsif ($env{'form.sortby'} eq 'creator') {
                    235:                     push(@{$Sortby{$grp_info{$group}{'creator'}}},$group);
                    236:                 } elsif ($env{'form.sortby'} eq 'creation') {
                    237:                     push(@{$Sortby{$grp_info{$group}{'creation'}}},$group);
                    238:                 } elsif ($env{'form.sortby'} eq 'modified') {
                    239:                     push(@{$Sortby{$grp_info{$group}{'modified'}}},$group);
                    240:                 } elsif ($env{'form.sortby'} eq 'quota') {
                    241:                     push(@{$Sortby{$grp_info{$group}{'quota'}}},$group);
                    242:                 } elsif ($env{'form.sortby'} eq 'totalmembers') {
                    243:                     push(@{$Sortby{$grp_info{$group}{'totalmembers'}}},
1.3       raeburn   244:                                                                        $group);
1.4       raeburn   245:                 } elsif ($env{'form.sortby'} eq 'totalfiles') {
1.5       raeburn   246:                     push(@{$Sortby{$grp_info{$group}{'totalfiles'}}},$group);
1.4       raeburn   247:                 } elsif ($env{'form.sortby'} eq 'boards') {
                    248:                     push(@{$Sortby{$grp_info{$group}{'boards'}}},$group);
                    249:                 } elsif ($env{'form.sortby'} eq 'diskuse') {
                    250:                     push(@{$Sortby{$grp_info{$group}{'diskuse'}}},$group);
                    251:                 } else {
                    252:                     push(@{$Sortby{$group}},$group);
                    253:                 }
                    254:             }
                    255:             foreach my $key (sort(keys(%Sortby))) {
                    256:                 foreach my $group (@{$Sortby{$key}}) {
                    257:                     my $description = 
1.39      albertel  258: 			&unescape($grp_info{$group}{'description'});
1.4       raeburn   259:                     my $creator = $grp_info{$group}{'creator'};
                    260:                     my $creation = $grp_info{$group}{'creation'};
                    261:                     my $modified = $grp_info{$group}{'modified'}; 
                    262:                     my $quota = $grp_info{$group}{'quota'};
                    263:                     my $totalmembers = $grp_info{$group}{'totalmembers'};
                    264:                     my $totalfiles = $grp_info{$group}{'totalfiles'};
1.29      raeburn   265:                     my $totaldirs = $grp_info{$group}{'totaldirs'};
1.4       raeburn   266:                     my $boards = $grp_info{$group}{'boards'};
                    267:                     my $diskuse = $grp_info{$group}{'diskuse'};
                    268:                     my $functionality;
1.5       raeburn   269:                     foreach my $tool (sort(keys(%{$functions}))) {
1.6       raeburn   270:                         if ($grp_info{$group}{functions}{$tool} eq 'on') {
1.4       raeburn   271:                             $functionality .= ' '.$tool;
1.3       raeburn   272:                         }
                    273:                     }
1.4       raeburn   274:                     if (!$functionality) {
1.6       raeburn   275:                         $functionality = &mt('None available');
1.4       raeburn   276:                     }
1.5       raeburn   277:                     my $link = $actionlinks{$action};
                    278:                     if ($action eq 'modify' || $action eq 'delete') {
                    279:                         $link .= $group;
                    280:                     } else {
1.19      albertel  281:                         $link .= $group.'/grppg';
1.5       raeburn   282:                     }
1.21      raeburn   283:                     $link .= '">'.$lt{$action}.'</a>';
                    284:                     if ($action eq 'view') { 
                    285:                         if (($manage_permission) && 
                    286:                             ($env{'form.refpage'} ne 'enrl')) {
                    287:                             $link .= '&nbsp;&nbsp;'.$actionlinks{'modify'}.
                    288:                                       $group.'">'.$lt{'modify'}.'</a>';
                    289:                         }
                    290:                     }
1.39      albertel  291:                     $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').
                    292: 			      '<td>'.$link.'</td>'.
                    293: 			      '<td>'.$group.'</td>'.
                    294: 			      '<td>'.$description.'</td>'.
                    295: 			      '<td>'.$creator.'</td>'.
                    296: 			      '<td>'. &Apache::lonnavmaps::timeToHumanString($creation).'</td>'.
                    297: 			      '<td>'. &Apache::lonnavmaps::timeToHumanString($modified).'</td>'.
                    298: 			      '<td>'.$functionality.'</td>'.
                    299: 			      '<td align="right">'.$quota.'</td>'.
                    300: 			      '<td align="right">'.$totalmembers.'</td>'.
                    301: 			      '<td align="right"><nobr>'.&mt('Files: ').$totalfiles.'</nobr><br /><nobr>'.&mt('Folders: ').$totaldirs.'</nobr></td>'.
                    302: 			      '<td align="right">'.$boards.'</td>'.
                    303: 			      '<td align="right">'.$diskuse.'</td>'.
                    304: 			      &Apache::loncommon::end_data_table_row());
1.3       raeburn   305:                 }
1.4       raeburn   306:             }
1.39      albertel  307:             $r->print(&Apache::loncommon::end_data_table());
1.21      raeburn   308:             $r->print('<input type="hidden" name="refpage" '.
                    309:                       'value="'.$env{'form.refpage'}.'" />');
                    310:             if ($action eq 'view') {
                    311:                 if (!defined($state)) {
                    312:                     $state = 'view';
                    313:                 }
                    314:                 $r->print('<input type="hidden" name="state" value="'.
                    315:                       $state.'" />');
                    316:             }
1.3       raeburn   317:         } else {
1.7       raeburn   318:             $r->print($lt{'nogr'});
                    319:             if ($manage_permission) {
                    320:                 $r->print('<br /><br /><a href="/adm/coursegroups?action=create&refpage='.$env{'form.refpage'}.'">'.$lt{'crng'}.'</a>');
                    321:             } else {
1.29      raeburn   322:                 $r->print('<br /><br />'.$lt{'alth'});
1.7       raeburn   323: 
                    324:             }
1.3       raeburn   325:         }
                    326:     } else {
1.4       raeburn   327:         my @coursegroups = split(/:/,$env{'request.course.groups'});
                    328:         if (@coursegroups > 0) {
1.7       raeburn   329:             $r->print('<br /><br />');
1.17      raeburn   330:             my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
1.15      albertel  331:             if (%curr_groups) {
1.4       raeburn   332:                 foreach my $group (@coursegroups) {
1.17      raeburn   333:                     my %group_info =  &Apache::longroup::get_group_settings(
1.5       raeburn   334:                                         $curr_groups{$group});
1.24      www       335:                     my $description = &unescape(
1.5       raeburn   336:                                         $group_info{description});
1.4       raeburn   337:                     my ($uname,$udom) = split(/:/,$group_info{creator});
1.19      albertel  338:                     $r->print('<font size="+1"><a href="/adm/'.$udom.'/'.$uname.'/'.$group.'/grppg">'.$group,'</a><font><br /><small>'.$description.'</small><br /><br />');
1.4       raeburn   339:                 }
                    340:             }
                    341:         } else {
1.6       raeburn   342:             $r->print(&mt('You are not currently a member of any '.
1.29      raeburn   343:                           'active [_1]s in this [_2]',$gpterm,
                    344:                           lc($crstype)));
1.4       raeburn   345:         }
1.3       raeburn   346:     }
                    347:     return;
                    348: }
                    349: 
                    350: sub group_administration {
1.45    ! albertel  351:     my ($r,$action,$state,$cdom,$cnum,$tabcol,$functions,$idx,
1.29      raeburn   352:         $view_permission,$manage_permission,$rowColor1,$rowColor2,$gpterm,
                    353:         $ucgpterm,$crstype) = @_;
1.3       raeburn   354:     my %sectioncount = ();
                    355:     my @tools = ();
                    356:     my @types = ();
                    357:     my @roles = ();
                    358:     my @sections = ();
                    359:     my %users = ();
                    360:     my %userdata = ();
                    361:     my @members = ();
                    362:     my %usertools = ();
1.5       raeburn   363:     my %stored = ();
                    364:     my %memchg;
1.6       raeburn   365:     my @member_changes = ('deletion','expire','activate','reenable',
1.5       raeburn   366:                           'changefunc','changepriv');
1.29      raeburn   367:     my ($groupname,$description,$startdate,$enddate,$granularity,$specificity,
1.37      raeburn   368:         $quota,$validate_script);
1.5       raeburn   369: 
                    370:     if (defined($env{'form.groupname'})) {
                    371:         $groupname = $env{'form.groupname'};
                    372:     }
                    373: 
                    374:     if (($action eq 'create') && ($state eq '')) {
                    375:         $state = 'pick_name';
                    376:     }
                    377:     if (($action eq 'create') || 
                    378:         (($action eq 'modify') && ($state eq 'chgresult'))) { 
                    379:         ($startdate,$enddate) = &get_dates_from_form();
                    380:         if (defined($env{'form.description'})) {
                    381:             $description = $env{'form.description'};
                    382:         }
                    383:         if (defined($env{'form.tool'})) {
                    384:             @tools=&Apache::loncommon::get_env_multiple('form.tool');
                    385:         }
                    386:         if (defined($env{'form.granularity'})) {
                    387:             $granularity=$env{'form.granularity'};
                    388:         }
                    389:         if (defined($env{'form.specificity'})) {
                    390:             $specificity=$env{'form.specificity'};
                    391:         }
1.29      raeburn   392:         if (defined($env{'form.quota'})) {
                    393:             $quota=$env{'form.quota'};
                    394:         }
1.5       raeburn   395:     }
                    396:     if (($action eq 'create') || (($action eq 'modify') 
                    397:         && (($state eq 'pick_privs') || ($state eq 'addresult')))) {
                    398:         if (defined($env{'form.member'})) {
                    399:             @members = &Apache::loncommon::get_env_multiple('form.member');
                    400:             foreach my $user (@members) {
                    401:                 %{$usertools{$user}} = ();
                    402:             }
                    403:         }
                    404:     }
1.3       raeburn   405: 
1.5       raeburn   406:     if ($action eq 'modify') {
1.3       raeburn   407:         if ($state eq '') {
1.21      raeburn   408:             if (defined($env{'form.groupname'})) {
                    409:                 $state = 'pick_task';
                    410:             } else {
                    411:                 $state = 'pick_group';
                    412:             }
1.3       raeburn   413:         } else {
1.5       raeburn   414:             %stored = &retrieve_settings($cdom,$cnum,$groupname);
                    415:             if (ref($stored{'types'}) eq 'ARRAY') {
                    416:                 @types = @{$stored{'types'}};
                    417:             }
                    418:             if (ref($stored{'roles'}) eq 'ARRAY') {
                    419:                 @roles = @{$stored{'roles'}};
                    420:             }
                    421:             if (ref($stored{'sectionpick'}) eq 'ARRAY') {
                    422:                 @sections = @{$stored{'sectionpick'}};
                    423:             }
                    424:             unless ($state eq 'chgresult') {
                    425:                 if (ref($stored{'tool'}) eq 'ARRAY') { 
                    426:                     @tools = @{$stored{'tool'}};
1.3       raeburn   427:                 }
1.5       raeburn   428:                 $startdate = $stored{'startdate'};
                    429:                 $enddate = $stored{'enddate'};
                    430:                 $description = $stored{'description'};
                    431:                 $granularity = $stored{'granularity'};
                    432:                 $specificity =  $stored{'specificity'};
1.29      raeburn   433:                 $quota = $stored{'quota'};
1.3       raeburn   434:             }
                    435:         }
                    436:     }
                    437: 
1.36      raeburn   438:     my $toolprivs = &Apache::longroup::get_tool_privs($gpterm);
1.22      albertel  439: 
1.36      raeburn   440:     my $fixedprivs = &Apache::longroup::get_fixed_privs();
1.22      albertel  441: 
                    442:     my %elements = 
                    443: 	(
                    444: 	 create => {
                    445: 	     pick_name => {
                    446: 		 startdate_month  => 'selectbox',
                    447: 		 startdate_hour   => 'selectbox',
                    448: 		 enddate_month    => 'selectbox',
                    449: 		 enddate_hour     => 'selectbox',
                    450: 		 startdate_day    => 'text',
                    451: 		 startdate_year   => 'text',
                    452: 		 startdate_minute => 'text',
                    453: 		 startdate_second => 'text',
                    454: 		 enddate_day      => 'text',
                    455: 		 enddate_year     => 'text',
                    456: 		 enddate_minute   => 'text',
                    457: 		 enddate_second   => 'text',
                    458: 		 groupname        => 'text',
                    459: 		 description      => 'text',
1.29      raeburn   460:                  quota            => 'text',
1.22      albertel  461: 		 tool             => 'checkbox',
                    462: 		 granularity      => 'radio',
                    463: 		 no_end_date      => 'checkbox',
                    464: 	     },
                    465: 	     pick_members => {
                    466: 		 member          => 'checkbox',
                    467: 		 defpriv         => 'checkbox',
                    468: 	     },
                    469: 	 },
                    470: 	 );
                    471:     
                    472:     $elements{'modify'} = {
                    473: 	change_settings => {
                    474: 	    %{$elements{'create'}{'pick_name'}},
                    475: 	    specificity => 'radio',
                    476: 	    defpriv     => 'checkbox',
                    477: 	    autorole    => 'checkbox',
                    478: 	    autoadd     => 'radio',
                    479: 	    autodrop    => 'radio',
                    480: 	},
                    481: 	add_members => {
                    482: 	    types       => 'selectbox',
                    483: 	    roles       => 'selectbox',
                    484: 	},
                    485:     };
                    486: 
1.5       raeburn   487:     if (ref($stored{'autorole'}) eq 'ARRAY') {
                    488:         foreach my $role (@{$stored{'autorole'}}) {
1.17      raeburn   489:             unless ($role eq 'cc') {
                    490:                 $elements{'modify'}{'change_settings'}{'sec_'.$role} = 
                    491:                                                                    'selectbox';
                    492:             }
1.5       raeburn   493:         }
                    494:     }
                    495: 
1.3       raeburn   496:     if (($action eq 'create') && ($state eq 'pick_name')) {
1.5       raeburn   497:         $elements{'create'}{'pick_name'}{'types'} = 'selectbox';
                    498:         $elements{'create'}{'pick_name'}{'roles'} = 'selectbox';
                    499:     }
                    500:     if ((($action eq 'create') &&  
                    501:         (($state eq 'pick_name') || ($state eq 'pick_privs'))) ||
                    502:        (($action eq 'modify') && (($state eq 'change_settings') ||
                    503:                                   ($state eq 'add_members')))) {
1.16      albertel  504:         %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
                    505:         if (%sectioncount) {
1.3       raeburn   506:             $elements{'create'}{'pick_name'}{'sectionpick'} = 'selectbox';
1.5       raeburn   507:             $elements{'modify'}{'change_mapping'}{'sectionpick'} = 'selectbox';
                    508:             $elements{'modify'}{'add_members'}{'sectionpick'} = 'selectbox';
1.3       raeburn   509:         }
                    510:     }
1.5       raeburn   511: 
1.12      raeburn   512:     if (($action eq 'create') || 
                    513:         ($action eq 'modify' && $state eq 'pick_members')) {
1.3       raeburn   514:         if (defined($env{'form.types'})) {
                    515:             @types=&Apache::loncommon::get_env_multiple('form.types');
                    516:         }
                    517:         if (defined($env{'form.roles'})) {
                    518:             @roles=&Apache::loncommon::get_env_multiple('form.roles');
                    519:         }
                    520:         if (defined($env{'form.sectionpick'})) {
                    521:             @sections=&Apache::loncommon::get_env_multiple('form.sectionpick');
1.20      raeburn   522:             if (grep/^all$/,@sections) {
1.3       raeburn   523:                 @sections = sort {$a cmp $b} keys(%sectioncount);
                    524:             }
                    525:         }
1.5       raeburn   526:     }
                    527: 
1.6       raeburn   528:     if (($state eq 'pick_members') || ($state eq 'pick_privs') || ($state eq 'change_privs')) {
                    529:         &build_members_list($cdom,$cnum,\@types,\@roles,\@sections,\%users,
                    530:                             \%userdata);
                    531:     }
                    532:     if ($state eq 'pick_members') {
1.3       raeburn   533:         if ((keys(%users) > 0) && (@tools > 0)) {
1.7       raeburn   534:             if ($granularity eq 'Yes') {
                    535:                 $elements{$action}{'pick_members'}{'togglefunc'} = 'checkbox';
                    536:             }
1.3       raeburn   537:             foreach my $tool (@tools) {
1.5       raeburn   538:                 if ($granularity eq 'Yes') {
                    539:                     $elements{$action}{'pick_members'}{'user_'.$tool} = 'checkbox';
1.3       raeburn   540:                 }
                    541:             }
1.5       raeburn   542:             $elements{$action}{'pick_members'}{'specificity'} = 'radio';
1.3       raeburn   543:         }
                    544:     }
1.6       raeburn   545:     if ($state eq 'change_members') {
                    546:         my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                    547:                                                                $groupname);
                    548:         my $now = time;
                    549:         my $num_expire = 0;
                    550:         my $num_activate = 0;
                    551:         my $num_reenable = 0;
                    552:         my $num_deletion = 0;
                    553:         my $numusers = 0;
                    554:         foreach my $key (sort(keys(%membership))) {
                    555:             if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                    556:                 my $user = $1;
                    557:                 my($end,$start,@userprivs) = split(/:/,$membership{$key});
                    558:                 unless ($start == -1) {
                    559:                     $numusers ++;
                    560:                     $num_deletion ++;
                    561:                     if (($end > 0) && ($end < $now)) {
                    562:                         $num_reenable ++;
                    563:                         next;
                    564:                     } elsif (($start > $now)) {
                    565:                         $num_activate = 1;
                    566:                         next;
                    567:                     } else {
                    568:                         $num_expire ++;
                    569:                         next;
                    570:                     }
                    571:                     next;
                    572:                 }
                    573:                 if ($num_reenable && $num_activate && $num_expire) {
                    574:                     last;
                    575:                 }
                    576:             }
                    577:         }
                    578:         if ($num_deletion) {
                    579:             $elements{$action}{'change_members'}{'deletion'} = 'checkbox';
                    580:         }
                    581:         if ($num_expire) {
                    582:             $elements{$action}{'change_members'}{'expire'} = 'checkbox';
                    583:         }
                    584:         if ($num_activate) {
                    585:             $elements{$action}{'change_members'}{'activate'} = 'checkbox';
                    586:         }
                    587:         if ($num_reenable) {
                    588:             $elements{$action}{'change_members'}{'reenable'} = 'checkbox';
                    589:         }
                    590:         if ($numusers) {
1.7       raeburn   591:             if ($granularity eq 'Yes') {
                    592:                 $elements{$action}{'change_members'}{'togglefunc'} = 'checkbox';
                    593:             }
1.6       raeburn   594:             foreach my $tool (@tools) {
                    595:                 if ($granularity eq 'Yes') {
                    596:                     $elements{$action}{'change_members'}{'user_'.$tool} = 'checkbox';
                    597:                 }
                    598:             }
                    599:             if ($specificity eq 'Yes') {
                    600:                 $elements{$action}{'change_members'}{'changepriv'} = 'checkbox';
                    601:             }
                    602:         }
                    603:     }
1.3       raeburn   604: 
1.5       raeburn   605:     if (($state eq 'pick_privs') || ($state eq 'change_privs') ||
1.21      raeburn   606:          (($specificity eq 'No') && 
                    607:           ($state eq 'memresult' || $state eq 'result' || $state eq 'addresult'))) { 
1.3       raeburn   608:         foreach my $tool (@tools) {
                    609:             my @values = &Apache::loncommon::get_env_multiple('form.user_'.$tool);
                    610:             foreach my $user (@values) {
1.21      raeburn   611:                 if ($state eq 'pick_privs' || $state eq 'result' 
                    612:                     || $state eq 'addresult') {
                    613:                     if (!grep(/^\Q$user\E$/,@members)) {
                    614:                         next;
                    615:                     }
                    616:                 }
1.3       raeburn   617:                 unless(exists($usertools{$user}{$tool})) {
                    618:                     $usertools{$user}{$tool} = 1;
                    619:                 }
                    620:             }
                    621:         }
1.6       raeburn   622:     }
                    623: 
                    624:     if (($action eq 'modify') && (($state eq 'change_privs') || ($state eq 'memresult'))) {
                    625:         foreach my $chg (@member_changes) {
                    626:             if (defined($env{'form.'.$chg})) {
                    627:                 @{$memchg{$chg}} = &Apache::loncommon::get_env_multiple('form.'.$chg);
                    628:             }
                    629:         }
                    630:                                                                               
                    631:         if ($state eq 'change_privs') {
                    632:             my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                    633:                                                                    $groupname);
                    634:             my $now = time;
                    635:             foreach my $key (sort(keys(%membership))) {
                    636:                 if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
                    637:                     my $user = $1;
                    638:                     my $changefunc = 0;
                    639:                     my ($end,$start,@userprivs) = split(/:/,$membership{$key});
                    640:                     unless ($start == -1) {
                    641:                         if (($end > 0) && ($end < $now)) {
                    642:                             unless (grep/^$user$/,$memchg{'reenable'}) {
                    643:                                 next;
                    644:                             }
                    645:                         }
                    646:                         my @currtools = ();
                    647:                         if (@userprivs > 0) {
1.36      raeburn   648:                             foreach my $tool (sort(keys(%{$fixedprivs}))) {
                    649:                                 foreach my $priv (keys(%{$$fixedprivs{$tool}})) {
1.6       raeburn   650:                                     if (grep/^$priv$/,@userprivs) {
                    651:                                         push(@currtools,$tool);
                    652:                                         last;
                    653:                                     }
                    654:                                 }
                    655:                             }
1.3       raeburn   656:                         }
1.6       raeburn   657:                         foreach my $tool (@currtools) {
                    658:                             if (keys(%{$usertools{$user}}) > 0) {
                    659:                                 if (!$usertools{$user}{$tool}) {
                    660:                                     push(@{$memchg{'changefunc'}},$user);
                    661:                                     $changefunc = 1;
                    662:                                     last;
                    663:                                 }
                    664:                             } else {
                    665:                                 push(@{$memchg{'changefunc'}},$user);
                    666:                                 $changefunc = 1;
                    667:                             }
                    668:                         }
                    669:                         if ($changefunc) {
                    670:                             next;
                    671:                         }
                    672:                         if (keys(%{$usertools{$user}}) > 0) {
                    673:                             foreach my $tool (keys(%{$usertools{$user}})) {
                    674:                                 if (!grep/^$tool$/,@currtools) {
                    675:                                     push(@{$memchg{'changefunc'}},$user);
                    676:                                     $changefunc = 1;
                    677:                                     last;
                    678:                                 }
                    679:                             }
                    680:                         }
                    681:                     }
                    682:                 }
                    683:             }
                    684:             &check_changes(\@member_changes,\%memchg);
                    685:             my %temptools;
                    686:             foreach my $change (@member_changes) {
                    687:                 if (($change eq 'deletion') || ($change eq 'expire')) {
                    688:                     next;
                    689:                 }
                    690:                 foreach my $user (@{$memchg{$change}}) {
                    691:                     unless (exists($usertools{$user})) {
                    692:                         %{$usertools{$user}} = ();
                    693:                     }
                    694:                     %{$temptools{$user}} = %{$usertools{$user}}; 
                    695:                 }
                    696:             }
                    697:             %usertools = %temptools;
                    698:         } elsif ($state eq 'memresult') {
                    699:             foreach my $change (@member_changes) {
                    700:                 if ($change eq 'expire' || $change eq 'deletion') {
                    701:                     next;
                    702:                 }
                    703:                 if (ref($memchg{$change}) eq 'ARRAY') { 
                    704:                     my @users = @{$memchg{$change}};
                    705:                     foreach my $user (@users) {
                    706:                         unless (exists($usertools{$user})) {
                    707:                             %{$usertools{$user}} = ();
                    708:                         }
                    709:                     }
                    710:                 }
                    711:             }
                    712:         }
                    713:     }
                    714: 
                    715:     if ((($state eq 'pick_privs') || ($state eq 'change_privs'))
                    716:         && ($specificity eq 'Yes')) {
                    717:         foreach my $user (sort(keys(%usertools))) {
                    718:             foreach my $tool (keys(%{$usertools{$user}})) {
1.36      raeburn   719:                 foreach my $priv (keys(%{$$toolprivs{$tool}})) {
                    720:                     unless (exists($$fixedprivs{$tool}{$priv})) {
1.6       raeburn   721:                         $elements{$action}{$state}{'userpriv_'.$priv} = 'checkbox';
1.3       raeburn   722:                     }
                    723:                 }
                    724:             }
                    725:         }
                    726:     }
1.37      raeburn   727: 
                    728:     if (($action eq 'create' && $state eq 'pick_name') || 
                    729:         ($action eq 'modify' && $state eq 'change_settings')) {
                    730:         my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,\%stored);
                    731:         my $space_trim = '/^\s*|\s*\$/g,""';
                    732:         my $float_check = '/^([0-9]*\.?[0-9]*)$/';
                    733:         $validate_script = '
                    734:     var newquota = document.'.$state.'.quota.value;
                    735:     newquota.replace('.$space_trim.');
                    736:     if (newquota == "" ) {
                    737:         document.'.$state.'.quota.value = 0;
                    738:         newquota = 0;       
                    739:     }
                    740:     var maxposs = '.$maxposs.';
                    741:     if (newquota > maxposs) {
                    742:         alert("The file repository quota you entered for this group ("+newquota+" Mb) exceeds the maximum possible ("+maxposs+" Mb). Please enter a smaller number.");
                    743:         return;
                    744:     }
                    745:     var re_quota = '.$float_check.';
                    746:     var check_quota = newquota.match(re_quota);
                    747:     if (check_quota == null) {
                    748:         alert("The quota you entered contains invalid characters, the quota should only include numbers, with or without a decimal point.");
                    749:         return;
                    750:     }
                    751:     if (newquota == 0) {
                    752:         var warn_zero = 0;
                    753:         for (var i=0; i<document.'.$state.'.tool.length; i++) {
                    754:             if (document.'.$state.'.tool[i].value == "files") {
                    755:                 if (document.'.$state.'.tool[i].checked) {
                    756:                     warn_zero = 1;
                    757:                 }
                    758:             }
                    759:         }
                    760:         if (warn_zero == 1) {
                    761:             alert("You have indicated that the file repository should be enabled, but you have set the respository quota to 0 Mb.\nThis will prevent any upload of files.\nPlease set a value or disable the repository feature.");
                    762:             return;
                    763:         }
                    764:     } 
                    765: ';
                    766:     }
1.5       raeburn   767:     my $jscript = &Apache::loncommon::check_uncheck_jscript();
1.3       raeburn   768:     $jscript .= qq|
                    769: function nextPage(formname,nextstate) {
                    770:     formname.state.value= nextstate;
1.37      raeburn   771:     $validate_script
1.3       raeburn   772:     formname.submit();
                    773: }
                    774: function backPage(formname,prevstate) {
                    775:     formname.state.value = prevstate;
                    776:     formname.submit();
                    777: }
1.6       raeburn   778: function changeSort(caller) {
                    779:     document.$state.state.value = '$state';
                    780:     document.$state.sortby.value = caller;
                    781:     document.$state.submit();
                    782: } 
1.15      albertel  783: 
1.3       raeburn   784: |;
                    785:     $jscript .= &Apache::lonhtmlcommon::set_form_elements(
1.5       raeburn   786:                            \%{$elements{$action}{$state}},\%stored);
                    787:     my $page = 0;
                    788:     my %states = ();
                    789:     my %branchstates = ();
                    790:     @{$states{'create'}} = ('pick_name','pick_members','pick_privs','result');
                    791:     @{$states{'modify'}} = ('pick_group','pick_task');
                    792:     @{$branchstates{'noprivs'}} = ('result');
                    793:     @{$branchstates{'settings'}} = ('change_settings','chgresult');
                    794:     @{$branchstates{'members'}} = ('change_members','change_privs','memresult');
                    795:     @{$branchstates{'adds'}} = ('add_members','pick_members','pick_privs',
                    796:                                 'addresult');
1.21      raeburn   797: 
1.5       raeburn   798:     if (defined($env{'form.branch'})) {
                    799:         push (@{$states{$action}},@{$branchstates{$env{'form.branch'}}});
                    800:     }
                    801: 
                    802:     if (($action eq 'create') || ($action eq 'modify')) {
                    803:         my $done = 0;
                    804:         my $i=0;
                    805:         while ($i<@{$states{$action}} && !$done) {
                    806:             if ($states{$action}[$i] eq $state) {
                    807:                 $page = $i;
                    808:                 $done = 1;
                    809:             }
                    810:             $i++;
                    811:         }
                    812:     }
1.3       raeburn   813: 
                    814:     my $loaditems =  &onload_action($action,$state);
1.29      raeburn   815:     my $crumbtitle = "$crstype $ucgpterm".'s'; 
                    816:     $r->print(&header("$crumbtitle Manager",
1.39      albertel  817: 		      $jscript,$action,$state,$page,$loaditems));
1.1       raeburn   818: 
1.3       raeburn   819:     if ($env{'form.refpage'} eq 'enrl') {
                    820:         &Apache::lonhtmlcommon::add_breadcrumb
                    821:         ({href=>"/adm/dropadd",
                    822:           text=>"Enrollment Manager",
                    823:           faq=>9,bug=>'Instructor Interface',});
                    824:     } else {
1.1       raeburn   825:         &Apache::lonhtmlcommon::add_breadcrumb
1.3       raeburn   826:        ({href=>"/adm/coursegroups",
1.29      raeburn   827:           text=>"$crumbtitle",
1.3       raeburn   828:           faq=>9,bug=>'Instructor Interface',});
                    829:     }
                    830: 
                    831:     my %trail = ();
1.5       raeburn   832:     %{$trail{'create'}} = &Apache::lonlocal::texthash (
1.29      raeburn   833:                             pick_name => $ucgpterm.' Settings',
1.3       raeburn   834:                             pick_members => 'Select Members',
                    835:                             pick_privs => 'Choose Privileges',
                    836:                             result => 'Creation Complete',
                    837:                           );
1.5       raeburn   838:     %{$trail{'modify'}} = &Apache::lonlocal::texthash(
1.29      raeburn   839:                             pick_group => $ucgpterm.'s',
1.5       raeburn   840:                             pick_task => 'Choose Task',
1.29      raeburn   841:                             change_settings => "$ucgpterm Settings",
1.5       raeburn   842:                             change_members => 'Modify/Delete Members',
                    843:                             change_privs => 'Change Privileges',
                    844:                             change_mapping => 'Membership Mapping',
                    845:                             add_members => 'Add Members',
                    846:                             pick_members => 'Select Members',
                    847:                             pick_privs => 'Choose Privileges',
                    848:                             chgresult => 'Setting Changes Complete',
                    849:                             memresult => 'Modifications Complete',
                    850:                             addresult => 'Additions Complete',
                    851:                           );
                    852:     my %navbuttons = &Apache::lonlocal::texthash(
                    853:                              gtns => 'Go to next step',
                    854:                              gtps => 'Go to previous step',
1.29      raeburn   855:                              crgr => 'Create '.$gpterm,
1.5       raeburn   856:                              mose => 'Modify settings',
                    857:                              gtpp => 'Go to previous page',
                    858:                              adme => 'Add members',
                    859:     );
1.3       raeburn   860:     if ((($action eq 'create') || ($action eq 'modify')) &&
                    861:               ($manage_permission)) {
                    862:         for (my $i=0; $i<@{$states{$action}}; $i++) {
                    863:             if ($state eq $states{$action}[$i]) {
                    864:                 &Apache::lonhtmlcommon::add_breadcrumb(
                    865:                    {text=>"$trail{$action}{$state}"});
                    866:                 $r->print(&Apache::lonhtmlcommon::breadcrumbs
1.29      raeburn   867: 			  ("$crumbtitle Manager"));
1.5       raeburn   868:                 &display_control($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                    869:                        \%sectioncount,$groupname,$description,$functions,
1.36      raeburn   870:                        \@tools,$toolprivs,$fixedprivs,$startdate,$enddate,
1.5       raeburn   871:                        \%users,\%userdata,$idx,\%memchg,\%usertools,
1.45    ! albertel  872:                        $view_permission,$manage_permission,
1.29      raeburn   873:                        \%stored,$granularity,$quota,$specificity,\@types,\@roles,
                    874:                        \@sections,\%states,\%navbuttons,$rowColor1,$rowColor2,
                    875:                        $gpterm,$ucgpterm,$crstype);
1.3       raeburn   876:                 last;
                    877:             } else {
1.8       raeburn   878:                 if (($state eq 'result') && ($i > 0)) {
1.3       raeburn   879:                     &Apache::lonhtmlcommon::add_breadcrumb(
                    880:     {href=>"javascript:backPage(document.$state,'$states{$action}[0]')",
                    881:       text=>"$trail{$action}{$states{$action}[$i]}"});
                    882:                 } else { 
                    883:                     &Apache::lonhtmlcommon::add_breadcrumb(
                    884:      {href=>"javascript:backPage(document.$state,'$states{$action}[$i]')",
                    885:       text=>"$trail{$action}{$states{$action}[$i]}"});
                    886:                 }
                    887:             }
                    888:         }
                    889:     } elsif (($action eq 'view') && ($view_permission)) {
                    890:                         &Apache::lonhtmlcommon::add_breadcrumb(
1.29      raeburn   891:                    {text=>"View $gpterm".'s'});
                    892:         my $crumbtitle = "$crstype $ucgpterm".'s Manager';
1.1       raeburn   893:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
1.29      raeburn   894: 		  (&mt($crumbtitle)));
1.39      albertel  895:         &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
                    896: 			$manage_permission,$action,$state,$gpterm,$ucgpterm,
                    897: 			$crstype);
1.3       raeburn   898: 
                    899:     }
                    900:     $r->print(&footer());
                    901:     return;
                    902: }
                    903: 
1.5       raeburn   904: sub retrieve_settings {
                    905:     my ($cdom,$cnum,$groupname) = @_;
1.17      raeburn   906:     my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum,$groupname);
1.15      albertel  907: 
                    908:     return if (!%curr_groups);
                    909: 
                    910:     my %groupinfo = 
1.17      raeburn   911: 	&Apache::longroup::get_group_settings($curr_groups{$groupname});
1.15      albertel  912: 
1.5       raeburn   913:     my %stored;
1.15      albertel  914: 
                    915:     $stored{'description'} = 
1.24      www       916: 	&unescape($groupinfo{'description'});
1.15      albertel  917:     $stored{'startdate'} = $groupinfo{'startdate'};
                    918:     $stored{'enddate'} = $groupinfo{'enddate'};
                    919:     if ($stored{'enddate'} == 0) {
                    920: 	$stored{'no_end_date'} = 1;
                    921:     }
                    922:     $stored{'granularity'} = $groupinfo{'granularity'};
                    923:     $stored{'specificity'} = $groupinfo{'specificity'};
                    924:     $stored{'creation'} = $groupinfo{'creation'};
                    925:     $stored{'creator'} = $groupinfo{'creator'};
1.29      raeburn   926:     $stored{'quota'} = $groupinfo{'quota'};
1.15      albertel  927: 
                    928:     foreach my $tool (sort(keys(%{$groupinfo{'functions'}}))) {
                    929: 	if ($groupinfo{functions}{$tool} eq 'on') {
                    930: 	    push(@{$stored{tool}},$tool);
                    931: 	}
                    932:     }
                    933:     foreach my $role (@{$groupinfo{'roles'}}) {
                    934: 	push(@{$stored{roles}},$role);
                    935:     }
                    936:     foreach my $type (@{$groupinfo{'types'}}) {
                    937: 	push(@{$stored{types}},$type);
                    938:     }
                    939:     foreach my $section (@{$groupinfo{'sectionpick'}}) {
                    940: 	push(@{$stored{sectionpick}},$section);
                    941:     }
                    942:     foreach my $defpriv (@{$groupinfo{'defpriv'}}) {
                    943: 	push(@{$stored{defpriv}},$defpriv);
                    944:     }
                    945:     $stored{'autoadd'} = $groupinfo{'autoadd'};
                    946:     $stored{'autodrop'} = $groupinfo{'autodrop'};
                    947:     if (exists($groupinfo{'autosec'})) {
                    948: 	foreach my $role (sort(keys(%{$groupinfo{'autosec'}}))) {
1.17      raeburn   949:             if (ref($groupinfo{'autosec'}{$role}) eq 'ARRAY') {
                    950: 	        foreach my $section (@{$groupinfo{'autosec'}{$role}}) {
                    951: 	            push (@{$stored{'sec_'.$role}},$section);
                    952: 	        }
                    953: 	        if (@{$groupinfo{'autosec'}{$role}} > 0) {
                    954: 		    push(@{$stored{'autorole'}},$role);
                    955: 	        }
                    956:             }
1.15      albertel  957: 	}
1.5       raeburn   958:     }
                    959:     return %stored;
                    960: }
                    961: 
1.3       raeburn   962: sub display_control {
1.5       raeburn   963:     my ($r,$cdom,$cnum,$tabcol,$action,$state,$page,$sectioncount,$groupname,
1.3       raeburn   964:         $description,$functions,$tools,$toolprivs,$fixedprivs,$startdate,
1.45    ! albertel  965:         $enddate,$users,$userdata,$idx,$memchg,$usertools,
1.29      raeburn   966:         $view_permission,$manage_permission,$stored,$granularity,$quota,
                    967:         $specificity,$types,$roles,$sections,$states,$navbuttons,$rowColor1,
                    968:         $rowColor2,$gpterm,$ucgpterm,$crstype) = @_;
1.3       raeburn   969:     if ($action eq 'create') {
                    970:         if ($state eq 'pick_name') {
1.5       raeburn   971:             &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,
                    972:                                    $functions,$tools,$toolprivs,$fixedprivs,
                    973:                                    $sectioncount,$stored,$states,$navbuttons,
1.29      raeburn   974:                                    $rowColor1,$rowColor2,$gpterm,$ucgpterm,
                    975:                                    $crstype);
1.3       raeburn   976:         } elsif ($state eq 'pick_members') {
1.5       raeburn   977:             &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
1.29      raeburn   978:                                  $groupname,$description,$granularity,$quota,
1.5       raeburn   979:                                  $startdate,$enddate,$tools,$fixedprivs,
                    980:                                  $toolprivs,$functions,$users,$userdata,$idx,
                    981:                                  $stored,$states,$navbuttons,$rowColor1,
1.29      raeburn   982:                                  $rowColor2,$gpterm,$ucgpterm,$crstype);
1.3       raeburn   983:         } elsif ($state eq 'pick_privs') {
1.45    ! albertel  984:             &choose_privs_form($r,$cdom,$cnum,$action,$state,$page,
1.5       raeburn   985:                                $startdate,$enddate,$tools,$functions,
                    986:                                $toolprivs,$fixedprivs,$userdata,$usertools,
                    987:                                $idx,$states,$stored,$sectioncount,$navbuttons,
1.45    ! albertel  988:                                $gpterm,$ucgpterm,$crstype);
1.3       raeburn   989:         } elsif ($state eq 'result') {
1.45    ! albertel  990:             &process_request($r,$cdom,$cnum,$action,$state,$page,
1.5       raeburn   991:                              $groupname,$description,$specificity,$userdata,
                    992:                              $startdate,$enddate,$tools,$functions,
                    993:                              $toolprivs,$usertools,$idx,$types,$roles,
                    994:                              $sections,$states,$navbuttons,$memchg,
1.45    ! albertel  995:                              $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
1.5       raeburn   996:         }
                    997:     } elsif ($action eq 'modify') {
                    998:         my $groupname = $env{'form.groupname'};
                    999:         if ($state eq 'pick_group') {
1.39      albertel 1000:             &display_groups($r,$cdom,$cnum,$functions,$idx,$view_permission,
                   1001: 			    $manage_permission,$action,$state,$gpterm,
                   1002: 			    $ucgpterm,$crstype);
1.5       raeburn  1003:         } elsif ($state eq 'pick_task') {
1.29      raeburn  1004:             &modify_menu($r,$groupname,$page,$gpterm);
1.5       raeburn  1005:         } elsif ($state eq 'change_settings') {
                   1006:             &general_settings_form($r,$cdom,$cnum,$action,$tabcol,$state,$page,
                   1007:                                    $functions,$tools,$toolprivs,$fixedprivs,
                   1008:                                    $sectioncount,$stored,$states,$navbuttons,
1.29      raeburn  1009:                                    $rowColor1,$rowColor2,$gpterm,$ucgpterm,
                   1010:                                    $crstype);
1.5       raeburn  1011:         } elsif ($state eq 'change_members') {
                   1012:             &change_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                   1013:                                  $groupname,$description,$startdate,$enddate,
                   1014:                                  $tools,$fixedprivs,$functions,$users,
1.29      raeburn  1015:                                  $userdata,$granularity,$quota,$specificity,
                   1016:                                  $idx,$states,$navbuttons,$rowColor1,$rowColor2,
                   1017:                                  $gpterm,$ucgpterm);
1.5       raeburn  1018:         } elsif ($state eq 'add_members') {
                   1019:             &add_members_form($r,$tabcol,$action,$state,$page,$startdate,
                   1020:                               $enddate,$groupname,$description,$granularity,
1.29      raeburn  1021:                               $quota,$sectioncount,$tools,$functions,$stored,
                   1022:                               $states,$navbuttons,$rowColor1,$rowColor2,$gpterm,
                   1023:                               $ucgpterm);
1.5       raeburn  1024:         } elsif ($state eq 'pick_members') {
                   1025:             &choose_members_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
1.29      raeburn  1026:                                  $groupname,$description,$granularity,$quota,
1.5       raeburn  1027:                                  $startdate,$enddate,$tools,$fixedprivs,
                   1028:                                  $toolprivs,$functions,$users,$userdata,$idx,
                   1029:                                  $stored,$states,$navbuttons,$rowColor1,
1.29      raeburn  1030:                                  $rowColor2,$gpterm,$ucgpterm,$crstype);
1.5       raeburn  1031:         } elsif ($state eq 'pick_privs') {
                   1032:             &choose_privs_form($r,$cdom,$cnum,$tabcol,$action,$state,$page,
                   1033:                                $startdate,$enddate,$tools,$functions,
                   1034:                                $toolprivs,$fixedprivs,$userdata,$usertools,
                   1035:                                $idx,$states,$stored,$sectioncount,$navbuttons,
1.29      raeburn  1036:                                $rowColor1,$rowColor2,$gpterm,$ucgpterm,$crstype);
1.5       raeburn  1037:         } elsif ($state eq 'change_privs') {
1.45    ! albertel 1038:             &change_privs_form($r,$cdom,$cnum,$action,$state,$page,
1.5       raeburn  1039:                                $startdate,$enddate,$tools,$functions,
                   1040:                                $toolprivs,$fixedprivs,$userdata,$usertools,
                   1041:                                $memchg,$idx,$states,$stored,$sectioncount,
1.45    ! albertel 1042:                                $navbuttons,$gpterm,$ucgpterm);
1.5       raeburn  1043:         } elsif ($state eq 'chgresult' || $state eq 'memresult' || 
                   1044:                  $state eq 'addresult') {
1.45    ! albertel 1045:             &process_request($r,$cdom,$cnum,$action,$state,$page,
1.5       raeburn  1046:                              $groupname,$description,$specificity,$userdata,
                   1047:                              $startdate,$enddate,$tools,$functions,
                   1048:                              $toolprivs,$usertools,$idx,$types,$roles,
                   1049:                              $sections,$states,$navbuttons,$memchg,
1.45    ! albertel 1050:                              $sectioncount,$stored,$gpterm,$ucgpterm,$crstype);
1.1       raeburn  1051:         }
                   1052:     }
                   1053: }
                   1054: 
                   1055: sub header {
1.39      albertel 1056:     my ($bodytitle,$jscript,$action,$state,$page,$loaditems) = @_;
1.9       albertel 1057:     my $start_page=
1.11      albertel 1058: 	&Apache::loncommon::start_page($bodytitle,
                   1059: 				       '<script type="text/javascript">'.
                   1060: 				       $jscript.'</script>',
1.39      albertel 1061: 				       {'add_entries' => $loaditems,});
1.3       raeburn  1062:     my $output = <<"END";
1.11      albertel 1063: $start_page
1.9       albertel 1064: <form method="POST" name="$state">
1.3       raeburn  1065: 
                   1066: END
                   1067:     if ($action eq 'create' || $action eq 'modify') {
                   1068:         $output .= <<"END";
                   1069:  <input type="hidden" name="action" value="$action" />
                   1070:  <input type="hidden" name="state" value="" />
                   1071:  <input type="hidden" name="origin" value="$state" />
1.5       raeburn  1072:  <input type="hidden" name="page" value="$page" />
1.3       raeburn  1073: END
                   1074:     }
                   1075:     return $output;
1.1       raeburn  1076: }
                   1077: 
1.3       raeburn  1078: sub onload_action {
                   1079:     my ($action,$state) = @_;
1.13      albertel 1080:     my %loaditems;
1.3       raeburn  1081:     if ((defined($env{'form.origin'})) && ($action eq 'create') &&
                   1082:                 ($state eq 'pick_name' || $state eq 'pick_members' || 
                   1083:                  $state eq 'pick_privs')) {
                   1084:         unless ($env{'form.origin'} eq '') {
1.13      albertel 1085: 	    $loaditems{'onload'} = 
                   1086: 		'javascript:setFormElements(document.'.$state.')';
1.1       raeburn  1087:         }
                   1088:     }
1.5       raeburn  1089:     if (($action eq 'modify') &&
                   1090:                 ($state eq 'change_settings' || $state eq 'change_members' ||
1.7       raeburn  1091:                  $state eq 'change_privs' || $state eq 'add_members' ||
                   1092:                  $state eq 'pick_members')) {
1.13      albertel 1093: 	$loaditems{'onload'} = 
                   1094: 	    'javascript:setFormElements(document.'.$state.')';
1.5       raeburn  1095:     }
1.13      albertel 1096:     return \%loaditems;
1.1       raeburn  1097: }
                   1098: 
                   1099: sub footer {
1.9       albertel 1100:     my $end_page = &Apache::loncommon::end_page();
1.1       raeburn  1101:        return(<<ENDFOOT);
1.6       raeburn  1102:    <input type="hidden" name="sortby" value="$env{'form.sortby'}" />
1.1       raeburn  1103:   </form>
1.9       albertel 1104: $end_page
1.1       raeburn  1105: ENDFOOT
                   1106: }
                   1107: 
1.3       raeburn  1108: sub build_members_list {
                   1109:     my ($cdom,$cnum,$types,$roles,$sections,$users,$userdata) = @_;
                   1110:     my %access = ();
                   1111:     foreach my $role (@{$roles}) {
                   1112:         %{$$users{$role}} = ();
                   1113:     }
                   1114:     foreach my $type (@{$types}) {
                   1115:         $access{$type} = $type;
                   1116:     }
                   1117:     &Apache::loncommon::get_course_users($cdom,$cnum,\%access,$roles,
1.5       raeburn  1118:                                          $sections,$users,$userdata);
1.3       raeburn  1119:     return;
                   1120: }
                   1121: 
                   1122: sub group_files {
1.29      raeburn  1123:     my ($group,$currdir,$numfiles,$numdirs) = @_;
                   1124:     my $dirptr=16384;
                   1125:     my @dir_list=&Apache::portfolio::get_dir_list($currdir,$group);
                   1126:     foreach my $line (@dir_list) {
                   1127:         my ($filename,$dom,undef,$testdir,undef,undef,undef,undef,$size,undef,$mtime,undef,undef,undef,$obs,undef)=split(/\&/,$line,16);
                   1128:         if (($filename !~ /^\.\.?$/) && ($filename !~ /\.meta$/ ) && ($filename !~ /(.*)\.(\d+)\.([^\.]*)$/) && ($filename ne 'no_such_dir')) { 
                   1129:             if ($dirptr&$testdir) {
                   1130:                 $currdir .= '/'.$filename;
                   1131:                 $$numdirs ++;
                   1132:                 &group_files($numfiles,$numdirs)
                   1133:             } else {
                   1134:                 $$numfiles ++;
                   1135:             }
                   1136:         }
                   1137:     }
1.3       raeburn  1138:     return;
                   1139: }
                   1140: 
                   1141: sub group_members {
1.4       raeburn  1142:     my ($cdom,$cnum,$group,$group_info) = @_;
                   1143:     my %memberhash = &Apache::lonnet::get_group_membership($cdom,$cnum,$group);
                   1144:     my $now = time;
                   1145:     my ($tmp)=keys(%memberhash);
                   1146:     if ($tmp=~/^error:/) {
                   1147:         $$group_info{'totalmembers'} = 'Unknown - an error occurred';
                   1148:         return $tmp;
                   1149:     }
                   1150:     my $totalmembers = 0;
                   1151:     my $active = 0;
                   1152:     my $previous = 0;
                   1153:     my $future = 0;
                   1154:     foreach my $member (keys %memberhash) {
                   1155:         $totalmembers ++;
                   1156:         my ($end,$start) = split(/:/,$memberhash{$member});
1.6       raeburn  1157:         unless ($start == -1) {
                   1158:             if (($end!=0) && ($end<$now)) {
                   1159:                 $previous ++;
                   1160:             } elsif (($start!=0) && ($start>$now)) {
                   1161:                 $future ++;
                   1162:             } else {
                   1163:                $active ++;
                   1164:             }
1.4       raeburn  1165:         }
                   1166:     }
                   1167:     if ($totalmembers == 0) {
                   1168:         $$group_info{$group}{'totalmembers'} = 'None';
                   1169:     } else {
                   1170:         $$group_info{$group}{'totalmembers'} = $active.' - active<br />'.$previous.' -previous<br />'.$future.' -future';
                   1171:     }
                   1172:     return 'ok';
1.3       raeburn  1173: }
                   1174: 
                   1175: 
1.5       raeburn  1176: sub general_settings_form {
                   1177:     my ($r,$cdom,$cnum,$action,$tabcol,$formname,$page,$functions,$tools,
                   1178:         $toolprivs,$fixedprivs,$sectioncount,$stored,$states,$navbuttons,
1.29      raeburn  1179:         $rowColor1,$rowColor2,$gpterm,$ucgpterm,$crstype) = @_;
1.5       raeburn  1180:     my ($nexttext,$prevtext);
1.42      albertel 1181:     &groupsettings_options($r,$functions,$action,$formname,$stored,1,
1.29      raeburn  1182:                            $gpterm,$ucgpterm,$crstype);
1.41      albertel 1183:     &access_date_settings($r,$action,$formname,$stored,2,$gpterm,$ucgpterm);
1.5       raeburn  1184:     if ($action eq 'create') {
1.40      albertel 1185:         &membership_options($r,$action,$formname,$sectioncount,3,$gpterm,
                   1186: 			    $ucgpterm);
1.5       raeburn  1187:         $nexttext = $$navbuttons{'gtns'};
                   1188:     } else {
                   1189:         my @available = ();
                   1190:         my @unavailable = ();
                   1191:         &check_tools($functions,$tools,\@available,\@unavailable);
                   1192:         @{$tools} = sort(keys(%{$functions}));
                   1193:         &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
                   1194:                                3,$tools,$stored,$toolprivs,$fixedprivs,
1.29      raeburn  1195:                                \@available,$formname,$gpterm,$ucgpterm);
1.44      albertel 1196:         &mapping_options($r,$action,$formname,$page,$sectioncount,
                   1197:                          $states,$stored,$navbuttons,4,5,
                   1198: 			 $gpterm,$ucgpterm,$crstype);
1.5       raeburn  1199:         $nexttext = $$navbuttons{'mose'};
                   1200:     }
                   1201:     $prevtext = $$navbuttons{'gtpp'};
                   1202:     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                   1203:                         $$states{$action}[$page+1],$nexttext);
                   1204:     return;
                   1205: }
                   1206: 
                   1207: sub groupsettings_options {
1.42      albertel 1208:     my ($r,$functions,$action,$formname,$stored,$image,$gpterm,
1.29      raeburn  1209:         $ucgpterm,$crstype) = @_;
1.1       raeburn  1210:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  1211:         'gdat' => "$ucgpterm open and close dates",
                   1212:         'sten' => "Set a start date/time and end date/time for the $gpterm",
                   1213:         'gfun' => "$ucgpterm functionality",
                   1214:         'gnde' => "$ucgpterm name, description and available functionality",
1.5       raeburn  1215:         'desc' => 'Description',
                   1216:         'func' => 'Functionality',
1.29      raeburn  1217:         'gnam' => "$ucgpterm Name",
                   1218:         'doyo' => "Do you want to assign different functionality ".
                   1219:                   "to different $gpterm members?",
1.1       raeburn  1220:     );
1.37      raeburn  1221:     my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,$stored);
1.40      albertel 1222:     &topic_bar($r,$image,$lt{'gnde'});
1.5       raeburn  1223:     $r->print('
1.42      albertel 1224:      <table class="LC_descriptive_input">
1.3       raeburn  1225:       <tr>
1.42      albertel 1226:        <td class="LC_description">'.$lt{'gnam'}.':</td>
1.5       raeburn  1227:        <td colspan="5">
                   1228: ');
                   1229:     if ($action eq 'create') {
                   1230:         $r->print('<input type="text" name="groupname" size="25" />');
                   1231:     } else {
                   1232:         $r->print('<input type="hidden" name="groupname" value="'.
                   1233:                          $env{'form.groupname'}.'" />'.$env{'form.groupname'});
                   1234:     }
                   1235:     $r->print(<<"END");
1.3       raeburn  1236:        </td>
                   1237:       <tr>
                   1238:       <tr>
1.42      albertel 1239:        <td class="LC_description">$lt{'desc'}:</td>
1.5       raeburn  1240:        <td colspan="5"><input type="text" name="description" size="40"
                   1241:                                                     value="" />
1.3       raeburn  1242:        </td>
                   1243:       <tr>
                   1244:       <tr>
1.42      albertel 1245:        <td class="LC_description">$lt{'func'}:</td>
1.3       raeburn  1246: END
                   1247:     my $numitems = keys(%{$functions});
                   1248:     my $halfnum = int($numitems/2);
                   1249:     my $remnum = $numitems%2;
                   1250:     if ($remnum) {
                   1251:         $halfnum ++;
                   1252:     }
1.5       raeburn  1253:     my @allfunctions = sort(keys (%{$functions}));
1.3       raeburn  1254:     for (my $i=0; $i<$halfnum; $i++) {
1.7       raeburn  1255:         $r->print('<td><label><input type="checkbox" name="tool" value="'.
1.3       raeburn  1256:                   $allfunctions[$i].'" />&nbsp;'.
1.7       raeburn  1257:                    $$functions{$allfunctions[$i]}.'</label></td>
1.3       raeburn  1258:                    <td>&nbsp;</td><td>&nbsp;</td>');
                   1259:     }
                   1260:     $r->print('<td><input type="button" value="check all" '.
                   1261:               'onclick="javascript:checkAll(document.'.$formname.'.tool)" />'.
                   1262:               '</td></tr><tr><td>&nbsp;</td>');
                   1263:     for (my $j=$halfnum; $j<@allfunctions; $j++) {
1.7       raeburn  1264:         $r->print('<td><label><input type="checkbox" name="tool" value="'.
1.3       raeburn  1265:                   $allfunctions[$j].'" />&nbsp;'.
1.7       raeburn  1266:                   $$functions{$allfunctions[$j]}.'</label></td>
1.3       raeburn  1267:                   <td>&nbsp;</td><td>&nbsp;</td>');
                   1268:     }
                   1269:     if ($remnum) {
                   1270:         $r->print('<td>&nbsp;</td>');
                   1271:     }
1.5       raeburn  1272:     $r->print('
1.3       raeburn  1273:        <td>
1.5       raeburn  1274:         <input type="button" value="uncheck all"
                   1275:           onclick="javascript:uncheckAll(document.'.$formname.'.tool)" />
1.3       raeburn  1276:        </td>
                   1277:       </tr>
                   1278:       <tr>
1.42      albertel 1279:        <td class="LC_description">'.&mt('Granularity:').'</td>
1.29      raeburn  1280:        <td colspan="10">'.$lt{'doyo'}.'&nbsp;<label><input type="radio" name="granularity" value="Yes" />'.&mt('Yes').'</label>&nbsp;<label><input type="radio" name="granularity" value="No" checked="checked" />'.&mt('No').'</label>');
1.5       raeburn  1281:     if ($action eq 'modify') {
                   1282:         $r->print('&nbsp;&nbsp;('.&mt('Currently set to "[_1]"',
                   1283:                                       $$stored{'granularity'}).')');
                   1284:     }
                   1285:     $r->print('
                   1286:        </td>
                   1287:       </tr>
1.29      raeburn  1288:       <tr>
1.42      albertel 1289:        <td class="LC_description">'.&mt('Disk quota: ').'</td><td colspan="10">');
1.29      raeburn  1290:     if ($action eq 'create') {
                   1291:         $r->print(&mt('If you enable the file repository for the [_1], allocate a disk quota.',$gpterm));
                   1292:     } else {
                   1293:         $r->print(&mt('Quota allocated to file repository:'));
                   1294:     } 
                   1295:     $r->print('&nbsp;<input type="text" name="quota" size="4" />Mb');
                   1296:     if ($action eq 'create') {
                   1297:         $r->print('<br />'.
                   1298:                   &mt('A total of [_1] Mb is shared between all [_2]s in the '.
                   1299:                   '[_3], and [_4] Mb are currently unallocated.',$crsquota,
                   1300:                   $gpterm,lc($crstype),$freespace));
                   1301:     } else {
                   1302:         $r->print('&nbsp;&nbsp;('.&mt('The quota is currently [_1] Mb',
                   1303:                                       $$stored{'quota'}).').');
                   1304: 
                   1305:         $r->print('<br />'.&mt('The quota can be increased to [_1] Mb, '.
                   1306:                   'by adding all unallocated space for [_2]s in the [_3].',
                   1307:                   $maxposs,$gpterm,lc($crstype)));
                   1308:     }
                   1309:     $r->print('
                   1310:        </td>
                   1311:       </tr>
1.3       raeburn  1312:      </table>
1.5       raeburn  1313: ');
                   1314:     return;
                   1315: }
                   1316: 
1.37      raeburn  1317: sub get_quota_constraints {
                   1318:     my ($action,$stored) = @_;
                   1319:     my ($crsquota,$freespace,$maxposs); 
                   1320:     $crsquota = $env{'course.'.$env{'request.course.id'}.'.internal.coursequota'};
                   1321:     if ($crsquota eq '') {
                   1322:         $crsquota = 20;
                   1323:     }
                   1324:     $freespace = $crsquota - &Apache::longroup::sum_quotas();
                   1325:     if ($action eq 'create') {
                   1326:         $maxposs = $freespace;
                   1327:     } else {
                   1328:         $maxposs = $$stored{'quota'} + $freespace;
                   1329:     }
                   1330:     return ($crsquota,$freespace,$maxposs);
                   1331: }
                   1332: 
1.5       raeburn  1333: sub membership_options {
1.40      albertel 1334:     my ($r,$action,$state,$sectioncount,$image,$gpterm,$ucgpterm) = @_;
1.29      raeburn  1335:     my $crstype = &Apache::loncommon::course_type();
1.5       raeburn  1336:     my %lt = &Apache::lonlocal::texthash(
                   1337:                 'pipa' => 'Pick parameters to generate membership list',
1.29      raeburn  1338:                 'gmem' => "$ucgpterm membership options",
1.5       raeburn  1339:                 'picr' => 'Pick the criteria to use to build a list of '.
1.29      raeburn  1340:                           lc($crstype).' users from which you will select ',
                   1341:                 'meof' => "members of the new $gpterm.",
                   1342:                 'admg' => "additional members of the $gpterm.",
                   1343:                 'ifno' => "If you do not wish to add members when you first ".
                   1344:                           "create the $gpterm, do not make any selections.",
                   1345:                 'asub' => "A subsequent step will also allow you to specify automatic adding/dropping of $gpterm members triggered by specified role and section changes.",
1.5       raeburn  1346:                 'acty' => 'Access types',
1.29      raeburn  1347:                 'coro' => $crstype.' roles',
                   1348:                 'cose' => $crstype.' sections',
1.5       raeburn  1349:              );
                   1350:     my %status_types = (
                   1351:                    active => &mt('Currently has access'),
                   1352:                    previous => &mt('Previously had access'),
                   1353:                    future => &mt('Will have future access'),
                   1354:                    );
1.15      albertel 1355: 
1.34      albertel 1356:     #FIXME need to plumb around for the various cr roles defined by the user
                   1357:     my @roles = ('st','cc','in','ta','ep');
1.5       raeburn  1358: 
                   1359:     my @sections = keys(%{$sectioncount});
                   1360: 
1.40      albertel 1361:     &topic_bar($r,$image,$lt{'pipa'});
1.5       raeburn  1362:     $r->print('
1.40      albertel 1363:      <b>'.$lt{'gmem'}.'</b><br />'.$lt{'picr'});
1.5       raeburn  1364:     if ($action eq 'create') {
1.21      raeburn  1365:         $r->print($lt{'meof'}.'<br />'.$lt{'ifno'}.'<br />'.$lt{'asub'});
1.5       raeburn  1366:     } else {
1.6       raeburn  1367:         $r->print($lt{'admg'});
1.5       raeburn  1368:     }
                   1369:     $r->print('
                   1370:      <br />
                   1371:      <br />
1.40      albertel 1372:      <table class="LC_status_selector">
1.3       raeburn  1373:       <tr>
1.40      albertel 1374:        <th>'.$lt{'acty'}.'</th>
                   1375:        <th>'.$lt{'coro'}.'</th>');
1.3       raeburn  1376:     if (@sections >0) {
1.5       raeburn  1377:         $r->print('
1.40      albertel 1378:        <th>'.$lt{'cose'}.'</th>');
1.3       raeburn  1379:     }
1.40      albertel 1380:     $r->print('</tr><tr><td>');
1.3       raeburn  1381:     $r->print(&Apache::lonhtmlcommon::status_select_row(\%status_types));
1.40      albertel 1382:     $r->print('</td><td>');
1.3       raeburn  1383:     $r->print(&Apache::lonhtmlcommon::role_select_row(\@roles));
                   1384:     if (@sections > 0) {
1.5       raeburn  1385:         @sections = sort {$a cmp $b} @sections;
1.31      albertel 1386:         unshift(@sections,'none'); # Put 'no sections' next
1.17      raeburn  1387:         unshift(@sections,'all'); # Put 'all' at the front of the list
1.40      albertel 1388:         $r->print('</td><td>'.
1.5       raeburn  1389:         &sections_selection(\@sections,'sectionpick').'</td>');
1.3       raeburn  1390:     }
                   1391:     $r->print('
                   1392:       </tr>
1.40      albertel 1393:      </table>');
1.5       raeburn  1394:     return;
                   1395: }
                   1396: 
                   1397: sub sections_selection {
                   1398:     my ($sections,$elementname) = @_;
                   1399:     my $section_sel;
                   1400:     my $numvisible = 4;
                   1401:     if (@{$sections} < 4) {
                   1402:         $numvisible = @{$sections};
                   1403:     }
                   1404:     foreach my $sec (@{$sections}) {
1.17      raeburn  1405:         if ($sec eq 'all') {
1.31      albertel 1406:             $section_sel .= '  <option value="'.$sec.'" selected="selected">'.&mt('all sections').'</option>'."\n";
1.17      raeburn  1407:         } elsif ($sec eq 'none') {
1.31      albertel 1408:             $section_sel .= '  <option value="'.$sec.'">'.&mt('no section').'</option>'."\n"; 
1.5       raeburn  1409:         } else {
1.31      albertel 1410:             $section_sel .= '  <option value="'.$sec.'">'.$sec."</option>\n";
1.5       raeburn  1411:         }
                   1412:     }
                   1413:     my $output = '
                   1414:         <select name="'.$elementname.'" multiple="true" size="'.$numvisible.'">
                   1415:           '.$section_sel.'
                   1416:         </select>';
                   1417:     return $output;
                   1418: }
                   1419: 
                   1420: sub access_date_settings {
1.41      albertel 1421:     my ($r,$action,$formname,$stored,$image,$gpterm,$ucgpterm) = @_;
1.5       raeburn  1422:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  1423:                 'sten' => "Default start and end dates for $gpterm access",
1.5       raeburn  1424:              );
                   1425:     my $starttime = time;
                   1426:     my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
                   1427:     if ($action eq 'modify') {
                   1428:         $starttime = $$stored{'startdate'};
                   1429:         unless ($$stored{'enddate'} == 0) {
                   1430:             $endtime = $$stored{'enddate'};
                   1431:         }
                   1432:     }
1.41      albertel 1433:     my ($table) = &date_setting_table($starttime,$endtime,$formname);
1.40      albertel 1434:     &topic_bar($r,$image,$lt{'sten'});
1.5       raeburn  1435:     $r->print('
1.41      albertel 1436:     '.$table.'
                   1437:     ');
1.3       raeburn  1438:     return;
                   1439: }
                   1440: 
1.5       raeburn  1441: sub choose_members_form {
                   1442:     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
1.29      raeburn  1443:         $granularity,$quota,$startdate,$enddate,$tools,$fixedprivs,$toolprivs,
1.5       raeburn  1444:         $functions,$users,$userdata,$idx,$stored,$states,$navbuttons,
1.29      raeburn  1445:         $rowColor1,$rowColor2,$gpterm,$ucgpterm,$crstype) = @_;
1.5       raeburn  1446:     my @regexps = ('user_','userpriv_','sec_');
                   1447:     my %origmembers;
1.3       raeburn  1448:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.5       raeburn  1449:          ['origin','action','state','page','member','specificity','branch',
1.7       raeburn  1450:           'defpriv','autorole','autoadd','autodrop','sortby','togglefunc'],
1.5       raeburn  1451:          \@regexps));
1.29      raeburn  1452:     my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
                   1453:                                        $ucgpterm,$crstype);
1.5       raeburn  1454:     if ($earlyout) {
1.42      albertel 1455: 	$r->print($earlyout)
1.5       raeburn  1456:         &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                   1457:                            $$navbuttons{'gtps'});
1.3       raeburn  1458:         return;
1.5       raeburn  1459:     } 
                   1460:     my ($specimg,$memimg);
                   1461:     my @available = ();
                   1462:     my @unavailable = ();
                   1463:     &check_tools($functions,$tools,\@available,\@unavailable);
                   1464:     if ($action eq 'create') {
1.40      albertel 1465:         &print_current_settings($r,$action,$functions,$startdate,$enddate,
                   1466: 				$groupname,$description,$granularity,$quota,
                   1467: 				\@available,\@unavailable,$gpterm,$ucgpterm);
1.5       raeburn  1468:         $specimg = 4;
                   1469:         $memimg = 5;
                   1470:     } else {
                   1471:         $specimg = 2;
                   1472:         $memimg = 3;
                   1473:         my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                   1474:                                                                $groupname);
                   1475:         foreach my $key (sort(keys(%membership))) {
                   1476:             if ($key =~ /^\Q$groupname\E:([^:]+):([^:]+)$/) {
1.6       raeburn  1477:                 my ($end,$start,@userprivs) = split(/:/,$membership{$key});
                   1478:                 unless ($start == -1) {  
                   1479:                     my $uname = $1;
                   1480:                     my $udom = $2;
                   1481:                     my $user = $uname.':'.$udom;
                   1482:                     $origmembers{$user} = 1; 
                   1483:                 }
1.5       raeburn  1484:             }
                   1485:         }
                   1486:     }
                   1487:     &privilege_specificity($r,$tabcol,$rowColor1,$rowColor2,$action,
                   1488:                           $specimg,$tools,$stored,$toolprivs,
1.29      raeburn  1489:                           $fixedprivs,\@available,$formname,$gpterm,$ucgpterm);
1.44      albertel 1490:     my $newusers = &pick_new_members($r,$action,$formname,\@available,$idx,
                   1491: 				     $stored,$memimg,$users,$userdata,
                   1492: 				     $granularity,\%origmembers,$gpterm,
                   1493: 				     $ucgpterm);
1.5       raeburn  1494:     if ($newusers || $action eq 'create') {
                   1495:         &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                   1496:                             $$navbuttons{'gtps'},$$states{$action}[$page+1],
                   1497:                             $$navbuttons{'gtns'});
                   1498:     } else {
                   1499:         &display_navbuttons($r,$formname,$$states{$action}[$page-1],
                   1500:                             $$navbuttons{'gtps'});
1.3       raeburn  1501:     }
1.5       raeburn  1502:     return;
                   1503: }
                   1504: 
                   1505: sub display_navbuttons {
                   1506:     my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
1.42      albertel 1507:     $r->print('<div class="LC_navbuttons">');
1.5       raeburn  1508:     if ($prev) {
                   1509:         $r->print('
                   1510:       <input type="button" name="previous" value = "'.$prevtext.'"
                   1511:     onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
                   1512:    &nbsp;&nbsp;&nbsp;');
                   1513:     }
                   1514:     if ($next) {
                   1515:         $r->print('
                   1516:       <input type="button" name="next" value="'.$nexttext.'"
                   1517:  onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
                   1518:     }
1.42      albertel 1519:     $r->print('</div>');
1.5       raeburn  1520: }
                   1521: 
                   1522: sub check_tools {
                   1523:     my ($functions,$tools,$available,$unavailable) = @_;
                   1524:     foreach my $item (sort(keys(%{$functions}))) {
                   1525:         if (grep/^$item$/,@{$tools}) {
                   1526:             push(@{$available},$item);
                   1527:         } else {
                   1528:             push(@{$unavailable},$item);
                   1529:         }
                   1530:     }
                   1531:     return;
                   1532: }
                   1533: 
                   1534: sub print_current_settings {
1.40      albertel 1535:     my ($r,$action,$functions,$startdate,$enddate,$groupname,$description,
                   1536: 	$granularity,$quota,$available,$unavailable,$gpterm,$ucgpterm) = @_;
1.5       raeburn  1537: 
                   1538:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  1539:         grna => "$ucgpterm Name",
1.5       raeburn  1540:         desc => 'Description',
1.29      raeburn  1541:         grfn => "$ucgpterm Functions",
1.5       raeburn  1542:         gran => 'Granularity',
1.29      raeburn  1543:         quot => 'File quota',
1.5       raeburn  1544:         dfac => 'Default access dates',
1.29      raeburn  1545:         ygrs => "Your $gpterm selections",
                   1546:         tfwa => "The following settings will apply to the $gpterm:",
                   1547:         difn => 'Different functionality<br />for different members:',
1.5       raeburn  1548:         stda => 'Start date',
                   1549:         enda => 'End date:',
                   1550:     );
1.3       raeburn  1551:     my $showstart = &Apache::lonlocal::locallocaltime($startdate);
1.5       raeburn  1552:     my $showend;
                   1553:     if ($enddate == 0) {
                   1554:         $showend = &mt('No end date set'); 
                   1555:     } else {
                   1556:         $showend = &Apache::lonlocal::locallocaltime($enddate);
                   1557:     }
                   1558:     if ($action eq 'create') {
                   1559:         $r->print('
1.42      albertel 1560: <div><span style="font-size: larger">'.$lt{'ygrs'}.'</span>
1.5       raeburn  1561: <br />'.$lt{'tfwa'}.'
1.40      albertel 1562: </div>');
1.5       raeburn  1563:     }
1.40      albertel 1564:     $r->print(&Apache::loncommon::start_data_table('LC_course_group_status').
                   1565: 	      &Apache::loncommon::start_data_table_header_row());
                   1566:     $r->print('
                   1567:   <th>'.$lt{'grna'}.'</th>
                   1568:   <th>'.$lt{'desc'}.'</th>
                   1569:   <th>'.$lt{'grfn'}.'</th>
                   1570:   <th>'.$lt{'gran'}.'</th>
                   1571:   <th>'.$lt{'quot'}.'</th>
                   1572:   <th>'.$lt{'dfac'}.'</th>
                   1573: ');
                   1574:     $r->print(&Apache::loncommon::end_data_table_header_row().
                   1575: 	      &Apache::loncommon::start_data_table_row('LC_data_table_dense'));
1.3       raeburn  1576:     $r->print('
1.40      albertel 1577:   <td valign="top">'.$groupname.'</td>
                   1578:   <td valign="top">'.$description.'</td>
1.3       raeburn  1579:   <td>
                   1580: ');
1.5       raeburn  1581:     if (@{$available} > 0) {
1.40      albertel 1582:         $r->print('<b>Available:</b>
1.3       raeburn  1583:                     <table cellpadding="" cellspacing="1"><tr>');
1.5       raeburn  1584:         my $rowcell = int(@{$available}/2) + @{$available}%2;
                   1585:         for (my $i=0; $i<@{$available}; $i++) {
                   1586:             if (@{$available} > 3) {
1.3       raeburn  1587:                 if ($i==$rowcell) {
                   1588:                     $r->print('</tr><tr>');
                   1589:                 }
                   1590:             }
1.40      albertel 1591:             $r->print('<td>'.$$functions{$$available[$i]}.
                   1592: 		      '</td><td>&nbsp;</td>');
1.3       raeburn  1593:         }
1.5       raeburn  1594:         if ((@{$available} > 3) && (@{$available}%2)) {
1.3       raeburn  1595:             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
                   1596:         }
                   1597:         $r->print('</tr></table><br />');
                   1598:     }
1.5       raeburn  1599:     if (@{$unavailable} > 0) {
1.40      albertel 1600:         $r->print('<b>Unavailable:</b>
1.3       raeburn  1601:                     <table cellpadding="0" cellspacing="1"  border="0"><tr>');
1.5       raeburn  1602:         my $rowcell = int(@{$unavailable}/2) + @{$unavailable}%2;
                   1603:         for (my $j=0; $j<@{$unavailable}; $j++) {
                   1604:             if (@{$unavailable} > 3) {
1.3       raeburn  1605:                 if ($j==$rowcell) {
                   1606:                     $r->print('</tr><tr>');
                   1607:                 }
                   1608:             }
1.40      albertel 1609:             $r->print('<td>'.$$functions{$$unavailable[$j]}.
                   1610: 		      '</td><td>&nbsp;</td>');
1.3       raeburn  1611:         }
1.5       raeburn  1612:         if ((@{$unavailable} > 3) && (@{$unavailable}%2)) {
1.3       raeburn  1613:             $r->print('<td>&nbsp;</td><td>&nbsp;</td>');
                   1614:         }
                   1615:         $r->print('</tr></table>');
                   1616:     }
                   1617:     $r->print(<<"END");
                   1618:   </td>
1.40      albertel 1619:   <td valign="top"><b>$lt{'difn'}</b> $granularity</td>
                   1620:   <td valign="top">$quota Mb</td> 
                   1621:   <td valign="top"><b>$lt{'stda'}</b> $showstart<br />
                   1622:       <b>$lt{'enda'}</b> $showend
1.3       raeburn  1623:   </td>
                   1624: END
1.40      albertel 1625:     $r->print(&Apache::loncommon::end_data_table_row().
                   1626: 	      &Apache::loncommon::end_data_table());
1.5       raeburn  1627:     return;
                   1628: }
                   1629: 
                   1630: sub pick_new_members {
1.44      albertel 1631:     my ($r,$action,$formname,$available,$idx,$stored,$img,$users,$userdata,
                   1632: 	$granularity,$origmembers,$gpterm,$ucgpterm) = @_;
1.5       raeburn  1633:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  1634:           'gpme' => "$ucgpterm membership",
1.5       raeburn  1635:           'addm' => 'Add members',
                   1636:           'setf' => 'Set functionality',
                   1637:           'func' => 'Functionality',
                   1638:           'nome' => 'No members to add at this time.',
1.29      raeburn  1639:           'nnew' => "There are no users to add as new members, as all users".
                   1640:                     " matching the specified type(s), role(s), and/or ".
                   1641:                     "section(s) are already affiliated with this $gpterm.",
1.5       raeburn  1642:           'yoma' =>  'You may need to use the '."'".'modify existing, past or '.
                   1643:                      'future members'."'".' page if you need to re-enable '.
                   1644:                      'or activate access for previous or future members.',
                   1645:     );
                   1646:     my %members;
                   1647:     my $totalusers = 0;
                   1648:     my $newusers = 0;
1.3       raeburn  1649:     foreach my $role (keys(%{$users})) {
                   1650:         foreach my $user (keys(%{$$users{$role}})) {
1.5       raeburn  1651:             $totalusers ++;
                   1652:             if (ref($origmembers) eq 'HASH') {
                   1653:                 if (exists($$origmembers{$user})) {
                   1654:                     next;
                   1655:                 }
                   1656:             }    
1.3       raeburn  1657:             unless (defined($members{$user})) {
                   1658:                 @{$members{$user}} = @{$$userdata{$user}};
1.5       raeburn  1659:                 $newusers ++;
1.3       raeburn  1660:             }
                   1661:         }
                   1662:     }
                   1663:     if (keys(%members) > 0) {
1.5       raeburn  1664:         if (@{$available} > 0 && $granularity eq 'Yes') {
                   1665:             $r->print(&check_uncheck_tools($r,$available));
                   1666:         }
                   1667:     }
1.40      albertel 1668:     &topic_bar($r,$img,$lt{'gpme'});
1.5       raeburn  1669:     if (keys(%members) > 0) {
                   1670:         $r->print('
1.3       raeburn  1671:     <table>
1.5       raeburn  1672:      <tr>');
                   1673:         &check_uncheck_buttons($r,$formname,'member',$lt{'addm'});
                   1674:         if (@{$available} > 0 && $granularity eq 'Yes') {
                   1675:             $r->print('<td><nobr>
                   1676:      <fieldset><legend><b>'.$lt{'setf'}.'</b></legend>
                   1677:       <input type="button" value="check all"
                   1678:         onclick="javascript:checkAllTools(document.'.$formname.')" />
                   1679:         &nbsp;&nbsp;
                   1680:       <input type="button" value="uncheck all"
1.3       raeburn  1681:         onclick="javascript:uncheckAllTools(document.'.$formname.')" />
1.5       raeburn  1682:      </fieldset></nobr></td>');
1.3       raeburn  1683:         }
                   1684:         $r->print('</tr></table>
                   1685:         ');
1.43      albertel 1686:         $r->print(&Apache::loncommon::start_data_table().
                   1687: 		  &Apache::loncommon::start_data_table_header_row());
1.5       raeburn  1688:         $r->print('
1.43      albertel 1689:      <th>'.&mt('Add?').'</b></td>
                   1690:      <th><a href="javascript:changeSort('."'fullname'".')">'.&mt('Name').'</a></td>
                   1691:      <th><a href="javascript:changeSort('."'username'".')">'.&mt('Username').'</a></td>
                   1692:      <th><a href="javascript:changeSort('."'domain'".')">'.&mt('Domain').'</a></td>
                   1693:      <th><a href="javascript:changeSort('."'id'".')">'.&mt('ID').'</a></td>
                   1694:      <th><a href="javascript:changeSort('."'section'".')">'.&mt('Section').'</a></td>
1.5       raeburn  1695: ');
                   1696:         if (@{$available} > 0) {
1.43      albertel 1697:             $r->print('<th>'.$lt{'func'}.'</th>');
1.3       raeburn  1698:         }
1.43      albertel 1699:         $r->print(&Apache::loncommon::end_data_table_header_row());
1.5       raeburn  1700:         if (@{$available} > 0) {
                   1701:             if ($granularity eq 'Yes') {
1.43      albertel 1702:                 $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense LC_data_table_highlight').'
1.35      raeburn  1703:  <td colspan="6">&nbsp;</td>
1.43      albertel 1704:  <td align="center"><nobr><b>'.&mt('All:').'</b>&nbsp;');
1.5       raeburn  1705:                 foreach my $tool (@{$available}) {
1.7       raeburn  1706:                     $r->print('<label><input type="checkbox" name="togglefunc" '.
                   1707:    'onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
                   1708:    ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
1.5       raeburn  1709:                 }
1.43      albertel 1710:                 $r->print('</nobr></td></tr>');
1.5       raeburn  1711:             }
                   1712:         }
1.3       raeburn  1713:         my %Sortby = ();
                   1714:         foreach my $user (sort(keys(%members))) {
                   1715:             if ($env{'form.sortby'} eq 'fullname') {
                   1716:                 push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);
                   1717:             } elsif ($env{'form.sortby'} eq 'username') {
                   1718:                 push(@{$Sortby{$members{$user}[$$idx{uname}]}},$user);
                   1719:             } elsif ($env{'form.sortby'} eq 'domain') {
                   1720:                 push(@{$Sortby{$members{$user}[$$idx{udom}]}},$user);
                   1721:             } elsif ($env{'form.sortby'} eq 'id') {
                   1722:                 push(@{$Sortby{$members{$user}[$$idx{id}]}},$user);
1.31      albertel 1723:             } elsif ($env{'form.sortby'} eq 'section') {
                   1724:                 push(@{$Sortby{$members{$user}[$$idx{section}]}},$user);
1.3       raeburn  1725:             } else {
                   1726:                 push(@{$Sortby{$members{$user}[$$idx{fullname}]}},$user);
                   1727:             }
                   1728:         }
                   1729:         foreach my $key (sort(keys(%Sortby))) {
                   1730:             foreach my $user (@{$Sortby{$key}}) {
                   1731:                 my $id = $members{$user}[$$idx{id}];
                   1732:                 my $fullname = $members{$user}[$$idx{fullname}];
                   1733:                 my $udom = $members{$user}[$$idx{udom}];
                   1734:                 my $uname = $members{$user}[$$idx{uname}];
1.31      albertel 1735:                 my $section = $members{$user}[$$idx{section}];
1.43      albertel 1736:                 $r->print(&Apache::loncommon::start_data_table_row('LC_data_table_dense').
                   1737: 			  '<td align="right"><input type="checkbox" name="member" value="'.$user.'" /></td>'.
                   1738: 			  '<td>'.$fullname.'</td>'.
                   1739: 			  '<td>'.$uname.'</td>'.
                   1740: 			  '<td>'.$udom.'</td>'.
                   1741: 			  '<td>'.$id.'</td>'.
                   1742: 			  '<td>'.$section.'</td>');
1.5       raeburn  1743:                 if (@{$available} > 0) {
1.43      albertel 1744:                     $r->print('<td align="center"><nobr>'.
1.5       raeburn  1745:                               '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
                   1746:                     foreach my $tool (@{$available}) {
                   1747:                         if ($granularity eq 'Yes') {
1.3       raeburn  1748:                             $r->print('<input type="checkbox" name="user_'.
                   1749:                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                   1750:                         } else {
                   1751:                             $r->print('<input type="hidden" name="user_'.
                   1752:                           $tool.'" value="'.$user.'" />'.$tool.'&nbsp;&nbsp;&nbsp;');
                   1753:                         }
                   1754:                     }
1.43      albertel 1755:                     $r->print('</nobr></td>');
1.3       raeburn  1756:                 }
1.43      albertel 1757:                 $r->print(&Apache::loncommon::end_data_table_row()."\n");
1.3       raeburn  1758:             }
                   1759:         }
1.43      albertel 1760:         $r->print(&Apache::loncommon::end_data_table());
1.5       raeburn  1761:     } else {
                   1762:         if ($totalusers > 0) {
                   1763:             $r->print($lt{'nnew'}.'<br /><br />'.$lt{'yoma'});
                   1764:         } else { 
                   1765:             $r->print($lt{'nome'});
                   1766:         }
                   1767:     }
                   1768:     return $newusers;
                   1769: }
                   1770: 
                   1771: sub privilege_specificity {
                   1772:     my ($r,$tabcol,$rowColor1,$rowColor2,$action,$img,$tools,$stored,
1.29      raeburn  1773:         $toolprivs,$fixedprivs,$available,$formname,$gpterm,$ucgpterm) = @_;
1.5       raeburn  1774:     my %lt = &Apache::lonlocal::texthash (
                   1775:       'uprv' => 'User privileges',
                   1776:       'frty' => 'For each type of functionality you have chosen to include, '.
                   1777:                 'there is a set of standard privileges which apply to all '.
                   1778:                 'of those for whom the functionality is enabled.',
                   1779:       'thar' => 'There are also additional privileges which can be set for '.
                   1780:                 'some, or all, members. Please choose one of the following:',
                   1781:       'fort' => 'For the types of functionality you have chosen to include '.
                   1782:                 'there are no additional privileges which can be set for some '.
                   1783:                 'or all members.',
                   1784:       'eaty' => 'Each of the types of functionality includes standard '.
                   1785:                 'privileges which apply to members with access to that '.
                   1786:                 'functionality, and may also include additional privileges '.
                   1787:                 'which can be set for specific members.',
1.29      raeburn  1788:       'cutg' => "Currently the $gpterm is configured ",
                   1789:       'sdif' => "so different $gpterm members can receive different privileges.",
                   1790:       'sall' => "so all $gpterm members will receive the same privileges.",
                   1791:       'algm' => "All $gpterm members will receive the same privileges.",
                   1792:       'smgp' => "Some $gpterm members will receive different privileges from ".
                   1793:                 "others.",
                   1794:       'thwi' => "These will be the privileges all $gpterm members receive, ". 
                   1795:                 "if you selected the first option above.",
                   1796:       'thes' => "These will be the privileges given to members assigned ".   
                   1797:                 "in the future, including via automatic $gpterm assignment ".
                   1798:                 "for specific sections/roles ",
                   1799:       'asyo' => "As you have chosen not to include any functionality in the ".
                   1800:                 "$gpterm, no default user privileges settings need to be set.",
1.5       raeburn  1801:       'plin' => 'Please indicate which <b>optional</b> privileges members '.
                   1802:                 'will receive by default.',
                   1803:       'oppr' => 'Optional privileges',
                   1804:       'defp' => 'The default privileges new members will receive are:', 
                   1805:     );
                   1806:     my $totaloptionalprivs = 0;
                   1807:     foreach my $tool (@{$tools}) {
                   1808:         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   1809:             if (!exists($$fixedprivs{$tool}{$priv})) {
                   1810:                 $totaloptionalprivs ++;
                   1811:             }
                   1812:         }
                   1813:     }
1.40      albertel 1814:     &topic_bar($r,$img,$lt{'uprv'});
1.5       raeburn  1815:     if ((($action eq 'create') && (@{$available} > 0)) || 
                   1816:         (($action eq 'modify') && ($formname eq 'change_settings'))) {  
                   1817:         my %specific = (
                   1818:                       'No'  => 'checked="checked"',
                   1819:                       'Yes' => '',
                   1820:                   );
                   1821:         if ($action eq 'create') {
                   1822:             $r->print($lt{'frty'}.'<br />');
                   1823:             if ($totaloptionalprivs) {
                   1824:                 $r->print($lt{'thar'});
                   1825:             } else {
                   1826:                 $r->print($lt{'fort'});
                   1827:             }
                   1828:         } else {
                   1829:             $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
                   1830:             if ($$stored{'specificity'} eq 'Yes') {
                   1831:                 $r->print($lt{'sdif'});
                   1832:                 $specific{'Yes'} = $specific{'No'};
                   1833:                 $specific{'No'} = '';
                   1834:             } else {
                   1835:                 $r->print($lt{'sall'});
                   1836:             }
                   1837:         }
                   1838:         if ($totaloptionalprivs) {
                   1839:             $r->print('
1.40      albertel 1840: <br /><br />
                   1841: <label><nobr><input type="radio" name="specificity" value="No" '.$specific{'No'}.' />&nbsp;'.$lt{'algm'}.'</nobr></label><br />
                   1842: <label><nobr><input type="radio" name="specificity" value="Yes" '.$specific{'Yes'}.' />&nbsp;'.$lt{'smgp'}.'</nobr></label>');
1.5       raeburn  1843:         } else {
                   1844:             $r->print('<input type="hidden" name="specificity" value="No" />');
                   1845:         }
                   1846:         if ($totaloptionalprivs) {
1.40      albertel 1847:             $r->print($lt{'plin'});
1.5       raeburn  1848:             if ($action eq 'create') {
                   1849:                 $r->print(' '.$lt{'thwi'});
                   1850:             }
                   1851:             $r->print('<br />'.$lt{'thes'});
                   1852:             if ($action eq 'create') {
                   1853:                 $r->print('('.&mt('if enabled on the next page').').');
                   1854:             } else {
                   1855:                 $r->print('('.&mt('if enabled below').').');
                   1856:             }
                   1857:             $r->print('<br /><br />
1.40      albertel 1858:   <table><tr>');
1.5       raeburn  1859:         &check_uncheck_buttons($r,$formname,'defpriv',$lt{'oppr'});
                   1860:         $r->print('
                   1861:     </tr>
                   1862:    </table>
1.3       raeburn  1863:    <br />
                   1864: ');
1.5       raeburn  1865:         } else {
1.40      albertel 1866:             $r->print($lt{'algm'}.'<br /><br />');
1.3       raeburn  1867:         }
1.42      albertel 1868:         &default_privileges($r,$action,$tools,$toolprivs,$fixedprivs,
                   1869: 			    $available);
1.3       raeburn  1870:     } else {
1.5       raeburn  1871:         if ($action eq 'create') {
                   1872:             $r->print($lt{'asyo'});
                   1873:         } elsif ($action eq 'modify' && $formname eq 'pick_members') {
                   1874:             my @defprivs;
                   1875:             if (ref($$stored{'defpriv'}) eq 'ARRAY') {
                   1876:                 @defprivs = @{$$stored{'defpriv'}};
                   1877:             }
                   1878:             $r->print($lt{'eaty'}.'&nbsp;'.$lt{cutg});
                   1879:             if ($$stored{'specificity'} eq 'Yes') {
                   1880:                 $r->print($lt{'sdif'});
                   1881:             } else {
                   1882:                 $r->print($lt{'sall'});
                   1883:             }
                   1884:             $r->print(' '.$lt{'defp'}.'<br /><br />');
1.45    ! albertel 1885:             &display_defprivs($r,$tools,$toolprivs,\@defprivs);
1.5       raeburn  1886:         }
1.3       raeburn  1887:     }
                   1888:     return;
                   1889: }
                   1890: 
1.5       raeburn  1891: sub default_privileges {
1.42      albertel 1892:     my ($r,$action,$tools,$toolprivs,$fixedprivs,$available) = @_;
1.5       raeburn  1893:     my %lt = &Apache::lonlocal::texthash(
                   1894:                                 'addp' => 'Additional privileges',
                   1895:                                 'fixp' => 'Fixed privileges',
                   1896:                                 'oppr' => 'Optional privileges',
                   1897:                                 'func' => 'Function',
                   1898:     );
1.42      albertel 1899:     $r->print(&Apache::lonhtmlcommon::start_pick_box('LC_group_priv_box').
                   1900: 	      &Apache::lonhtmlcommon::row_title($lt{'func'},undef,
                   1901: 						'LC_groups_functionality'));
                   1902:     $r->print(join('</td><td class="LC_groups_functionality">',@{$tools}));
                   1903:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   1904:     my $fixed = '';
                   1905:     my $dynamic = '';
1.3       raeburn  1906:     foreach my $tool (@{$tools}) {
1.5       raeburn  1907:         my $privcount = 0;
1.42      albertel 1908: 	if ($dynamic ne '') {
                   1909: 	    $dynamic .= '</td><td class="LC_groups_optional">';
                   1910: 	}
                   1911: 	$dynamic .= '<table class="LC_group_priv"><tr>';
1.5       raeburn  1912:         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   1913:             if (exists($$fixedprivs{$tool}{$priv})) {
1.42      albertel 1914: 		if ($fixed ne '') {
                   1915: 		    $fixed .= '</td><td class="LC_groups_fixed">';
                   1916: 		}
1.5       raeburn  1917:                 $fixed .= '<input type="hidden" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
                   1918:                 if ($action eq 'modify') {
1.42      albertel 1919:                     if (grep(/^$tool$/,@{$available})) {
1.5       raeburn  1920:                         $fixed .= '<small>'.&mt('(on)').'<small>&nbsp;';
                   1921:                     } else {
                   1922:                         $fixed .= '<small>'.&mt('(off)').'<small>&nbsp;';
1.3       raeburn  1923:                     }
                   1924:                 }
1.5       raeburn  1925:             } else {
1.42      albertel 1926:                 $privcount++;
1.5       raeburn  1927:                 if ($privcount == 3) {
                   1928:                     $dynamic .= '</tr>
1.42      albertel 1929:                                  <tr>'."\n";
1.5       raeburn  1930:                 }
1.7       raeburn  1931:                 $dynamic .= '<td><label><input type="checkbox" name="defpriv" value="'.$priv.'" />'.$$toolprivs{$tool}{$priv}.'</label></td>'."\n";
1.3       raeburn  1932:             }
                   1933:         }
1.42      albertel 1934:         if ($privcount == 0) {
                   1935:             $dynamic .= '<td>None</td>'."\n";
1.5       raeburn  1936:         }
                   1937:         if ($privcount < 3) {
1.42      albertel 1938:             $dynamic .= '</td>
                   1939:                          <td>&nbsp;</td>'."\n";
1.5       raeburn  1940:         } elsif ($privcount%2) {
                   1941:             $dynamic = '<td>&nbsp;</td>'."\n";
                   1942:         }
1.42      albertel 1943: 	$dynamic .= '</tr></table>';
1.3       raeburn  1944:     }
1.42      albertel 1945:     $r->print(&Apache::lonhtmlcommon::row_title($lt{'fixp'},undef,
                   1946: 						'LC_groups_fixed').
                   1947: 	      $fixed.
                   1948: 	      &Apache::lonhtmlcommon::row_closure(1));
                   1949:     $r->print(&Apache::lonhtmlcommon::row_title($lt{'oppr'},undef,
                   1950: 						'LC_groups_optional').
                   1951: 	      $dynamic.
                   1952: 	      &Apache::lonhtmlcommon::end_pick_box());
1.5       raeburn  1953:     $r->print('<br />');
                   1954:     return;
1.42      albertel 1955: 
1.5       raeburn  1956: }
                   1957: 
                   1958: sub display_defprivs {
1.45    ! albertel 1959:     my ($r,$tools,$toolprivs,$defprivs) = @_;
        !          1960:     my $function = &Apache::loncommon::get_users_function();
        !          1961:     my $tabcol = &Apache::loncommon::designparm($function.'.tabbg');
        !          1962:     my $rowColor1 = "#dddddd";
        !          1963:     my $rowColor2 = "#eeeeee";
1.5       raeburn  1964:     my %lt = &Apache::lonlocal::texthash(
                   1965:                                 'priv' => 'Privileges',
                   1966:                                 'func' => 'Function',
                   1967:     );
                   1968:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
                   1969:     $r->print('<tr>');
                   1970:     my $numrows = 0;
                   1971:     my %currprivs;
                   1972:     foreach my $tool (@{$tools}) {
                   1973:         @{$currprivs{$tool}} = ();
                   1974:         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   1975:             if (ref($defprivs) eq 'ARRAY') {
1.45    ! albertel 1976:                 if (grep(/^\Q$priv\E$/,@{$defprivs})) {
1.5       raeburn  1977:                     push(@{$currprivs{$tool}},$priv);
                   1978:                 }
1.3       raeburn  1979:             }
                   1980:         }
1.5       raeburn  1981:         my $rowcount = int(@{$currprivs{$tool}}/3);
                   1982:         if (@{$currprivs{$tool}}%3 > 0) {
                   1983:             $rowcount ++;
                   1984:         }
                   1985:         if ($rowcount > $numrows) {
                   1986:             $numrows = $rowcount;
                   1987:         }
                   1988:     }
                   1989:     my @rowCols = ($rowColor1,$rowColor2);
                   1990:     foreach my $tool (@{$tools}) {
                   1991:         $r->print('<td align="center" valign="top">
                   1992:                     <table cellspacing="0" cellpadding="5">
                   1993:                      <tr bgcolor="#cccccc">
                   1994:                       <td colspan="3" align="center"><b>'.$tool.'</b></td>
                   1995:                      </tr>
                   1996:         ');
                   1997:         my $rownum = 1;
                   1998:         my $privcount = 0;
                   1999:         $r->print('<tr bgcolor="'.$rowColor1.'">');
                   2000:         foreach my $priv (@{$currprivs{$tool}}) {
                   2001:             $privcount ++;
                   2002:             if ($privcount%4 == 0) {
                   2003:                 $rownum ++;
                   2004:                 my $bgcol = $rownum%2; 
                   2005:                 $r->print('</tr>
                   2006:                              <tr bgcolor="'.$rowCols[$bgcol].'">'."\n");
                   2007:             }
                   2008:             $r->print('<td>'.$$toolprivs{$tool}{$priv}.'</td>'."\n");
                   2009:         }
                   2010:         if ($privcount%3 > 0) {
                   2011:             my $emptycells = 3-($privcount%3);
                   2012:             while($emptycells > 0) {
                   2013:                 $r->print('<td>&nbsp;</td>'."\n");
                   2014:                 $emptycells --;
                   2015:             }
                   2016:         }
                   2017:         while ($rownum < $numrows) {
                   2018:             $rownum ++;
                   2019:             my $bgcol = $rownum%2;
                   2020:             $r->print('<tr bgcolor="'.$rowCols[$bgcol].'"><td colspan="3">&nbsp;</td></tr>');
1.3       raeburn  2021:         }
1.5       raeburn  2022:         $r->print('</table>'."\n".'</td>');
                   2023:     }
                   2024:     $r->print('</tr>'."\n");
                   2025:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   2026:     $r->print('<br />');
                   2027:     return;
1.3       raeburn  2028: }
1.5       raeburn  2029: 
                   2030: 
                   2031: sub change_members_form {
                   2032:     my ($r,$cdom,$cnum,$tabcol,$action,$formname,$page,$groupname,$description,
                   2033:         $startdate,$enddate,$tools,$fixedprivs,$functions,$users,$userdata,
1.29      raeburn  2034:         $granularity,$quota,$specificity,$idx,$states,$navbuttons,$rowColor1,
                   2035:         $rowColor2,$gpterm,$ucgpterm) = @_;
1.5       raeburn  2036:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  2037:                                          grse => "$ucgpterm settings",
                   2038:                                          mogm => "Modify $gpterm membership",
1.5       raeburn  2039:                                         );
                   2040:     my @regexps = ('user_','userpriv_');
                   2041:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.6       raeburn  2042:                          ['origin','action','state','page','expire','deletion',
1.7       raeburn  2043:                           'reenable','activate','changepriv','sortby',
                   2044:                           'togglefunc'],\@regexps));
1.5       raeburn  2045:     my $rowimg = 1;
                   2046:     my @available = ();
                   2047:     my @unavailable = ();
                   2048:     &check_tools($functions,$tools,\@available,\@unavailable);
                   2049:     my $nexttext = $$navbuttons{'gtns'};
                   2050:     my $prevtext = $$navbuttons{'gtpp'};
                   2051:     $r->print('
1.3       raeburn  2052: <br />
1.5       raeburn  2053: ');
1.40      albertel 2054:     &topic_bar($r,1,$lt{'grse'});
                   2055:     &print_current_settings($r,$action,$functions,$startdate,$enddate,
                   2056: 			    $groupname,$description,$granularity,$quota,
                   2057: 			    \@available,\@unavailable,$gpterm,$ucgpterm);
                   2058:     &topic_bar($r,2,$lt{'mogm'});
1.5       raeburn  2059:     &current_membership($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,
                   2060:                         $rowColor2,$groupname,\@available,\@unavailable,
                   2061:                         $fixedprivs,$granularity,$specificity);
                   2062:     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                   2063:                         $$states{$action}[$page+1],$nexttext);
                   2064:     return;
                   2065: }
                   2066: 
                   2067: sub current_membership {
                   2068:     my ($r,$cdom,$cnum,$formname,$tabcol,$rowColor1,$rowColor2,$groupname,
                   2069:         $available,$unavailable,$fixedprivs,$granularity,$specificity) = @_;
                   2070:     my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                   2071:                                                                    $groupname);
                   2072:     my %lt = &Apache::lonlocal::texthash(
1.6       raeburn  2073:                                           'actn' => 'Action?',
                   2074:                                           'name' => 'Name',
                   2075:                                           'usnm' => 'Username',
                   2076:                                           'doma' => 'Domain',
                   2077:                                           'stda' => 'Start Date',
                   2078:                                           'enda' => 'End Date',
1.5       raeburn  2079:                                           'expi' => 'Expire',
                   2080:                                           'reen' => 'Re-enable',
                   2081:                                           'acti' => 'Activate',
                   2082:                                           'dele' => 'Delete',
                   2083:                                           'curf' => 'Current Functionality',
                   2084:                                           'chpr' => 'Change Privileges' 
                   2085:                                         );
1.36      raeburn  2086:     my ($current,$hastools,$addtools,$num_reenable,$num_activate,$num_expire) =
                   2087:         &Apache::longroup::group_memberlist($cdom,$cnum,$groupname,$fixedprivs,
                   2088:                                             $available);
                   2089:     if (keys(%{$current}) > 0) {
                   2090:         $r->print('
1.5       raeburn  2091:  <tr>
                   2092:   <td>&nbsp;</td>
                   2093:   <td colspan="2">
                   2094:    <table>
                   2095:     <tr>');
1.36      raeburn  2096:         if ($num_expire) {
                   2097:             &check_uncheck_buttons($r,$formname,'expire',$lt{'expi'});
                   2098:         }
                   2099:         if ($num_reenable) {
                   2100:             &check_uncheck_buttons($r,$formname,'reenable',$lt{'reen'});
                   2101:         }
                   2102:         if ($num_activate) {
                   2103:             &check_uncheck_buttons($r,$formname,'activate',$lt{'acti'});
                   2104:         }
                   2105:         &check_uncheck_buttons($r,$formname,'deletion',$lt{'dele'});
                   2106:         if (@{$available} > 0) {
                   2107:             if ($specificity eq 'Yes') {
                   2108:                 &check_uncheck_buttons($r,$formname,'changepriv',$lt{'chpr'});
1.5       raeburn  2109:             }
1.36      raeburn  2110:             if ($granularity eq 'Yes') {
                   2111:                 $r->print(&check_uncheck_tools($r,$available));
                   2112:                 $r->print('
1.5       raeburn  2113:      <td>
                   2114:       <nobr>
                   2115:        <fieldset><legend><b>'.$lt{'curf'}.'</b></legend>
                   2116:        <input type="button" value="check all"
                   2117:        onclick="javascript:checkAllTools(document.'.$formname.')" />
                   2118:        &nbsp;&nbsp;
                   2119:        <input type="button" value="uncheck all"
                   2120:         onclick="javascript:uncheckAllTools(document.'.$formname.')" />
                   2121:       </fieldset>
                   2122:      </nobr>
                   2123:     </td>
                   2124: ');
1.3       raeburn  2125:             }
1.36      raeburn  2126:         }
                   2127:         $r->print(<<"END");
1.5       raeburn  2128:    </tr>
                   2129:   </table>
                   2130:   </td>
                   2131:   <td width="100%">&nbsp;</td>
                   2132:  </tr>
1.3       raeburn  2133:  <tr>
                   2134:   <td colspan="4">&nbsp;</td>
                   2135:  </tr>
                   2136:  <tr>
                   2137:   <td>&nbsp;</td>
                   2138:   <td colspan="3">
1.5       raeburn  2139: END
1.36      raeburn  2140:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
                   2141:         $r->print(<<"END");
1.5       raeburn  2142:    <table border="0" cellpadding="4" cellspacing="1">
                   2143:     <tr bgcolor="$tabcol" align="center">
1.6       raeburn  2144:      <td><b>$lt{'actn'}</b></td>
                   2145:      <td><b><a href="javascript:changeSort('fullname')">$lt{'name'}</a></b></td>
                   2146:      <td><b><a href="javascript:changeSort('username')">$lt{'usnm'}</a></b>
1.5       raeburn  2147:      </td>
1.6       raeburn  2148:      <td><b><a href="javascript:changeSort('domain')">$lt{'doma'}</a></b></td>
1.5       raeburn  2149:      <td><b><a href="javascript:changeSort('id')">ID</a></b></td>
1.6       raeburn  2150:      <td><b><a href="javascript:changeSort('start')">$lt{'stda'}</a></b></td>
                   2151:      <td><b><a href="javascript:changeSort('end')">$lt{'enda'}</a></b></td>
1.5       raeburn  2152: END
1.36      raeburn  2153:         my $colspan = 0;
                   2154:         if ($hastools) {
                   2155:             $r->print('<td><b>'.$lt{'curf'}.'</b></td>');
                   2156:             $colspan ++;  
                   2157:         }
                   2158:         if ($addtools) {
                   2159:             $r->print('<td><b>Additional Functionality</b></td>');
                   2160:             $colspan ++;
                   2161:         }
                   2162:         $r->print('</tr>');
                   2163:         if ($colspan) {
                   2164:             if ($granularity eq 'Yes') {
                   2165:                 $r->print('<tr bgcolor="#cccccc">
1.6       raeburn  2166:  <td colspan="7">&nbsp;</td>
                   2167:  <td colspan="'.$colspan.'" align="center"><small><nobr><b>'.&mt('All:').
                   2168:   '</b>&nbsp;');
1.36      raeburn  2169:                 foreach my $tool (@{$available}) {
                   2170:                     $r->print('<label><input type="checkbox" name="togglefunc"'.
1.7       raeburn  2171:    ' onclick="javascript:toggleTools(document.'.$formname.'.user_'.$tool.',this);"'.
                   2172:    ' value="'.$tool.'">'.'<b>'.$tool.'</b></label>&nbsp;&nbsp;&nbsp;');
1.6       raeburn  2173:                 }
1.36      raeburn  2174:                 $r->print('</nobr></small></td></tr>');
1.6       raeburn  2175:             }
1.36      raeburn  2176:         }
                   2177:         my %Sortby = ();
                   2178:         foreach my $user (sort(keys(%{$current}))) {
                   2179:             if ($env{'form.sortby'} eq 'fullname') {
                   2180:                 push(@{$Sortby{$$current{$user}{fullname}}},$user);
                   2181:             } elsif ($env{'form.sortby'} eq 'username') {
                   2182:                 push(@{$Sortby{$$current{$user}{uname}}},$user);
                   2183:             } elsif ($env{'form.sortby'} eq 'domain') {
                   2184:                 push(@{$Sortby{$$current{$user}{udom}}},$user);
                   2185:             } elsif ($env{'form.sortby'} eq 'id') {
                   2186:                 push(@{$Sortby{$$current{$user}{id}}},$user);
                   2187:             } else {
                   2188:                 push(@{$Sortby{$$current{$user}{fullname}}},$user);
                   2189:             }
                   2190:         }
                   2191:         my $rowNum = 0;
                   2192:         my $rowColor;
                   2193:         foreach my $key (sort(keys(%Sortby))) {
                   2194:             foreach my $user (@{$Sortby{$key}}) {
                   2195:                 if ($rowNum %2 == 1) {
                   2196:                     $rowColor = $rowColor1;
1.5       raeburn  2197:                 } else {
1.36      raeburn  2198:                     $rowColor = $rowColor2;
1.5       raeburn  2199:                 }
1.36      raeburn  2200:                 my $id = $$current{$user}{id};
                   2201:                 my $fullname = $$current{$user}{fullname};
                   2202:                 my $udom = $$current{$user}{udom};
                   2203:                 my $uname = $$current{$user}{uname};
                   2204:                 my $start = $$current{$user}{start};
                   2205:                 my $end = $$current{$user}{end};
                   2206:                 $r->print('<tr bgcolor="'.$rowColor.'">
                   2207:                             <td><small>');
                   2208:                 if ($$current{$user}{changestate} eq 'reenable') {
                   2209:                     $r->print('<nobr><label>'. 
1.5       raeburn  2210:    '<input type="checkbox" name="reenable" value="'.$user.'" />'.
1.7       raeburn  2211:    $lt{'reen'}.'</label></nobr><br />');
1.36      raeburn  2212:                 } elsif ($$current{$user}{changestate} eq 'expire') {
                   2213:                     $r->print('<nobr><label>'.
1.5       raeburn  2214:    '<input type="checkbox" name="expire" value="'.$user.'" />'.
1.7       raeburn  2215:    $lt{'expi'}.'</label></nobr><br />');
1.36      raeburn  2216:                 } elsif ($$current{$user}{changestate} eq 'activate') {
                   2217:                     $r->print('<nobr><label>'.
1.5       raeburn  2218:    '<input type="checkbox" name="activate" value="'.$user.'" />'.
1.7       raeburn  2219:    $lt{'acti'}.'</label></nobr><br />');
1.36      raeburn  2220:                 }
                   2221:                 $r->print('<nobr><label>'.
1.6       raeburn  2222:    '<input type="checkbox" name="deletion" value="'.$user.'" />'.
1.7       raeburn  2223:    $lt{'dele'}.'</label></nobr>');
1.36      raeburn  2224:                 if ($specificity eq 'Yes') {
                   2225:                     $r->print('<br /><nobr><label>'.
1.5       raeburn  2226:    '<input type="checkbox" name="changepriv" value="'.$user.'" />'.$lt{'chpr'}.
1.7       raeburn  2227:    '</label></nobr>');
1.36      raeburn  2228:                 }
                   2229:                 $r->print('
1.5       raeburn  2230:    </td>
                   2231:    <td><small>'.
                   2232:     $fullname.'</small></td><td><small>'.$uname.'</small></td><td><small>'.
                   2233:     $udom.'</small></td><td><small>'.$id.'</small></td><td><small>'.$start.
                   2234:     '</small></td><td><small>'.$end.'</small></td>');
1.36      raeburn  2235:                 if ($hastools) {
                   2236:                     $r->print('<td align="left"><small><nobr>'.
1.6       raeburn  2237:                                   '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;');
1.36      raeburn  2238:                     foreach my $tool (@{$$current{$user}{currtools}}) {
                   2239:                         if ($granularity eq 'Yes') {
                   2240:                             $r->print('<label><input type="checkbox" '. 
1.7       raeburn  2241:                                        'checked="checked" '. 
                   2242:                                        'name="user_'.$tool.'" value="'.
                   2243:                                        $user.'" />'.$tool.'</label>');
1.36      raeburn  2244:                          } else {
                   2245:                              $r->print('<input type="hidden" '.
1.7       raeburn  2246:                                        'checked="checked" '.
                   2247:                                        'name="user_'.$tool.'" value="'.
                   2248:                                        $user.'" />'.$tool);
1.36      raeburn  2249:                          }
                   2250:                          $r->print('&nbsp;&nbsp;&nbsp;');
1.5       raeburn  2251:                     }
1.36      raeburn  2252:                     $r->print('</nobr></small></td>');
                   2253:                 }
                   2254:                 if ($addtools) {
                   2255:                     $r->print('<td align="left"><small>');
                   2256:                     if ($granularity eq 'Yes') {
                   2257:                         foreach my $tool (@{$$current{$user}{newtools}}) {
                   2258:                             $r->print('<nobr><label><input type="checkbox"
1.5       raeburn  2259:                                           name="user_'.$tool.'" value="'.
                   2260:                                           $user.'" />'.$tool.
1.7       raeburn  2261:                                           '</label></nobr>&nbsp;&nbsp;&nbsp;');
1.36      raeburn  2262:                         }
                   2263:                     } else {
                   2264:                         foreach my $tool (@{$$current{$user}{newtools}}) {
                   2265:                             $r->print('<nobr><input type="hidden" 
1.5       raeburn  2266:                                           name="user_'. $tool.'" value="'.
                   2267:                                           $user.'" />'.$tool.
                   2268:                                           '</nobr>&nbsp;&nbsp;&nbsp;');
                   2269:                         }
                   2270:                     }
1.36      raeburn  2271:                     $r->print('</small></td>');
1.5       raeburn  2272:                 }
1.36      raeburn  2273:                 $r->print('</tr>'."\n");
                   2274:                 $rowNum ++;
1.5       raeburn  2275:             }
1.36      raeburn  2276:         }
                   2277:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   2278:         $r->print('
1.3       raeburn  2279:   </td>
1.5       raeburn  2280:  </tr>');
                   2281:     }
                   2282:     return;
                   2283: }
                   2284: 
                   2285: sub check_uncheck_buttons {
                   2286:     my ($r,$formname,$field,$title,$colspan) = @_;
                   2287:     $r->print('
                   2288:      <td '.$colspan.'>
                   2289:       <nobr>
                   2290:        <fieldset>
                   2291:        <legend><b>'.$title.'</b></legend>
                   2292:        <input type="button" value="check all"
                   2293:        onclick="javascript:checkAll(document.'.$formname.'.'.$field.')" />
                   2294:        &nbsp;&nbsp;
                   2295:        <input type="button" value="uncheck all"
                   2296:        onclick="javascript:uncheckAll(document.'.$formname.'.'.$field.')" />
                   2297:        </fieldset>
                   2298:       </nobr>
                   2299:      </td>
                   2300: ');
                   2301: }
                   2302: 
                   2303: 
                   2304: sub change_privs_form {
1.45    ! albertel 2305:     my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
        !          2306: 	$tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,
        !          2307: 	$memchg,$idx,$states,$stored,$sectioncount,$navbuttons,$gpterm,
        !          2308: 	$ucgpterm) = @_;
1.5       raeburn  2309:     my @regexps = ('userpriv_');
                   2310:     my $nexttext;
1.6       raeburn  2311:     my %lt = &Apache::lonlocal::texthash(
                   2312:                'tode' => 'To be deleted',
                   2313:                'toex' => 'To be expired',
1.29      raeburn  2314:                'nome' => "No members to be deleted or expired from the $gpterm.",
1.6       raeburn  2315:     );
1.5       raeburn  2316:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.6       raeburn  2317:          ['origin','action','state','page','sortby'],\@regexps));
                   2318:     if ($env{'form.branch'} eq 'adds') {
                   2319:         $nexttext = $$navbuttons{'adme'};
                   2320:     } else {
                   2321:         $nexttext = $$navbuttons{'mose'};
                   2322:     }
1.40      albertel 2323:     &topic_bar($r,3,&mt('Members to delete or expire'));
1.6       raeburn  2324:     my $exp_or_del = 0;
                   2325:     if (ref($$memchg{'deletion'}) eq 'ARRAY') {
                   2326:         if (@{$$memchg{'deletion'}} > 0) {
                   2327:             $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'tode'}.':</b><br /><ul>');
                   2328:             foreach my $user (@{$$memchg{'deletion'}}) {
                   2329:                 $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                   2330:                           '&nbsp;('.$user.')</li>');
                   2331:             }
1.45    ! albertel 2332:             $r->print('</ul>');
1.6       raeburn  2333:             $exp_or_del += @{$$memchg{'deletion'}};
                   2334:         }
                   2335:     }
                   2336:     if (ref($$memchg{'expire'}) eq 'ARRAY') {
                   2337:         if (@{$$memchg{'expire'}} > 0) {
                   2338:             $r->print('<tr><td>&nbsp;</td><td colspan="3"><b>'.$lt{'toex'}.':</b><br /><ul>');
                   2339:             foreach my $user (@{$$memchg{'expire'}}) {
                   2340:                 $r->print('<li>'.$$userdata{$user}[$$idx{fullname}].
                   2341:                           '&nbsp;('.$user.')</li>');
                   2342:             }
1.45    ! albertel 2343:             $r->print('</ul>');
1.6       raeburn  2344:             $exp_or_del += @{$$memchg{'expire'}};
                   2345:         }
                   2346:     }
                   2347:     if (!$exp_or_del) {
1.45    ! albertel 2348:         $r->print($lt{'nome'}.'<br />');
1.6       raeburn  2349:     }
1.5       raeburn  2350:     
1.40      albertel 2351:     &topic_bar($r,4,&mt('[_1] member privileges',$ucgpterm));
1.6       raeburn  2352: 
1.45    ! albertel 2353:     my $numchgs = &member_privileges_form($r,$action,$formname,$tools,
1.6       raeburn  2354:                                           $toolprivs,$fixedprivs,$userdata,
                   2355:                                           $usertools,$idx,$memchg,$states,
1.45    ! albertel 2356:                                           $stored,$gpterm);
1.5       raeburn  2357:     my $prevtext = $$navbuttons{'gtps'};
1.6       raeburn  2358:     if ($numchgs || $exp_or_del) {
                   2359:         &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                   2360:                             $$states{$action}[$page+1],$nexttext);
                   2361:     } else {
                   2362:         &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext);
                   2363:     }
1.5       raeburn  2364:     return;
                   2365: }
                   2366: 
                   2367: sub add_members_form {
                   2368:     my ($r,$tabcol,$action,$formname,$page,$startdate,$enddate,$groupname,
1.29      raeburn  2369:         $description,$granularity,$quota,$sectioncount,$tools,$functions,
                   2370:         $stored,$states,$navbuttons,$rowColor1,$rowColor2,$gpterm,$ucgpterm)=@_; 
1.40      albertel 2371:     $r->print(' <br />');
1.5       raeburn  2372:     my @available = ();
                   2373:     my @unavailable = ();
                   2374:     &check_tools($functions,$tools,\@available,\@unavailable);
1.40      albertel 2375:     &print_current_settings($r,$action,$functions,$startdate,$enddate,
                   2376: 			    $groupname,$description,$granularity,$quota,
                   2377: 			    \@available,\@unavailable,$gpterm,$ucgpterm);
                   2378:     &membership_options($r,$action,$formname,$sectioncount,1,$gpterm,$ucgpterm);
1.5       raeburn  2379:     my $nexttext = $$navbuttons{'gtns'};
                   2380:     my $prevtext = $$navbuttons{'gtpp'};
                   2381:     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                   2382:                         $$states{$action}[$page+1],$nexttext);
                   2383:     return;
                   2384: }
                   2385: 
                   2386: sub choose_privs_form {
1.45    ! albertel 2387:     my ($r,$cdom,$cnum,$action,$formname,$page,$startdate,$enddate,
        !          2388: 	$tools,$functions,$toolprivs,$fixedprivs,$userdata,$usertools,$idx,
        !          2389: 	$states,$stored,$sectioncount,$navbuttons,$gpterm,$ucgpterm,
        !          2390: 	$crstype) = @_;
1.5       raeburn  2391: 
                   2392:     my @regexps = ('userpriv_');
                   2393:     my $nexttext;
                   2394:     
                   2395:     if ($action eq 'create') {
                   2396:         push(@regexps,'sec_');
                   2397:         $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.6       raeburn  2398:          ['origin','action','state','page','sortby','autoadd','autodrop'],
1.5       raeburn  2399:          \@regexps));
                   2400:         $nexttext = $$navbuttons{'crgr'};
                   2401:     } else {
                   2402:         $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.6       raeburn  2403:          ['origin','action','state','page','sortby'],\@regexps));
1.5       raeburn  2404:         $nexttext = $$navbuttons{'adme'};
                   2405:     }
                   2406: 
1.40      albertel 2407:     &topic_bar($r,6,&mt('[_1] member privileges',$ucgpterm));
1.5       raeburn  2408: 
1.45    ! albertel 2409:     &member_privileges_form($r,$action,$formname,$tools,$toolprivs,
1.5       raeburn  2410:                             $fixedprivs,$userdata,$usertools,$idx,undef,
1.45    ! albertel 2411:                             $states,$stored,$gpterm);
1.5       raeburn  2412: 
                   2413:     if ($action eq 'create') {
                   2414:         if (keys(%{$sectioncount}) > 0) {
                   2415:             my $img1 = 7;
                   2416:             my $img2 = 8;
1.44      albertel 2417:             &mapping_options($r,$action,$formname,$page,$sectioncount,
1.5       raeburn  2418:                              $states,$stored,$navbuttons,$img1,$img2,
1.44      albertel 2419:                              $gpterm,$ucgpterm,$crstype);
1.5       raeburn  2420:         }
                   2421:     }
                   2422:     my $prevtext = $$navbuttons{'gtps'};
                   2423:     &display_navbuttons($r,$formname,$$states{$action}[$page-1],$prevtext,
                   2424:                         $$states{$action}[$page+1],$nexttext);
                   2425:     return;
                   2426: }
                   2427: 
                   2428: sub build_boxes {
                   2429:     my ($r,$tools,$usertools,$fixedprivs,$toolprivs,$showtools,
1.6       raeburn  2430:         $showboxes,$prefix,$specificity,$excluded) = @_;
1.5       raeburn  2431:     my $totalboxes = 0;
                   2432:     if (@{$tools} > 0) {
                   2433:         if ($specificity eq 'Yes') {
                   2434:             foreach my $tool (@{$tools}) {
                   2435:                 @{$$showboxes{$tool}} = ();
                   2436:                 foreach my $user (sort(keys(%{$usertools}))) {
1.6       raeburn  2437:                     if (ref($excluded) eq 'ARRAY') {
                   2438:                         if (grep/^$user$/,@{$excluded}) {
                   2439:                             next;
                   2440:                         }
1.5       raeburn  2441:                     }
1.6       raeburn  2442:                     if ($$usertools{$user}{$tool}) {
                   2443:                         unless (grep/^$tool$/,@{$showtools}) {
                   2444:                             push(@{$showtools},$tool);
                   2445:                         }
                   2446:                         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   2447:                             unless (exists($$fixedprivs{$tool}{$priv})) {
                   2448:                                 unless(grep(/^$priv$/,@{$$showboxes{$tool}})) {
                   2449:                                     push(@{$$showboxes{$tool}},$priv);
                   2450:                                     $totalboxes ++;
                   2451:                                 }
1.5       raeburn  2452:                             }
                   2453:                         }
                   2454:                     }
                   2455:                 }
                   2456:             }
                   2457:             if ($totalboxes > 0) {
                   2458:                 $r->print('
                   2459: <script type="text/javascript">
                   2460: function checkAllTools(formname) {
                   2461: ');
                   2462:                 foreach my $tool (sort(keys(%{$showboxes}))) {
                   2463:                     foreach my $priv (@{$$showboxes{$tool}}) {
                   2464:                         $r->print('  checkAll(formname.'.$prefix.$priv.');'."\n");
                   2465:                     }
                   2466:                 }
                   2467:                 $r->print('
                   2468: }
                   2469: function uncheckAllTools(formname) {
                   2470: ');
                   2471:                 foreach my $tool (sort(keys(%{$showboxes}))) {
                   2472:                     foreach my $priv (@{$$showboxes{$tool}}) {
                   2473:                         $r->print('  uncheckAll(formname'.$prefix.$priv.');'."\n");
                   2474:                     }
                   2475:                 }
                   2476:                 $r->print('
                   2477: }
                   2478: </script>
                   2479:                 ');
                   2480:             }
                   2481:         }
                   2482:     }
                   2483:     return $totalboxes;
                   2484: }
                   2485: 
                   2486: sub member_privileges_form {
1.45    ! albertel 2487:     my ($r,$action,$formname,$tools,$toolprivs,$fixedprivs,$userdata,
        !          2488:         $usertools,$idx,$memchg,$states,$stored,$gpterm) = @_;
1.5       raeburn  2489:     my %lt = &Apache::lonlocal::texthash(
                   2490:             'addp' => 'Additional privileges',
                   2491:             'fixp' => 'Fixed privileges',
                   2492:             'oppr' => 'Optional privileges',
                   2493:             'func' => 'Function',
                   2494:             'forf' => 'For the functionality you have chosen to include '.
                   2495:                       'there are no optional privileges to set besides '.
                   2496:                       'the standard privileges.',
1.29      raeburn  2497:             'algr' => "All $gpterm members will receive the same privileges.",
                   2498:             'asno' => "As no $gpterm members are being added, ".
                   2499:                       "there are no specific user privileges to set.",
                   2500:             'asng' => "As no $gpterm tools will be made available to users, ".
                   2501:                       "there are no specific user privileges to set.",
                   2502:             'nogm' => "No $gpterm member privileges to display or set, ".
                   2503:                       "as you have not indicated that you will be activating,".
                   2504:                       " re-enabling, changing privileges, or adding/removing ".
                   2505:                       "functionality for any current members ",
1.5       raeburn  2506:             'full' => 'Fullname',
                   2507:             'user' => 'Username',
                   2508:             'doma' => 'Domain',
                   2509:     );
                   2510:     my @defprivs;
                   2511:     my $specificity;
                   2512:     if ($action eq 'create') {
                   2513:         if (defined($env{'form.defpriv'})) {
                   2514:             @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
                   2515:         }
                   2516:         $specificity = $env{'form.specificity'};
                   2517:     } else {
1.17      raeburn  2518:         if (defined($$stored{'defpriv'})) {
                   2519:             @defprivs = @{$$stored{'defpriv'}};
                   2520:         }
1.5       raeburn  2521:         $specificity = $$stored{'specificity'};
                   2522:     }
                   2523:     my @showtools;
                   2524:     my %showboxes = ();
                   2525:     my $numtools = 1 + @{$tools};
1.3       raeburn  2526: 
1.6       raeburn  2527:     my @excluded = ();
                   2528:     my $numchgs = 0;
                   2529:     if ($formname eq 'change_privs') {
                   2530:         my @currmembers = ();
                   2531:         if (ref($$memchg{'deletion'}) eq 'ARRAY') {
                   2532:             push(@excluded,@{$$memchg{'deletion'}});
                   2533:         }
                   2534:         if (ref($$memchg{'expire'}) eq 'ARRAY') {
                   2535:             push(@excluded,@{$$memchg{'expire'}});
                   2536:         }
                   2537:         if (@excluded > 0) {
                   2538:             foreach my $user (sort(keys(%{$usertools}))) {
                   2539:                 if (grep/^$user$/,@excluded) {
                   2540:                     next;
                   2541:                 }
                   2542:                 push(@currmembers,$user);
                   2543:             }
                   2544:         } else {
                   2545:             @currmembers = sort(keys(%{$usertools}));
                   2546:         }
                   2547:         $numchgs = @currmembers;
                   2548:         if (!$numchgs) {
1.45    ! albertel 2549:             $r->print($lt{'nogm'}); 
1.6       raeburn  2550:             return $numchgs;
                   2551:         }
                   2552:     }
                   2553:  
                   2554:     my $totalboxes = &build_boxes($r,$tools,$usertools,$fixedprivs,
                   2555:                                    $toolprivs,\@showtools,\%showboxes,
                   2556:                                    'userpriv_',$specificity,\@excluded);
1.5       raeburn  2557:     if (@{$tools} > 0) {
                   2558:         if ($specificity eq 'Yes') {
                   2559:             if ($totalboxes > 0) {
                   2560:                 my $numcells = 2;
                   2561:                 my $colspan = $numcells + 1;
                   2562:                 my %total;
1.6       raeburn  2563:                 if (keys(%{$usertools}) > 1) {
                   2564:                     $r->print('
1.45    ! albertel 2565:    <table border="0" cellspacing="2" cellpadding="2">
1.5       raeburn  2566:     <tr>
                   2567: ');
1.6       raeburn  2568:                     foreach my $tool (@{$tools}) {
                   2569:                         if (@{$showboxes{$tool}} > 0) {
                   2570:                             $r->print('<td valign="top">');
1.45    ! albertel 2571:                             $r->print('<table class="thinborder"><tr>'.
        !          2572: 				      '<th colspan="'.$colspan.'">'.
1.6       raeburn  2573:                                       $tool.'</th></tr><tr>');
                   2574:                             my $privcount = 0;
                   2575:                             foreach my $priv (@{$showboxes{$tool}}) {
                   2576:                                 $privcount ++;
                   2577:                                 if (($privcount == @{$showboxes{$tool}}) && 
                   2578:                                     ($privcount > 1)) {
                   2579:                                     if ($privcount%$numcells) {
                   2580:                                         $r->print('<td colspan="'.$colspan.'">');
                   2581:                                     } else {
                   2582:                                         $r->print('<td>');
                   2583:                                     }
1.5       raeburn  2584:                                 } else {
                   2585:                                     $r->print('<td>');
                   2586:                                 }
1.6       raeburn  2587:                                 $r->print(qq|
1.5       raeburn  2588:        <fieldset><legend><b>$$toolprivs{$tool}{$priv}</b></legend>
                   2589:        <nobr>
                   2590:        <input type="button" value="check all"
                   2591:          onclick="javascript:checkAll(document.$formname.userpriv_$priv)" />
                   2592:        &nbsp;
                   2593:        <input type="button" value="uncheck all"
                   2594:         onclick="javascript:uncheckAll(document.$formname.userpriv_$priv)" />
                   2595:       </nobr></fieldset><br />|);
1.6       raeburn  2596:                                 $r->print('</td>');
                   2597:                                 if ($privcount < @{$showboxes{$tool}}) {
                   2598:                                     if (@{$showboxes{$tool}} > 2) {
                   2599:                                         if ($privcount%$numcells == 0) {
                   2600:                                             $r->print('</tr><tr>');
                   2601:                                         }
                   2602:                                     } else {
                   2603:                                         $r->print('<tr></tr>');
1.5       raeburn  2604:                                     }
                   2605:                                 }
                   2606:                             }
1.6       raeburn  2607:                             $r->print('</tr></table></td><td>&nbsp;</td>');
1.5       raeburn  2608:                         }
                   2609:                     }
1.45    ! albertel 2610:                     $r->print('</tr></table>');
1.5       raeburn  2611:                 }
1.45    ! albertel 2612:                 $r->print(&Apache::loncommon::start_data_table().
        !          2613: 			  &Apache::loncommon::start_data_table_header_row());
1.5       raeburn  2614:                 $r->print(<<"END");
1.45    ! albertel 2615:     <th>$lt{'full'}</th>
        !          2616:     <th>$lt{'user'}</th>
1.5       raeburn  2617:     <th>$lt{'doma'}</th>
                   2618:     <th colspan="$numtools">$lt{'addp'}</th>
                   2619: END
1.45    ! albertel 2620:                 $r->print(&Apache::loncommon::end_data_table_header_row());
        !          2621:                 &member_privs_entries($r,$usertools,$toolprivs,$fixedprivs,
1.6       raeburn  2622:                                       $userdata,$idx,\@showtools,\@defprivs,
                   2623:                                       \@excluded);
1.45    ! albertel 2624:                 $r->print(&Apache::loncommon::end_data_table());
1.5       raeburn  2625:             } else {
1.43      albertel 2626:                 $r->print($lt{'forf'}.'<br />');
1.45    ! albertel 2627:                 &display_defprivs($r,$tools,$toolprivs,\@defprivs);
1.5       raeburn  2628:             }
                   2629:         } else {
                   2630:             if (keys(%{$usertools}) > 0) {
1.43      albertel 2631:                 $r->print($lt{'algr'}.'<br /><br />');
1.45    ! albertel 2632:                 &display_defprivs($r,$tools,$toolprivs,\@defprivs);
1.5       raeburn  2633:             } else {
1.43      albertel 2634:                 $r->print($lt{'asno'}.'<br />');
1.5       raeburn  2635:             }
                   2636:         }
                   2637:     } else {
1.43      albertel 2638:         $r->print($lt{'asng'});
1.5       raeburn  2639:     }
1.6       raeburn  2640:     return $numchgs;
1.1       raeburn  2641: }
                   2642: 
1.5       raeburn  2643: sub process_request {
1.45    ! albertel 2644:     my ($r,$cdom,$cnum,$action,$state,$page,$groupname,$description,
1.5       raeburn  2645:         $specificity,$userdata,$startdate,$enddate,$tools,$functions,$toolprivs,
                   2646:         $usertools,$idx,$types,$roles,$sections,$states,$navbuttons,$memchg,
1.45    ! albertel 2647:         $sectioncount,$stored,$gpterm,$ucgpterm,$crstype) = @_;
1.3       raeburn  2648: 
                   2649:     $r->print(&Apache::lonhtmlcommon::echo_form_input(
1.6       raeburn  2650:                                  ['origin','action','state','page','sortby']));
1.5       raeburn  2651: 
1.29      raeburn  2652:     my $earlyout = &validate_groupname($groupname,$action,$cdom,$cnum,$gpterm,
                   2653:                                        $ucgpterm,$crstype);
1.5       raeburn  2654:     if ($earlyout) {
                   2655:         $r->print('
                   2656: <table width="100%" cellpadding="0" cellspacing="0" border="0">
                   2657:  <tr>
                   2658:   <td>&nbsp;</td>
                   2659:   <td colspan="3">
                   2660: '.$earlyout.'</td></tr>');
                   2661:         &display_navbuttons($r,$state,$$states{$action}[$page-1],
                   2662:                             $$navbuttons{'gtps'});
                   2663:         $r->print('</table>');
                   2664:         return;
                   2665:     }
                   2666: 
                   2667:     my @defprivs = ();
                   2668:     if ($action eq 'create' || $state eq 'chgresult') { 
                   2669:         if (defined($env{'form.defpriv'})) {
                   2670:             @defprivs = &Apache::loncommon::get_env_multiple('form.defpriv');
                   2671:         }
                   2672:         if ($state eq 'chgresult') {
                   2673:             my @okprivs = ();
                   2674:             foreach my $tool (@{$tools}) {
                   2675:                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   2676:                     push(@okprivs,$priv);
                   2677:                 }
                   2678:             }
                   2679:             my @temp = ();
                   2680:             foreach my $defpriv (@defprivs) {
                   2681:                 if (grep/^$defpriv$/,@okprivs) {
                   2682:                     push(@temp,$defpriv);
                   2683:                 }
                   2684:             }
                   2685:             @defprivs = @temp; 
                   2686:         }
                   2687:     } else {
1.17      raeburn  2688:         if (defined($$stored{'defpriv'})) {
                   2689:             @defprivs = @{$$stored{'defpriv'}};
                   2690:         }
1.5       raeburn  2691:     }
                   2692: 
                   2693:     my $outcome;
                   2694:     if ($action eq 'create' || $state eq 'chgresult') {
                   2695:         $outcome = &write_group_data($r,$cdom,$cnum,$action,$state,$groupname,
                   2696:                                      $description,$startdate,$enddate,
                   2697:                                      $specificity,$functions,$tools,
                   2698:                                      $sectioncount,$roles,$types,$sections,
1.29      raeburn  2699:                                      \@defprivs,$stored,$gpterm,$ucgpterm,
                   2700:                                      $crstype); 
1.5       raeburn  2701:     }
                   2702:     if (($action eq 'create' && $outcome eq 'ok') || (($action eq 'modify') && 
                   2703:        (($state eq 'memresult') || ($state eq 'addresult')))) {
1.6       raeburn  2704:         &process_membership($r,$cdom,$cnum,$action,$state,$groupname,$tools,
                   2705:                             $enddate,$startdate,$userdata,$idx,$toolprivs,
1.29      raeburn  2706:                             $usertools,$specificity,\@defprivs,$memchg,$gpterm,
                   2707:                             $ucgpterm);
1.5       raeburn  2708:     }
                   2709:     return;
                   2710: }
                   2711: 
                   2712: sub write_group_data {
                   2713:     my ($r,$cdom,$cnum,$action,$state,$groupname,$description,$startdate,
                   2714:         $enddate,$specificity,$functions,$tools,$sectioncount,$roles,$types,
1.29      raeburn  2715:         $sections,$defprivs,$stored,$gpterm,$ucgpterm,$crstype) = @_;
1.5       raeburn  2716:     my $now = time;
                   2717:     my $creation = $now;
                   2718:     my $creator = $env{'user.name'}.':'.$env{'user.domain'};
                   2719:     if ($state eq 'chgresult') {
                   2720:         $creation = $$stored{'creation'};
                   2721:         $creator = $$stored{'creator'};
                   2722:     }
1.24      www      2723:     my $esc_description = &escape($description);
1.5       raeburn  2724:     my @single_attributes = ('description','functions','startdate','enddate',
                   2725:                              'creation','modified','creator','granularity',
1.29      raeburn  2726:                              'specificity','autoadd','autodrop','quota');
1.5       raeburn  2727:     my @mult_attributes = ('roles','types','sectionpick','defpriv');
1.15      albertel 2728: 
1.37      raeburn  2729:     my ($crsquota,$freespace,$maxposs) = &get_quota_constraints($action,
                   2730:                                                                 $stored);
                   2731:     my $quota = $env{'form.quota'};
                   2732:     
                   2733:     $quota =~ s/^\s*([^\s]*)\s*$/$1/;
                   2734:     if ($quota eq '') {
                   2735:         $quota = 0;
                   2736:     }
                   2737:     if ($quota !~ /^\d*\.?\d*$/) {
                   2738:         $quota = 0;
                   2739:         $r->print(&mt('The value you entered for the quota for the file repository in this [_1] contained invalid characters, so it has been set to 0 Mb. You can change this by modifying the [_1] settings.<br />',$gpterm));
                   2740:     }
                   2741:     if ($quota > $maxposs) {
                   2742:         $quota = $maxposs;
                   2743:         $r->print(&mt('The value you entered for the quota for the file repository in this [_1] exceeded the maximum possible value, so it has been set to [_2] Mb (the maximum possible value).<br />',$gpterm,$maxposs));
                   2744:     }
1.5       raeburn  2745:     my %groupinfo = (
                   2746:                      description => $esc_description,
                   2747:                      startdate => $startdate,
                   2748:                      enddate => $enddate,
                   2749:                      creation => $creation,
                   2750:                      modified => $now,
                   2751:                      creator => $creator,
                   2752:                      granularity => $env{'form.granularity'},
                   2753:                      specificity => $specificity,
                   2754:                      autoadd => $env{'form.autoadd'},
                   2755:                      autodrop => $env{'form.autodrop'},
1.37      raeburn  2756:                      quota => $quota,
1.5       raeburn  2757:                    );
1.37      raeburn  2758: 
1.5       raeburn  2759:     foreach my $func (keys(%{$functions})) {
                   2760:         my $status;
                   2761:         if (grep(/^$func$/,@{$tools})) {
                   2762:             $status = 'on';
                   2763:         } else {
                   2764:             $status = 'off';
                   2765:         }
                   2766:         $groupinfo{'functions'} .=  qq|<name id="$func">$status</name>|;
                   2767:     }
                   2768: 
                   2769:     $groupinfo{'roles'} = $roles;
                   2770:     $groupinfo{'types'} = $types;
                   2771:     $groupinfo{'sectionpick'} = $sections;
                   2772:     $groupinfo{'defpriv'} = $defprivs;
                   2773: 
                   2774:     my %groupsettings = ();
                   2775:     foreach my $item (@single_attributes) {
                   2776:         $groupsettings{$groupname} .= qq|<$item>$groupinfo{$item}</$item>|;
                   2777:     }
                   2778:     foreach my $item (@mult_attributes) {
                   2779:         foreach my $entry (@{$groupinfo{$item}}) {
                   2780:             $groupsettings{$groupname} .= qq|<$item>$entry</$item>|;
                   2781:         }
                   2782:     }
                   2783:     my $autosec;
                   2784:     my @autorole = &Apache::loncommon::get_env_multiple('form.autorole');
1.15      albertel 2785: 
1.5       raeburn  2786:     foreach my $role (@autorole) {
                   2787:         if (defined($env{'form.sec_'.$role})) {
                   2788:             my @autosections=&Apache::loncommon::get_env_multiple('form.sec_'.
                   2789:                                                                   $role);
                   2790:             $autosec .= '<role id="'.$role.'">';
                   2791:             foreach my $sec (@autosections) {
                   2792:                 $autosec .= '<section>'.$sec.'</section>';
                   2793:             }
                   2794:             $autosec .= '</role>';
                   2795:         }
                   2796:     }
                   2797:     if ($autosec) {
                   2798:         $groupsettings{$groupname} .= qq|<autosec>$autosec</autosec>|;
                   2799:     }
                   2800:     my $result = &Apache::lonnet::modify_coursegroup($cdom,$cnum,
                   2801:                                                      \%groupsettings);
                   2802: 
                   2803:     if ($result eq 'ok') {
                   2804:         if ($action eq 'create') {
1.32      raeburn  2805:             my $result = &add_group_folder($cdom,$cnum,$now,$groupname,$action,
                   2806:                                            $description,$tools,\%groupinfo,
                   2807:                                            $gpterm,$ucgpterm,$crstype);
                   2808:             if ($result ne 'ok') {
1.37      raeburn  2809:                 $r->print(&mt('A problem occurred when creating folders for the new [_1]. [_2].<br />',$gpterm,$result));
1.32      raeburn  2810:             }
1.29      raeburn  2811:             $r->print(&mt('[_1] [_2] was created.<br />',$ucgpterm,$groupname));
1.5       raeburn  2812:         } else {
1.29      raeburn  2813:             $r->print(&mt('[_1] [_2] was updated.<br />',$ucgpterm,$groupname));
1.5       raeburn  2814:         }
                   2815:     } else {
                   2816:         my %actiontype = (
                   2817:                           'create' => 'creating',
                   2818:                           'modify' => 'modifying',
                   2819:                          );
1.29      raeburn  2820:         &Apache::lonnet::logthis("Failed to store $gpterm $groupname ".
                   2821:                                  'in '.lc($crstype).': '.$cnum.
                   2822:                                  ' in domain: '.$cdom);
1.37      raeburn  2823:         $r->print(&mt('An error occurred when [_1] the [_2]. '.
1.29      raeburn  2824:                       'Please try again.',$actiontype{$action},$gpterm));
1.5       raeburn  2825:     }
                   2826:     return $result;
                   2827: }
                   2828: 
                   2829: sub process_membership {
1.6       raeburn  2830:     my ($r,$cdom,$cnum,$action,$state,$groupname,$tools,$enddate,$startdate,
1.29      raeburn  2831:         $userdata,$idx,$toolprivs,$usertools,$specificity,$defprivs,$memchg,
                   2832:         $gpterm,$ucgpterm)=@_;
1.5       raeburn  2833:     my %usersettings = ();
1.6       raeburn  2834:     my %added= ();
                   2835:     my %failed = ();
                   2836:     my $num_ok = 0;
                   2837:     my $num_fail = 0;
1.3       raeburn  2838:     my %group_privs = ();
1.20      raeburn  2839:     my %curr_privs = ();
1.21      raeburn  2840:     my %curr_start = ();
                   2841:     my %curr_end = ();
1.3       raeburn  2842:     my %tooltype = ();
1.5       raeburn  2843: 
1.3       raeburn  2844:     foreach my $tool (@{$tools}) {
                   2845:         foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   2846:             $tooltype{$priv} = $tool;
1.5       raeburn  2847:             if ($specificity eq 'Yes') {
1.3       raeburn  2848:                 my @users =
                   2849:                   &Apache::loncommon::get_env_multiple('form.userpriv_'.$priv);
                   2850:                 foreach my $user (@users) {
                   2851:                     $group_privs{$user} .= $priv.':';
1.8       raeburn  2852:                     if ($state eq 'memresult') { 
                   2853:                         unless (exists($$usertools{$user}{$tool})) {
                   2854:                             $$usertools{$user}{$tool} = 1;
                   2855:                         }
                   2856:                     }
1.3       raeburn  2857:                 }
                   2858:             } else {
1.5       raeburn  2859:                 if (@{$defprivs} > 0) {
1.26      raeburn  2860:                     if (grep/^\Q$priv\E$/,@{$defprivs}) {
1.5       raeburn  2861:                         foreach my $user (sort(keys(%{$usertools}))) {
                   2862:                             if ($$usertools{$user}{$tool}) {
                   2863:                                 $group_privs{$user} .= $priv.':';
                   2864:                             }
1.3       raeburn  2865:                         }
                   2866:                     }
                   2867:                 }
                   2868:             }
                   2869:         }
                   2870:     }
                   2871:     foreach my $user (keys(%group_privs)) {
                   2872:         $group_privs{$user} =~ s/:$//;
                   2873:     }
1.5       raeburn  2874: 
1.6       raeburn  2875:     my $now = time;
                   2876:     my @activate = ();
                   2877:     my @expire = ();
                   2878:     my @deletion = ();
                   2879:     my @reenable = ();
1.20      raeburn  2880:     my @unchanged = ();
1.6       raeburn  2881:     if ($state eq 'memresult') {
                   2882:         if (ref($$memchg{'activate'}) eq 'ARRAY') {
                   2883:             @activate = @{$$memchg{'activate'}};
                   2884:         }
                   2885:         if (ref($$memchg{'expire'}) eq 'ARRAY') {
                   2886:             @expire = @{$$memchg{'expire'}};
                   2887:         }
                   2888:         if (ref($$memchg{'deletion'}) eq 'ARRAY') {
                   2889:             @deletion = @{$$memchg{'deletion'}};
                   2890:         }
                   2891:         if (ref($$memchg{'reenable'}) eq 'ARRAY') {
                   2892:             @reenable = @{$$memchg{'reenable'}};
                   2893:         }
1.20      raeburn  2894:         my %membership = &Apache::lonnet::get_group_membership($cdom,$cnum,
                   2895:                                                                  $groupname);
                   2896:         foreach my $key (sort(keys(%membership))) {
                   2897:             if ($key =~ /^\Q$groupname\E:([^:]+:[^:]+)$/) {
1.21      raeburn  2898:                 ($curr_end{$1},$curr_start{$1},$curr_privs{$1}) = 
                   2899:                                                 split(/:/,$membership{$key},3);
1.20      raeburn  2900:             }
                   2901:         }
1.6       raeburn  2902:         if (@expire + @deletion > 0) {
                   2903:             foreach my $user (@expire) {
1.21      raeburn  2904:                 my $savestart = $curr_start{$user};
                   2905:                 if ($savestart > $now) {
                   2906:                     $savestart = $now;
1.6       raeburn  2907:                 }
1.21      raeburn  2908:                 $usersettings{$groupname.':'.$user} = $now.':'.$savestart.':'.
                   2909:                                                       $curr_privs{$user};
1.6       raeburn  2910:                 if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
1.21      raeburn  2911:                                                        $user,$now,$savestart,
                   2912:                                                        $curr_privs{$user}) eq 'ok') {
1.6       raeburn  2913:                     push(@{$added{'expired'}},$user);
                   2914:                     $num_ok ++;
                   2915:                 } else {
                   2916:                     push(@{$failed{'expired'}},$user);
                   2917:                     $num_fail ++;
                   2918:                 }
                   2919:             }
                   2920:             foreach my $user (@deletion) {
                   2921:                 $usersettings{$groupname.':'.$user} = $now.':-1:';
                   2922:                 if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
                   2923:                                                        $user,$now,'-1','')
                   2924:                                                          eq 'ok') {
                   2925:                     push(@{$added{'deleted'}},$user);
                   2926:                     $num_ok ++;
                   2927:                 } else {
                   2928:                     push(@{$failed{'deleted'}},$user);
                   2929:                     $num_fail ++;
                   2930:                 }
                   2931:             }
                   2932:         }
1.8       raeburn  2933:     }
1.6       raeburn  2934: 
1.5       raeburn  2935:     foreach my $user (sort(keys(%{$usertools}))) {
1.20      raeburn  2936:         if ((grep(/^$user$/,@expire)) || (grep(/^$user$/,@deletion))) {
                   2937:             next;
                   2938:         }
1.6       raeburn  2939:         my $type;
                   2940:         my $start = $startdate;
                   2941:         my $end = $enddate;
                   2942:         if ($state eq 'memresult') {
                   2943:             if (@activate > 0) {
                   2944:                 if (grep/^$user$/,@activate) {
                   2945:                     $start = $now;
1.21      raeburn  2946:                     $end = $enddate;
1.6       raeburn  2947:                     $type = 'activated';
                   2948:                 }
                   2949:             }
                   2950:             if (@reenable > 0) {
                   2951:                 if (grep/^$user$/,@reenable) {
1.21      raeburn  2952:                     $start = $startdate;
                   2953:                     $end = $enddate;
1.6       raeburn  2954:                     $type = 'reenabled';
                   2955:                 }
                   2956:             }
1.38      raeburn  2957:             if ($type eq '') {
                   2958:                 if ($curr_privs{$user} eq $group_privs{$user}) {
                   2959:                     push(@unchanged,$user);
                   2960:                     next;
                   2961:                 }
                   2962:                 if (exists($curr_start{$user})) {
                   2963:                     $start = $curr_start{$user};
                   2964:                 }
                   2965:                 if (exists($curr_end{$user})) {
                   2966:                     $end = $curr_end{$user};
                   2967:                 }
                   2968:                 $type = 'modified';
                   2969:             }
1.6       raeburn  2970:         } else {
                   2971:             $type = 'added';
                   2972:         }
                   2973:         $usersettings{$groupname.':'.$user} = $end.':'.$start.':'.
1.5       raeburn  2974:                                               $group_privs{$user};
                   2975:         if (&Apache::lonnet::modify_group_roles($cdom,$cnum,$groupname,
1.6       raeburn  2976:                                                 $user,$end,$start,
1.5       raeburn  2977:                                                 $group_privs{$user}) eq 'ok') {
1.6       raeburn  2978:             push(@{$added{$type}},$user);
                   2979:             $num_ok ++;
1.3       raeburn  2980:         } else {
1.6       raeburn  2981:             push(@{$failed{$type}},$user);
                   2982:             $num_fail ++;
1.5       raeburn  2983:         }
                   2984:     }
                   2985:     my $roster_result = &Apache::lonnet::modify_coursegroup_membership($cdom,
                   2986:                                                        $cnum,\%usersettings);
1.6       raeburn  2987:     if ($num_ok) {
                   2988:         foreach my $type (sort(keys(%added))) { 
                   2989:             $r->print(&mt('The following users were successfully [_1]',$type));
1.20      raeburn  2990:             if (!($type eq 'deleted' || $type eq 'expired')) {   
1.6       raeburn  2991:                 $r->print(&mt(' with the following privileges'));
                   2992:             }
                   2993:             $r->print(':<br />');
                   2994:             foreach my $user (@{$added{$type}}) {
1.8       raeburn  2995:                 my $privlist = '';
                   2996:                 if (!($type eq 'deleted' ||  $type eq 'expired')) {
                   2997:                     $privlist = ': ';
1.6       raeburn  2998:                     my @privs = split(/:/,$group_privs{$user});
                   2999:                     my $curr_tool = '';
                   3000:                     foreach my $priv (@privs) {
                   3001:                         unless ($curr_tool eq $tooltype{$priv}) {
                   3002:                             $curr_tool = $tooltype{$priv};
                   3003:                             $privlist .= '<b>'.$curr_tool.'</b>: ';
                   3004:                         }
                   3005:                         $privlist .= $$toolprivs{$curr_tool}{$priv}.', ';
                   3006:                     }
                   3007:                     $privlist =~ s/, $//;
                   3008:                 }
1.8       raeburn  3009:                 $r->print($$userdata{$user}[$$idx{fullname}].'&nbsp;-&nbsp;'.$user.$privlist.'<br />');
1.6       raeburn  3010:             }
1.20      raeburn  3011:             $r->print('<br />');
1.6       raeburn  3012:         }
                   3013:     }
                   3014:     if ($num_fail) {
                   3015:         foreach my $type (sort(keys(%failed))) {
                   3016:             $r->print(&mt('The following users could not be [_1], because an error occurred:<br />',$type));
                   3017:             foreach my $user (@{$failed{$type}}) {
                   3018:                 $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
                   3019:             }
1.5       raeburn  3020:         }
1.20      raeburn  3021:         $r->print('<br />');
                   3022:     }
                   3023:     if (@unchanged > 0) {
                   3024:         $r->print(&mt('No change occurred for the following users:<br />'));
                   3025:         foreach my $user (sort(@unchanged)) {
                   3026:             $r->print($$userdata{$user}[$$idx{fullname}].' - '.$user.'<br />');
                   3027:         }
                   3028:         $r->print('<br />');
1.5       raeburn  3029:     }
                   3030:     if ($roster_result eq 'ok') {
1.29      raeburn  3031:         $r->print('<br />'.&mt('[_1] membership list updated.',$ucgpterm));
1.30      albertel 3032: 	$r->print('<p>'.&mt("For full access to all of [_1]'s privileges, users will need to log out and log back in.",$groupname).'</p>');
1.5       raeburn  3033:     } else {
1.29      raeburn  3034:         $r->print('<br />'.&mt('An error occurred while updating the [_1] membership list -',$gpterm).$roster_result.'<br />');
1.5       raeburn  3035:     }
                   3036:     return;
                   3037: }
                   3038: 
                   3039: sub mapping_options {
1.44      albertel 3040:     my ($r,$action,$formname,$page,$sectioncount,$states,$stored,
                   3041:         $navbuttons,$img1,$img2,$gpterm,$ucgpterm,$crstype) = @_;
1.5       raeburn  3042:     my %lt = &Apache::lonlocal::texthash(
1.29      raeburn  3043:         'auto' => "Settings for automatic $gpterm enrollment",
                   3044:         'gmma' => "$ucgpterm membership mapping to specific sections/roles",
                   3045:         'endi' => "Enable/disable automatic $gpterm enrollment for ".
                   3046:                           "users in specified roles and sections",
                   3047:         'adds'  => "If automatic $gpterm enrollment is enabled, when a user is assigned a ".lc($crstype)."-wide or section-specific role, he/she will automatically be added as a member of the $gpterm, with start and end access dates defined by the default dates set for the $gpterm, unless he/she is already a $gpterm member, with access dates that permit either current or future $gpterm access.",
                   3048:         'drops'  => "If automatic $gpterm disenrollment is enabled, when a user's role is expired, access to the $gpterm will be terminated unless the user continues to have other ".lc($crstype)."-wide or section-specific active or future roles which receive automatic membership in the $gpterm.",
                   3049:         'pirs' => "Pick roles and sections for automatic $gpterm enrollment",
1.5       raeburn  3050:         'curr' => 'Currently set to',
                   3051:         'on' => 'on',
                   3052:         'off' => 'off',
1.29      raeburn  3053:         'auad' => "Automatically enable $gpterm membership when roles are added?",
                   3054:         'auex' => "Automatically expire $gpterm membership when roles are removed?",
                   3055:         'mapr' => "Mapping of roles and sections affected by automatic $gpterm enrollment/disenrollment follows scheme chosen below.",
1.5       raeburn  3056:     );
1.44      albertel 3057:     &automapping($r,$action,$stored,\%lt,$img1);
                   3058:     &mapping_settings($r,$sectioncount,\%lt,$stored,$img2,$crstype);
1.5       raeburn  3059:     return;
                   3060: }
                   3061: 
                   3062: sub automapping {
1.44      albertel 3063:     my ($r,$action,$stored,$lt,$image) = @_;
1.5       raeburn  3064:     my $add = 'off';
                   3065:     my $drop = 'off';
                   3066:     if (exists($$stored{'autoadd'})) {
                   3067:         $add = $$stored{'autoadd'};
                   3068:     }
                   3069:     if (exists($$stored{'autodrop'})) {
                   3070:         $drop = $$stored{'autodrop'};
                   3071:     }
1.40      albertel 3072:     &topic_bar($r,$image,$$lt{'endi'});
1.5       raeburn  3073:     $r->print('
1.44      albertel 3074:     <b>'.$$lt{'gmma'}.':</b><br />'.$$lt{'adds'}.'<br />'.$$lt{'drops'}.'<br /><br />
1.5       raeburn  3075:    <nobr>'.$$lt{'auad'}.':&nbsp;
1.18      albertel 3076:     <label><input type="radio" name="autoadd" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autoadd" value="off" checked="checked" />off</label>');
1.5       raeburn  3077:     if ($action eq 'modify') {
                   3078:         $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$add}.'</b>)');
                   3079:     }
                   3080:     $r->print('
1.44      albertel 3081:     </nobr><br />
1.5       raeburn  3082:     <nobr>'.$$lt{'auex'}.':&nbsp;
1.18      albertel 3083:     <label><input type="radio" name="autodrop" value="on" />on&nbsp;&nbsp;</label><label><input type="radio" name="autodrop" value="off" checked="checked" />off</label>');
1.5       raeburn  3084:     if ($action eq 'modify') {
                   3085:         $r->print('&nbsp;&nbsp;&nbsp;&nbsp;('.$$lt{'curr'}.' <b>'.$$lt{$drop}.'</b>)');
1.3       raeburn  3086:     }
1.44      albertel 3087:     $r->print('</nobr><br /><br />'.$$lt{'mapr'});
1.5       raeburn  3088: }
1.3       raeburn  3089: 
1.5       raeburn  3090: sub mapping_settings {
1.44      albertel 3091:     my ($r,$sectioncount,$lt,$stored,$image,$crstype) = @_;
1.5       raeburn  3092:     my @sections = keys(%{$sectioncount});
                   3093:     if (@sections > 0) {
                   3094:         @sections = sort {$a cmp $b} @sections;
1.17      raeburn  3095:         unshift(@sections,'none'); # Put 'no sections' next
                   3096:         unshift(@sections,'all'); # Put 'all' at the front of the list
1.3       raeburn  3097:     }
1.40      albertel 3098:     &topic_bar($r,$image,$$lt{'pirs'});
1.5       raeburn  3099:     my @roles = &standard_roles();
                   3100:     my %customroles = &my_custom_roles();
1.44      albertel 3101:     $r->print(&Apache::loncommon::start_data_table().
                   3102: 	      &Apache::loncommon::start_data_table_header_row());
1.5       raeburn  3103:     $r->print('
                   3104:                  <th>'.&mt('Active?').'</th>
                   3105:                  <th>'.&mt('Role').'</th>');
                   3106:     if (@sections > 0) {
1.44      albertel 3107:         $r->print('<th>'.&mt('Sections').'</th>');
1.3       raeburn  3108:     }
1.44      albertel 3109:     $r->print(&Apache::loncommon::end_data_table_header_row()."\n");
1.5       raeburn  3110:     foreach my $role (@roles) {
1.29      raeburn  3111:         my $plrole=&Apache::lonnet::plaintext($role,$crstype);
1.5       raeburn  3112:         my $sections_sel;
                   3113:         if (@sections > 0) {
1.17      raeburn  3114:             if ($role eq 'cc') {
                   3115:                 $sections_sel = '<td align="right">'.
                   3116:                                 &mt('all sections').'<input type="hidden" '. 
                   3117:                                 'name="sec_cc" value="all" /></td>';
                   3118:             } else { 
                   3119:                 $sections_sel='<td align="right">'.
                   3120:                               &sections_selection(\@sections,'sec_'.$role).
                   3121:                               '</td>';
                   3122:             }
1.5       raeburn  3123:         }
1.44      albertel 3124:         $r->print(&Apache::loncommon::start_data_table_row().
                   3125: 		  '<td><input type="checkbox" '.
1.45    ! albertel 3126:                   'name="autorole" value="'.$role.'" /></td><td>'.$plrole.
1.44      albertel 3127:                   '</td>'.$sections_sel.
                   3128: 		  &Apache::loncommon::end_data_table_row());
1.5       raeburn  3129:     }
                   3130:     foreach my $role (sort(keys(%customroles))) {
                   3131:         my $sections_sel;
                   3132:         if (@sections > 0) {
1.44      albertel 3133:             $sections_sel = 
                   3134: 		'<td>'.&sections_selection(\@sections,'sec_'.$role).'</td>';
1.5       raeburn  3135:         }
1.44      albertel 3136:         $r->print(&Apache::loncommon::start_data_table_row().
                   3137: 		  '<td><input type="checkbox" '.
1.45    ! albertel 3138:                   'value="'.$role.'" /></td><td>'.$role.'</td>'.
1.44      albertel 3139:                   $sections_sel.
                   3140: 		  &Apache::loncommon::end_data_table_row());
1.5       raeburn  3141:     }
1.44      albertel 3142:     $r->print(&Apache::loncommon::end_data_table());
1.5       raeburn  3143:     return;
                   3144: }
1.3       raeburn  3145: 
1.5       raeburn  3146: sub standard_roles {
1.17      raeburn  3147:     my @roles = ('cc','in','ta','ep','st');
1.5       raeburn  3148:     return @roles;
                   3149: }
                   3150: 
                   3151: sub my_custom_roles {
                   3152:     my %returnhash=();
                   3153:     my %rolehash=&Apache::lonnet::dump('roles');
                   3154:     foreach (keys %rolehash) {
                   3155:         if ($_=~/^rolesdef\_(\w+)$/) {
                   3156:             $returnhash{$1}=$1;
                   3157:         }
                   3158:     }
                   3159:     return %returnhash;
                   3160: }
                   3161: 
                   3162: sub modify_menu {
1.29      raeburn  3163:     my ($r,$groupname,$page,$gpterm) = @_;
1.5       raeburn  3164:     my @menu =
                   3165:         (
1.29      raeburn  3166:           { text => "Modify default $gpterm settings",
1.5       raeburn  3167:             help => 'Course_Modify_Group',
                   3168:             state => 'change_settings',
                   3169:             branch => 'settings',
                   3170:             },
1.6       raeburn  3171:           { text => 'Modify access, tools and/or privileges for previous, '.
                   3172:                     'future, or current members',
1.5       raeburn  3173:             help => 'Course_Modify_Group_Membership',
                   3174:             state => 'change_members',
                   3175:             branch => 'members',
                   3176:             },
1.29      raeburn  3177:           { text => "Add member(s) to the $gpterm",
1.5       raeburn  3178:             help => 'Course_Group_Add_Members',
                   3179:             state => 'add_members',
                   3180:             branch => 'adds',
                   3181:             },
                   3182:           );
                   3183:     my $menu_html = '';
                   3184:     foreach my $menu_item (@menu) {
                   3185:         $menu_html .=
                   3186:         '<p><font size="+1"><a href="/adm/coursegroups?action=modify&refpage='.$env{'form.refpage'}.'&groupname='.$groupname.'&state='.$menu_item->{'state'}.'&branch='.$menu_item->{'branch'}.'">';
                   3187:         $menu_html.= &mt($menu_item->{'text'}).'</a></font>';
                   3188:         if (exists($menu_item->{'help'})) {
                   3189:             $menu_html.=
                   3190:                 &Apache::loncommon::help_open_topic($menu_item->{'help'});
                   3191:         }
                   3192:         $menu_html.='</p>'.$/;
1.3       raeburn  3193:     }
1.5       raeburn  3194:     $r->print($menu_html);
1.3       raeburn  3195:     return;
                   3196: }
                   3197: 
                   3198: sub member_privs_entries {
1.45    ! albertel 3199:     my ($r,$usertools,$toolprivs,$fixedprivs,$userdata,$idx,$showtools,
        !          3200: 	$defprivs,$excluded) = @_;
1.5       raeburn  3201:     foreach my $user (sort(keys(%{$usertools}))) {
1.6       raeburn  3202:         if (defined($excluded)) {
                   3203:             if (ref($excluded) eq 'ARRAY') {
                   3204:                 if (grep/^$user$/,@{$excluded}) {
                   3205:                     next;
                   3206:                 }
                   3207:             }
                   3208:         }
1.5       raeburn  3209:         my ($uname,$udom) = split(/:/,$user);
1.45    ! albertel 3210:         $r->print(&Apache::loncommon::start_data_table_row().'
1.5       raeburn  3211:                 <td>'.$$userdata{$user}[$$idx{fullname}].'</td>
1.3       raeburn  3212:                 <td>'.$uname.'</td>
                   3213:                 <td>'.$udom.'</td>
                   3214:                 <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>');
1.5       raeburn  3215:         foreach my $tool (@{$showtools}) {
                   3216:             if (exists($$usertools{$user}{$tool})) {
1.45    ! albertel 3217:                 $r->print('<td valign="top"><table><tr><th colspan="2">'.$tool.'</th></tr>');
1.3       raeburn  3218:                 my $privcount = 0;
                   3219:                 my $fixed = '';
                   3220:                 my $dynamic = '';
                   3221:                 foreach my $priv (sort(keys(%{$$toolprivs{$tool}}))) {
                   3222:                     if (exists($$fixedprivs{$tool}{$priv})) {
1.5       raeburn  3223:                         $fixed .= '<input type="hidden" name="userpriv_'.$priv.'" value="'.$user.'" />'.$$toolprivs{$tool}{$priv}.'&nbsp;';
1.3       raeburn  3224:                     } else {
                   3225:                         $privcount ++;
                   3226:                         if ($privcount == 3) {
                   3227:                             $dynamic .= '</tr><tr>';
                   3228:                         }
1.7       raeburn  3229:                         $dynamic .='<td><nobr><label><input type="checkbox" '.
1.5       raeburn  3230:                                'name="userpriv_'.$priv.'" value="'.$user.'"';
                   3231:                         if (grep/^\Q$priv\E$/,@{$defprivs}) {
                   3232:                             $dynamic .= ' checked="checked" ';
                   3233:                         }
                   3234:                         $dynamic .= ' />'.$$toolprivs{$tool}{$priv}.
1.7       raeburn  3235:                                     '</label></nobr></td>';
1.3       raeburn  3236:                     }
                   3237:                 }
                   3238:                 $r->print('<tr><td colspan="2"><nobr>'.$fixed.'</nobr></td></tr><tr>'.$dynamic.'</tr></table></td>');
                   3239:             } else {
1.45    ! albertel 3240:                 $r->print('<td valign="top"><table width="100%"><tr><th colspan="2">'.$tool.'</th></tr><tr><td>&nbsp;</td></tr><tr><td>&nbsp;</td></tr></table></td>');
1.3       raeburn  3241:             }
                   3242:         }
1.45    ! albertel 3243:         $r->print(&Apache::loncommon::end_data_table_row());
1.3       raeburn  3244:     }
                   3245: }
                   3246: 
                   3247: sub get_dates_from_form {
                   3248:     my $startdate;
                   3249:     my $enddate;
                   3250:     $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
                   3251:     $enddate   = &Apache::lonhtmlcommon::get_date_from_form('enddate');
                   3252:     if ( exists ($env{'form.no_end_date'}) ) {
                   3253:         $enddate = 0;
                   3254:     }
                   3255:     return ($startdate,$enddate);
1.5       raeburn  3256: }
                   3257: 
1.3       raeburn  3258: sub date_setting_table {
                   3259:     my ($starttime,$endtime,$formname) = @_;
                   3260:     my $startform = &Apache::lonhtmlcommon::date_setter($formname,
                   3261:                                                       'startdate',$starttime);
                   3262:     my $endform = &Apache::lonhtmlcommon::date_setter($formname,
                   3263:                                                       'enddate',$endtime);
1.41      albertel 3264:     my $perpetual = 
                   3265: 	'<nobr><label><input type="checkbox" name="no_end_date" />'.
                   3266: 	&mt('None').'</label></nobr>';
1.42      albertel 3267:     my $table = "<table class=\"LC_descriptive_input\">\n".
                   3268: 	'<tr><td class="LC_description">'.&mt('Start:').'</td>'.
1.3       raeburn  3269:         '<td>'.$startform.'</td>'.
1.41      albertel 3270:         '<td>&nbsp;</td>'."</tr>\n".
1.42      albertel 3271: 	'<tr><td class="LC_description">'.&mt('End:').'</td>'.
1.3       raeburn  3272:         '<td>'.$endform.'</td>'.
1.41      albertel 3273:         '<td>'.$perpetual.'</td>'."</tr>\n".
                   3274: 	"</table>\n";
                   3275:     return $table;
1.1       raeburn  3276: }
                   3277: 
1.32      raeburn  3278: sub add_group_folder {
                   3279:     my ($cdom,$cnum,$now,$groupname,$action,$description,$tools,$groupinfo,
                   3280:         $gpterm,$ucgpterm,$crstype) = @_;
                   3281:     if ($cdom eq '' || $cnum eq '') {
                   3282:         return &mt('Error: invalid course domain or number - group folder creation failed');  
                   3283:     }
                   3284:     my ($outcome,$allgrpsmap,$grpmap,$boardsmap,$grppage);
                   3285:     my $navmap = Apache::lonnavmaps::navmap->new();
                   3286:     my $crspath = '/uploaded/'.$cdom.'/'.$cnum.'/';
                   3287:     $allgrpsmap = $crspath.'default_0.sequence';
                   3288:     my $topmap = $navmap->getResourceByUrl($allgrpsmap);
                   3289:     undef($navmap);
                   3290:     if ($action eq 'create') {
                   3291:     # check if default_0.sequence exists.
                   3292:         if (!$topmap) {
                   3293:             my $grpstitle = &mt('[_1] [_2]',$crstype,$ucgpterm);
                   3294:             my $topmap_url = '/'.$env{'course.'.$env{'request.course.id'}.'.url'};
                   3295:             $topmap_url =~ s|/+|/|g;
                   3296:             if ($topmap_url =~ m|^/uploaded|) {
                   3297:                 $outcome = &map_updater($cdom,$cnum,'default_0.sequence',
                   3298:                                         'toplevelgroup',$grpstitle,$topmap_url);
                   3299:                 if ($outcome ne 'ok') {
                   3300:                     return $outcome;
                   3301:                 }
                   3302:             } else {
                   3303:                 $outcome = &mt('Non-standard course - group folder not added.');
                   3304:                 return $outcome;
                   3305:             }
                   3306:         }
                   3307:         my $grpfolder = &mt('[_1] Folder -',$ucgpterm,).$description;
                   3308:         $grppage='/adm/'.$cdom.'/'.$cnum.'/'.$groupname.'/grppg';
                   3309:         my $grptitle = &mt('Group homepage').' - '.$description;
                   3310:         my ($seqid,$discussions,$disctitle);
                   3311:         my $outcome = &map_updater($cdom,$cnum,'default_'.$now.'.sequence',
                   3312:                                    'grpseq',$grpfolder,$allgrpsmap,$grppage,
                   3313:                                    $grptitle);
                   3314:         if ($outcome ne 'ok') {
                   3315:             return $outcome;
                   3316:         }
                   3317:         my $pageout = &create_homepage($cdom,$cnum,$groupname,$groupinfo,
                   3318:                                        $tools,$gpterm,$ucgpterm,$now);
                   3319:         # Link to folder for bulletin boards
                   3320:         $grpmap = $crspath.'default_'.$now.'.sequence';
                   3321:         if (grep/^discussion$/,@{$tools}) {
                   3322:             $seqid = $now + 1;
                   3323:             $disctitle = &mt('Discussion Boards');
                   3324:             my $outcome = &map_updater($cdom,$cnum,'default_'.$seqid.
                   3325:                                        '.sequence','bbseq',$disctitle,$grpmap);
                   3326:             if ($outcome ne 'ok') {
                   3327:                 return $outcome;
                   3328:             }
                   3329:             $boardsmap = $crspath.'default_'.$seqid.'.sequence';
                   3330:         }
                   3331:     } else {
                   3332:         #modify group folder if status of discussions tools is changed
                   3333:     }
                   3334:     my ($furl,$ferr)= &Apache::lonuserstate::readmap($cdom.'/'.$cnum);
1.33      raeburn  3335:     $navmap = Apache::lonnavmaps::navmap->new();
1.32      raeburn  3336:     # modify parameters
                   3337:     my $parm_result;
                   3338:     if ($action eq 'create') {
                   3339:         if ($allgrpsmap) { 
                   3340:             $parm_result .= &parm_setter($navmap,$cdom,$allgrpsmap,$groupname);
                   3341:         }
                   3342:         if ($grpmap) {
                   3343:             $parm_result .= &parm_setter($navmap,$cdom,$grpmap,$groupname);
                   3344:         }
                   3345:         if ($grppage) {
                   3346:             $parm_result .= &parm_setter($navmap,$cdom,$grppage,$groupname);
                   3347:         }
                   3348:         if ($boardsmap) {
                   3349:             $parm_result .= &parm_setter($navmap,$cdom,$boardsmap,$groupname);
                   3350:         }
                   3351:     }
                   3352:     if ($parm_result) {
                   3353:         return $parm_result;
                   3354:     } else {
                   3355:         return 'ok';
                   3356:     }
                   3357: }
                   3358: 
                   3359: sub map_updater {
                   3360:     my ($cdom,$cnum,$newfile,$itemname,$itemtitle,$parentmap,$startsrc,
                   3361:         $starttitle,$endsrc,$endtitle) = @_;
                   3362:     my $outcome;
                   3363:     $env{'form.'.$itemname} = &new_map($startsrc,$starttitle,$endsrc,
                   3364:                                        $endtitle);
                   3365:     my $newmapurl=&Apache::lonnet::finishuserfileupload($cnum,$cdom,$itemname,
                   3366:                                                         $newfile);
                   3367:     if ($newmapurl !~ m|^/uploaded|) {
1.37      raeburn  3368:         $outcome = &mt('Error uploading new folder.')." ($newfile): $newmapurl".'<br />';
1.32      raeburn  3369:         return $outcome;
                   3370:     } 
                   3371:     my ($errtext,$fatal)=&Apache::lonratedt::mapread($parentmap);
                   3372:     if ($fatal) {
1.37      raeburn  3373:         $outcome = &mt('Error reading contents of parent folder')." ($parentmap): $errtext".'<br />';
1.32      raeburn  3374:         return $outcome;
                   3375:     } else {
                   3376:         my $newidx=&Apache::lonratedt::getresidx($newmapurl);
                   3377:         $Apache::lonratedt::resources[$newidx] = $itemtitle.':'.$newmapurl.
                   3378:                                                  ':false:normal:res';
                   3379:         $Apache::lonratedt::order[1+$#Apache::lonratedt::order]=$newidx;
                   3380:         my ($outtext,$errtext) = &Apache::lonratedt::storemap($parentmap,1);
                   3381:         if ($errtext) {
1.37      raeburn  3382:             $outcome = &mt('Error storing updated parent folder')." ($parentmap):  $errtext".'<br />';
1.32      raeburn  3383:             return $outcome;
                   3384:         }
                   3385:     }
                   3386:     return 'ok';
                   3387: }
                   3388: 
                   3389: sub new_map {
                   3390:     my ($startsrc,$starttitle,$endsrc,$endtitle) = @_;
                   3391:     my $newmapstr = '
                   3392: <map>
                   3393:  <resource id="1" src="'.$startsrc.'" type="start" title="'.$starttitle.'"></resource>
                   3394:  <link from="1" to="2" index="1"></link>
                   3395:  <resource id="2" src="'.$endsrc.'" type="finish" title="'.$endtitle.'"></resource>
                   3396: </map>
                   3397: ';
                   3398:     return $newmapstr;
                   3399: }
                   3400: 
                   3401: sub parm_setter {
                   3402:     my ($navmap,$cdom,$url,$groupname) = @_;
1.37      raeburn  3403:     my $allresults;
1.32      raeburn  3404:     my %hide_settings = (
                   3405:                            'course' =>  {
                   3406:                                           'num' => 13,
                   3407:                                           'set' => 'yes',
                   3408:                                         },
                   3409:                             'group' =>  {
                   3410:                                           'num' => 5,
                   3411:                                           'set' => 'no',
                   3412:                                           'extra' => $groupname,
                   3413:                                         },
                   3414:                         );
                   3415:     my $res = $navmap->getResourceByUrl($url);
                   3416:     my $symb = $res->symb();
                   3417:     foreach my $level (keys(%hide_settings)) {
1.37      raeburn  3418:         my $parmresult =  &Apache::lonparmset::storeparm_by_symb($symb,
1.32      raeburn  3419:                                                  '0_hiddenresource',
                   3420:                                                  $hide_settings{$level}{'num'},
                   3421:                                                  $hide_settings{$level}{'set'},
                   3422:                                                  'string_yesno',undef,$cdom,
                   3423:                                                  undef,undef,
                   3424:                                                  $hide_settings{$level}{'extra'});
1.37      raeburn  3425:         if ($parmresult) {
                   3426:             $allresults .= $level.': '.$parmresult;
                   3427:         }
1.32      raeburn  3428:     }
1.37      raeburn  3429:     return $allresults;
1.32      raeburn  3430: }
                   3431: 
1.3       raeburn  3432: sub create_homepage {
1.32      raeburn  3433:     my ($cdom,$cnum,$name,$groupinfo,$tools,$gpterm,$ucgpterm,$now) = @_;
1.3       raeburn  3434:     my $functionality = join(',',@{$tools});
1.24      www      3435:     my $content = &unescape($$groupinfo{description});
1.3       raeburn  3436:     $content=~s/\s+$//s;
                   3437:     $content=~s/^\s+//s;
                   3438:     $content=~s/\<br\s*\/*\>$//s;
                   3439:     $content=&Apache::lonfeedback::clear_out_html($content,1);
                   3440: 
                   3441:     my %pageinfo = (
1.29      raeburn  3442:                      'aaa_title' => "$ucgpterm: $name",
1.3       raeburn  3443:                      'abb_links' => $functionality,
                   3444:                      'bbb_content' => $content,
                   3445:                      'ccc_webreferences' => '',
1.32      raeburn  3446:                      'uploaded.lastmodified' => $now,
1.3       raeburn  3447:                    );
                   3448:    my $putresult = &Apache::lonnet::put('grppage_'.$name,\%pageinfo,$cdom,$cnum);
                   3449:    return $putresult;
1.1       raeburn  3450: }
                   3451: 
1.5       raeburn  3452: sub check_uncheck_tools {
                   3453:     my ($r,$available) = @_;
                   3454:     if (ref($available) eq 'ARRAY') { 
                   3455:         $r->print('
                   3456: <script type="text/javascript">
                   3457: function checkAllTools(formname) {
                   3458: ');
                   3459:         foreach my $tool (@{$available}) {
                   3460:             $r->print('  checkAll(formname.user_'.$tool.');'."\n");
                   3461:         }
                   3462:         $r->print(' checkAll(formname.togglefunc);'."\n");
                   3463:         $r->print('
                   3464: }
                   3465: function uncheckAllTools(formname) {
                   3466: ');
                   3467:         foreach my $tool (@{$available}) {
                   3468:             $r->print('  uncheckAll(formname.user_'.$tool.');'."\n");
                   3469:         }
                   3470:         $r->print(' uncheckAll(formname.togglefunc);'."\n");
                   3471:         $r->print('
                   3472: }
                   3473: function toggleTools(field,caller) {
                   3474:      if (caller.checked) {
                   3475:          checkAll(field);
                   3476:      } else {
                   3477:          uncheckAll(field);
                   3478:      }
                   3479:      return;   
                   3480: }
                   3481: </script>
                   3482: ');
                   3483:     }
                   3484:     return;
                   3485: }
                   3486: 
                   3487: sub validate_groupname {
1.29      raeburn  3488:     my ($groupname,$action,$cdom,$cnum,$gpterm,$ucgpterm,$crstype) = @_;
1.16      albertel 3489:     my %sectioncount = &Apache::loncommon::get_sections($cdom,$cnum);
1.17      raeburn  3490:     my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
1.15      albertel 3491: 
1.5       raeburn  3492:     my %lt = &Apache::lonlocal::texthash (
1.29      raeburn  3493:                       igna => "Invalid $gpterm name",
                   3494:                       tgne => "The $gpterm name entered ",
                   3495:                       grna => "$ucgpterm names and section names used in a ".
                   3496:                                "$crstype must be unique.",
                   3497:                       isno => "is not a valid name.",
                   3498:                       gnmo => "$ucgpterm names may only contain letters, ". 
                   3499:                               "numbers or underscores.",
                   3500:                       cnnb => "can not be used as it is the name of ",
                   3501:                       inth => " in this $crstype", 
                   3502:                       thgr => "- does not correspond to the name of an ".
                   3503:                               "existing $gpterm",    
1.5       raeburn  3504:     );
1.15      albertel 3505: 
1.42      albertel 3506:     my $exitmsg = '<span class="LC_error">'.$lt{'igna'}.'</span><br /><br />'.
                   3507: 	$lt{'tgne'}.' "'.$groupname.'" ';
1.5       raeburn  3508:     my $dupmsg = $lt{'grna'};
                   3509:     my $earlyout;
                   3510:     if (($groupname eq '') || ($groupname =~ /\W/)) {
                   3511:         $earlyout = $exitmsg.$lt{'isno'}.'<br />'.$lt{'gnmo'};
                   3512:         return $earlyout;
                   3513:     }
1.16      albertel 3514:     if (exists($sectioncount{$groupname})) {
                   3515: 	return $exitmsg.$lt{'cnnb'}.&mt('a section').$lt{'inth'}.
                   3516: 	    '<br />'.$lt{'grna'};
1.5       raeburn  3517:     }
1.15      albertel 3518:     if ($action eq 'create' 
                   3519: 	&& exists($curr_groups{$groupname})) {
                   3520: 
1.29      raeburn  3521: 	return $exitmsg.$lt{'cnnb'}.&mt('an existing [_1]',$gpterm).
1.15      albertel 3522: 	    $lt{'inth'}.'<br />'.$lt{'grna'};
                   3523: 
1.5       raeburn  3524:     } elsif ($action eq 'modify') {
                   3525:         unless(exists($curr_groups{$groupname})) {
1.29      raeburn  3526:             $earlyout = &mt('[_1] name:',$ucgpterm).' '.$groupname.$lt{'thgr'}.
                   3527:                         $lt{'inth'};
1.5       raeburn  3528:             return $earlyout;
                   3529:         }
                   3530:     }
                   3531:     return;
                   3532: }
                   3533: 
                   3534: sub topic_bar {
1.40      albertel 3535:     my ($r,$imgnum,$title) = @_;
1.5       raeburn  3536:     $r->print('
1.40      albertel 3537: <div class="LC_topic_bar">
1.45    ! albertel 3538:     <img alt="'.&mt('Step [_1]',$imgnum).
        !          3539: 	      '"src="/res/adm/pages/bl_step'.$imgnum.'.gif" />&nbsp;
        !          3540:     <span>'.$title.'</span>
1.40      albertel 3541: </div>
1.5       raeburn  3542: ');
                   3543:     return;
                   3544: }
                   3545: 
                   3546: sub check_changes {
                   3547:     my ($member_changes,$memchg) = @_;
                   3548:     my %exclusions;
                   3549:     @{$exclusions{'changefunc'}} = ('expire');
                   3550:     @{$exclusions{'changepriv'}} = ('expire','changefunc');
                   3551: 
                   3552:     foreach my $change (@{$member_changes}) {
1.6       raeburn  3553:         if ($change eq 'deletion') {
1.5       raeburn  3554:             next;
                   3555:         }
1.6       raeburn  3556:         my @checks = ('deletion');
1.5       raeburn  3557:         if (exists($exclusions{$change})) {
                   3558:             push(@checks,@{$exclusions{$change}});
                   3559:         }
                   3560:         my @temp = ();
                   3561:         foreach my $item (@{$$memchg{$change}}) {
                   3562:             my $match = 0;
                   3563:             foreach my $check (@checks) {
1.6       raeburn  3564:                 if (defined($$memchg{$check})) { 
                   3565:                     if (ref(@{$$memchg{$check}}) eq 'ARRAY') {
                   3566:                         if (@{$$memchg{$check}} > 0) {
                   3567:                             if (grep/^$item$/,@{$$memchg{$check}}) {
                   3568:                                 $match = 1;
                   3569:                                 last;
                   3570:                             }
                   3571:                         }
1.5       raeburn  3572:                     }
                   3573:                 }
                   3574:             }
                   3575:             if ($match) {
                   3576:                 next;
                   3577:             }
                   3578:             push(@temp,$item);
                   3579:         }
                   3580:         @{$$memchg{$change}} = @temp;
                   3581:     }
                   3582: }
1.3       raeburn  3583: 
1.1       raeburn  3584: 1;

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.