Annotation of loncom/interface/londropadd.pm, revision 1.112

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>