--- loncom/interface/Attic/londropadd.pm 2002/04/04 20:41:17 1.23 +++ loncom/interface/Attic/londropadd.pm 2006/11/23 03:17:17 1.150 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to drop and add students in courses # -# $Id: londropadd.pm,v 1.23 2002/04/04 20:41:17 albertel Exp $ +# $Id: londropadd.pm,v 1.150 2006/11/23 03:17:17 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,321 +25,512 @@ # # 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::lonhtmlcommon(); use Apache::Constants qw(:common :http REDIRECT); +use Spreadsheet::WriteExcel; +use Apache::lonstathelpers(); +use Apache::lonlocal; +use Apache::longroup; -# ================================================================ Print header - +############################################################### +############################################################### sub header { - my $r=shift; - $r->print(< - -LON-CAPA Student Drop/Add - - - -

Drop/Add Students

-
-

Course: $ENV{'course.'.$ENV{'request.course.id'}.'.description'}

+ my $start_page=&Apache::loncommon::start_page('Enrollment Manager'); + return(< ENDHEAD } -# ========================================================= Store uploaded file -# needs $ENV{'form.upfile'} -# return $datatoken to be put into hidden field - -sub upfile_store { - my $r=shift; - $ENV{'form.upfile'}=~s/\r/\n/gs; - $ENV{'form.upfile'}=~s/\f/\n/gs; - $ENV{'form.upfile'}=~s/\n+/\n/gs; - $ENV{'form.upfile'}=~s/\n+$//gs; - - my $datatoken=$ENV{'user.name'}.'_'.$ENV{'user.domain'}. - '_enroll_'.$ENV{'request.course.id'}.'_'.time.'_'.$$; - { - my $fh=Apache::File->new('>'.$r->dir_config('lonDaemons'). - '/tmp/'.$datatoken.'.tmp'); - print $fh $ENV{'form.upfile'}; - } - return $datatoken; -} - -# ================================================= Load uploaded file from tmp -# needs $ENV{'form.datatoken'} -# sets $ENV{'form.upfile'} - -sub load_tmp_file { - my $r=shift; - my @studentdata=(); - { - my $fh; - if ($fh=Apache::File->new($r->dir_config('lonDaemons'). - '/tmp/'.$ENV{'form.datatoken'}.'.tmp')) { - @studentdata=<$fh>; - } +############################################################### +############################################################### +# Drop student from all sections of a course, except optional $csec +sub modifystudent { + 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 + my $cdom = $env{'request.'.$courseid.'.domain'}; + my $cnum = $env{'request.'.$courseid.'.num'}; + my %roles = &Apache::lonnet::dump('roles',$udom,$unam); + my ($tmp) = keys(%roles); + # Bail out if we were unable to get the students roles + 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)) { + if ($course=~m{^/\Q$cdom\E/\Q$cnum\E(?:\/)*(?:\s+)*(\w+)*\_st$}) { + # We are in this course + my $section=$1; + $section='' if ($course eq "/$cdom/$cnum".'_st'); + if (defined($csec) && $section eq $csec) { + $result .= 'ok:'; + } elsif ( ((!$section) && (!$csec)) || ($section ne $csec) ) { + my (undef,$end,$start)=split(/\_/,$roles{$course}); + my $now=time; + # if this is an active role + if (!($start && ($now<$start)) || !($end && ($now>$end))) { + my $reply=&Apache::lonnet::modifystudent + # dom name id mode pass f m l g + ($udom,$unam,'', '', '',undef,undef,undef,undef, + $section,time,undef,undef,$desiredhost); + $result .= $reply.':'; + } + } + } } - $ENV{'form.upfile'}=join('',@studentdata); -} - -# ========================================= Separate uploaded file into records -# returns array of records - -sub upfile_record_sep { - if ($ENV{'form.upfiletype'} eq 'xml') { + if ($result eq '') { + $result = 'Unable to find section for this student'; } else { - return split(/\n/,$ENV{'form.upfile'}); + $result =~ s/(ok:)+/ok/g; } + return $result; } -# =============================================== Separate a record into fields - -sub record_sep { - my $record=shift; - my %components=(); - if ($ENV{'form.upfiletype'} eq 'xml') { - } elsif ($ENV{'form.upfiletype'} eq 'space') { - my $i=0; - foreach (split(/\s+/,$record)) { - my $field=$_; - $field=~s/^(\"|\')//; - $field=~s/(\"|\')$//; - $components{$i}=$field; - $i++; - } - } elsif ($ENV{'form.upfiletype'} eq 'tab') { - my $i=0; - foreach (split(/\t+/,$record)) { - my $field=$_; - $field=~s/^(\"|\')//; - $field=~s/(\"|\')$//; - $components{$i}=$field; - $i++; +############################################################### +############################################################### +# 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_library_servers($dom); + foreach my $server (keys(%servers)) { + $select_menus{$dom}->{'select2'}->{$server} + = "$server $servers{$server}"; } - } else { - my @allfields=split(/\,/,$record); - my $i=0; - my $j; - for ($j=0;$j<=$#allfields;$j++) { - my $field=$allfields[$j]; - if ($field=~/^\s*(\"|\')/) { - my $delimiter=$1; - while (($field!~/$delimiter$/) && ($j<$#allfields)) { - $j++; - $field.=','.$allfields[$j]; - } - $field=~s/^\s*$delimiter//; - $field=~s/$delimiter\s*$//; - } - $components{$i}=$field; - $i++; - } - } - return %components; -} - -# =========== Drop student from all sections of a course, except optional $csec - -sub dropstudent { - my ($udom,$unam,$courseid,$csec)=@_; - $courseid=~s/\_/\//g; - $courseid=~s/^(\w)/\/$1/; - foreach (split(/\&/, - &Apache::lonnet::reply('dump:'.$udom.':'.$unam.':roles', - &Apache::lonnet::homeserver($unam,$udom)))) { - my ($key,$value)=split(/\=/,$_); - $key=&Apache::lonnet::unescape($key); - if ($key=~/^$courseid(?:\/)*(\w+)*\_st$/) { - my $section=$1; - if ($key eq $courseid.'_st') { $section=''; } - if (((!$section) && (!$csec)) || ($section ne $csec)) { - my ($dummy,$end,$start)=split(/\_/, - &Apache::lonnet::unescape($value)); - my $now=time; - my $notactive=0; - if ($start) { - if ($now<$start) { $notactive=1; } - } - if ($end) { - if ($now>$end) { $notactive=1; } - } - unless ($notactive) { - my $reply=&Apache::lonnet::modifystudent( - $udom,$unam,'','','', - '','','','',$section,time); - } - } + } + my $result = &Apache::loncommon::linked_select_forms + ('studentform',' with home server ',$defdom, + 'lcdomain','lcserver',\%select_menus); + return $result; +} + +############################################################### +############################################################### +# Menu Phase One +sub print_main_menu { + my ($r,$enrl_permission,$view_permission,$grp_manage_permission, + $grp_view_permission)=@_; + # + my $cid =$env{'request.course.id'}; + my $cdom=$env{'course.'.$cid.'.domain'}; + my $cnum=$env{'course.'.$cid.'.num'}; + my @menu = + ( + { text => 'Upload a class list', + help => 'Course_Create_Class_List', + action => 'upload', + permission => $enrl_permission, + }, + { text => 'Enroll a single student', + help => 'Course_Add_Student', + action => 'enrollstudent', + permission => $enrl_permission, + }, + { text => 'Modify student data', + help => 'Course_Modify_Student_Data', + action => 'modifystudent', + permission => $enrl_permission, + }, + { text => 'View Class List', + help => 'Course_View_Class_List', + action => 'classlist', + permission => $view_permission, + }, + { text => 'Drop Students', + help => 'Course_Drop_Student', + action => 'drop', + permission => $enrl_permission, + }, + { text => 'Automated Enrollment Manager', + permission => &Apache::lonnet::auto_run($cnum,$cdom), + url => '/adm/populate', + }, + { text => 'Create a new group', + help => 'Course_Create_Group', + permission => $grp_manage_permission, + url => '/adm/coursegroups?refpage=enrl&action=create', + }, + { text => 'Modify an existing group', + help => 'Course_Modify_Group', + permission => $grp_manage_permission, + url => '/adm/coursegroups?refpage=enrl&action=modify', + }, +# { text => 'Delete an existing group', +# help => 'Course_Delete_Group', +# permission => $grp_manage_permission, +# url => '/adm/coursegroups?refpage=enrl&action=delete', +# }, + { text => 'Enter an existing group', + help => 'Course_Display_Group', + permission => $grp_view_permission, + url => '/adm/coursegroups?refpage=enrl&action=view', + }, + ); + my $menu_html = ''; + foreach my $menu_item (@menu) { + next if (! $menu_item->{'permission'}); + $menu_html.='

'; + $menu_html.=''; + if (exists($menu_item->{'url'})) { + $menu_html.=qq{}; + } else { + $menu_html.= + qq{}; + } + $menu_html.= &mt($menu_item->{'text'}).''; + if (exists($menu_item->{'help'})) { + $menu_html.= + &Apache::loncommon::help_open_topic($menu_item->{'help'}); } + $menu_html.='

'.$/; } + $r->print($menu_html); + return; } -# ============================================================== Menu Phase One - -sub menu_phase_one { - my $r=shift; - $r->print(< -
-

Upload a courselist

- -
Type: -

-


-

Enroll a single student

-

-


-

Drop students

-

-ENDUPFORM +############################################################### +############################################################### +sub hidden_input { + my ($name,$value) = @_; + return ''."\n"; } - -sub phase_two_header { +sub print_upload_manager_header { my ($r,$datatoken,$distotal,$krbdefdom)=@_; - $r->print(< - - -


-

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.
-'); +} + +############################################################### +############################################################### +sub javascript_validations { + my ($mode,$krbdefdom,$curr_authtype,$curr_authfield)=@_; + my $authheader; + if ($mode eq 'auth') { + my %param = ( formname => 'studentform', + kerb_def_dom => $krbdefdom, + curr_authtype => $curr_authtype); + $authheader = &Apache::loncommon::authform_header(%param); + } elsif ($mode eq 'createcourse') { + my %param = ( formname => 'ccrs', + kerb_def_dom => $krbdefdom, + curr_authtype => $curr_authtype ); + $authheader = &Apache::loncommon::authform_header(%param); + } elsif ($mode eq 'modifycourse') { + my %param = ( formname => 'cmod', + kerb_def_dom => $krbdefdom, + mode => 'modifycourse', + curr_authtype => $curr_authtype, + curr_autharg => $curr_authfield ); + $authheader = &Apache::loncommon::authform_header(%param); + } + + + my %alert = &Apache::lonlocal::texthash + (username => 'You need to specify the username field.', + authen => 'You must choose an authentication type.', + krb => 'You need to specify the Kerberos domain.', + ipass => 'You need to specify the initial password.', + name => 'The optional name field was not specified.', + snum => 'The optional student number field was not specified.', + section => 'The optional section field was not specified.', + email => 'The optional email address field was not specified.', + continue => 'Continue enrollment?', + ); + +# my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition(); + my $function_name =(<=2) && (tw<=6)) { foundname=1; } + if (tw==7) { foundid=1; } + if (tw==8) { foundsec=1; } + if (tw==9) { foundpwd=1; } + if (tw==10) { foundemail=1; } + } + verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail); +} + +// +// 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) +// 10 = email address + 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;') - } + 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) { - vf.login[1].checked=true; - vf.intpwd.value=''; - vf.krbdom.value=''; + changed_radio('int',document.studentform); + set_auth_radio_buttons('int',document.studentform); + vf.intarg.value=''; + vf.krbarg.value=''; vf.locarg.value=''; } - } function clearpwd(vf) { @@ -348,256 +539,580 @@ function clearpwd(vf) { if (eval('vf.f'+i+'.selectedIndex')==9) { eval('vf.f'+i+'.selectedIndex=0;') } - } -} - -function setkrb(vf) { - if (vf.krbdom.value!='') { - clearpwd(vf); - vf.login[0].checked=true; - vf.krbdom.value=vf.krbdom.value.toUpperCase(); - vf.intpwd.value=''; - } + } } -function setint(vf) { - if (vf.intpwd.value!='') { - clearpwd(vf); - vf.login[1].checked=true; - vf.krbdom.value=''; - } +ENDPICK } -function clickkrb(vf) { - vf.krbdom.value='$krbdefdom'; - clearpwd(vf); - vf.intpwd.value=''; +############################################################### +############################################################### +sub upload_manager_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 clickint(vf) { - vf.krbdom.value=''; +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 pclose() { - parmwin=window.open("/adm/rat/empty.html","LONCAPAparms", - "height=350,width=350,scrollbars=no,menubar=no"); - parmwin.close(); - } - - function pjump(type,dis,value,marker,ret,call) { - parmwin=window.open("/adm/rat/parameter.html?type="+escape(type) - +"&value="+escape(value)+"&marker="+escape(marker) - +"&return="+escape(ret) - +"&call="+escape(call)+"&name="+escape(dis),"LONCAPAparms", - "height=350,width=350,scrollbars=no,menubar=no"); - - } - - function dateset() { - if (document.studentform.pres_marker.value=='end') { - document.studentform.enddate.value= - document.studentform.pres_value.value; - } - if (document.studentform.pres_marker.value=='start') { - document.studentform.startdate.value= - document.studentform.pres_value.value; - } - pclose(); +function clearpwd(vf) { + var i; + if (eval('vf.f8.selectedIndex')!=0) { + eval('vf.f8.selectedIndex=0;') } - - - +} ENDPICK } -sub phase_two_end { +############################################################### +############################################################### +sub print_upload_manager_footer { my ($r,$i,$keyfields,$defdom,$today,$halfyear)=@_; - $r->print(< - - -

Login Type

-

Note: this will not take effect if the user already exists

-

- -Kerberos authenticated with domain - -

-

- -Internally authenticated (with initial password -) -

-

- -Local Authentication with argument - -

-

LON-CAPA Domain for Students

-LON-CAPA domain:

-

Starting and Ending Dates

- - - - - -Set Starting Date

- -Set Ending Date

-

Full Update

- 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 ($krbdef,$krbdefdom) = + &Apache::loncommon::get_kerberos_defaults($defdom); + my %param = ( formname => 'document.studentform', + kerb_def_dom => $krbdefdom, + kerb_def_auth => $krbdef + ); + if (exists($env{'form.ipwd_choice'}) && + defined($env{'form.ipwd_choice'}) && + $env{'form.ipwd_choice'} ne '') { + $param{'curr_authtype'} = 'int'; + } + 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); + my $date_table = &date_setting_table(); + my $Str = "

FieldSamples
\n"; + $Str .= &hidden_input('nfields',$i); + $Str .= &hidden_input('keyfields',$keyfields); + $Str .= '

'.&mt('Login Type')."

\n"; + $Str .= "

\n". + &mt('Note: this will not take effect if the user already exists'). + &Apache::loncommon::help_open_topic('Auth_Options'). + "

\n"; + $Str .= $krbform."\n

\n". + $intform."\n

\n". + $locform."\n

\n"; + $Str .= '

'.&mt('LON-CAPA Domain for Students')."

\n"; + $Str .= "

\n".&mt('LON-CAPA domain: [_1]',$domform)."\n

\n"; + $Str .= "

".&mt('Starting and Ending Dates')."

\n"; + $Str .= "

\n".$date_table."

\n"; + $Str .= "

".&mt('Full Update')."

\n"; + $Str .= '

\n"; + $Str .= "

".&mt('Student Number')."

\n"; + $Str .= "

\n".'\n

\n"; + $Str .= ''."
\n"; + $Str .= &mt('Note: for large courses, this operation may be time '. + 'consuming'); + $r->print($Str); + return; +} + +############################################################### +############################################################### +sub print_upload_manager_form { my $r=shift; - my $datatoken=&upfile_store($r); - - my @records=&upfile_record_sep(); + my $firstLine; + 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(); + if($env{'form.noFirstLine'}){ + $firstLine=shift(@records); + } 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 %sone; my %stwo; my %sthree; - my $i=0; - + # + # Restore memorized settings + &Apache::loncommon::restore_course_settings + ('enrollment_upload',{ 'username_choice' => 'scalar', # column settings + 'names_choice' => 'scalar', + 'fname_choice' => 'scalar', + 'mname_choice' => 'scalar', + 'lname_choice' => 'scalar', + 'gen_choice' => 'scalar', + 'id_choice' => 'scalar', + 'sec_choice' => 'scalar', + 'ipwd_choice' => 'scalar', + 'email_choice' => 'scalar', + }); + # + # Determine kerberos parameters as appropriate + my $defdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + my ($krbdef,$krbdefdom) = + &Apache::loncommon::get_kerberos_defaults($defdom); + # + &print_upload_manager_header($r,$datatoken,$distotal,$krbdefdom); + my $i; + my $keyfields; if ($total>=0) { - %sone=&record_sep($records[0]); - if ($total>=1) { - %stwo=&record_sep($records[1]); - } - if ($total>=2) { - %sthree=&record_sep($records[2]); - } - foreach (sort keys %sone) { - $r->print(''); - if (defined($sone{$_})) { - $r->print($sone{$_}."
\n"); - } - if (defined($stwo{$_})) { - $r->print($stwo{$_}."
\n"); - } - if (defined($sthree{$_})) { - $r->print($sthree{$_}."
\n"); - } - $r->print(''); - $i++; + my @field= + (['username',&mt('Username'), $env{'form.username_choice'}], + ['names',&mt('Last Name, First Names'),$env{'form.names_choice'}], + ['fname',&mt('First Name'), $env{'form.fname_choice'}], + ['mname',&mt('Middle Names/Initials'),$env{'form.mname_choice'}], + ['lname',&mt('Last Name'), $env{'form.lname_choice'}], + ['gen', &mt('Generation'), $env{'form.gen_choice'}], + ['id', &mt('ID/Student Number'),$env{'form.id_choice'}], + ['sec', &mt('Section'), $env{'form.sec_choice'}], + ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}], + ['email',&mt('EMail Address'), $env{'form.email_choice'}]); + if ($env{'form.upfile_associate'} eq 'reverse') { + &Apache::loncommon::csv_print_samples($r,\@records); + $i=&Apache::loncommon::csv_print_select_table($r,\@records, + \@field); + foreach (@field) { + $keyfields.=$_->[0].','; + } + chop($keyfields); + } else { + unshift(@field,['none','']); + $i=&Apache::loncommon::csv_samples_select_table($r,\@records, + \@field); + my %sone=&Apache::loncommon::record_sep($records[0]); + $keyfields=join(',',sort(keys(%sone))); } - $i--; } - my $keyfields=join(',',sort keys %sone); - - &phase_two_end($r,$i,$keyfields,$defdom,$today,$halfyear); + &print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear); } -# ======================================================= Enroll single student - +############################################################### +############################################################### sub enroll_single_student { my $r=shift; - $r->print('

Enrolling Student

'); - if (($ENV{'form.cuname'})&&($ENV{'form.cuname'}!~/\W/)&& - ($ENV{'form.cdomain'})&&($ENV{'form.cdomain'}!~/\W/)) { + # Remove non alphanumeric values from section + $env{'form.csec'}=~s/\W//g; + # + # We do the dates first because the action of making them the defaul + # in the course is entirely separate from the action of enrolling the + # student. Also, a failure in setting the dates as default is not fatal + # to the process of enrolling / modifying a student. + my ($startdate,$enddate) = &get_dates_from_form(); + if ($env{'form.makedatesdefault'}) { + $r->print(&make_dates_default($startdate,$enddate)); + } + + $r->print('

'.&mt('Enrolling Student').'

'); + $r->print('

'.&mt('Enrolling').' '.$env{'form.cuname'}." \@ ". + $env{'form.lcdomain'}.'

'); + if (($env{'form.cuname'}) + && ($env{'form.cuname'} + eq &LONCAPA::clean_username($env{'form.cuname'})) + && ($env{'form.lcdomain'}) + && ($env{'form.lcdomain'} + eq &LONCAPA::clean_domain($env{'form.lcdomain'}))) { + # 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(''.&mt('Error').':'. + &mt('Invalid home server specified')); + return; + } + } + $r->print(" ".&mt('with server')." $desiredhost :") if (defined($desiredhost)); + # End of home server selection logic my $amode=''; my $genpwd=''; - if ($ENV{'form.login'} eq 'krb') { - $amode='krb4'; - $genpwd=$ENV{'form.krbdom'}; - } elsif ($ENV{'form.login'} eq 'int') { + 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.intpwd'}; - } elsif ($ENV{'form.login'} eq 'loc') { + $genpwd=$env{'form.intarg'}; + } elsif ($env{'form.login'} eq 'loc') { $amode='localauth'; - $genpwd=$ENV{'form.locarg'}; + $genpwd=$env{'form.locarg'}; if (!$genpwd) { $genpwd=" "; } } - if (($amode) && ($genpwd)) { - &dropstudent($ENV{'form.cdomain'},$ENV{'form.cuname'}, - $ENV{'request.course.id'},$ENV{'form.csec'}); - $r->print(&Apache::lonnet::modifystudent( - $ENV{'form.cdomain'},$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'})); + my $home = &Apache::lonnet::homeserver($env{'form.cuname'}, + $env{'form.lcdomain'}); + if ((($amode) && ($genpwd)) || ($home ne 'no_host')) { + # Clean out any old roles the student has in this class. + &modifystudent($env{'form.lcdomain'},$env{'form.cuname'}, + $env{'request.course.id'},$env{'form.csec'}, + $desiredhost); + my $login_result = &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'},$enddate, + $startdate,$env{'form.forceid'}, + $desiredhost,$env{'form.emailaddress'}); + if ($login_result =~ /^ok/) { + $r->print($login_result); + $r->print("

".&mt('If active, the new role will be available when the student next logs in to LON-CAPA.')."

"); + } else { + $r->print(&mt('unable to enroll').": ".$login_result); + } } else { - $r->print('Invalid login mode or password'); - } + $r->print('

'.&mt('ERROR').' '); + if ($amode =~ /^krb/) { + $r->print(&mt('Missing Kerberos domain information.').' '); + } else { + $r->print(&mt('Invalid login mode or password.').' '); + } + $r->print(''.&mt('Unable to enroll').' '.$env{'form.cuname'}.'.

'); + } } else { - $r->print('Invalid username or domain'); + $r->print(&mt('Invalid username or domain')); } } -# ======================================================= Menu Phase Two Enroll - -sub menu_phase_two_enroll { - my $r=shift; - - $ENV{'SERVER_NAME'}=~/(\w+\.\w+)$/; - my $krbdefdom=$1; - $krbdefdom=~tr/a-z/A-Z/; - - my $today=time; - my $halfyear=$today+15552000; +sub setup_date_selectors { + my ($starttime,$endtime,$mode) = @_; + if (! defined($starttime)) { + $starttime = time; + unless ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') { + if (exists($env{'course.'.$env{'request.course.id'}. + '.default_enrollment_start_date'})) { + $starttime = $env{'course.'.$env{'request.course.id'}. + '.default_enrollment_start_date'}; + } + } + } + if (! defined($endtime)) { + $endtime = time+(6*30*24*60*60); # 6 months from now, approx + unless ($mode eq 'createcourse') { + if (exists($env{'course.'.$env{'request.course.id'}. + '.default_enrollment_end_date'})) { + $endtime = $env{'course.'.$env{'request.course.id'}. + '.default_enrollment_end_date'}; + } + } + } + my $startdateform = &Apache::lonhtmlcommon::date_setter('studentform', + 'startdate', + $starttime); + my $enddateform = &Apache::lonhtmlcommon::date_setter('studentform', + 'enddate', + $endtime); + if ($mode eq 'create_enrolldates') { + $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs', + 'startenroll', + $starttime); + $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs', + 'endenroll', + $endtime); + } + if ($mode eq 'create_defaultdates') { + $startdateform = &Apache::lonhtmlcommon::date_setter('ccrs', + 'startaccess', + $starttime); + $enddateform = &Apache::lonhtmlcommon::date_setter('ccrs', + 'endaccess', + $endtime); + } + return ($startdateform,$enddateform); +} + +sub get_dates_from_form { + my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate'); + my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate'); + if ($env{'form.no_end_date'}) { + $enddate = 0; + } + return ($startdate,$enddate); +} + +sub date_setting_table { + my ($starttime,$endtime,$mode) = @_; + my ($startform,$endform)=&setup_date_selectors($starttime,$endtime,$mode); + my $dateDefault = ''. + ''; + if ($mode eq 'create_enrolldates' || $mode eq 'create_defaultdates') { + $dateDefault = ' '; + } + my $perpetual = ''; + if ($mode eq 'create_enrolldates') { + $perpetual = ' '; + } + my $result = ''; + $result .= "\n"; + $result .= ''. + ''. + ''."\n"; + $result .= ''. + ''. + ''."\n"; + $result .= "
'.&mt('Starting Date').''.$startform.''.$dateDefault.'
'.&mt('Ending Date').''.$endform.''.$perpetual.'
\n"; + return $result; +} + +sub make_dates_default { + my ($startdate,$enddate) = @_; + my $result = ''; + my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $crs = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $put_result = &Apache::lonnet::put('environment', + {'default_enrollment_start_date'=>$startdate, + 'default_enrollment_end_date' =>$enddate},$dom,$crs); + if ($put_result eq 'ok') { + $result .= "Set default start and end dates for course
"; + # + # Refresh the course environment + &Apache::lonnet::coursedescription($env{'request.course.id'}, + {'freshen_cache' => 1}); + } else { + $result .= &mt('Unable to set default dates for course').":".$put_result. + '
'; + } + return $result; +} - my $defdom=$r->dir_config('lonDefDomain'); +## +## Single student enrollment routines (some of them) +## +sub get_student_username_domain_form { + my $r = shift; + my $domform = &Apache::loncommon::select_dom_form + ($env{'course.'.$env{'request.course.id'}.'.domain'},'cudomain',0); + my %lt=&Apache::lonlocal::texthash( + 'eos' => "Enroll One Student", + 'usr' => "Username", + 'dom' => "Domain", + 'been' => "Begin Enrollment", + ); + $r->print(< + +

$lt{'eos'}

+ + + + + + + +
$lt{'usr'}:
$lt{'dom'}:$domform
  + +
+ +END + return; +} - $r->print(< -function verify(vf) { +sub print_enroll_single_student_form { + my $r=shift; + $r->print("

".&mt('Enroll One Student')."

"); + # + my $username = &LONCAPA::clean_username($env{'form.cuname'}); + my $domain = &LONCAPA::clean_domain($env{'form.cudomain'}); + my $home = &Apache::lonnet::homeserver($username,$domain); + # $new_user flags whether we are creating a new user or using an old one + my $new_user = 1; + if ($home ne 'no_host') { + $new_user = 0; + } + # + my $user_data_html = ''; + my $javascript_validations = ''; + if ($new_user) { + my $defdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; + # Set up authentication forms + my ($krbdef,$krbdefdom) = + &Apache::loncommon::get_kerberos_defaults($domain); + $javascript_validations=&javascript_validations('auth',$krbdefdom); + my %param = ( formname => 'document.studentform', + kerb_def_dom => $krbdefdom, + kerb_def_auth => $krbdef + ); + 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 $homeserver_form = ''; + my %servers = &Apache::loncommon::get_library_servers($domain); + $homeserver_form = '\n"; + # + # + my %lt=&Apache::lonlocal::texthash( + 'udf' => "User Data for", + 'fn' => "First Name", + 'mn' => "Middle Name", + 'ln' => "Last Name", + 'gen' => "Generation", + 'hs' => "Home Server", + 'pswd' => "Password", + 'psam' => "Please select an authentication mechanism", + 'mail' => "Email Address" + ); + my $authhelp=&Apache::loncommon::help_open_topic('Auth_Options'); + $user_data_html = <$lt{'udf'} $username\@$domain + + + + + + + + + + + + + +
$lt{'fn'}:
$lt{'mn'}:
$lt{'ln'}:
$lt{'gen'}:
$lt{'hs'}:$homeserver_form
$lt{'mail'}:
+

$lt{'pswd'}

+$lt{'psam'}$authhelp + +

+$krbform +
+$intform +
+$locform +

+END + } else { + # User already exists. Do not worry about authentication + my %uenv = &Apache::lonnet::dump('environment',$domain,$username); + $javascript_validations = &javascript_validations('noauth'); + my %lt=&Apache::lonlocal::texthash( + 'udf' => "User Data for", + 'fn' => "First Name", + 'mn' => "Middle Name", + 'ln' => "Last Name", + 'gen' => "Generation", + 'mail' => "Email Address", + ); + $user_data_html = <$lt{'udf'} $username\@$domain + +
+ + + + + + + + + + +
$lt{'fn'}: + +
$lt{'mn'}: + +
$lt{'ln'}: + +
$lt{'gen'}: + +
$lt{'mail'}: + +
+END + } + my $date_table = &date_setting_table(); + # Print it all out + my %lt=&Apache::lonlocal::texthash( + 'cd' => "Course Data", + 'gs' => "Section", + 'idsn' => "ID/Student Number", + 'disn' => "Disable ID/Student Number Safeguard and Force Change of Conflicting IDs (only do if you know what you are doing)", + 'eas' => "Enroll as student", + ); + $r->print(< + + + + + +$user_data_html + +

$lt{'cd'}

+ +

$lt{'gs'}: +

+$date_table +

+

$lt{'idsn'}

+

+$lt{'idsn'}: +

+ +

+ +

+END + return; +} + +# ========================================================= Menu Phase Two Drop +sub print_drop_menu { + my $r=shift; + $r->print("

".&mt('Drop Students')."

"); + my $cid=$env{'request.course.id'}; + my ($classlist,$keylist) = &Apache::loncoursedata::get_classlist(); + if (! defined($classlist)) { + $r->print(&mt('There are no students currently enrolled.')."\n"); + return; + } + # Print out the available choices + &show_drop_list($r,$classlist,$keylist); + return; +} + +# ============================================== view classlist +sub print_html_classlist { + my ($r,$mode) = @_; + if (! exists($env{'form.sortby'})) { + $env{'form.sortby'} = 'username'; + } + if ($env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) { + $env{'form.Status'} = 'Active'; + } + my $status_select = &Apache::lonhtmlcommon::StatusOptions + ($env{'form.Status'}); + my $cid =$env{'request.course.id'}; + my $cdom=$env{'course.'.$cid.'.domain'}; + my $cnum=$env{'course.'.$cid.'.num'}; + # + # List course personnel + my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum); + # + if (! defined($env{'form.output'}) || + $env{'form.output'} !~ /^(csv|excel|html)$/ ) { + $env{'form.output'} = 'html'; + } + # + $r->print('
'.&Apache::loncommon::start_data_table()); + foreach my $role (sort keys %coursepersonnel) { + next if ($role =~ /^\s*$/); + $r->print(&Apache::loncommon::start_data_table_row(). + ''.$role.''); + foreach my $user (split(',',$coursepersonnel{$role})) { + my ($puname,$pudom)=split(':',$user); + $r->print(' '.&Apache::loncommon::aboutmewrapper( + &Apache::loncommon::plainname($puname, + $pudom), + $puname,$pudom)); + } + $r->print(''.&Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table()); + # + # Interface output + $r->print(''); + $r->print("

\n"); + if ($env{'form.action'} ne 'modifystudent') { + my %lt=&Apache::lonlocal::texthash('csv' => "CSV", + 'excel' => "Excel", + 'html' => 'HTML'); + my $output_selector = ''; + $r->print(&mt('Output Format: [_1]',$output_selector).(' 'x3)); } - if (vf.login[1].checked) { - foundatype=1; - if ((vf.intpwd.value=='') && (foundpwd==0)) { - alert('You need to specify the initial password'); - return; + $r->print(&mt('Student Status: [_1]',$status_select)."\n"); + $r->print(''. + "\n

\n"); + # + # Print the classlist + $r->print('

'.&mt('Current Class List').'

'); + my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist(); + if (! defined($classlist)) { + $r->print(&mt('There are no students currently enrolled.')."\n"); + } else { + # Print out the available choices + if ($env{'form.action'} eq 'modifystudent') { + &show_class_list($r,'view','modify', + $env{'form.Status'},$classlist,$keylist); + } else { + &show_class_list($r,$env{'form.output'},'aboutme', + $env{'form.Status'},$classlist,$keylist); } } - if (vf.login[2].checked) { - foundatype=1; - //An argument is not required +} + +# =================================================== Show student list to drop +sub show_class_list { + my ($r,$mode,$linkto,$statusmode,$classlist,$keylist)=@_; + my $cid=$env{'request.course.id'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $cnum = $env{'course.'.$cid.'.num'}; + my ($classgroups) = &Apache::loncoursedata::get_group_memberships( + $classlist,$keylist,$cdom,$cnum); + # + # Variables for excel output + my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format); + # + # Variables for csv output + my ($CSVfile,$CSVfilename); + # + my $sortby = $env{'form.sortby'}; + if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end|type)$/) { + $sortby = 'username'; + } + if (! exists($env{'form.displayphotos'})) { + $env{'form.displayphotos'} = 'off'; + } + my $displayphotos = $env{'form.displayphotos'}; + + # Print out header + unless ($mode eq 'autoenroll') { + $r->print(< +END + } + $r->print(< + +END + if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll') { + if ($linkto eq 'aboutme') { + $r->print(&mt("Select a user name to view the user's personal page.")); + } elsif ($linkto eq 'modify') { + $r->print(&mt("Select a user name to modify the student's information")); + } + my %lt=&Apache::lonlocal::texthash( + 'usrn' => "username", + 'dom' => "domain", + 'sn' => "student name", + 'sec' => "section", + 'grp' => "active groups", + 'start' => "start date", + 'end' => "end date", + 'type' => "enroll type/action", + 'photo' => "photo", + ); + unless ($mode eq 'autoenroll') { + $r->print(< + +END + } + if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) { + $r->print(' + + '); + } + $r->print(" +

+".&Apache::loncommon::start_data_table()." + + "); + if ($mode eq 'autoenroll') { + $r->print(" + $lt{'type'} + "); + } else { + $r->print(" +Count + "); + } + $r->print(< + $lt{'usrn'} + + $lt{'dom'} + + ID + + $lt{'sn'} + + $lt{'sec'} + + $lt{'start'} + + $lt{'end'} + + $lt{'grp'} + +END + if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) { + my %photo_options = &Apache::lonlocal::texthash( + 'on' => 'Show', + 'off' => 'Hide', + ); + my $photochg = 'on'; + if ($displayphotos eq 'on') { + $photochg = 'off'; + } + $r->print(' '."\n".' '. + ''. + $photo_options{$photochg}.' '.$lt{'photo'}."\n". + ' '."\n"); + } + $r->print(" \n"); + } elsif ($mode eq 'csv') { + # + # Open a file + $CSVfilename = '/prtspool/'. + $env{'user.name'}.'_'.$env{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.csv'; + unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) { + $r->log_error("Couldn't open $CSVfilename for output $!"); + $r->print("Problems occured in writing the csv file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator."); + $CSVfile = undef; + } + # + # Write headers and data to file + if($statusmode eq 'Expired') { + print $CSVfile '"'.&mt('Students with expired roles').'"'."\n"; + } + if($statusmode eq 'Future') { + print $CSVfile '"'.&mt('Students with future roles').'"'."\n"; + } + if ($statusmode eq 'Any') { + print $CSVfile '"'.join('","',map { + &Apache::loncommon::csv_translate(&mt($_)) + } ("username","domain","ID","student name", + "section","start date","end date","status","active groups")) + .'"'."\n"; + } else { + print $CSVfile '"'.join('","',map { + &Apache::loncommon::csv_translate(&mt($_)) + } ("username","domain","ID","student name", + "section","start date","end date","active groups")).'"'."\n"; + } + } elsif ($mode eq 'excel') { + # Create the excel spreadsheet + ($excel_workbook,$excel_filename,$format) = + &Apache::loncommon::create_workbook($r); + return if (! defined($excel_workbook)); + $excel_sheet = $excel_workbook->addworksheet('classlist'); + # + my $description = 'Class List for '. + $env{'course.'.$env{'request.course.id'}.'.description'}; + $excel_sheet->write($row++,0,$description,$format->{'h1'}); + # + $excel_sheet->write($row++,0,["username","domain","ID", + "student name","section", + "start date","end date","status", + "active groups"], + $format->{'bold'}); + } + # + # Sort the students + my %index; + my $i; + foreach (@$keylist) { + $index{$_} = $i++; + } + $index{'groups'} = scalar(@{$keylist}); + my $index = $index{$sortby}; + my $second = $index{'username'}; + my $third = $index{'domain'}; + my @Sorted_Students = sort { + lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index]) + || + lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second]) + || + lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third]) + } (keys(%$classlist)); + my $studentcount = 0; + my $autocount = 0; + my $manualcount = 0; + my $unlockcount = 0; + my $lockcount = 0; + foreach my $student (@Sorted_Students) { + my $sdata = $classlist->{$student}; + my $groups = $classgroups->{$student}; + my $username = $sdata->[$index{'username'}]; + my $domain = $sdata->[$index{'domain'}]; + my $section = $sdata->[$index{'section'}]; + my $active_groups; + if (ref($groups->{active}) eq 'HASH') { + $active_groups = join(', ',keys(%{$groups->{'active'}})); + } + my $name = $sdata->[$index{'fullname'}]; + my $id = $sdata->[$index{'id'}]; + my $status = $sdata->[$index{'status'}]; + my $start = $sdata->[$index{'start'}]; + my $end = $sdata->[$index{'end'}]; + my $type = $sdata->[$index{'type'}]; + next if (($statusmode ne 'Any') && ($status ne $statusmode)); + if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') { + if (! defined($start) || $start == 0) { + $start = &mt('none'); + } else { + $start = &Apache::lonlocal::locallocaltime($start); + } + if (! defined($end) || $end == 0) { + $end = &mt('none'); + } else { + $end = &Apache::lonlocal::locallocaltime($end); + } + $r->print(&Apache::loncommon::start_data_table_row()); + if ($mode eq 'autoenroll') { + my $lockedtype = $sdata->[$index{'lockedtype'}]; + $studentcount++; + my $cellentry; + if ($type eq 'auto') { + $cellentry = ''.&mt('auto').' '; + $autocount ++; + } else { + $cellentry = '
'.&mt('manual').'
'; + $manualcount ++; + if ($lockedtype) { + $cellentry .= ''; + $unlockcount ++; + } else { + $cellentry .= ''; + $lockcount ++; + } + $cellentry .= '
'; + } + $r->print("$cellentry\n "); + } else { + $r->print("".(++$studentcount)."\n "); + } + if ($linkto eq 'nothing') { + $r->print($username); + } elsif ($linkto eq 'aboutme') { + $r->print(&Apache::loncommon::aboutmewrapper($username, + $username, + $domain)); + } elsif ($linkto eq 'modify') { + $r->print(''. + $username."\n"); + } + $r->print(<<"END"); + + $domain + $id + $name + $section + $start + $end + $active_groups +END + if ($env{'course.'.$env{'request.course.id'}. + '.internal.showphoto'}) { + if ($displayphotos eq 'on') { + my $imgurl = + &Apache::lonnet::retrievestudentphoto($domain, + $username,'gif', + 'thumbnail'); + + $r->print(' '); + } else { + $r->print('   '); + } + } + $r->print(&Apache::loncommon::end_data_table_row()); + } elsif ($mode eq 'csv') { + next if (! defined($CSVfile)); + # no need to bother with $linkto + if (! defined($start) || $start == 0) { + $start = &mt('none'); + } else { + $start = &Apache::lonlocal::locallocaltime($start); + } + if (! defined($end) || $end == 0) { + $end = &mt('none'); + } else { + $end = &Apache::lonlocal::locallocaltime($end); + } + my @line = (); + foreach ($username,$domain,$id,$name,$section,$start,$end) { + push @line,&Apache::loncommon::csv_translate($_); + } + if ($statusmode eq 'Any') { + push @line,&Apache::loncommon::csv_translate($status); + } + push @line,&Apache::loncommon::csv_translate($active_groups); + print $CSVfile '"'.join('","',@line).'"'."\n"; + } elsif ($mode eq 'excel') { + $excel_sheet->write($row,0,[$username,$domain,$id, + $name,$section]); + my $col = 5; + foreach my $time ($start,$end) { + if (defined($time) && $time != 0) { + $excel_sheet->write($row,$col++, + &Apache::lonstathelpers::calc_serial($time), + $format->{'date'}); + } else { + $excel_sheet->write($row,$col++,'none'); + } + } + $excel_sheet->write($row,$col++,$status); + $excel_sheet->write($row,$col++,$active_groups); + $row++; + } + } + if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') { + $r->print(&Apache::loncommon::end_data_table().'
'); + } elsif ($mode eq 'excel') { + $excel_workbook->close(); + $r->print('

'. + &mt('Your Excel spreadsheet').' '.&mt('is ready for download').'.

'."\n"); + } elsif ($mode eq 'csv') { + close($CSVfile); + $r->print(''. + &mt('Your CSV file').' is ready for download.'. + "\n"); + $r->rflush(); } - if (foundatype==0) { - alert('You need to set the login type'); + if ($mode eq 'autoenroll') { + return ($studentcount,$autocount,$manualcount,$lockcount,$unlockcount); + } + return; +} + + +# +# print out form for modification of a single students data +# +sub print_modify_student_form { + my $r = shift(); + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['sdom','sname']); + my $sname = $env{'form.sname'}; + my $sdom = $env{'form.sdom'}; + my $sortby = $env{'form.sortby'}; + # determine the students name information + my %info=&Apache::lonnet::get('environment', + ['firstname','middlename', + 'lastname','generation','id'], + $sdom, $sname); + my ($tmp) = keys(%info); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $r->print(''.&mt('Error').''. + '

'. + &mt('Unable to retrieve environment data for').' '.$sname. + &mt('in domain').' '.$sdom.'

'. + &mt('Please contact your LON-CAPA administrator regarding this situation.').'

'.&Apache::loncommon::end_page()); return; } - if (foundname==0) { message='No first and last name specified. '; } - if (foundid==0) { message+='No ID or student number field specified. '; } - if (foundsec==0) { message+='No section or group field specified. '; } - if (vf.startdate.value=='') { - message+='No starting date set. '; - } - if (vf.enddate.value=='') { - message+='No ending date set. '; - } - if ((vf.enddate.value!='') && (vf.startdate.value!='')) { - if (Math.round(vf.enddate.value)print('

'&mt('Error').'

'); + $r->print('

'.$starttime.'

'); + return; } - if (message!='') { - message+='Continue enrollment?'; - if (confirm(message)) { - pclose(); - vf.submit(); - } + # + # Deal with date forms + my $current_date_description = ''; + my $textdate = ''; + + if (! defined($starttime) || $starttime == 0) { + $current_date_description = &mt('Current Starting Date: not set'). + '
'; } else { - pclose(); - vf.submit(); - } + $current_date_description = + &mt('Current Starting Date: [_1]', + &Apache::lonlocal::locallocaltime($starttime)).'
'; + } + if (! defined($endtime) || $endtime == 0) { + $current_date_description.= &mt('Current Ending Date: not set'). + '
'; + } else { + $current_date_description.= + &mt('Current Ending Date: [_1]', + &Apache::lonlocal::locallocaltime($endtime)).'
'; + + } + my $date_table = &date_setting_table($starttime,$endtime); + # + if (! exists($env{'form.Status'}) || + $env{'form.Status'} !~ /^(Any|Expired|Active|Future)$/) { + $env{'form.Status'} = 'crap'; + } + # Make sure student is enrolled in course + my %lt=&Apache::lonlocal::texthash( + 'mef' => "Modify Enrollment for", + 'odcc' => "Only domain coordinators can change a users password.", + 'sn' => "Student Name", + 'fn' => "First", + 'mn' => "Middle", + 'ln' => "Last", + 'gen' => "Generation", + 'sid' => "Student ID", + 'disn' => "Disable ID/Student Number Safeguard and Force Change of Conflicting IDs (only do if you know what you are doing)", + 'sec' => "Section", + 'sm' => "Submit Modifications", + ); +# Check if section name is valid + my $section_check = §ion_check_js(); + $r->print(<<"END"); + +

+ +$lt{'odcc'} + +

+ + + + + + +

$lt{'mef'} $info{'firstname'} $info{'middlename'} +$info{'lastname'} $info{'generation'}, $sname\@$sdom

+

+$lt{'sn'} + + + +
$lt{'fn'}$lt{'mn'}$lt{'ln'}$lt{'gen'}
+ + + +
+

+$lt{'sid'}: +

+ +

+$lt{'sec'}: +

+

$current_date_description

+

$date_table

+ +END + $r->print(&Apache::loncommon::end_page()); + return; } -function setint(vf) { - if (vf.intpwd.value!='') { - vf.login[1].checked=true; - vf.krbdom.value=''; - vf.locarg.value=''; - } +# +# modify a single students section +# +sub modify_single_student { + my ($r) = @_; + # + # Remove non alphanumeric values from the section + $env{'form.section'} =~ s/\W//g; + # + # Do the date defaults first + my ($starttime,$endtime) = &get_dates_from_form(); + if ($env{'form.makedatesdefault'}) { + $r->print(&make_dates_default($starttime,$endtime)); + } + # Get the 'sortby' and 'Status' variables so the user goes back to their + # previous screen + my $sortby = $env{'form.sortby'}; + my $status = $env{'form.Status'}; + # + # We always need this information + my $slogin = $env{'form.slogin'}; + my $sdom = $env{'form.sdomain'}; + # + # Get the old data + my %old=&Apache::lonnet::get('environment', + ['firstname','middlename', + 'lastname','generation','id'], + $sdom, $slogin); + $old{'section'} = &Apache::lonnet::getsection($sdom,$slogin, + $env{'request.course.id'}); + my ($tmp) = keys(%old); + if ($tmp =~ /^(con_lost|error|no_such_host)/i) { + $r->print(&mt('There was an error determining the environment values for')." $slogin \@ $sdom."); + return; + } + undef $tmp; + # + # Get the new data + my $firstname = $env{'form.firstname'}; + my $middlename = $env{'form.middlename'}; + my $lastname = $env{'form.lastname'}; + my $generation = $env{'form.generation'}; + my $section = $env{'form.section'}; + my $courseid = $env{'request.course.id'}; + my $sid = $env{'form.id'}; + my $displayable_starttime = localtime($starttime); + my $displayable_endtime = localtime($endtime); + # + # check for forceid override + if ((defined($old{'id'})) && ($old{'id'} ne '') && + ($sid ne $old{'id'}) && (! exists($env{'form.forceid'}))) { + $r->print("".&mt('You changed the students id but did not disable the ID change safeguard. The students id will not be changed.').""); + $sid = $old{'id'}; + } + # + # talk to the user about what we are going to do + my %lt=&Apache::lonlocal::texthash( + 'mdu' => "Modifying data for user", + 'si' => "Student Information", + 'fd' => "Field", + 'ov' => "Old Value", + 'nv' => "New Value", + 'fn' => "First name", + 'mn' => "Middle name", + 'ln' => "Last name", + 'gen' => "Generation", + 'sec' => "Section", + 'ri' => "Role Information", + 'st' => "Start Time", + 'et' => "End Time", + ); + $r->print(<$lt{'mdu'} $slogin \@ $sdom +

$lt{'si'}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
$lt{'fd'} $lt{'ov'} $lt{'nv'}
$lt{'fn'} $old{'firstname'} $firstname
$lt{'mn'} $old{'middlename'} $middlename
$lt{'ln'} $old{'lastname'} $lastname
$lt{'gen'} $old{'generation'} $generation
ID $old{'id'} $sid
$lt{'sec'} $old{'section'} $section
+

$lt{'ri'}

+ + + +
$lt{'st'}: $displayable_starttime
$lt{'et'}: $displayable_endtime
+

+END + # + # Send request(s) to modify data (final undef is for 'desiredhost', + # which is a moot point because the student already has an account. + my $modify_section_results = &modifystudent($sdom,$slogin, + $env{'request.course.id'}, + $section,undef); + if ($modify_section_results !~ /^ok/) { + $r->print(&mt('An error occured during the attempt to change the section for this student.')."
"); + } + my $roleresults = &Apache::lonnet::modifystudent + ($sdom,$slogin,$sid,undef,undef,$firstname,$middlename,$lastname, + $generation,$section,$endtime,$starttime,$env{'form.forceid'}); + if ($roleresults eq 'refused' ) { + $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.')); + } elsif ($roleresults !~ /ok/) { + $r->print(&mt('An error occurred during the attempt to change the role information for this student.')."
". + &mt('The error reported was')." ". + $roleresults); + &Apache::lonnet::logthis("londropadd:failed attempt to modify student". + " data for ".$slogin." \@ ".$sdom." by ". + $env{'user.name'}." \@ ".$env{'user.domain'}. + ":".$roleresults); + } else { # everything is okay! + $r->print(&mt('Student information updated successfully.')."
". + &mt('The student must log out and log in again to see these changes.')); + } + my $Masd=&mt('Modify another students data'); + $r->print(<

+ + + +$Masd +END + $r->print(&Apache::loncommon::end_page()); + return; +} + +sub get_enrollment_data { + my ($sname,$sdomain) = @_; + my $courseid = $env{'request.course.id'}; + my $cdom = $env{'request.'.$courseid.'.domain'}; + my $cnum = $env{'request.'.$courseid.'.num'}; + my %roles = &Apache::lonnet::dump('roles',$sdomain,$sname); + my ($tmp) = keys(%roles); + # Bail out if we were unable to get the students roles + return ('error'.$tmp) if ($tmp =~ /^(con_lost|error|no_such_host)/i); + # Go through the roles looking for enrollment in this course + my ($end,$start) = (undef,undef); + my $section = ''; + my $count = scalar(keys(%roles)); + while (my ($course,$role) = each(%roles)) { + if ($course=~m{^/\Q$cdom\E/\Q$cnum\E/*\s*(\w+)*_st$} ) { + # + # Get active role + $section=$1; + (undef,$end,$start)=split(/\_/,$role); + my $now=time; + my $notactive=0; + if ($start) { + if ($now<$start) { $notactive=1; } + } + if ($end) { + if ($now>$end) { $notactive=1; } + } + unless ($notactive) { return ($start,$end,$section); } + } + } + return ($start,$end,$section); } -function setloc(vf) { - if (vf.locarg.value!='') { - vf.login[2].checked=true; - vf.krbdom.value=''; - vf.intpwd.value=''; - } -} +################################################# +################################################# -function clickkrb(vf) { - vf.krbdom.value='$krbdefdom'; - vf.intpwd.value=''; - vf.locarg.value=''; -} +=pod -function clickint(vf) { - vf.krbdom.value=''; - vf.locarg.value=''; -} +=item show_drop_list -function clickloc(vf) { - vf.krbdom.value=''; - vf.intpwd.value=''; -} +Display a list of students to drop +Inputs: - function pclose() { - parmwin=window.open("/adm/rat/empty.html","LONCAPAparms", - "height=350,width=350,scrollbars=no,menubar=no"); - parmwin.close(); - } +=over 4 - function pjump(type,dis,value,marker,ret,call) { - parmwin=window.open("/adm/rat/parameter.html?type="+escape(type) - +"&value="+escape(value)+"&marker="+escape(marker) - +"&return="+escape(ret) - +"&call="+escape(call)+"&name="+escape(dis),"LONCAPAparms", - "height=350,width=350,scrollbars=no,menubar=no"); +=item $r, Apache request - } +=item $classlist, hash pointer returned from loncoursedata::get_classlist(); - function dateset() { - if (document.studentform.pres_marker.value=='end') { - document.studentform.enddate.value= - document.studentform.pres_value.value; - } - if (document.studentform.pres_marker.value=='start') { - document.studentform.startdate.value= - document.studentform.pres_value.value; - } - pclose(); - } +=item $keylist, array pointer returned from loncoursedata::get_classlist() +which describes the order elements are stored in the %$classlist values. - -

Personal Data

-First Name:
-Middle Name:
-Last Name:
-Generation:

- -ID/Student Number:

- -Group/Section:

- -

Login Data

-Username:

-Domain:

-Note: login settings below will not take effect if the user already exists

- - -Kerberos authenticated with domain -

- -Internally authenticated (with initial password -) -

- -Local Authentication with argument - -

-

Starting and Ending Dates

- - - - - -Set Starting Date

- -Set Ending Date

-

ID/Student Number

- -Disable ID/Student Number Safeguard and Force Change of Conflicting IDs -(only do if you know what you are doing)

-
- -ENDSENROLL -} +=item $nosort, if true, sorting links are omitted. -# ========================================================= Menu Phase Two Drop +=back -sub menu_phase_two_drop { - my $r=shift; - my $cid=$ENV{'request.course.id'}; - my $classlst=&Apache::lonnet::reply - ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist', - $ENV{'course.'.$cid.'.home'}); - my %currentlist=(); - my $now=time; - unless ($classlst=~/^error\:/) { - foreach (split(/\&/,$classlst)) { - my ($name,$value)=split(/\=/,$_); - my ($end,$start)=split(/\:/, - &Apache::lonnet::unescape($value)); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - $currentlist{&Apache::lonnet::unescape($name)}=1; - } - } -# ----------------------------------------------------------- Print out choices - &show_drop_list($r,%currentlist); - } else { - $r->print( - '

Could not access classlist: '.$classlst. - '

'); - } +=cut + +################################################# +################################################# +sub show_drop_list { + my ($r,$classlist,$keylist,$nosort)=@_; + my $cid=$env{'request.course.id'}; + if (! exists($env{'form.sortby'})) { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['sortby']); + } + my $sortby = $env{'form.sortby'}; + if ($sortby !~ /^(username|domain|section|groups|fullname|id|start|end)$/) { + $sortby = 'username'; + } + my $cdom = $env{'course.'.$cid.'.domain'}; + my $cnum = $env{'course.'.$cid,'.num'}; + my ($classgroups) = &Apache::loncoursedata::get_group_memberships( + $classlist,$keylist,$cdom,$cnum); + # + my $action = "drop"; + $r->print(< + + + +

+ +END -sub show_drop_list { - my ($r,%currentlist)=@_; - my $cid=$ENV{'request.course.id'}; +my %lt=&Apache::lonlocal::texthash('usrn' => "username", + 'dom' => "domain", + 'sn' => "student name", + 'sec' => "section", + 'start' => "start date", + 'end' => "end date", + 'groups' => "active groups", + ); + if ($nosort) { + $r->print(&Apache::loncommon::start_data_table()); + $r->print(< +   + $lt{'usrn'} + $lt{'dom'} + ID + $lt{'sn'} + $lt{'sec'} + $lt{'start'} + $lt{'end'} + $lt{'groups'} + +END + + } else { + $r->print(&Apache::loncommon::start_data_table()); + $r->print(<  + + $lt{'usrn'} + + $lt{'dom'} + + ID + + $lt{'sn'} + + $lt{'sec'} + + $lt{'start'} + + $lt{'end'} + + $lt{'groups'} + + +END + } + # + # Sort the students + my %index; + my $i; + foreach (@$keylist) { + $index{$_} = $i++; + } + $index{'groups'} = scalar(@$keylist); + my $index = $index{$sortby}; + my $second = $index{'username'}; + my $third = $index{'domain'}; + my @Sorted_Students = sort { + lc($classlist->{$a}->[$index]) cmp lc($classlist->{$b}->[$index]) + || + lc($classlist->{$a}->[$second]) cmp lc($classlist->{$b}->[$second]) + || + lc($classlist->{$a}->[$third]) cmp lc($classlist->{$b}->[$third]) + } (keys(%$classlist)); + foreach my $student (@Sorted_Students) { + my $error; + my $sdata = $classlist->{$student}; + my $username = $sdata->[$index{'username'}]; + my $domain = $sdata->[$index{'domain'}]; + my $section = $sdata->[$index{'section'}]; + my $name = $sdata->[$index{'fullname'}]; + my $id = $sdata->[$index{'id'}]; + my $start = $sdata->[$index{'start'}]; + my $end = $sdata->[$index{'end'}]; + my $groups = $classgroups->{$student}; + my $active_groups; + if (ref($groups->{active}) eq 'HASH') { + $active_groups = join(', ',keys(%{$groups->{'active'}})); + } + if (! defined($start) || $start == 0) { + $start = &mt('none'); + } else { + $start = &Apache::lonlocal::locallocaltime($start); + } + if (! defined($end) || $end == 0) { + $end = &mt('none'); + } else { + $end = &Apache::lonlocal::locallocaltime($end); + } + my $status = $sdata->[$index{'status'}]; + next if ($status ne 'Active'); + # + $r->print(&Apache::loncommon::start_data_table_row()); + $r->print(<<"END"); + + $username + $domain + $id + $name + $section + $start + $end + $active_groups +END + $r->print(&Apache::loncommon::end_data_table_row()); + } + $r->print(&Apache::loncommon::end_data_table().'
'); + %lt=&Apache::lonlocal::texthash( + 'dp' => "Drop Students", + 'ca' => "check all", + 'ua' => "uncheck all", + ); + $r->print(<<"END"); +

+   + +

+END + return; +} - $r->print(''); - $r->print(''); - foreach (sort keys %currentlist) { - my ($sname,$sdom)=split(/\:/,$_); - my %reply=&Apache::lonnet::idrget($sdom,$sname); - my $ssec=&Apache::lonnet::usection($sdom,$sname,$cid); - my @reply=split(/[\&\=]/,&Apache::lonnet::reply( - 'get:'.$sdom.':'.$sname. - ':environment:firstname&middlename&lastname&generation', - &Apache::lonnet::homeserver($sname,$sdom))); - $r->print( - '\n"); - } - $r->print('
'. - $sname.''.$sdom.''. - $reply{$sname}.''. - &Apache::lonnet::unescape($reply[2]).' '. - &Apache::lonnet::unescape($reply[3]).', '. - &Apache::lonnet::unescape($reply[0]).' '. - &Apache::lonnet::unescape($reply[1]). - ''. - $ssec."

'); - $r->print(''); +# +# Print out the initial form to get the courselist file +# +sub print_first_courselist_upload_form { + my $r=shift; + my $str; + $str = ''; + $str .= ''; + $str .= ''; + $str .= "

".&mt('Upload a class list')."

\n"; + $str .= &Apache::loncommon::upfile_select_html(); + $str .= "

\n"; + $str .= ''."\n"; + $str .= '

\n"; + $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List", + &mt("How do I create a class list from a spreadsheet")). + "
\n"; + $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV", + &mt("How do I create a CSV file from a spreadsheet")). + "
\n"; + $str .= &Apache::loncommon::end_page(); + $r->print($str); + return; } # ================================================= Drop/Add from uploaded file - sub upfile_drop_add { my $r=shift; - - &load_tmp_file($r); - my @studentdata=&upfile_record_sep(); - - my @keyfields=split(/\,/,$ENV{'form.keyfields'}); - my $cid=$ENV{'request.course.id'}; - - my %fields=(); - for (my $i=0;$i<=$ENV{'form.nfields'};$i++) { - $fields{$ENV{'form.f'.$i}}=$keyfields[$i]; - } - my $startdate=$ENV{'form.startdate'}; - my $enddate=$ENV{'form.enddate'}; - if ($startdate=~/\D/) { $startdate=''; } - if ($enddate=~/\D/) { $enddate=''; } - my $domain=$ENV{'form.lcdomain'}; - my $amode=''; - my $genpwd=''; - if ($ENV{'form.login'} eq 'krb') { - $amode='krb4'; - $genpwd=$ENV{'form.krbdom'}; - } elsif ($ENV{'form.login'} eq 'int') { - $amode='internal'; - if ((defined($ENV{'form.intpwd'})) && ($ENV{'form.intpwd'})) { - $genpwd=$ENV{'form.intpwd'}; - } - } elsif ($ENV{'form.login'} eq 'loc') { - $amode='localauth'; - if ((defined($ENV{'form.locarg'})) && ($ENV{'form.locarg'})) { - $genpwd=$ENV{'form.locarg'}; - } - } - unless (($domain=~/\W/) || ($amode eq '')) { - $r->print('

Enrolling Students

'); - my $count=0; - my $flushc=0; - my %student=(); -# ----------------------------------------------------------- Get new classlist -# --------------------------------------------------------- Enroll new students - foreach (@studentdata) { - my %entries=&record_sep($_); - - unless (($entries{$fields{'username'}} eq '') || - (!defined($entries{$fields{'username'}}))) { - my $fname=''; my $mname=''; my $lname=''; my $gen=''; - if (defined($fields{'names'})) { - ($lname,$fname,$mname)= - ($entries{$fields{'names'}}=~/([^\,]+)\,\s*(\w+)\s*(.*)$/); - } else { - if (defined($fields{'fname'})) { - $fname=$entries{$fields{'fname'}}; - } - if (defined($fields{'mname'})) { - $mname=$entries{$fields{'mname'}}; - } - if (defined($fields{'lname'})) { - $lname=$entries{$fields{'lname'}}; - } - if (defined($fields{'gen'})) { - $gen=$entries{$fields{'gen'}}; - } - } - if ($entries{$fields{'username'}}=~/\W/) { - $r->print('

Unacceptable username: '. - $entries{$fields{'username'}}.' for user '. - $fname.' '.$mname.' '.$lname.' '.$gen.'

'); - } else { - my $sec=''; - my $username=$entries{$fields{'username'}}; - if (defined($fields{'sec'})) { - if (defined($entries{$fields{'sec'}})) { - $sec=$entries{$fields{'sec'}}; - } - } - my $id=''; - if (defined($fields{'id'})) { - if (defined($entries{$fields{'id'}})) { - $id=$entries{$fields{'id'}}; - } - $id=~tr/A-Z/a-z/; - } - my $password=''; - if ($genpwd) { - $password=$genpwd; - } else { - if (defined($fields{'ipwd'})) { - if ($entries{$fields{'ipwd'}}) { - $password=$entries{$fields{'ipwd'}}; - } - } - } - if ($password) { - &dropstudent($domain,$username,$cid,$sec); - my $reply=&Apache::lonnet::modifystudent( - $domain,$username,$id,$amode,$password, - $fname,$mname,$lname,$gen,$sec,$enddate,$startdate, - $ENV{'form.forceid'}); - unless ($reply eq 'ok') { - $r->print( - "

Error enrolling $username: $reply

"); + &Apache::loncommon::load_tmp_file($r); + my @studentdata=&Apache::loncommon::upfile_record_sep(); + if($env{'form.noFirstLine'}){shift(@studentdata);} + my @keyfields = split(/\,/,$env{'form.keyfields'}); + my $cid = $env{'request.course.id'}; + my %fields=(); + for (my $i=0; $i<=$env{'form.nfields'}; $i++) { + if ($env{'form.upfile_associate'} eq 'reverse') { + if ($env{'form.f'.$i} ne 'none') { + $fields{$keyfields[$i]}=$env{'form.f'.$i}; + } + } else { + $fields{$env{'form.f'.$i}}=$keyfields[$i]; + } + } + # + # Store the field choices away + foreach my $field (qw/username names + fname mname lname gen id sec ipwd email/) { + $env{'form.'.$field.'_choice'}=$fields{$field}; + } + &Apache::loncommon::store_course_settings('enrollment_upload', + { 'username_choice' => 'scalar', + 'names_choice' => 'scalar', + 'fname_choice' => 'scalar', + 'mname_choice' => 'scalar', + 'lname_choice' => 'scalar', + 'gen_choice' => 'scalar', + 'id_choice' => 'scalar', + 'sec_choice' => 'scalar', + 'ipwd_choice' => 'scalar', + 'email_choice' => 'scalar' }); + + # + my ($startdate,$enddate) = &get_dates_from_form(); + if ($env{'form.makedatesdefault'}) { + $r->print(&make_dates_default($startdate,$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_library_servers($domain); + if (! exists($home_servers{$desiredhost})) { + $r->print(''.&mt('Error').''. + &mt('Invalid home server specified')); + $r->print(&Apache::loncommon::end_page()); + return; + } + } + # Determine authentication mechanism + 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'; + if ((defined($env{'form.intarg'})) && ($env{'form.intarg'})) { + $genpwd=$env{'form.intarg'}; + } + } elsif ($env{'form.login'} eq 'loc') { + $amode='localauth'; + if ((defined($env{'form.locarg'})) && ($env{'form.locarg'})) { + $genpwd=$env{'form.locarg'}; + } + } + if ($amode =~ /^krb/) { + if (! defined($genpwd) || $genpwd eq '') { + $r->print(''. + &mt('Unable to enroll students').' '. + &mt('No Kerberos domain was specified.').'

'); + $amode = ''; # This causes the loop below to be skipped + } + } + if ( $domain eq &clean_domain($domain) + && ($amode ne '')) { + ####################################### + ## Enroll Students ## + ####################################### + $r->print('

'.&mt('Enrolling Students')."

\n

\n"); + my $count=0; + my $flushc=0; + my %student=(); + # Get information about course groups + my %curr_groups = &Apache::longroup::coursegroups(); + # Get new classlist + foreach (@studentdata) { + my %entries=&Apache::loncommon::record_sep($_); + # Determine student name + unless (($entries{$fields{'username'}} eq '') || + (!defined($entries{$fields{'username'}}))) { + my ($fname, $mname, $lname,$gen) = ('','','',''); + if (defined($fields{'names'})) { + ($lname,$fname,$mname)=($entries{$fields{'names'}}=~ + /([^\,]+)\,\s*(\w+)\s*(.*)$/); + } else { + if (defined($fields{'fname'})) { + $fname=$entries{$fields{'fname'}}; + } + if (defined($fields{'mname'})) { + $mname=$entries{$fields{'mname'}}; + } + if (defined($fields{'lname'})) { + $lname=$entries{$fields{'lname'}}; + } + if (defined($fields{'gen'})) { + $gen=$entries{$fields{'gen'}}; + } + } + if ($entries{$fields{'username'}} + ne &LONCAPA::clean_username($entries{$fields{'username'}})) { + $r->print('
'. + &mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]', + $entries{$fields{'username'}},$fname,$mname,$lname,$gen). + ''); + } else { + # determine section number + my $sec=''; + my $username=$entries{$fields{'username'}}; + if (defined($fields{'sec'})) { + if (defined($entries{$fields{'sec'}})) { + $sec=$entries{$fields{'sec'}}; + } + } + # remove non alphanumeric values from section + $sec =~ s/\W//g; + if ($sec eq "none" || $sec eq 'all') { + $r->print('
'. + &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a reserved word.', + $username,$sec,$fname,$mname,$lname,$gen)); + next; + } elsif (($sec ne '') && (exists($curr_groups{$sec}))) { + $r->print('
'. + &mt('[_1]: Unable to enroll: section name "[_2]" for user [_3] [_4] [_5] [_6] is a course group. Section names and group names must be distinct.', + $username,$sec,$fname,$mname,$lname,$gen)); + next; + } + # determine student id number + my $id=''; + if (defined($fields{'id'})) { + if (defined($entries{$fields{'id'}})) { + $id=$entries{$fields{'id'}}; + } + $id=~tr/A-Z/a-z/; + } + # determine email address + my $email=''; + if (defined($fields{'email'})) { + if (defined($entries{$fields{'email'}})) { + $email=$entries{$fields{'email'}}; + unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } + } + } + # determine student password + my $password=''; + if ($genpwd) { + $password=$genpwd; + } else { + if (defined($fields{'ipwd'})) { + if ($entries{$fields{'ipwd'}}) { + $password=$entries{$fields{'ipwd'}}; + } + } + } + # Clean up whitespace + foreach (\$domain,\$username,\$id,\$fname,\$mname, + \$lname,\$gen,\$sec) { + $$_ =~ s/(\s+$|^\s+)//g; + } + if ($password || $env{'form.login'} eq 'loc') { + &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'},$desiredhost, + $email); + if ($reply ne 'ok') { + $reply =~ s/^error://; + $r->print('
'. + &mt('[_1]: Unable to enroll: [_2]',$username,$reply)); } else { $count++; $flushc++; $student{$username}=1; @@ -947,142 +2314,280 @@ sub upfile_drop_add { $flushc=0; } } - } else { - $r->print( - "

No password for $username

"); - } - } - } - } - $r->print('

Processed Students: '.$count); -# --------------------------------------------------------------- Drop students - if ($ENV{'form.fullup'} eq 'yes') { - $r->print('

Dropping Students

'); -# ------------------------------------------------------- Get current classlist - my $classlst=&Apache::lonnet::reply - ('dump:'.$ENV{'course.'.$cid.'.domain'}.':'. - $ENV{'course.'.$cid.'.num'}.':classlist', - $ENV{'course.'.$cid.'.home'}); - my %currentlist=(); - my $now=time; - unless ($classlst=~/^error\:/) { - foreach (split(/\&/,$classlst)) { - my ($name,$value)=split(/\=/,$_); - my ($end,$start)=split(/\:/, - &Apache::lonnet::unescape($value)); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - $currentlist{&Apache::lonnet::unescape($name)}=1; - } - } -# ------------------------------------------------ Now got up-to-date classlist - foreach (@studentdata) { - my %entries=&record_sep($_); - unless (($entries{$fields{'username'}} eq '') || - (!defined($entries{$fields{'username'}}))) { - delete($currentlist{ - $entries{$fields{'username'}}.':'. - $domain}); - } - } -# ----------------------------------------------------------- Print out choices - &show_drop_list($r,%currentlist); - } else { - $r->print( - '

Could not access classlist: '.$classlst. - '

'); - } - } -# ------------------------------------------------------------------------ Done - - } + } else { + $r->print('
'. + &mt('[_1]: Unable to enroll. No password specified.',$username) + ); + } + } + } + } # end of foreach (@studentdata) + $r->print("

\n

\n".&mt('Processed [_1] student(s).',$count). + "

\n"); + $r->print("

\n". + &mt('If active, the new role will be available when the '. + 'students next log in to LON-CAPA.')."

\n"); + ##################################### + # Drop students # + ##################################### + if ($env{'form.fullup'} eq 'yes') { + $r->print('

'.&mt('Dropping Students')."

\n"); + # Get current classlist + my ($classlist,$keylist)=&Apache::loncoursedata::get_classlist(); + if (! defined($classlist)) { + $r->print(&mt('There are no students currently enrolled.'). + "\n"); + } else { + # Remove the students we just added from the list of students. + foreach (@studentdata) { + my %entries=&Apache::loncommon::record_sep($_); + unless (($entries{$fields{'username'}} eq '') || + (!defined($entries{$fields{'username'}}))) { + delete($classlist->{$entries{$fields{'username'}}. + ':'.$domain}); + } + } + # Print out list of dropped students. + &show_drop_list($r,$classlist,$keylist,'nosort'); + } + } + } # end of unless } # ================================================================== Phase four - sub drop_student_list { my $r=shift; my $count=0; - foreach (keys %ENV) { - if ($_=~/^form\.drop\:/) { - my ($dummy,$uname,$udom)=split(/\:/,$_); - &dropstudent($udom,$uname,$ENV{'request.course.id'}); - $r->print('Dropped '.$uname.' at '.$udom.'
'); + my @droplist = &Apache::loncommon::get_env_multiple('form.droplist'); + foreach (@droplist) { + my ($uname,$udom)=split(/\:/,$_); + # drop student + my $result = &modifystudent($udom,$uname,$env{'request.course.id'}); + if ($result eq 'ok' || $result eq 'ok:') { + $r->print(&mt('Dropped [_1]',$uname.'@'.$udom).'
'); $count++; + } else { + $r->print( + &mt('Error dropping [_1]:[_2]',$uname.'@'.$udom,$result). + '
'); } } - $r->print('

Dropped '.$count.' student(s).'); - $r->print('

Re-enrollment will re-activate data.'); + $r->print('

'.&mt('Dropped [_1] student(s).',$count).'

'); + $r->print('

'.&mt('Re-enrollment will re-activate data.')) if ($count); } -# ================================================================ Main Handler - -sub handler { - my $r=shift; +sub section_check_js { + my $groupslist; + my %curr_groups = &Apache::longroup::coursegroups(); + if (%curr_groups) { + $groupslist = join('","',sort(keys(%curr_groups))); + } + return <<"END"; +function validate(caller) { + var groups = new Array("$groupslist"); + var secname = caller.value; + if ((secname == 'all') || (secname == 'none')) { + alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name."); + return 'error'; + } + if (secname != '') { + for (var k=0; kheader_only) { - $r->content_type('text/html'); - $r->send_http_header; - return OK; - } +################################################################### +################################################################### -# ----------------------------------------------------- Needs to be in a course +=pod - if (($ENV{'request.course.fn'}) && - (&Apache::lonnet::allowed('cst',$ENV{'request.course.id'}))) { +=item &handler -# ------------------------------------------------------------------ Start page - $r->content_type('text/html'); - $r->send_http_header; - &header($r); - -# --------------------------------------------------- Phase one, initial screen - unless ($ENV{'form.phase'}) { - &menu_phase_one($r); - } -# ------------------------------------------------------------------- Phase two - if ($ENV{'form.phase'} eq 'two') { - if ($ENV{'form.fileupload'}) { - &menu_phase_two_upload($r); - } elsif ($ENV{'form.enroll'}) { - &menu_phase_two_enroll($r); - } elsif ($ENV{'form.drop'}) { - &menu_phase_two_drop($r); - } - } +The typical handler you see in all these modules. Takes $r, the +http request, as an argument. +The response to the request is governed by two form variables + form.action form.state response + --------------------------------------------------- + undefined undefined print main menu + upload undefined print courselist upload menu + upload got_file deal with uploaded file, + print the upload managing menu + upload enrolling enroll students based on upload + drop undefined print the classlist ready to drop + drop done drop the selected students + enrollstudent undefined print student username domain form + enrollstudent gotusername print single student enroll menu + enrollstudent enrolling enroll student + classlist undefined print html classlist + classlist csv print csv classlist + modifystudent undefined print classlist to select student to modify + modifystudent selected print modify student menu + modifystudent done make modifications to student record +=cut -# ----------------------------------------------------------------- Phase three - if ($ENV{'form.phase'} eq 'three') { - if ($ENV{'form.datatoken'}) { - &upfile_drop_add($r); - } - } -# ------------------------------------------------------------------ Phase four - if ($ENV{'form.phase'} eq 'four') { - &drop_student_list($r); - } -# ------------------------------------------------------------------ Phase four - if ($ENV{'form.phase'} eq 'five') { - &enroll_single_student($r); - } -# ------------------------------------------------------------------------- End - $r->print(''); - } else { -# ----------------------------- Not in a course, or not allowed to modify parms - $ENV{'user.error.msg'}= - "/adm/dropadd:cst:0:0:Cannot drop or add students"; - return HTTP_NOT_ACCEPTABLE; - } - return OK; +################################################################### +################################################################### +sub handler { + my $r=shift; + if ($r->header_only) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + return OK; + } + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['action','state']); + + &Apache::lonhtmlcommon::clear_breadcrumbs(); + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>"/adm/dropadd", + text=>"Enrollment Manager", + faq=>9,bug=>'Instructor Interface',}); + # Needs to be in a course + if (! ($env{'request.course.fn'})) { + # Not in a course + $env{'user.error.msg'}= + "/adm/dropadd:cst:0:0:Cannot manage or view course groups, ". + "or drop or add students"; + return HTTP_NOT_ACCEPTABLE; + } + # + my $view_permission = + &Apache::lonnet::allowed('vcl',$env{'request.course.id'}); + my $enrl_permission = + &Apache::lonnet::allowed('cst',$env{'request.course.id'}); + + my $grp_view_permission = + &Apache::lonnet::allowed('vcg',$env{'request.course.id'}); + my $grp_manage_permission = + &Apache::lonnet::allowed('mdg',$env{'request.course.id'}); + + + if (! $grp_view_permission && ! $grp_manage_permission && + ! $view_permission && ! $enrl_permission) { + $env{'user.error.msg'}= + "/adm/coursegroups:cst:0:0:Cannot manage or view course groups, ". + "or drop or add students"; + return HTTP_NOT_ACCEPTABLE; + } + + # + # Only output the header information if they did not request csv format + # + # Start page + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + $r->print(&header()); + # + # Main switch on form.action and form.state, as appropriate + if (! exists($env{'form.action'})) { + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Enrollment Manager')); + &print_main_menu($r,$enrl_permission,$view_permission,$grp_manage_permission, + $grp_view_permission); + } elsif ($env{'form.action'} eq 'upload' && $enrl_permission) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/dropadd?action=upload&state=', + text=>"Upload Classlist"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Upload Classlist', + 'Course_Create_Class_List')); + if (! exists($env{'form.state'})) { + &print_first_courselist_upload_form($r); + } elsif ($env{'form.state'} eq 'got_file') { + &print_upload_manager_form($r); + } elsif ($env{'form.state'} eq 'enrolling') { + if ($env{'form.datatoken'}) { + &upfile_drop_add($r); + } else { + # Hmmm, this is an error + } + } else { + &print_first_courselist_upload_form($r); + } + } elsif ($env{'form.action'} eq 'drop' && $enrl_permission) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/dropadd?action=drop', + text=>"Drop Students"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Drop Students', + 'Course_Drop_Student')); + if (! exists($env{'form.state'})) { + &print_drop_menu($r); + } elsif ($env{'form.state'} eq 'done') { + &drop_student_list($r); + } else { + &print_drop_menu($r); + } + } elsif ($env{'form.action'} eq 'enrollstudent' && $enrl_permission) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/dropadd?action=enrollstudent', + text=>"Enroll Student"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Enroll Student', + 'Course_Add_Student')); + if (! exists($env{'form.state'})) { + &get_student_username_domain_form($r); + } elsif ($env{'form.state'} eq 'gotusername') { + &print_enroll_single_student_form($r); + } elsif ($env{'form.state'} eq 'enrolling') { + &enroll_single_student($r); + } else { + &get_student_username_domain_form($r); + } + } elsif ($env{'form.action'} eq 'classlist' && $view_permission) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/dropadd?action=classlist', + text=>"View Classlist"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('View Classlist', + 'Course_View_Class_List')); + if (! exists($env{'form.state'})) { + &print_html_classlist($r,undef); + } elsif ($env{'form.state'} eq 'csv') { + &print_html_classlist($r,'csv'); + } elsif ($env{'form.state'} eq 'excel') { + &print_html_classlist($r,'excel'); + } else { + &print_html_classlist($r,undef); + } + } elsif ($env{'form.action'} eq 'modifystudent' && $enrl_permission) { + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/dropadd?action=modifystudent', + text=>"Modify Student Data"}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Modify Student Data', + 'Course_Modify_Student_Data')); + if (! exists($env{'form.state'})) { + &print_html_classlist($r); + } elsif ($env{'form.state'} eq 'selected') { + &print_modify_student_form($r); + } elsif ($env{'form.state'} eq 'done') { + &modify_single_student($r); + } else { + &print_html_classlist($r); + } + } else { + # We should not end up here, but I guess it is possible + &Apache::lonnet::logthis("Undetermined state in londropadd.pm. ". + "form.action = ".$env{'form.action'}. + "Someone should fix this."); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Enrollment Manager')); + &print_main_menu($r,$enrl_permission,$view_permission); + } + # + # Finish up + $r->print(''.&Apache::loncommon::end_page()); + return OK; } +################################################################### +################################################################### + 1; __END__ - -