Annotation of loncom/interface/londropadd.pm, revision 1.91.2.2
1.1 www 1: # The LearningOnline Network with CAPA
2: # Handler to drop and add students in courses
3: #
1.91.2.2! albertel 4: # $Id: londropadd.pm,v 1.91.2.1 2004/01/21 00:23:30 albertel Exp $
1.17 albertel 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: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
1.1 www 28: # (Handler to set parameters for assessments
29: #
30: # (Handler to resolve ambiguous file locations
31: #
32: # (TeX Content Handler
33: #
1.50 matthew 34: ###############################################################
1.82 www 35: ##############################################################
1.1 www 36:
37: package Apache::londropadd;
38:
39: use strict;
1.24 albertel 40: use Apache::lonnet();
41: use Apache::loncommon();
1.50 matthew 42: use Apache::lonhtmlcommon();
1.1 www 43: use Apache::Constants qw(:common :http REDIRECT);
1.60 matthew 44: use Spreadsheet::WriteExcel;
1.86 www 45: use Apache::lonlocal;
1.91.2.1 albertel 46: use localenroll();
1.1 www 47:
1.50 matthew 48: ###############################################################
49: ###############################################################
1.10 www 50: sub header {
1.46 www 51: my $bodytag=&Apache::loncommon::bodytag('Enrollment Manager');
1.88 matthew 52: my $title = &mt('LON-CAPA Enrollment Manager');
1.27 matthew 53: return(<<ENDHEAD);
1.1 www 54: <html>
55: <head>
1.88 matthew 56: <title>$title</title>
1.1 www 57: </head>
1.46 www 58: $bodytag
1.40 matthew 59: <form method="post" enctype="multipart/form-data"
60: action="/adm/dropadd" name="studentform">
1.1 www 61: ENDHEAD
1.10 www 62: }
63:
1.50 matthew 64: ###############################################################
65: ###############################################################
66: # Drop student from all sections of a course, except optional $csec
1.26 matthew 67: sub modifystudent {
1.33 matthew 68: my ($udom,$unam,$courseid,$csec,$desiredhost)=@_;
1.26 matthew 69: # if $csec is undefined, drop the student from all the courses matching
70: # this one. If $csec is defined, drop them from all other sections of
71: # this course and add them to section $csec
1.25 matthew 72: $courseid=~s/\_/\//g;
73: $courseid=~s/^(\w)/\/$1/;
1.26 matthew 74: my %roles = &Apache::lonnet::dump('roles',$udom,$unam);
75: my ($tmp) = keys(%roles);
76: # Bail out if we were unable to get the students roles
1.35 matthew 77: return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i);
1.26 matthew 78: # Go through the roles looking for enrollment in this course
1.35 matthew 79: my $result = '';
1.26 matthew 80: foreach my $course (keys(%roles)) {
1.35 matthew 81: if ($course=~/^$courseid(?:\/)*(?:\s+)*(\w+)*\_st$/) {
1.26 matthew 82: # We are in this course
1.25 matthew 83: my $section=$1;
1.26 matthew 84: $section='' if ($course eq $courseid.'_st');
1.87 matthew 85: if (defined($csec) && $section eq $csec) {
1.71 matthew 86: $result .= 'ok:';
87: } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) {
1.27 matthew 88: my (undef,$end,$start)=split(/\_/,$roles{$course});
1.25 matthew 89: my $now=time;
1.50 matthew 90: # if this is an active role
1.27 matthew 91: if (!($start && ($now<$start)) || !($end && ($now>$end))) {
1.25 matthew 92: my $reply=&Apache::lonnet::modifystudent
1.70 matthew 93: # dom name id mode pass f m l g
94: ($udom,$unam,'', '', '',undef,undef,undef,undef,
1.33 matthew 95: $section,time,undef,undef,$desiredhost);
1.35 matthew 96: $result .= $reply.':';
1.25 matthew 97: }
1.10 www 98: }
99: }
1.20 harris41 100: }
1.35 matthew 101: if ($result eq '') {
1.62 matthew 102: $result = 'Unable to find section for this student';
1.37 matthew 103: } else {
104: $result =~ s/(ok:)+/ok/g;
1.35 matthew 105: }
106: return $result;
1.10 www 107: }
108:
1.50 matthew 109: ###############################################################
110: ###############################################################
111: # build a domain and server selection form
1.31 matthew 112: sub domain_form {
113: my ($defdom) = @_;
114: # Set up domain and server selection forms
115: #
116: # Get the domains
117: my @domains = &Apache::loncommon::get_domains();
118: # build up the menu information to be passed to
119: # &Apache::loncommon::linked_select_forms
120: my %select_menus;
121: foreach my $dom (@domains) {
122: # set up the text for this domain
123: $select_menus{$dom}->{'text'}= $dom;
124: # we want a choice of 'default' as the default in the second menu
125: $select_menus{$dom}->{'default'}= 'default';
126: $select_menus{$dom}->{'select2'}->{'default'} = 'default';
127: # Now build up the other items in the second menu
1.45 matthew 128: my %servers = &Apache::loncommon::get_library_servers($dom);
1.31 matthew 129: foreach my $server (keys(%servers)) {
130: $select_menus{$dom}->{'select2'}->{$server}
131: = "$server $servers{$server}";
132: }
133: }
134: my $result = &Apache::loncommon::linked_select_forms
135: ('studentform',' with home server ',$defdom,
136: 'lcdomain','lcserver',\%select_menus);
137: return $result;
138: }
139:
1.50 matthew 140: ###############################################################
141: ###############################################################
142: # Menu Phase One
143: sub print_main_menu {
1.10 www 144: my $r=shift;
1.88 matthew 145: my %Text = &Apache::lonlocal::texthash
146: ('upload' => 'Upload a class list',
147: 'enrollone' => 'Enroll a single student',
148: 'modify' => 'Modify student data',
149: 'view' => 'View Class List',
1.91 raeburn 150: 'drop' => 'Drop Students',
151: 'populate' => 'Automated Enrollment Manager');
1.88 matthew 152:
1.48 matthew 153: $r->print(<<END);
154: <p>
1.50 matthew 155: <font size="+1">
1.88 matthew 156: <a href="/adm/dropadd?action=upload">$Text{'upload'}</a>
1.50 matthew 157: </font>
158: </p><p>
159: <font size="+1">
1.88 matthew 160: <a href="/adm/dropadd?action=enrollstudent">$Text{'enrollone'}</a>
1.50 matthew 161: </font>
1.48 matthew 162: </p><p>
1.50 matthew 163: <font size="+1">
1.88 matthew 164: <a href="/adm/dropadd?action=modifystudent">$Text{'modify'}</a>
1.50 matthew 165: </font>
1.48 matthew 166: </p><p>
1.50 matthew 167: <font size="+1">
1.88 matthew 168: <a href="/adm/dropadd?action=classlist">$Text{'view'}</a>
1.50 matthew 169: </font>
1.48 matthew 170: </p><p>
1.50 matthew 171: <font size="+1">
1.88 matthew 172: <a href="/adm/dropadd?action=drop">$Text{'drop'}</a>
1.50 matthew 173: </font>
1.91 raeburn 174: </p><p>
1.91.2.1 albertel 175: END
176: if (&localenroll::run() ) {
177: $r->print(<<END);
1.91 raeburn 178: <font size="+1">
179: <a href="/adm/populate">$Text{'populate'}</a>
180: </font>
1.48 matthew 181: END
1.91.2.1 albertel 182: }
1.10 www 183: }
184:
1.50 matthew 185: ###############################################################
186: ###############################################################
1.89 matthew 187: sub hidden_input {
188: my ($name,$value) = @_;
189: return '<input type="hidden" name="'.$name.'" value="'.$value.'" />'."\n";
190: }
191:
1.50 matthew 192: sub print_upload_manager_header {
1.23 albertel 193: my ($r,$datatoken,$distotal,$krbdefdom)=@_;
1.24 albertel 194: my $javascript;
1.50 matthew 195: if (! exists($ENV{'form.upfile_associate'})) {
196: $ENV{'form.upfile_associate'} = 'forward';
197: }
198: if ($ENV{'form.associate'} eq 'Reverse Association') {
199: if ( $ENV{'form.upfile_associate'} ne 'reverse' ) {
200: $ENV{'form.upfile_associate'} = 'reverse';
201: } else {
202: $ENV{'form.upfile_associate'} = 'forward';
203: }
204: }
1.24 albertel 205: if ($ENV{'form.upfile_associate'} eq 'reverse') {
1.50 matthew 206: $javascript=&upload_manager_javascript_reverse_associate();
1.24 albertel 207: } else {
1.50 matthew 208: $javascript=&upload_manager_javascript_forward_associate();
1.24 albertel 209: }
1.89 matthew 210: my $javascript_validations=&javascript_validations('auth',$krbdefdom);
1.82 www 211: my $checked=(($ENV{'form.noFirstLine'})?' checked="1"':'');
1.88 matthew 212: $r->print('<h3>'.&mt('Uploading Class List')."</h3>\n".
213: "<hr>\n".
214: '<h3>'.&mt('Identify fields')."</h3>\n");
215: $r->print("<p>\n".
216: &mt('Total number of records found in file: [_1].',$distotal).
217: "\n".
218: "</p><hr>\n");
1.89 matthew 219: $r->print(&mt('Enter as many fields as you can. '.
220: 'The system will inform you and bring you back to '.
221: 'this page if the data selected is insufficient to '.
222: 'enroll students in your class.')."<hr>\n");
223: $r->print(&hidden_input('action','upload').
224: &hidden_input('state','got_file').
225: &hidden_input('associate','').
226: &hidden_input('datatoken',$datatoken).
227: &hidden_input('fileupload',$ENV{'form.fileupload'}).
228: &hidden_input('upfiletype',$ENV{'form.upfiletype'}).
229: &hidden_input('upfile_associate',$ENV{'form.upfile_associate'}));
230: $r->print('<input type="button" value="Reverse Association" '.
231: 'name="'.&mt('Reverse Association').'" '.
232: 'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />');
233: $r->print('<input type="checkbox" name="noFirstLine" $checked />'.
234: &mt('Ignore First Line'));
235: $r->print("<hr />\n".
236: '<script type="text/javascript" language="Javascript">'."\n".
237: $javascript."\n".$javascript_validations.'</script>');
1.24 albertel 238: }
239:
1.50 matthew 240: ###############################################################
241: ###############################################################
1.24 albertel 242: sub javascript_validations {
1.91.2.2! albertel 243: my ($mode,$krbdefdom,$curr_authtype,$curr_authfield)=@_;
1.89 matthew 244: my $authheader;
245: if ($mode eq 'auth') {
246: my %param = ( formname => 'studentform',
247: kerb_def_dom => $krbdefdom );
248: $authheader = &Apache::loncommon::authform_header(%param);
1.91 raeburn 249: } elsif ($mode eq 'createcourse') {
250: my %param = ( formname => 'ccrs',
251: kerb_def_dom => $krbdefdom );
252: $authheader = &Apache::loncommon::authform_header(%param);
1.91.2.2! albertel 253: } elsif ($mode eq 'modifycourse') {
! 254: my %param = ( formname => 'cmod',
! 255: kerb_def_dom => $krbdefdom,
! 256: mode => 'modifycourse',
! 257: curr_authtype => $curr_authtype,
! 258: curr_autharg => $curr_authfield );
! 259: $authheader = &Apache::loncommon::authform_header(%param);
1.89 matthew 260: }
1.91.2.2! albertel 261:
1.91 raeburn 262:
1.89 matthew 263: my %alert = &Apache::lonlocal::texthash
264: (username => 'You need to specify the username field.',
265: authen => 'You must choose an authentication type.',
266: krb => 'You need to specify the Kerberos domain.',
267: ipass => 'You need to specify the initial password.',
268: name => 'The optional name field was not specified.',
269: snum => 'The optional student number field was not specified.',
270: section => 'The optional section or group field was not specified.',
271: email => 'The optional email address field was not specified.',
272: continue => 'Continue enrollment?',
273: );
274:
275: # my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
276: my $function_name =(<<END);
1.73 www 277: function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail) {
1.89 matthew 278: END
1.91.2.2! albertel 279: my $auth_checks;
! 280: if ($mode eq 'createcourse') {
! 281: $auth_checks .= (<<END);
! 282: if (vf.autoadds[0].checked == true) {
! 283: if (current.radiovalue == null || current.radiovalue == 'nochange') {
! 284: alert('$alert{'authen'}');
! 285: return;
! 286: }
! 287: }
1.91 raeburn 288: END
1.91.2.2! albertel 289: } else {
1.91 raeburn 290: $auth_checks .= (<<END);
1.91.2.2! albertel 291: var foundatype=0;
1.3 www 292: if (founduname==0) {
1.89 matthew 293: alert('$alert{'username'}');
1.3 www 294: return;
295: }
1.61 matthew 296: // alert('current.radiovalue = '+current.radiovalue);
1.29 matthew 297: if (current.radiovalue == null || current.radiovalue == 'nochange') {
1.28 matthew 298: // They did not check any of the login radiobuttons.
1.89 matthew 299: alert('$alert{'authen'}');
1.28 matthew 300: return;
301: }
1.91.2.2! albertel 302: END
! 303: }
! 304: if ($mode eq 'createcourse') {
! 305: $auth_checks .= "
! 306: if ( (vf.autoadds[0].checked == true) &&
! 307: (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') ) {
! 308: ";
! 309: } elsif ($mode eq 'modifycourse') {
! 310: $auth_checks .= "
! 311: if (vf.elements[current.argfield].value == null || vf.elements[current.argfield].value == '') {
! 312: ";
! 313: }
! 314: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
! 315: $auth_checks .= (<<END);
! 316: var alertmsg = '';
! 317: switch (current.radiovalue) {
! 318: case 'krb':
! 319: alertmsg = '$alert{'krb'}';
! 320: break;
! 321: default:
! 322: alertmsg = '';
! 323: }
! 324: if (alertmsg != '') {
! 325: alert(alertmsg);
! 326: return;
! 327: }
! 328: }
! 329: END
! 330: } else {
! 331: $auth_checks .= (<<END);
1.28 matthew 332: foundatype=1;
1.29 matthew 333: if (current.argfield == null || current.argfield == '') {
1.28 matthew 334: var alertmsg = '';
1.29 matthew 335: switch (current.value) {
1.28 matthew 336: case 'krb':
1.89 matthew 337: alertmsg = '$alert{'krb'}';
1.28 matthew 338: break;
339: case 'loc':
340: case 'fsys':
1.89 matthew 341: alertmsg = '$alert{'ipass'}';
1.28 matthew 342: break;
343: case 'fsys':
344: alertmsg = '';
345: break;
346: default:
347: alertmsg = '';
1.3 www 348: }
1.28 matthew 349: if (alertmsg != '') {
350: alert(alertmsg);
1.3 www 351: return;
352: }
353: }
1.89 matthew 354: END
1.91.2.2! albertel 355: }
1.91 raeburn 356: my $optional_checks = '';
1.91.2.2! albertel 357: if ( ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1.91 raeburn 358: $optional_checks = (<<END);
359: vf.submit();
360: }
361: END
362: } else {
363: $optional_checks = (<<END);
1.89 matthew 364: var message='';
365: if (foundname==0) {
366: message='$alert{'name'}';
1.24 albertel 367: }
1.89 matthew 368: if (foundid==0) {
369: if (message!='') {
370: message+='\\n';
371: }
372: message+='$alert{'snum'}';
373: }
374: if (foundsec==0) {
375: if (message!='') {
376: message+='\\n';
377: }
378: message+='$alert{'section'}';
379: }
380: if (foundemail==0) {
381: if (message!='') {
382: message+='\\n';
383: }
384: message+='$alert{'email'}';
1.74 matthew 385: }
386: if (message!='') {
1.89 matthew 387: message+= '\\n$alert{'continue'}';
388: if (confirm(message)) {
389: vf.state.value='enrolling';
390: vf.submit();
391: }
1.74 matthew 392: } else {
1.89 matthew 393: vf.state.value='enrolling';
394: vf.submit();
1.74 matthew 395: }
396: }
1.89 matthew 397: END
1.91 raeburn 398: }
1.89 matthew 399: my $result = $function_name;
1.91.2.2! albertel 400: if ( ($mode eq 'auth') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1.89 matthew 401: $result .= $auth_checks;
402: }
403: $result .= $optional_checks;
1.91.2.2! albertel 404: if ( ($mode eq 'auth') || ($mode eq 'createcourse') || ($mode eq 'modifycourse') ) {
1.89 matthew 405: $result .= $authheader;
406: }
407: return $result;
1.74 matthew 408: }
409:
1.50 matthew 410: ###############################################################
411: ###############################################################
412: sub upload_manager_javascript_forward_associate {
1.24 albertel 413: return(<<ENDPICK);
414: function verify(vf) {
415: var founduname=0;
416: var foundpwd=0;
417: var foundname=0;
418: var foundid=0;
419: var foundsec=0;
1.73 www 420: var foundemail=0;
1.24 albertel 421: var tw;
422: for (i=0;i<=vf.nfields.value;i++) {
423: tw=eval('vf.f'+i+'.selectedIndex');
424: if (tw==1) { founduname=1; }
425: if ((tw>=2) && (tw<=6)) { foundname=1; }
426: if (tw==7) { foundid=1; }
427: if (tw==8) { foundsec=1; }
428: if (tw==9) { foundpwd=1; }
1.73 www 429: if (tw==10) { foundemail=1; }
1.24 albertel 430: }
1.73 www 431: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail);
1.24 albertel 432: }
433:
1.49 matthew 434: //
435: // vf = this.form
436: // tf = column number
437: //
438: // values of nw
439: //
440: // 0 = none
441: // 1 = username
442: // 2 = names (lastname, firstnames)
443: // 3 = fname (firstname)
444: // 4 = mname (middlename)
445: // 5 = lname (lastname)
446: // 6 = gen (generation)
447: // 7 = id
448: // 8 = section
449: // 9 = ipwd (password)
1.73 www 450: // 10 = email address
451:
1.24 albertel 452: function flip(vf,tf) {
453: var nw=eval('vf.f'+tf+'.selectedIndex');
454: var i;
1.49 matthew 455: // make sure no other columns are labeled the same as this one
1.24 albertel 456: for (i=0;i<=vf.nfields.value;i++) {
457: if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
458: eval('vf.f'+i+'.selectedIndex=0;')
459: }
460: }
1.49 matthew 461: // If we set this to 'lastname, firstnames', clear out all the ones
462: // set to 'fname','mname','lname','gen' (3,4,5,6) currently.
1.24 albertel 463: if (nw==2) {
464: for (i=0;i<=vf.nfields.value;i++) {
465: if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
466: (eval('vf.f'+i+'.selectedIndex')<=6)) {
467: eval('vf.f'+i+'.selectedIndex=0;')
468: }
469: }
470: }
1.49 matthew 471: // If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
472: // clear out any that are set to 'lastname, firstnames' (2)
1.24 albertel 473: if ((nw>=3) && (nw<=6)) {
474: for (i=0;i<=vf.nfields.value;i++) {
475: if (eval('vf.f'+i+'.selectedIndex')==2) {
476: eval('vf.f'+i+'.selectedIndex=0;')
477: }
478: }
479: }
1.49 matthew 480: // If we set the password, make the password form below correspond to
481: // the new value.
1.24 albertel 482: if (nw==9) {
1.28 matthew 483: changed_radio('int',document.studentform);
484: set_auth_radio_buttons('int',document.studentform);
485: vf.intarg.value='';
486: vf.krbarg.value='';
1.24 albertel 487: vf.locarg.value='';
488: }
489: }
490:
491: function clearpwd(vf) {
492: var i;
493: for (i=0;i<=vf.nfields.value;i++) {
494: if (eval('vf.f'+i+'.selectedIndex')==9) {
495: eval('vf.f'+i+'.selectedIndex=0;')
496: }
497: }
498: }
499:
500: ENDPICK
501: }
502:
1.50 matthew 503: ###############################################################
504: ###############################################################
505: sub upload_manager_javascript_reverse_associate {
1.24 albertel 506: return(<<ENDPICK);
507: function verify(vf) {
508: var founduname=0;
509: var foundpwd=0;
510: var foundname=0;
511: var foundid=0;
512: var foundsec=0;
513: var tw;
514: for (i=0;i<=vf.nfields.value;i++) {
515: tw=eval('vf.f'+i+'.selectedIndex');
516: if (i==0 && tw!=0) { founduname=1; }
517: if (((i>=1) && (i<=5)) && tw!=0 ) { foundname=1; }
518: if (i==6 && tw!=0) { foundid=1; }
519: if (i==7 && tw!=0) { foundsec=1; }
520: if (i==8 && tw!=0) { foundpwd=1; }
521: }
522: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec);
523: }
524:
525: function flip(vf,tf) {
526: var nw=eval('vf.f'+tf+'.selectedIndex');
527: var i;
528: // picked the all one one name field, reset the other name ones to blank
529: if (tf==1 && nw!=0) {
530: for (i=2;i<=5;i++) {
531: eval('vf.f'+i+'.selectedIndex=0;')
532: }
533: }
534: //picked one of the piecewise name fields, reset the all in
535: //one field to blank
536: if ((tf>=2) && (tf<=5) && (nw!=0)) {
537: eval('vf.f1.selectedIndex=0;')
538: }
539: // intial password specified, pick internal authentication
540: if (tf==8 && nw!=0) {
1.28 matthew 541: changed_radio('int',document.studentform);
542: set_auth_radio_buttons('int',document.studentform);
543: vf.krbarg.value='';
544: vf.intarg.value='';
1.24 albertel 545: vf.locarg.value='';
546: }
547: }
548:
549: function clearpwd(vf) {
550: var i;
551: if (eval('vf.f8.selectedIndex')!=0) {
552: eval('vf.f8.selectedIndex=0;')
553: }
554: }
1.2 www 555: ENDPICK
1.23 albertel 556: }
1.10 www 557:
1.50 matthew 558: ###############################################################
559: ###############################################################
560: sub print_upload_manager_footer {
1.23 albertel 561: my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_;
1.64 albertel 562:
563: my ($krbdef,$krbdefdom) =
564: &Apache::loncommon::get_kerberos_defaults($defdom);
565: my %param = ( formname => 'document.studentform',
566: kerb_def_dom => $krbdefdom,
567: kerb_def_auth => $krbdef
568: );
1.28 matthew 569: my $krbform = &Apache::loncommon::authform_kerberos(%param);
570: my $intform = &Apache::loncommon::authform_internal(%param);
571: my $locform = &Apache::loncommon::authform_local(%param);
1.31 matthew 572: my $domform = &domain_form($defdom);
1.68 matthew 573: my $date_table = &date_setting_table();
1.90 matthew 574: my $Str = "</table>\n";
575: $Str .= &hidden_input('nfields',$i);
576: $Str .= &hidden_input('keyfields',$keyfields);
577: $Str .= '<h3>'.&mt('Login Type')."</h3>\n";
578: $Str .= "<p>\n".
579: &mt('Note: this will not take effect if the user already exists').
580: "</p><p>\n";
581: $Str .= $krbform."\n</p><p>\n".
582: $intform."\n</p><p>\n".
583: $locform."\n</p>\n";
584: $Str .= '<h3>'.&mt('LON-CAPA Domain for Students')."</h3>\n";
585: $Str .= "<p>\n".&mt('LON-CAPA domain: [_1]',$domform)."\n</p>\n";
586: $Str .= "<h3>".&mt('Starting and Ending Dates')."</h3>\n";
587: $Str .= "<p>\n".$date_table."</p>\n";
588: $Str .= "<h3>".&mt('Full Update')."</h3>\n";
589: $Str .= '<input type="checkbox" name="fullup" value="yes">'.
590: ' '.&mt('Full update (also print list of users not enrolled anymore)').
591: "</p>\n";
592: $Str .= "<h3>".&mt('Student Number')."</h3>\n";
593: $Str .= "<p>\n".'<input type="checkbox" name="forceid" value="yes">';
594: $Str .= &mt('Disable ID/Student Number Safeguard and Force Change '.
595: 'of Conflicting IDs (only do if you know what you are doing)').
596: "\n</p><p>\n";
597: $Str .= '<input type="button" onClick="javascript:verify(this.form)" '.
598: 'value="Update Courselist" />'."<br />\n";
599: $Str .= &mt('Note: for large courses, this operation may be time '.
600: 'consuming');
601: $r->print($Str);
602: return;
1.23 albertel 603: }
1.24 albertel 604:
1.90 matthew 605: ###############################################################
606: ###############################################################
1.50 matthew 607: sub print_upload_manager_form {
1.23 albertel 608: my $r=shift;
1.82 www 609: my $firstLine;
1.24 albertel 610: my $datatoken;
611: if (!$ENV{'form.datatoken'}) {
1.90 matthew 612: $datatoken=&Apache::loncommon::upfile_store($r);
1.24 albertel 613: } else {
1.90 matthew 614: $datatoken=$ENV{'form.datatoken'};
615: &Apache::loncommon::load_tmp_file($r);
1.24 albertel 616: }
617: my @records=&Apache::loncommon::upfile_record_sep();
1.90 matthew 618: if($ENV{'form.noFirstLine'}){
619: $firstLine=shift(@records);
620: }
1.23 albertel 621: my $total=$#records;
622: my $distotal=$total+1;
623: my $today=time;
624: my $halfyear=$today+15552000;
1.85 matthew 625: my $defdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
1.64 albertel 626: my ($krbdef,$krbdefdom) =
627: &Apache::loncommon::get_kerberos_defaults($defdom);
1.50 matthew 628: &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom);
1.24 albertel 629: my $i;
630: my $keyfields;
1.23 albertel 631: if ($total>=0) {
1.90 matthew 632: my @field=(['username',&mt('Username')],
633: ['names',&mt('Last Name, First Names')],
634: ['fname',&mt('First Name')],
635: ['mname',&mt('Middle Names/Initials')],
636: ['lname',&mt('Last Name')],
637: ['gen',&mt('Generation')],
638: ['id',&mt('ID/Student Number')],
639: ['sec',&mt('Group/Section')],
640: ['ipwd',&mt('Initial Password')],
641: ['email',&mt('EMail Address')]);
1.24 albertel 642: if ($ENV{'form.upfile_associate'} eq 'reverse') {
643: &Apache::loncommon::csv_print_samples($r,\@records);
1.90 matthew 644: $i=&Apache::loncommon::csv_print_select_table($r,\@records,
645: \@field);
646: foreach (@field) {
647: $keyfields.=$_->[0].',';
648: }
1.24 albertel 649: chop($keyfields);
650: } else {
1.90 matthew 651: unshift(@field,['none','']);
652: $i=&Apache::loncommon::csv_samples_select_table($r,\@records,
653: \@field);
1.24 albertel 654: my %sone=&Apache::loncommon::record_sep($records[0]);
655: $keyfields=join(',',sort(keys(%sone)));
1.23 albertel 656: }
657: }
1.50 matthew 658: &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear);
1.10 www 659: }
660:
1.90 matthew 661: ###############################################################
662: ###############################################################
1.12 www 663: sub enroll_single_student {
664: my $r=shift;
1.80 matthew 665: # Remove non alphanumeric values from section
666: $ENV{'form.csec'}=~s/\W//g;
1.68 matthew 667: #
668: # We do the dates first because the action of making them the defaul
669: # in the course is entirely seperate from the action of enrolling the
670: # student. Also, a failure in setting the dates as default is not fatal
671: # to the process of enrolling / modifying a student.
672: my ($startdate,$enddate) = &get_dates_from_form();
673: if ($ENV{'form.makedatesdefault'}) {
674: $r->print(&make_dates_default($startdate,$enddate));
675: }
676:
1.12 www 677: $r->print('<h3>Enrolling Student</h3>');
1.54 matthew 678: $r->print('<p>Enrolling '.$ENV{'form.cuname'}." \@ ".
1.34 matthew 679: $ENV{'form.lcdomain'}.'</p>');
1.12 www 680: if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\W/)&&
1.31 matthew 681: ($ENV{'form.lcdomain'})&&($ENV{'form.lcdomain'}!~/\W/)) {
682: # Deal with home server selection
683: my $domain=$ENV{'form.lcdomain'};
684: my $desiredhost = $ENV{'form.lcserver'};
685: if (lc($desiredhost) eq 'default') {
686: $desiredhost = undef;
687: } else {
1.45 matthew 688: my %home_servers =&Apache::loncommon::get_library_servers($domain);
1.31 matthew 689: if (! exists($home_servers{$desiredhost})) {
690: $r->print('<font color="#ff0000">Error:</font>'.
691: 'Invalid home server specified');
692: return;
693: }
694: }
1.34 matthew 695: $r->print(" with server $desiredhost :") if (defined($desiredhost));
1.31 matthew 696: # End of home server selection logic
1.12 www 697: my $amode='';
698: my $genpwd='';
699: if ($ENV{'form.login'} eq 'krb') {
1.47 albertel 700: $amode='krb';
701: $amode.=$ENV{'form.krbver'};
1.28 matthew 702: $genpwd=$ENV{'form.krbarg'};
1.12 www 703: } elsif ($ENV{'form.login'} eq 'int') {
1.26 matthew 704: $amode='internal';
1.28 matthew 705: $genpwd=$ENV{'form.intarg'};
1.15 albertel 706: } elsif ($ENV{'form.login'} eq 'loc') {
707: $amode='localauth';
708: $genpwd=$ENV{'form.locarg'};
709: if (!$genpwd) { $genpwd=" "; }
710: }
1.34 matthew 711: my $home = &Apache::lonnet::homeserver($ENV{'form.cuname'},
712: $ENV{'form.lcdomain'});
713: if ((($amode) && ($genpwd)) || ($home ne 'no_host')) {
1.55 matthew 714: # Clean out any old roles the student has in this class.
1.33 matthew 715: &modifystudent($ENV{'form.lcdomain'},$ENV{'form.cuname'},
716: $ENV{'request.course.id'},$ENV{'form.csec'},
717: $desiredhost);
1.55 matthew 718: my $login_result = &Apache::lonnet::modifystudent
719: ($ENV{'form.lcdomain'},$ENV{'form.cuname'},
720: $ENV{'form.cstid'},$amode,$genpwd,
721: $ENV{'form.cfirst'},$ENV{'form.cmiddle'},
722: $ENV{'form.clast'},$ENV{'form.cgen'},
1.67 matthew 723: $ENV{'form.csec'},$enddate,
724: $startdate,$ENV{'form.forceid'},
1.55 matthew 725: $desiredhost);
726: if ($login_result =~ /^ok/) {
727: $r->print($login_result);
728: $r->print("<p> If active, the new role will be available ".
729: "when the student next logs in to LON-CAPA.</p>");
730: } else {
731: $r->print("unable to enroll: ".$login_result);
732: }
1.12 www 733: } else {
1.79 matthew 734: $r->print('<p><font color="#ff0000">ERROR</font> ');
735: if ($amode =~ /^krb/) {
736: $r->print('Missing Kerberos domain information. ');
737: } else {
738: $r->print('Invalid login mode or password. ');
739: }
740: $r->print('<b>Unable to enroll '.$ENV{'form.cuname'}.'.</b></p>');
741: }
1.12 www 742: } else {
743: $r->print('Invalid username or domain');
1.26 matthew 744: }
1.12 www 745: }
746:
1.68 matthew 747: sub setup_date_selectors {
1.91 raeburn 748: my ($starttime,$endtime,$mode) = @_;
1.68 matthew 749: if (! defined($starttime)) {
750: $starttime = time;
1.91 raeburn 751: unless ($mode eq 'createcourse') {
752: if (exists($ENV{'course.'.$ENV{'request.course.id'}.
1.68 matthew 753: '.default_enrollment_start_date'})) {
1.91 raeburn 754: $starttime = $ENV{'course.'.$ENV{'request.course.id'}.
1.68 matthew 755: '.default_enrollment_start_date'};
1.91 raeburn 756: }
1.68 matthew 757: }
758: }
759: if (! defined($endtime)) {
760: $endtime = time+(6*30*24*60*60); # 6 months from now, approx
1.91 raeburn 761: unless ($mode eq 'createcourse') {
762: if (exists($ENV{'course.'.$ENV{'request.course.id'}.
1.68 matthew 763: '.default_enrollment_end_date'})) {
1.91 raeburn 764: $endtime = $ENV{'course.'.$ENV{'request.course.id'}.
1.68 matthew 765: '.default_enrollment_end_date'};
1.91 raeburn 766: }
1.68 matthew 767: }
768: }
769: my $startdateform = &Apache::lonhtmlcommon::date_setter('studentform',
770: 'startdate',
771: $starttime);
772: my $enddateform = &Apache::lonhtmlcommon::date_setter('studentform',
773: 'enddate',
774: $endtime);
1.91 raeburn 775: if ($mode eq 'createcourse') {
776: $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs',
777: 'startdate',
778: $starttime);
779: $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs',
780: 'enddate',
781: $endtime);
782: }
1.68 matthew 783: return ($startdateform,$enddateform);
784: }
785:
786: sub get_dates_from_form {
787: my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate');
788: my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate');
789: if ($ENV{'form.no_end_date'}) {
790: $enddate = 0;
791: }
792: return ($startdate,$enddate);
793: }
794:
795: sub date_setting_table {
1.91 raeburn 796: my ($starttime,$endtime,$mode) = @_;
797: my ($startform,$endform)=&setup_date_selectors($starttime,$endtime,$mode);
1.68 matthew 798: my $dateDefault = '<nobr>'.
799: '<input type="checkbox" name="makedatesdefault" />'.
800: ' make these dates the default for future enrollment';
1.91 raeburn 801: if ($mode eq 'createcourse') {
802: $dateDefault = ' ';
803: }
1.68 matthew 804: my $perpetual = '<nobr><input type="checkbox" name="no_end_date"';
805: if (defined($endtime) && $endtime == 0) {
806: $perpetual .= ' checked';
807: }
808: $perpetual.= ' />'.' no ending date</nobr>';
809: my $result = '';
810: $result .= "<table>\n";
811: $result .= '<tr><td align="right">Starting Date</td>'.
812: '<td>'.$startform.'</td>'.
813: '<td>'.$dateDefault.'</td>'."</tr>\n";
814: $result .= '<tr><td align="right">Ending Date</td>'.
815: '<td>'.$endform.'</td>'.
816: '<td>'.$perpetual.'</td>'."</tr>\n";
817: $result .= "</table>\n";
818: return $result;
819: }
820:
821: sub make_dates_default {
822: my ($startdate,$enddate) = @_;
823: my $result = '';
824: my $dom = $ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
825: my $crs = $ENV{'course.'.$ENV{'request.course.id'}.'.num'};
826: my $put_result = &Apache::lonnet::put('environment',
827: {'default_enrollment_start_date'=>$startdate,
828: 'default_enrollment_end_date' =>$enddate},$dom,$crs);
829: if ($put_result eq 'ok') {
830: $result .= "Set default start and end dates for course<br />";
1.69 matthew 831: #
832: # Refresh the course environment
833: &Apache::lonnet::coursedescription($ENV{'request.course.id'});
1.68 matthew 834: } else {
835: $result .= "Unable to set default dates for course:".$put_result.
836: '<br />';
837: }
838: return $result;
839: }
840:
1.74 matthew 841: ##
842: ## Single student enrollment routines (some of them)
843: ##
844: sub get_student_username_domain_form {
845: my $r = shift;
846: my $domform = &Apache::loncommon::select_dom_form
1.85 matthew 847: ($ENV{'course.'.$ENV{'request.course.id'}.'.domain'},'cudomain',0);
1.74 matthew 848: $r->print(<<END);
849: <input type="hidden" name="action" value="enrollstudent" />
850: <input type="hidden" name="state" value="gotusername" />
851: <h3>Enroll One Student</h3>
852: <table>
853: <tr><th>Username:</th>
854: <td><input type="text" name="cuname" size="15" /></td></tr>
855: <tr><th>Domain:</th>
856: <td>$domform</td></tr>
857: <tr><th> </th>
858: <td>
859: <input type="submit" name="Begin Enrollment" value="Begin Enrollment" />
860: </td></tr>
861: </table>
862: END
863: return;
864: }
865:
1.50 matthew 866: sub print_enroll_single_student_form {
1.10 www 867: my $r=shift;
1.40 matthew 868: $r->print("<h3>Enroll One Student</h3>");
1.74 matthew 869: #
870: my $username = $ENV{'form.cuname'};
871: my $domain = $ENV{'form.cudomain'};
872: my $home = &Apache::lonnet::homeserver($username,$domain);
873: # $new_user flags whether we are creating a new user or using an old one
874: my $new_user = 1;
875: if ($home ne 'no_host') {
876: $new_user = 0;
877: }
878: #
879: my $user_data_html = '';
880: my $javascript_validations = '';
881: if ($new_user) {
1.85 matthew 882: my $defdom=$ENV{'course.'.$ENV{'request.course.id'}.'.domain'};
1.74 matthew 883: # Set up authentication forms
884: my ($krbdef,$krbdefdom) =
1.75 matthew 885: &Apache::loncommon::get_kerberos_defaults($domain);
1.89 matthew 886: $javascript_validations=&javascript_validations('auth',$krbdefdom);
1.74 matthew 887: my %param = ( formname => 'document.studentform',
888: kerb_def_dom => $krbdefdom,
889: kerb_def_auth => $krbdef
890: );
891: my $krbform = &Apache::loncommon::authform_kerberos(%param);
892: my $intform = &Apache::loncommon::authform_internal(%param);
893: my $locform = &Apache::loncommon::authform_local(%param);
894: #
895: # Set up domain selection form
896: my $homeserver_form = '';
897: my %servers = &Apache::loncommon::get_library_servers($domain);
898: $homeserver_form = '<select name="lcserver" size="1">'."\n".
899: '<option value="default" selected>default</option>'."\n";
900: while (my ($servername,$serverdescription) = each (%servers)) {
901: $homeserver_form .= '<option value="'.$servername.'">'.
902: $serverdescription."</option>\n";
903: }
904: $homeserver_form .= "</select>\n";
905: #
906: #
907: $user_data_html = <<END;
908: <h3>User Data for $username\@$domain</h3>
909: <table>
910: <tr><th>First Name:</th>
911: <td><input type="text" name="cfirst" size="15"></td></tr>
912: <tr><th>Middle Name:</th>
913: <td><input type="text" name="cmiddle" size="15"></td></tr>
914: <tr><th>Last Name:</th>
915: <td><input type="text" name="clast" size="15"></td></tr>
916: <tr><th>Generation:</th>
917: <td><input type="text" name="cgen" size="5"> </td></tr>
918: <tr><th>Home Server:</th>
919: <td>$homeserver_form</td></tr>
920: </table>
921: <h3>Password</h3>
922: Please select an authentication mechanism
923: <table>
924: <p>
925: $krbform
1.75 matthew 926: <br />
1.74 matthew 927: $intform
1.75 matthew 928: <br />
1.74 matthew 929: $locform
930: </p>
931: END
932: } else {
933: # User already exists. Do not worry about authentication
934: my %uenv = &Apache::lonnet::dump('environment',$domain,$username);
1.89 matthew 935: $javascript_validations = &javascript_validations('noauth');
1.74 matthew 936: $user_data_html = <<END;
937: <h3>User Data for $username\@$domain</h3>
938: <input type="hidden" name="lcserver" value="default" />
939: <table>
940: <tr><th>First Name:</th>
941: <td>
942: <input type="text" name="cfirst" value="$uenv{'firstname'}" size="15" />
943: </td></tr>
944: <tr><th>Middle Name:</th>
945: <td>
946: <input type="text" name="cmiddle" value="$uenv{'middlename'}" size="15" />
947: </td></tr>
948: <tr><th>Last Name:</th>
949: <td>
950: <input type="text" name="clast"value="$uenv{'lastname'}" size="15" />
951: </td></tr>
952: <tr><th>Generation:</th>
953: <td>
954: <input type="text" name="cgen" value="$uenv{'generation'}" size="5" />
955: </td></tr>
956: </table>
957: END
958: }
1.68 matthew 959: my $date_table = &date_setting_table();
1.74 matthew 960: # Print it all out
1.50 matthew 961: $r->print(<<END);
1.74 matthew 962: <input type="hidden" name="action" value="enrollstudent" />
963: <input type="hidden" name="state" value="done" />
964: <input type="hidden" name="cuname" value="$username" />
965: <input type="hidden" name="lcdomain" value="$domain" />
1.28 matthew 966: <script type="text/javascript" language="Javascript">
1.12 www 967: function verify(vf) {
968: var founduname=0;
969: var foundpwd=0;
970: var foundname=0;
971: var foundid=0;
972: var foundsec=0;
973: var tw;
1.26 matthew 974: if ((typeof(vf.cuname.value) !="undefined") && (vf.cuname.value!='') &&
1.31 matthew 975: (typeof(vf.lcdomain.value)!="undefined") && (vf.lcdomain.value!='')) {
1.12 www 976: founduname=1;
977: }
1.14 harris41 978: if ((typeof(vf.cfirst.value)!="undefined") && (vf.cfirst.value!='') &&
1.26 matthew 979: (typeof(vf.clast.value) !="undefined") && (vf.clast.value!='')) {
1.12 www 980: foundname=1;
981: }
1.14 harris41 982: if ((typeof(vf.csec.value)!="undefined") && (vf.csec.value!='')) {
1.12 www 983: foundsec=1;
984: }
1.14 harris41 985: if ((typeof(vf.cstid.value)!="undefined") && (vf.cstid.value!='')) {
1.12 www 986: foundid=1;
987: }
988: if (founduname==0) {
989: alert('You need to specify at least the username and domain fields');
990: return;
991: }
1.24 albertel 992: verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec);
1.12 www 993: }
994:
1.24 albertel 995: $javascript_validations
1.12 www 996:
1.24 albertel 997: function clearpwd(vf) {
998: //nothing else needs clearing
1.15 albertel 999: }
1000:
1.12 www 1001: </script>
1.11 www 1002:
1.74 matthew 1003: $user_data_html
1.50 matthew 1004:
1005: <h3>Course Data</h3>
1006:
1007: <p>Group/Section: <input type="text" name="csec" size="5" />
1008: <p>
1.68 matthew 1009: $date_table
1.50 matthew 1010: </p>
1011: <h3>ID/Student Number</h3>
1012: <p>
1013: ID/Student Number: <input type="text" name="cstid" size="10">
1.26 matthew 1014: </p><p>
1015: <input type="checkbox" name="forceid" value="yes">
1.18 www 1016: Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
1.50 matthew 1017: (only do if you know what you are doing)
1018: </p><p>
1019: <input type="button" onClick="verify(this.form)" value="Enroll as student">
1.26 matthew 1020: </p>
1.50 matthew 1021: END
1022: return;
1.10 www 1023: }
1024:
1025: # ========================================================= Menu Phase Two Drop
1.51 matthew 1026: sub print_drop_menu {
1.10 www 1027: my $r=shift;
1.40 matthew 1028: $r->print("<h3>Drop Students</h3>");
1.11 www 1029: my $cid=$ENV{'request.course.id'};
1.56 matthew 1030: my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist();
1031: if (! defined($classlist)) {
1.27 matthew 1032: $r->print("There are no students currently enrolled.\n");
1.51 matthew 1033: return;
1.25 matthew 1034: }
1.51 matthew 1035: # Print out the available choices
1.56 matthew 1036: &show_drop_list($r,$classlist,$keylist);
1.51 matthew 1037: return;
1.11 www 1038: }
1039:
1.40 matthew 1040: # ============================================== view classlist
1.50 matthew 1041: sub print_html_classlist {
1.40 matthew 1042: my $r=shift;
1.57 matthew 1043: if (! exists($ENV{'form.sortby'})) {
1044: $ENV{'form.sortby'} = 'username';
1045: }
1.59 matthew 1046: if ($ENV{'form.Status'} !~ /^(Any|Expired|Active)$/) {
1.57 matthew 1047: $ENV{'form.Status'} = 'Active';
1048: }
1049: my $status_select = &Apache::lonhtmlcommon::StatusOptions
1050: ($ENV{'form.Status'},'studentform');
1.48 matthew 1051: $r->print(<<END);
1.58 matthew 1052: <input type="hidden" name="action" value="$ENV{'form.action'}" />
1.57 matthew 1053: <input type="hidden" name="state" value="" />
1.50 matthew 1054: <p>
1.76 albertel 1055: <font size="+1">Current Class List</font>
1.57 matthew 1056:
1.59 matthew 1057: END
1058: if ($ENV{'form.action'} ne 'modifystudent') {
1059: $r->print(<<END);
1.57 matthew 1060: <font size="+1">
1061: <a href="javascript:document.studentform.state.value='csv';document.studentform.submit();">CSV format</a>
1.61 matthew 1062:
1.60 matthew 1063: <a href="javascript:document.studentform.state.value='excel';document.studentform.submit();">Excel format</a>
1.57 matthew 1064: </font>
1065:
1.61 matthew 1066: Student Status:
1.48 matthew 1067: END
1.59 matthew 1068: }
1069: $r->print($status_select."</p>\n");
1.40 matthew 1070: my $cid=$ENV{'request.course.id'};
1.56 matthew 1071: my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
1072: if (! defined($classlist)) {
1.40 matthew 1073: $r->print("There are no students currently enrolled.\n");
1074: } else {
1075: # Print out the available choices
1.50 matthew 1076: if ($ENV{'form.action'} eq 'modifystudent') {
1.53 matthew 1077: &show_class_list($r,'view','modify','modifystudent',
1.57 matthew 1078: $ENV{'form.Status'},$classlist,$keylist);
1.50 matthew 1079: } else {
1.53 matthew 1080: &show_class_list($r,'view','aboutme','classlist',
1.57 matthew 1081: $ENV{'form.Status'},$classlist,$keylist);
1.50 matthew 1082: }
1.41 matthew 1083: }
1084: }
1085:
1086: # ============================================== view classlist
1.60 matthew 1087: sub print_formatted_classlist {
1.41 matthew 1088: my $r=shift;
1.60 matthew 1089: my $mode = shift;
1.41 matthew 1090: my $cid=$ENV{'request.course.id'};
1.56 matthew 1091: my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
1092: if (! defined($classlist)) {
1.41 matthew 1093: $r->print("There are no students currently enrolled.\n");
1094: } else {
1.60 matthew 1095: &show_class_list($r,$mode,'nolink','csv',
1.57 matthew 1096: $ENV{'form.Status'},$classlist,$keylist);
1.40 matthew 1097: }
1098: }
1099:
1100: # =================================================== Show student list to drop
1101: sub show_class_list {
1.56 matthew 1102: my ($r,$mode,$linkto,$action,$statusmode,$classlist,$keylist)=@_;
1.40 matthew 1103: my $cid=$ENV{'request.course.id'};
1.60 matthew 1104: #
1105: # Variables for excel output
1106: my ($excel_workbook, $excel_sheet, $excel_filename,$row);
1107: #
1.53 matthew 1108: my $sortby = $ENV{'form.sortby'};
1109: if ($sortby !~ /^(username|domain|section|fullname|id)$/) {
1110: $sortby = 'username';
1111: }
1.42 matthew 1112: # Print out header
1.41 matthew 1113: if ($mode eq 'view') {
1.50 matthew 1114: if ($linkto eq 'aboutme') {
1.56 matthew 1115: $r->print('Select a user name to view the users personal page.');
1.50 matthew 1116: } elsif ($linkto eq 'modify') {
1117: $r->print('Select a user name to modify the students information');
1118: }
1.41 matthew 1119: $r->print(<<END);
1.59 matthew 1120:
1.53 matthew 1121: <input type="hidden" name="sortby" value="$sortby" />
1.59 matthew 1122: <input type="hidden" name="sname" value="" />
1123: <input type="hidden" name="sdom" value="" />
1.40 matthew 1124: <p>
1125: <table border=2>
1.53 matthew 1126: <tr><th>
1.57 matthew 1127: <a href="javascript:document.studentform.sortby.value='username';document.studentform.submit();">username</a>
1.53 matthew 1128: </th><th>
1.57 matthew 1129: <a href="javascript:document.studentform.sortby.value='domain';document.studentform.submit();">domain</a>
1.53 matthew 1130: </th><th>
1.57 matthew 1131: <a href="javascript:document.studentform.sortby.value='id';document.studentform.submit();">ID</a>
1.53 matthew 1132: </th><th>
1.57 matthew 1133: <a href="javascript:document.studentform.sortby.value='fullname';document.studentform.submit();">student name</a>
1.53 matthew 1134: </th><th>
1.57 matthew 1135: <a href="javascript:document.studentform.sortby.value='section';document.studentform.submit();">section</a>
1.53 matthew 1136: </th>
1137: </tr>
1.40 matthew 1138: END
1.41 matthew 1139: } elsif ($mode eq 'csv') {
1.58 matthew 1140: if($statusmode eq 'Expired') {
1141: $r->print('"Students with expired roles"');
1142: }
1143: if ($statusmode eq 'Any') {
1144: $r->print('"'.join('","',("username","domain","ID","student name",
1145: "section","status")).'"'."\n");
1146: } else {
1147: $r->print('"'.join('","',("username","domain","ID","student name",
1148: "section")).'"'."\n");
1149: }
1.60 matthew 1150: } elsif ($mode eq 'excel') {
1151: # Create the excel spreadsheet
1152: $excel_filename = '/prtspool/'.
1153: $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
1154: time.'_'.rand(1000000000).'.xls';
1155: $excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.
1156: $excel_filename);
1157: $excel_workbook->set_tempdir('/home/httpd/perl/tmp');
1158: $excel_sheet = $excel_workbook->addworksheet('classlist');
1159: #
1.76 albertel 1160: my $description = 'Class List for '.
1.60 matthew 1161: $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
1162: $excel_sheet->write($row++,0,$description);
1163: #
1164: $excel_sheet->write($row++,0,["username","domain","ID",
1165: "student name","section","status"]);
1.41 matthew 1166: }
1.56 matthew 1167: #
1168: # Sort the students
1169: my %index;
1170: my $i;
1171: foreach (@$keylist) {
1172: $index{$_} = $i++;
1173: }
1174: my $index = $index{$sortby};
1175: my $second = $index{'username'};
1176: my $third = $index{'domain'};
1.53 matthew 1177: my @Sorted_Students = sort {
1.56 matthew 1178: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
1179: ||
1180: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
1181: ||
1182: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1183: } (keys(%$classlist));
1.53 matthew 1184: foreach my $student (@Sorted_Students) {
1.56 matthew 1185: my $username = $classlist->{$student}->[$index{'username'}];
1186: my $domain = $classlist->{$student}->[$index{'domain'}];
1187: my $section = $classlist->{$student}->[$index{'section'}];
1188: my $name = $classlist->{$student}->[$index{'fullname'}];
1189: my $id = $classlist->{$student}->[$index{'id'}];
1190: my $status = $classlist->{$student}->[$index{'status'}];
1.57 matthew 1191: next if (($statusmode ne 'Any') && ($status ne $statusmode));
1.51 matthew 1192: if ($mode eq 'view') {
1193: $r->print("<tr>\n <td>\n ");
1194: if ($linkto eq 'nothing') {
1195: $r->print($username);
1196: } elsif ($linkto eq 'aboutme') {
1197: $r->print(&Apache::loncommon::aboutmewrapper($username,
1198: $username,
1199: $domain));
1200: } elsif ($linkto eq 'modify') {
1.59 matthew 1201: $r->print('<a href="'.
1202: "javascript:document.studentform.sname.value='".
1203: $username.
1204: "';document.studentform.sdom.value='".$domain.
1205: "';document.studentform.state.value='selected".
1206: "';document.studentform.submit();".'">'.
1.53 matthew 1207: $username."</a>\n");
1.50 matthew 1208: }
1.51 matthew 1209: $r->print(<<"END");
1.50 matthew 1210: </td>
1.51 matthew 1211: <td>$domain</td>
1212: <td>$id</td>
1213: <td>$name</td>
1214: <td>$section</td>
1.40 matthew 1215: </tr>
1216: END
1.51 matthew 1217: } elsif ($mode eq 'csv') {
1218: # no need to bother with $linkto
1219: my @line = ();
1220: foreach ($username,$domain,$id,$name,$section) {
1221: push @line,&Apache::loncommon::csv_translate($_);
1.58 matthew 1222: }
1223: if ($statusmode eq 'Any') {
1224: push @line,&Apache::loncommon::csv_translate($status);
1.41 matthew 1225: }
1.51 matthew 1226: my $tmp = $";
1227: $" = '","';
1228: $r->print("\"@line\"\n");
1229: $" = $tmp;
1.60 matthew 1230: } elsif ($mode eq 'excel') {
1231: $excel_sheet->write($row++,0,[$username,$domain,$id,
1232: $name,$section,$status]);
1.40 matthew 1233: }
1234: }
1.60 matthew 1235: if ($mode eq 'view') {
1236: $r->print('</table><br>');
1237: } elsif ($mode eq 'excel') {
1238: $excel_workbook->close();
1239: $r->print('<p><a href="'.$excel_filename.'">'.
1240: 'Your Excel spreadsheet</a> is ready for download.</p>'."\n");
1241: }
1.40 matthew 1242: }
1243:
1.50 matthew 1244:
1245: #
1246: # print out form for modification of a single students data
1247: #
1248: sub print_modify_student_form {
1249: my $r = shift();
1250: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.59 matthew 1251: ['sdom','sname']);
1.53 matthew 1252: my $sname = $ENV{'form.sname'};
1253: my $sdom = $ENV{'form.sdom'};
1254: my $sortby = $ENV{'form.sortby'};
1.50 matthew 1255: # determine the students name information
1256: my %info=&Apache::lonnet::get('environment',
1257: ['firstname','middlename',
1.52 matthew 1258: 'lastname','generation','id'],
1.50 matthew 1259: $sdom, $sname);
1260: my ($tmp) = keys(%info);
1261: if ($tmp =~ /^(con_lost|error|no_such_host)/i) {
1262: $r->print('<font color="#ff0000" size="+2">Error</font>'.
1263: '<p>'.
1264: 'Unable to retrieve environment data for '.$sname.
1265: 'in domain '.$sdom.'</p><p>'.
1266: 'Please contact your LON-CAPA administrator '.
1267: 'regarding this situation.</p></body></html>');
1268: return;
1269: }
1270: # determine the students starting and ending times and section
1271: my ($starttime,$endtime,$section) = &get_enrollment_data($sname,$sdom);
1.87 matthew 1272: if ($starttime =~ /^error/) {
1273: $r->print('<h2>Error</h2>');
1274: $r->print('<p>'.$starttime.'</p>');
1275: return;
1276: }
1.50 matthew 1277: # Deal with date forms
1.68 matthew 1278: my $date_table = &date_setting_table($starttime,$endtime);
1.59 matthew 1279: #
1280: if (! exists($ENV{'form.Status'}) ||
1281: $ENV{'form.Status'} !~ /^(Any|Expired|Active)$/) {
1282: $ENV{'form.Status'} = 'crap';
1283: }
1.50 matthew 1284: # Make sure student is enrolled in course
1285: $r->print(<<END);
1.52 matthew 1286: <p>
1287: <font size="+1">
1288: Only domain coordinators can change a users password.
1289: </font>
1290: </p>
1.50 matthew 1291: <input type="hidden" name="slogin" value="$sname" />
1292: <input type="hidden" name="sdomain" value="$sdom" />
1293: <input type="hidden" name="action" value="modifystudent" />
1.53 matthew 1294: <input type="hidden" name="state" value="done" />
1295: <input type="hidden" name="sortby" value="$sortby" />
1.59 matthew 1296: <input type="hidden" name="Status" value="$ENV{'form.Status'}" />
1297:
1.50 matthew 1298: <h2>Modify Enrollment for $info{'firstname'} $info{'middlename'}
1299: $info{'lastname'} $info{'generation'}, $sname\@$sdom</h2>
1300: <p>
1301: <b>Student Name</b>
1302: <table>
1303: <tr><th>First</th><th>Middle</th><th>Last</th><th>Generation</th></tr>
1304: <tr><td>
1305: <input type="text" name="firstname" value="$info{'firstname'}" /></td><td>
1306: <input type="text" name="middlename" value="$info{'middlename'}" /></td><td>
1307: <input type="text" name="lastname" value="$info{'lastname'}" /></td><td>
1308: <input type="text" name="generation" value="$info{'generation'}" /></td></tr>
1309: </table>
1310: </p><p>
1.52 matthew 1311: <b>Student ID</b>: <input type="text" name="id" value="$info{'id'}" size="12"/>
1312: </p><p>
1.53 matthew 1313: <input type="checkbox" name="forceid" >
1314: Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
1315: (only do if you know what you are doing)
1316: </p><p>
1.50 matthew 1317: <b>Section</b>: <input type="text" name="section" value="$section" size="4"/>
1318: </p>
1.68 matthew 1319: <p>$date_table</p>
1.50 matthew 1320: <input type="submit" value="Submit Modifications" />
1321: </body></html>
1322: END
1323: return;
1324: }
1325:
1326: #
1327: # modify a single students section
1328: #
1329: sub modify_single_student {
1330: my $r = shift;
1.68 matthew 1331: #
1.80 matthew 1332: # Remove non alphanumeric values from the section
1333: $ENV{'form.section'} =~ s/\W//g;
1.77 matthew 1334: #
1.68 matthew 1335: # Do the date defaults first
1336: my ($starttime,$endtime) = &get_dates_from_form();
1337: if ($ENV{'form.makedatesdefault'}) {
1338: $r->print(&make_dates_default($starttime,$endtime));
1339: }
1.59 matthew 1340: # Get the 'sortby' and 'Status' variables so the user goes back to their
1341: # previous screen
1.53 matthew 1342: my $sortby = $ENV{'form.sortby'};
1.59 matthew 1343: my $status = $ENV{'form.Status'};
1.53 matthew 1344: #
1345: # We always need this information
1346: my $slogin = $ENV{'form.slogin'};
1347: my $sdom = $ENV{'form.sdomain'};
1348: #
1349: # Get the old data
1350: my %old=&Apache::lonnet::get('environment',
1351: ['firstname','middlename',
1352: 'lastname','generation','id'],
1353: $sdom, $slogin);
1.59 matthew 1354: $old{'section'} = &Apache::lonnet::getsection($sdom,$slogin,
1355: $ENV{'request.course.id'});
1.53 matthew 1356: my ($tmp) = keys(%old);
1357: if ($tmp =~ /^(con_lost|error|no_such_host)/i) {
1358: $r->print("There was an error determining the environment values ".
1359: " for $slogin \@ $sdom.");
1360: return;
1361: }
1362: undef $tmp;
1363: #
1364: # Get the new data
1.50 matthew 1365: my $firstname = $ENV{'form.firstname'};
1366: my $middlename = $ENV{'form.middlename'};
1367: my $lastname = $ENV{'form.lastname'};
1368: my $generation = $ENV{'form.generation'};
1369: my $section = $ENV{'form.section'};
1370: my $courseid = $ENV{'request.course.id'};
1.52 matthew 1371: my $sid = $ENV{'form.id'};
1.50 matthew 1372: my $displayable_starttime = localtime($starttime);
1373: my $displayable_endtime = localtime($endtime);
1.53 matthew 1374: #
1375: # check for forceid override
1.63 matthew 1376: if ((defined($old{'id'})) && ($old{'id'} ne '') &&
1377: ($sid ne $old{'id'}) && (! exists($ENV{'form.forceid'}))) {
1.53 matthew 1378: $r->print("<font color=\"ff0000\">You changed the students id ".
1379: " but did not disable the ID change safeguard.".
1380: " The students id will not be changed.</font>");
1381: $sid = $old{'id'};
1382: }
1383: #
1.50 matthew 1384: # talk to the user about what we are going to do
1385: $r->print(<<END);
1.53 matthew 1386: <h2>Modifying data for user $slogin \@ $sdom </h2>
1.50 matthew 1387: <h3>Student Information</h3>
1.53 matthew 1388: <table rules="rows" border="1" cellpadding="3" >
1389: <tr>
1390: <th> Field </th>
1391: <th> Old Value </th>
1392: <th> New Value </th>
1393: </tr>
1394: <tr>
1395: <td> <b>First name</b> </td>
1396: <td> $old{'firstname'} </td>
1397: <td> $firstname </td>
1398: </tr><tr>
1399: <td> <b>Middle name</b> </td>
1400: <td> $old{'middlename'} </td>
1401: <td> $middlename </td>
1402: </tr><tr>
1403: <td> <b>Last name</b> </td>
1404: <td> $old{'lastname'} </td>
1405: <td> $lastname </td>
1406: </tr><tr>
1407: <td> <b>Generation</b> </td>
1408: <td> $old{'generation'} </td>
1409: <td> $generation </td>
1410: </tr><tr>
1411: <td> <b>ID</b> </td>
1412: <td> $old{'id'} </td>
1413: <td> $sid </td>
1.59 matthew 1414: </tr><tr>
1415: <td> <b>Section</b> </td>
1416: <td> $old{'section'} </td>
1417: <td> $section</td>
1.53 matthew 1418: </tr>
1.50 matthew 1419: </table>
1420: <h3>Role Information</h3>
1421: <table>
1.68 matthew 1422: <tr><td align="right"><b>Start Time:</b></td><td> $displayable_starttime </td></tr>
1423: <tr><td align="right"><b>End Time:</b></td><td> $displayable_endtime </td></tr>
1.50 matthew 1424: </table>
1.52 matthew 1425: <p>
1.50 matthew 1426: END
1.53 matthew 1427: #
1.63 matthew 1428: # Send request(s) to modify data (final undef is for 'desiredhost',
1429: # which is a moot point because the student already has an account.
1430: my $modify_section_results = &modifystudent($sdom,$slogin,
1431: $ENV{'request.course.id'},
1432: $section,undef);
1433: if ($modify_section_results !~ /^ok/) {
1434: $r->print("An error occured during the attempt to change the ".
1435: "section for this student.<br />");
1436: }
1.52 matthew 1437: my $roleresults = &Apache::lonnet::modifystudent
1.53 matthew 1438: ($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname,
1439: $generation,$section,$endtime,$starttime,$ENV{'form.forceid'});
1440: if ($roleresults eq 'refused' ) {
1.50 matthew 1441: $r->print("Your request to change the role information for this ".
1.53 matthew 1442: "student was refused. You do not appear to have ".
1443: "sufficient authority to change student information.");
1.50 matthew 1444: } elsif ($roleresults !~ /ok/) {
1445: $r->print("An error occurred during the attempt to change the role".
1.52 matthew 1446: " information for this student. <br />".
1447: "The error reported was ".
1.50 matthew 1448: $roleresults);
1.53 matthew 1449: &Apache::lonnet::logthis("londropadd:failed attempt to modify student".
1450: " data for ".$slogin." \@ ".$sdom." by ".
1451: $ENV{'user.name'}." \@ ".$ENV{'user.domain'}.
1452: ":".$roleresults);
1.50 matthew 1453: } else { # everything is okay!
1.52 matthew 1454: $r->print("Student information updated successfully. <br />".
1455: "The student must log out and log in again to see ".
1456: "these changes.");
1.50 matthew 1457: }
1458: $r->print(<<END);
1.52 matthew 1459: </p><p>
1.59 matthew 1460: <input type="hidden" name="action" value="modifystudent" />
1461: <input type="hidden" name="sortby" value="$sortby" />
1462: <input type="hidden" name="Status" value="$status" />
1463: <a href="javascript:document.studentform.submit();">Modify another students data</a>
1.50 matthew 1464: </body></html>
1465: END
1466: return;
1467: }
1468:
1469: sub get_enrollment_data {
1470: my ($sname,$sdomain) = @_;
1471: my $courseid = $ENV{'request.course.id'};
1472: $courseid =~ s:_:/:g;
1473: my %roles = &Apache::lonnet::dump('roles',$sdomain,$sname);
1474: my ($tmp) = keys(%roles);
1475: # Bail out if we were unable to get the students roles
1.87 matthew 1476: return ('error'.$tmp) if ($tmp =~ /^(con_lost|error|no_such_host)/i);
1.50 matthew 1477: # Go through the roles looking for enrollment in this course
1478: my ($end,$start) = (undef,undef);
1479: my $section = '';
1480: my $count = scalar(keys(%roles));
1481: while (my ($course,$role) = each(%roles)) {
1482: if ($course=~ /^\/$courseid\/*\s*(\w+)*_st$/ ) {
1483: #
1484: # Get active role
1485: $section=$1;
1486: (undef,$end,$start)=split(/\_/,$role);
1487: my $now=time;
1488: my $notactive=0;
1489: if ($start) {
1490: if ($now<$start) { $notactive=1; }
1491: }
1492: if ($end) {
1493: if ($now>$end) { $notactive=1; }
1494: }
1495: unless ($notactive) { return ($start,$end,$section); }
1496: }
1497: }
1498: return ($start,$end,$section);
1499: }
1500:
1.56 matthew 1501: #################################################
1502: #################################################
1503:
1504: =pod
1505:
1506: =item show_drop_list
1507:
1508: Display a list of students to drop
1509: Inputs:
1510:
1511: =over 4
1512:
1513: =item $r, Apache request
1514:
1515: =item $classlist, hash pointer returned from loncoursedata::get_classlist();
1516:
1517: =item $keylist, array pointer returned from loncoursedata::get_classlist()
1518: which describes the order elements are stored in the %$classlist values.
1519:
1520: =item $nosort, if true, sorting links are omitted.
1521:
1522: =back
1523:
1524: =cut
1525:
1526: #################################################
1527: #################################################
1.11 www 1528: sub show_drop_list {
1.56 matthew 1529: my ($r,$classlist,$keylist,$nosort)=@_;
1.11 www 1530: my $cid=$ENV{'request.course.id'};
1.59 matthew 1531: if (! exists($ENV{'form.sortby'})) {
1532: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1533: ['sortby']);
1534: }
1.54 matthew 1535: my $sortby = $ENV{'form.sortby'};
1536: if ($sortby !~ /^(username|domain|section|fullname|id)$/) {
1537: $sortby = 'username';
1538: }
1.56 matthew 1539: #
1.54 matthew 1540: my $action = "drop";
1541: $r->print(<<END);
1542: <input type="hidden" name="sortby" value="$sortby" />
1543: <input type="hidden" name="action" value="$action" />
1.50 matthew 1544: <input type="hidden" name="state" value="done" />
1.32 matthew 1545: <script>
1.51 matthew 1546: function checkAll(field) {
1.32 matthew 1547: for (i = 0; i < field.length; i++)
1548: field[i].checked = true ;
1549: }
1550:
1.51 matthew 1551: function uncheckAll(field) {
1.32 matthew 1552: for (i = 0; i < field.length; i++)
1553: field[i].checked = false ;
1554: }
1555: </script>
1556: <p>
1.26 matthew 1557: <input type="hidden" name="phase" value="four">
1.56 matthew 1558: END
1559:
1560: if ($nosort) {
1561: $r->print(<<END);
1562: <table border=2>
1563: <tr>
1564: <th> </th>
1565: <th>username</th>
1566: <th>domain</th>
1567: <th>ID</th>
1568: <th>student name</th>
1569: <th>section</th>
1570: </tr>
1571: END
1572:
1573: } else {
1574: $r->print(<<END);
1.26 matthew 1575: <table border=2>
1.54 matthew 1576: <tr><th> </th>
1577: <th>
1578: <a href="/adm/dropadd?action=$action&sortby=username">username</a>
1579: </th><th>
1580: <a href="/adm/dropadd?action=$action&sortby=domain">domain</a>
1581: </th><th>
1582: <a href="/adm/dropadd?action=$action&sortby=id">ID</a>
1583: </th><th>
1584: <a href="/adm/dropadd?action=$action&sortby=fullname">student name</a>
1585: </th><th>
1586: <a href="/adm/dropadd?action=$action&sortby=section">section</a>
1587: </th>
1588: </tr>
1.26 matthew 1589: END
1.56 matthew 1590: }
1591: #
1592: # Sort the students
1593: my %index;
1594: my $i;
1595: foreach (@$keylist) {
1596: $index{$_} = $i++;
1597: }
1598: my $index = $index{$sortby};
1599: my $second = $index{'username'};
1600: my $third = $index{'domain'};
1.54 matthew 1601: my @Sorted_Students = sort {
1.56 matthew 1602: lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index])
1603: ||
1604: lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
1605: ||
1606: lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
1607: } (keys(%$classlist));
1.54 matthew 1608: foreach my $student (@Sorted_Students) {
1.52 matthew 1609: my $error;
1.56 matthew 1610: my $username = $classlist->{$student}->[$index{'username'}];
1611: my $domain = $classlist->{$student}->[$index{'domain'}];
1612: my $section = $classlist->{$student}->[$index{'section'}];
1613: my $name = $classlist->{$student}->[$index{'fullname'}];
1614: my $id = $classlist->{$student}->[$index{'id'}];
1615: my $status = $classlist->{$student}->[$index{'status'}];
1.51 matthew 1616: next if ($status ne 'Active');
1617: #
1618: $r->print(<<"END");
1.26 matthew 1619: <tr>
1.51 matthew 1620: <td><input type="checkbox" name="droplist" value="$student"></td>
1621: <td>$username</td>
1622: <td>$domain</td>
1623: <td>$id</td>
1624: <td>$name</td>
1625: <td>$section</td>
1.26 matthew 1626: </tr>
1627: END
1.25 matthew 1628: }
1629: $r->print('</table><br>');
1.32 matthew 1630: $r->print(<<"END");
1631: </p><p>
1632: <input type="button" value="check all" onclick="javascript:checkAll(document.studentform.droplist)">
1633: <input type="button" value="uncheck all" onclick="javascript:uncheckAll(document.studentform.droplist)">
1634: <p><input type=submit value="Drop Students"></p>
1635: END
1.51 matthew 1636: return;
1.10 www 1637: }
1638:
1.48 matthew 1639: #
1640: # Print out the initial form to get the courselist file
1641: #
1642: sub print_first_courselist_upload_form {
1643: my $r=shift;
1.88 matthew 1644: my $str;
1645: $str = '<input type="hidden" name="phase" value="two">';
1646: $str .= '<input type="hidden" name="action" value="upload" />';
1647: $str .= '<input type="hidden" name="state" value="got_file" />';
1648: $str .= "<h3>".&mt('Upload a class list')."</h3>\n";
1649: $str .= &Apache::loncommon::upfile_select_html();
1650: $str .= "<p>\n";
1651: $str .= '<input type="submit" name="fileupload" value="'.
1652: &mt('Upload class list').'">'."\n";
1653: $str .= '<input type="checkbox" name="noFirstLine" /> '.
1654: &mt('Ignore First Line')."</p>\n";
1655: $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List",
1656: "How do I create a class list from a spreadsheet").
1657: "<br />\n";
1658: $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
1659: "How do I create a CSV file from a spreadsheet").
1660: "<br />\n";
1661: $str .= "</body>\n</html>\n";
1662: $r->print($str);
1.48 matthew 1663: return;
1664: }
1665:
1.10 www 1666: # ================================================= Drop/Add from uploaded file
1667: sub upfile_drop_add {
1668: my $r=shift;
1.24 albertel 1669: &Apache::loncommon::load_tmp_file($r);
1670: my @studentdata=&Apache::loncommon::upfile_record_sep();
1.82 www 1671: if($ENV{'form.noFirstLine'}){shift(@studentdata);}
1.26 matthew 1672: my @keyfields = split(/\,/,$ENV{'form.keyfields'});
1673: my $cid = $ENV{'request.course.id'};
1.25 matthew 1674: my %fields=();
1.26 matthew 1675: for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
1.25 matthew 1676: if ($ENV{'form.upfile_associate'} eq 'reverse') {
1677: if ($ENV{'form.f'.$i} ne 'none') {
1678: $fields{$keyfields[$i]}=$ENV{'form.f'.$i};
1679: }
1680: } else {
1681: $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
1682: }
1683: }
1.26 matthew 1684: #
1.68 matthew 1685: my ($startdate,$enddate) = &get_dates_from_form();
1686: if ($ENV{'form.makedatesdefault'}) {
1687: $r->print(&make_dates_default($startdate,$enddate));
1688: }
1.31 matthew 1689: # Determine domain and desired host (home server)
1.25 matthew 1690: my $domain=$ENV{'form.lcdomain'};
1.31 matthew 1691: my $desiredhost = $ENV{'form.lcserver'};
1692: if (lc($desiredhost) eq 'default') {
1693: $desiredhost = undef;
1694: } else {
1.45 matthew 1695: my %home_servers = &Apache::loncommon::get_library_servers($domain);
1.31 matthew 1696: if (! exists($home_servers{$desiredhost})) {
1.88 matthew 1697: $r->print('<font color="#ff0000">'.&mt('Error').'</font>'.
1698: &mt('Invalid home server specified'));
1699: $r->print("</body>\n</html>\n");
1.31 matthew 1700: return;
1701: }
1702: }
1.26 matthew 1703: # Determine authentication mechanism
1704: my $amode = '';
1705: my $genpwd = '';
1.25 matthew 1706: if ($ENV{'form.login'} eq 'krb') {
1.47 albertel 1707: $amode='krb';
1708: $amode.=$ENV{'form.krbver'};
1.28 matthew 1709: $genpwd=$ENV{'form.krbarg'};
1.25 matthew 1710: } elsif ($ENV{'form.login'} eq 'int') {
1711: $amode='internal';
1.28 matthew 1712: if ((defined($ENV{'form.intarg'})) && ($ENV{'form.intarg'})) {
1713: $genpwd=$ENV{'form.intarg'};
1.25 matthew 1714: }
1715: } elsif ($ENV{'form.login'} eq 'loc') {
1716: $amode='localauth';
1717: if ((defined($ENV{'form.locarg'})) && ($ENV{'form.locarg'})) {
1718: $genpwd=$ENV{'form.locarg'};
1.79 matthew 1719: }
1720: }
1721: if ($amode =~ /^krb/) {
1722: if (! defined($genpwd) || $genpwd eq '') {
1723: $r->print('<font color="red" size="+1">'.
1.88 matthew 1724: &mt('Unable to enroll students').'</font> '.
1725: &mt('No Kerberos domain was specified.').'</p>');
1.79 matthew 1726: $amode = ''; # This causes the loop below to be skipped
1.25 matthew 1727: }
1728: }
1729: unless (($domain=~/\W/) || ($amode eq '')) {
1.26 matthew 1730: #######################################
1731: ## Enroll Students ##
1732: #######################################
1.88 matthew 1733: $r->print('<h3>'.&mt('Enrolling Students')."</h3>\n<p>\n");
1.25 matthew 1734: my $count=0;
1735: my $flushc=0;
1736: my %student=();
1.26 matthew 1737: # Get new classlist
1.25 matthew 1738: foreach (@studentdata) {
1739: my %entries=&Apache::loncommon::record_sep($_);
1.26 matthew 1740: # Determine student name
1.25 matthew 1741: unless (($entries{$fields{'username'}} eq '') ||
1742: (!defined($entries{$fields{'username'}}))) {
1.26 matthew 1743: my ($fname, $mname, $lname,$gen) = ('','','','');
1.25 matthew 1744: if (defined($fields{'names'})) {
1.26 matthew 1745: ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
1746: /([^\,]+)\,\s*(\w+)\s*(.*)$/);
1.25 matthew 1747: } else {
1748: if (defined($fields{'fname'})) {
1749: $fname=$entries{$fields{'fname'}};
1750: }
1751: if (defined($fields{'mname'})) {
1752: $mname=$entries{$fields{'mname'}};
1753: }
1754: if (defined($fields{'lname'})) {
1755: $lname=$entries{$fields{'lname'}};
1756: }
1757: if (defined($fields{'gen'})) {
1758: $gen=$entries{$fields{'gen'}};
1759: }
1760: }
1761: if ($entries{$fields{'username'}}=~/\W/) {
1.88 matthew 1762: $r->print('<br />'.
1763: &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]',
1764: $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
1765: '</b>');
1.25 matthew 1766: } else {
1.26 matthew 1767: # determine section number
1.25 matthew 1768: my $sec='';
1769: my $username=$entries{$fields{'username'}};
1770: if (defined($fields{'sec'})) {
1771: if (defined($entries{$fields{'sec'}})) {
1772: $sec=$entries{$fields{'sec'}};
1773: }
1774: }
1.80 matthew 1775: # remove non alphanumeric values from section
1776: $sec =~ s/\W//g;
1.26 matthew 1777: # determine student id number
1.25 matthew 1778: my $id='';
1779: if (defined($fields{'id'})) {
1780: if (defined($entries{$fields{'id'}})) {
1781: $id=$entries{$fields{'id'}};
1782: }
1783: $id=~tr/A-Z/a-z/;
1784: }
1.73 www 1785: # determine email address
1786: my $email='';
1787: if (defined($fields{'email'})) {
1788: if (defined($entries{$fields{'email'}})) {
1789: $email=$entries{$fields{'email'}};
1790: unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
1791: }
1792: }
1.26 matthew 1793: # determine student password
1.25 matthew 1794: my $password='';
1795: if ($genpwd) {
1796: $password=$genpwd;
1797: } else {
1798: if (defined($fields{'ipwd'})) {
1799: if ($entries{$fields{'ipwd'}}) {
1800: $password=$entries{$fields{'ipwd'}};
1801: }
1802: }
1803: }
1.56 matthew 1804: # Clean up whitespace
1805: foreach (\$domain,\$username,\$id,\$fname,\$mname,
1806: \$lname,\$gen,\$sec) {
1807: $$_ =~ s/(\s+$|^\s+)//g;
1808: }
1.84 albertel 1809: if ($password || $ENV{'form.login'} eq 'loc') {
1.33 matthew 1810: &modifystudent($domain,$username,$cid,$sec,
1811: $desiredhost);
1.25 matthew 1812: my $reply=&Apache::lonnet::modifystudent
1813: ($domain,$username,$id,$amode,$password,
1814: $fname,$mname,$lname,$gen,$sec,$enddate,
1.73 www 1815: $startdate,$ENV{'form.forceid'},$desiredhost,
1816: $email);
1.26 matthew 1817: if ($reply ne 'ok') {
1.72 matthew 1818: $reply =~ s/^error://;
1.88 matthew 1819: $r->print('<br />'.
1820: &mt('<b>[_1]</b>: Unable to enroll: [_2]',$username,$reply));
1.10 www 1821: } else {
1.7 www 1822: $count++; $flushc++;
1823: $student{$username}=1;
1.6 www 1824: $r->print('. ');
1.7 www 1825: if ($flushc>15) {
1826: $r->rflush;
1827: $flushc=0;
1828: }
1.6 www 1829: }
1.25 matthew 1830: } else {
1.88 matthew 1831: $r->print('<br />'.
1832: &mt('<b>[_1]</b>: Unable to enroll. No password specified.',$username)
1833: );
1.25 matthew 1834: }
1835: }
1.26 matthew 1836: }
1837: } # end of foreach (@studentdata)
1.88 matthew 1838: $r->print("</p>\n<p>\n".&mt('Processed [_1] student(s).',$count).
1839: "</p>\n");
1840: $r->print("<p>\n".
1841: &mt('If active, the new role will be available when the '.
1842: 'students next log in to LON-CAPA.')."</p>\n");
1.26 matthew 1843: #####################################
1844: # Drop students #
1845: #####################################
1.25 matthew 1846: if ($ENV{'form.fullup'} eq 'yes') {
1.88 matthew 1847: $r->print('<h3>'.&mt('Dropping Students')."</h3>\n");
1.26 matthew 1848: # Get current classlist
1.56 matthew 1849: my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
1850: if (! defined($classlist)) {
1.88 matthew 1851: $r->print(&mt('There are no students currently enrolled.').
1852: "\n");
1.56 matthew 1853: } else {
1854: # Remove the students we just added from the list of students.
1.25 matthew 1855: foreach (@studentdata) {
1856: my %entries=&Apache::loncommon::record_sep($_);
1857: unless (($entries{$fields{'username'}} eq '') ||
1858: (!defined($entries{$fields{'username'}}))) {
1.56 matthew 1859: delete($classlist->{$entries{$fields{'username'}}.
1.26 matthew 1860: ':'.$domain});
1.25 matthew 1861: }
1862: }
1.56 matthew 1863: # Print out list of dropped students.
1864: &show_drop_list($r,$classlist,$keylist,'nosort');
1.25 matthew 1865: }
1866: }
1.26 matthew 1867: } # end of unless
1.10 www 1868: }
1869:
1.11 www 1870: # ================================================================== Phase four
1871: sub drop_student_list {
1872: my $r=shift;
1873: my $count=0;
1.35 matthew 1874: my @droplist;
1875: if (ref($ENV{'form.droplist'})) {
1876: @droplist = @{$ENV{'form.droplist'}};
1877: } else {
1878: @droplist = ($ENV{'form.droplist'});
1879: }
1880: foreach (@droplist) {
1.26 matthew 1881: my ($uname,$udom)=split(/\:/,$_);
1.56 matthew 1882: # drop student
1.35 matthew 1883: my $result = &modifystudent($udom,$uname,$ENV{'request.course.id'});
1.37 matthew 1884: if ($result eq 'ok' || $result eq 'ok:') {
1.88 matthew 1885: $r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'<br>');
1.59 matthew 1886: $count++;
1.35 matthew 1887: } else {
1.88 matthew 1888: $r->print(
1889: &mt('Error dropping [_1]:[_2]',$uname.'@'.$udom,$result).
1.35 matthew 1890: '<br />');
1891: }
1.20 harris41 1892: }
1.88 matthew 1893: $r->print('<p><b>'.&mt('Dropped [_1] student(s).',$count).'</b></p>');
1894: $r->print('<p>'.&mt('Re-enrollment will re-activate data.')) if ($count);
1.11 www 1895: }
1896:
1.50 matthew 1897: ###################################################################
1898: ###################################################################
1899:
1900: =pod
1901:
1902: =item &handler
1903:
1904: The typical handler you see in all these modules. Takes $r, the
1905: http request, as an argument.
1906:
1907: The response to the request is governed by two form variables
1908:
1909: form.action form.state response
1910: ---------------------------------------------------
1911: undefined undefined print main menu
1912: upload undefined print courselist upload menu
1913: upload got_file deal with uploaded file,
1914: print the upload managing menu
1915: upload enrolling enroll students based on upload
1916: drop undefined print the classlist ready to drop
1917: drop done drop the selected students
1.74 matthew 1918: enrollstudent undefined print student username domain form
1919: enrollstudent gotusername print single student enroll menu
1.50 matthew 1920: enrollstudent enrolling enroll student
1921: classlist undefined print html classlist
1922: classlist csv print csv classlist
1923: modifystudent undefined print classlist to select student to modify
1924: modifystudent selected print modify student menu
1925: modifystudent done make modifications to student record
1926:
1927: =cut
1928:
1929: ###################################################################
1930: ###################################################################
1.10 www 1931: sub handler {
1.26 matthew 1932: my $r=shift;
1933: if ($r->header_only) {
1.86 www 1934: &Apache::loncommon::content_type($r,'text/html');
1.26 matthew 1935: $r->send_http_header;
1936: return OK;
1937: }
1.48 matthew 1938: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.50 matthew 1939: ['action','state']);
1.26 matthew 1940: # Needs to be in a course
1.50 matthew 1941: if (! (($ENV{'request.course.fn'}) &&
1942: (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'})))) {
1943: # Not in a course, or not allowed to modify parms
1944: $ENV{'user.error.msg'}=
1945: "/adm/dropadd:cst:0:0:Cannot drop or add students";
1946: return HTTP_NOT_ACCEPTABLE;
1947: }
1948: #
1949: # Only output the header information if they did not request csv format
1950: #
1951: if (exists($ENV{'form.state'}) && ($ENV{'form.state'} eq 'csv')) {
1952: $r->content_type('text/csv');
1953: } else {
1.26 matthew 1954: # Start page
1.86 www 1955: &Apache::loncommon::content_type($r,'text/html');
1.26 matthew 1956: $r->send_http_header;
1.50 matthew 1957: $r->print(&header());
1958: }
1959: #
1960: # Main switch on form.action and form.state, as appropriate
1961: if (! exists($ENV{'form.action'})) {
1962: &print_main_menu($r);
1963: } elsif ($ENV{'form.action'} eq 'upload') {
1964: if (! exists($ENV{'form.state'})) {
1965: &print_first_courselist_upload_form($r);
1966: } elsif ($ENV{'form.state'} eq 'got_file') {
1967: &print_upload_manager_form($r);
1968: } elsif ($ENV{'form.state'} eq 'enrolling') {
1.26 matthew 1969: if ($ENV{'form.datatoken'}) {
1970: &upfile_drop_add($r);
1.50 matthew 1971: } else {
1972: # Hmmm, this is an error
1.26 matthew 1973: }
1.50 matthew 1974: } else {
1975: &print_first_courselist_upload_form($r);
1.26 matthew 1976: }
1.50 matthew 1977: } elsif ($ENV{'form.action'} eq 'drop') {
1978: if (! exists($ENV{'form.state'})) {
1.51 matthew 1979: &print_drop_menu($r);
1.50 matthew 1980: } elsif ($ENV{'form.state'} eq 'done') {
1.26 matthew 1981: &drop_student_list($r);
1.50 matthew 1982: } else {
1.55 matthew 1983: &print_drop_menu($r);
1.26 matthew 1984: }
1.50 matthew 1985: } elsif ($ENV{'form.action'} eq 'enrollstudent') {
1986: if (! exists($ENV{'form.state'})) {
1.74 matthew 1987: &get_student_username_domain_form($r);
1988: } elsif ($ENV{'form.state'} eq 'gotusername') {
1.50 matthew 1989: &print_enroll_single_student_form($r);
1990: } elsif ($ENV{'form.state'} eq 'enrolling') {
1.26 matthew 1991: &enroll_single_student($r);
1.50 matthew 1992: } else {
1.74 matthew 1993: &get_student_username_domain_form($r);
1.26 matthew 1994: }
1.50 matthew 1995: } elsif ($ENV{'form.action'} eq 'classlist') {
1996: if (! exists($ENV{'form.state'})) {
1997: &print_html_classlist($r);
1998: } elsif ($ENV{'form.state'} eq 'csv') {
1.60 matthew 1999: &print_formatted_classlist($r,'csv');
2000: } elsif ($ENV{'form.state'} eq 'excel') {
2001: &print_formatted_classlist($r,'excel');
1.50 matthew 2002: } else {
2003: &print_html_classlist($r);
2004: }
2005: } elsif ($ENV{'form.action'} eq 'modifystudent') {
2006: if (! exists($ENV{'form.state'})) {
2007: &print_html_classlist($r);
2008: } elsif ($ENV{'form.state'} eq 'selected') {
2009: &print_modify_student_form($r);
2010: } elsif ($ENV{'form.state'} eq 'done') {
2011: &modify_single_student($r);
2012: } else {
2013: &print_html_classlist($r);
2014: }
2015: } else {
2016: # We should not end up here, but I guess it is possible
2017: &Apache::lonnet::logthis("Undetermined state in londropadd.pm. ".
2018: "form.action = ".$ENV{'form.action'}.
2019: "Someone should fix this.");
2020: &print_main_menu($r);
2021: }
2022: #
2023: # Finish up
2024: if (exists($ENV{'form.state'}) && ($ENV{'form.state'} eq 'csv')) {
2025: $r->print("\n");
1.26 matthew 2026: } else {
1.50 matthew 2027: $r->print('</form></body></html>');
1.26 matthew 2028: }
2029: return OK;
1.1 www 2030: }
2031:
1.50 matthew 2032: ###################################################################
2033: ###################################################################
2034:
1.1 www 2035: 1;
2036: __END__
1.50 matthew 2037:
1.1 www 2038:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>