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