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