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

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

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.