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