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