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