# The LearningOnline Network with CAPA
# Handler to drop and add students in courses
#
# $Id: londropadd.pm,v 1.49 2002/09/13 15:33:39 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
# (Handler to set parameters for assessments
#
# (Handler to resolve ambiguous file locations
#
# (TeX Content Handler
#
# YEAR=2000
# 05/29/00,05/30,10/11 Gerd Kortemeyer)
#
# 10/11,10/12,10/16 Gerd Kortemeyer)
#
# 11/20,11/21,11/22,11/23,11/24,11/25,11/27,11/28,
# 12/08,12/12 Gerd Kortemeyer)
#
# 12/26,12/27,12/28,
# YEAR=2001
# 01/01/01,01/15,02/10,02/13,02/14,02/22 Gerd Kortemeyer
# 8/6 Scott Harrison
# Guy Albertelli
# 9/25 Gerd Kortemeyer
# 12/19 Guy Albertelli
# YEAR=2002
# 1/4 Gerd Kortemeyer
package Apache::londropadd;
use strict;
use Apache::lonnet();
use Apache::loncommon();
use Apache::Constants qw(:common :http REDIRECT);
# ================================================================ Print header
sub header {
my $bodytag=&Apache::loncommon::bodytag('Enrollment Manager');
return(<LON-CAPA Enrollment Manager
$bodytag
END
}
sub phase_two_header {
my ($r,$datatoken,$distotal,$krbdefdom)=@_;
my $javascript;
if ($ENV{'form.upfile_associate'} eq 'reverse') {
$javascript=&phase_two_javascript_reverse_associate();
} else {
$javascript=&phase_two_javascript_forward_associate();
}
my $javascript_validations=&javascript_validations($krbdefdom);
$r->print(<Uploading Class List
Identify fields
Total number of records found in file: $distotal
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.
ENDPICK
}
sub javascript_validations {
my ($krbdefdom)=@_;
my %param = ( formname => 'studentform',
kerb_def_dom => $krbdefdom );
my $authheader = &Apache::loncommon::authform_header(%param);
return (<=2) && (tw<=6)) { foundname=1; }
if (tw==7) { foundid=1; }
if (tw==8) { foundsec=1; }
if (tw==9) { foundpwd=1; }
}
verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec);
}
//
// vf = this.form
// tf = column number
//
// values of nw
//
// 0 = none
// 1 = username
// 2 = names (lastname, firstnames)
// 3 = fname (firstname)
// 4 = mname (middlename)
// 5 = lname (lastname)
// 6 = gen (generation)
// 7 = id
// 8 = section
// 9 = ipwd (password)
//
function flip(vf,tf) {
var nw=eval('vf.f'+tf+'.selectedIndex');
var i;
// make sure no other columns are labeled the same as this one
for (i=0;i<=vf.nfields.value;i++) {
if ((i!=tf) && (eval('vf.f'+i+'.selectedIndex')==nw)) {
eval('vf.f'+i+'.selectedIndex=0;')
}
}
// If we set this to 'lastname, firstnames', clear out all the ones
// set to 'fname','mname','lname','gen' (3,4,5,6) currently.
if (nw==2) {
for (i=0;i<=vf.nfields.value;i++) {
if ((eval('vf.f'+i+'.selectedIndex')>=3) &&
(eval('vf.f'+i+'.selectedIndex')<=6)) {
eval('vf.f'+i+'.selectedIndex=0;')
}
}
}
// If we set this to one of 'fname','mname','lname','gen' (3,4,5,6),
// clear out any that are set to 'lastname, firstnames' (2)
if ((nw>=3) && (nw<=6)) {
for (i=0;i<=vf.nfields.value;i++) {
if (eval('vf.f'+i+'.selectedIndex')==2) {
eval('vf.f'+i+'.selectedIndex=0;')
}
}
}
// If we set the password, make the password form below correspond to
// the new value.
if (nw==9) {
changed_radio('int',document.studentform);
set_auth_radio_buttons('int',document.studentform);
vf.intarg.value='';
vf.krbarg.value='';
vf.locarg.value='';
}
}
function clearpwd(vf) {
var i;
for (i=0;i<=vf.nfields.value;i++) {
if (eval('vf.f'+i+'.selectedIndex')==9) {
eval('vf.f'+i+'.selectedIndex=0;')
}
}
}
ENDPICK
}
sub phase_two_javascript_reverse_associate {
return(<=1) && (i<=5)) && tw!=0 ) { foundname=1; }
if (i==6 && tw!=0) { foundid=1; }
if (i==7 && tw!=0) { foundsec=1; }
if (i==8 && tw!=0) { foundpwd=1; }
}
verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec);
}
function flip(vf,tf) {
var nw=eval('vf.f'+tf+'.selectedIndex');
var i;
// picked the all one one name field, reset the other name ones to blank
if (tf==1 && nw!=0) {
for (i=2;i<=5;i++) {
eval('vf.f'+i+'.selectedIndex=0;')
}
}
//picked one of the piecewise name fields, reset the all in
//one field to blank
if ((tf>=2) && (tf<=5) && (nw!=0)) {
eval('vf.f1.selectedIndex=0;')
}
// intial password specified, pick internal authentication
if (tf==8 && nw!=0) {
changed_radio('int',document.studentform);
set_auth_radio_buttons('int',document.studentform);
vf.krbarg.value='';
vf.intarg.value='';
vf.locarg.value='';
}
}
function clearpwd(vf) {
var i;
if (eval('vf.f8.selectedIndex')!=0) {
eval('vf.f8.selectedIndex=0;')
}
}
ENDPICK
}
sub phase_two_end {
my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_;
my %param = ( formname => 'document.studentform');
my $krbform = &Apache::loncommon::authform_kerberos(%param);
my $intform = &Apache::loncommon::authform_internal(%param);
my $locform = &Apache::loncommon::authform_local(%param);
my $domform = &domain_form($defdom);
$r->print(<
Login Type
Note: this will not take effect if the user already exists
Full update
(also print list of users not enrolled anymore)
ID/Student Number
Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
(only do if you know what you are doing)
Note: for large courses, this operation might be time consuming.
ENDPICK
}
# ======================================================= Menu Phase Two Upload
sub menu_phase_two_upload {
my $r=shift;
my $datatoken;
if (!$ENV{'form.datatoken'}) {
$datatoken=&Apache::loncommon::upfile_store($r);
} else {
$datatoken=$ENV{'form.datatoken'};
&Apache::loncommon::load_tmp_file($r);
}
my @records=&Apache::loncommon::upfile_record_sep();
my $total=$#records;
my $distotal=$total+1;
$ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
my $krbdefdom=$1;
$krbdefdom=~tr/a-z/A-Z/;
my $today=time;
my $halfyear=$today+15552000;
my $defdom=$r->dir_config('lonDefDomain');
&phase_two_header($r,$datatoken,$distotal,$krbdefdom);
my $i;
my $keyfields;
if ($total>=0) {
my @d=(['username','Username'],['names','Last Name, First Names'],
['fname','First Name'],['mname','Middle Names/Initials'],
['lname','Last Name'],['gen','Generation'],
['id','ID/Student Number'],['sec','Group/Section'],
['ipwd','Initial Password']);
if ($ENV{'form.upfile_associate'} eq 'reverse') {
&Apache::loncommon::csv_print_samples($r,\@records);
$i=&Apache::loncommon::csv_print_select_table($r,\@records,\@d);
foreach (@d) { $keyfields.=$_->[0].','; }
chop($keyfields);
} else {
unshift(@d,['none','']);
$i=&Apache::loncommon::csv_samples_select_table($r,\@records,\@d);
my %sone=&Apache::loncommon::record_sep($records[0]);
$keyfields=join(',',sort(keys(%sone)));
}
}
&phase_two_end($r,$i,$keyfields,$defdom,$today,$halfyear);
}
# ======================================================= Enroll single student
sub enroll_single_student {
my $r=shift;
$r->print('
Enrolling Student
');
$r->print('
Enrolling '.$ENV{'form.cuname'}." in domain ".
$ENV{'form.lcdomain'}.'
');
if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\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_library_servers($domain);
if (! exists($home_servers{$desiredhost})) {
$r->print('Error:'.
'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') {
$amode='krb';
$amode.=$ENV{'form.krbver'};
$genpwd=$ENV{'form.krbarg'};
} elsif ($ENV{'form.login'} eq 'int') {
$amode='internal';
$genpwd=$ENV{'form.intarg'};
} elsif ($ENV{'form.login'} eq 'loc') {
$amode='localauth';
$genpwd=$ENV{'form.locarg'};
if (!$genpwd) { $genpwd=" "; }
}
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.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'},
$desiredhost));
} else {
$r->print('
ERROR '.
'Invalid login mode or password. '.
'Unable to enroll '.$ENV{'form.cuname'}.'.
');
}
} else {
$r->print('Invalid username or domain');
}
}
# ======================================================= Menu Phase Two Enroll
sub menu_phase_two_enroll {
my $r=shift;
$r->print("
Enroll One Student
");
my ($krbdefdom) = $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/;
$krbdefdom=~tr/a-z/A-Z/;
my $today = time;
my $halfyear = $today+15552000;
my $defdom=$r->dir_config('lonDefDomain');
my $javascript_validations=&javascript_validations($krbdefdom);
# Set up authentication forms
my %param = ( formname => 'document.studentform');
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 = &domain_form($defdom);
# Print it all out
$r->print(<
function verify(vf) {
var founduname=0;
var foundpwd=0;
var foundname=0;
var foundid=0;
var foundsec=0;
var tw;
if ((typeof(vf.cuname.value) !="undefined") && (vf.cuname.value!='') &&
(typeof(vf.lcdomain.value)!="undefined") && (vf.lcdomain.value!='')) {
founduname=1;
}
if ((typeof(vf.cfirst.value)!="undefined") && (vf.cfirst.value!='') &&
(typeof(vf.clast.value) !="undefined") && (vf.clast.value!='')) {
foundname=1;
}
if ((typeof(vf.csec.value)!="undefined") && (vf.csec.value!='')) {
foundsec=1;
}
if ((typeof(vf.cstid.value)!="undefined") && (vf.cstid.value!='')) {
foundid=1;
}
if (founduname==0) {
alert('You need to specify at least the username and domain fields');
return;
}
verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec);
}
$javascript_validations
function clearpwd(vf) {
//nothing else needs clearing
}
Personal Data
First Name:
Middle Name:
Last Name:
Generation:
ID/Student Number:
Group/Section:
Login Data
Username:
Domain: $domform
Note: login settings below will not take effect if the user already exists
Disable ID/Student Number Safeguard and Force Change of Conflicting IDs
(only do if you know what you are doing)
ENDSENROLL
}
# =================================================== get the current classlist
sub get_current_classlist {
my ($domain,$identifier) = @_;
# domain is the domain the class is being run in
# identifier is the internal, unique identifier for the class.
my %currentlist=();
my $now=time;
my %results=&Apache::lonnet::dump('classlist',$domain,$identifier);
my ($tmp) = keys(%results);
if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
foreach my $student (keys(%results)) {
# Extract the start and end dates
my ($end,$start)=split(/\:/,$results{$student});
# If the class isn't over, put it in the list
unless (($end) && ($now>$end)) {
$currentlist{$student}=1;
}
}
return (undef,%currentlist);
} else {
$tmp =~ s/^error://;
return ($tmp,undef);
}
}
# ========================================================= Menu Phase Two Drop
sub menu_phase_two_drop {
my $r=shift;
$r->print("
Drop Students
");
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("
ERROR:$error
");
}
} elsif (!defined(%currentlist)) {
$r->print("There are no students currently enrolled.\n");
} else {
# Print out the available choices
&show_drop_list($r,%currentlist);
}
}
# ============================================== view classlist
sub menu_phase_two_view {
my $r=shift;
$r->print(<Current Classlist
CSV format
END
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("
ERROR:$error
");
}
} 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("
ERROR:$error
");
}
} 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(<
') 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');
username
domain
ID
student 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('
'.
'Internal error: unable to get environment '.
'for '.$sname.' in domain '.$sdom.'
END
}
#
# Print out the initial form to get the courselist file
#
sub print_first_courselist_upload_form {
my $r=shift;
my $upfile_select=&Apache::loncommon::upfile_select_html();
my $create_classlist_help =
&Apache::loncommon::help_open_topic("Course_Create_Class_List",
"How do I create a class list from a spreadsheet");
my $create_csv_help =
&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
"How do I create a CSV file from a spreadsheet");
$r->print(<