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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to drop and add students in courses 
                      3: #
1.111   ! matthew     4: # $Id: londropadd.pm,v 1.110 2004/05/13 21:03:16 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:           &Apache::lonnet::logthis('showing class list '.$ENV{'form.output'});
                   1176: 
                   1177:             &show_class_list($r,$ENV{'form.output'},'aboutme',
1.103     matthew  1178:                              $ENV{'form.Status'},$classlist,$keylist);
1.50      matthew  1179:         }
1.41      matthew  1180:     }
                   1181: }
                   1182: 
1.40      matthew  1183: # =================================================== Show student list to drop
                   1184: sub show_class_list {
1.110     matthew  1185:     my ($r,$mode,$linkto,$statusmode,$classlist,$keylist)=@_;
1.40      matthew  1186:     my $cid=$ENV{'request.course.id'};
1.60      matthew  1187:     #
                   1188:     # Variables for excel output
1.104     matthew  1189:     my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format);
1.60      matthew  1190:     #
1.103     matthew  1191:     # Variables for csv output
                   1192:     my ($CSVfile,$CSVfilename);
                   1193:     #
1.53      matthew  1194:     my $sortby = $ENV{'form.sortby'};
1.110     matthew  1195:     if ($sortby !~ /^(username|domain|section|fullname|id|start|end)$/) {
1.53      matthew  1196:         $sortby = 'username';
                   1197:     }
1.42      matthew  1198:     # Print out header 
1.103     matthew  1199:     $r->print(<<END);
1.109     matthew  1200: 
                   1201: <input type="hidden" name="state" value="$ENV{'form.state'}" />
1.103     matthew  1202: <input type="hidden" name="sortby" value="$sortby" />
                   1203: END
1.110     matthew  1204:     if ($mode eq 'html' || $mode eq 'view') {
1.50      matthew  1205:         if ($linkto eq 'aboutme') {
1.94      sakharuk 1206:             $r->print(&mt('Select a user name to view the users personal page.'));
1.50      matthew  1207:         } elsif ($linkto eq 'modify') {
1.94      sakharuk 1208:             $r->print(&mt('Select a user name to modify the students information'));
1.50      matthew  1209:         }
1.94      sakharuk 1210: 	my %lt=&Apache::lonlocal::texthash(
1.110     matthew  1211:                                            'usrn'   => "username",
                   1212:                                            'dom'    => "domain",
                   1213:                                            'sn'     => "student name",
                   1214:                                            'sec'    => "section",
                   1215:                                            'start'  => "start date",
                   1216:                                            'end'    => "end date",
1.94      sakharuk 1217: 					   );
1.41      matthew  1218:         $r->print(<<END);
1.59      matthew  1219: <input type="hidden" name="sname"  value="" />
                   1220: <input type="hidden" name="sdom"   value="" />
1.40      matthew  1221: <p>
                   1222: <table border=2>
1.108     matthew  1223: <tr><th>Count
                   1224:     </th><th>
1.94      sakharuk 1225:        <a href="javascript:document.studentform.sortby.value='username';document.studentform.submit();">$lt{'usrn'}</a>
1.53      matthew  1226:     </th><th>
1.94      sakharuk 1227:        <a href="javascript:document.studentform.sortby.value='domain';document.studentform.submit();">$lt{'dom'}</a>
1.53      matthew  1228:     </th><th>
1.57      matthew  1229:        <a href="javascript:document.studentform.sortby.value='id';document.studentform.submit();">ID</a>
1.53      matthew  1230:     </th><th>
1.94      sakharuk 1231:        <a href="javascript:document.studentform.sortby.value='fullname';document.studentform.submit();">$lt{'sn'}</a>
1.53      matthew  1232:     </th><th>
1.94      sakharuk 1233:        <a href="javascript:document.studentform.sortby.value='section';document.studentform.submit();">$lt{'sec'}</a>
1.110     matthew  1234:     </th><th>
                   1235:        <a href="javascript:document.studentform.sortby.value='start';document.studentform.submit();">$lt{'start'}</a>
                   1236:     </th><th>
                   1237:        <a href="javascript:document.studentform.sortby.value='end';document.studentform.submit();">$lt{'end'}</a>
1.53      matthew  1238:     </th>
                   1239: </tr>
1.40      matthew  1240: END
1.41      matthew  1241:     } elsif ($mode eq 'csv') {
1.103     matthew  1242: 	#
                   1243: 	# Open a file
                   1244: 	$CSVfilename = '/prtspool/'.
                   1245: 	    $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
                   1246:             time.'_'.rand(1000000000).'.csv';
                   1247: 	unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
                   1248: 	    $r->log_error("Couldn't open $CSVfilename for output $!");
                   1249: 	    $r->print("Problems occured in writing the csv file.  ".
                   1250: 		      "This error has been logged.  ".
                   1251: 		      "Please alert your LON-CAPA administrator.");
                   1252: 	    $CSVfile = undef;
                   1253: 	}
                   1254: 	#
                   1255: 	# Write headers and data to file
1.58      matthew  1256:         if($statusmode eq 'Expired') {
1.103     matthew  1257:             print $CSVfile '"'.&mt('Students with expired roles').'"'."\n";
1.58      matthew  1258:         }
                   1259:         if ($statusmode eq 'Any') {
1.103     matthew  1260:             print $CSVfile '"'.join('","',map {
                   1261: 		&Apache::loncommon::csv_translate(&mt($_))
                   1262:                 } ("username","domain","ID","student name",
1.110     matthew  1263:                    "section","start date","end date","status")).'"'."\n";
1.58      matthew  1264:         } else {
1.103     matthew  1265:             print $CSVfile '"'.join('","',map {
                   1266: 		&Apache::loncommon::csv_translate(&mt($_))
                   1267:                 } ("username","domain","ID","student name",
1.110     matthew  1268:                    "section","start date","end date")).'"'."\n";
1.58      matthew  1269:         }
1.60      matthew  1270:     } elsif ($mode eq 'excel') {
                   1271:         # Create the excel spreadsheet
                   1272:         $excel_filename = '/prtspool/'.
                   1273:             $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
                   1274:                 time.'_'.rand(1000000000).'.xls';
                   1275:         $excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.
                   1276:                                                        $excel_filename);
                   1277:         $excel_workbook->set_tempdir('/home/httpd/perl/tmp');
1.104     matthew  1278:         #
                   1279:         $format = &Apache::loncommon::define_excel_formats($excel_workbook);
1.60      matthew  1280:         $excel_sheet = $excel_workbook->addworksheet('classlist');
                   1281:         #
1.76      albertel 1282:         my $description = 'Class List for '.
1.60      matthew  1283:             $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
1.104     matthew  1284:         $excel_sheet->write($row++,0,$description,$format->{'h1'});
1.60      matthew  1285:         #
                   1286:         $excel_sheet->write($row++,0,["username","domain","ID",
1.110     matthew  1287:                                       "student name","section",
                   1288:                                       "start date","end date","status"],
                   1289:                             $format->{'bold'});
1.41      matthew  1290:     }
1.56      matthew  1291:     #
                   1292:     # Sort the students
                   1293:     my %index;
                   1294:     my $i;
                   1295:     foreach (@$keylist) {
                   1296:         $index{$_} = $i++;
                   1297:     }
                   1298:     my $index  = $index{$sortby};
                   1299:     my $second = $index{'username'};
                   1300:     my $third  = $index{'domain'};
1.53      matthew  1301:     my @Sorted_Students = sort {
1.56      matthew  1302:         lc($classlist->{$a}->[$index])  cmp lc($classlist->{$b}->[$index])
                   1303:             ||
                   1304:         lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
                   1305:             ||
                   1306:         lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
                   1307:         } (keys(%$classlist));
1.108     matthew  1308:     my $studentcount = 0;
1.53      matthew  1309:     foreach my $student (@Sorted_Students) {
1.110     matthew  1310:         my $sdata = $classlist->{$student};
                   1311:         my $username = $sdata->[$index{'username'}];
                   1312:         my $domain   = $sdata->[$index{'domain'}];
                   1313:         my $section  = $sdata->[$index{'section'}];
                   1314:         my $name     = $sdata->[$index{'fullname'}];
                   1315:         my $id       = $sdata->[$index{'id'}];
                   1316:         my $status   = $sdata->[$index{'status'}];
                   1317:         my $start    = $sdata->[$index{'start'}];
                   1318:         my $end      = $sdata->[$index{'end'}];
1.57      matthew  1319:         next if (($statusmode ne 'Any') && ($status ne $statusmode));
1.110     matthew  1320:         if ($mode eq 'view' || $mode eq 'html') {
                   1321:             $start = &Apache::lonlocal::locallocaltime($start);
                   1322:             $end   = &Apache::lonlocal::locallocaltime($end);
1.108     matthew  1323:             $r->print("<tr>\n    <td>".(++$studentcount)."</td><td>\n    ");
1.51      matthew  1324:             if ($linkto eq 'nothing') {
                   1325:                 $r->print($username);
                   1326:             } elsif ($linkto eq 'aboutme') {
                   1327:                 $r->print(&Apache::loncommon::aboutmewrapper($username,
                   1328:                                                              $username,
                   1329:                                                              $domain));
                   1330:             } elsif ($linkto eq 'modify') {
1.59      matthew  1331:                 $r->print('<a href="'.
                   1332:                           "javascript:document.studentform.sname.value='".
                   1333:                           $username.
                   1334:                           "';document.studentform.sdom.value='".$domain.
                   1335:                           "';document.studentform.state.value='selected".
                   1336:                           "';document.studentform.submit();".'">'.
1.53      matthew  1337:                           $username."</a>\n");
1.50      matthew  1338:             }
1.51      matthew  1339:             $r->print(<<"END");
1.50      matthew  1340:     </td>
1.51      matthew  1341:     <td>$domain</td>
                   1342:     <td>$id</td>
                   1343:     <td>$name</td>
                   1344:     <td>$section</td>
1.110     matthew  1345:     <td>$start</td>
                   1346:     <td>$end</td>
1.40      matthew  1347: </tr>
                   1348: END
1.51      matthew  1349:         } elsif ($mode eq 'csv') {
1.103     matthew  1350:             next if (! defined($CSVfile));
1.51      matthew  1351:             # no need to bother with $linkto
1.110     matthew  1352:             $start = &Apache::lonlocal::locallocaltime($start);
                   1353:             $end   = &Apache::lonlocal::locallocaltime($end);
1.51      matthew  1354:             my @line = ();
1.110     matthew  1355:             foreach ($username,$domain,$id,$name,$section,$start,$end) {
1.51      matthew  1356:                 push @line,&Apache::loncommon::csv_translate($_);
1.58      matthew  1357:             }
                   1358:             if ($statusmode eq 'Any') {
                   1359:                 push @line,&Apache::loncommon::csv_translate($status);
1.41      matthew  1360:             }
1.103     matthew  1361:             print $CSVfile '"'.join('","',@line).'"'."\n";
1.60      matthew  1362:         } elsif ($mode eq 'excel') {
1.110     matthew  1363:             $excel_sheet->write($row,0,[$username,$domain,$id,
                   1364:                                           $name,$section]);
                   1365:             my $col = 5;
                   1366:             foreach my $time ($start,$end) {
                   1367:                 $excel_sheet->write($row,$col++,
                   1368:                                    &Apache::lonstathelpers::calc_serial($time),
                   1369:                                     $format->{'date'});
                   1370:             }
                   1371:             $excel_sheet->write($row,$col++,$status);
                   1372:             $row++;
1.40      matthew  1373:         }
                   1374:     }
1.110     matthew  1375:     if ($mode eq 'view' || $mode eq 'html') {
1.60      matthew  1376:         $r->print('</table><br>');
                   1377:     } elsif ($mode eq 'excel') {
                   1378:         $excel_workbook->close();
                   1379:         $r->print('<p><a href="'.$excel_filename.'">'.
1.94      sakharuk 1380:                   &mt('Your Excel spreadsheet').'</a> '.&mt('is ready for download').'.</p>'."\n");
1.103     matthew  1381:     } elsif ($mode eq 'csv') {
                   1382:         close($CSVfile);
                   1383:         $r->print('<a href="'.$CSVfilename.'">'.
                   1384:                   &mt('Your CSV file').'</a> is ready for download.'.
                   1385:                   "\n");
                   1386:         $r->rflush();
1.60      matthew  1387:     }
1.40      matthew  1388: }
                   1389: 
1.50      matthew  1390: 
                   1391: #
                   1392: # print out form for modification of a single students data
                   1393: #
                   1394: sub print_modify_student_form {
                   1395:     my $r = shift();
                   1396:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.59      matthew  1397:                                             ['sdom','sname']);    
1.53      matthew  1398:     my $sname  = $ENV{'form.sname'};
                   1399:     my $sdom   = $ENV{'form.sdom'};
                   1400:     my $sortby = $ENV{'form.sortby'};
1.50      matthew  1401:     # determine the students name information
                   1402:     my %info=&Apache::lonnet::get('environment',
                   1403:                                   ['firstname','middlename',
1.52      matthew  1404:                                    'lastname','generation','id'],
1.50      matthew  1405:                                   $sdom, $sname);
                   1406:     my ($tmp) = keys(%info);
                   1407:     if ($tmp =~ /^(con_lost|error|no_such_host)/i) {
1.94      sakharuk 1408:         $r->print('<font color="#ff0000" size="+2">'.&mt('Error').'</font>'.
1.50      matthew  1409:                   '<p>'.
1.94      sakharuk 1410:                   &mt('Unable to retrieve environment data for').' '.$sname.
                   1411:                   &mt('in domain').' '.$sdom.'</p><p>'.
                   1412:                   &mt('Please contact your LON-CAPA administrator regarding this situation.').'</p></body></html>');
1.50      matthew  1413:         return;
                   1414:     }
                   1415:     # determine the students starting and ending times and section
                   1416:     my ($starttime,$endtime,$section) = &get_enrollment_data($sname,$sdom);
1.87      matthew  1417:     if ($starttime =~ /^error/) {
1.94      sakharuk 1418:         $r->print('<h2>'&mt('Error').'</h2>');
1.87      matthew  1419:         $r->print('<p>'.$starttime.'</p>');
                   1420:         return;
                   1421:     }
1.101     matthew  1422:     #
1.50      matthew  1423:     # Deal with date forms
1.101     matthew  1424:     my $current_date_description = '';
                   1425:     my $textdate = '';
                   1426: 
                   1427:     if (! defined($starttime) || $starttime == 0) {
                   1428:         $current_date_description = &mt('Current Starting Date: not set').
                   1429:             '<br />';
                   1430:     } else {
                   1431:         $current_date_description = 
                   1432:             &mt('Current Starting Date: [_1]',
                   1433:                 &Apache::lonlocal::locallocaltime($starttime)).'<br />';
                   1434:     }
                   1435:     if (! defined($endtime) || $endtime == 0) {
                   1436:         $current_date_description.= &mt('Current Ending Date: not set').
                   1437:             '<br />';
                   1438:     } else {
                   1439:         $current_date_description.= 
                   1440:             &mt('Current Ending Date: [_1]',
                   1441:                 &Apache::lonlocal::locallocaltime($endtime)).'<br />';
                   1442: 
                   1443:     }
1.68      matthew  1444:     my $date_table = &date_setting_table($starttime,$endtime);
1.59      matthew  1445:     #
                   1446:     if (! exists($ENV{'form.Status'}) || 
                   1447:         $ENV{'form.Status'} !~ /^(Any|Expired|Active)$/) {
                   1448:         $ENV{'form.Status'} = 'crap';
                   1449:     }
1.94      sakharuk 1450:     # Make sure student is enrolled in course
                   1451:     my %lt=&Apache::lonlocal::texthash(
                   1452: 	           'mef'   => "Modify Enrollment for",
                   1453:                    'odcc'  => "Only domain coordinators can change a users password.",
                   1454:                    'sn'    => "Student Name",
                   1455:                    'fn'    => "First",
                   1456:                    'mn'    => "Middle",
                   1457:                    'ln'    => "Last",
                   1458:                    'gen'   => "Generation",
                   1459:                    'sid'   => "Student ID",
                   1460:                    'disn'  => "Disable ID/Student Number Safeguard and Force Change of Conflicting IDs (only do if you know what you are doing)",
                   1461:                    'sec'   => "Section",
                   1462:                    'sm'    => "Submit Modifications",
                   1463: 				       );
1.50      matthew  1464:     $r->print(<<END);
1.52      matthew  1465: <p>
                   1466: <font size="+1">
1.94      sakharuk 1467: $lt{'odcc'}
1.52      matthew  1468: </font>
                   1469: </p>
1.50      matthew  1470: <input type="hidden" name="slogin"  value="$sname"  />
                   1471: <input type="hidden" name="sdomain" value="$sdom" />
                   1472: <input type="hidden" name="action"  value="modifystudent" />
1.53      matthew  1473: <input type="hidden" name="state"   value="done" />
                   1474: <input type="hidden" name="sortby"  value="$sortby" />
1.59      matthew  1475: <input type="hidden" name="Status"  value="$ENV{'form.Status'}" />
1.94      sakharuk 1476: <h2>$lt{'mef'} $info{'firstname'} $info{'middlename'} 
1.50      matthew  1477: $info{'lastname'} $info{'generation'}, $sname\@$sdom</h2>
                   1478: <p>
1.94      sakharuk 1479: <b>$lt{'sn'}</b>
1.50      matthew  1480: <table>
1.94      sakharuk 1481: <tr><th>$lt{'fn'}</th><th>$lt{'mn'}</th><th>$lt{'ln'}</th><th>$lt{'gen'}</th></tr>
1.50      matthew  1482: <tr><td>
                   1483: <input type="text" name="firstname"  value="$info{'firstname'}"  /></td><td>
                   1484: <input type="text" name="middlename" value="$info{'middlename'}" /></td><td>
                   1485: <input type="text" name="lastname"   value="$info{'lastname'}"   /></td><td>
                   1486: <input type="text" name="generation" value="$info{'generation'}" /></td></tr>
                   1487: </table>
                   1488: </p><p>
1.94      sakharuk 1489: <b>$lt{'sid'}</b>: <input type="text" name="id" value="$info{'id'}" size="12"/>
1.52      matthew  1490: </p><p>
1.53      matthew  1491: <input type="checkbox" name="forceid" > 
1.94      sakharuk 1492: $lt{'disn'}
1.53      matthew  1493: </p><p>
1.101     matthew  1494: <b>$lt{'sec'}</b>: <input type="text" name="section" value="$section" size="14"/>
1.50      matthew  1495: </p>
1.101     matthew  1496: <p>$current_date_description</p>
1.68      matthew  1497: <p>$date_table</p>
1.94      sakharuk 1498: <input type="submit" value="$lt{'sm'}" />
1.50      matthew  1499: </body></html>
                   1500: END
                   1501:     return;
                   1502: }
                   1503: 
                   1504: #
                   1505: # modify a single students section 
                   1506: #
                   1507: sub modify_single_student {
                   1508:     my $r = shift;
1.68      matthew  1509:     #
1.80      matthew  1510:     # Remove non alphanumeric values from the section
                   1511:     $ENV{'form.section'} =~ s/\W//g;
1.77      matthew  1512:     #
1.68      matthew  1513:     # Do the date defaults first
                   1514:     my ($starttime,$endtime) = &get_dates_from_form();
                   1515:     if ($ENV{'form.makedatesdefault'}) {
                   1516:         $r->print(&make_dates_default($starttime,$endtime));
                   1517:     }
1.59      matthew  1518:     # Get the 'sortby' and 'Status' variables so the user goes back to their
                   1519:     # previous screen
1.53      matthew  1520:     my $sortby = $ENV{'form.sortby'};
1.59      matthew  1521:     my $status = $ENV{'form.Status'};
1.53      matthew  1522:     #
                   1523:     # We always need this information
                   1524:     my $slogin     = $ENV{'form.slogin'};
                   1525:     my $sdom       = $ENV{'form.sdomain'};
                   1526:     #
                   1527:     # Get the old data
                   1528:     my %old=&Apache::lonnet::get('environment',
                   1529:                                  ['firstname','middlename',
                   1530:                                   'lastname','generation','id'],
                   1531:                                  $sdom, $slogin);
1.59      matthew  1532:     $old{'section'} = &Apache::lonnet::getsection($sdom,$slogin,
                   1533:                                                   $ENV{'request.course.id'});
1.53      matthew  1534:     my ($tmp) = keys(%old);
                   1535:     if ($tmp =~ /^(con_lost|error|no_such_host)/i) {
1.94      sakharuk 1536:         $r->print(&mt('There was an error determining the environment values for')." $slogin \@ $sdom.");
1.53      matthew  1537:         return;
                   1538:     }
                   1539:     undef $tmp;
                   1540:     #
                   1541:     # Get the new data
1.50      matthew  1542:     my $firstname  = $ENV{'form.firstname'};
                   1543:     my $middlename = $ENV{'form.middlename'};
                   1544:     my $lastname   = $ENV{'form.lastname'};
                   1545:     my $generation = $ENV{'form.generation'};
                   1546:     my $section    = $ENV{'form.section'};
                   1547:     my $courseid   = $ENV{'request.course.id'};
1.52      matthew  1548:     my $sid        = $ENV{'form.id'};
1.50      matthew  1549:     my $displayable_starttime = localtime($starttime);
                   1550:     my $displayable_endtime   = localtime($endtime);
1.53      matthew  1551:     # 
                   1552:     # check for forceid override
1.63      matthew  1553:     if ((defined($old{'id'})) && ($old{'id'} ne '') && 
                   1554:         ($sid ne $old{'id'}) && (! exists($ENV{'form.forceid'}))) {
1.94      sakharuk 1555:         $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  1556:         $sid = $old{'id'};
                   1557:     }
                   1558:     #
1.50      matthew  1559:     # talk to the user about what we are going to do
1.94      sakharuk 1560:     my %lt=&Apache::lonlocal::texthash(
                   1561: 	           'mdu'   => "Modifying data for user",
                   1562:                    'si'    => "Student Information",
                   1563:                    'fd'    => "Field",
                   1564:                    'ov'    => "Old Value",
                   1565:                    'nv'    => "New Value",
                   1566:                    'fn'    => "First name",
                   1567:                    'mn'    => "Middle name",
                   1568:                    'ln'    => "Last name",
                   1569:                    'gen'   => "Generation",
                   1570:                    'sec'   => "Section",
                   1571:                    'ri'    => "Role Information",
                   1572:                    'st'    => "Start Time",
                   1573:                    'et'    => "End Time",
                   1574: 				       );
1.50      matthew  1575:     $r->print(<<END);
1.94      sakharuk 1576:     <h2>$lt{'mdu'} $slogin \@ $sdom </h2>
                   1577: <h3>$lt{'si'}</h3>
1.53      matthew  1578: <table rules="rows" border="1" cellpadding="3" >
                   1579: <tr>
1.94      sakharuk 1580:     <th> $lt{'fd'} </th>
                   1581:     <th> $lt{'ov'} </th>
                   1582:     <th> $lt{'nv'} </th>
1.53      matthew  1583: </tr>
                   1584: <tr>
1.94      sakharuk 1585:     <td> <b>$lt{'fn'}</b> </td>
1.53      matthew  1586:     <td> $old{'firstname'} </td>
                   1587:     <td> $firstname </td>
                   1588: </tr><tr>
1.94      sakharuk 1589:     <td> <b>$lt{'mn'}</b> </td>
1.53      matthew  1590:     <td> $old{'middlename'} </td>
                   1591:     <td> $middlename </td>
                   1592: </tr><tr>
1.94      sakharuk 1593:     <td> <b>$lt{'ln'}</b> </td>
1.53      matthew  1594:     <td> $old{'lastname'} </td>
                   1595:     <td> $lastname </td>
                   1596: </tr><tr>
1.94      sakharuk 1597:     <td> <b>$lt{'gen'}</b> </td>
1.53      matthew  1598:     <td> $old{'generation'} </td>
                   1599:     <td> $generation </td>
                   1600: </tr><tr>
                   1601:     <td> <b>ID</b> </td>
                   1602:     <td> $old{'id'} </td>
                   1603:     <td> $sid </td>
1.59      matthew  1604: </tr><tr>
1.94      sakharuk 1605:     <td> <b>$lt{'sec'}</b> </td>
1.59      matthew  1606:     <td> $old{'section'} </td>
                   1607:     <td> $section</td>
1.53      matthew  1608: </tr>
1.50      matthew  1609: </table>
1.94      sakharuk 1610: <h3>$lt{'ri'}</h3>
1.50      matthew  1611: <table>
1.94      sakharuk 1612: <tr><td align="right"><b>$lt{'st'}:</b></td><td> $displayable_starttime </td></tr>
                   1613: <tr><td align="right"><b>$lt{'et'}:</b></td><td> $displayable_endtime   </td></tr>
1.50      matthew  1614: </table>
1.52      matthew  1615: <p>
1.50      matthew  1616: END
1.53      matthew  1617:     #
1.63      matthew  1618:     # Send request(s) to modify data (final undef is for 'desiredhost',
                   1619:     # which is a moot point because the student already has an account.
                   1620:     my $modify_section_results = &modifystudent($sdom,$slogin,
                   1621:                                                 $ENV{'request.course.id'},
                   1622:                                                 $section,undef);
                   1623:     if ($modify_section_results !~ /^ok/) {
1.94      sakharuk 1624:         $r->print(&mt('An error occured during the attempt to change the section for this student.')."<br />");
1.63      matthew  1625:     }
1.52      matthew  1626:     my $roleresults = &Apache::lonnet::modifystudent
1.53      matthew  1627:         ($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname,
                   1628:          $generation,$section,$endtime,$starttime,$ENV{'form.forceid'});
                   1629:     if ($roleresults eq 'refused' ) {
1.94      sakharuk 1630:         $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  1631:     } elsif ($roleresults !~ /ok/) {
1.94      sakharuk 1632:         $r->print(&mt('An error occurred during the attempt to change the role information for this student.')."  <br />".
                   1633:                   &mt('The error reported was')." ".
1.50      matthew  1634:                   $roleresults);
1.53      matthew  1635:         &Apache::lonnet::logthis("londropadd:failed attempt to modify student".
                   1636:                                  " data for ".$slogin." \@ ".$sdom." by ".
                   1637:                                  $ENV{'user.name'}." \@ ".$ENV{'user.domain'}.
                   1638:                                  ":".$roleresults);
1.50      matthew  1639:     } else { # everything is okay!
1.94      sakharuk 1640:         $r->print(&mt('Student information updated successfully.')." <br />".
                   1641:                   &mt('The student must log out and log in again to see these changes.'));
1.50      matthew  1642:     }
1.94      sakharuk 1643:     my $Masd=&mt('Modify another students data');
1.50      matthew  1644:     $r->print(<<END);
1.52      matthew  1645: </p><p>
1.59      matthew  1646: <input type="hidden" name="action" value="modifystudent" />
                   1647: <input type="hidden" name="sortby" value="$sortby" />
                   1648: <input type="hidden" name="Status" value="$status" />
1.94      sakharuk 1649: <a href="javascript:document.studentform.submit();">$Masd</a>
1.50      matthew  1650: </body></html>
                   1651: END
                   1652:     return;
                   1653: }
                   1654: 
                   1655: sub get_enrollment_data {
                   1656:     my ($sname,$sdomain) = @_;
                   1657:     my $courseid = $ENV{'request.course.id'};
                   1658:     $courseid =~ s:_:/:g;
                   1659:     my %roles = &Apache::lonnet::dump('roles',$sdomain,$sname);
                   1660:     my ($tmp) = keys(%roles);
                   1661:     # Bail out if we were unable to get the students roles
1.87      matthew  1662:     return ('error'.$tmp) if ($tmp =~ /^(con_lost|error|no_such_host)/i);
1.50      matthew  1663:     # Go through the roles looking for enrollment in this course
                   1664:     my ($end,$start) = (undef,undef);
                   1665:     my $section = '';
                   1666:     my $count = scalar(keys(%roles));
                   1667:     while (my ($course,$role) = each(%roles)) {
                   1668:         if ($course=~ /^\/$courseid\/*\s*(\w+)*_st$/ ) {
                   1669:             #
                   1670:             # Get active role
                   1671:             $section=$1;
                   1672:             (undef,$end,$start)=split(/\_/,$role);
                   1673:             my $now=time;
                   1674:             my $notactive=0;
                   1675:             if ($start) {
                   1676:                 if ($now<$start) { $notactive=1; }
                   1677:             }
                   1678:             if ($end) {
                   1679:                 if ($now>$end) { $notactive=1; }
                   1680:             } 
                   1681:             unless ($notactive) { return ($start,$end,$section); }
                   1682:         }
                   1683:     }
                   1684:     return ($start,$end,$section);
                   1685: }
                   1686: 
1.56      matthew  1687: #################################################
                   1688: #################################################
                   1689: 
                   1690: =pod
                   1691: 
                   1692: =item show_drop_list
                   1693: 
                   1694: Display a list of students to drop
                   1695: Inputs: 
                   1696: 
                   1697: =over 4
                   1698: 
                   1699: =item $r, Apache request
                   1700: 
                   1701: =item $classlist, hash pointer returned from loncoursedata::get_classlist();
                   1702: 
                   1703: =item $keylist, array pointer returned from loncoursedata::get_classlist() 
                   1704: which describes the order elements are stored in the %$classlist values.
                   1705: 
                   1706: =item $nosort, if true, sorting links are omitted.
                   1707: 
                   1708: =back
                   1709: 
                   1710: =cut
                   1711: 
                   1712: #################################################
                   1713: #################################################
1.11      www      1714: sub show_drop_list {
1.56      matthew  1715:     my ($r,$classlist,$keylist,$nosort)=@_;
1.11      www      1716:     my $cid=$ENV{'request.course.id'};
1.59      matthew  1717:     if (! exists($ENV{'form.sortby'})) {
                   1718:         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   1719:                                                 ['sortby']);
                   1720:     }
1.54      matthew  1721:     my $sortby = $ENV{'form.sortby'};
1.110     matthew  1722:     if ($sortby !~ /^(username|domain|section|fullname|id|start|end)$/) {
1.54      matthew  1723:         $sortby = 'username';
                   1724:     }
1.56      matthew  1725:     #
1.54      matthew  1726:     my $action = "drop";
                   1727:     $r->print(<<END);
                   1728: <input type="hidden" name="sortby" value="$sortby" />
                   1729: <input type="hidden" name="action" value="$action" />
1.50      matthew  1730: <input type="hidden" name="state"  value="done" />
1.32      matthew  1731: <script>
1.51      matthew  1732: function checkAll(field) {
1.32      matthew  1733:     for (i = 0; i < field.length; i++)
                   1734:         field[i].checked = true ;
                   1735: }
                   1736: 
1.51      matthew  1737: function uncheckAll(field) {
1.32      matthew  1738:     for (i = 0; i < field.length; i++)
                   1739:         field[i].checked = false ;
                   1740: }
                   1741: </script>
                   1742: <p>
1.26      matthew  1743: <input type="hidden" name="phase" value="four">
1.56      matthew  1744: END
                   1745: 
1.110     matthew  1746: my %lt=&Apache::lonlocal::texthash('usrn'   => "username",
                   1747:                                    'dom'    => "domain",
                   1748:                                    'sn'     => "student name",
                   1749:                                    'sec'    => "section",
                   1750:                                    'start'  => "start date",
                   1751:                                    'end'    => "end date",
                   1752:                                    );
1.56      matthew  1753:     if ($nosort) {
                   1754:         $r->print(<<END);
                   1755: <table border=2>
                   1756: <tr>
                   1757:     <th>&nbsp;</th>
1.94      sakharuk 1758:     <th>$lt{'usrn'}</th>
                   1759:     <th>$lt{'dom'}</th>
1.56      matthew  1760:     <th>ID</th>
1.94      sakharuk 1761:     <th>$lt{'sn'}</th>
                   1762:     <th>$lt{'sec'}</th>
1.110     matthew  1763:     <th>$lt{'start'}</th>
                   1764:     <th>$lt{'end'}</th>
1.56      matthew  1765: </tr>
                   1766: END
                   1767: 
                   1768:     } else  {
                   1769:         $r->print(<<END);
1.26      matthew  1770: <table border=2>
1.54      matthew  1771: <tr><th>&nbsp;</th>
                   1772:     <th>
1.94      sakharuk 1773:        <a href="/adm/dropadd?action=$action&sortby=username">$lt{'usrn'}</a>
1.54      matthew  1774:     </th><th>
1.94      sakharuk 1775:        <a href="/adm/dropadd?action=$action&sortby=domain">$lt{'dom'}</a>
1.54      matthew  1776:     </th><th>
                   1777:        <a href="/adm/dropadd?action=$action&sortby=id">ID</a>
                   1778:     </th><th>
1.94      sakharuk 1779:        <a href="/adm/dropadd?action=$action&sortby=fullname">$lt{'sn'}</a>
1.54      matthew  1780:     </th><th>
1.94      sakharuk 1781:        <a href="/adm/dropadd?action=$action&sortby=section">$lt{'sec'}</a>
1.110     matthew  1782:     </th><th>
                   1783:        <a href="/adm/dropadd?action=$action&sortby=start">$lt{'start'}</a>
                   1784:     </th><th>
                   1785:        <a href="/adm/dropadd?action=$action&sortby=end">$lt{'end'}</a>
1.54      matthew  1786:     </th>
                   1787: </tr>
1.26      matthew  1788: END
1.56      matthew  1789:     }
                   1790:     #
                   1791:     # Sort the students
                   1792:     my %index;
                   1793:     my $i;
                   1794:     foreach (@$keylist) {
                   1795:         $index{$_} = $i++;
                   1796:     }
                   1797:     my $index  = $index{$sortby};
                   1798:     my $second = $index{'username'};
                   1799:     my $third  = $index{'domain'};
1.54      matthew  1800:     my @Sorted_Students = sort {
1.56      matthew  1801:         lc($classlist->{$a}->[$index])  cmp lc($classlist->{$b}->[$index])
                   1802:             ||
                   1803:         lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second])
                   1804:             ||
                   1805:         lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third])
                   1806:         } (keys(%$classlist));
1.54      matthew  1807:     foreach my $student (@Sorted_Students) {
1.52      matthew  1808:         my $error;
1.110     matthew  1809:         my $sdata = $classlist->{$student};
                   1810:         my $username = $sdata->[$index{'username'}];
                   1811:         my $domain   = $sdata->[$index{'domain'}];
                   1812:         my $section  = $sdata->[$index{'section'}];
                   1813:         my $name     = $sdata->[$index{'fullname'}];
                   1814:         my $id       = $sdata->[$index{'id'}];
                   1815:         my $start    = $sdata->[$index{'start'}];
                   1816:         my $end      = $sdata->[$index{'end'}];
                   1817:         if (! defined($start) || $start == 0) {
                   1818:             $start = &mt('none');
                   1819:         } else {
                   1820:             $start = &Apache::lonlocal::locallocaltime($start);
                   1821:         }
                   1822:         if (! defined($end) || $end == 0) {
                   1823:             $end = &mt('none');
                   1824:         } else {
                   1825:             $end = &Apache::lonlocal::locallocaltime($end);
                   1826:         }
                   1827:         my $status   = $sdata->[$index{'status'}];
1.51      matthew  1828:         next if ($status ne 'Active');
                   1829:         #
                   1830:         $r->print(<<"END");
1.26      matthew  1831: <tr>
1.51      matthew  1832:     <td><input type="checkbox" name="droplist" value="$student"></td>
                   1833:     <td>$username</td>
                   1834:     <td>$domain</td>
                   1835:     <td>$id</td>
                   1836:     <td>$name</td>
                   1837:     <td>$section</td>
1.110     matthew  1838:     <td>$start</td>
                   1839:     <td>$end</td>
1.26      matthew  1840: </tr>
                   1841: END
1.25      matthew  1842:     }
                   1843:     $r->print('</table><br>');
1.111   ! matthew  1844:     %lt=&Apache::lonlocal::texthash(
1.94      sakharuk 1845: 	               'dp'   => "Drop Students",
                   1846:                        'ca'   => "check all",
                   1847:                        'ua'   => "uncheck all",
                   1848: 				       );
1.32      matthew  1849:     $r->print(<<"END");
                   1850: </p><p>
1.94      sakharuk 1851: <input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)"> &nbsp;
                   1852: <input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)"> 
                   1853: <p><input type=submit value="$lt{'dp'}"></p>
1.32      matthew  1854: END
1.51      matthew  1855:     return;
1.10      www      1856: }
                   1857: 
1.48      matthew  1858: #
                   1859: # Print out the initial form to get the courselist file
                   1860: #
                   1861: sub print_first_courselist_upload_form {
                   1862:     my $r=shift;
1.88      matthew  1863:     my $str;
                   1864:     $str  = '<input type="hidden" name="phase" value="two">';
                   1865:     $str .= '<input type="hidden" name="action" value="upload" />';
                   1866:     $str .= '<input type="hidden"   name="state"  value="got_file" />';
                   1867:     $str .= "<h3>".&mt('Upload a class list')."</h3>\n";
                   1868:     $str .= &Apache::loncommon::upfile_select_html();
                   1869:     $str .= "<p>\n";
                   1870:     $str .= '<input type="submit" name="fileupload" value="'.
                   1871:         &mt('Upload class list').'">'."\n";
                   1872:     $str .= '<input type="checkbox" name="noFirstLine" /> '.
                   1873:         &mt('Ignore First Line')."</p>\n";
                   1874:     $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List",
1.92      sakharuk 1875:                          &mt("How do I create a class list from a spreadsheet")).
1.88      matthew  1876:                              "<br />\n";
                   1877:     $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
1.92      sakharuk 1878:                            &mt("How do I create a CSV file from a spreadsheet")).
1.88      matthew  1879:                                "<br />\n";
                   1880:     $str .= "</body>\n</html>\n";
                   1881:     $r->print($str);
1.48      matthew  1882:     return;
                   1883: }
                   1884: 
1.10      www      1885: # ================================================= Drop/Add from uploaded file
                   1886: sub upfile_drop_add {
                   1887:     my $r=shift;
1.24      albertel 1888:     &Apache::loncommon::load_tmp_file($r);
                   1889:     my @studentdata=&Apache::loncommon::upfile_record_sep();
1.82      www      1890:     if($ENV{'form.noFirstLine'}){shift(@studentdata);}
1.26      matthew  1891:     my @keyfields = split(/\,/,$ENV{'form.keyfields'});
                   1892:     my $cid = $ENV{'request.course.id'};
1.25      matthew  1893:     my %fields=();
1.26      matthew  1894:     for (my $i=0; $i<=$ENV{'form.nfields'}; $i++) {
1.25      matthew  1895:         if ($ENV{'form.upfile_associate'} eq 'reverse') {
                   1896:             if ($ENV{'form.f'.$i} ne 'none') {
                   1897:                 $fields{$keyfields[$i]}=$ENV{'form.f'.$i};
                   1898:             }
                   1899:         } else {
                   1900:             $fields{$ENV{'form.f'.$i}}=$keyfields[$i];
                   1901:         }
                   1902:     }
1.99      matthew  1903:     #
                   1904:     # Store the field choices away
                   1905:     foreach my $field (qw/username names 
                   1906:                        fname mname lname gen id sec ipwd email/) {
                   1907:         $ENV{'form.'.$field.'_choice'}=$fields{$field};
                   1908:     }
                   1909:     &Apache::loncommon::store_course_settings('enrollment_upload',
                   1910:                                               { 'username_choice' => 'scalar',
                   1911:                                                 'names_choice' => 'scalar',
                   1912:                                                 'fname_choice' => 'scalar',
                   1913:                                                 'mname_choice' => 'scalar',
                   1914:                                                 'lname_choice' => 'scalar',
                   1915:                                                 'gen_choice' => 'scalar',
                   1916:                                                 'id_choice' => 'scalar',
                   1917:                                                 'sec_choice' => 'scalar',
                   1918:                                                 'ipwd_choice' => 'scalar',
                   1919:                                                 'email_choice' => 'scalar' });
                   1920: 
1.26      matthew  1921:     #
1.68      matthew  1922:     my ($startdate,$enddate) = &get_dates_from_form();
                   1923:     if ($ENV{'form.makedatesdefault'}) {
                   1924:         $r->print(&make_dates_default($startdate,$enddate));
                   1925:     }
1.31      matthew  1926:     # Determine domain and desired host (home server)
1.25      matthew  1927:     my $domain=$ENV{'form.lcdomain'};
1.31      matthew  1928:     my $desiredhost = $ENV{'form.lcserver'};
                   1929:     if (lc($desiredhost) eq 'default') {
                   1930:         $desiredhost = undef;
                   1931:     } else {
1.45      matthew  1932:         my %home_servers = &Apache::loncommon::get_library_servers($domain);
1.31      matthew  1933:         if (! exists($home_servers{$desiredhost})) {
1.88      matthew  1934:             $r->print('<font color="#ff0000">'.&mt('Error').'</font>'.
                   1935:                       &mt('Invalid home server specified'));
                   1936:             $r->print("</body>\n</html>\n");
1.31      matthew  1937:             return;
                   1938:         }
                   1939:     }
1.26      matthew  1940:     # Determine authentication mechanism
                   1941:     my $amode  = '';
                   1942:     my $genpwd = '';
1.25      matthew  1943:     if ($ENV{'form.login'} eq 'krb') {
1.47      albertel 1944:         $amode='krb';
                   1945: 	$amode.=$ENV{'form.krbver'};
1.28      matthew  1946:         $genpwd=$ENV{'form.krbarg'};
1.25      matthew  1947:     } elsif ($ENV{'form.login'} eq 'int') {
                   1948:         $amode='internal';
1.28      matthew  1949:         if ((defined($ENV{'form.intarg'})) && ($ENV{'form.intarg'})) {
                   1950:             $genpwd=$ENV{'form.intarg'};
1.25      matthew  1951:         }
                   1952:     } elsif ($ENV{'form.login'} eq 'loc') {
                   1953:         $amode='localauth';
                   1954:         if ((defined($ENV{'form.locarg'})) && ($ENV{'form.locarg'})) {
                   1955:             $genpwd=$ENV{'form.locarg'};
1.79      matthew  1956:         }
                   1957:     }
                   1958:     if ($amode =~ /^krb/) {
                   1959:         if (! defined($genpwd) || $genpwd eq '') {
                   1960:             $r->print('<font color="red" size="+1">'.
1.88      matthew  1961:                       &mt('Unable to enroll students').'</font>  '.
                   1962:                       &mt('No Kerberos domain was specified.').'</p>');
1.79      matthew  1963:             $amode = ''; # This causes the loop below to be skipped
1.25      matthew  1964:         }
                   1965:     }
                   1966:     unless (($domain=~/\W/) || ($amode eq '')) {
1.26      matthew  1967:         #######################################
                   1968:         ##         Enroll Students           ##
                   1969:         #######################################
1.88      matthew  1970:         $r->print('<h3>'.&mt('Enrolling Students')."</h3>\n<p>\n");
1.25      matthew  1971:         my $count=0;
                   1972:         my $flushc=0;
                   1973:         my %student=();
1.26      matthew  1974:         # Get new classlist
1.25      matthew  1975:         foreach (@studentdata) {
                   1976:             my %entries=&Apache::loncommon::record_sep($_);
1.26      matthew  1977:             # Determine student name
1.25      matthew  1978:             unless (($entries{$fields{'username'}} eq '') ||
                   1979:                     (!defined($entries{$fields{'username'}}))) {
1.26      matthew  1980:                 my ($fname, $mname, $lname,$gen) = ('','','','');
1.25      matthew  1981:                 if (defined($fields{'names'})) {
1.26      matthew  1982:                     ($lname,$fname,$mname)=($entries{$fields{'names'}}=~
                   1983:                                             /([^\,]+)\,\s*(\w+)\s*(.*)$/);
1.25      matthew  1984:                 } else {
                   1985:                     if (defined($fields{'fname'})) {
                   1986:                         $fname=$entries{$fields{'fname'}};
                   1987:                     }
                   1988:                     if (defined($fields{'mname'})) {
                   1989:                         $mname=$entries{$fields{'mname'}};
                   1990:                     }
                   1991:                     if (defined($fields{'lname'})) {
                   1992:                         $lname=$entries{$fields{'lname'}};
                   1993:                     }
                   1994:                     if (defined($fields{'gen'})) {
                   1995:                         $gen=$entries{$fields{'gen'}};
                   1996:                     }
                   1997:                 }
                   1998:                 if ($entries{$fields{'username'}}=~/\W/) {
1.88      matthew  1999:                     $r->print('<br />'.
                   2000:       &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]',
                   2001:           $entries{$fields{'username'}},$fname,$mname,$lname,$gen).
                   2002:                               '</b>');
1.25      matthew  2003:                 } else {
1.26      matthew  2004:                     # determine section number
1.25      matthew  2005:                     my $sec='';
                   2006:                     my $username=$entries{$fields{'username'}};
                   2007:                     if (defined($fields{'sec'})) {
                   2008:                         if (defined($entries{$fields{'sec'}})) {
                   2009:                             $sec=$entries{$fields{'sec'}};
                   2010:                         }
                   2011:                     }
1.80      matthew  2012:                     # remove non alphanumeric values from section
                   2013:                     $sec =~ s/\W//g;
1.26      matthew  2014:                     # determine student id number
1.25      matthew  2015:                     my $id='';
                   2016:                     if (defined($fields{'id'})) {
                   2017:                         if (defined($entries{$fields{'id'}})) {
                   2018:                             $id=$entries{$fields{'id'}};
                   2019:                         }
                   2020:                         $id=~tr/A-Z/a-z/;
                   2021:                     }
1.73      www      2022:                     # determine email address
                   2023:                     my $email='';
                   2024:                     if (defined($fields{'email'})) {
                   2025:                         if (defined($entries{$fields{'email'}})) {
                   2026:                             $email=$entries{$fields{'email'}};
                   2027:                             unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; }
                   2028:                         }
                   2029:                     }
1.26      matthew  2030:                     # determine student password
1.25      matthew  2031:                     my $password='';
                   2032:                     if ($genpwd) { 
                   2033:                         $password=$genpwd; 
                   2034:                     } else {
                   2035:                         if (defined($fields{'ipwd'})) {
                   2036:                             if ($entries{$fields{'ipwd'}}) {
                   2037:                                 $password=$entries{$fields{'ipwd'}};
                   2038:                             }
                   2039:                         }
                   2040:                     }
1.56      matthew  2041:                     # Clean up whitespace
                   2042:                     foreach (\$domain,\$username,\$id,\$fname,\$mname,
                   2043:                              \$lname,\$gen,\$sec) {
                   2044:                         $$_ =~ s/(\s+$|^\s+)//g;
                   2045:                     }
1.84      albertel 2046:                     if ($password || $ENV{'form.login'} eq 'loc') {
1.33      matthew  2047:                         &modifystudent($domain,$username,$cid,$sec,
                   2048:                                        $desiredhost);
1.25      matthew  2049:                         my $reply=&Apache::lonnet::modifystudent
                   2050:                             ($domain,$username,$id,$amode,$password,
                   2051:                              $fname,$mname,$lname,$gen,$sec,$enddate,
1.73      www      2052:                              $startdate,$ENV{'form.forceid'},$desiredhost,
                   2053:                              $email);
1.26      matthew  2054:                         if ($reply ne 'ok') {
1.72      matthew  2055:                             $reply =~ s/^error://;
1.88      matthew  2056:                             $r->print('<br />'.
                   2057:                 &mt('<b>[_1]</b>:  Unable to enroll: [_2]',$username,$reply));
1.10      www      2058:          		} else {
1.7       www      2059:                             $count++; $flushc++;
                   2060:                             $student{$username}=1;
1.6       www      2061:                             $r->print('. ');
1.7       www      2062:                             if ($flushc>15) {
                   2063: 				$r->rflush;
                   2064:                                 $flushc=0;
                   2065:                             }
1.6       www      2066:                         }
1.25      matthew  2067:                     } else {
1.88      matthew  2068:                         $r->print('<br />'.
                   2069:       &mt('<b>[_1]</b>: Unable to enroll.  No password specified.',$username)
                   2070:                                   );
1.25      matthew  2071:                     }
                   2072:                 }
1.26      matthew  2073:             }
                   2074:         } # end of foreach (@studentdata)
1.88      matthew  2075:         $r->print("</p>\n<p>\n".&mt('Processed [_1] student(s).',$count).
                   2076:                   "</p>\n");
                   2077:         $r->print("<p>\n".
                   2078:                   &mt('If active, the new role will be available when the '.
                   2079:                   'students next log in to LON-CAPA.')."</p>\n");
1.26      matthew  2080:         #####################################
                   2081:         #           Drop students           #
                   2082:         #####################################
1.25      matthew  2083:         if ($ENV{'form.fullup'} eq 'yes') {
1.88      matthew  2084:             $r->print('<h3>'.&mt('Dropping Students')."</h3>\n");
1.26      matthew  2085:             #  Get current classlist
1.56      matthew  2086:             my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist();
                   2087:             if (! defined($classlist)) {
1.88      matthew  2088:                 $r->print(&mt('There are no students currently enrolled.').
                   2089:                           "\n");
1.56      matthew  2090:             } else {
                   2091:                 # Remove the students we just added from the list of students.
1.25      matthew  2092:                 foreach (@studentdata) {
                   2093:                     my %entries=&Apache::loncommon::record_sep($_);
                   2094:                     unless (($entries{$fields{'username'}} eq '') ||
                   2095:                             (!defined($entries{$fields{'username'}}))) {
1.56      matthew  2096:                         delete($classlist->{$entries{$fields{'username'}}.
1.26      matthew  2097:                                                 ':'.$domain});
1.25      matthew  2098:                     }
                   2099:                 }
1.56      matthew  2100:                 # Print out list of dropped students.
                   2101:                 &show_drop_list($r,$classlist,$keylist,'nosort');
1.25      matthew  2102:             }
                   2103:         }
1.26      matthew  2104:     } # end of unless
1.10      www      2105: }
                   2106: 
1.11      www      2107: # ================================================================== Phase four
                   2108: sub drop_student_list {
                   2109:     my $r=shift;
                   2110:     my $count=0;
1.35      matthew  2111:     my @droplist;
                   2112:     if (ref($ENV{'form.droplist'})) {
                   2113:         @droplist = @{$ENV{'form.droplist'}};
                   2114:     } else {
                   2115:         @droplist = ($ENV{'form.droplist'});
                   2116:     }
                   2117:     foreach (@droplist) {
1.26      matthew  2118:         my ($uname,$udom)=split(/\:/,$_);
1.56      matthew  2119:         # drop student
1.35      matthew  2120:         my $result = &modifystudent($udom,$uname,$ENV{'request.course.id'});
1.37      matthew  2121:         if ($result eq 'ok' || $result eq 'ok:') {
1.88      matthew  2122:             $r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'<br>');
1.59      matthew  2123:             $count++;
1.35      matthew  2124:         } else {
1.88      matthew  2125:             $r->print(
                   2126:           &mt('Error dropping [_1]:[_2]',$uname.'@'.$udom,$result).
1.35      matthew  2127:                       '<br />');
                   2128:         }
1.20      harris41 2129:     }
1.88      matthew  2130:     $r->print('<p><b>'.&mt('Dropped [_1] student(s).',$count).'</b></p>');
                   2131:     $r->print('<p>'.&mt('Re-enrollment will re-activate data.')) if ($count);
1.11      www      2132: }
                   2133: 
1.50      matthew  2134: ###################################################################
                   2135: ###################################################################
                   2136: 
                   2137: =pod
                   2138: 
                   2139: =item &handler
                   2140: 
                   2141: The typical handler you see in all these modules.  Takes $r, the
                   2142: http request, as an argument.  
                   2143: 
                   2144: The response to the request is governed by two form variables
                   2145: 
                   2146:  form.action      form.state     response
                   2147:  ---------------------------------------------------
                   2148:  undefined        undefined      print main menu
                   2149:  upload           undefined      print courselist upload menu
                   2150:  upload           got_file       deal with uploaded file,
                   2151:                                  print the upload managing menu
                   2152:  upload           enrolling      enroll students based on upload
                   2153:  drop             undefined      print the classlist ready to drop
                   2154:  drop             done           drop the selected students
1.74      matthew  2155:  enrollstudent    undefined      print student username domain form
                   2156:  enrollstudent    gotusername    print single student enroll menu
1.50      matthew  2157:  enrollstudent    enrolling      enroll student
                   2158:  classlist        undefined      print html classlist
                   2159:  classlist        csv            print csv classlist
                   2160:  modifystudent    undefined      print classlist to select student to modify
                   2161:  modifystudent    selected       print modify student menu
                   2162:  modifystudent    done           make modifications to student record
                   2163: 
                   2164: =cut
                   2165: 
                   2166: ###################################################################
                   2167: ###################################################################
1.10      www      2168: sub handler {
1.26      matthew  2169:     my $r=shift;
                   2170:     if ($r->header_only) {
1.86      www      2171:         &Apache::loncommon::content_type($r,'text/html');
1.26      matthew  2172:         $r->send_http_header;
                   2173:         return OK;
                   2174:     }
1.48      matthew  2175:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.50      matthew  2176:                                             ['action','state']);
1.102     matthew  2177: 
                   2178:     &Apache::lonhtmlcommon::clear_breadcrumbs();
                   2179:     &Apache::lonhtmlcommon::add_breadcrumb
                   2180:         ({href=>"/adm/dropadd",
                   2181:           text=>"Enrollment Manager",
                   2182:           faq=>9,bug=>'Instructor Interface',});
1.26      matthew  2183:     #  Needs to be in a course
1.50      matthew  2184:     if (! (($ENV{'request.course.fn'}) &&
                   2185:           (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'})))) {
                   2186:         # Not in a course, or not allowed to modify parms
                   2187:         $ENV{'user.error.msg'}=
                   2188:             "/adm/dropadd:cst:0:0:Cannot drop or add students";
                   2189:         return HTTP_NOT_ACCEPTABLE; 
                   2190:     }
                   2191:     #
                   2192:     # Only output the header information if they did not request csv format
                   2193:     #
1.102     matthew  2194:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                   2195:                                             ['state','action']);
1.103     matthew  2196:     # Start page
                   2197:     &Apache::loncommon::content_type($r,'text/html');
                   2198:     $r->send_http_header;
                   2199:     $r->print(&header());
1.50      matthew  2200:     #
                   2201:     # Main switch on form.action and form.state, as appropriate
                   2202:     if (! exists($ENV{'form.action'})) {
1.102     matthew  2203:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2204:                   (undef,'Enrollment Manager'));
1.50      matthew  2205:         &print_main_menu($r);
                   2206:     } elsif ($ENV{'form.action'} eq 'upload') {
1.102     matthew  2207:         &Apache::lonhtmlcommon::add_breadcrumb
                   2208:             ({href=>'/adm/dropadd?action=upload&state=',
1.106     matthew  2209:               text=>"Upload Classlist"});
1.102     matthew  2210:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2211:                   (undef,'Upload Classlist'));
1.50      matthew  2212:         if (! exists($ENV{'form.state'})) {
                   2213:             &print_first_courselist_upload_form($r);            
                   2214:         } elsif ($ENV{'form.state'} eq 'got_file') {
                   2215:             &print_upload_manager_form($r);
                   2216:         } elsif ($ENV{'form.state'} eq 'enrolling') {
1.26      matthew  2217:             if ($ENV{'form.datatoken'}) {
                   2218:                 &upfile_drop_add($r);
1.50      matthew  2219:             } else {
                   2220:                 # Hmmm, this is an error
1.26      matthew  2221:             }
1.50      matthew  2222:         } else {
                   2223:             &print_first_courselist_upload_form($r);            
1.26      matthew  2224:         }
1.50      matthew  2225:     } elsif ($ENV{'form.action'} eq 'drop') {
1.102     matthew  2226:         &Apache::lonhtmlcommon::add_breadcrumb
                   2227:             ({href=>'/adm/dropadd?action=drop',
1.106     matthew  2228:               text=>"Drop Students"});
1.102     matthew  2229:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2230:                   (undef,'Drop Students'));
1.50      matthew  2231:         if (! exists($ENV{'form.state'})) {
1.51      matthew  2232:             &print_drop_menu($r);
1.50      matthew  2233:         } elsif ($ENV{'form.state'} eq 'done') {
1.26      matthew  2234:             &drop_student_list($r);
1.50      matthew  2235:         } else {
1.55      matthew  2236:             &print_drop_menu($r);
1.26      matthew  2237:         }
1.50      matthew  2238:     } elsif ($ENV{'form.action'} eq 'enrollstudent') {
1.102     matthew  2239:         &Apache::lonhtmlcommon::add_breadcrumb
                   2240:             ({href=>'/adm/dropadd?action=enrollstudent',
1.106     matthew  2241:               text=>"Enroll Student"});
1.102     matthew  2242:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2243:                   (undef,'Enroll Student'));
1.50      matthew  2244:         if (! exists($ENV{'form.state'})) {
1.74      matthew  2245:             &get_student_username_domain_form($r);
                   2246:         } elsif ($ENV{'form.state'} eq 'gotusername') {
1.50      matthew  2247:             &print_enroll_single_student_form($r);
                   2248:         } elsif ($ENV{'form.state'} eq 'enrolling') {
1.26      matthew  2249:             &enroll_single_student($r);
1.50      matthew  2250:         } else {
1.74      matthew  2251:             &get_student_username_domain_form($r);
1.26      matthew  2252:         }
1.50      matthew  2253:     } elsif ($ENV{'form.action'} eq 'classlist') {
1.102     matthew  2254:         &Apache::lonhtmlcommon::add_breadcrumb
                   2255:             ({href=>'/adm/dropadd?action=classlist',
1.106     matthew  2256:               text=>"View Classlist"});
1.102     matthew  2257:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2258:                   (undef,'View Classlist'));
1.50      matthew  2259:         if (! exists($ENV{'form.state'})) {
1.103     matthew  2260:             &print_html_classlist($r,undef);
1.50      matthew  2261:         } elsif ($ENV{'form.state'} eq 'csv') {
1.103     matthew  2262:             &print_html_classlist($r,'csv');
1.60      matthew  2263:         } elsif ($ENV{'form.state'} eq 'excel') {
1.103     matthew  2264:             &print_html_classlist($r,'excel');
1.50      matthew  2265:         } else {
1.103     matthew  2266:             &print_html_classlist($r,undef);
1.50      matthew  2267:         }
                   2268:     } elsif ($ENV{'form.action'} eq 'modifystudent') {
1.102     matthew  2269:         &Apache::lonhtmlcommon::add_breadcrumb
                   2270:             ({href=>'/adm/dropadd?action=modifystudent',
1.106     matthew  2271:               text=>"Modify Student Data"});
1.102     matthew  2272:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2273:                   (undef,'Modify Student Data'));
1.50      matthew  2274:         if (! exists($ENV{'form.state'})) {
                   2275:             &print_html_classlist($r);
                   2276:         } elsif ($ENV{'form.state'} eq 'selected') {
                   2277:             &print_modify_student_form($r);
                   2278:         } elsif ($ENV{'form.state'} eq 'done') {
                   2279:             &modify_single_student($r);
                   2280:         } else {
                   2281:             &print_html_classlist($r);
                   2282:         }        
                   2283:     } else {
                   2284:         # We should not end up here, but I guess it is possible
                   2285:         &Apache::lonnet::logthis("Undetermined state in londropadd.pm.  ".
                   2286:                                  "form.action = ".$ENV{'form.action'}.
                   2287:                                  "Someone should fix this.");
1.102     matthew  2288:         $r->print(&Apache::lonhtmlcommon::breadcrumbs
                   2289:                   (undef,'Enrollment Manager'));
1.50      matthew  2290:         &print_main_menu($r);
                   2291:     }
                   2292:     #
                   2293:     # Finish up
1.103     matthew  2294:     $r->print('</form></body></html>');
1.26      matthew  2295:     return OK;
1.1       www      2296: }
                   2297: 
1.50      matthew  2298: ###################################################################
                   2299: ###################################################################
                   2300: 
1.1       www      2301: 1;
                   2302: __END__
1.50      matthew  2303: 
1.1       www      2304: 

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