--- loncom/interface/Attic/londropadd.pm 2002/04/25 19:21:34 1.30 +++ loncom/interface/Attic/londropadd.pm 2002/05/09 15:56:02 1.42 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to drop and add students in courses # -# $Id: londropadd.pm,v 1.30 2002/04/25 19:21:34 matthew Exp $ +# $Id: londropadd.pm,v 1.42 2002/05/09 15:56:02 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,20 +62,20 @@ sub header { return(<<ENDHEAD); <html> <head> -<title>LON-CAPA Student Drop/Add</title> +<title>LON-CAPA Enrollment Manager</title> </head> <body bgcolor="#FFFFFF"> <img align=right src=/adm/lonIcons/lonlogos.gif> -<h1>Drop/Add Students</h1> -<form method="post" enctype="multipart/form-data" -action="/adm/dropadd" name="studentform"> -<h2>Course: $ENV{'course.'.$ENV{'request.course.id'}.'.description'}</h2> +<h1>$ENV{'course.'.$ENV{'request.course.id'}.'.description'}</h1> +<h2>Enrollment Manager</h2> +<form method="post" enctype="multipart/form-data" + action="/adm/dropadd" name="studentform"> ENDHEAD } # =========== Drop student from all sections of a course, except optional $csec sub modifystudent { - my ($udom,$unam,$courseid,$csec)=@_; + my ($udom,$unam,$courseid,$csec,$desiredhost)=@_; # if $csec is undefined, drop the student from all the courses matching # this one. If $csec is defined, drop them from all other sections of # this course and add them to section $csec @@ -84,24 +84,61 @@ sub modifystudent { my %roles = &Apache::lonnet::dump('roles',$udom,$unam); my ($tmp) = keys(%roles); # Bail out if we were unable to get the students roles - return if ($tmp =~ /^(con_lost|error|no_such_host)/i); + return "$1" if ($tmp =~ /^(con_lost|error|no_such_host)/i); # Go through the roles looking for enrollment in this course + my $result = ''; foreach my $course (keys(%roles)) { - my $value = $roles{$course}; - if ($course=~/^$courseid(?:\/)*(\w+)*\_st$/) { + if ($course=~/^$courseid(?:\/)*(?:\s+)*(\w+)*\_st$/) { # We are in this course my $section=$1; $section='' if ($course eq $courseid.'_st'); - if (((!$section) && (!$csec)) || ($section ne $csec)) { + if ( ((!$section) && (!$csec)) || ($section ne $csec) ) { my (undef,$end,$start)=split(/\_/,$roles{$course}); my $now=time; if (!($start && ($now<$start)) || !($end && ($now>$end))) { my $reply=&Apache::lonnet::modifystudent - ($udom,$unam,'','','','','','','',$section,time); + ($udom,$unam,'','','','','','','', + $section,time,undef,undef,$desiredhost); + $result .= $reply.':'; } } } } + if ($result eq '') { + $result eq 'Unable to find section for this student'; + } else { + $result =~ s/(ok:)+/ok/g; + } + return $result; +} + +# ============ build a domain and server selection form +sub domain_form { + my ($defdom) = @_; + # Set up domain and server selection forms + # + # Get the domains + my @domains = &Apache::loncommon::get_domains(); + # build up the menu information to be passed to + # &Apache::loncommon::linked_select_forms + my %select_menus; + foreach my $dom (@domains) { + # set up the text for this domain + $select_menus{$dom}->{'text'}= $dom; + # we want a choice of 'default' as the default in the second menu + $select_menus{$dom}->{'default'}= 'default'; + $select_menus{$dom}->{'select2'}->{'default'} = 'default'; + # Now build up the other items in the second menu + my %servers = &Apache::loncommon::get_home_servers($dom); + foreach my $server (keys(%servers)) { + $select_menus{$dom}->{'select2'}->{$server} + = "$server $servers{$server}"; + } + } + my $result = &Apache::loncommon::linked_select_forms + ('studentform',' with home server ',$defdom, + 'lcdomain','lcserver',\%select_menus); + return $result; } # ============================================================== Menu Phase One @@ -113,13 +150,17 @@ sub menu_phase_one { <hr> <h3>Upload a courselist</h3> $upfile_select -<p><input type=submit name=fileupload value="Upload Courselist"> -<hr> +<p><input type=submit name="fileupload" value="Upload Courselist"> +<hr /> <h3>Enroll a single student</h3> -<p><input type=submit name=enroll value="Enroll Student"> -<hr> +<p><input type=submit name="enroll" value="Enroll Student"></p> +<hr /> +<h3>Classlist</h3> +<p><input type=submit name="view" value="View Class List"> +<input type=submit name="viewcsv" value="Comma Separated Class List"></p> +<hr /> <h3>Drop students</h3> -<p><input type=submit name=drop value="Selection List"> +<p><input type=submit name="drop" value="Selection List"></p> ENDUPFORM } @@ -133,12 +174,14 @@ sub phase_two_header { } my $javascript_validations=&javascript_validations($krbdefdom); $r->print(<<ENDPICK); +<h3>Uploading Class List</h3> <hr> <h3>Identify fields</h3> Total number of records found in file: $distotal <hr /> 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 run your class.<hr /> -<input type="submit" name="associate" value="Reverse Association" /> +<input type="button" value="Reverse Association" onClick="javascript:this.form.associate.value='Reverse Association';submit(this.form);" /> +<input type="hidden" name="associate" value="" /> <input type="hidden" name="phase" value="three" /> <input type="hidden" name="datatoken" value="$datatoken" /> <input type="hidden" name="fileupload" value="$ENV{'form.fileupload'}" /> @@ -382,8 +425,7 @@ sub phase_two_end { my $krbform = &Apache::loncommon::authform_kerberos(%param); my $intform = &Apache::loncommon::authform_internal(%param); my $locform = &Apache::loncommon::authform_local(%param); - # Set up domain selection form - my $domform = &Apache::loncommon::select_dom_form($defdom,'lcdomain'); + my $domform = &domain_form($defdom); $r->print(<<ENDPICK); </table> <input type=hidden name=nfields value=$i> @@ -421,7 +463,7 @@ LON-CAPA domain: $domform <p> <input type=checkbox name=forceid value=yes> Disable ID/Student Number Safeguard and Force Change of Conflicting IDs (only do if you know what you are doing)<p> -<input type="button" onClick="verify(this.form)" value="Update Courselist"><br> +<input type="button" onClick="javascript:verify(this.form)" value="Update Courselist" /><br /> Note: for large courses, this operation might be time consuming. ENDPICK } @@ -474,9 +516,25 @@ sub menu_phase_two_upload { sub enroll_single_student { my $r=shift; $r->print('<h3>Enrolling Student</h3>'); - $r->print($ENV{'form.cuname'}." in domain ".$ENV{'form.cdomain'}.": "); + $r->print('<p>Enrolling '.$ENV{'form.cuname'}." in domain ". + $ENV{'form.lcdomain'}.'</p>'); if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\W/)&& - ($ENV{'form.cdomain'})&&($ENV{'form.cdomain'}!~/\W/)) { + ($ENV{'form.lcdomain'})&&($ENV{'form.lcdomain'}!~/\W/)) { + # Deal with home server selection + my $domain=$ENV{'form.lcdomain'}; + my $desiredhost = $ENV{'form.lcserver'}; + if (lc($desiredhost) eq 'default') { + $desiredhost = undef; + } else { + my %home_servers = &Apache::loncommon::get_home_servers($domain); + if (! exists($home_servers{$desiredhost})) { + $r->print('<font color="#ff0000">Error:</font>'. + 'Invalid home server specified'); + return; + } + } + $r->print(" with server $desiredhost :") if (defined($desiredhost)); + # End of home server selection logic my $amode=''; my $genpwd=''; if ($ENV{'form.login'} eq 'krb') { @@ -490,18 +548,24 @@ sub enroll_single_student { $genpwd=$ENV{'form.locarg'}; if (!$genpwd) { $genpwd=" "; } } - if (($amode) && ($genpwd)) { - &modifystudent($ENV{'form.cdomain'},$ENV{'form.cuname'}, - $ENV{'request.course.id'},$ENV{'form.csec'}); + my $home = &Apache::lonnet::homeserver($ENV{'form.cuname'}, + $ENV{'form.lcdomain'}); + if ((($amode) && ($genpwd)) || ($home ne 'no_host')) { + &modifystudent($ENV{'form.lcdomain'},$ENV{'form.cuname'}, + $ENV{'request.course.id'},$ENV{'form.csec'}, + $desiredhost); $r->print(&Apache::lonnet::modifystudent( - $ENV{'form.cdomain'},$ENV{'form.cuname'}, + $ENV{'form.lcdomain'},$ENV{'form.cuname'}, $ENV{'form.cstid'},$amode,$genpwd, $ENV{'form.cfirst'},$ENV{'form.cmiddle'}, $ENV{'form.clast'},$ENV{'form.cgen'}, $ENV{'form.csec'},$ENV{'form.enddate'}, - $ENV{'form.startdate'},$ENV{'form.forceid'})); + $ENV{'form.startdate'},$ENV{'form.forceid'}, + $desiredhost)); } else { - $r->print('Invalid login mode or password'); + $r->print('<p><font color="#ff0000">ERROR</font> '. + 'Invalid login mode or password. '. + 'Unable to enroll '.$ENV{'form.cuname'}.'.</p>'); } } else { $r->print('Invalid username or domain'); @@ -511,6 +575,7 @@ sub enroll_single_student { # ======================================================= Menu Phase Two Enroll sub menu_phase_two_enroll { my $r=shift; + $r->print("<h3>Enroll One Student</h3>"); my ($krbdefdom) = $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; $krbdefdom=~tr/a-z/A-Z/; my $today = time; @@ -523,7 +588,7 @@ sub menu_phase_two_enroll { my $intform = &Apache::loncommon::authform_internal(%param); my $locform = &Apache::loncommon::authform_local(%param); # Set up domain selection form - my $domform = &Apache::loncommon::select_dom_form($defdom,'cdomain'); + my $domform = &domain_form($defdom); # Print it all out $r->print(<<ENDSENROLL); <script type="text/javascript" language="Javascript"> @@ -535,7 +600,7 @@ function verify(vf) { var foundsec=0; var tw; if ((typeof(vf.cuname.value) !="undefined") && (vf.cuname.value!='') && - (typeof(vf.cdomain.value)!="undefined") && (vf.cdomain.value!='')) { + (typeof(vf.lcdomain.value)!="undefined") && (vf.lcdomain.value!='')) { founduname=1; } if ((typeof(vf.cfirst.value)!="undefined") && (vf.cfirst.value!='') && @@ -628,6 +693,7 @@ sub get_current_classlist { } return (undef,%currentlist); } else { + $tmp =~ s/^error://; return ($tmp,undef); } } @@ -635,13 +701,17 @@ sub get_current_classlist { # ========================================================= Menu Phase Two Drop sub menu_phase_two_drop { my $r=shift; + $r->print("<h3>Drop Students</h3>"); my $cid=$ENV{'request.course.id'}; - my ($error,%currentlist)=&get_current_classlist($ENV{'course.'.$cid.'.domain'}, - $ENV{'course.'.$cid.'.num'}); + my ($error,%currentlist)=&get_current_classlist + ($ENV{'course.'.$cid.'.domain'},$ENV{'course.'.$cid.'.num'}); if (defined($error)) { - $r->print('<pre>ERROR:$error</pre>'); - } - if (!defined(%currentlist)) { + if ($error =~ /^No such file or directory/) { + $r->print("There are no students currently enrolled.\n"); + } else { + $r->print("<pre>ERROR:$error</pre>"); + } + } elsif (!defined(%currentlist)) { $r->print("There are no students currently enrolled.\n"); } else { # Print out the available choices @@ -649,11 +719,126 @@ sub menu_phase_two_drop { } } +# ============================================== view classlist +sub menu_phase_two_view { + my $r=shift; + $r->print("<h3>Current Classlist</h3>"); + my $cid=$ENV{'request.course.id'}; + my ($error,%currentlist)=&get_current_classlist + ($ENV{'course.'.$cid.'.domain'},$ENV{'course.'.$cid.'.num'}); + if (defined($error)) { + if ($error =~ /^No such file or directory/) { + $r->print("There are no students currently enrolled.\n"); + } else { + $r->print("<pre>ERROR:$error</pre>"); + } + } elsif (!defined(%currentlist)) { + $r->print("There are no students currently enrolled.\n"); + } else { + # Print out the available choices + &show_class_list($r,'view',%currentlist); + } +} + +# ============================================== view classlist +sub menu_phase_two_viewcsv { + my $r=shift; + my $cid=$ENV{'request.course.id'}; + my ($error,%currentlist)=&get_current_classlist + ($ENV{'course.'.$cid.'.domain'},$ENV{'course.'.$cid.'.num'}); + if (defined($error)) { + if ($error =~ /^No such file or directory/) { + $r->print("There are no students currently enrolled.\n"); + } else { + $r->print("<pre>ERROR:$error</pre>"); + } + } elsif (!defined(%currentlist)) { + $r->print("There are no students currently enrolled.\n"); + } else { + &show_class_list($r,'csv',%currentlist); + } +} + +# =================================================== Show student list to drop +sub show_class_list { + my ($r,$mode,%currentlist)=@_; + my $cid=$ENV{'request.course.id'}; + # Print out header + if ($mode eq 'view') { + $r->print(<<END); +<p> +<table border=2> +<tr><th>username</th><th>domain</th><th>ID</th> + <th>student name</th><th>generation</th><th>section</th></tr> +END + } elsif ($mode eq 'csv') { + $r->print(<<END); +username,domain,ID,last name,first name,middle name,generation,section +END + } + foreach (sort keys %currentlist) { + my ($sname,$sdom)=split(/\:/,$_); + my %reply=&Apache::lonnet::idrget($sdom,$sname); + my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid); + my %info=&Apache::lonnet::get('environment', + ['firstname','middlename', + 'lastname','generation'], + $sdom, $sname); + my ($tmp) = keys(%info); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $r->print( ($mode eq 'view' ? + '<tr><td colspan="6"><font color="red">' :''). + 'Internal error: unable to get environment '. + 'for '.$sname.' in domain '.$sdom. + ( $mode eq 'view' ?'</font></td></tr>' :'')); + } else { + if ($mode eq 'view') { + $r->print(<<"END"); +<tr> + <td>$sname</td> + <td>$sdom</td> + <td>$reply{$sname}</td> + <td>$info{'lastname'}, $info{'firstname'} $info{'middlename'}</td> + <td>$info{'generation'}</td> + <td>$ssec</td> +</tr> +END + } elsif ($mode eq 'csv') { + my @line = (); + foreach ($sname,$sdom,$reply{$sname}, + $info{'lastname'},$info{'firstname'}, + $info{'middlename'},$info{'generation'},$ssec) { + push @line,&Apache::loncommon::csv_translate($_); + } + my $tmp = $"; + $" = '","'; + $r->print("\"@line\"\n"); + $" = $tmp; + } + } + } + $r->print('</table><br>') if ($mode eq 'view'); +} + # =================================================== Show student list to drop sub show_drop_list { my ($r,%currentlist)=@_; my $cid=$ENV{'request.course.id'}; $r->print(<<'END'); +<script> +function checkAll(field) +{ + for (i = 0; i < field.length; i++) + field[i].checked = true ; +} + +function uncheckAll(field) +{ + for (i = 0; i < field.length; i++) + field[i].checked = false ; +} +</script> +<p> <input type="hidden" name="phase" value="four"> <table border=2> <tr><th> </th><th>username</th><th>domain</th> @@ -688,7 +873,12 @@ END } } $r->print('</table><br>'); - $r->print('<input type=submit value="Drop Students">'); + $r->print(<<"END"); +</p><p> +<input type="button" value="check all" onclick="javascript:checkAll(document.studentform.droplist)"> +<input type="button" value="uncheck all" onclick="javascript:uncheckAll(document.studentform.droplist)"> +<p><input type=submit value="Drop Students"></p> +END } # ================================================= Drop/Add from uploaded file @@ -713,8 +903,19 @@ sub upfile_drop_add { my $enddate = $ENV{'form.enddate'}; if ($startdate=~/\D/) { $startdate=''; } if ($enddate=~/\D/) { $enddate=''; } - # + # Determine domain and desired host (home server) my $domain=$ENV{'form.lcdomain'}; + my $desiredhost = $ENV{'form.lcserver'}; + if (lc($desiredhost) eq 'default') { + $desiredhost = undef; + } else { + my %home_servers = &Apache::loncommon::get_home_servers($domain); + if (! exists($home_servers{$desiredhost})) { + $r->print('<font color="#ff0000">Error:</font>'. + 'Invalid home server specified'); + return; + } + } # Determine authentication mechanism my $amode = ''; my $genpwd = ''; @@ -797,11 +998,12 @@ sub upfile_drop_add { } } if ($password) { - &modifystudent($domain,$username,$cid,$sec); + &modifystudent($domain,$username,$cid,$sec, + $desiredhost); my $reply=&Apache::lonnet::modifystudent ($domain,$username,$id,$amode,$password, $fname,$mname,$lname,$gen,$sec,$enddate, - $startdate,$ENV{'form.forceid'}); + $startdate,$ENV{'form.forceid'},$desiredhost); if ($reply ne 'ok') { $r->print('<p><b>'. 'Error enrolling '.$username.': '. @@ -857,10 +1059,21 @@ sub upfile_drop_add { sub drop_student_list { my $r=shift; my $count=0; - foreach (@{$ENV{'form.droplist'}}) { + my @droplist; + if (ref($ENV{'form.droplist'})) { + @droplist = @{$ENV{'form.droplist'}}; + } else { + @droplist = ($ENV{'form.droplist'}); + } + foreach (@droplist) { my ($uname,$udom)=split(/\:/,$_); - &modifystudent($udom,$uname,$ENV{'request.course.id'}); - $r->print('Dropped '.$uname.' at '.$udom.'<br>'); + my $result = &modifystudent($udom,$uname,$ENV{'request.course.id'}); + if ($result eq 'ok' || $result eq 'ok:') { + $r->print('Dropped '.$uname.' at '.$udom.'<br>'); + } else { + $r->print('Error dropping '.$uname.' at '.$udom.': '.$result. + '<br />'); + } $count++; } $r->print('<p><b>Dropped '.$count.' student(s).</b>'); @@ -879,9 +1092,9 @@ sub handler { if (($ENV{'request.course.fn'}) && (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'}))) { # Start page - $r->content_type('text/html'); + $r->content_type('text/html') if (! exists($ENV{'form.viewcsv'})); $r->send_http_header; - $r->print(&header()); + $r->print(&header()) if (! exists($ENV{'form.viewcsv'})); # Phase one, initial screen unless ($ENV{'form.phase'}) { &menu_phase_one($r); @@ -902,6 +1115,10 @@ sub handler { &menu_phase_two_enroll($r); } elsif ($ENV{'form.drop'}) { &menu_phase_two_drop($r); + } elsif ($ENV{'form.view'}) { + &menu_phase_two_view($r); + } elsif ($ENV{'form.viewcsv'}) { + &menu_phase_two_viewcsv($r); } } # Phase three @@ -919,7 +1136,7 @@ sub handler { &enroll_single_student($r); } # End - $r->print('</form></body></html>'); + $r->print('</form></body></html>') if (! exists($ENV{'form.viewcsv'})); } else { # Not in a course, or not allowed to modify parms $ENV{'user.error.msg'}=