Annotation of loncom/interface/lonuserutils.pm, revision 1.34
1.1 raeburn 1: # The LearningOnline Network with CAPA
2: # Utility functions for managing LON-CAPA user accounts
3: #
1.34 ! raeburn 4: # $Id: lonuserutils.pm,v 1.33 2007/12/24 05:26:31 raeburn Exp $
1.1 raeburn 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA#
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: #
28: ###############################################################
29: ###############################################################
30:
31: package Apache::lonuserutils;
32:
33: use strict;
34: use Apache::lonnet;
35: use Apache::loncommon();
36: use Apache::lonhtmlcommon;
37: use Apache::lonlocal;
1.8 raeburn 38: use Apache::longroup;
39: use LONCAPA qw(:DEFAULT :match);
1.1 raeburn 40:
41: ###############################################################
42: ###############################################################
43: # Drop student from all sections of a course, except optional $csec
44: sub modifystudent {
45: my ($udom,$unam,$courseid,$csec,$desiredhost)=@_;
46: # if $csec is undefined, drop the student from all the courses matching
47: # this one. If $csec is defined, drop them from all other sections of
48: # this course and add them to section $csec
1.17 raeburn 49: my ($cnum,$cdom) = &get_course_identity($courseid);
1.1 raeburn 50: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
51: my ($tmp) = keys(%roles);
52: # Bail out if we were unable to get the students roles
53: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
54: # Go through the roles looking for enrollment in this course
55: my $result = '';
56: foreach my $course (keys(%roles)) {
57: if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) {
58: # We are in this course
59: my $section=$1;
60: $section='' if ($course eq "/$cdom/$cnum".'_st');
61: if (defined($csec) && $section eq $csec) {
62: $result .= 'ok:';
63: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
64: my (undef,$end,$start)=split(/\_/,$roles{$course});
65: my $now=time;
66: # if this is an active role
67: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
68: my $reply=&Apache::lonnet::modifystudent
69: # dom name id mode pass f m l g
70: ($udom,$unam,'', '', '',undef,undef,undef,undef,
1.22 raeburn 71: $section,time,undef,undef,$desiredhost,'','manual',
72: '',$courseid);
1.1 raeburn 73: $result .= $reply.':';
74: }
75: }
76: }
77: }
78: if ($result eq '') {
79: $result = 'Unable to find section for this student';
80: } else {
81: $result =~ s/(ok:)+/ok/g;
82: }
83: return $result;
84: }
85:
86: sub modifyuserrole {
87: my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass,
88: $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role,
1.5 raeburn 89: $end,$start,$checkid) = @_;
90: my ($scope,$userresult,$authresult,$roleresult,$idresult);
1.1 raeburn 91: if ($setting eq 'course' || $context eq 'course') {
92: $scope = '/'.$cid;
93: $scope =~ s/\_/\//g;
94: if ($role ne 'cc' && $sec ne '') {
95: $scope .='/'.$sec;
96: }
1.5 raeburn 97: } elsif ($context eq 'domain') {
1.1 raeburn 98: $scope = '/'.$env{'request.role.domain'}.'/';
1.13 raeburn 99: } elsif ($context eq 'author') {
1.1 raeburn 100: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
101: }
102: if ($context eq 'domain') {
103: my $uhome = &Apache::lonnet::homeserver($uname,$udom);
104: if ($uhome ne 'no_host') {
1.5 raeburn 105: if (($changeauth eq 'Yes') && (&Apache::lonnet::allowed('mau',$udom))) {
1.1 raeburn 106: if ((($umode =~ /^krb4|krb5|internal$/) && $upass ne '') ||
107: ($umode eq 'localauth')) {
108: $authresult = &Apache::lonnet::modifyuserauth($udom,$uname,$umode,$upass);
109: }
110: }
1.5 raeburn 111: if (($forceid) && (&Apache::lonnet::allowed('mau',$udom)) &&
112: ($env{'form.recurseid'}) && ($checkid)) {
113: my %userupdate = (
114: lastname => $last,
115: middlename => $middle,
116: firstname => $first,
117: generation => $gene,
118: id => $uid,
119: );
120: $idresult = &propagate_id_change($uname,$udom,\%userupdate);
121: }
1.1 raeburn 122: }
123: }
124: $userresult =
125: &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first,
126: $middle,$last,$gene,$forceid,$desiredhome,
127: $email,$role,$start,$end);
128: if ($userresult eq 'ok') {
1.5 raeburn 129: if ($role ne '') {
1.22 raeburn 130: $role =~ s/_/\//g;
1.1 raeburn 131: $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope,
132: $role,$end,$start);
133: }
134: }
1.5 raeburn 135: return ($userresult,$authresult,$roleresult,$idresult);
1.1 raeburn 136: }
137:
1.5 raeburn 138: sub propagate_id_change {
139: my ($uname,$udom,$user) = @_;
1.12 raeburn 140: my (@types,@roles);
1.5 raeburn 141: @types = ('active','future');
142: @roles = ('st');
143: my $idresult;
144: my %roleshash = &Apache::lonnet::get_my_roles($uname,
1.12 raeburn 145: $udom,'userroles',\@types,\@roles);
146: my %args = (
147: one_time => 1,
148: );
1.5 raeburn 149: foreach my $item (keys(%roleshash)) {
1.22 raeburn 150: my ($cnum,$cdom,$role) = split(/:/,$item,-1);
1.5 raeburn 151: my ($start,$end) = split(/:/,$roleshash{$item});
152: if (&Apache::lonnet::is_course($cdom,$cnum)) {
1.12 raeburn 153: my $result = &update_classlist($cdom,$cnum,$udom,$uname,$user);
154: my %coursehash =
155: &Apache::lonnet::coursedescription($cdom.'_'.$cnum,\%args);
156: my $cdesc = $coursehash{'description'};
157: if ($cdesc eq '') {
158: $cdesc = $cdom.'_'.$cnum;
159: }
1.5 raeburn 160: if ($result eq 'ok') {
1.12 raeburn 161: $idresult .= &mt('Classlist update for "[_1]" in "[_2]".',$uname.':'.$udom,$cdesc).'<br />'."\n";
1.5 raeburn 162: } else {
1.12 raeburn 163: $idresult .= &mt('Error: "[_1]" during classlist update for "[_2]" in "[_3]".',$result,$uname.':'.$udom,$cdesc).'<br />'."\n";
1.5 raeburn 164: }
165: }
166: }
167: return $idresult;
168: }
169:
170: sub update_classlist {
171: my ($cdom,$cnum,$udom,$uname,$user) = @_;
1.6 albertel 172: my ($uid,$classlistentry);
1.5 raeburn 173: my $fullname =
174: &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'},
175: $user->{'lastname'},$user->{'generation'},
176: 'lastname');
177: my %classhash = &Apache::lonnet::get('classlist',[$uname.':'.$udom],
178: $cdom,$cnum);
179: my @classinfo = split(/:/,$classhash{$uname.':'.$udom});
180: my $ididx=&Apache::loncoursedata::CL_ID() - 2;
181: my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2;
182: for (my $i=0; $i<@classinfo; $i++) {
183: if ($i == $ididx) {
184: if (defined($user->{'id'})) {
185: $classlistentry .= $user->{'id'}.':';
186: } else {
187: $classlistentry .= $classinfo[$i].':';
188: }
189: } elsif ($i == $nameidx) {
190: $classlistentry .= $fullname.':';
191: } else {
192: $classlistentry .= $classinfo[$i].':';
193: }
194: }
195: $classlistentry =~ s/:$//;
196: my $reply=&Apache::lonnet::cput('classlist',
197: {"$uname:$udom" => $classlistentry},
198: $cdom,$cnum);
199: if (($reply eq 'ok') || ($reply eq 'delayed')) {
200: return 'ok';
201: } else {
202: return 'error: '.$reply;
203: }
204: }
205:
206:
1.1 raeburn 207: ###############################################################
208: ###############################################################
1.2 raeburn 209: # build a role type and role selection form
210: sub domain_roles_select {
211: # Set up the role type and role selection boxes when in
212: # domain context
213: #
214: # Role types
1.13 raeburn 215: my @roletypes = ('domain','author','course');
1.2 raeburn 216: my %lt = &role_type_names();
1.1 raeburn 217: #
218: # build up the menu information to be passed to
219: # &Apache::loncommon::linked_select_forms
220: my %select_menus;
1.2 raeburn 221: if ($env{'form.roletype'} eq '') {
222: $env{'form.roletype'} = 'domain';
223: }
224: foreach my $roletype (@roletypes) {
1.1 raeburn 225: # set up the text for this domain
1.2 raeburn 226: $select_menus{$roletype}->{'text'}= $lt{$roletype};
1.1 raeburn 227: # we want a choice of 'default' as the default in the second menu
1.2 raeburn 228: if ($env{'form.roletype'} ne '') {
229: $select_menus{$roletype}->{'default'} = $env{'form.showrole'};
230: } else {
231: $select_menus{$roletype}->{'default'} = 'Any';
232: }
1.1 raeburn 233: # Now build up the other items in the second menu
1.2 raeburn 234: my @roles;
235: if ($roletype eq 'domain') {
236: @roles = &domain_roles();
1.13 raeburn 237: } elsif ($roletype eq 'author') {
1.2 raeburn 238: @roles = &construction_space_roles();
239: } else {
1.17 raeburn 240: my $custom = 1;
241: @roles = &course_roles('domain',undef,$custom);
1.1 raeburn 242: }
1.2 raeburn 243: my $order = ['Any',@roles];
244: $select_menus{$roletype}->{'order'} = $order;
245: foreach my $role (@roles) {
1.5 raeburn 246: if ($role eq 'cr') {
247: $select_menus{$roletype}->{'select2'}->{$role} =
248: &mt('Custom role');
249: } else {
250: $select_menus{$roletype}->{'select2'}->{$role} =
251: &Apache::lonnet::plaintext($role);
252: }
1.2 raeburn 253: }
254: $select_menus{$roletype}->{'select2'}->{'Any'} = &mt('Any');
1.1 raeburn 255: }
1.2 raeburn 256: my $result = &Apache::loncommon::linked_select_forms
257: ('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
1.13 raeburn 258: 'roletype','showrole',\%select_menus,['domain','author','course']);
1.1 raeburn 259: return $result;
260: }
261:
262: ###############################################################
263: ###############################################################
264: sub hidden_input {
265: my ($name,$value) = @_;
266: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
267: }
268:
269: sub print_upload_manager_header {
1.22 raeburn 270: my ($r,$datatoken,$distotal,$krbdefdom,$context,$permission)=@_;
1.1 raeburn 271: my $javascript;
272: #
273: if (! exists($env{'form.upfile_associate'})) {
274: $env{'form.upfile_associate'} = 'forward';
275: }
276: if ($env{'form.associate'} eq 'Reverse Association') {
277: if ( $env{'form.upfile_associate'} ne 'reverse' ) {
278: $env{'form.upfile_associate'} = 'reverse';
279: } else {
280: $env{'form.upfile_associate'} = 'forward';
281: }
282: }
283: if ($env{'form.upfile_associate'} eq 'reverse') {
284: $javascript=&upload_manager_javascript_reverse_associate();
285: } else {
286: $javascript=&upload_manager_javascript_forward_associate();
287: }
288: #
289: # Deal with restored settings
290: my $password_choice = '';
291: if (exists($env{'form.ipwd_choice'}) &&
292: $env{'form.ipwd_choice'} ne '') {
293: # If a column was specified for password, assume it is for an
294: # internal password. This is a bug waiting to be filed (could be
295: # local or krb auth instead of internal) but I do not have the
296: # time to mess around with this now.
297: $password_choice = 'int';
298: }
299: #
1.22 raeburn 300: my $groupslist;
301: if ($context eq 'course') {
302: $groupslist = &get_groupslist();
303: }
1.1 raeburn 304: my $javascript_validations =
1.22 raeburn 305: &javascript_validations('upload',$krbdefdom,$password_choice,undef,
306: $env{'request.role.domain'},$context,
1.33 raeburn 307: $groupslist);
1.1 raeburn 308: my $checked=(($env{'form.noFirstLine'})?' checked="checked" ':'');
309: $r->print(&mt('Total number of records found in file: <b>[_1]</b>.',$distotal).
310: "<br />\n");
311: $r->print('<div class="LC_left_float"><h3>'.
312: &mt('Identify fields in uploaded list')."</h3>\n");
313: $r->print(&mt('Enter as many fields as you can.<br /> The system will inform you and bring you back to this page, <br /> if the data selected are insufficient to add users.')."<br />\n");
314: $r->print(&hidden_input('action','upload').
315: &hidden_input('state','got_file').
316: &hidden_input('associate','').
317: &hidden_input('datatoken',$datatoken).
318: &hidden_input('fileupload',$env{'form.fileupload'}).
319: &hidden_input('upfiletype',$env{'form.upfiletype'}).
320: &hidden_input('upfile_associate',$env{'form.upfile_associate'}));
321: $r->print('<br /><input type="button" value="Reverse Association" '.
322: 'name="'.&mt('Reverse Association').'" '.
323: 'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />');
324: $r->print('<label><input type="checkbox" name="noFirstLine"'.$checked.'/>'.
325: &mt('Ignore First Line').'</label>');
326: $r->print("<br /><br />\n".
327: '<script type="text/javascript" language="Javascript">'."\n".
328: $javascript."\n".$javascript_validations.'</script>');
329: }
330:
331: ###############################################################
332: ###############################################################
333: sub javascript_validations {
1.22 raeburn 334: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield,$domain,
1.33 raeburn 335: $context,$groupslist)=@_;
1.22 raeburn 336:
337: my %param = (
338: kerb_def_dom => $krbdefdom,
339: curr_authtype => $curr_authtype,
340: );
341: if ($mode eq 'createuser') {
342: $param{'formname'} = 'cu';
343: } elsif ($mode eq 'upload') {
344: $param{'formname'} = 'studentform';
345: } elsif ($mode eq 'singlestudent') {
346: $param{'formname'} = 'cu';
1.1 raeburn 347: } elsif ($mode eq 'createcourse') {
1.22 raeburn 348: $param{'formname'} = 'ccrs';
1.1 raeburn 349: } elsif ($mode eq 'modifycourse') {
1.22 raeburn 350: $param{'formname'} = 'cmod';
351: $param{'mode'} = 'modifycourse',
352: $param{'curr_autharg'} = $curr_authfield;
353: }
354:
355: my ($setsection_call,$setsections_js);
356: my $finish = " vf.submit();\n";
357: if ($mode eq 'upload') {
358: if (($context eq 'course') || ($context eq 'domain')) {
359: if ($context eq 'course') {
360: if ($env{'request.course.sec'} eq '') {
361: $setsection_call = 'setSections(document.'.$param{'formname'}.');';
362: $setsections_js =
363: &setsections_javascript($param{'formname'},$groupslist,
364: $mode);
365: } else {
366: $setsection_call = "'ok'";
367: }
368: } elsif ($context eq 'domain') {
369: $setsection_call = 'setCourse()';
370: $setsections_js = &dc_setcourse_js($param{'formname'},$mode);
371: }
372: $finish = " var checkSec = $setsection_call\n".
373: " if (checkSec == 'ok') {\n".
374: " vf.submit();\n".
375: " }\n";
376: }
1.1 raeburn 377: }
1.22 raeburn 378: my $authheader = &Apache::loncommon::authform_header(%param);
1.1 raeburn 379:
380: my %alert = &Apache::lonlocal::texthash
381: (username => 'You need to specify the username field.',
382: authen => 'You must choose an authentication type.',
383: krb => 'You need to specify the Kerberos domain.',
384: ipass => 'You need to specify the initial password.',
385: name => 'The optional name field was not specified.',
386: snum => 'The optional ID number field was not specified.',
387: section => 'The optional section field was not specified.',
388: email => 'The optional email address field was not specified.',
389: role => 'The optional role field was not specified.',
390: continue => 'Continue adding users?',
391: );
392:
393: my $function_name =(<<END);
1.22 raeburn 394: $setsections_js
395:
1.1 raeburn 396: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail) {
397: END
398: my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
399: my $auth_checks;
400: if ($mode eq 'createcourse') {
401: $auth_checks .= (<<END);
402: if (vf.autoadds[0].checked == true) {
403: if (current.radiovalue == null || current.radiovalue == 'nochange') {
404: alert('$alert{'authen'}');
405: return;
406: }
407: }
408: END
409: } else {
410: $auth_checks .= (<<END);
411: var foundatype=0;
412: if (founduname==0) {
413: alert('$alert{'username'}');
414: return;
415: }
416:
417: END
418: if ($authnum > 1) {
419: $auth_checks .= (<<END);
420: if (current.radiovalue == null || current.radiovalue == '' || current.radiovalue == 'nochange') {
421: // They did not check any of the login radiobuttons.
422: alert('$alert{'authen'}');
423: return;
424: }
425: END
426: }
427: }
428: if ($mode eq 'createcourse') {
429: $auth_checks .= "
430: if ( (vf.autoadds[0].checked == true) &&
431: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
432: ";
433: } elsif ($mode eq 'modifycourse') {
434: $auth_checks .= "
435: if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
436: ";
437: }
438: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
439: $auth_checks .= (<<END);
440: var alertmsg = '';
441: switch (current.radiovalue) {
442: case 'krb':
443: alertmsg = '$alert{'krb'}';
444: break;
445: default:
446: alertmsg = '';
447: }
448: if (alertmsg != '') {
449: alert(alertmsg);
450: return;
451: }
452: }
453: END
454: } else {
455: $auth_checks .= (<<END);
456: foundatype=1;
457: if (current.argfield == null || current.argfield == '') {
458: var alertmsg = '';
459: switch (current.value) {
460: case 'krb':
461: alertmsg = '$alert{'krb'}';
462: break;
463: case 'loc':
464: case 'fsys':
465: alertmsg = '$alert{'ipass'}';
466: break;
467: case 'fsys':
468: alertmsg = '';
469: break;
470: default:
471: alertmsg = '';
472: }
473: if (alertmsg != '') {
474: alert(alertmsg);
475: return;
476: }
477: }
478: END
479: }
480: my $section_checks;
481: my $optional_checks = '';
482: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
483: $optional_checks = (<<END);
484: vf.submit();
485: }
486: END
487: } else {
488: $section_checks = §ion_check_js();
489: $optional_checks = (<<END);
490: var message='';
491: if (foundname==0) {
492: message='$alert{'name'}';
493: }
494: if (foundid==0) {
495: if (message!='') {
496: message+='\\n';
497: }
498: message+='$alert{'snum'}';
499: }
500: if (foundsec==0) {
501: if (message!='') {
502: message+='\\n';
503: }
504: }
505: if (foundemail==0) {
506: if (message!='') {
507: message+='\\n';
508: }
509: message+='$alert{'email'}';
510: }
511: if (message!='') {
512: message+= '\\n$alert{'continue'}';
513: if (confirm(message)) {
514: vf.state.value='enrolling';
1.22 raeburn 515: $finish
1.1 raeburn 516: }
517: } else {
518: vf.state.value='enrolling';
1.22 raeburn 519: $finish
1.1 raeburn 520: }
521: }
522: END
523: }
524: my $result = $function_name;
1.22 raeburn 525: if ( ($mode eq 'upload') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1.1 raeburn 526: $result .= $auth_checks;
527: }
528: $result .= $optional_checks."\n".$section_checks;
1.22 raeburn 529: if ( ($mode eq 'upload') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1.1 raeburn 530: $result .= $authheader;
531: }
532: return $result;
533: }
534: ###############################################################
535: ###############################################################
536: sub upload_manager_javascript_forward_associate {
537: return(<<ENDPICK);
538: function verify(vf,sec_caller) {
539: var founduname=0;
540: var foundpwd=0;
541: var foundname=0;
542: var foundid=0;
543: var foundsec=0;
544: var foundemail=0;
545: var foundrole=0;
546: var tw;
547: for (i=0;i<=vf.nfields.value;i++) {
548: tw=eval('vf.f'+i+'.selectedIndex');
549: if (tw==1) { founduname=1; }
550: if ((tw>=2) && (tw<=6)) { foundname=1; }
551: if (tw==7) { foundid=1; }
552: if (tw==8) { foundsec=1; }
553: if (tw==9) { foundpwd=1; }
554: if (tw==10) { foundemail=1; }
555: if (tw==11) { foundrole=1; }
556: }
557: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole);
558: }
559:
560: //
561: // vf = this.form
562: // tf = column number
563: //
564: // values of nw
565: //
566: // 0 = none
567: // 1 = username
568: // 2 = names (lastname, firstnames)
569: // 3 = fname (firstname)
570: // 4 = mname (middlename)
571: // 5 = lname (lastname)
572: // 6 = gen (generation)
573: // 7 = id
574: // 8 = section
575: // 9 = ipwd (password)
576: // 10 = email address
577: // 11 = role
578:
579: function flip(vf,tf) {
580: var nw=eval('vf.f'+tf+'.selectedIndex');
581: var i;
582: // make sure no other columns are labeled the same as this one
583: for (i=0;i<=vf.nfields.value;i++) {
584: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
585: eval('vf.f'+i+'.selectedIndex=0;')
586: }
587: }
588: // If we set this to 'lastname, firstnames', clear out all the ones
589: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
590: if (nw==2) {
591: for (i=0;i<=vf.nfields.value;i++) {
592: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
593: (eval('vf.f'+i+'.selectedIndex')<=6)) {
594: eval('vf.f'+i+'.selectedIndex=0;')
595: }
596: }
597: }
598: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
599: // clear out any that are set to 'lastname, firstnames' (2)
600: if ((nw>=3) && (nw<=6)) {
601: for (i=0;i<=vf.nfields.value;i++) {
602: if (eval('vf.f'+i+'.selectedIndex')==2) {
603: eval('vf.f'+i+'.selectedIndex=0;')
604: }
605: }
606: }
607: // If we set the password, make the password form below correspond to
608: // the new value.
609: if (nw==9) {
610: changed_radio('int',document.studentform);
611: set_auth_radio_buttons('int',document.studentform);
612: vf.intarg.value='';
613: vf.krbarg.value='';
614: vf.locarg.value='';
615: }
616: }
617:
618: function clearpwd(vf) {
619: var i;
620: for (i=0;i<=vf.nfields.value;i++) {
621: if (eval('vf.f'+i+'.selectedIndex')==9) {
622: eval('vf.f'+i+'.selectedIndex=0;')
623: }
624: }
625: }
626:
627: ENDPICK
628: }
629:
630: ###############################################################
631: ###############################################################
632: sub upload_manager_javascript_reverse_associate {
633: return(<<ENDPICK);
634: function verify(vf,sec_caller) {
635: var founduname=0;
636: var foundpwd=0;
637: var foundname=0;
638: var foundid=0;
639: var foundsec=0;
640: var foundrole=0;
641: var tw;
642: for (i=0;i<=vf.nfields.value;i++) {
643: tw=eval('vf.f'+i+'.selectedIndex');
644: if (i==0 && tw!=0) { founduname=1; }
645: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
646: if (i==6 && tw!=0) { foundid=1; }
647: if (i==7 && tw!=0) { foundsec=1; }
648: if (i==8 && tw!=0) { foundpwd=1; }
649: if (i==9 && tw!=0) { foundrole=1; }
650: }
651: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole);
652: }
653:
654: function flip(vf,tf) {
655: var nw=eval('vf.f'+tf+'.selectedIndex');
656: var i;
657: // picked the all one name field, reset the other name ones to blank
658: if (tf==1 && nw!=0) {
659: for (i=2;i<=5;i++) {
660: eval('vf.f'+i+'.selectedIndex=0;')
661: }
662: }
663: //picked one of the piecewise name fields, reset the all in
664: //one field to blank
665: if ((tf>=2) && (tf<=5) && (nw!=0)) {
666: eval('vf.f1.selectedIndex=0;')
667: }
668: // intial password specified, pick internal authentication
669: if (tf==8 && nw!=0) {
670: changed_radio('int',document.studentform);
671: set_auth_radio_buttons('int',document.studentform);
672: vf.krbarg.value='';
673: vf.intarg.value='';
674: vf.locarg.value='';
675: }
676: }
677:
678: function clearpwd(vf) {
679: var i;
680: if (eval('vf.f8.selectedIndex')!=0) {
681: eval('vf.f8.selectedIndex=0;')
682: }
683: }
684: ENDPICK
685: }
686:
687: ###############################################################
688: ###############################################################
689: sub print_upload_manager_footer {
1.22 raeburn 690: my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission) = @_;
691: my $form = 'document.studentform';
692: my $formname = 'studentform';
1.1 raeburn 693: my ($krbdef,$krbdefdom) =
694: &Apache::loncommon::get_kerberos_defaults($defdom);
1.22 raeburn 695: my %param = ( formname => $form,
1.1 raeburn 696: kerb_def_dom => $krbdefdom,
697: kerb_def_auth => $krbdef
698: );
699: if (exists($env{'form.ipwd_choice'}) &&
700: defined($env{'form.ipwd_choice'}) &&
701: $env{'form.ipwd_choice'} ne '') {
702: $param{'curr_authtype'} = 'int';
703: }
704: my $krbform = &Apache::loncommon::authform_kerberos(%param);
705: my $intform = &Apache::loncommon::authform_internal(%param);
706: my $locform = &Apache::loncommon::authform_local(%param);
1.22 raeburn 707: my $date_table = &date_setting_table(undef,undef,$context,undef,
708: $formname,$permission);
1.1 raeburn 709: my $Str = "\n".'<div class="LC_left_float">';
710: $Str .= &hidden_input('nfields',$i);
711: $Str .= &hidden_input('keyfields',$keyfields);
712: $Str .= "<h3>".&mt('Login Type')."</h3>\n";
713: if ($context eq 'domain') {
714: $Str .= '<p>'.&mt('Change authentication for existing users to these settings?').' <span class="LC_nobreak"><label><input type="radio" name="changeauth" value="No" checked="checked" />'.&mt('No').'</label> <label><input type="radio" name="changeauth" value="Yes" />'.&mt('Yes').'</label></span></p>';
715: } else {
716: $Str .= "<p>\n".
717: &mt('Note: this will not take effect if the user already exists').
718: &Apache::loncommon::help_open_topic('Auth_Options').
719: "</p>\n";
720: }
721: $Str .= &set_login($defdom,$krbform,$intform,$locform);
722: my ($home_server_pick,$numlib) =
723: &Apache::loncommon::home_server_form_item($defdom,'lcserver',
724: 'default','hide');
725: if ($numlib > 1) {
726: $Str .= '<h3>'.&mt('LON-CAPA Home Server for New Users')."</h3>\n".
727: &mt('LON-CAPA domain: [_1] with home server: [_2]',$defdom,
728: $home_server_pick).'<br />';
729: } else {
730: $Str .= $home_server_pick;
731: }
732: $Str .= '<h3>'.&mt('Starting and Ending Dates').
733: "</h3>\n";
734: $Str .= "<p>\n".$date_table."</p>\n";
735: if ($context eq 'domain') {
736: $Str .= '<h3>'.&mt('Settings for assigning roles:').'</h3>'."\n".
737: &mt('Pick the action to take on roles for these users:').'<br /><span class="LC_nobreak"><label><input type="radio" name="roleaction" value="norole" checked="checked" /> '.&mt('No role changes').'</label> <label><input type="radio" name="roleaction" value="domain" /> '.&mt('Add a domain role').'</label> <label><input type="radio" name="roleaction" value="course" /> '.&mt('Add a course role').'</label></span>';
738: }
1.13 raeburn 739: if ($context eq 'author') {
1.1 raeburn 740: $Str .= '<h3>'.&mt('Default role')."</h3>\n".
1.25 raeburn 741: &mt('Choose the role to assign to users without a value specified in the uploaded file');
1.1 raeburn 742: } elsif ($context eq 'course') {
743: $Str .= '<h3>'.&mt('Default role and section')."</h3>\n".
1.25 raeburn 744: &mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file');
1.1 raeburn 745: } else {
1.25 raeburn 746: $Str .= '<br /><br /><b>'.&mt('Default role and/or section(s)')."</b><br />\n".
747: &mt('Role and/or section(s) for users without values specified in the uploaded file.');
1.1 raeburn 748: }
1.22 raeburn 749: $Str .= '<br />';
750: if (($context eq 'domain') || ($context eq 'author')) {
751: my ($options,$cb_script,$coursepick) = &default_role_selector($context,1);
752: if ($context eq 'domain') {
753: $Str .= '<span class="LC_role_level">'.&mt('Domain Level').'</span><br />'.$options.'<br /><br /><span class="LC_role_level">'.&mt('Course Level').'</span><br />'.$cb_script.$coursepick;
754: } elsif ($context eq 'author') {
755: $Str .= $options;
756: }
1.1 raeburn 757: } else {
1.22 raeburn 758: my ($cnum,$cdom) = &get_course_identity();
759: my $rowtitle = &mt('section');
760: my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,
761: $permission,$context,'upload');
762: $Str .= $secbox."<h3>".&mt('Full Update')."</h3>\n".
763: '<p><label><input type="checkbox" name="fullup" value="yes">'.
764: ' '.&mt('Display students with current/future access, who are not in the uploaded file.').'<br />'.&mt('Students selected from this list can be dropped.');
1.1 raeburn 765: "</label></p>\n";
766: }
1.5 raeburn 767: if ($context eq 'course' || $context eq 'domain') {
768: $Str .= &forceid_change($context);
769: }
1.1 raeburn 770: $Str .= '</div><div class="LC_clear_float_footer"><br /><input type="button"'.
771: 'onClick="javascript:verify(this.form,this.form.csec)" '.
772: 'value="Update Users" />'."<br />\n";
773: if ($context eq 'course') {
774: $Str .= &mt('Note: for large courses, this operation may be time '.
775: 'consuming');
776: }
777: $Str .= '</div>';
778: $r->print($Str);
779: return;
780: }
781:
1.5 raeburn 782: sub forceid_change {
783: my ($context) = @_;
784: my $output =
785: "<h3>".&mt('ID/Student Number')."</h3>\n".
786: "<p>\n".'<label><input type="checkbox" name="forceid" value="yes">'.
787: &mt('Disable ID/Student Number Safeguard and Force Change '.
788: 'of Conflicting IDs').'</label><br />'."\n".
1.25 raeburn 789: &mt('(only do if you know what you are doing.)')."\n";
1.5 raeburn 790: if ($context eq 'domain') {
1.25 raeburn 791: $output .= '<br /><label><input type="checkbox" name="recurseid"'.
1.5 raeburn 792: ' value="yes">'.
1.13 raeburn 793: &mt('Update ID/Student Number in courses in which user is Active/Future student,<br />(if forcing change).').
1.25 raeburn 794: '</label>'."\n";
1.5 raeburn 795: }
1.25 raeburn 796: $output .= '</p>';
1.5 raeburn 797: return $output;
798: }
799:
1.1 raeburn 800: ###############################################################
801: ###############################################################
802: sub print_upload_manager_form {
1.21 raeburn 803: my ($r,$context,$permission) = @_;
1.1 raeburn 804: my $firstLine;
805: my $datatoken;
806: if (!$env{'form.datatoken'}) {
807: $datatoken=&Apache::loncommon::upfile_store($r);
808: } else {
809: $datatoken=$env{'form.datatoken'};
810: &Apache::loncommon::load_tmp_file($r);
811: }
812: my @records=&Apache::loncommon::upfile_record_sep();
813: if($env{'form.noFirstLine'}){
814: $firstLine=shift(@records);
815: }
816: my $total=$#records;
817: my $distotal=$total+1;
818: my $today=time;
819: my $halfyear=$today+15552000;
820: #
821: # Restore memorized settings
822: my $col_setting_names = { 'username_choice' => 'scalar', # column settings
823: 'names_choice' => 'scalar',
824: 'fname_choice' => 'scalar',
825: 'mname_choice' => 'scalar',
826: 'lname_choice' => 'scalar',
827: 'gen_choice' => 'scalar',
828: 'id_choice' => 'scalar',
829: 'sec_choice' => 'scalar',
830: 'ipwd_choice' => 'scalar',
831: 'email_choice' => 'scalar',
832: 'role_choice' => 'scalar',
833: };
834: my $defdom = $env{'request.role.domain'};
835: if ($context eq 'course') {
836: &Apache::loncommon::restore_course_settings('enrollment_upload',
837: $col_setting_names);
838: } else {
839: &Apache::loncommon::restore_settings($context,'user_upload',
840: $col_setting_names);
841: }
842: #
843: # Determine kerberos parameters as appropriate
844: my ($krbdef,$krbdefdom) =
845: &Apache::loncommon::get_kerberos_defaults($defdom);
846: #
1.22 raeburn 847: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom,$context,
848: $permission);
1.1 raeburn 849: my $i;
850: my $keyfields;
851: if ($total>=0) {
852: my @field=
853: (['username',&mt('Username'), $env{'form.username_choice'}],
854: ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}],
855: ['fname',&mt('First Name'), $env{'form.fname_choice'}],
856: ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}],
857: ['lname',&mt('Last Name'), $env{'form.lname_choice'}],
858: ['gen', &mt('Generation'), $env{'form.gen_choice'}],
859: ['id', &mt('ID/Student Number'),$env{'form.id_choice'}],
860: ['sec', &mt('Section'), $env{'form.sec_choice'}],
861: ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}],
862: ['email',&mt('E-mail Address'), $env{'form.email_choice'}],
863: ['role',&mt('Role'), $env{'form.role_choice'}]);
864: if ($env{'form.upfile_associate'} eq 'reverse') {
865: &Apache::loncommon::csv_print_samples($r,\@records);
866: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
867: \@field);
868: foreach (@field) {
869: $keyfields.=$_->[0].',';
870: }
871: chop($keyfields);
872: } else {
873: unshift(@field,['none','']);
874: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
875: \@field);
876: my %sone=&Apache::loncommon::record_sep($records[0]);
877: $keyfields=join(',',sort(keys(%sone)));
878: }
879: }
880: $r->print('</div>');
881: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
1.22 raeburn 882: $context,$permission);
1.1 raeburn 883: }
884:
885: sub setup_date_selectors {
1.22 raeburn 886: my ($starttime,$endtime,$mode,$nolink,$formname) = @_;
887: if ($formname eq '') {
888: $formname = 'studentform';
889: }
1.1 raeburn 890: if (! defined($starttime)) {
891: $starttime = time;
892: unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
893: if (exists($env{'course.'.$env{'request.course.id'}.
894: '.default_enrollment_start_date'})) {
895: $starttime = $env{'course.'.$env{'request.course.id'}.
896: '.default_enrollment_start_date'};
897: }
898: }
899: }
900: if (! defined($endtime)) {
901: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
902: unless ($mode eq 'createcourse') {
903: if (exists($env{'course.'.$env{'request.course.id'}.
904: '.default_enrollment_end_date'})) {
905: $endtime = $env{'course.'.$env{'request.course.id'}.
906: '.default_enrollment_end_date'};
907: }
908: }
909: }
1.11 raeburn 910:
911: my $startdateform =
1.22 raeburn 912: &Apache::lonhtmlcommon::date_setter($formname,'startdate',$starttime,
1.11 raeburn 913: undef,undef,undef,undef,undef,undef,undef,$nolink);
914:
915: my $enddateform =
1.22 raeburn 916: &Apache::lonhtmlcommon::date_setter($formname,'enddate',$endtime,
1.11 raeburn 917: undef,undef,undef,undef,undef,undef,undef,$nolink);
918:
1.1 raeburn 919: if ($mode eq 'create_enrolldates') {
920: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
921: 'startenroll',
922: $starttime);
923: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
924: 'endenroll',
925: $endtime);
926: }
927: if ($mode eq 'create_defaultdates') {
928: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
929: 'startaccess',
930: $starttime);
931: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
932: 'endaccess',
933: $endtime);
934: }
935: return ($startdateform,$enddateform);
936: }
937:
938:
939: sub get_dates_from_form {
940: my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
941: my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate');
942: if ($env{'form.no_end_date'}) {
943: $enddate = 0;
944: }
945: return ($startdate,$enddate);
946: }
947:
948: sub date_setting_table {
1.22 raeburn 949: my ($starttime,$endtime,$mode,$bulkaction,$formname,$permission) = @_;
1.11 raeburn 950: my $nolink;
951: if ($bulkaction) {
952: $nolink = 1;
953: }
954: my ($startform,$endform) =
1.22 raeburn 955: &setup_date_selectors($starttime,$endtime,$mode,$nolink,$formname);
1.1 raeburn 956: my $dateDefault;
957: if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') {
958: $dateDefault = ' ';
1.13 raeburn 959: } elsif ($mode ne 'author' && $mode ne 'domain') {
1.11 raeburn 960: if (($bulkaction eq 'reenable') ||
961: ($bulkaction eq 'activate') ||
1.22 raeburn 962: ($bulkaction eq 'chgdates') ||
963: ($env{'form.action'} eq 'upload')) {
964: if ($env{'request.course.sec'} eq '') {
965: $dateDefault = '<span class="LC_nobreak">'.
1.25 raeburn 966: '<label><input type="checkbox" name="makedatesdefault" value="1" /> '.
1.22 raeburn 967: &mt('make these dates the default access dates for future student enrollment').
968: '</label></span>';
969: }
1.11 raeburn 970: }
1.1 raeburn 971: }
1.11 raeburn 972: my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"';
1.1 raeburn 973: if (defined($endtime) && $endtime == 0) {
974: $perpetual .= ' checked';
975: }
1.11 raeburn 976: $perpetual.= ' /> '.&mt('no ending date').'</label></span>';
1.1 raeburn 977: if ($mode eq 'create_enrolldates') {
978: $perpetual = ' ';
979: }
1.11 raeburn 980: my $result = &Apache::lonhtmlcommon::start_pick_box()."\n";
981: $result .= &Apache::lonhtmlcommon::row_title(&mt('Starting Date'),
982: 'LC_oddrow_value')."\n".
983: $startform."\n".
984: &Apache::lonhtmlcommon::row_closure(1).
985: &Apache::lonhtmlcommon::row_title(&mt('Ending Date'),
986: 'LC_oddrow_value')."\n".
987: $endform.' '.$perpetual.
988: &Apache::lonhtmlcommon::row_closure(1).
1.22 raeburn 989: &Apache::lonhtmlcommon::end_pick_box();
1.1 raeburn 990: if ($dateDefault) {
991: $result .= $dateDefault.'<br />'."\n";
992: }
993: return $result;
994: }
995:
996: sub make_dates_default {
997: my ($startdate,$enddate,$context) = @_;
998: my $result = '';
999: if ($context eq 'course') {
1.17 raeburn 1000: my ($cnum,$cdom) = &get_course_identity();
1.1 raeburn 1001: my $put_result = &Apache::lonnet::put('environment',
1002: {'default_enrollment_start_date'=>$startdate,
1.17 raeburn 1003: 'default_enrollment_end_date' =>$enddate},$cdom,$cnum);
1.1 raeburn 1004: if ($put_result eq 'ok') {
1.25 raeburn 1005: $result .= &mt('Set default start and end access dates for course.').
1.11 raeburn 1006: '<br />'."\n";
1.1 raeburn 1007: #
1008: # Refresh the course environment
1009: &Apache::lonnet::coursedescription($env{'request.course.id'},
1010: {'freshen_cache' => 1});
1011: } else {
1.25 raeburn 1012: $result .= &mt('Unable to set default access dates for course.').":".$put_result.
1.1 raeburn 1013: '<br />';
1014: }
1015: }
1016: return $result;
1017: }
1018:
1019: sub default_role_selector {
1.2 raeburn 1020: my ($context,$checkpriv) = @_;
1.1 raeburn 1021: my %customroles;
1022: my ($options,$coursepick,$cb_jscript);
1.13 raeburn 1023: if ($context ne 'author') {
1.1 raeburn 1024: %customroles = &my_custom_roles();
1025: }
1026:
1027: my %lt=&Apache::lonlocal::texthash(
1028: 'rol' => "Role",
1029: 'grs' => "Section",
1030: 'exs' => "Existing sections",
1031: 'new' => "New section",
1032: );
1033: $options = '<select name="defaultrole">'."\n".
1034: ' <option value="">'.&mt('Please select').'</option>'."\n";
1035: if ($context eq 'course') {
1.2 raeburn 1036: $options .= &default_course_roles($context,$checkpriv,%customroles);
1.13 raeburn 1037: } elsif ($context eq 'author') {
1.2 raeburn 1038: my @roles = &construction_space_roles($checkpriv);
1.1 raeburn 1039: foreach my $role (@roles) {
1040: my $plrole=&Apache::lonnet::plaintext($role);
1041: $options .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
1042: }
1043: } elsif ($context eq 'domain') {
1.2 raeburn 1044: my @roles = &domain_roles($checkpriv);
1.1 raeburn 1045: foreach my $role (@roles) {
1046: my $plrole=&Apache::lonnet::plaintext($role);
1047: $options .= ' <option value="'.$role.'">'.$plrole.'</option>';
1048: }
1049: my $courseform = &Apache::loncommon::selectcourse_link
1.22 raeburn 1050: ('studentform','dccourse','dcdomain','coursedesc',"$env{'request.role.domain'}",undef,'Course');
1.1 raeburn 1051: $cb_jscript =
1.22 raeburn 1052: &Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'},'currsec','studentform');
1.1 raeburn 1053: $coursepick = &Apache::loncommon::start_data_table().
1054: &Apache::loncommon::start_data_table_header_row().
1055: '<th>'.$courseform.'</th><th>'.$lt{'rol'}.'</th>'.
1056: '<th>'.$lt{'grs'}.'</th>'.
1057: &Apache::loncommon::end_data_table_header_row().
1058: &Apache::loncommon::start_data_table_row()."\n".
1.22 raeburn 1059: '<td><input type="text" name="coursedesc" value="" onFocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc',''".')" /></td>'."\n".
1.1 raeburn 1060: '<td><select name="courserole">'."\n".
1.2 raeburn 1061: &default_course_roles($context,$checkpriv,%customroles)."\n".
1.1 raeburn 1062: '</select></td><td>'.
1063: '<table class="LC_createuser">'.
1064: '<tr class="LC_section_row"><td valign"top">'.
1.22 raeburn 1065: $lt{'exs'}.'<br /><select name="currsec">'.
1.1 raeburn 1066: ' <option value=""><--'.&mt('Pick course first').
1067: '</select></td>'.
1068: '<td> </td>'.
1069: '<td valign="top">'.$lt{'new'}.'<br />'.
1070: '<input type="text" name="newsec" value="" size="5" />'.
1.22 raeburn 1071: '<input type="hidden" name="groups" value="" />'.
1072: '<input type="hidden" name="sections" value="" />'.
1073: '<input type="hidden" name="origdom" value="'.
1074: $env{'request.role.domain'}.'" />'.
1075: '<input type="hidden" name="dccourse" value="" />'.
1076: '<input type="hidden" name="dcdomain" value="" />'.
1077: '</td></tr></table></td>'.
1.1 raeburn 1078: &Apache::loncommon::end_data_table_row().
1.22 raeburn 1079: &Apache::loncommon::end_data_table()."\n";
1.1 raeburn 1080: }
1081: $options .= '</select>';
1082: return ($options,$cb_jscript,$coursepick);
1083: }
1084:
1085: sub default_course_roles {
1.2 raeburn 1086: my ($context,$checkpriv,%customroles) = @_;
1.1 raeburn 1087: my $output;
1.17 raeburn 1088: my $custom = 1;
1089: my @roles = &course_roles($context,$checkpriv,$custom);
1.1 raeburn 1090: foreach my $role (@roles) {
1.22 raeburn 1091: if ($role ne 'cr') {
1092: my $plrole=&Apache::lonnet::plaintext($role);
1093: $output .= ' <option value="'.$role.'">'.$plrole.'</option>';
1094: }
1.1 raeburn 1095: }
1096: if (keys(%customroles) > 0) {
1.22 raeburn 1097: if (grep(/^cr$/,@roles)) {
1098: foreach my $cust (sort(keys(%customroles))) {
1099: my $custrole='cr_'.$env{'user.domain'}.
1100: '_'.$env{'user.name'}.'_'.$cust;
1101: $output .= ' <option value="'.$custrole.'">'.$cust.'</option>';
1102: }
1.1 raeburn 1103: }
1104: }
1105: return $output;
1106: }
1107:
1108: sub construction_space_roles {
1.2 raeburn 1109: my ($checkpriv) = @_;
1.17 raeburn 1110: my @allroles = &roles_by_context('author');
1.1 raeburn 1111: my @roles;
1.2 raeburn 1112: if ($checkpriv) {
1113: foreach my $role (@allroles) {
1114: if (&Apache::lonnet::allowed('c'.$role,$env{'user.domain'}.'/'.$env{'user.name'})) {
1115: push(@roles,$role);
1116: }
1.1 raeburn 1117: }
1.2 raeburn 1118: return @roles;
1119: } else {
1120: return @allroles;
1.1 raeburn 1121: }
1122: }
1123:
1124: sub domain_roles {
1.2 raeburn 1125: my ($checkpriv) = @_;
1.17 raeburn 1126: my @allroles = &roles_by_context('domain');
1.1 raeburn 1127: my @roles;
1.2 raeburn 1128: if ($checkpriv) {
1129: foreach my $role (@allroles) {
1130: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
1131: push(@roles,$role);
1132: }
1.1 raeburn 1133: }
1.2 raeburn 1134: return @roles;
1135: } else {
1136: return @allroles;
1.1 raeburn 1137: }
1138: }
1139:
1140: sub course_roles {
1.17 raeburn 1141: my ($context,$checkpriv,$custom) = @_;
1142: my @allroles = &roles_by_context('course',$custom);
1.1 raeburn 1143: my @roles;
1144: if ($context eq 'domain') {
1145: @roles = @allroles;
1146: } elsif ($context eq 'course') {
1147: if ($env{'request.course.id'}) {
1.2 raeburn 1148: if ($checkpriv) {
1149: foreach my $role (@allroles) {
1150: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
1151: push(@roles,$role);
1152: } else {
1.22 raeburn 1153: if ($role ne 'cc' && $env{'request.course.sec'} ne '') {
1154: if (&Apache::lonnet::allowed('c'.$role,
1.2 raeburn 1155: $env{'request.course.id'}.'/'.
1.22 raeburn 1156: $env{'request.course.sec'})) {
1.2 raeburn 1157: push(@roles,$role);
1158: }
1.1 raeburn 1159: }
1160: }
1161: }
1.2 raeburn 1162: } else {
1163: @roles = @allroles;
1.1 raeburn 1164: }
1165: }
1166: }
1167: return @roles;
1168: }
1169:
1170: sub curr_role_permissions {
1.2 raeburn 1171: my ($context,$setting,$checkpriv) = @_;
1.17 raeburn 1172: my $custom = 1;
1.1 raeburn 1173: my @roles;
1.13 raeburn 1174: if ($context eq 'author') {
1.2 raeburn 1175: @roles = &construction_space_roles($checkpriv);
1.1 raeburn 1176: } elsif ($context eq 'domain') {
1177: if ($setting eq 'course') {
1.17 raeburn 1178: @roles = &course_roles($context,$checkpriv,$custom);
1.1 raeburn 1179: } else {
1.2 raeburn 1180: @roles = &domain_roles($checkpriv);
1.1 raeburn 1181: }
1182: } elsif ($context eq 'course') {
1.17 raeburn 1183: @roles = &course_roles($context,$checkpriv,$custom);
1.1 raeburn 1184: }
1185: return @roles;
1186: }
1187:
1188: # ======================================================= Existing Custom Roles
1189:
1190: sub my_custom_roles {
1191: my %returnhash=();
1192: my %rolehash=&Apache::lonnet::dump('roles');
1193: foreach my $key (keys %rolehash) {
1194: if ($key=~/^rolesdef\_(\w+)$/) {
1195: $returnhash{$1}=$1;
1196: }
1197: }
1198: return %returnhash;
1199: }
1200:
1.2 raeburn 1201: sub print_userlist {
1202: my ($r,$mode,$permission,$context,$formname,$totcodes,$codetitles,
1203: $idlist,$idlist_titles) = @_;
1204: my $format = $env{'form.output'};
1.1 raeburn 1205: if (! exists($env{'form.sortby'})) {
1206: $env{'form.sortby'} = 'username';
1207: }
1.2 raeburn 1208: if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) {
1209: $env{'form.Status'} = 'Active';
1.1 raeburn 1210: }
1211: my $status_select = &Apache::lonhtmlcommon::StatusOptions
1.2 raeburn 1212: ($env{'form.Status'});
1.1 raeburn 1213:
1.2 raeburn 1214: if ($env{'form.showrole'} eq '') {
1.13 raeburn 1215: if ($context eq 'course') {
1216: $env{'form.showrole'} = 'st';
1217: } else {
1218: $env{'form.showrole'} = 'Any';
1219: }
1.2 raeburn 1220: }
1.1 raeburn 1221: if (! defined($env{'form.output'}) ||
1222: $env{'form.output'} !~ /^(csv|excel|html)$/ ) {
1223: $env{'form.output'} = 'html';
1224: }
1225:
1.2 raeburn 1226: my @statuses;
1227: if ($env{'form.Status'} eq 'Any') {
1228: @statuses = ('previous','active','future');
1229: } elsif ($env{'form.Status'} eq 'Expired') {
1230: @statuses = ('previous');
1231: } elsif ($env{'form.Status'} eq 'Active') {
1232: @statuses = ('active');
1233: } elsif ($env{'form.Status'} eq 'Future') {
1234: @statuses = ('future');
1235: }
1.1 raeburn 1236:
1.2 raeburn 1237: # if ($context eq 'course') {
1238: # $r->print(&display_adv_courseroles());
1239: # }
1.1 raeburn 1240: #
1241: # Interface output
1.2 raeburn 1242: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
1243: '<input type="hidden" name="action" value="'.
1.1 raeburn 1244: $env{'form.action'}.'" />');
1245: $r->print("<p>\n");
1246: if ($env{'form.action'} ne 'modifystudent') {
1247: my %lt=&Apache::lonlocal::texthash('csv' => "CSV",
1248: 'excel' => "Excel",
1249: 'html' => 'HTML');
1250: my $output_selector = '<select size="1" name="output" >';
1251: foreach my $outputformat ('html','csv','excel') {
1252: my $option = '<option value="'.$outputformat.'" ';
1253: if ($outputformat eq $env{'form.output'}) {
1254: $option .= 'selected ';
1255: }
1256: $option .='>'.$lt{$outputformat}.'</option>';
1257: $output_selector .= "\n".$option;
1258: }
1259: $output_selector .= '</select>';
1260: $r->print('<label>'.&mt('Output Format: [_1]',$output_selector).'</label>'.(' 'x3));
1261: }
1.2 raeburn 1262: $r->print('<label>'.&mt('User Status: [_1]',$status_select).'</label>'.(' 'x3)."\n");
1263: my $roleselected = '';
1264: if ($env{'form.showrole'} eq 'Any') {
1265: $roleselected = ' selected="selected" ';
1266: }
1.33 raeburn 1267: my ($role_select,$cnum,$cdom);
1.2 raeburn 1268: if ($context eq 'domain') {
1269: $role_select = &domain_roles_select();
1270: $r->print('<label>'.&mt('Role Type: [_1]',$role_select).'</label>');
1271: } else {
1272: $role_select = '<select name="showrole">'."\n".
1273: '<option value="Any" '.$roleselected.'>'.
1274: &mt('Any role').'</option>';
1275: my @poss_roles = &curr_role_permissions($context);
1276: foreach my $role (@poss_roles) {
1277: $roleselected = '';
1278: if ($role eq $env{'form.showrole'}) {
1279: $roleselected = ' selected="selected" ';
1280: }
1.22 raeburn 1281: my $plrole;
1282: if ($role eq 'cr') {
1283: $plrole = &mt('Custom role');
1284: } else {
1285: $plrole=&Apache::lonnet::plaintext($role);
1286: }
1.2 raeburn 1287: $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>';
1288: }
1.22 raeburn 1289: $role_select .= '</select>';
1.2 raeburn 1290: $r->print('<label>'.&mt('Role: [_1]',$role_select).'</label>');
1.33 raeburn 1291: if ($context eq 'course') {
1292: ($cnum,$cdom) = &get_course_identity();
1293: $r->print(§ion_group_filter($cnum,$cdom));
1294: }
1.2 raeburn 1295: }
1296: if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
1.25 raeburn 1297: $r->print(' '.&list_submit_button(&mt('Update Display')).
1298: "\n</p>\n");
1.2 raeburn 1299: }
1300: my ($indexhash,$keylist) = &make_keylist_array();
1301: my (%userlist,%userinfo);
1.3 raeburn 1302: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
1303: my $courseform =
1304: &Apache::lonhtmlcommon::course_selection($formname,$totcodes,
1305: $codetitles,$idlist,$idlist_titles);
1306: $r->print('<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n".
1307: &Apache::lonhtmlcommon::start_pick_box()."\n".
1308: &Apache::lonhtmlcommon::row_title(&mt('Select Course(s)'),
1309: 'LC_oddrow_value')."\n".
1310: $courseform."\n".
1311: &Apache::lonhtmlcommon::row_closure(1).
1312: &Apache::lonhtmlcommon::end_pick_box().'</p>'.
1313: '<p>'.&list_submit_button(&mt('Update Display')).
1.34 ! raeburn 1314: "\n".'</p><span class="LC_warning">'.&mt('Warning: data retrieval for multiple courses can take considerable time, as this operation is not currently optimized.').'</span>'."\n");
1.11 raeburn 1315: if ($env{'form.coursepick'}) {
1316: $r->print('<hr />'.&mt('Searching').' ...<br /> <br />');
1317: }
1318: } else {
1319: $r->print('<hr />'.&mt('Searching').' ...<br /> <br />');
1.3 raeburn 1320: }
1321: $r->rflush();
1.1 raeburn 1322: if ($context eq 'course') {
1.3 raeburn 1323: my $classlist = &Apache::loncoursedata::get_classlist();
1324: my $secidx = &Apache::loncoursedata::CL_SECTION();
1.22 raeburn 1325: my $viewablesec = &viewable_section($permission);
1.3 raeburn 1326: foreach my $student (keys(%{$classlist})) {
1.22 raeburn 1327: my $section = $classlist->{$student}[$secidx];
1328: if ($viewablesec ne '') {
1329: if ($section ne $viewablesec) {
1.3 raeburn 1330: next;
1331: } else {
1332: $userlist{$student} = $classlist->{$student};
1.1 raeburn 1333: }
1.3 raeburn 1334: } else {
1335: $userlist{$student} = $classlist->{$student};
1.1 raeburn 1336: }
1337: }
1.2 raeburn 1338: my $showroles;
1339: if ($env{'form.showrole'} ne 'Any') {
1340: $showroles = [$env{'form.showrole'}];
1.1 raeburn 1341: } else {
1.2 raeburn 1342: $showroles = undef;
1343: }
1.22 raeburn 1344: my $withsec = 1;
1.2 raeburn 1345: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
1.22 raeburn 1346: \@statuses,$showroles,undef,$withsec);
1.2 raeburn 1347: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1.11 raeburn 1348: \%advrolehash,$permission);
1.2 raeburn 1349: } else {
1350: my (%cstr_roles,%dom_roles);
1.13 raeburn 1351: if ($context eq 'author') {
1.2 raeburn 1352: # List co-authors and assistant co-authors
1.17 raeburn 1353: my @possroles = &roles_by_context($context);
1.2 raeburn 1354: %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
1355: \@statuses,\@possroles);
1356: &gather_userinfo($context,$format,\%userlist,$indexhash,\%userinfo,
1.11 raeburn 1357: \%cstr_roles,$permission);
1.2 raeburn 1358: } elsif ($context eq 'domain') {
1359: if ($env{'form.roletype'} eq 'domain') {
1360: %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
1361: foreach my $key (keys(%dom_roles)) {
1362: if (ref($dom_roles{$key}) eq 'HASH') {
1363: &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11 raeburn 1364: \%userinfo,$dom_roles{$key},$permission);
1.2 raeburn 1365: }
1366: }
1.13 raeburn 1367: } elsif ($env{'form.roletype'} eq 'author') {
1.2 raeburn 1368: my %dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'},['au']);
1369: my %coauthors;
1370: foreach my $key (keys(%dom_roles)) {
1371: if (ref($dom_roles{$key}) eq 'HASH') {
1372: if ($env{'form.showrole'} eq 'au') {
1373: &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11 raeburn 1374: \%userinfo,$dom_roles{$key},$permission);
1.2 raeburn 1375: } else {
1376: my @possroles;
1377: if ($env{'form.showrole'} eq 'Any') {
1.22 raeburn 1378: @possroles = &roles_by_context('author');
1.2 raeburn 1379: } else {
1380: @possroles = ($env{'form.showrole'});
1381: }
1382: foreach my $author (sort(keys(%{$dom_roles{$key}}))) {
1.22 raeburn 1383: my ($role,$authorname,$authordom) = split(/:/,$author,-1);
1.2 raeburn 1384: my $extent = '/'.$authordom.'/'.$authorname;
1385: %{$coauthors{$extent}} =
1386: &Apache::lonnet::get_my_roles($authorname,
1387: $authordom,undef,\@statuses,\@possroles);
1388: }
1389: &gather_userinfo($context,$format,\%userlist,
1.11 raeburn 1390: $indexhash,\%userinfo,\%coauthors,$permission);
1.2 raeburn 1391: }
1392: }
1393: }
1394: } elsif ($env{'form.roletype'} eq 'course') {
1395: if ($env{'form.coursepick'}) {
1396: my %courses = &process_coursepick();
1397: my %allusers;
1398: foreach my $cid (keys(%courses)) {
1.17 raeburn 1399: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
1.11 raeburn 1400: next if ($cnum eq '' || $cdom eq '');
1.17 raeburn 1401: my $custom = 1;
1.2 raeburn 1402: my (@roles,@sections,%access,%users,%userdata,
1.6 albertel 1403: %statushash);
1.2 raeburn 1404: if ($env{'form.showrole'} eq 'Any') {
1.17 raeburn 1405: @roles = &course_roles($context,undef,$custom);
1.2 raeburn 1406: } else {
1407: @roles = ($env{'form.showrole'});
1408: }
1409: foreach my $role (@roles) {
1410: %{$users{$role}} = ();
1411: }
1412: foreach my $type (@statuses) {
1413: $access{$type} = $type;
1414: }
1415: &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users,\%userdata,\%statushash);
1416: foreach my $user (keys(%userdata)) {
1417: next if (ref($userinfo{$user}) eq 'HASH');
1418: foreach my $item ('fullname','id') {
1419: $userinfo{$user}{$item} = $userdata{$user}[$indexhash->{$item}];
1420: }
1421: }
1422: foreach my $role (keys(%users)) {
1423: foreach my $user (keys(%{$users{$role}})) {
1424: my $uniqid = $user.':'.$role;
1425: $allusers{$uniqid}{$cid} = { desc => $cdesc,
1426: secs => $statushash{$user}{$role},
1427: };
1428: }
1429: }
1430: }
1431: &gather_userinfo($context,$format,\%userlist,$indexhash,
1.11 raeburn 1432: \%userinfo,\%allusers,$permission);
1.2 raeburn 1433: } else {
1.10 raeburn 1434: $r->print('<input type="hidden" name="phase" value="'.
1435: $env{'form.phase'}.'" /></form>');
1.2 raeburn 1436: return;
1437: }
1.1 raeburn 1438: }
1439: }
1.3 raeburn 1440: }
1441: if (keys(%userlist) == 0) {
1.13 raeburn 1442: if ($context eq 'author') {
1.3 raeburn 1443: $r->print(&mt('There are no co-authors to display.')."\n");
1444: } elsif ($context eq 'domain') {
1445: if ($env{'form.roletype'} eq 'domain') {
1446: $r->print(&mt('There are no users with domain roles to display.')."\n");
1.13 raeburn 1447: } elsif ($env{'form.roletype'} eq 'author') {
1.3 raeburn 1448: $r->print(&mt('There are no authors or co-authors to display.')."\n");
1449: } elsif ($env{'form.roletype'} eq 'course') {
1450: $r->print(&mt('There are no course users to display')."\n");
1.2 raeburn 1451: }
1.3 raeburn 1452: } elsif ($context eq 'course') {
1453: $r->print(&mt('There are no course users to display.')."\n");
1454: }
1455: } else {
1456: # Print out the available choices
1.4 raeburn 1457: my $usercount;
1.3 raeburn 1458: if ($env{'form.action'} eq 'modifystudent') {
1.10 raeburn 1459: ($usercount) = &show_users_list($r,$context,'view',$permission,
1.4 raeburn 1460: $env{'form.Status'},\%userlist,$keylist);
1.1 raeburn 1461: } else {
1.4 raeburn 1462: ($usercount) = &show_users_list($r,$context,$env{'form.output'},
1.10 raeburn 1463: $permission,$env{'form.Status'},\%userlist,$keylist);
1.4 raeburn 1464: }
1465: if (!$usercount) {
1466: $r->print('<br />'.&mt('There are no users matching the search criteria.'));
1.2 raeburn 1467: }
1468: }
1.10 raeburn 1469: $r->print('<input type="hidden" name="phase" value="'.
1470: $env{'form.phase'}.'" /></form>');
1.2 raeburn 1471: }
1472:
1.33 raeburn 1473: sub section_group_filter {
1474: my ($cnum,$cdom) = @_;
1475: my @filters;
1476: if ($env{'request.course.sec'} eq '') {
1477: @filters = ('sec');
1478: }
1479: push(@filters,'grp');
1480: my %name = (
1481: sec => 'secfilter',
1482: grp => 'grpfilter',
1483: );
1484: my %title = &Apache::lonlocal::texthash (
1485: sec => 'Section(s)',
1486: grp => 'Group(s)',
1487: all => 'all',
1488: none => 'none',
1489: );
1490: my ($output,@options);
1491: foreach my $item (@filters) {
1492: my $markup;
1493: if ($env{'form.'.$name{$item}} eq '') {
1494: $env{'form.'.$name{$item}} = 'all';
1495: }
1496: if ($item eq 'sec') {
1497: if ($env{'form.showrole'} eq 'cc') {
1498: $env{'form.'.$name{$item}} = 'none';
1499: }
1500: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
1501: @options = sort(keys(%sections_count));
1502: } elsif ($item eq 'grp') {
1503: my %curr_groups = &Apache::longroup::coursegroups();
1504: @options = sort(keys(%curr_groups));
1505: }
1506: if (@options > 0) {
1507: my $currsel;
1508: $markup = '<select name="'.$name{$item}.'" />'."\n";
1509: foreach my $option ('all','none',@options) {
1510: $currsel = '';
1511: if ($env{'form.'.$name{$item}} eq $option) {
1512: $currsel = ' selected="selected" ';
1513: }
1514: $markup .= ' <option value="'.$option.'"'.$currsel.'>';
1515: if (($option eq 'all') || ($option eq 'none')) {
1516: $markup .= $title{$option};
1517: } else {
1518: $markup .= $option;
1519: }
1520: $markup .= '</option>'."\n";
1521: }
1522: $markup .= '</select>'."\n";
1523: $output .= (' 'x3).'<label>'.$title{$item}.': '.$markup.'</label>';
1524: }
1525: }
1526: return $output;
1527: }
1528:
1.2 raeburn 1529: sub list_submit_button {
1530: my ($text) = @_;
1.11 raeburn 1531: return '<input type="button" name="updatedisplay" value="'.$text.'" onclick="javascript:display_update()" />';
1.2 raeburn 1532: }
1533:
1534: sub gather_userinfo {
1.11 raeburn 1535: my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_;
1.2 raeburn 1536: foreach my $item (keys(%{$rolehash})) {
1537: my %userdata;
1.22 raeburn 1538: if ($context eq 'author') {
1.2 raeburn 1539: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
1540: split(/:/,$item);
1541: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
1.24 raeburn 1542: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1543: $item,$userlist);
1.22 raeburn 1544: } elsif ($context eq 'course') {
1545: my $viewablesec = &viewable_section($permission);
1546: ($userdata{'username'},$userdata{'domain'},$userdata{'role'},
1547: $userdata{'section'}) = split(/:/,$item,-1);
1548: ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item});
1549: if (($viewablesec ne '') && ($userdata{'section'} ne '')) {
1550: next if ($viewablesec ne $userdata{'section'});
1551: }
1.24 raeburn 1552: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1553: $item,$userlist);
1.2 raeburn 1554: } elsif ($context eq 'domain') {
1555: if ($env{'form.roletype'} eq 'domain') {
1556: ($userdata{'role'},$userdata{'username'},$userdata{'domain'}) =
1557: split(/:/,$item);
1558: ($userdata{'end'},$userdata{'start'})=split(/:/,$rolehash->{$item});
1.24 raeburn 1559: &build_user_record($context,\%userdata,$userinfo,$indexhash,
1560: $item,$userlist);
1.13 raeburn 1561: } elsif ($env{'form.roletype'} eq 'author') {
1.2 raeburn 1562: if (ref($rolehash->{$item}) eq 'HASH') {
1563: $userdata{'extent'} = $item;
1564: foreach my $key (keys(%{$rolehash->{$item}})) {
1565: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) = split(/:/,$key);
1566: ($userdata{'start'},$userdata{'end'}) =
1567: split(/:/,$rolehash->{$item}{$key});
1568: my $uniqid = $key.':'.$item;
1.25 raeburn 1569: &build_user_record($context,\%userdata,$userinfo,
1570: $indexhash,$uniqid,$userlist);
1.2 raeburn 1571: }
1572: }
1573: } elsif ($env{'form.roletype'} eq 'course') {
1574: ($userdata{'username'},$userdata{'domain'},$userdata{'role'}) =
1575: split(/:/,$item);
1576: if (ref($rolehash->{$item}) eq 'HASH') {
1.11 raeburn 1577: my $numcids = keys(%{$rolehash->{$item}});
1.2 raeburn 1578: foreach my $cid (sort(keys(%{$rolehash->{$item}}))) {
1579: if (ref($rolehash->{$item}{$cid}) eq 'HASH') {
1580: my $spanstart = '';
1581: my $spanend = '; ';
1582: my $space = ', ';
1583: if ($format eq 'html' || $format eq 'view') {
1584: $spanstart = '<span class="LC_nobreak">';
1.23 raeburn 1585: # FIXME: actions on courses disabled for now
1586: # if ($permission->{'cusr'}) {
1587: # if ($numcids > 1) {
1.25 raeburn 1588: # $spanstart .= '<input type="radio" name="'.$item.'" value="'.$cid.'" /> ';
1.23 raeburn 1589: # } else {
1.25 raeburn 1590: # $spanstart .= '<input type="hidden" name="'.$item.'" value="'.$cid.'" /> ';
1.23 raeburn 1591: # }
1592: # }
1.2 raeburn 1593: $spanend = '</span><br />';
1594: $space = ', ';
1595: }
1596: $userdata{'extent'} .= $spanstart.
1597: $rolehash->{$item}{$cid}{'desc'}.$space;
1598: if (ref($rolehash->{$item}{$cid}{'secs'}) eq 'HASH') {
1599: foreach my $sec (sort(keys(%{$rolehash->{$item}{$cid}{'secs'}}))) {
1.25 raeburn 1600: if (($env{'form.Status'} eq 'Any') ||
1601: ($env{'form.Status'} eq $rolehash->{$item}{$cid}{'secs'}{$sec})) {
1602: $userdata{'extent'} .= $sec.$space.$rolehash->{$item}{$cid}{'secs'}{$sec}.$spanend;
1603: $userdata{'status'} = $rolehash->{$item}{$cid}{'secs'}{$sec};
1604: }
1.2 raeburn 1605: }
1606: }
1607: }
1608: }
1609: }
1.25 raeburn 1610: if ($userdata{'status'} ne '') {
1611: &build_user_record($context,\%userdata,$userinfo,
1612: $indexhash,$item,$userlist);
1613: }
1.2 raeburn 1614: }
1615: }
1616: }
1617: return;
1618: }
1619:
1620: sub build_user_record {
1.24 raeburn 1621: my ($context,$userdata,$userinfo,$indexhash,$record_key,$userlist) = @_;
1.11 raeburn 1622: next if ($userdata->{'start'} eq '-1' && $userdata->{'end'} eq '-1');
1.24 raeburn 1623: if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
1624: &process_date_info($userdata);
1625: }
1.2 raeburn 1626: my $username = $userdata->{'username'};
1627: my $domain = $userdata->{'domain'};
1628: if (ref($userinfo->{$username.':'.$domain}) eq 'HASH') {
1.24 raeburn 1629: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
1.2 raeburn 1630: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
1631: } else {
1632: &aggregate_user_info($domain,$username,$userinfo);
1633: $userdata->{'fullname'} = $userinfo->{$username.':'.$domain}{'fullname'};
1634: $userdata->{'id'} = $userinfo->{$username.':'.$domain}{'id'};
1635: }
1636: foreach my $key (keys(%{$indexhash})) {
1637: if (defined($userdata->{$key})) {
1638: $userlist->{$record_key}[$indexhash->{$key}] = $userdata->{$key};
1639: }
1640: }
1641: return;
1642: }
1643:
1644: sub courses_selector {
1645: my ($cdom,$formname) = @_;
1646: my %coursecodes = ();
1647: my %codes = ();
1648: my @codetitles = ();
1649: my %cat_titles = ();
1650: my %cat_order = ();
1651: my %idlist = ();
1652: my %idnums = ();
1653: my %idlist_titles = ();
1654: my $caller = 'global';
1655: my $format_reply;
1656: my $jscript = '';
1657:
1.7 albertel 1658: my $totcodes = 0;
1659: $totcodes =
1.2 raeburn 1660: &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,
1661: $cdom,$totcodes);
1662: if ($totcodes > 0) {
1663: $format_reply =
1664: &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,
1665: \%codes,\@codetitles,\%cat_titles,\%cat_order);
1666: if ($format_reply eq 'ok') {
1667: my $numtypes = @codetitles;
1668: &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
1669: my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
1670: my $longtitles_str = join('","',@{$longtitles});
1671: my $allidlist = $idlist{$codetitles[0]};
1672: $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
1673: $jscript .= $scripttext;
1674: $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles);
1675: }
1676: }
1677: my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
1678:
1679: my %elements = (
1680: Year => 'selectbox',
1681: coursepick => 'radio',
1682: coursetotal => 'text',
1683: courselist => 'text',
1684: );
1685: $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements);
1686: if ($env{'form.coursepick'} eq 'category') {
1687: $jscript .= qq|
1688: function setCourseCat(formname) {
1689: if (formname.Year.options[formname.Year.selectedIndex].value == -1) {
1690: return;
1691: }
1692: courseSet('Year');
1693: for (var j=0; j<formname.Semester.length; j++) {
1694: if (formname.Semester.options[j].value == "$env{'form.Semester'}") {
1695: formname.Semester.options[j].selected = true;
1696: }
1697: }
1698: if (formname.Semester.options[formname.Semester.selectedIndex].value == -1) {
1699: return;
1700: }
1701: courseSet('Semester');
1702: for (var j=0; j<formname.Department.length; j++) {
1703: if (formname.Department.options[j].value == "$env{'form.Department'}") { formname.Department.options[j].selected = true;
1704: }
1705: }
1706: if (formname.Department.options[formname.Department.selectedIndex].value == -1) {
1707: return;
1708: }
1709: courseSet('Department');
1710: for (var j=0; j<formname.Number.length; j++) {
1711: if (formname.Number.options[j].value == "$env{'form.Number'}") {
1712: formname.Number.options[j].selected = true;
1713: }
1714: }
1715: }
1716: |;
1717: }
1718: return ($cb_jscript,$jscript,$totcodes,\@codetitles,\%idlist,
1719: \%idlist_titles);
1720: }
1721:
1722: sub course_selector_loadcode {
1723: my ($formname) = @_;
1724: my $loadcode;
1725: if ($env{'form.coursepick'} ne '') {
1726: $loadcode = 'javascript:setFormElements(document.'.$formname.')';
1727: if ($env{'form.coursepick'} eq 'category') {
1728: $loadcode .= ';javascript:setCourseCat(document.'.$formname.')';
1729: }
1730: }
1731: return $loadcode;
1732: }
1733:
1734: sub process_coursepick {
1735: my $coursefilter = $env{'form.coursepick'};
1736: my $cdom = $env{'request.role.domain'};
1737: my %courses;
1738: if ($coursefilter eq 'all') {
1739: %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
1740: undef,undef,'Course');
1741: } elsif ($coursefilter eq 'category') {
1742: my $instcode = &instcode_from_coursefilter();
1743: %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
1744: undef,undef,'Course');
1745: } elsif ($coursefilter eq 'specific') {
1746: if ($env{'form.coursetotal'} > 1) {
1747: my @course_ids = split(/&&/,$env{'form.courselist'});
1748: foreach my $cid (@course_ids) {
1749: $courses{$cid} = '';
1.1 raeburn 1750: }
1.2 raeburn 1751: } else {
1752: $courses{$env{'form.courselist'}} = '';
1.1 raeburn 1753: }
1.2 raeburn 1754: }
1755: return %courses;
1756: }
1757:
1758: sub instcode_from_coursefilter {
1759: my $instcode = '';
1760: my @cats = ('Semester','Year','Department','Number');
1761: foreach my $category (@cats) {
1762: if (defined($env{'form.'.$category})) {
1763: unless ($env{'form.'.$category} eq '-1') {
1764: $instcode .= $env{'form.'.$category};
1765: }
1766: }
1767: }
1768: if ($instcode eq '') {
1769: $instcode = '.';
1770: }
1771: return $instcode;
1772: }
1773:
1774: sub display_adv_courseroles {
1775: my $output;
1776: #
1777: # List course personnel
1778: my %coursepersonnel =
1779: &Apache::lonnet::get_course_adv_roles($env{'request.course.id'});
1780: #
1781: $output = '<br />'.&Apache::loncommon::start_data_table();
1782: foreach my $role (sort(keys(%coursepersonnel))) {
1783: next if ($role =~ /^\s*$/);
1784: $output .= &Apache::loncommon::start_data_table_row().
1785: '<td>'.$role.'</td><td>';
1786: foreach my $user (split(',',$coursepersonnel{$role})) {
1787: my ($puname,$pudom)=split(':',$user);
1788: $output .= ' '.&Apache::loncommon::aboutmewrapper(
1789: &Apache::loncommon::plainname($puname,$pudom),
1790: $puname,$pudom);
1791: }
1792: $output .= '</td>'.&Apache::loncommon::end_data_table_row();
1793: }
1794: $output .= &Apache::loncommon::end_data_table();
1795: }
1796:
1797: sub make_keylist_array {
1798: my ($index,$keylist);
1799: $index->{'domain'} = &Apache::loncoursedata::CL_SDOM();
1800: $index->{'username'} = &Apache::loncoursedata::CL_SNAME();
1801: $index->{'end'} = &Apache::loncoursedata::CL_END();
1802: $index->{'start'} = &Apache::loncoursedata::CL_START();
1803: $index->{'id'} = &Apache::loncoursedata::CL_ID();
1804: $index->{'section'} = &Apache::loncoursedata::CL_SECTION();
1805: $index->{'fullname'} = &Apache::loncoursedata::CL_FULLNAME();
1806: $index->{'status'} = &Apache::loncoursedata::CL_STATUS();
1807: $index->{'type'} = &Apache::loncoursedata::CL_TYPE();
1808: $index->{'lockedtype'} = &Apache::loncoursedata::CL_LOCKEDTYPE();
1809: $index->{'groups'} = &Apache::loncoursedata::CL_GROUP();
1810: $index->{'email'} = &Apache::loncoursedata::CL_PERMANENTEMAIL();
1811: $index->{'role'} = &Apache::loncoursedata::CL_ROLE();
1812: $index->{'extent'} = &Apache::loncoursedata::CL_EXTENT();
1813: foreach my $key (keys(%{$index})) {
1814: $keylist->[$index->{$key}] = $key;
1815: }
1816: return ($index,$keylist);
1817: }
1818:
1819: sub aggregate_user_info {
1820: my ($udom,$uname,$userinfo) = @_;
1821: my %info=&Apache::lonnet::get('environment',
1822: ['firstname','middlename',
1823: 'lastname','generation','id'],
1824: $udom,$uname);
1825: my ($tmp) = keys(%info);
1826: my ($fullname,$id);
1827: if ($tmp =~/^(con_lost|error|no_such_host)/i) {
1828: $fullname = 'not available';
1829: $id = 'not available';
1830: &Apache::lonnet::logthis('unable to retrieve environment '.
1831: 'for '.$uname.':'.$udom);
1.1 raeburn 1832: } else {
1.2 raeburn 1833: $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
1834: $id = $info{'id'};
1835: }
1836: $userinfo->{$uname.':'.$udom} = {
1837: fullname => $fullname,
1838: id => $id,
1839: };
1840: return;
1841: }
1.1 raeburn 1842:
1.2 raeburn 1843: sub process_date_info {
1844: my ($userdata) = @_;
1845: my $now = time;
1846: $userdata->{'status'} = 'Active';
1847: if ($userdata->{'start'} > 0) {
1848: if ($now < $userdata->{'start'}) {
1849: $userdata->{'status'} = 'Future';
1850: }
1.1 raeburn 1851: }
1.2 raeburn 1852: if ($userdata->{'end'} > 0) {
1853: if ($now > $userdata->{'end'}) {
1854: $userdata->{'status'} = 'Expired';
1855: }
1856: }
1857: return;
1.1 raeburn 1858: }
1859:
1860: sub show_users_list {
1.10 raeburn 1861: my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist)=@_;
1.1 raeburn 1862: #
1863: # Variables for excel output
1864: my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
1865: #
1866: # Variables for csv output
1867: my ($CSVfile,$CSVfilename);
1868: #
1869: my $sortby = $env{'form.sortby'};
1.3 raeburn 1870: my @sortable = ('username','domain','id','fullname','start','end','email','role');
1.2 raeburn 1871: if ($context eq 'course') {
1.3 raeburn 1872: push(@sortable,('section','groups','type'));
1.2 raeburn 1873: } else {
1.3 raeburn 1874: push(@sortable,'extent');
1875: }
1876: if (!grep(/^\Q$sortby\E$/,@sortable)) {
1877: $sortby = 'username';
1.1 raeburn 1878: }
1.22 raeburn 1879: my $setting = $env{'form.roletype'};
1.33 raeburn 1880: my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers,$secfilter,$grpfilter);
1.1 raeburn 1881: if ($context eq 'course') {
1.22 raeburn 1882: $cid = $env{'request.course.id'};
1.17 raeburn 1883: ($cnum,$cdom) = &get_course_identity($cid);
1.2 raeburn 1884: ($classgroups) = &Apache::loncoursedata::get_group_memberships(
1885: $userlist,$keylist,$cdom,$cnum);
1.16 raeburn 1886: if ($mode eq 'autoenroll') {
1887: $env{'form.showrole'} = 'st';
1888: } else {
1889: if (! exists($env{'form.displayphotos'})) {
1890: $env{'form.displayphotos'} = 'off';
1891: }
1892: $displayphotos = $env{'form.displayphotos'};
1893: if (! exists($env{'form.displayclickers'})) {
1894: $env{'form.displayclickers'} = 'off';
1895: }
1896: $displayclickers = $env{'form.displayclickers'};
1897: if ($env{'course.'.$cid.'.internal.showphoto'}) {
1898: $r->print('
1.1 raeburn 1899: <script type="text/javascript">
1900: function photowindow(photolink) {
1901: var title = "Photo_Viewer";
1902: var options = "scrollbars=1,resizable=1,menubar=0";
1903: options += ",width=240,height=240";
1904: stdeditbrowser = open(photolink,title,options,"1");
1905: stdeditbrowser.focus();
1906: }
1907: </script>
1.16 raeburn 1908: ');
1909: }
1910: $r->print(<<END);
1.1 raeburn 1911: <input type="hidden" name="displayphotos" value="$displayphotos" />
1912: <input type="hidden" name="displayclickers" value="$displayclickers" />
1913: END
1.16 raeburn 1914: }
1.1 raeburn 1915: }
1.16 raeburn 1916: if ($mode ne 'autoenroll') {
1.11 raeburn 1917: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
1918: my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox");
1.25 raeburn 1919: my $singconfirm = &mt(' for a single user?');
1920: my $multconfirm = &mt(' for multiple users?');
1.11 raeburn 1921: my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode);
1.1 raeburn 1922: $r->print(<<END);
1.10 raeburn 1923:
1924: <script type="text/javascript" language="Javascript">
1.11 raeburn 1925: $check_uncheck_js
1926:
1927: function verify_action (field) {
1928: var numchecked = 0;
1929: var singconf = '$singconfirm';
1930: var multconf = '$multconfirm';
1931: if (field.length > 0) {
1932: for (i = 0; i < field.length; i++) {
1933: if (field[i].checked == true) {
1934: numchecked ++;
1935: }
1936: }
1937: } else {
1938: if (field.checked == true) {
1939: numchecked ++;
1940: }
1941: }
1942: if (numchecked == 0) {
1943: alert("$alert");
1944: }
1945: else {
1946: var message = document.studentform.bulkaction[document.studentform.bulkaction.selectedIndex].text;
1947: if (numchecked == 1) {
1948: message += singconf;
1949: }
1950: else {
1951: message += multconf;
1952: }
1953: if (confirm(message)) {
1954: document.studentform.phase.value = 'bulkchange';
1955: document.studentform.submit();
1956: }
1957: }
1958: }
1.10 raeburn 1959:
1960: function username_display_launch(username,domain) {
1961: var target;
1962: for (var i=0; i<document.studentform.usernamelink.length; i++) {
1963: if (document.studentform.usernamelink[i].checked) {
1964: target = document.studentform.usernamelink[i].value;
1965: }
1966: }
1967: if (target == 'modify') {
1968: document.studentform.srchterm.value=username;
1969: document.studentform.srchdomain.value=domain;
1970: document.studentform.phase.value='get_user_info';
1971: document.studentform.action.value = 'singleuser';
1972: document.studentform.submit();
1973: }
1974: else {
1975: document.location.href = '/adm/'+domain+'/'+username+'/aboutme';
1976: }
1977: }
1978: </script>
1.11 raeburn 1979: $date_sec_selector
1.1 raeburn 1980: <input type="hidden" name="state" value="$env{'form.state'}" />
1981: END
1982: }
1983: $r->print(<<END);
1984: <input type="hidden" name="sortby" value="$sortby" />
1985: END
1986:
1987: my %lt=&Apache::lonlocal::texthash(
1988: 'username' => "username",
1989: 'domain' => "domain",
1990: 'id' => 'ID',
1991: 'fullname' => "name",
1992: 'section' => "section",
1993: 'groups' => "active groups",
1994: 'start' => "start date",
1995: 'end' => "end date",
1996: 'status' => "status",
1.2 raeburn 1997: 'role' => "role",
1.1 raeburn 1998: 'type' => "enroll type/action",
1999: 'email' => "email address",
2000: 'clicker' => "clicker id",
2001: 'photo' => "photo",
1.2 raeburn 2002: 'extent' => "extent",
1.11 raeburn 2003: 'pr' => "Proceed",
2004: 'ca' => "check all",
2005: 'ua' => "uncheck all",
2006: 'ac' => "Action to take for selected users",
1.10 raeburn 2007: 'link' => "Behavior of username links",
2008: 'aboutme' => "Display a user's personal page",
2009: 'modify' => "Modify a user's information",
1.1 raeburn 2010: );
1.2 raeburn 2011: if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
2012: $lt{'extent'} = &mt('Course(s): description, section(s), status');
1.13 raeburn 2013: } elsif ($context eq 'author') {
1.2 raeburn 2014: $lt{'extent'} = &mt('Author');
2015: }
1.1 raeburn 2016: my @cols = ('username','domain','id','fullname');
2017: if ($context eq 'course') {
2018: push(@cols,'section');
2019: }
1.2 raeburn 2020: if (!($context eq 'domain' && $env{'form.roletype'} eq 'course')) {
2021: push(@cols,('start','end'));
2022: }
1.3 raeburn 2023: if ($env{'form.showrole'} eq 'Any' || $env{'form.showrole'} eq 'cr') {
1.2 raeburn 2024: push(@cols,'role');
2025: }
1.13 raeburn 2026: if ($context eq 'domain' && ($env{'form.roletype'} eq 'author' ||
1.2 raeburn 2027: $env{'form.roletype'} eq 'course')) {
2028: push (@cols,'extent');
2029: }
2030: if (($statusmode eq 'Any') &&
2031: (!($context eq 'domain' && $env{'form.roletype'} eq 'course'))) {
1.1 raeburn 2032: push(@cols,'status');
2033: }
2034: if ($context eq 'course') {
2035: push(@cols,'groups');
2036: }
2037: push(@cols,'email');
2038:
1.4 raeburn 2039: my $rolefilter = $env{'form.showrole'};
1.5 raeburn 2040: if ($env{'form.showrole'} eq 'cr') {
2041: $rolefilter = &mt('custom');
2042: } elsif ($env{'form.showrole'} ne 'Any') {
1.2 raeburn 2043: $rolefilter = &Apache::lonnet::plaintext($env{'form.showrole'});
2044: }
1.16 raeburn 2045: my $results_description;
2046: if ($mode ne 'autoenroll') {
2047: $results_description = &results_header_row($rolefilter,$statusmode,
1.24 raeburn 2048: $context,$permission,$mode);
1.16 raeburn 2049: $r->print('<b>'.$results_description.'</b><br />');
2050: }
1.26 raeburn 2051: my ($output,$actionselect,%canchange,%canchangesec);
1.16 raeburn 2052: if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll') {
2053: if ($mode ne 'autoenroll') {
2054: if ($permission->{'cusr'}) {
2055: $actionselect = &select_actions($context,$setting,$statusmode);
2056: }
2057: $r->print(<<END);
1.10 raeburn 2058: <input type="hidden" name="srchby" value="uname" />
2059: <input type="hidden" name="srchin" value="dom" />
2060: <input type="hidden" name="srchtype" value="exact" />
2061: <input type="hidden" name="srchterm" value="" />
1.11 raeburn 2062: <input type="hidden" name="srchdomain" value="" />
1.1 raeburn 2063: END
1.16 raeburn 2064: $output = '<p>';
2065: my @linkdests = ('aboutme');
2066: if ($permission->{'cusr'}) {
2067: push (@linkdests,'modify');
2068: $output .= '<span class="LC_nobreak">'.$lt{'link'}.': ';
2069: my $usernamelink = $env{'form.usernamelink'};
2070: if ($usernamelink eq '') {
2071: $usernamelink = 'aboutme';
2072: }
2073: foreach my $item (@linkdests) {
2074: my $checkedstr = '';
2075: if ($item eq $usernamelink) {
2076: $checkedstr = ' checked="checked" ';
2077: }
2078: $output .= '<label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.'> '.$lt{$item}.'</label> ';
2079: }
2080: $output .= '</span><br />';
2081: } else {
2082: $output .= &mt("Click on a username to view the user's personal page.").'<br />';
2083: }
2084: if ($actionselect) {
2085: $output .= <<"END";
1.11 raeburn 2086: $lt{'ac'}: $actionselect <input type="button" value="$lt{'pr'}" onclick="javascript:verify_action(document.studentform.actionlist)" /></p>
2087: <p><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.actionlist)" />
2088: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.actionlist)" />
2089: END
1.26 raeburn 2090: my @allroles;
2091: if ($env{'form.showrole'} eq 'Any') {
2092: my $custom = 1;
2093: if ($context eq 'domain') {
2094: @allroles = &roles_by_context($setting,$custom);
2095: } else {
2096: @allroles = &roles_by_context($context,$custom);
2097: }
2098: } else {
2099: @allroles = ($env{'form.showrole'});
2100: }
2101: foreach my $role (@allroles) {
2102: if ($context eq 'domain') {
2103: if ($setting eq 'domain') {
2104: if (&Apache::lonnet::allowed('c'.$role,
2105: $env{'request.role.domain'})) {
2106: $canchange{$role} = 1;
2107: }
1.31 raeburn 2108: } elsif ($setting eq 'author') {
2109: if (&Apache::lonnet::allowed('c'.$role,
2110: $env{'request.role.domain'})) {
2111: $canchange{$role} = 1;
2112: }
1.26 raeburn 2113: }
2114: } elsif ($context eq 'author') {
2115: if (&Apache::lonnet::allowed('c'.$role,
2116: $env{'user.domain'}.'/'.$env{'user.name'})) {
2117: $canchange{$role} = 1;
2118: }
2119: } elsif ($context eq 'course') {
2120: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
2121: $canchange{$role} = 1;
2122: } elsif ($env{'request.course.sec'} ne '') {
2123: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
2124: $canchangesec{$role} = $env{'request.course.sec'};
2125: }
2126: }
2127: }
2128: }
1.16 raeburn 2129: }
1.4 raeburn 2130: }
2131: $output .= "\n<p>\n".
1.1 raeburn 2132: &Apache::loncommon::start_data_table().
1.4 raeburn 2133: &Apache::loncommon::start_data_table_header_row();
1.1 raeburn 2134: if ($mode eq 'autoenroll') {
1.4 raeburn 2135: $output .= "
1.1 raeburn 2136: <th><a href=\"javascript:document.studentform.sortby.value='type';document.studentform.submit();\">$lt{'type'}</a></th>
1.4 raeburn 2137: ";
1.1 raeburn 2138: } else {
1.11 raeburn 2139: $output .= "\n".'<th>'.&mt('Count').'</th>'."\n";
2140: if ($actionselect) {
2141: $output .= '<th>'.&mt('Select').'</th>'."\n";
2142: }
1.1 raeburn 2143: }
2144: foreach my $item (@cols) {
1.4 raeburn 2145: $output .= "<th><a href=\"javascript:document.studentform.sortby.value='$item';document.studentform.submit();\">$lt{$item}</a></th>\n";
1.1 raeburn 2146: }
1.2 raeburn 2147: my %role_types = &role_type_names();
1.16 raeburn 2148: if ($context eq 'course' && $mode ne 'autoenroll') {
1.4 raeburn 2149: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
2150: # Clicker display on or off?
2151: my %clicker_options = &Apache::lonlocal::texthash(
2152: 'on' => 'Show',
2153: 'off' => 'Hide',
2154: );
2155: my $clickerchg = 'on';
2156: if ($displayclickers eq 'on') {
2157: $clickerchg = 'off';
2158: }
2159: $output .= ' <th>'."\n".' '.
2160: '<a href="javascript:document.studentform.displayclickers.value='.
1.1 raeburn 2161: "'".$clickerchg."'".';document.studentform.submit();">'.
2162: $clicker_options{$clickerchg}.'</a> '.$lt{'clicker'}."\n".
1.4 raeburn 2163: ' </th>'."\n";
1.1 raeburn 2164:
1.4 raeburn 2165: # Photo display on or off?
2166: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2167: my %photo_options = &Apache::lonlocal::texthash(
2168: 'on' => 'Show',
2169: 'off' => 'Hide',
2170: );
2171: my $photochg = 'on';
2172: if ($displayphotos eq 'on') {
2173: $photochg = 'off';
2174: }
2175: $output .= ' <th>'."\n".' '.
2176: '<a href="javascript:document.studentform.displayphotos.value='.
1.1 raeburn 2177: "'".$photochg."'".';document.studentform.submit();">'.
2178: $photo_options{$photochg}.'</a> '.$lt{'photo'}."\n".
1.4 raeburn 2179: ' </th>'."\n";
2180: }
1.1 raeburn 2181: }
1.4 raeburn 2182: }
1.16 raeburn 2183: $output .= &Apache::loncommon::end_data_table_header_row();
1.1 raeburn 2184: # Done with the HTML header line
2185: } elsif ($mode eq 'csv') {
2186: #
2187: # Open a file
2188: $CSVfilename = '/prtspool/'.
1.2 raeburn 2189: $env{'user.name'}.'_'.$env{'user.domain'}.'_'.
2190: time.'_'.rand(1000000000).'.csv';
1.1 raeburn 2191: unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
2192: $r->log_error("Couldn't open $CSVfilename for output $!");
2193: $r->print("Problems occured in writing the csv file. ".
2194: "This error has been logged. ".
2195: "Please alert your LON-CAPA administrator.");
2196: $CSVfile = undef;
2197: }
2198: #
2199: # Write headers and data to file
1.2 raeburn 2200: print $CSVfile '"'.$results_description.'"'."\n";
1.1 raeburn 2201: print $CSVfile '"'.join('","',map {
2202: &Apache::loncommon::csv_translate($lt{$_})
2203: } (@cols)).'"'."\n";
2204: } elsif ($mode eq 'excel') {
2205: # Create the excel spreadsheet
2206: ($excel_workbook,$excel_filename,$format) =
2207: &Apache::loncommon::create_workbook($r);
2208: return if (! defined($excel_workbook));
2209: $excel_sheet = $excel_workbook->addworksheet('userlist');
1.2 raeburn 2210: $excel_sheet->write($row++,0,$results_description,$format->{'h2'});
1.1 raeburn 2211: #
2212: my @colnames = map {$lt{$_}} (@cols);
2213: $excel_sheet->write($row++,0,\@colnames,$format->{'bold'});
2214: }
2215:
2216: # Done with header lines in all formats
2217:
2218: my %index;
2219: my $i;
1.2 raeburn 2220: foreach my $idx (@$keylist) {
2221: $index{$idx} = $i++;
2222: }
1.4 raeburn 2223: my $usercount = 0;
1.33 raeburn 2224: my ($secfilter,$grpfilter);
2225: if ($context eq 'course') {
2226: $secfilter = $env{'form.secfilter'};
2227: $grpfilter = $env{'form.grpfilter'};
2228: if ($secfilter eq '') {
2229: $secfilter = 'all';
2230: }
2231: if ($grpfilter eq '') {
2232: $grpfilter = 'all';
2233: }
2234: }
1.2 raeburn 2235: # Get groups, role, permanent e-mail so we can sort on them if
2236: # necessary.
2237: foreach my $user (keys(%{$userlist})) {
1.11 raeburn 2238: if ($context eq 'domain' && $user eq $env{'request.role.domain'}.'-domainconfig:'.$env{'request.role.domain'}) {
2239: delete($userlist->{$user});
2240: next;
2241: }
1.2 raeburn 2242: my ($uname,$udom,$role,$groups,$email);
1.5 raeburn 2243: if (($statusmode ne 'Any') &&
2244: ($userlist->{$user}->[$index{'status'}] ne $statusmode)) {
2245: delete($userlist->{$user});
2246: next;
2247: }
1.2 raeburn 2248: if ($context eq 'domain') {
2249: if ($env{'form.roletype'} eq 'domain') {
2250: ($role,$uname,$udom) = split(/:/,$user);
1.11 raeburn 2251: if (($uname eq $env{'request.role.domain'}.'-domainconfig') &&
2252: ($udom eq $env{'request.role.domain'})) {
2253: delete($userlist->{$user});
2254: next;
2255: }
1.13 raeburn 2256: } elsif ($env{'form.roletype'} eq 'author') {
1.2 raeburn 2257: ($uname,$udom,$role) = split(/:/,$user,-1);
2258: } elsif ($env{'form.roletype'} eq 'course') {
2259: ($uname,$udom,$role) = split(/:/,$user);
2260: }
2261: } else {
2262: ($uname,$udom,$role) = split(/:/,$user,-1);
2263: if (($context eq 'course') && $role eq '') {
2264: $role = 'st';
2265: }
2266: }
2267: $userlist->{$user}->[$index{'role'}] = $role;
2268: if (($env{'form.showrole'} ne 'Any') && (!($env{'form.showrole'} eq 'cr' && $role =~ /^cr\//)) && ($role ne $env{'form.showrole'})) {
2269: delete($userlist->{$user});
2270: next;
2271: }
1.33 raeburn 2272: if ($context eq 'course') {
2273: my @ac_groups;
2274: if (ref($classgroups) eq 'HASH') {
2275: $groups = $classgroups->{$user};
2276: }
2277: if (ref($groups->{'active'}) eq 'HASH') {
2278: @ac_groups = keys(%{$groups->{'active'}});
2279: $userlist->{$user}->[$index{'groups'}] = join(', ',@ac_groups);
2280: }
2281: if ($mode ne 'autoenroll') {
2282: my $section = $userlist->{$user}->[$index{'section'}];
2283: if ($secfilter eq 'none') {
2284: if ($section ne '') {
2285: delete($userlist->{$user});
2286: next;
2287: }
2288: } elsif ($secfilter ne 'all') {
2289: if ($section ne $secfilter) {
2290: delete($userlist->{$user});
2291: next;
2292: }
2293: }
2294: if ($grpfilter eq 'none') {
2295: if (@ac_groups > 0) {
2296: delete($userlist->{$user});
2297: next;
2298: }
2299: } elsif ($grpfilter ne 'all') {
2300: if (!grep(/^\Q$grpfilter\E$/,@ac_groups)) {
2301: delete($userlist->{$user});
2302: next;
2303: }
2304: }
2305: }
1.2 raeburn 2306: }
2307: my %emails = &Apache::loncommon::getemails($uname,$udom);
2308: if ($emails{'permanentemail'} =~ /\S/) {
2309: $userlist->{$user}->[$index{'email'}] = $emails{'permanentemail'};
2310: }
1.4 raeburn 2311: $usercount ++;
2312: }
2313: my $autocount = 0;
2314: my $manualcount = 0;
2315: my $lockcount = 0;
2316: my $unlockcount = 0;
2317: if ($usercount) {
2318: $r->print($output);
2319: } else {
2320: if ($mode eq 'autoenroll') {
2321: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
2322: } else {
2323: return;
2324: }
1.1 raeburn 2325: }
1.2 raeburn 2326: #
2327: # Sort the users
1.1 raeburn 2328: my $index = $index{$sortby};
2329: my $second = $index{'username'};
2330: my $third = $index{'domain'};
1.2 raeburn 2331: my @sorted_users = sort {
2332: lc($userlist->{$a}->[$index]) cmp lc($userlist->{$b}->[$index])
1.1 raeburn 2333: ||
1.2 raeburn 2334: lc($userlist->{$a}->[$second]) cmp lc($userlist->{$b}->[$second]) ||
2335: lc($userlist->{$a}->[$third]) cmp lc($userlist->{$b}->[$third])
2336: } (keys(%$userlist));
1.4 raeburn 2337: my $rowcount = 0;
1.2 raeburn 2338: foreach my $user (@sorted_users) {
1.4 raeburn 2339: my %in;
1.2 raeburn 2340: my $sdata = $userlist->{$user};
1.4 raeburn 2341: $rowcount ++;
1.2 raeburn 2342: foreach my $item (@{$keylist}) {
2343: $in{$item} = $sdata->[$index{$item}];
2344: }
1.11 raeburn 2345: my $role = $in{'role'};
1.2 raeburn 2346: $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}]);
2347: if (! defined($in{'start'}) || $in{'start'} == 0) {
2348: $in{'start'} = &mt('none');
2349: } else {
2350: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
1.1 raeburn 2351: }
1.2 raeburn 2352: if (! defined($in{'end'}) || $in{'end'} == 0) {
2353: $in{'end'} = &mt('none');
1.1 raeburn 2354: } else {
1.2 raeburn 2355: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
1.1 raeburn 2356: }
1.2 raeburn 2357: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') {
2358: $r->print(&Apache::loncommon::start_data_table_row());
1.11 raeburn 2359: my $checkval;
1.16 raeburn 2360: if ($mode eq 'autoenroll') {
2361: my $cellentry;
2362: if ($in{'type'} eq 'auto') {
2363: $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label>';
2364: $autocount ++;
2365: } else {
2366: $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><nobr><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label></nobr></td></tr><tr><td><nobr>';
2367: $manualcount ++;
2368: if ($in{'lockedtype'}) {
2369: $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Unlock').'</label>';
2370: $unlockcount ++;
2371: } else {
2372: $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Lock').'</label>';
2373: $lockcount ++;
1.11 raeburn 2374: }
1.16 raeburn 2375: $cellentry .= '</nobr></td></tr></table>';
2376: }
2377: $r->print("<td>$cellentry</td>\n");
2378: } else {
2379: $r->print("<td>$rowcount</td>\n");
2380: $checkval;
2381: if ($actionselect) {
1.26 raeburn 2382: my $showcheckbox;
2383: if ($role =~ /^cr\//) {
2384: $showcheckbox = $canchange{'cr'};
2385: } else {
2386: $showcheckbox = $canchange{$role};
2387: }
2388: if (!$showcheckbox) {
2389: if ($context eq 'course') {
2390: if ($canchangesec{$role} ne '') {
2391: if ($canchangesec{$role} eq $in{'section'}) {
2392: $showcheckbox = 1;
2393: }
2394: }
1.16 raeburn 2395: }
1.26 raeburn 2396: }
2397: if ($showcheckbox) {
2398: $checkval = $user;
2399: if ($context eq 'course') {
2400: if ($role eq 'st') {
2401: $checkval .= ':st';
2402: }
2403: $checkval .= ':'.$in{'section'};
2404: if ($role eq 'st') {
2405: $checkval .= ':'.$in{'type'}.':'.
2406: $in{'lockedtype'};
2407: }
1.16 raeburn 2408: }
1.26 raeburn 2409: $r->print('<td><input type="checkbox" name="'.
2410: 'actionlist" value="'.$checkval.'"></td>');
2411: } else {
2412: $r->print('<td> </td>');
1.16 raeburn 2413: }
1.11 raeburn 2414: }
2415: }
1.2 raeburn 2416: foreach my $item (@cols) {
1.10 raeburn 2417: if ($item eq 'username') {
1.16 raeburn 2418: $r->print('<td>'.&print_username_link($mode,$permission,
2419: \%in).'</td>');
2420: } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) {
1.11 raeburn 2421: $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.$checkval.'_'.$item.'" value="'.$sdata->[$index{$item}].'" /></td>'."\n");
1.10 raeburn 2422: } else {
2423: $r->print('<td>'.$in{$item}.'</td>'."\n");
2424: }
1.2 raeburn 2425: }
1.16 raeburn 2426: if (($context eq 'course') && ($mode ne 'autoenroll')) {
1.4 raeburn 2427: if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
2428: if ($displayclickers eq 'on') {
2429: my $clickers =
1.2 raeburn 2430: (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
1.4 raeburn 2431: if ($clickers!~/\w/) { $clickers='-'; }
2432: $r->print('<td>'.$clickers.'</td>');
1.2 raeburn 2433: } else {
2434: $r->print(' <td> </td> ');
2435: }
1.4 raeburn 2436: if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
2437: if ($displayphotos eq 'on' && $sdata->[$index{'role'}] eq 'st') {
2438: my $imgurl =
2439: &Apache::lonnet::retrievestudentphoto($in{'domain'},$in{'username'},
2440: 'gif','thumbnail');
2441: $r->print(' <td align="right"><a href="javascript:photowindow('."'".&Apache::lonnet::studentphoto($in{'domain'},$in{'username'},'jpg')."'".')"><img src="'.$imgurl.'" border="1"></a></td>');
2442: } else {
2443: $r->print(' <td> </td> ');
2444: }
2445: }
1.2 raeburn 2446: }
2447: }
2448: $r->print(&Apache::loncommon::end_data_table_row());
2449: } elsif ($mode eq 'csv') {
2450: next if (! defined($CSVfile));
2451: # no need to bother with $linkto
2452: if (! defined($in{'start'}) || $in{'start'} == 0) {
2453: $in{'start'} = &mt('none');
2454: } else {
2455: $in{'start'} = &Apache::lonlocal::locallocaltime($in{'start'});
2456: }
2457: if (! defined($in{'end'}) || $in{'end'} == 0) {
2458: $in{'end'} = &mt('none');
2459: } else {
2460: $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
2461: }
2462: my @line = ();
2463: foreach my $item (@cols) {
2464: push @line,&Apache::loncommon::csv_translate($in{$item});
2465: }
2466: print $CSVfile '"'.join('","',@line).'"'."\n";
2467: } elsif ($mode eq 'excel') {
2468: my $col = 0;
2469: foreach my $item (@cols) {
2470: if ($item eq 'start' || $item eq 'end') {
2471: if (defined($item) && $item != 0) {
2472: $excel_sheet->write($row,$col++,
2473: &Apache::lonstathelpers::calc_serial($in{item}),
2474: $format->{'date'});
2475: } else {
2476: $excel_sheet->write($row,$col++,'none');
2477: }
2478: } else {
2479: $excel_sheet->write($row,$col++,$in{$item});
2480: }
2481: }
2482: $row++;
1.1 raeburn 2483: }
2484: }
1.2 raeburn 2485: if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') {
2486: $r->print(&Apache::loncommon::end_data_table().'<br />');
2487: } elsif ($mode eq 'excel') {
2488: $excel_workbook->close();
2489: $r->print('<p><a href="'.$excel_filename.'">'.
2490: &mt('Your Excel spreadsheet').'</a> '.&mt('is ready for download').'.</p>'."\n");
2491: } elsif ($mode eq 'csv') {
2492: close($CSVfile);
2493: $r->print('<a href="'.$CSVfilename.'">'.
2494: &mt('Your CSV file').'</a> is ready for download.'.
2495: "\n");
2496: $r->rflush();
2497: }
2498: if ($mode eq 'autoenroll') {
2499: return ($usercount,$autocount,$manualcount,$lockcount,$unlockcount);
1.4 raeburn 2500: } else {
2501: return ($usercount);
1.2 raeburn 2502: }
1.1 raeburn 2503: }
2504:
1.10 raeburn 2505: sub print_username_link {
1.16 raeburn 2506: my ($mode,$permission,$in) = @_;
1.10 raeburn 2507: my $output;
1.16 raeburn 2508: if ($mode eq 'autoenroll') {
2509: $output = $in->{'username'};
2510: } elsif (!$permission->{'cusr'}) {
1.10 raeburn 2511: $output = &Apache::loncommon::aboutmewrapper($in->{'username'},
2512: $in->{'username'},
2513: $in->{'domain'});
2514: } else {
2515: $output = '<a href="javascript:username_display_launch('.
2516: "'$in->{'username'}','$in->{'domain'}'".')" />'.
2517: $in->{'username'}.'</a>';
2518: }
2519: return $output;
2520: }
2521:
1.2 raeburn 2522: sub role_type_names {
2523: my %lt = &Apache::lonlocal::texthash (
1.13 raeburn 2524: 'domain' => 'Domain Roles',
2525: 'author' => 'Co-Author Roles',
2526: 'course' => 'Course Roles',
1.2 raeburn 2527: );
2528: return %lt;
2529: }
2530:
1.11 raeburn 2531: sub select_actions {
2532: my ($context,$setting,$statusmode) = @_;
2533: my %lt = &Apache::lonlocal::texthash(
2534: revoke => "Revoke user roles",
2535: delete => "Delete user roles",
2536: reenable => "Re-enable expired user roles",
2537: activate => "Make future user roles active now",
2538: chgdates => "Change starting/ending dates",
2539: chgsec => "Change section associated with user roles",
2540: );
2541: my ($output,$options,%choices);
1.23 raeburn 2542: # FIXME Disable actions for now for roletype=course in domain context
2543: if ($context eq 'domain' && $setting eq 'course') {
2544: return;
2545: }
1.26 raeburn 2546: if ($context eq 'course') {
2547: if ($env{'form.showrole'} ne 'Any') {
2548: if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},
2549: $env{'request.course.id'})) {
2550: if ($env{'request.course.sec'} eq '') {
2551: return;
2552: } else {
2553: if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
2554: return;
2555: }
2556: }
2557: }
2558: }
2559: }
1.11 raeburn 2560: if ($statusmode eq 'Any') {
2561: $options .= '
2562: <option value="chgdates">'.$lt{'chgdates'}.'</option>';
2563: $choices{'dates'} = 1;
2564: } else {
2565: if ($statusmode eq 'Future') {
2566: $options .= '
2567: <option value="activate">'.$lt{'activate'}.'</option>';
2568: $choices{'dates'} = 1;
2569: } elsif ($statusmode eq 'Expired') {
2570: $options .= '
2571: <option value="reenable">'.$lt{'reenable'}.'</option>';
2572: $choices{'dates'} = 1;
2573: }
1.13 raeburn 2574: if ($statusmode eq 'Active' || $statusmode eq 'Future') {
2575: $options .= '
2576: <option value="chgdates">'.$lt{'chgdates'}.'</option>
2577: <option value="revoke">'.$lt{'revoke'}.'</option>';
2578: $choices{'dates'} = 1;
2579: }
1.11 raeburn 2580: }
2581: if ($context eq 'domain') {
2582: $options .= '
2583: <option value="delete">'.$lt{'delete'}.'</option>';
2584: }
2585: if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
1.26 raeburn 2586: if (($statusmode ne 'Expired') && ($env{'request.course.sec'} eq '')) {
1.11 raeburn 2587: $options .= '
2588: <option value="chgsec">'.$lt{'chgsec'}.'</option>';
2589: $choices{'sections'} = 1;
2590: }
2591: }
2592: if ($options) {
2593: $output = '<select name="bulkaction" onchange="javascript:opendatebrowser(this.form,'."'studentform'".')" />'."\n".
2594: '<option value="" selected="selected">'.
2595: &mt('Please select').'</option>'."\n".$options."\n".'</select>';
2596: if ($choices{'dates'}) {
2597: $output .=
2598: '<input type="hidden" name="startdate_month" value="" />'."\n".
2599: '<input type="hidden" name="startdate_day" value="" />'."\n".
2600: '<input type="hidden" name="startdate_year" value="" />'."\n".
2601: '<input type="hidden" name="startdate_hour" value="" />'."\n".
2602: '<input type="hidden" name="startdate_minute" value="" />'."\n".
2603: '<input type="hidden" name="startdate_second" value="" />'."\n".
2604: '<input type="hidden" name="enddate_month" value="" />'."\n".
2605: '<input type="hidden" name="enddate_day" value="" />'."\n".
2606: '<input type="hidden" name="enddate_year" value="" />'."\n".
2607: '<input type="hidden" name="enddate_hour" value="" />'."\n".
2608: '<input type="hidden" name="enddate_minute" value="" />'."\n".
2609: '<input type="hidden" name="enddate_second" value="" />'."\n";
2610: if ($context eq 'course') {
2611: $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n";
2612: }
2613: }
2614: if ($choices{'sections'}) {
2615: $output .= '<input type="hidden" name="retainsec" value= "" />'."\n".
2616: '<input type="hidden" name="newsecs" value= "" />'."\n";
2617: }
2618: }
2619: return $output;
2620: }
2621:
2622: sub date_section_javascript {
2623: my ($context,$setting) = @_;
2624: my $title;
2625: if (($context eq 'course') || ($context eq 'domain' && $setting eq 'course')) {
2626: $title = &mt('Date and Section selector');
2627: } else {
2628: $title = &mt('Date selector');
2629: }
2630: my $output = '
2631: <script type="text/javascript">
2632: var stdeditbrowser;'."\n";
2633: $output .= <<"ENDONE";
2634: function opendatebrowser(callingform,formname) {
2635: var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value;
2636: if (bulkaction == 'revoke' || bulkaction == 'delete' || bulkaction == '') {
2637: return;
2638: }
2639: var url = '/adm/createuser?';
2640: var type = '';
2641: var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value;
2642: ENDONE
2643: if ($context eq 'domain') {
2644: $output .= '
2645: type = callingform.roletype.options[callingform.roletype.selectedIndex].value;
2646: ';
2647: }
2648: my $width= '700';
2649: my $height = '400';
2650: $output .= <<"ENDTWO";
2651: url += 'action=dateselect&callingform=' + formname +
2652: '&roletype='+type+'&showrole='+showrole +'&bulkaction='+bulkaction;
2653: var title = '$title';
2654: var options = 'scrollbars=1,resizable=1,menubar=0';
2655: options += ',width=$width,height=$height';
2656: stdeditbrowser = open(url,title,options,'1');
2657: stdeditbrowser.focus();
2658: }
2659: </script>
2660: ENDTWO
2661: return $output;
2662: }
2663:
2664: sub date_section_selector {
1.21 raeburn 2665: my ($context,$permission) = @_;
1.11 raeburn 2666: my $callingform = $env{'form.callingform'};
2667: my $formname = 'dateselect';
2668: my $groupslist = &get_groupslist();
2669: my $sec_js = &setsections_javascript($formname,$groupslist);
2670: my $output = <<"END";
2671: <script type="text/javascript">
2672:
2673: $sec_js
2674:
2675: function saveselections(formname) {
2676:
2677: END
2678: if ($env{'form.bulkaction'} eq 'chgsec') {
2679: $output .= <<"END";
2680: opener.document.$callingform.retainsec.value = formname.retainsec.value;
2681: setSections(formname);
2682: if (seccheck == 'ok') {
2683: opener.document.$callingform.newsecs.value = formname.sections.value;
2684: window.close();
2685: }
2686: return;
2687: END
2688: } else {
2689: if ($context eq 'course') {
2690: if (($env{'form.bulkaction'} eq 'reenable') ||
2691: ($env{'form.bulkaction'} eq 'activate') ||
2692: ($env{'form.bulkaction'} eq 'chgdates')) {
1.26 raeburn 2693: if ($env{'request.course.sec'} eq '') {
2694: $output .= <<"END";
1.11 raeburn 2695:
2696: if (formname.makedatesdefault.checked == true) {
2697: opener.document.$callingform.makedatesdefault.value = 1;
2698: }
2699: else {
2700: opener.document.$callingform.makedatesdefault.value = 0;
2701: }
2702:
2703: END
1.26 raeburn 2704: }
1.11 raeburn 2705: }
2706: }
2707: $output .= <<"END";
2708: opener.document.$callingform.startdate_month.value = formname.startdate_month.options[formname.startdate_month.selectedIndex].value;
2709: opener.document.$callingform.startdate_day.value = formname.startdate_day.value;
2710: opener.document.$callingform.startdate_year.value = formname.startdate_year.value;
2711: opener.document.$callingform.startdate_hour.value = formname.startdate_hour.options[formname.startdate_hour.selectedIndex].value;
2712: opener.document.$callingform.startdate_minute.value = formname.startdate_minute.value;
2713: opener.document.$callingform.startdate_second.value = formname.startdate_second.value;
2714: opener.document.$callingform.enddate_month.value = formname.enddate_month.options[formname.enddate_month.selectedIndex].value;
2715: opener.document.$callingform.enddate_day.value = formname.enddate_day.value;
2716: opener.document.$callingform.enddate_year.value = formname.enddate_year.value;
2717: opener.document.$callingform.enddate_hour.value = formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value;
2718: opener.document.$callingform.enddate_minute.value = formname.enddate_minute.value;
2719: opener.document.$callingform.enddate_second.value = formname.enddate_second.value;
2720: window.close();
2721: END
2722: }
2723: $output .= '
2724: }
2725: </script>
2726: ';
2727: my %lt = &Apache::lonlocal::texthash (
2728: chac => 'Access dates to apply for selected users',
2729: chse => 'Changes in section affiliation to apply to selected users',
2730: fors => 'For student roles changing the section, will result in a section switch as students may only be in one section of a course at a time.',
2731: forn => 'For a role in a course that is not a student role, a user may have roles in more than one section of a course at a time.',
2732: reta => "Retain each user's current section affiliations?",
2733: dnap => '(Does not apply to student roles).',
2734: );
2735: my ($date_items,$headertext);
2736: if ($env{'form.bulkaction'} eq 'chgsec') {
2737: $headertext = $lt{'chse'};
2738: } else {
2739: $headertext = $lt{'chac'};
2740: my $starttime;
2741: if (($env{'form.bulkaction'} eq 'activate') ||
2742: ($env{'form.bulkaction'} eq 'reenable')) {
2743: $starttime = time;
2744: }
2745: $date_items = &date_setting_table($starttime,undef,$context,
1.21 raeburn 2746: $env{'form.bulkaction'},$formname,
2747: $permission);
1.11 raeburn 2748: }
2749: $output .= '<h3>'.$headertext.'</h3>'.
2750: '<form name="'.$formname.'" method="post">'."\n".
2751: $date_items;
2752: if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
1.17 raeburn 2753: my ($cnum,$cdom) = &get_course_identity();
1.11 raeburn 2754: my $info;
2755: if ($env{'form.showrole'} eq 'st') {
2756: $output .= '<p>'.$lt{'fors'}.'</p>';
1.26 raeburn 2757: } elsif ($env{'form.showrole'} eq 'Any') {
1.11 raeburn 2758: $output .= '<p>'.$lt{'fors'}.'</p>'.
2759: '<p>'.$lt{'forn'}.' ';
2760: $info = $lt{'reta'};
2761: } else {
2762: $output .= '<p>'.$lt{'forn'}.' ';
2763: $info = $lt{'reta'};
2764: }
2765: if ($info) {
2766: $info .= '<span class="LC_nobreak">'.
2767: '<label><input type="radio" name="retainsec" value="1" '.
2768: 'checked="checked" />'.&mt('Yes').'</label> '.
2769: '<label><input type="radio" name="retainsec" value="0" />'.
2770: &mt('No').'</label></span>';
2771: if ($env{'form.showrole'} eq 'Any') {
2772: $info .= '<br />'.$lt{'dnap'};
2773: }
2774: $info .= '</p>';
2775: } else {
2776: $info = '<input type="hidden" name="retainsec" value="0" />';
2777: }
1.21 raeburn 2778: my $rowtitle = &mt('New section to assign');
2779: my $secbox = §ion_picker($cdom,$cnum,$env{'form.showrole'},$rowtitle,$permission,$context);
1.11 raeburn 2780: $output .= $info.$secbox;
2781: }
2782: $output .= '<p>'.
2783: &mt('Use "Save" to update the main window with your selections.').'<br /><br />'.
2784: '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n".
2785: '</form>';
2786: return $output;
2787: }
2788:
1.17 raeburn 2789: sub section_picker {
2790: my ($cdom,$cnum,$role,$rowtitle,$permission,$context,$mode) = @_;
2791: my %sections_count = &Apache::loncommon::get_sections($cdom,$cnum);
2792: my $sections_select .= &course_sections(\%sections_count,$role);
2793: my $secbox = '<p>'.&Apache::lonhtmlcommon::start_pick_box()."\n";
2794: if ($mode eq 'upload') {
2795: my ($options,$cb_script,$coursepick) =
2796: &default_role_selector($context,1);
2797: $secbox .= &Apache::lonhtmlcommon::row_title('role','LC_oddrow_value').
2798: $options. &Apache::lonhtmlcommon::row_closure(1)."\n";
2799: }
2800: $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n";
2801: if ($env{'request.course.sec'} eq '') {
2802: $secbox .= '<table class="LC_createuser"><tr class="LC_section_row">'."\n".
2803: '<td align="center">'.&mt('Existing sections')."\n".
2804: '<br />'.$sections_select.'</td><td align="center">'.
2805: &mt('New section').'<br />'."\n".
2806: '<input type="text" name="newsec" size="15" />'."\n".
2807: '<input type="hidden" name="sections" value="" />'."\n".
2808: '</td></tr></table>'."\n";
2809: } else {
2810: $secbox .= '<input type="hidden" name="sections" value="'.
2811: $env{'request.course.sec'}.'" />'.
2812: $env{'request.course.sec'};
2813: }
2814: $secbox .= &Apache::lonhtmlcommon::row_closure(1)."\n".
2815: &Apache::lonhtmlcommon::end_pick_box().'</p>';
2816: return $secbox;
2817: }
2818:
1.2 raeburn 2819: sub results_header_row {
1.24 raeburn 2820: my ($rolefilter,$statusmode,$context,$permission,$mode) = @_;
1.5 raeburn 2821: my ($description,$showfilter);
2822: if ($rolefilter ne 'Any') {
2823: $showfilter = $rolefilter;
2824: }
1.2 raeburn 2825: if ($context eq 'course') {
1.24 raeburn 2826: if ($mode eq 'csv' || $mode eq 'excel') {
2827: $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': ';
2828: }
1.2 raeburn 2829: if ($statusmode eq 'Expired') {
1.5 raeburn 2830: $description .= &mt('Users in course with expired [_1] roles',$showfilter);
1.11 raeburn 2831: } elsif ($statusmode eq 'Future') {
1.5 raeburn 2832: $description .= &mt('Users in course with future [_1] roles',$showfilter);
1.2 raeburn 2833: } elsif ($statusmode eq 'Active') {
1.5 raeburn 2834: $description .= &mt('Users in course with active [_1] roles',$showfilter);
1.2 raeburn 2835: } else {
2836: if ($rolefilter eq 'Any') {
2837: $description .= &mt('All users in course');
2838: } else {
2839: $description .= &mt('All users in course with [_1] roles',$rolefilter);
2840: }
2841: }
1.33 raeburn 2842: my $constraint;
1.26 raeburn 2843: my $viewablesec = &viewable_section($permission);
2844: if ($viewablesec ne '') {
1.15 raeburn 2845: if ($env{'form.showrole'} eq 'st') {
1.33 raeburn 2846: $constraint = &mt('only users in section "[_1]"',$viewablesec);
1.26 raeburn 2847: } elsif ($env{'form.showrole'} ne 'cc') {
1.33 raeburn 2848: $constraint = &mt('only users affiliated with no section or section "[_1]"',$viewablesec);
2849: }
2850: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
2851: if ($env{'form.grpfilter'} eq 'none') {
2852: $constraint .= &mt(' and not in any group');
2853: } else {
2854: $constraint .= &mt(' and members of group: "[_1]"',$env{'form.grpfilter'});
2855: }
2856: }
2857: } else {
2858: if (($env{'form.secfilter'} ne 'all') && ($env{'form.secfilter'} ne '')) {
2859: if ($env{'form.secfilter'} eq 'none') {
2860: $constraint = &mt('only users affiliated with no section');
2861: } else {
2862: $constraint = &mt('only users affiliated with section "[_1]"',$env{'form.secfilter'});
2863: }
2864: }
2865: if (($env{'form.grpfilter'} ne 'all') && ($env{'form.grpfilter'} ne '')) {
2866: if ($env{'form.grpfilter'} eq 'none') {
2867: if ($constraint eq '') {
2868: $constraint = &mt('only users not in any group');
2869: } else {
2870: $constraint .= &mt(' and also not in any group');
2871: }
2872: } else {
2873: if ($constraint eq '') {
2874: $constraint = &mt('only members of group: "[_1]"',$env{'form.grpfilter'});
2875: } else {
2876: $constraint .= &mt(' and also members of group: "[_1]"'.$env{'form.grpfilter'});
2877: }
2878: }
1.15 raeburn 2879: }
2880: }
1.33 raeburn 2881: if ($constraint ne '') {
2882: $description .= ' ('.$constraint.')';
2883: }
1.13 raeburn 2884: } elsif ($context eq 'author') {
1.14 raeburn 2885: $description =
2886: &mt('Author space for <span class="LC_cusr_emph">[_1]</span>',
2887: &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})).': ';
1.2 raeburn 2888: if ($statusmode eq 'Expired') {
1.5 raeburn 2889: $description .= &mt('Co-authors with expired [_1] roles',$showfilter);
1.2 raeburn 2890: } elsif ($statusmode eq 'Future') {
1.5 raeburn 2891: $description .= &mt('Co-authors with future [_1] roles',$showfilter);
1.2 raeburn 2892: } elsif ($statusmode eq 'Active') {
1.5 raeburn 2893: $description .= &mt('Co-authors with active [_1] roles',$showfilter);
1.2 raeburn 2894: } else {
2895: if ($rolefilter eq 'Any') {
1.5 raeburn 2896: $description .= &mt('All co-authors');
1.2 raeburn 2897: } else {
2898: $description .= &mt('All co-authors with [_1] roles',$rolefilter);
2899: }
2900: }
2901: } elsif ($context eq 'domain') {
2902: my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description');
2903: $description = &mt('Domain - ').$domdesc.': ';
2904: if ($env{'form.roletype'} eq 'domain') {
2905: if ($statusmode eq 'Expired') {
1.5 raeburn 2906: $description .= &mt('Users in domain with expired [_1] roles',$showfilter);
1.2 raeburn 2907: } elsif ($statusmode eq 'Future') {
1.5 raeburn 2908: $description .= &mt('Users in domain with future [_1] roles',$showfilter);
1.2 raeburn 2909: } elsif ($statusmode eq 'Active') {
1.5 raeburn 2910: $description .= &mt('Users in domain with active [_1] roles',$showfilter);
1.2 raeburn 2911: } else {
2912: if ($rolefilter eq 'Any') {
1.5 raeburn 2913: $description .= &mt('All users in domain');
1.2 raeburn 2914: } else {
2915: $description .= &mt('All users in domain with [_1] roles',$rolefilter);
2916: }
2917: }
1.13 raeburn 2918: } elsif ($env{'form.roletype'} eq 'author') {
1.2 raeburn 2919: if ($statusmode eq 'Expired') {
1.5 raeburn 2920: $description .= &mt('Co-authors in domain with expired [_1] roles',$showfilter);
1.2 raeburn 2921: } elsif ($statusmode eq 'Future') {
1.5 raeburn 2922: $description .= &mt('Co-authors in domain with future [_1] roles',$showfilter);
1.2 raeburn 2923: } elsif ($statusmode eq 'Active') {
1.5 raeburn 2924: $description .= &mt('Co-authors in domain with active [_1] roles',$showfilter);
1.2 raeburn 2925: } else {
2926: if ($rolefilter eq 'Any') {
1.5 raeburn 2927: $description .= &mt('All users with co-author roles in domain',$showfilter);
1.2 raeburn 2928: } else {
2929: $description .= &mt('All co-authors in domain with [_1] roles',$rolefilter);
2930: }
2931: }
2932: } elsif ($env{'form.roletype'} eq 'course') {
2933: my $coursefilter = $env{'form.coursepick'};
2934: if ($coursefilter eq 'category') {
2935: my $instcode = &instcode_from_coursefilter();
2936: if ($instcode eq '.') {
2937: $description .= &mt('All courses in domain').' - ';
2938: } else {
2939: $description .= &mt('Courses in domain with institutional code: [_1]',$instcode).' - ';
2940: }
2941: } elsif ($coursefilter eq 'selected') {
2942: $description .= &mt('Selected courses in domain').' - ';
2943: } elsif ($coursefilter eq 'all') {
2944: $description .= &mt('All courses in domain').' - ';
2945: }
2946: if ($statusmode eq 'Expired') {
1.5 raeburn 2947: $description .= &mt('users with expired [_1] roles',$showfilter);
1.2 raeburn 2948: } elsif ($statusmode eq 'Future') {
1.5 raeburn 2949: $description .= &mt('users with future [_1] roles',$showfilter);
1.2 raeburn 2950: } elsif ($statusmode eq 'Active') {
1.5 raeburn 2951: $description .= &mt('users with active [_1] roles',$showfilter);
1.2 raeburn 2952: } else {
2953: if ($rolefilter eq 'Any') {
2954: $description .= &mt('all users');
2955: } else {
2956: $description .= &mt('users with [_1] roles',$rolefilter);
2957: }
2958: }
2959: }
2960: }
2961: return $description;
2962: }
1.22 raeburn 2963:
2964: sub viewable_section {
2965: my ($permission) = @_;
2966: my $viewablesec;
2967: if (ref($permission) eq 'HASH') {
2968: if (exists($permission->{'view_section'})) {
2969: $viewablesec = $permission->{'view_section'};
2970: } elsif (exists($permission->{'cusr_section'})) {
2971: $viewablesec = $permission->{'cusr_section'};
2972: }
2973: }
2974: return $viewablesec;
2975: }
2976:
1.2 raeburn 2977:
1.1 raeburn 2978: #################################################
2979: #################################################
2980: sub show_drop_list {
1.30 raeburn 2981: my ($r,$classlist,$nosort,$permission) = @_;
1.29 raeburn 2982: my $cid = $env{'request.course.id'};
1.17 raeburn 2983: my ($cnum,$cdom) = &get_course_identity($cid);
1.1 raeburn 2984: if (! exists($env{'form.sortby'})) {
2985: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
2986: ['sortby']);
2987: }
2988: my $sortby = $env{'form.sortby'};
2989: if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) {
2990: $sortby = 'username';
2991: }
2992: my $action = "drop";
1.17 raeburn 2993: my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript();
1.1 raeburn 2994: $r->print(<<END);
2995: <input type="hidden" name="sortby" value="$sortby" />
2996: <input type="hidden" name="action" value="$action" />
2997: <input type="hidden" name="state" value="done" />
1.17 raeburn 2998: <script type="text/javascript" language="Javascript">
2999: $check_uncheck_js
1.1 raeburn 3000: </script>
3001: <p>
3002: <input type="hidden" name="phase" value="four">
3003: END
1.30 raeburn 3004: my ($indexhash,$keylist) = &make_keylist_array();
3005: my $studentcount = 0;
3006: if (ref($classlist) eq 'HASH') {
3007: foreach my $student (keys(%{$classlist})) {
3008: my $sdata = $classlist->{$student};
3009: my $status = $sdata->[$indexhash->{'status'}];
3010: my $section = $sdata->[$indexhash->{'section'}];
3011: if ($status ne 'Active') {
3012: delete($classlist->{$student});
3013: next;
3014: }
3015: if ($env{'request.course.sec'} ne '') {
3016: if ($section ne $env{'request.course.sec'}) {
3017: delete($classlist->{$student});
3018: next;
3019: }
3020: }
3021: $studentcount ++;
3022: }
3023: }
3024: if (!$studentcount) {
3025: $r->print(&mt('There are no students to drop.'));
3026: return;
3027: }
3028: my ($classgroups) = &Apache::loncoursedata::get_group_memberships(
3029: $classlist,$keylist,$cdom,$cnum);
3030: my %lt=&Apache::lonlocal::texthash('usrn' => "username",
3031: 'dom' => "domain",
3032: 'sn' => "student name",
3033: 'sec' => "section",
3034: 'start' => "start date",
3035: 'end' => "end date",
3036: 'groups' => "active groups",
3037: );
1.1 raeburn 3038: if ($nosort) {
1.17 raeburn 3039: $r->print(&Apache::loncommon::start_data_table().
3040: &Apache::loncommon::start_data_table_header_row());
1.1 raeburn 3041: $r->print(<<END);
3042: <th> </th>
3043: <th>$lt{'usrn'}</th>
3044: <th>$lt{'dom'}</th>
3045: <th>ID</th>
3046: <th>$lt{'sn'}</th>
3047: <th>$lt{'sec'}</th>
3048: <th>$lt{'start'}</th>
3049: <th>$lt{'end'}</th>
3050: <th>$lt{'groups'}</th>
3051: END
1.17 raeburn 3052: $r->print(&Apache::loncommon::end_data_table_header_row());
1.1 raeburn 3053: } else {
1.17 raeburn 3054: $r->print(&Apache::loncommon::start_data_table().
3055: &Apache::loncommon::start_data_table_header_row());
1.1 raeburn 3056: $r->print(<<END);
1.17 raeburn 3057: <th> </th>
1.1 raeburn 3058: <th>
1.17 raeburn 3059: <a href="/adm/createuser?action=$action&sortby=username">$lt{'usrn'}</a>
1.1 raeburn 3060: </th><th>
1.17 raeburn 3061: <a href="/adm/createuser?action=$action&sortby=domain">$lt{'dom'}</a>
1.1 raeburn 3062: </th><th>
1.17 raeburn 3063: <a href="/adm/createuser?action=$action&sortby=id">ID</a>
1.1 raeburn 3064: </th><th>
1.17 raeburn 3065: <a href="/adm/createuser?action=$action&sortby=fullname">$lt{'sn'}</a>
1.1 raeburn 3066: </th><th>
1.17 raeburn 3067: <a href="/adm/createuser?action=$action&sortby=section">$lt{'sec'}</a>
1.1 raeburn 3068: </th><th>
1.17 raeburn 3069: <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
1.1 raeburn 3070: </th><th>
1.17 raeburn 3071: <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
1.1 raeburn 3072: </th><th>
1.17 raeburn 3073: <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
1.1 raeburn 3074: </th>
3075: END
1.17 raeburn 3076: $r->print(&Apache::loncommon::end_data_table_header_row());
1.1 raeburn 3077: }
3078: #
3079: # Sort the students
1.30 raeburn 3080: my $index = $indexhash->{$sortby};
3081: my $second = $indexhash->{'username'};
3082: my $third = $indexhash->{'domain'};
1.1 raeburn 3083: my @Sorted_Students = sort {
3084: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
3085: ||
3086: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
3087: ||
3088: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1.30 raeburn 3089: } (keys(%{$classlist}));
1.1 raeburn 3090: foreach my $student (@Sorted_Students) {
3091: my $error;
3092: my $sdata = $classlist->{$student};
1.30 raeburn 3093: my $username = $sdata->[$indexhash->{'username'}];
3094: my $domain = $sdata->[$indexhash->{'domain'}];
3095: my $section = $sdata->[$indexhash->{'section'}];
3096: my $name = $sdata->[$indexhash->{'fullname'}];
3097: my $id = $sdata->[$indexhash->{'id'}];
3098: my $start = $sdata->[$indexhash->{'start'}];
3099: my $end = $sdata->[$indexhash->{'end'}];
1.1 raeburn 3100: my $groups = $classgroups->{$student};
3101: my $active_groups;
3102: if (ref($groups->{active}) eq 'HASH') {
3103: $active_groups = join(', ',keys(%{$groups->{'active'}}));
3104: }
3105: if (! defined($start) || $start == 0) {
3106: $start = &mt('none');
3107: } else {
3108: $start = &Apache::lonlocal::locallocaltime($start);
3109: }
3110: if (! defined($end) || $end == 0) {
3111: $end = &mt('none');
3112: } else {
3113: $end = &Apache::lonlocal::locallocaltime($end);
3114: }
1.17 raeburn 3115: my $studentkey = $student.':'.$section;
1.30 raeburn 3116: my $startitem = '<input type="hidden" name="'.$studentkey.'_start" value="'.$sdata->[$indexhash->{'start'}].'" />';
1.1 raeburn 3117: #
3118: $r->print(&Apache::loncommon::start_data_table_row());
3119: $r->print(<<"END");
1.29 raeburn 3120: <td><input type="checkbox" name="droplist" value="$studentkey"></td>
1.1 raeburn 3121: <td>$username</td>
3122: <td>$domain</td>
3123: <td>$id</td>
3124: <td>$name</td>
3125: <td>$section</td>
1.29 raeburn 3126: <td>$start $startitem</td>
1.1 raeburn 3127: <td>$end</td>
3128: <td>$active_groups</td>
3129: END
3130: $r->print(&Apache::loncommon::end_data_table_row());
3131: }
3132: $r->print(&Apache::loncommon::end_data_table().'<br />');
3133: %lt=&Apache::lonlocal::texthash(
1.29 raeburn 3134: 'dp' => "Drop Students",
1.1 raeburn 3135: 'ca' => "check all",
3136: 'ua' => "uncheck all",
3137: );
3138: $r->print(<<"END");
3139: </p><p>
3140: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)">
3141: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)">
3142: <p><input type=submit value="$lt{'dp'}"></p>
3143: END
3144: return;
3145: }
3146:
3147: #
3148: # Print out the initial form to get the file containing a list of users
3149: #
3150: sub print_first_users_upload_form {
3151: my ($r,$context) = @_;
3152: my $str;
3153: $str = '<input type="hidden" name="phase" value="two">';
3154: $str .= '<input type="hidden" name="action" value="upload" />';
3155: $str .= '<input type="hidden" name="state" value="got_file" />';
1.2 raeburn 3156: $str .= "<h3>".&mt('Upload a file containing information about users')."</h3>\n";
1.1 raeburn 3157: $str .= &Apache::loncommon::upfile_select_html();
3158: $str .= "<p>\n";
3159: $str .= '<input type="submit" name="fileupload" value="'.
1.2 raeburn 3160: &mt('Upload file of users').'">'."\n";
1.1 raeburn 3161: $str .= '<label><input type="checkbox" name="noFirstLine" /> '.
3162: &mt('Ignore First Line')."</label></p>\n";
3163: $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List",
3164: &mt("How do I create a users list from a spreadsheet")).
3165: "<br />\n";
3166: $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
3167: &mt("How do I create a CSV file from a spreadsheet")).
3168: "<br />\n";
3169: $str .= &Apache::loncommon::end_page();
3170: $r->print($str);
3171: return;
3172: }
3173:
3174: # ================================================= Drop/Add from uploaded file
3175: sub upfile_drop_add {
1.21 raeburn 3176: my ($r,$context,$permission) = @_;
1.1 raeburn 3177: &Apache::loncommon::load_tmp_file($r);
3178: my @userdata=&Apache::loncommon::upfile_record_sep();
3179: if($env{'form.noFirstLine'}){shift(@userdata);}
3180: my @keyfields = split(/\,/,$env{'form.keyfields'});
3181: my %fields=();
3182: for (my $i=0; $i<=$env{'form.nfields'}; $i++) {
3183: if ($env{'form.upfile_associate'} eq 'reverse') {
3184: if ($env{'form.f'.$i} ne 'none') {
3185: $fields{$keyfields[$i]}=$env{'form.f'.$i};
3186: }
3187: } else {
3188: $fields{$env{'form.f'.$i}}=$keyfields[$i];
3189: }
3190: }
1.29 raeburn 3191: if ($env{'form.fullup'} ne 'yes') {
3192: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n".
3193: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />');
3194: }
1.1 raeburn 3195: #
3196: # Store the field choices away
3197: foreach my $field (qw/username names
3198: fname mname lname gen id sec ipwd email role/) {
3199: $env{'form.'.$field.'_choice'}=$fields{$field};
3200: }
3201: &Apache::loncommon::store_course_settings('enrollment_upload',
3202: { 'username_choice' => 'scalar',
3203: 'names_choice' => 'scalar',
3204: 'fname_choice' => 'scalar',
3205: 'mname_choice' => 'scalar',
3206: 'lname_choice' => 'scalar',
3207: 'gen_choice' => 'scalar',
3208: 'id_choice' => 'scalar',
3209: 'sec_choice' => 'scalar',
3210: 'ipwd_choice' => 'scalar',
3211: 'email_choice' => 'scalar',
3212: 'role_choice' => 'scalar' });
3213: #
3214: my ($startdate,$enddate) = &get_dates_from_form();
3215: if ($env{'form.makedatesdefault'}) {
1.27 raeburn 3216: $r->print(&make_dates_default($startdate,$enddate,$context));
1.1 raeburn 3217: }
3218: # Determine domain and desired host (home server)
3219: my $domain=$env{'request.role.domain'};
3220: my $desiredhost = $env{'form.lcserver'};
3221: if (lc($desiredhost) eq 'default') {
3222: $desiredhost = undef;
3223: } else {
3224: my %home_servers = &Apache::lonnet::get_servers($domain,'library');
3225: if (! exists($home_servers{$desiredhost})) {
3226: $r->print('<span class="LC_error">'.&mt('Error').
3227: &mt('Invalid home server specified').'</span>');
3228: $r->print(&Apache::loncommon::end_page());
3229: return;
3230: }
3231: }
3232: # Determine authentication mechanism
3233: my $changeauth;
3234: if ($context eq 'domain') {
3235: $changeauth = $env{'form.changeauth'};
3236: }
3237: my $amode = '';
3238: my $genpwd = '';
3239: if ($env{'form.login'} eq 'krb') {
3240: $amode='krb';
3241: $amode.=$env{'form.krbver'};
3242: $genpwd=$env{'form.krbarg'};
3243: } elsif ($env{'form.login'} eq 'int') {
3244: $amode='internal';
3245: if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) {
3246: $genpwd=$env{'form.intarg'};
3247: }
3248: } elsif ($env{'form.login'} eq 'loc') {
3249: $amode='localauth';
3250: if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) {
3251: $genpwd=$env{'form.locarg'};
3252: }
3253: }
3254: if ($amode =~ /^krb/) {
3255: if (! defined($genpwd) || $genpwd eq '') {
3256: $r->print('<span class="Error">'.
3257: &mt('Unable to enroll users').' '.
3258: &mt('No Kerberos domain was specified.').'</span></p>');
3259: $amode = ''; # This causes the loop below to be skipped
3260: }
3261: }
3262: my ($cid,$defaultsec,$defaultrole,$setting);
3263: if ($context eq 'domain') {
3264: $setting = $env{'form.roleaction'};
3265: if ($setting eq 'domain') {
3266: $defaultrole = $env{'form.defaultrole'};
3267: } elsif ($setting eq 'course') {
3268: $defaultrole = $env{'form.courserole'};
1.27 raeburn 3269: $defaultsec = $env{'form.sections'};
1.1 raeburn 3270: }
1.13 raeburn 3271: } elsif ($context eq 'author') {
1.1 raeburn 3272: $defaultrole = $env{'form.defaultrole'};
1.27 raeburn 3273: } elsif ($context eq 'course') {
3274: $defaultrole = $env{'form.defaultrole'};
3275: $defaultsec = $env{'form.sections'};
1.1 raeburn 3276: }
1.27 raeburn 3277: if ($env{'request.course.id'} ne '') {
3278: $cid = $env{'request.course.id'};
3279: } elsif ($setting eq 'course') {
3280: if (&Apache::lonnet::is_course($env{'form.dcdomain'},$env{'form.dccourse'})) {
3281: $cid = $env{'form.dcdomain'}.'_'.$env{'form.dccourse'};
1.1 raeburn 3282: }
3283: }
1.27 raeburn 3284: # Check to see if user information can be changed
3285: my @userinfo = ('firstname','middlename','lastname','generation',
3286: 'permanentemail','id');
3287: my %canmodify;
3288: if (&Apache::lonnet::allowed('mau',$domain)) {
3289: foreach my $field (@userinfo) {
3290: $canmodify{$field} = 1;
3291: }
3292: }
3293: my (%userlist,%modifiable_fields,@poss_roles);
3294: my $secidx = &Apache::loncoursedata::CL_SECTION();
3295: my @courseroles = &roles_by_context('course',1);
3296: if (!&Apache::lonnet::allowed('mau',$domain)) {
3297: if ($context eq 'course' || $context eq 'author') {
3298: @poss_roles = &curr_role_permissions($context);
3299: my @statuses = ('active','future');
3300: my ($indexhash,$keylist) = &make_keylist_array();
3301: my %info;
3302: foreach my $role (@poss_roles) {
3303: %{$modifiable_fields{$role}} = &can_modify_userinfo($context,$domain,
3304: \@userinfo,[$role]);
3305: }
3306: if ($context eq 'course') {
3307: my ($cnum,$cdom) = &get_course_identity();
3308: my $roster = &Apache::loncoursedata::get_classlist();
3309: %userlist = %{$roster};
3310: my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef,
3311: \@statuses,\@poss_roles);
3312: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
3313: \%advrolehash,$permission);
3314: } elsif ($context eq 'author') {
3315: my %cstr_roles = &Apache::lonnet::get_my_roles(undef,undef,undef,
3316: \@statuses,\@poss_roles);
3317: &gather_userinfo($context,'view',\%userlist,$indexhash,\%info,
3318: \%cstr_roles,$permission);
3319:
3320: }
3321: }
1.1 raeburn 3322: }
3323: if ( $domain eq &LONCAPA::clean_domain($domain)
3324: && ($amode ne '')) {
3325: #######################################
3326: ## Add/Modify Users ##
3327: #######################################
3328: if ($context eq 'course') {
3329: $r->print('<h3>'.&mt('Enrolling Users')."</h3>\n<p>\n");
1.13 raeburn 3330: } elsif ($context eq 'author') {
1.1 raeburn 3331: $r->print('<h3>'.&mt('Updating Co-authors')."</h3>\n<p>\n");
3332: } else {
3333: $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n");
3334: }
3335: my %counts = (
3336: user => 0,
3337: auth => 0,
3338: role => 0,
3339: );
3340: my $flushc=0;
3341: my %student=();
1.27 raeburn 3342: my (%curr_groups,@sections,@cleansec,@secs,$defaultwarn,$groupwarn);
1.1 raeburn 3343: my %userchg;
1.27 raeburn 3344: if ($context eq 'course' || $setting eq 'course') {
3345: if ($context eq 'course') {
3346: # Get information about course groups
3347: %curr_groups = &Apache::longroup::coursegroups();
3348: } elsif ($setting eq 'course') {
3349: if ($cid) {
3350: %curr_groups =
3351: &Apache::longroup::coursegroups($env{'form.dcdomain'},
3352: $env{'form.dccourse'});
3353: }
3354: }
3355: # determine section number
3356: if ($defaultsec =~ /,/) {
3357: push(@sections,split(/,/,$defaultsec));
3358: } else {
3359: push(@sections,$defaultsec);
3360: }
3361: # remove non alphanumeric values from section
3362: foreach my $item (@sections) {
3363: $item =~ s/\W//g;
3364: if ($item eq "none" || $item eq 'all') {
3365: $defaultwarn = &mt('Default section name [_1] could not be used as it is a reserved word.',$item);
3366: } elsif ($item ne '' && exists($curr_groups{$item})) {
3367: $groupwarn = &mt('Default section name "[_1]" is the name of a course group. Section names and group names must be distinct.',$item);
3368: } elsif ($item ne '') {
3369: push(@cleansec,$item);
3370: }
3371: }
3372: if ($defaultwarn) {
3373: $r->print($defaultwarn.'<br />');
3374: }
3375: if ($groupwarn) {
3376: $r->print($groupwarn.'<br />');
3377: }
1.1 raeburn 3378: }
1.5 raeburn 3379: my (%curr_rules,%got_rules,%alerts);
1.27 raeburn 3380: my %customroles = &my_custom_roles();
3381: my ($custom_ok,@permitted_roles) =
3382: &roles_on_upload($context,%customroles);
1.1 raeburn 3383: # Get new users list
1.27 raeburn 3384: foreach my $line (@userdata) {
3385: my %entries=&Apache::loncommon::record_sep($line);
1.1 raeburn 3386: # Determine user name
3387: unless (($entries{$fields{'username'}} eq '') ||
3388: (!defined($entries{$fields{'username'}}))) {
3389: my ($fname, $mname, $lname,$gen) = ('','','','');
3390: if (defined($fields{'names'})) {
3391: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
3392: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
3393: } else {
3394: if (defined($fields{'fname'})) {
3395: $fname=$entries{$fields{'fname'}};
3396: }
3397: if (defined($fields{'mname'})) {
3398: $mname=$entries{$fields{'mname'}};
3399: }
3400: if (defined($fields{'lname'})) {
3401: $lname=$entries{$fields{'lname'}};
3402: }
3403: if (defined($fields{'gen'})) {
3404: $gen=$entries{$fields{'gen'}};
3405: }
3406: }
3407: if ($entries{$fields{'username'}}
3408: ne &LONCAPA::clean_username($entries{$fields{'username'}})) {
3409: $r->print('<br />'.
3410: &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]',
3411: $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
3412: '</b>');
1.27 raeburn 3413: next;
1.1 raeburn 3414: } else {
1.5 raeburn 3415: my $username = $entries{$fields{'username'}};
1.27 raeburn 3416: if (defined($fields{'sec'})) {
3417: if (defined($entries{$fields{'sec'}})) {
3418: my $item = $entries{$fields{'sec'}};
3419: $item =~ s/(\s+$|^\s+)//g;
3420: if ($item eq "none" || $item eq 'all') {
3421: $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',$username,$fname,$mname,$lname,$gen,$item));
3422: next;
3423: } elsif (exists($curr_groups{$item})) {
3424: $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.',$username,$fname,$mname,$lname,$gen,$item).' '.&mt('Section names and group names must be distinct.'));
3425: next;
3426: } else {
3427: push(@secs,$item);
3428: }
3429: }
3430: }
3431: if ($env{'request.course.sec'} ne '') {
3432: @secs = ($env{'request.course.sec'});
3433: if (ref($userlist{$username.':'.$domain}) eq 'ARRAY') {
3434: my $currsec = $userlist{$username.':'.$domain}[$secidx];
3435: if ($currsec ne $env{'request.course.sec'}) {
3436: $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',$username,$fname,$mname,$lname,$gen,$secs[0]).'<br />');
3437: if ($currsec eq '') {
3438: $r->print(&mt('This user already has an active/future student role in the course, unaffiliated to any section.'));
3439:
3440: } else {
3441: $r->print(&mt('This user already has an active/future role in section "[_1]" of the course.',$currsec));
3442: }
3443: $r->print('<br />'.&mt('Although your current role has privileges to add students to section "[_1]", you do not have privileges to modify existing enrollments in other sections.',$secs[0]).'<br />');
3444: next;
1.1 raeburn 3445: }
3446: }
1.27 raeburn 3447: } elsif ($context eq 'course' || $setting eq 'course') {
3448: if (@secs == 0) {
3449: @secs = @cleansec;
1.1 raeburn 3450: }
3451: }
3452: # determine id number
3453: my $id='';
3454: if (defined($fields{'id'})) {
3455: if (defined($entries{$fields{'id'}})) {
3456: $id=$entries{$fields{'id'}};
3457: }
3458: $id=~tr/A-Z/a-z/;
3459: }
3460: # determine email address
3461: my $email='';
3462: if (defined($fields{'email'})) {
3463: if (defined($entries{$fields{'email'}})) {
3464: $email=$entries{$fields{'email'}};
3465: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } }
3466: }
3467: # determine user password
3468: my $password = $genpwd;
3469: if (defined($fields{'ipwd'})) {
3470: if ($entries{$fields{'ipwd'}}) {
3471: $password=$entries{$fields{'ipwd'}};
3472: }
3473: }
3474: # determine user role
3475: my $role = '';
3476: if (defined($fields{'role'})) {
3477: if ($entries{$fields{'role'}}) {
1.27 raeburn 3478: if (grep(/^\Q$entries{$fields{'role'}}\E$/,@permitted_roles)) {
1.1 raeburn 3479: $role=$entries{$fields{'role'}};
1.27 raeburn 3480: $role =~ s/(\s+$|^\s+)//g;
3481: }
3482: if ($custom_ok) {
3483: if ($customroles{$role}) {
3484: $role = 'cr_'.$env{'user.domain'}.'_'.$env{'user.name'}.'_'.$entries{$fields{'role'}};
3485: }
3486: }
3487: if ($role eq '') {
3488: my $rolestr = join(', ',@permitted_roles);
1.1 raeburn 3489: $r->print('<br />'.
3490: &mt('<b>[_1]</b>: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'<br />'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n");
3491: next;
3492: }
3493: }
3494: }
3495: if ($role eq '') {
3496: $role = $defaultrole;
3497: }
3498: # Clean up whitespace
3499: foreach (\$domain,\$username,\$id,\$fname,\$mname,
1.27 raeburn 3500: \$lname,\$gen) {
1.1 raeburn 3501: $$_ =~ s/(\s+$|^\s+)//g;
3502: }
1.5 raeburn 3503: # check against rules
3504: my $checkid = 0;
3505: my $newuser = 0;
3506: my (%rulematch,%inst_results,%idinst_results);
3507: my $uhome=&Apache::lonnet::homeserver($username,$domain);
3508: if ($uhome eq 'no_host') {
3509: $checkid = 1;
3510: $newuser = 1;
3511: my $checkhash;
3512: my $checks = { 'username' => 1 };
3513: $checkhash->{$username.':'.$domain} = { 'newuser' => 1, };
3514: &Apache::loncommon::user_rule_check($checkhash,$checks,
3515: \%alerts,\%rulematch,\%inst_results,\%curr_rules,
3516: \%got_rules);
3517: if (ref($alerts{'username'}) eq 'HASH') {
3518: if (ref($alerts{'username'}{$domain}) eq 'HASH') {
3519: next if ($alerts{'username'}{$domain}{$username});
3520: }
3521: }
1.13 raeburn 3522: } else {
1.27 raeburn 3523: if ($context eq 'course' || $context eq 'author') {
3524: if ($role eq '') {
3525: my @checkroles;
3526: foreach my $role (@poss_roles) {
3527: my $endkey;
3528: if ($role ne 'st') {
3529: $endkey = ':'.$role;
3530: }
3531: if (exists($userlist{$username.':'.$domain.$endkey})) {
3532: if (!grep(/^\Q$role\E$/,@checkroles)) {
3533: push(@checkroles,$role);
3534: }
3535: }
3536: }
3537: if (@checkroles > 0) {
3538: %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles);
3539: }
3540: } elsif (ref($modifiable_fields{$role}) eq 'HASH') {
3541: %canmodify = %{$modifiable_fields{$role}};
3542: }
3543: }
3544: my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id);
3545: for (my $i=0; $i<@userinfo; $i++) {
3546: if (${$newinfo[$i]} ne '') {
3547: if (!$canmodify{$userinfo[$i]}) {
3548: ${$newinfo[$i]} = '';
3549: }
3550: }
3551: }
1.5 raeburn 3552: }
3553: if ($id ne '') {
3554: if (!$newuser) {
3555: my %idhash = &Apache::lonnet::idrget($domain,($username));
3556: if ($idhash{$username} ne $id) {
3557: $checkid = 1;
3558: }
3559: }
3560: if ($checkid) {
3561: my $checkhash;
3562: my $checks = { 'id' => 1 };
3563: $checkhash->{$username.':'.$domain} = { 'newuser' => $newuser,
3564: 'id' => $id };
3565: &Apache::loncommon::user_rule_check($checkhash,$checks,
3566: \%alerts,\%rulematch,\%idinst_results,\%curr_rules,
3567: \%got_rules);
3568: if (ref($alerts{'id'}) eq 'HASH') {
3569: if (ref($alerts{'id'}{$domain}) eq 'HASH') {
3570: next if ($alerts{'id'}{$domain}{$id});
3571: }
3572: }
3573: }
3574: }
1.1 raeburn 3575: if ($password || $env{'form.login'} eq 'loc') {
1.27 raeburn 3576: my $multiple = 0;
3577: my ($userresult,$authresult,$roleresult,$idresult);
3578: my (%userres,%authres,%roleres,%idres);
1.1 raeburn 3579: if ($role eq 'st') {
1.27 raeburn 3580: my $sec;
3581: if ($cid) {
3582: if (@secs > 0) {
3583: $sec = $secs[0];
3584: }
3585: &modifystudent($domain,$username,$cid,$sec,
3586: $desiredhost);
3587: $roleresult =
3588: &Apache::lonnet::modifystudent
3589: ($domain,$username,$id,$amode,$password,
3590: $fname,$mname,$lname,$gen,$sec,$enddate,
3591: $startdate,$env{'form.forceid'},
3592: $desiredhost,$email,'manual','',$cid);
3593: $userresult = $roleresult;
3594: }
1.1 raeburn 3595: } else {
1.27 raeburn 3596: if (($context eq 'course') ||
3597: (grep(/^\Q$role\E$/,@courseroles))) {
3598: if (!$cid) {
3599: next;
3600: }
3601: }
3602: my $singlesec;
3603: if ((grep(/^\Q$role\E$/,@courseroles)) && ($role ne 'cc')) {
3604: if (@secs > 1) {
3605: $multiple = 1;
3606: foreach my $sec (@secs) {
3607: ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) =
3608: &modifyuserrole($context,$setting,
3609: $changeauth,$cid,$domain,$username,
3610: $id,$amode,$password,$fname,
3611: $mname,$lname,$gen,$sec,
3612: $env{'form.forceid'},$desiredhost,
3613: $email,$role,$enddate,$startdate,$checkid);
3614: }
3615: } elsif (@secs > 0) {
3616: $singlesec = $secs[0];
3617: }
3618: }
3619: if (!$multiple) {
1.28 raeburn 3620: ($userresult,$authresult,$roleresult,$idresult) =
1.27 raeburn 3621: &modifyuserrole($context,$setting,
3622: $changeauth,$cid,$domain,$username,
3623: $id,$amode,$password,$fname,
3624: $mname,$lname,$gen,$singlesec,
3625: $env{'form.forceid'},$desiredhost,
3626: $email,$role,$enddate,$startdate,$checkid);
3627: }
3628: }
3629: if ($multiple) {
3630: foreach my $sec (sort(keys(%userres))) {
3631: $flushc =
3632: &user_change_result($r,$userres{$sec},$authres{$sec},
3633: $roleres{$sec},$idres{$sec},\%counts,$flushc,
3634: $username,\%userchg);
3635:
3636: }
3637: } else {
3638: $flushc =
3639: &user_change_result($r,$userresult,$authresult,
1.28 raeburn 3640: $roleresult,$idresult,\%counts,$flushc,
1.29 raeburn 3641: $username,\%userchg);
1.1 raeburn 3642: }
3643: } else {
3644: if ($context eq 'course') {
3645: $r->print('<br />'.
3646: &mt('<b>[_1]</b>: Unable to enroll. No password specified.',$username)
3647: );
1.13 raeburn 3648: } elsif ($context eq 'author') {
1.1 raeburn 3649: $r->print('<br />'.
3650: &mt('<b>[_1]</b>: Unable to add co-author. No password specified.',$username)
3651: );
3652: } else {
3653: $r->print('<br />'.
3654: &mt('<b>[_1]</b>: Unable to add user. No password specified.',$username)
3655: );
3656: }
3657: }
3658: }
3659: }
3660: } # end of foreach (@userdata)
3661: # Flush the course logs so reverse user roles immediately updated
1.5 raeburn 3662: &Apache::lonnet::flushcourselogs();
1.29 raeburn 3663: $r->print("</p>\n<p>\n".&mt('Processed [quant,_1,user].',$counts{'user'}).
1.1 raeburn 3664: "</p>\n");
3665: if ($counts{'role'} > 0) {
3666: $r->print("<p>\n".
1.29 raeburn 3667: &mt('Roles added for [quant,_1,user].',$counts{'role'}).' '.&mt('If a user is currently logged-in to LON-CAPA, any new roles which are active will be available when the user next logs in.')."</p>\n");
3668: } else {
3669: $r->print('<p>'.&mt('No roles added').'</p>');
1.1 raeburn 3670: }
3671: if ($counts{'auth'} > 0) {
3672: $r->print("<p>\n".
3673: &mt('Authentication changed for [_1] existing users.',
3674: $counts{'auth'})."</p>\n");
3675: }
1.13 raeburn 3676: $r->print(&print_namespacing_alerts($domain,\%alerts,\%curr_rules));
1.1 raeburn 3677: #####################################
1.29 raeburn 3678: # Display list of students to drop #
1.1 raeburn 3679: #####################################
3680: if ($env{'form.fullup'} eq 'yes') {
1.29 raeburn 3681: $r->print('<h3>'.&mt('Students to Drop')."</h3>\n");
1.1 raeburn 3682: # Get current classlist
1.30 raeburn 3683: my $classlist = &Apache::loncoursedata::get_classlist();
1.1 raeburn 3684: if (! defined($classlist)) {
1.29 raeburn 3685: $r->print('<form name="studentform" method="post" action="/adm/createuser" />'.
3686: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'.
3687: &mt('There are no students with current/future access to the course.').
3688: '</form>'."\n");
1.1 raeburn 3689: } else {
3690: # Remove the students we just added from the list of students.
1.30 raeburn 3691: foreach my $line (@userdata) {
3692: my %entries=&Apache::loncommon::record_sep($line);
1.1 raeburn 3693: unless (($entries{$fields{'username'}} eq '') ||
3694: (!defined($entries{$fields{'username'}}))) {
3695: delete($classlist->{$entries{$fields{'username'}}.
3696: ':'.$domain});
3697: }
3698: }
3699: # Print out list of dropped students.
1.30 raeburn 3700: &show_drop_list($r,$classlist,'nosort',$permission);
1.1 raeburn 3701: }
3702: }
3703: } # end of unless
1.29 raeburn 3704: if ($env{'form.fullup'} ne 'yes') {
3705: $r->print('</form>');
3706: }
1.1 raeburn 3707: }
3708:
1.13 raeburn 3709: sub print_namespacing_alerts {
3710: my ($domain,$alerts,$curr_rules) = @_;
3711: my $output;
3712: if (ref($alerts) eq 'HASH') {
3713: if (keys(%{$alerts}) > 0) {
3714: if (ref($alerts->{'username'}) eq 'HASH') {
3715: foreach my $dom (sort(keys(%{$alerts->{'username'}}))) {
3716: my $count;
3717: if (ref($alerts->{'username'}{$dom}) eq 'HASH') {
3718: $count = keys(%{$alerts->{'username'}{$dom}});
3719: }
3720: my $domdesc = &Apache::lonnet::domain($domain,'description');
3721: if (ref($curr_rules->{$dom}) eq 'HASH') {
3722: $output .= &Apache::loncommon::instrule_disallow_msg(
3723: 'username',$domdesc,$count,'upload');
3724: }
3725: $output .= &Apache::loncommon::user_rule_formats($dom,
3726: $domdesc,$curr_rules->{$dom}{'username'},
3727: 'username');
3728: }
3729: }
3730: if (ref($alerts->{'id'}) eq 'HASH') {
3731: foreach my $dom (sort(keys(%{$alerts->{'id'}}))) {
3732: my $count;
3733: if (ref($alerts->{'id'}{$dom}) eq 'HASH') {
3734: $count = keys(%{$alerts->{'id'}{$dom}});
3735: }
3736: my $domdesc = &Apache::lonnet::domain($domain,'description');
3737: if (ref($curr_rules->{$dom}) eq 'HASH') {
3738: $output .= &Apache::loncommon::instrule_disallow_msg(
3739: 'id',$domdesc,$count,'upload');
3740: }
3741: $output .= &Apache::loncommon::user_rule_formats($dom,
3742: $domdesc,$curr_rules->{$dom}{'id'},'id');
3743: }
3744: }
3745: }
3746: }
3747: }
3748:
1.1 raeburn 3749: sub user_change_result {
1.29 raeburn 3750: my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc,
3751: $username,$userchg) = @_;
1.1 raeburn 3752: my $okresult = 0;
3753: if ($userresult ne 'ok') {
3754: if ($userresult =~ /^error:(.+)$/) {
3755: my $error = $1;
3756: $r->print('<br />'.
3757: &mt('<b>[_1]</b>: Unable to add/modify: [_2]',$username,$error));
3758: }
3759: } else {
3760: $counts->{'user'} ++;
3761: $okresult = 1;
3762: }
3763: if ($authresult ne 'ok') {
3764: if ($authresult =~ /^error:(.+)$/) {
3765: my $error = $1;
3766: $r->print('<br />'.
3767: &mt('<b>[_1]</b>: Unable to modify authentication: [_2]',$username,$error));
3768: }
3769: } else {
3770: $counts->{'auth'} ++;
3771: $okresult = 1;
3772: }
3773: if ($roleresult ne 'ok') {
3774: if ($roleresult =~ /^error:(.+)$/) {
3775: my $error = $1;
3776: $r->print('<br />'.
3777: &mt('<b>[_1]</b>: Unable to add role: [_2]',$username,$error));
3778: }
3779: } else {
3780: $counts->{'role'} ++;
3781: $okresult = 1;
3782: }
3783: if ($okresult) {
3784: $flushc++;
3785: $userchg->{$username}=1;
3786: $r->print('. ');
3787: if ($flushc>15) {
3788: $r->rflush;
3789: $flushc=0;
3790: }
3791: }
1.29 raeburn 3792: if ($idresult) {
3793: $r->print($idresult);
3794: }
1.1 raeburn 3795: return $flushc;
3796: }
3797:
3798: # ========================================================= Menu Phase Two Drop
1.17 raeburn 3799: sub print_drop_menu {
3800: my ($r,$context,$permission) = @_;
3801: $r->print('<h3>'.&mt("Drop Students").'</h3>'."\n".
3802: '<form name="studentform" method="post">'."\n");
1.30 raeburn 3803: my $classlist = &Apache::loncoursedata::get_classlist();
1.1 raeburn 3804: if (! defined($classlist)) {
3805: $r->print(&mt('There are no students currently enrolled.')."\n");
1.30 raeburn 3806: } else {
3807: &show_drop_list($r,$classlist,'nosort',$permission);
1.1 raeburn 3808: }
1.17 raeburn 3809: $r->print('</form>'. &Apache::loncommon::end_page());
1.1 raeburn 3810: return;
3811: }
3812:
3813: # ================================================================== Phase four
3814:
1.11 raeburn 3815: sub update_user_list {
3816: my ($r,$context,$setting,$choice) = @_;
3817: my $now = time;
1.1 raeburn 3818: my $count=0;
1.11 raeburn 3819: my @changelist;
1.29 raeburn 3820: if ($choice eq 'drop') {
3821: @changelist = &Apache::loncommon::get_env_multiple('form.droplist');
3822: } else {
1.11 raeburn 3823: @changelist = &Apache::loncommon::get_env_multiple('form.actionlist');
3824: }
3825: my %result_text = ( ok => { 'revoke' => 'Revoked',
3826: 'delete' => 'Deleted',
3827: 'reenable' => 'Re-enabled',
1.17 raeburn 3828: 'activate' => 'Activated',
3829: 'chgdates' => 'Changed Access Dates for',
3830: 'chgsec' => 'Changed section for',
3831: 'drop' => 'Dropped',
1.11 raeburn 3832: },
3833: error => {'revoke' => 'revoking',
3834: 'delete' => 'deleting',
3835: 'reenable' => 're-enabling',
3836: 'activate' => 'activating',
1.17 raeburn 3837: 'chgdates' => 'changing access dates for',
3838: 'chgsec' => 'changing section for',
3839: 'drop' => 'dropping',
1.11 raeburn 3840: },
3841: );
3842: my ($startdate,$enddate);
3843: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
3844: ($startdate,$enddate) = &get_dates_from_form();
3845: }
3846: foreach my $item (@changelist) {
3847: my ($role,$uname,$udom,$cid,$sec,$scope,$result,$type,$locktype,@sections,
3848: $scopestem);
1.17 raeburn 3849: if ($choice eq 'drop') {
3850: ($uname,$udom,$sec) = split(/:/,$item,-1);
3851: $role = 'st';
3852: $cid = $env{'request.course.id'};
3853: $scopestem = '/'.$cid;
3854: $scopestem =~s/\_/\//g;
3855: if ($sec eq '') {
3856: $scope = $scopestem;
3857: } else {
3858: $scope = $scopestem.'/'.$sec;
3859: }
3860: } elsif ($context eq 'course') {
1.11 raeburn 3861: ($uname,$udom,$role,$sec,$type,$locktype) = split(/\:/,$item,-1);
3862: $cid = $env{'request.course.id'};
3863: $scopestem = '/'.$cid;
3864: $scopestem =~s/\_/\//g;
3865: if ($sec eq '') {
3866: $scope = $scopestem;
3867: } else {
3868: $scope = $scopestem.'/'.$sec;
3869: }
1.13 raeburn 3870: } elsif ($context eq 'author') {
1.11 raeburn 3871: ($uname,$udom,$role) = split(/\:/,$item,-1);
3872: $scope = '/'.$env{'user.domain'}.'/'.$env{'user.name'};
3873: } elsif ($context eq 'domain') {
3874: if ($setting eq 'domain') {
3875: ($role,$uname,$udom) = split(/\:/,$item,-1);
3876: $scope = '/'.$env{'request.role.domain'}.'/';
1.13 raeburn 3877: } elsif ($setting eq 'author') {
1.11 raeburn 3878: ($uname,$udom,$role,$scope) = split(/\:/,$item);
3879: } elsif ($setting eq 'course') {
3880: ($uname,$udom,$role,$cid,$sec,$type,$locktype) =
3881: split(/\:/,$item);
3882: $scope = '/'.$cid;
3883: $scope =~s/\_/\//g;
3884: if ($sec ne '') {
3885: $scope .= '/'.$sec;
3886: }
3887: }
3888: }
3889: my $plrole = &Apache::lonnet::plaintext($role);
3890: my $start = $env{'form.'.$item.'_start'};
3891: my $end = $env{'form.'.$item.'_end'};
1.17 raeburn 3892: if ($choice eq 'drop') {
3893: # drop students
3894: $end = $now;
3895: $type = 'manual';
3896: $result =
3897: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
3898: } elsif ($choice eq 'revoke') {
3899: # revoke or delete user role
1.11 raeburn 3900: $end = $now;
3901: if ($role eq 'st') {
3902: $result =
3903: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
3904: } else {
3905: $result =
3906: &Apache::lonnet::revokerole($udom,$uname,$scope,$role);
3907: }
3908: } elsif ($choice eq 'delete') {
3909: if ($role eq 'st') {
1.29 raeburn 3910: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid);
3911: }
3912: $result =
3913: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now,
3914: $start,1);
1.11 raeburn 3915: } else {
3916: #reenable, activate, change access dates or change section
3917: if ($choice ne 'chgsec') {
3918: $start = $startdate;
3919: $end = $enddate;
3920: }
3921: if ($choice eq 'reenable') {
3922: if ($role eq 'st') {
3923: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
3924: } else {
3925: $result =
3926: &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
3927: $now);
3928: }
3929: } elsif ($choice eq 'activate') {
3930: if ($role eq 'st') {
3931: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
3932: } else {
3933: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
3934: $now);
3935: }
3936: } elsif ($choice eq 'chgdates') {
3937: if ($role eq 'st') {
3938: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid);
3939: } else {
3940: $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end,
3941: $start);
3942: }
3943: } elsif ($choice eq 'chgsec') {
3944: my (@newsecs,$revresult,$nochg,@retained);
3945: if ($role ne 'cc') {
3946: @newsecs = split(/,/,$env{'form.newsecs'});
3947: }
3948: # remove existing section if not to be retained.
3949: if (!$env{'form.retainsec'}) {
3950: if ($sec eq '') {
3951: if (@newsecs == 0) {
3952: $result = &mt('No change in section assignment (none)');
3953: $nochg = 1;
3954: }
3955: } else {
1.28 raeburn 3956: if (@newsecs > 0) {
3957: if (grep(/^\Q$sec\E$/,@newsecs)) {
3958: push(@retained,$sec);
3959: } else {
3960: $revresult =
3961: &Apache::lonnet::revokerole($udom,$uname,
3962: $scope,$role);
3963: }
3964: } else {
1.11 raeburn 3965: $revresult =
1.28 raeburn 3966: &Apache::lonnet::revokerole($udom,$uname,
3967: $scope,$role);
1.11 raeburn 3968: }
3969: }
3970: } else {
1.28 raeburn 3971: if ($sec eq '') {
3972: $nochg = 1;
3973: } else {
3974: push(@retained,$sec);
3975: }
1.11 raeburn 3976: }
3977: # add new sections
3978: if (@newsecs == 0) {
3979: if (!$nochg) {
1.28 raeburn 3980: if ($role eq 'st') {
3981: $result =
3982: &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid);
3983: } else {
3984: my $newscope = $scopestem;
3985: $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start);
1.11 raeburn 3986: }
3987: }
3988: } else {
3989: foreach my $newsec (@newsecs) {
3990: if (!grep(/^\Q$newsec\E$/,@retained)) {
3991: if ($role eq 'st') {
3992: $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid);
3993: } else {
3994: my $newscope = $scopestem;
3995: if ($newsec ne '') {
3996: $newscope .= '/'.$newsec;
3997: }
3998: $result = &Apache::lonnet::assignrole($udom,$uname,
3999: $newscope,$role,$end,$start);
4000: }
4001: }
4002: }
4003: }
4004: }
4005: }
1.17 raeburn 4006: my $extent = $scope;
4007: if ($choice eq 'drop' || $context eq 'course') {
4008: my ($cnum,$cdom,$cdesc) = &get_course_identity($cid);
4009: if ($cdesc) {
4010: $extent = $cdesc;
4011: }
4012: }
1.1 raeburn 4013: if ($result eq 'ok' || $result eq 'ok:') {
1.11 raeburn 4014: $r->print(&mt("$result_text{'ok'}{$choice} role of '[_1]' in [_2] for [_3]",
1.17 raeburn 4015: $plrole,$extent,$uname.':'.$udom).'<br />');
1.1 raeburn 4016: $count++;
4017: } else {
4018: $r->print(
1.29 raeburn 4019: &mt("Error $result_text{'error'}{$choice} [_1] in [_2] for [_3]: [_4].",
1.17 raeburn 4020: $plrole,$extent,$uname.':'.$udom,$result).'<br />');
1.11 raeburn 4021: }
4022: }
1.32 raeburn 4023: $r->print('<form name="studentform" method="post" action="/adm/createuser">'."\n");
1.33 raeburn 4024: if ($choice eq 'drop') {
4025: $r->print('<input type="hidden" name="action" value="listusers" />'."\n".
4026: '<input type="hidden" name="Status" value="Active" />'."\n".
4027: '<input type="hidden" name="showrole" value="st" />'."\n");
4028: } else {
4029: foreach my $item ('action','sortby','roletype','showrole','Status','secfilter','grpfilter') {
4030: if ($env{'form.'.$item} ne '') {
4031: $r->print('<input type="hidden" name="'.$item.'" value="'.$env{'form.'.$item}.
4032: '" />'."\n");
4033: }
1.32 raeburn 4034: }
4035: }
1.29 raeburn 4036: $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} role(s) for [quant,_1,user,users,no users].",$count).'</b></p>');
1.11 raeburn 4037: if ($count > 0) {
1.17 raeburn 4038: if ($choice eq 'revoke' || $choice eq 'drop') {
1.11 raeburn 4039: $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.</p>'));
4040: }
4041: # Flush the course logs so reverse user roles immediately updated
4042: &Apache::lonnet::flushcourselogs();
4043: }
4044: if ($env{'form.makedatesdefault'}) {
4045: if ($choice eq 'chgdates' || $choice eq 'reenable' || $choice eq 'activate') {
1.29 raeburn 4046: $r->print(&make_dates_default($startdate,$enddate,$context));
1.1 raeburn 4047: }
4048: }
1.33 raeburn 4049: my $linktext = &mt('Display User Lists');
4050: if ($choice eq 'drop') {
4051: $linktext = &mt('Display current class roster');
4052: }
4053: $r->print('<a href="javascript:document.studentform.submit()">'.$linktext.'</a></form>'."\n");
1.1 raeburn 4054: }
4055:
1.8 raeburn 4056: sub classlist_drop {
1.29 raeburn 4057: my ($scope,$uname,$udom,$now) = @_;
1.8 raeburn 4058: my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)});
1.29 raeburn 4059: if (&Apache::lonnet::is_course($cdom,$cnum)) {
4060: my $user = $uname.':'.$udom;
1.8 raeburn 4061: if (!&active_student_roles($cnum,$cdom,$uname,$udom)) {
4062: my $result =
4063: &Apache::lonnet::cput('classlist',
1.29 raeburn 4064: { $user => $now },$cdom,$cnum);
1.8 raeburn 4065: return &mt('Drop from classlist: [_1]',
4066: '<b>'.$result.'</b>').'<br />';
4067: }
4068: }
4069: }
4070:
4071: sub active_student_roles {
4072: my ($cnum,$cdom,$uname,$udom) = @_;
4073: my %roles =
4074: &Apache::lonnet::get_my_roles($uname,$udom,'userroles',
4075: ['future','active'],['st']);
4076: return exists($roles{"$cnum:$cdom:st"});
4077: }
4078:
1.1 raeburn 4079: sub section_check_js {
1.8 raeburn 4080: my $groupslist= &get_groupslist();
1.1 raeburn 4081: return <<"END";
4082: function validate(caller) {
1.9 raeburn 4083: var groups = new Array($groupslist);
1.1 raeburn 4084: var secname = caller.value;
4085: if ((secname == 'all') || (secname == 'none')) {
4086: alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
4087: return 'error';
4088: }
4089: if (secname != '') {
4090: for (var k=0; k<groups.length; k++) {
4091: if (secname == groups[k]) {
4092: alert("'"+secname+"' may not be used as the name for a section, as it is the name of a course group.\\nSection names and group names must be distinct. Please choose a different section name.");
4093: return 'error';
4094: }
4095: }
4096: }
4097: return 'ok';
4098: }
4099: END
4100: }
4101:
4102: sub set_login {
4103: my ($dom,$authformkrb,$authformint,$authformloc) = @_;
4104: my %domconfig = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
4105: my $response;
4106: my ($authnum,%can_assign) =
4107: &Apache::loncommon::get_assignable_auth($dom);
4108: if ($authnum) {
4109: $response = &Apache::loncommon::start_data_table();
4110: if (($can_assign{'krb4'}) || ($can_assign{'krb5'})) {
4111: $response .= &Apache::loncommon::start_data_table_row().
4112: '<td>'.$authformkrb.'</td>'.
4113: &Apache::loncommon::end_data_table_row()."\n";
4114: }
4115: if ($can_assign{'int'}) {
4116: $response .= &Apache::loncommon::start_data_table_row().
4117: '<td>'.$authformint.'</td>'.
4118: &Apache::loncommon::end_data_table_row()."\n"
4119: }
4120: if ($can_assign{'loc'}) {
4121: $response .= &Apache::loncommon::start_data_table_row().
4122: '<td>'.$authformloc.'</td>'.
4123: &Apache::loncommon::end_data_table_row()."\n";
4124: }
4125: $response .= &Apache::loncommon::end_data_table();
4126: }
4127: return $response;
4128: }
4129:
1.8 raeburn 4130: sub course_sections {
4131: my ($sections_count,$role) = @_;
4132: my $output = '';
4133: my @sections = (sort {$a <=> $b} keys %{$sections_count});
1.29 raeburn 4134: my $numsec = scalar(@sections);
4135: if ($numsec <= 1) {
1.8 raeburn 4136: $output = '<select name="currsec_'.$role.'" >'."\n".
1.29 raeburn 4137: ' <option value="">'.&mt('Select').'</option>'."\n".
4138: ' <option value="">'.&mt('No section').'</option>'."\n";
4139: if ($numsec == 1) {
4140: $output .=
1.8 raeburn 4141: ' <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n";
1.29 raeburn 4142: }
1.8 raeburn 4143: } else {
4144: $output = '<select name="currsec_'.$role.'" ';
4145: my $multiple = 4;
4146: if (scalar(@sections) < 4) { $multiple = scalar(@sections); }
1.29 raeburn 4147: if ($role eq 'st') {
4148: $output .= '>'."\n".
4149: ' <option value="">'.&mt('Select').'</option>'."\n".
4150: ' <option value="">'.&mt('No section')."</option>\n";
4151: } else {
4152: $output .= 'multiple="multiple" size="'.$multiple.'">'."\n";
4153: }
1.8 raeburn 4154: foreach my $sec (@sections) {
4155: $output .= '<option value="'.$sec.'">'.$sec."</option>\n";
4156: }
4157: }
4158: $output .= '</select>';
4159: return $output;
4160: }
4161:
4162: sub get_groupslist {
4163: my $groupslist;
4164: my %curr_groups = &Apache::longroup::coursegroups();
4165: if (%curr_groups) {
4166: $groupslist = join('","',sort(keys(%curr_groups)));
4167: $groupslist = '"'.$groupslist.'"';
4168: }
1.11 raeburn 4169: return $groupslist;
1.8 raeburn 4170: }
4171:
4172: sub setsections_javascript {
1.28 raeburn 4173: my ($formname,$groupslist,$mode) = @_;
4174: my ($checkincluded,$finish,$rolecode,$setsection_js);
4175: if ($mode eq 'upload') {
4176: $checkincluded = 'formname.name == "'.$formname.'"';
4177: $finish = "return 'ok';";
4178: $rolecode = "var role = formname.defaultrole.options[formname.defaultrole.selectedIndex].value;\n";
4179: } elsif ($formname eq 'cu') {
1.8 raeburn 4180: $checkincluded = 'formname.elements[i-1].checked == true';
4181: $finish = 'formname.submit()';
1.28 raeburn 4182: $rolecode = "var match = str.split('_');
4183: var role = match[3];\n";
4184: } elsif ($formname eq 'enrollstudent') {
4185: $checkincluded = 'formname.name == "'.$formname.'"';
4186: $finish = 'formname.submit()';
4187: $rolecode = "var match = str.split('_');
4188: var role = match[1];\n";
1.8 raeburn 4189: } else {
1.28 raeburn 4190: $checkincluded = 'formname.name == "'.$formname.'"';
1.8 raeburn 4191: $finish = "seccheck = 'ok';";
1.28 raeburn 4192: $rolecode = "var match = str.split('_');
4193: var role = match[1];\n";
1.11 raeburn 4194: $setsection_js = "var seccheck = 'alert';";
1.8 raeburn 4195: }
4196: my %alerts = &Apache::lonlocal::texthash(
4197: secd => 'Section designations do not apply to Course Coordinator roles.',
4198: accr => 'A course coordinator role will be added with access to all sections.',
4199: inea => 'In each course, each user may only have one student role at a time.',
4200: youh => 'You had selected ',
4201: secs => 'sections.',
4202: plmo => 'Please modify your selections so they include no more than one section.',
4203: mayn => 'may not be used as the name for a section, as it is a reserved word.',
4204: plch => 'Please choose a different section name.',
4205: mnot => 'may not be used as a section name, as it is the name of a course group.',
4206: secn => 'Section names and group names must be distinct. Please choose a different section name.',
1.11 raeburn 4207: );
1.8 raeburn 4208: $setsection_js .= <<"ENDSECCODE";
4209:
4210: function setSections(formname) {
4211: var re1 = /^currsec_/;
4212: var groups = new Array($groupslist);
4213: for (var i=0;i<formname.elements.length;i++) {
4214: var str = formname.elements[i].name;
4215: var checkcurr = str.match(re1);
4216: if (checkcurr != null) {
4217: if ($checkincluded) {
1.28 raeburn 4218: $rolecode
1.8 raeburn 4219: if (role == 'cc') {
4220: alert("$alerts{'secd'}\\n$alerts{'accr'}");
4221: }
4222: else {
4223: var sections = '';
4224: var numsec = 0;
4225: var sections;
4226: for (var j=0; j<formname.elements[i].length; j++) {
4227: if (formname.elements[i].options[j].selected == true ) {
4228: if (formname.elements[i].options[j].value != "") {
4229: if (numsec == 0) {
4230: if (formname.elements[i].options[j].value != "") {
4231: sections = formname.elements[i].options[j].value;
4232: numsec ++;
4233: }
4234: }
4235: else {
4236: sections = sections + "," + formname.elements[i].options[j].value
4237: numsec ++;
4238: }
4239: }
4240: }
4241: }
4242: if (numsec > 0) {
4243: if (formname.elements[i+1].value != "" && formname.elements[i+1].value != null) {
4244: sections = sections + "," + formname.elements[i+1].value;
4245: }
4246: }
4247: else {
4248: sections = formname.elements[i+1].value;
4249: }
4250: var newsecs = formname.elements[i+1].value;
4251: var numsplit;
4252: if (newsecs != null && newsecs != "") {
4253: numsplit = newsecs.split(/,/g);
4254: numsec = numsec + numsplit.length;
4255: }
4256:
4257: if ((role == 'st') && (numsec > 1)) {
4258: alert("$alerts{'inea'} $alerts{'youh'} "+numsec+" $alerts{'secs'}\\n$alerts{'plmo'}")
4259: return;
4260: }
4261: else {
4262: if (numsplit != null) {
4263: for (var j=0; j<numsplit.length; j++) {
4264: if ((numsplit[j] == 'all') ||
4265: (numsplit[j] == 'none')) {
4266: alert("'"+numsplit[j]+"' $alerts{'mayn'}\\n$alerts{'plch'}");
4267: return;
4268: }
4269: for (var k=0; k<groups.length; k++) {
4270: if (numsplit[j] == groups[k]) {
4271: alert("'"+numsplit[j]+"' $alerts{'mnot'}\\n$alerts{'secn'}");
4272: return;
4273: }
4274: }
4275: }
4276: }
4277: formname.elements[i+2].value = sections;
4278: }
4279: }
4280: }
4281: }
4282: }
4283: $finish
4284: }
4285: ENDSECCODE
1.11 raeburn 4286: return $setsection_js;
1.8 raeburn 4287: }
4288:
1.15 raeburn 4289: sub can_create_user {
4290: my ($dom,$context,$usertype) = @_;
4291: my %domconf = &Apache::lonnet::get_dom('configuration',['usercreation'],$dom);
4292: my $cancreate = 1;
1.28 raeburn 4293: if (&Apache::lonnet::allowed('mau',$dom)) {
4294: return $cancreate;
4295: }
1.15 raeburn 4296: if (ref($domconf{'usercreation'}) eq 'HASH') {
4297: if (ref($domconf{'usercreation'}{'cancreate'}) eq 'HASH') {
4298: if ($context eq 'course' || $context eq 'author') {
4299: my $creation = $domconf{'usercreation'}{'cancreate'}{$context};
4300: if ($creation eq 'none') {
4301: $cancreate = 0;
4302: } elsif ($creation ne 'any') {
4303: if (defined($usertype)) {
4304: if ($creation ne $usertype) {
4305: $cancreate = 0;
4306: }
4307: }
4308: }
4309: }
4310: }
4311: }
4312: return $cancreate;
4313: }
4314:
1.20 raeburn 4315: sub can_modify_userinfo {
4316: my ($context,$dom,$fields,$userroles) = @_;
4317: my %domconfig =
4318: &Apache::lonnet::get_dom('configuration',['usermodification'],
4319: $dom);
4320: my %canmodify;
4321: if (ref($fields) eq 'ARRAY') {
4322: foreach my $field (@{$fields}) {
4323: $canmodify{$field} = 0;
4324: if (&Apache::lonnet::allowed('mau',$dom)) {
4325: $canmodify{$field} = 1;
4326: } else {
4327: if (ref($domconfig{'usermodification'}) eq 'HASH') {
4328: if (ref($domconfig{'usermodification'}{$context}) eq 'HASH') {
4329: if (ref($userroles) eq 'ARRAY') {
4330: foreach my $role (@{$userroles}) {
4331: my $testrole;
4332: if ($role =~ /^cr\//) {
4333: $testrole = 'cr';
4334: } else {
4335: $testrole = $role;
4336: }
4337: if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') {
4338: if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {
4339: $canmodify{$field} = 1;
4340: last;
4341: }
4342: }
4343: }
4344: } else {
4345: foreach my $key (keys(%{$domconfig{'usermodification'}{$context}})) {
4346: if (ref($domconfig{'usermodification'}{$context}{$key}) eq 'HASH') {
4347: if ($domconfig{'usermodification'}{$context}{$key}{$field}) {
4348: $canmodify{$field} = 1;
4349: last;
4350: }
4351: }
4352: }
4353: }
4354: }
4355: } elsif ($context eq 'course') {
4356: if (ref($userroles) eq 'ARRAY') {
4357: if (grep(/^st$/,@{$userroles})) {
4358: $canmodify{$field} = 1;
4359: }
4360: } else {
4361: $canmodify{$field} = 1;
4362: }
4363: }
4364: }
4365: }
4366: }
4367: return %canmodify;
4368: }
4369:
1.18 raeburn 4370: sub check_usertype {
4371: my ($dom,$uname,$rules) = @_;
4372: my $usertype;
4373: if (ref($rules) eq 'HASH') {
4374: my @user_rules = keys(%{$rules});
4375: if (@user_rules > 0) {
4376: my %rule_check = &Apache::lonnet::inst_rulecheck($dom,$uname,undef,'username',\@user_rules);
4377: if (keys(%rule_check) > 0) {
4378: $usertype = 'unofficial';
4379: foreach my $item (keys(%rule_check)) {
4380: if ($rule_check{$item}) {
4381: $usertype = 'official';
4382: last;
4383: }
4384: }
4385: }
4386: }
4387: }
4388: return $usertype;
4389: }
4390:
1.17 raeburn 4391: sub roles_by_context {
4392: my ($context,$custom) = @_;
4393: my @allroles;
4394: if ($context eq 'course') {
4395: @allroles = ('st','ad','ta','ep','in','cc');
4396: if ($custom) {
4397: push(@allroles,'cr');
4398: }
4399: } elsif ($context eq 'author') {
4400: @allroles = ('ca','aa');
4401: } elsif ($context eq 'domain') {
4402: @allroles = ('li','dg','sc','au','dc');
4403: }
4404: return @allroles;
4405: }
4406:
1.16 raeburn 4407: sub get_permission {
1.17 raeburn 4408: my ($context,$roles) = @_;
1.16 raeburn 4409: my %permission;
4410: if ($context eq 'course') {
1.17 raeburn 4411: my $custom = 1;
4412: my @allroles = &roles_by_context($context,$custom);
4413: foreach my $role (@allroles) {
4414: if (&Apache::lonnet::allowed('c'.$role,$env{'request.course.id'})) {
4415: $permission{'cusr'} = 1;
4416: last;
4417: }
1.16 raeburn 4418: }
4419: if (&Apache::lonnet::allowed('ccr',$env{'request.course.id'})) {
4420: $permission{'custom'} = 1;
4421: }
4422: if (&Apache::lonnet::allowed('vcl',$env{'request.course.id'})) {
4423: $permission{'view'} = 1;
4424: }
4425: if (!$permission{'view'}) {
4426: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
4427: $permission{'view'} = &Apache::lonnet::allowed('vcl',$scope);
4428: if ($permission{'view'}) {
4429: $permission{'view_section'} = $env{'request.course.sec'};
4430: }
4431: }
1.17 raeburn 4432: if (!$permission{'cusr'}) {
4433: if ($env{'request.course.sec'} ne '') {
4434: my $scope = $env{'request.course.id'}.'/'.$env{'request.course.sec'};
4435: $permission{'cusr'} = (&Apache::lonnet::allowed('cst',$scope));
4436: if ($permission{'cusr'}) {
4437: $permission{'cusr_section'} = $env{'request.course.sec'};
4438: }
4439: }
4440: }
1.16 raeburn 4441: if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
4442: $permission{'grp_manage'} = 1;
4443: }
4444: } elsif ($context eq 'author') {
4445: $permission{'cusr'} = &authorpriv($env{'user.name'},$env{'request.role.domain'});
4446: $permission{'view'} = $permission{'cusr'};
4447: } else {
1.17 raeburn 4448: my @allroles = &roles_by_context($context);
4449: foreach my $role (@allroles) {
1.28 raeburn 4450: if (&Apache::lonnet::allowed('c'.$role,$env{'request.role.domain'})) {
4451: $permission{'cusr'} = 1;
1.17 raeburn 4452: last;
4453: }
4454: }
4455: if (!$permission{'cusr'}) {
4456: if (&Apache::lonnet::allowed('mau',$env{'request.role.domain'})) {
4457: $permission{'cusr'} = 1;
4458: }
1.16 raeburn 4459: }
4460: if (&Apache::lonnet::allowed('ccr',$env{'request.role.domain'})) {
4461: $permission{'custom'} = 1;
4462: }
4463: $permission{'view'} = $permission{'cusr'};
4464: }
4465: my $allowed = 0;
4466: foreach my $perm (values(%permission)) {
4467: if ($perm) { $allowed=1; last; }
4468: }
4469: return (\%permission,$allowed);
4470: }
4471:
4472: # ==================================================== Figure out author access
4473:
4474: sub authorpriv {
4475: my ($auname,$audom)=@_;
4476: unless ((&Apache::lonnet::allowed('cca',$audom.'/'.$auname))
4477: || (&Apache::lonnet::allowed('caa',$audom.'/'.$auname))) { return ''; } return 1;
4478: }
4479:
1.27 raeburn 4480: sub roles_on_upload {
4481: my ($context,%customroles) = @_;
4482: my (@possible_roles,@permitted_roles);
4483: if ($context eq 'domain') {
4484: @possible_roles = &curr_role_permissions($context,undef,1);
4485: push(@possible_roles,&curr_role_permissions($context,'course',1));
4486: } else {
4487: @possible_roles = &curr_role_permissions($context,undef,1);
4488: }
4489: my $custom_ok = 0;
4490: foreach my $role (@possible_roles) {
4491: if ($role eq 'cr') {
4492: $custom_ok = 1;
4493: push(@permitted_roles,keys(%customroles));
4494: } else {
4495: push(@permitted_roles,$role);
4496: }
4497: }
4498: return ($custom_ok,@permitted_roles);
4499: }
4500:
1.17 raeburn 4501: sub get_course_identity {
4502: my ($cid) = @_;
4503: my ($cnum,$cdom,$cdesc);
4504: if ($cid eq '') {
4505: $cid = $env{'request.course.id'}
4506: }
4507: if ($cid ne '') {
4508: $cnum = $env{'course.'.$cid.'.num'};
4509: $cdom = $env{'course.'.$cid.'.domain'};
4510: $cdesc = $env{'course.'.$cid.'.description'};
4511: if ($cnum eq '' || $cdom eq '') {
4512: my %coursehash =
4513: &Apache::lonnet::coursedescription($cid,{'one_time' => 1});
4514: $cdom = $coursehash{'domain'};
4515: $cnum = $coursehash{'num'};
4516: $cdesc = $coursehash{'description'};
4517: }
4518: }
4519: return ($cnum,$cdom,$cdesc);
4520: }
4521:
1.19 raeburn 4522: sub dc_setcourse_js {
4523: my ($formname,$mode) = @_;
4524: my $dc_setcourse_code;
4525: my $cctext = &Apache::lonnet::plaintext('cc');
4526: my %alerts = §ioncheck_alerts();
4527: my $role = 'role';
4528: if ($mode eq 'upload') {
4529: $role = 'courserole';
4530: }
4531: $dc_setcourse_code = (<<"SCRIPTTOP");
4532: function setCourse() {
4533: var course = document.$formname.dccourse.value;
4534: if (course != "") {
4535: if (document.$formname.dcdomain.value != document.$formname.origdom.value) {
4536: alert("$alerts{'curd'}");
4537: return;
4538: }
4539: var userrole = document.$formname.$role.options[document.$formname.$role.selectedIndex].value
4540: var section="";
4541: var numsections = 0;
4542: var newsecs = new Array();
4543: for (var i=0; i<document.$formname.currsec.length; i++) {
4544: if (document.$formname.currsec.options[i].selected == true ) {
4545: if (document.$formname.currsec.options[i].value != "" && document.$formname.currsec.options[i].value != null) {
4546: if (numsections == 0) {
4547: section = document.$formname.currsec.options[i].value
4548: numsections = 1;
4549: }
4550: else {
4551: section = section + "," + document.$formname.currsec.options[i].value
4552: numsections ++;
4553: }
4554: }
4555: }
4556: }
4557: if (document.$formname.newsec.value != "" && document.$formname.newsec.value != null) {
4558: if (numsections == 0) {
4559: section = document.$formname.newsec.value
4560: }
4561: else {
4562: section = section + "," + document.$formname.newsec.value
4563: }
4564: newsecs = document.$formname.newsec.value.split(/,/g);
4565: numsections = numsections + newsecs.length;
4566: }
4567: if ((userrole == 'st') && (numsections > 1)) {
4568: alert("$alerts{'inea'}. $alerts{'youh'} "+numsections+" $alerts{'sect'}.\\n$alerts{'plsm'}.")
4569: return;
4570: }
4571: for (var j=0; j<newsecs.length; j++) {
4572: if ((newsecs[j] == 'all') || (newsecs[j] == 'none')) {
4573: alert("'"+newsecs[j]+"' $alerts{'mayn'}.\\n$alerts{'plsc'}.");
4574: return;
4575: }
4576: if (document.$formname.groups.value != '') {
4577: var groups = document.$formname.groups.value.split(/,/g);
4578: for (var k=0; k<groups.length; k++) {
4579: if (newsecs[j] == groups[k]) {
4580: alert("'"+newsecs[j]+"' $alerts{'mayt'}.\\n$alerts{'secn'}. $alerts{'plsc'}.");
4581: return;
4582: }
4583: }
4584: }
4585: }
4586: if ((userrole == 'cc') && (numsections > 0)) {
4587: alert("$alerts{'secd'} $cctext $alerts{'role'}.\\n$alerts{'accr'}.");
4588: section = "";
4589: }
4590: SCRIPTTOP
4591: if ($mode ne 'upload') {
4592: $dc_setcourse_code .= (<<"ENDSCRIPT");
4593: var coursename = "_$env{'request.role.domain'}"+"_"+course+"_"+userrole
4594: var numcourse = getIndex(document.$formname.dccourse);
4595: if (numcourse == "-1") {
4596: alert("$alerts{'thwa'}");
4597: return;
4598: }
4599: else {
4600: document.$formname.elements[numcourse].name = "act"+coursename;
4601: var numnewsec = getIndex(document.$formname.newsec);
4602: if (numnewsec != "-1") {
4603: document.$formname.elements[numnewsec].name = "sec"+coursename;
4604: document.$formname.elements[numnewsec].value = section;
4605: }
4606: var numstart = getIndex(document.$formname.start);
4607: if (numstart != "-1") {
4608: document.$formname.elements[numstart].name = "start"+coursename;
4609: }
4610: var numend = getIndex(document.$formname.end);
4611: if (numend != "-1") {
4612: document.$formname.elements[numend].name = "end"+coursename
4613: }
4614: }
4615: }
4616: document.$formname.submit();
4617: }
4618:
4619: ENDSCRIPT
4620: } else {
4621: $dc_setcourse_code .= "
4622: document.$formname.sections.value = section;
4623: }
4624: return 'ok';
4625: }
4626: ";
4627: }
4628: $dc_setcourse_code .= (<<"ENDSCRIPT");
4629:
4630: function getIndex(caller) {
4631: for (var i=0;i<document.$formname.elements.length;i++) {
4632: if (document.$formname.elements[i] == caller) {
4633: return i;
4634: }
4635: }
4636: return -1;
4637: }
4638: ENDSCRIPT
4639: }
4640:
4641: sub sectioncheck_alerts {
4642: my %alerts = &Apache::lonlocal::texthash(
4643: curd => 'You must select a course in the current domain',
4644: inea => 'In each course, each user may only have one student role at a time',
4645: youh => 'You had selected',
4646: sect => 'sections',
4647: plsm => 'Please modify your selections so they include no more than one section',
4648: mayn => 'may not be used as the name for a section, as it is a reserved word',
4649: plsc => 'Please choose a different section name',
4650: mayt => 'may not be used as the name for a section, as it is the name of a course group',
4651: secn => 'Section names and group names must be distinct',
4652: secd => 'Section designations do not apply to ',
4653: role => 'roles',
4654: accr => 'role will be added with access to all sections',
4655: thwa => 'There was a problem with your course selection'
4656: );
4657: return %alerts;
4658: }
1.17 raeburn 4659:
1.1 raeburn 4660: 1;
4661:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>