--- loncom/interface/lonuserutils.pm 2008/01/20 22:25:05 1.50 +++ loncom/interface/lonuserutils.pm 2009/08/03 16:26:09 1.96 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.50 2008/01/20 22:25:05 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.96 2009/08/03 16:26:09 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -42,7 +42,7 @@ use LONCAPA qw(:DEFAULT :match); ############################################################### # Drop student from all sections of a course, except optional $csec sub modifystudent { - my ($udom,$unam,$courseid,$csec,$desiredhost)=@_; + my ($udom,$unam,$courseid,$csec,$desiredhost,$context)=@_; # 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 @@ -69,7 +69,7 @@ sub modifystudent { # dom name id mode pass f m l g ($udom,$unam,'', '', '',undef,undef,undef,undef, $section,time,undef,undef,$desiredhost,'','manual', - '',$courseid); + '',$courseid,'',$context); $result .= $reply.':'; } } @@ -86,7 +86,7 @@ sub modifystudent { sub modifyuserrole { my ($context,$setting,$changeauth,$cid,$udom,$uname,$uid,$umode,$upass, $first,$middle,$last,$gene,$sec,$forceid,$desiredhome,$email,$role, - $end,$start,$checkid) = @_; + $end,$start,$checkid,$inststatus) = @_; my ($scope,$userresult,$authresult,$roleresult,$idresult); if ($setting eq 'course' || $context eq 'course') { $scope = '/'.$cid; @@ -124,12 +124,13 @@ sub modifyuserrole { $userresult = &Apache::lonnet::modifyuser($udom,$uname,$uid,$umode,$upass,$first, $middle,$last,$gene,$forceid,$desiredhome, - $email,$role,$start,$end); + $email,$inststatus); if ($userresult eq 'ok') { if ($role ne '') { $role =~ s/_/\//g; $roleresult = &Apache::lonnet::assignrole($udom,$uname,$scope, - $role,$end,$start); + $role,$end,$start,'', + '',$context); } } return ($userresult,$authresult,$roleresult,$idresult); @@ -168,7 +169,7 @@ sub propagate_id_change { } sub update_classlist { - my ($cdom,$cnum,$udom,$uname,$user) = @_; + my ($cdom,$cnum,$udom,$uname,$user,$newend) = @_; my ($uid,$classlistentry); my $fullname = &Apache::lonnet::format_name($user->{'firstname'},$user->{'middlename'}, @@ -179,15 +180,37 @@ sub update_classlist { my @classinfo = split(/:/,$classhash{$uname.':'.$udom}); my $ididx=&Apache::loncoursedata::CL_ID() - 2; my $nameidx=&Apache::loncoursedata::CL_FULLNAME() - 2; + my $endidx = &Apache::loncoursedata::CL_END() - 2; + my $startidx = &Apache::loncoursedata::CL_START() - 2; for (my $i=0; $i<@classinfo; $i++) { - if ($i == $ididx) { + if ($i == $endidx) { + if ($newend ne '') { + $classlistentry .= $newend.':'; + } else { + $classlistentry .= $classinfo[$i].':'; + } + } elsif ($i == $startidx) { + if ($newend ne '') { + if ($classinfo[$i] > $newend) { + $classlistentry .= $newend.':'; + } else { + $classlistentry .= $classinfo[$i].':'; + } + } else { + $classlistentry .= $classinfo[$i].':'; + } + } elsif ($i == $ididx) { if (defined($user->{'id'})) { $classlistentry .= $user->{'id'}.':'; } else { $classlistentry .= $classinfo[$i].':'; } } elsif ($i == $nameidx) { - $classlistentry .= $fullname.':'; + if (defined($user->{'lastname'})) { + $classlistentry .= $fullname.':'; + } else { + $classlistentry .= $classinfo[$i].':'; + } } else { $classlistentry .= $classinfo[$i].':'; } @@ -305,9 +328,11 @@ sub print_upload_manager_header { &javascript_validations('upload',$krbdefdom,$password_choice,undef, $env{'request.role.domain'},$context, $groupslist); - my $checked=(($env{'form.noFirstLine'})?' checked="checked" ':''); - $r->print(&mt('Total number of records found in file: <b>[_1]</b>.',$distotal). - "<br />\n"); + my $checked=(($env{'form.noFirstLine'})?' checked="checked"':''); + $r->print('<p>' + .&mt('Total number of records found in file: [_1]' + ,'<b>'.$distotal.'</b>') + ."</p>\n"); $r->print('<div class="LC_left_float"><h3>'. &mt('Identify fields in uploaded list')."</h3>\n"); $r->print(&mt('Enter as many fields as you can.<br /> The system will inform you and bring you back to this page, <br /> if the data selected are insufficient to add users.')."<br />\n"); @@ -318,14 +343,17 @@ sub print_upload_manager_header { &hidden_input('fileupload',$env{'form.fileupload'}). &hidden_input('upfiletype',$env{'form.upfiletype'}). &hidden_input('upfile_associate',$env{'form.upfile_associate'})); - $r->print('<br /><input type="button" value="Reverse Association" '. - 'name="'.&mt('Reverse Association').'" '. - 'onClick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />'); - $r->print('<label><input type="checkbox" name="noFirstLine"'.$checked.'/>'. - &mt('Ignore First Line').'</label>'); + $r->print('<br /><label><input type="checkbox" name="noFirstLine"'.$checked.' />'. + &mt('Ignore First Line').'</label><br />'); + $r->print('<br /><input type="button" value="'.&mt('Reverse Association').'" '. + 'name="Reverse Association" '. + 'onclick="javascript:this.form.associate.value=\'Reverse Association\';submit(this.form);" />'); $r->print("<br /><br />\n". '<script type="text/javascript" language="Javascript">'."\n". - $javascript."\n".$javascript_validations.'</script>'); + '// <![CDATA['."\n". + $javascript."\n".$javascript_validations."\n". + '// ]]>'."\n". + '</script>'); } ############################################################### @@ -378,16 +406,20 @@ sub javascript_validations { 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 ID number field was not specified.', + snum => 'The optional student/employee ID field was not specified.', section => 'The optional section field was not specified.', - email => 'The optional email address field was not specified.', + email => 'The optional e-mail address field was not specified.', role => 'The optional role field was not specified.', + domain => 'The optional domain field was not specified.', continue => 'Continue adding users?', ); + if (($mode eq 'upload') && ($context eq 'domain')) { + $alert{'inststatus'} = &mt('The optional affiliation field was not specified'); + } my $function_name = <<"END"; $setsections_js -function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail) { +function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus) { END my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain); my $auth_checks; @@ -502,6 +534,32 @@ END } message+='$alert{'email'}'; } + if (foundrole==0) { + if (message!='') { + message+='\\n'; + } + message+='$alert{'role'}'; + } + if (founddomain==0) { + if (message!='') { + message+='\\n'; + } + message+='$alert{'domain'}'; + } +END + if (($mode eq 'upload') && ($context eq 'domain')) { + $optional_checks .= (<<END); + + if (foundinststatus==0) { + if (message!='') { + message+='\\n'; + } + message+='$alert{'inststatus'}'; + } +END + } + $optional_checks .= (<<END); + if (message!='') { message+= '\\n$alert{'continue'}'; if (confirm(message)) { @@ -531,6 +589,8 @@ function verify(vf,sec_caller) { var foundsec=0; var foundemail=0; var foundrole=0; + var founddomain=0; + var foundinststatus=0; var tw; for (i=0;i<=vf.nfields.value;i++) { tw=eval('vf.f'+i+'.selectedIndex'); @@ -541,8 +601,10 @@ function verify(vf,sec_caller) { if (tw==9) { foundpwd=1; } if (tw==10) { foundemail=1; } if (tw==11) { foundrole=1; } + if (tw==12) { founddomain=1; } + if (tw==13) { foundinststatus=1; } } - verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole); + verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus); } // @@ -563,6 +625,8 @@ function verify(vf,sec_caller) { // 9 = ipwd (password) // 10 = email address // 11 = role +// 12 = domain +// 13 = inststatus function flip(vf,tf) { var nw=eval('vf.f'+tf+'.selectedIndex'); @@ -626,6 +690,8 @@ function verify(vf,sec_caller) { var foundid=0; var foundsec=0; var foundrole=0; + var founddomain=0; + var foundinststatus=0; var tw; for (i=0;i<=vf.nfields.value;i++) { tw=eval('vf.f'+i+'.selectedIndex'); @@ -635,8 +701,10 @@ function verify(vf,sec_caller) { if (i==7 && tw!=0) { foundsec=1; } if (i==8 && tw!=0) { foundpwd=1; } if (i==9 && tw!=0) { foundrole=1; } + if (i==10 && tw!=0) { founddomain=1; } + if (i==13 && tw!=0) { foundinstatus=1; } } - verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole); + verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole,founddomain,foundinststatus); } function flip(vf,tf) { @@ -694,74 +762,137 @@ sub print_upload_manager_footer { my $locform = &Apache::loncommon::authform_local(%param); my $date_table = &date_setting_table(undef,undef,$context,undef, $formname,$permission); + my $Str = "\n".'<div class="LC_left_float">'; $Str .= &hidden_input('nfields',$i); $Str .= &hidden_input('keyfields',$keyfields); - $Str .= "<h3>".&mt('Login Type')."</h3>\n"; + + $Str .= '<h3>'.&mt('Options').'</h3>' + .&Apache::lonhtmlcommon::start_pick_box(); + + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Login Type')); if ($context eq 'domain') { - $Str .= '<p>'.&mt('Change authentication for existing users to these settings?').' <span class="LC_nobreak"><label><input type="radio" name="changeauth" value="No" checked="checked" />'.&mt('No').'</label> <label><input type="radio" name="changeauth" value="Yes" />'.&mt('Yes').'</label></span></p>'; + $Str .= '<p>' + .&mt('Change authentication for existing users in domain "[_1]" to these settings?' + ,$defdom) + .' <span class="LC_nobreak"><label>' + .'<input type="radio" name="changeauth" value="No" checked="checked" />' + .&mt('No').'</label>' + .' <label>' + .'<input type="radio" name="changeauth" value="Yes" />' + .&mt('Yes').'</label>' + .'</span></p>'; } else { - $Str .= "<p>\n". - &mt('Note: this will not take effect if the user already exists'). + $Str .= '<p class="LC_info">'."\n". + &mt('This will not take effect if the user already exists.'). &Apache::loncommon::help_open_topic('Auth_Options'). "</p>\n"; } - $Str .= &set_login($defdom,$krbform,$intform,$locform); + $Str .= &set_login($defdom,$krbform,$intform,$locform) + .&Apache::lonhtmlcommon::row_closure(); + my ($home_server_pick,$numlib) = &Apache::loncommon::home_server_form_item($defdom,'lcserver', 'default','hide'); +#FIXME: Broken?!? $home_server_pick returns empty value on prod (2.8.1) and on dev server. SB 2009-08-03 if ($numlib > 1) { - $Str .= '<h3>'.&mt('LON-CAPA Home Server for New Users')."</h3>\n". - &mt('LON-CAPA domain: [_1] with home server: [_2]',$defdom, - $home_server_pick).'<br />'; - } else { - $Str .= $home_server_pick; - } - $Str .= '<h3>'.&mt('Starting and Ending Dates'). - "</h3>\n"; - $Str .= "<p>\n".$date_table."</p>\n"; - if ($context eq 'domain') { - $Str .= '<h3>'.&mt('Settings for assigning roles:').'</h3>'."\n". - &mt('Pick the action to take on roles for these users:').'<br /><span class="LC_nobreak"><label><input type="radio" name="roleaction" value="norole" checked="checked" /> '.&mt('No role changes').'</label> <label><input type="radio" name="roleaction" value="domain" /> '.&mt('Add a domain role').'</label> <label><input type="radio" name="roleaction" value="course" /> '.&mt('Add a course role').'</label></span>'; + $Str .= &Apache::lonhtmlcommon::row_title( + &mt('LON-CAPA Home Server for New Users')) + .&mt('LON-CAPA domain: [_1] with home server:','"'.$defdom.'"') + .$home_server_pick + .&Apache::lonhtmlcommon::row_closure(); + } else { + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Home Server')) + .$home_server_pick + .&Apache::lonhtmlcommon::row_closure(); } - if ($context eq 'author') { - $Str .= '<h3>'.&mt('Default role')."</h3>\n". - &mt('Choose the role to assign to users without a value specified in the uploaded file'); + + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain')) + .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1) + .&Apache::lonhtmlcommon::row_closure(); + + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates')) + ."<p>\n".$date_table."</p>\n" + .&Apache::lonhtmlcommon::row_closure(); + + if ($context eq 'domain') { + $Str .= &Apache::lonhtmlcommon::row_title( + &mt('Settings for assigning roles')) + .&mt('Pick the action to take on roles for these users:').'<br />' + .'<span class="LC_nobreak"><label>' + .'<input type="radio" name="roleaction" value="norole" checked="checked" />' + .' '.&mt('No role changes').'</label>' + .' <label>' + .'<input type="radio" name="roleaction" value="domain" />' + .' '.&mt('Add a domain role').'</label>' + .' <label>' + .'<input type="radio" name="roleaction" value="course" />' + .' '.&mt('Add a course role').'</label>' + .'</span>'; + } elsif ($context eq 'author') { + $Str .= &Apache::lonhtmlcommon::row_title( + &mt('Default role')) + .&mt('Choose the role to assign to users without a value specified in the uploaded file.') } elsif ($context eq 'course') { - $Str .= '<h3>'.&mt('Default role and section')."</h3>\n". - &mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file'); + $Str .= &Apache::lonhtmlcommon::row_title( + &mt('Default role and section')) + .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.'); } else { - $Str .= '<br /><br /><b>'.&mt('Default role and/or section(s)')."</b><br />\n". - &mt('Role and/or section(s) for users without values specified in the uploaded file.'); + $Str .= &Apache::lonhtmlcommon::row_title( + &mt('Default role and/or section(s)')) + .&mt('Role and/or section(s) for users without values specified in the uploaded file.'); } - $Str .= '<br />'; if (($context eq 'domain') || ($context eq 'author')) { + $Str .= '<br />'; my ($options,$cb_script,$coursepick) = &default_role_selector($context,1); if ($context eq 'domain') { - $Str .= '<span class="LC_role_level">'.&mt('Domain Level').'</span><br />'.$options.'<br /><br /><span class="LC_role_level">'.&mt('Course Level').'</span><br />'.$cb_script.$coursepick; + $Str .= '<p>' + .'<b>'.&mt('Domain Level').'</b><br />' + .$options + .'</p><p>' + .'<b>'.&mt('Course Level').'</b>' + .'</p>' + .$cb_script.$coursepick + .&Apache::lonhtmlcommon::row_closure(); } elsif ($context eq 'author') { - $Str .= $options; + $Str .= $options + .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box } } else { my ($cnum,$cdom) = &get_course_identity(); my $rowtitle = &mt('section'); my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle, $permission,$context,'upload'); - $Str .= $secbox."<h3>".&mt('Full Update')."</h3>\n". - '<p><label><input type="checkbox" name="fullup" value="yes">'. - ' '.&mt('Display students with current/future access who are not in the uploaded file.').'</label><br />'.&mt('Students selected from this list can be dropped.').'</p>'."\n"; + $Str .= $secbox + .&Apache::lonhtmlcommon::row_closure(); + + $Str .= &Apache::lonhtmlcommon::row_title(&mt('Full Update')) + .'<label><input type="checkbox" name="fullup" value="yes" />'. + ' '.&mt('Display students with current/future access who are not in the uploaded file.') + .'</label><br />' + .&mt('Students selected from this list can be dropped.') + .&Apache::lonhtmlcommon::row_closure(); } if ($context eq 'course' || $context eq 'domain') { $Str .= &forceid_change($context); } - $Str .= '</div><div class="LC_clear_float_footer"><br /><input type="button"'. - 'onClick="javascript:verify(this.form,this.form.csec)" '. - 'value="Update Users" />'."<br />\n"; - if ($context eq 'course') { - $Str .= &mt('Note: for large courses, this operation may be time '. - 'consuming'); - } + + $Str .= &Apache::lonhtmlcommon::end_pick_box(); $Str .= '</div>'; + + # Footer + $Str .= '<div class="LC_clear_float_footer">' + .'<hr />'; + if ($context eq 'course') { + $Str .= '<p class="LC_info">' + .&mt('Note: For large courses, this operation may be time consuming.') + .'</p>'; + } + $Str .= '<p><input type="button"' + .' onclick="javascript:verify(this.form,this.form.csec)"' + .' value="'.&mt('Update Users').'" />' + .'</p>'."\n" + .'</div>'; $r->print($Str); return; } @@ -769,18 +900,18 @@ sub print_upload_manager_footer { sub forceid_change { my ($context) = @_; my $output = - "<h3>".&mt('ID/Student Number')."</h3>\n". - "<p>\n".'<label><input type="checkbox" name="forceid" value="yes">'. - &mt('Disable ID/Student Number Safeguard and Force Change '. - 'of Conflicting IDs').'</label><br />'."\n". - &mt('(only do if you know what you are doing.)')."\n"; + &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID')) + .'<label><input type="checkbox" name="forceid" value="yes" />' + .&mt('Disable Student/Employee ID Safeguard and force change of conflicting IDs') + .'</label><br />'."\n" + .&mt('(only do if you know what you are doing.)')."\n"; if ($context eq 'domain') { $output .= '<br /><label><input type="checkbox" name="recurseid"'. - ' value="yes">'. - &mt('Update ID/Student Number in courses in which user is Active/Future student,<br />(if forcing change).'). + ' value="yes" />'. + &mt('Update student/employee ID in courses in which user is active/future student,[_1](if forcing change).','<br />'). '</label>'."\n"; } - $output .= '</p>'; + $output .= &Apache::lonhtmlcommon::row_closure(1); # last row in pick_box return $output; } @@ -817,6 +948,8 @@ sub print_upload_manager_form { 'ipwd_choice' => 'scalar', 'email_choice' => 'scalar', 'role_choice' => 'scalar', + 'domain_choice' => 'scalar', + 'inststatus_choice' => 'scalar', }; my $defdom = $env{'request.role.domain'}; if ($context eq 'course') { @@ -843,11 +976,13 @@ sub print_upload_manager_form { ['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'}], + ['id', &mt('Student/Employee ID'),$env{'form.id_choice'}], ['sec', &mt('Section'), $env{'form.sec_choice'}], ['ipwd', &mt('Initial Password'),$env{'form.ipwd_choice'}], ['email',&mt('E-mail Address'), $env{'form.email_choice'}], - ['role',&mt('Role'), $env{'form.role_choice'}]); + ['role',&mt('Role'), $env{'form.role_choice'}], + ['domain',&mt('Domain'), $env{'form.domain_choice'}], + ['inststatus',&mt('Affiliation'), $env{'form.inststatus_choice'}]); if ($env{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($r,\@records); $i=&Apache::loncommon::csv_print_select_table($r,\@records, @@ -924,8 +1059,15 @@ sub setup_date_selectors { sub get_dates_from_form { - my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate'); - my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate'); + my ($startname,$endname) = @_; + if ($startname eq '') { + $startname = 'startdate'; + } + if ($endname eq '') { + $endname = 'enddate'; + } + my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname); + my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname); if ($env{'form.no_end_date'}) { $enddate = 0; } @@ -958,7 +1100,7 @@ sub date_setting_table { } my $perpetual = '<span class="LC_nobreak"><label><input type="checkbox" name="no_end_date"'; if (defined($endtime) && $endtime == 0) { - $perpetual .= ' checked'; + $perpetual .= ' checked="checked"'; } $perpetual.= ' /> '.&mt('no ending date').'</label></span>'; if ($mode eq 'create_enrolldates') { @@ -1043,7 +1185,7 @@ sub default_role_selector { '<th>'.$lt{'grs'}.'</th>'. &Apache::loncommon::end_data_table_header_row(). &Apache::loncommon::start_data_table_row()."\n". - '<td><input type="text" name="coursedesc" value="" onFocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc',''".')" /></td>'."\n". + '<td><input type="text" name="coursedesc" value="" onfocus="this.blur();opencrsbrowser('."'studentform','dccourse','dcdomain','coursedesc',''".')" /></td>'."\n". '<td><select name="courserole">'."\n". &default_course_roles($context,$checkpriv,%customroles)."\n". '</select></td><td>'. @@ -1236,49 +1378,36 @@ sub print_userlist { 'html' => 'HTML'); my $output_selector = '<select size="1" name="output" >'; foreach my $outputformat ('html','csv','excel') { - my $option = '<option value="'.$outputformat.'" '; + my $option = '<option value="'.$outputformat.'"'; if ($outputformat eq $env{'form.output'}) { - $option .= 'selected '; + $option .= ' selected="selected"'; } $option .='>'.$lt{$outputformat}.'</option>'; $output_selector .= "\n".$option; } $output_selector .= '</select>'; - $r->print('<label>'.&mt('Output Format: [_1]',$output_selector).'</label>'.(' 'x3)); - } - $r->print('<label>'.&mt('User Status: [_1]',$status_select).'</label>'.(' 'x3)."\n"); + $r->print('<label><span class="LC_nobreak">' + .&mt('Output Format: [_1]',$output_selector) + .'</span></label>'.(' 'x3)); + } + $r->print('<label><span class="LC_nobreak">' + .&mt('User Status: [_1]',$status_select) + .'</span></label>'.(' 'x3)."\n"); my $roleselected = ''; if ($env{'form.showrole'} eq 'Any') { - $roleselected = ' selected="selected" '; + $roleselected = ' selected="selected"'; } - my ($role_select,$cnum,$cdom); - if ($context eq 'domain') { - $role_select = &domain_roles_select(); - $r->print('<label>'.&mt('Role Type: [_1]',$role_select).'</label>'); - } else { - $role_select = '<select name="showrole">'."\n". - '<option value="Any" '.$roleselected.'>'. - &mt('Any role').'</option>'; - my @poss_roles = &curr_role_permissions($context); - foreach my $role (@poss_roles) { - $roleselected = ''; - if ($role eq $env{'form.showrole'}) { - $roleselected = ' selected="selected" '; - } - my $plrole; - if ($role eq 'cr') { - $plrole = &mt('Custom role'); - } else { - $plrole=&Apache::lonnet::plaintext($role); - } - $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>'; - } - $role_select .= '</select>'; - $r->print('<label>'.&mt('Role: [_1]',$role_select).'</label>'); - if ($context eq 'course') { - ($cnum,$cdom) = &get_course_identity(); - $r->print(§ion_group_filter($cnum,$cdom)); - } + my ($cnum,$cdom); + $r->print(&role_filter($context)); + if ($context eq 'course') { + ($cnum,$cdom) = &get_course_identity(); + $r->print(§ion_group_filter($cnum,$cdom)); + } + if ($env{'form.phase'} eq '') { + $r->print('<br /><br />'.&list_submit_button(&mt('Display List of Users')). + "\n</p>\n". + '<input type="hidden" name="phase" value="" /></form>'); + return; } if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) { $r->print(' '.&list_submit_button(&mt('Update Display')). @@ -1309,7 +1438,9 @@ sub print_userlist { if ($context eq 'course') { if (($env{'form.showrole'} eq 'st') || ($env{'form.showrole'} eq 'Any')) { my $classlist = &Apache::loncoursedata::get_classlist(); - %userlist = %{$classlist}; + if (ref($classlist) eq 'HASH') { + %userlist = %{$classlist}; + } } if ($env{'form.showrole'} ne 'st') { my $showroles; @@ -1443,13 +1574,55 @@ sub print_userlist { $permission,$env{'form.Status'},\%userlist,$keylist); } if (!$usercount) { - $r->print('<br />'.&mt('There are no users matching the search criteria.')); + $r->print('<br /><span class="LC_warning">' + .&mt('There are no users matching the search criteria.') + .'</span>' + ); } } $r->print('<input type="hidden" name="phase" value="'. $env{'form.phase'}.'" /></form>'); } +sub role_filter { + my ($context) = @_; + my $output; + my $roleselected = ''; + if ($env{'form.showrole'} eq 'Any') { + $roleselected = ' selected="selected"'; + } + my ($role_select); + if ($context eq 'domain') { + $role_select = &domain_roles_select(); + $output = '<label><span class="LC_nobreak">' + .&mt('Role Type: [_1]',$role_select) + .'</span></label>'; + } else { + $role_select = '<select name="showrole">'."\n". + '<option value="Any" '.$roleselected.'>'. + &mt('Any role').'</option>'; + my @poss_roles = &curr_role_permissions($context); + foreach my $role (@poss_roles) { + $roleselected = ''; + if ($role eq $env{'form.showrole'}) { + $roleselected = ' selected="selected"'; + } + my $plrole; + if ($role eq 'cr') { + $plrole = &mt('Custom role'); + } else { + $plrole=&Apache::lonnet::plaintext($role); + } + $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>'; + } + $role_select .= '</select>'; + $output = '<label><span class="LC_nobreak">' + .&mt('Role: [_1]',$role_select) + .'</span></label>'; + } + return $output; +} + sub section_group_filter { my ($cnum,$cdom) = @_; my @filters; @@ -1489,7 +1662,7 @@ sub section_group_filter { foreach my $option ('all','none',@options) { $currsel = ''; if ($env{'form.'.$name{$item}} eq $option) { - $currsel = ' selected="selected" '; + $currsel = ' selected="selected"'; } $markup .= ' <option value="'.$option.'"'.$currsel.'>'; if (($option eq 'all') || ($option eq 'none')) { @@ -1513,6 +1686,10 @@ sub list_submit_button { sub gather_userinfo { my ($context,$format,$userlist,$indexhash,$userinfo,$rolehash,$permission) = @_; + my $viewablesec; + if ($context eq 'course') { + $viewablesec = &viewable_section($permission); + } foreach my $item (keys(%{$rolehash})) { my %userdata; if ($context eq 'author') { @@ -1522,7 +1699,6 @@ sub gather_userinfo { &build_user_record($context,\%userdata,$userinfo,$indexhash, $item,$userlist); } elsif ($context eq 'course') { - my $viewablesec = &viewable_section($permission); ($userdata{'username'},$userdata{'domain'},$userdata{'role'}, $userdata{'section'}) = split(/:/,$item,-1); ($userdata{'start'},$userdata{'end'})=split(/:/,$rolehash->{$item}); @@ -1840,7 +2016,10 @@ sub process_date_info { } sub show_users_list { - my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist)=@_; + my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname)=@_; + if ($formname eq '') { + $formname = 'studentform'; + } # # Variables for excel output my ($excel_workbook, $excel_sheet, $excel_filename,$row,$format); @@ -1855,6 +2034,9 @@ sub show_users_list { } else { push(@sortable,'extent'); } + if ($mode eq 'pickauthor') { + @sortable = ('username','fullname','email','status'); + } if (!grep(/^\Q$sortby\E$/,@sortable)) { $sortby = 'username'; } @@ -1879,6 +2061,7 @@ sub show_users_list { if ($env{'course.'.$cid.'.internal.showphoto'}) { $r->print(' <script type="text/javascript"> +// <![CDATA[ function photowindow(photolink) { var title = "Photo_Viewer"; var options = "scrollbars=1,resizable=1,menubar=0"; @@ -1886,6 +2069,7 @@ function photowindow(photolink) { stdeditbrowser = open(photolink,title,options,"1"); stdeditbrowser.focus(); } +// ]]> </script> '); } @@ -1895,121 +2079,42 @@ function photowindow(photolink) { END } } - if ($mode ne 'autoenroll') { + if ($mode ne 'autoenroll' && $mode ne 'pickauthor') { my $check_uncheck_js = &Apache::loncommon::check_uncheck_jscript(); - my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox"); - my $singconfirm = &mt(' for a single user?'); - my $multconfirm = &mt(' for multiple users?'); my $date_sec_selector = &date_section_javascript($context,$setting,$statusmode); - my %lt = &Apache::lonlocal::texthash( - acwi => 'Access will be set to start immediately', - asyo => 'as you did not select an end date in the pop-up window', - accw => 'Access will be set to continue indefinitely', - asyd => 'as you did not select an end date in the pop-up window', - sewi => "Sections will be switched to 'No section'", - ayes => "as you either selected the 'No section' option", - oryo => 'or you did not select a section in the pop-up window', - arol => 'A role with no section will be added', - swbs => 'Sections will be switched to:', - rwba => 'Roles will be added for section(s):', - ); + my $verify_action_js = &bulkaction_javascript($formname); $r->print(<<END); <script type="text/javascript" language="Javascript"> +// <![CDATA[ $check_uncheck_js -function verify_action (field) { - var numchecked = 0; - var singconf = '$singconfirm'; - var multconf = '$multconfirm'; - if (field.length > 0) { - for (i = 0; i < field.length; i++) { - if (field[i].checked == true) { - numchecked ++; - } - } - } else { - if (field.checked == true) { - numchecked ++; - } - } - if (numchecked == 0) { - alert("$alert"); - } - else { - var message = document.studentform.bulkaction[document.studentform.bulkaction.selectedIndex].text; - var choice = document.studentform.bulkaction[document.studentform.bulkaction.selectedIndex].value; - if (numchecked == 1) { - message += singconf; - } - else { - message += multconf; - } - if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') { - var datemsg = ''; - if ((document.studentform.startdate_month.value == '') && - (document.studentform.startdate_day.value == '') && - (document.studentform.startdate_year.value == '')) { - datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n"; - } - if ((document.studentform.enddate_month.value == '') && - (document.studentform.enddate_day.value == '') && - (document.studentform.enddate_year.value == '')) { - datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n"; - } - if (datemsg != '') { - message += "\\n"+datemsg; - } - } - if (choice == 'chgsec') { - var rolefilter = document.studentform.showrole.options[document.studentform.showrole.selectedIndex].value; - var retained = document.studentform.retainsec.value; - var secshow = document.studentform.newsecs.value; - if (secshow == '') { - if (rolefilter == 'st' || retained == 0 || retained == "") { - message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n"; - } else { - message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n"; - } - } else { - if (rolefilter == 'st' || retained == 0 || retained == "") { - message += "\\n\\n$lt{'swbs'} "+secshow+".\\n"; - } else { - message += "\\n\\n$lt{'rwba'} "+secshow+".\\n"; - } - } - } - if (confirm(message)) { - document.studentform.phase.value = 'bulkchange'; - document.studentform.submit(); - } - } -} +$verify_action_js function username_display_launch(username,domain) { var target; - for (var i=0; i<document.studentform.usernamelink.length; i++) { - if (document.studentform.usernamelink[i].checked) { - target = document.studentform.usernamelink[i].value; + for (var i=0; i<document.$formname.usernamelink.length; i++) { + if (document.$formname.usernamelink[i].checked) { + target = document.$formname.usernamelink[i].value; } } if (target == 'modify') { - if (document.studentform.userwin.checked == true) { + if (document.$formname.userwin.checked == true) { var url = '/adm/createuser?srchterm='+username+'&srchdomain='+domain+'&phase=get_user_info&action=singleuser&srchin=dom&srchby=uname&srchtype=exact&popup=1'; var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no'; modifywin = window.open(url,'',options,1); modifywin.focus(); return; } else { - document.studentform.srchterm.value=username; - document.studentform.srchdomain.value=domain; - document.studentform.phase.value='get_user_info'; - document.studentform.action.value = 'singleuser'; - document.studentform.submit(); + document.$formname.srchterm.value=username; + document.$formname.srchdomain.value=domain; + document.$formname.phase.value='get_user_info'; + document.$formname.action.value = 'singleuser'; + document.$formname.submit(); } } if (target == 'aboutme') { - if (document.studentform.userwin.checked == true) { + if (document.$formname.userwin.checked == true) { var url = '/adm/'+domain+'/'+username+'/aboutme?popup=1'; var options = 'height=600,width=800,resizable=yes,scrollbars=yes,location=no,menubar=no,toolbar=no'; aboutmewin = window.open(url,'',options,1); @@ -2020,6 +2125,7 @@ function username_display_launch(usernam } } } +// ]]> </script> $date_sec_selector <input type="hidden" name="state" value="$env{'form.state'}" /> @@ -2041,47 +2147,51 @@ END 'status' => "status", 'role' => "role", 'type' => "enroll type/action", - 'email' => "email address", - 'clicker' => "clicker id", + 'email' => "e-mail address", 'photo' => "photo", 'extent' => "extent", - 'go' => "go", 'pr' => "Proceed", 'ca' => "check all", 'ua' => "uncheck all", 'ac' => "Action to take for selected users", - 'link' => "Behavior of username links", - 'aboutme' => "Display a user's personal page", + 'link' => "Behavior of clickable username link for each user", + 'aboutme' => "Display a user's personal information page", 'owin' => "Open in a new window", 'modify' => "Modify a user's information", + 'clicker' => "Clicker-ID", ); if ($context eq 'domain' && $env{'form.roletype'} eq 'course') { $lt{'extent'} = &mt('Course(s): description, section(s), status'); } elsif ($context eq 'author') { $lt{'extent'} = &mt('Author'); } - my @cols = ('username','domain','id','fullname'); - if ($context eq 'course') { - push(@cols,'section'); - } - if (!($context eq 'domain' && $env{'form.roletype'} eq 'course')) { - push(@cols,('start','end')); - } - if ($env{'form.showrole'} eq 'Any' || $env{'form.showrole'} eq 'cr') { - push(@cols,'role'); - } - if ($context eq 'domain' && ($env{'form.roletype'} eq 'author' || - $env{'form.roletype'} eq 'course')) { - push (@cols,'extent'); - } - if (($statusmode eq 'Any') && - (!($context eq 'domain' && $env{'form.roletype'} eq 'course'))) { - push(@cols,'status'); - } - if ($context eq 'course') { - push(@cols,'groups'); + my @cols; + if ($mode eq 'pickauthor') { + @cols = ('username','fullname','status','email'); + } else { + @cols = ('username','domain','id','fullname'); + if ($context eq 'course') { + push(@cols,'section'); + } + if (!($context eq 'domain' && $env{'form.roletype'} eq 'course')) { + push(@cols,('start','end')); + } + if ($env{'form.showrole'} eq 'Any' || $env{'form.showrole'} eq 'cr') { + push(@cols,'role'); + } + if ($context eq 'domain' && ($env{'form.roletype'} eq 'author' || + $env{'form.roletype'} eq 'course')) { + push (@cols,'extent'); + } + if (($statusmode eq 'Any') && + (!($context eq 'domain' && $env{'form.roletype'} eq 'course'))) { + push(@cols,'status'); + } + if ($context eq 'course') { + push(@cols,'groups'); + } + push(@cols,'email'); } - push(@cols,'email'); my $rolefilter = $env{'form.showrole'}; if ($env{'form.showrole'} eq 'cr') { @@ -2093,13 +2203,13 @@ END if ($mode ne 'autoenroll') { $results_description = &results_header_row($rolefilter,$statusmode, $context,$permission,$mode); - $r->print('<b>'.$results_description.'</b><br />'); + $r->print('<b>'.$results_description.'</b><br /><br />'); } my ($output,$actionselect,%canchange,%canchangesec); - if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll') { - if ($mode ne 'autoenroll') { + if ($mode eq 'html' || $mode eq 'view' || $mode eq 'autoenroll' || $mode eq 'pickauthor') { + if ($mode ne 'autoenroll' && $mode ne 'pickauthor') { if ($permission->{'cusr'}) { - $actionselect = &select_actions($context,$setting,$statusmode); + $actionselect = &select_actions($context,$setting,$statusmode,$formname); } $r->print(<<END); <input type="hidden" name="srchby" value="uname" /> @@ -2108,33 +2218,12 @@ END <input type="hidden" name="srchterm" value="" /> <input type="hidden" name="srchdomain" value="" /> END - $output = '<p>'; - my @linkdests = ('aboutme'); - if ($permission->{'cusr'}) { - unshift (@linkdests,'modify'); - } - $output .= '<span class="LC_nobreak">'.$lt{'link'}.': '; - my $usernamelink = $env{'form.usernamelink'}; - if ($usernamelink eq '') { - $usernamelink = 'aboutme'; - } - foreach my $item (@linkdests) { - my $checkedstr = ''; - if ($item eq $usernamelink) { - $checkedstr = ' checked="checked" '; - } - $output .= '<label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.'> '.$lt{$item}.'</label> '; - } - my $checkwin; - if ($env{'form.userwin'}) { - $checkwin = 'checked = "checked"'; - } - $output .= ' <input type="checkbox" name="userwin" value="1" $checkwin />'.$lt{'owin'}.'</span><br />'; if ($actionselect) { $output .= <<"END"; -$lt{'ac'}: $actionselect <input type="button" value="$lt{'go'}" onclick="javascript:opendatebrowser(this.form,'studentform','go')" /></p> -<p><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.actionlist)" /> -<input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.actionlist)" /><br /><br /><input type="button" value="$lt{'pr'}" onclick="javascript:verify_action(document.studentform.actionlist)" /> +<div class="LC_left_float"><fieldset><legend>$lt{'ac'}</legend> +$actionselect +<br/><br /><input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.$formname.actionlist)" /> +<input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.$formname.actionlist)" /><br /><input type="button" value="$lt{'pr'}" onclick="javascript:verify_action('actionlist')" /></fieldset></div> END my @allroles; if ($env{'form.showrole'} eq 'Any') { @@ -2176,40 +2265,68 @@ END } } } + $output .= '<div class="LC_left_float"><fieldset><legend>'.$lt{'link'}.'</legend>'. + '<table><tr>'; + my @linkdests = ('aboutme'); + if ($permission->{'cusr'}) { + unshift (@linkdests,'modify'); + } + $output .= '<td>'; + my $usernamelink = $env{'form.usernamelink'}; + if ($usernamelink eq '') { + $usernamelink = 'aboutme'; + } + foreach my $item (@linkdests) { + my $checkedstr = ''; + if ($item eq $usernamelink) { + $checkedstr = ' checked="checked"'; + } + $output .= '<span class="LC_nobreak"><label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.' /> '.$lt{$item}.'</label></span><br />'; + } + my $checkwin; + if ($env{'form.userwin'}) { + $checkwin = ' checked="checked"'; + } + $output .= '</td><td valign="top"><span class="LC_nobreak"><input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}.'</span></td></tr></table></fieldset></div>'; } - $output .= "\n<p>\n". + $output .= "\n".'<div class="LC_clear_float_footer"> </div>'."\n". &Apache::loncommon::start_data_table(). &Apache::loncommon::start_data_table_header_row(); if ($mode eq 'autoenroll') { $output .= " - <th><a href=\"javascript:document.studentform.sortby.value='type';document.studentform.submit();\">$lt{'type'}</a></th> + <th><a href=\"javascript:document.$formname.sortby.value='type';document.$formname.submit();\">$lt{'type'}</a></th> "; } else { - $output .= "\n".'<th>'.&mt('Count').'</th>'."\n"; + if ($mode eq 'pickauthor') { + $output .= "\n".'<th> </th>'."\n"; + } else { + $output .= "\n".'<th>'.&mt('Count').'</th>'."\n"; + } if ($actionselect) { $output .= '<th>'.&mt('Select').'</th>'."\n"; } } foreach my $item (@cols) { - $output .= "<th><a href=\"javascript:document.studentform.sortby.value='$item';document.studentform.submit();\">$lt{$item}</a></th>\n"; + $output .= "<th><a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\">$lt{$item}</a></th>\n"; } my %role_types = &role_type_names(); if ($context eq 'course' && $mode ne 'autoenroll') { if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') { # Clicker display on or off? - my %clicker_options = &Apache::lonlocal::texthash( - 'on' => 'Show', - 'off' => 'Hide', - ); + my %clicker_options = ( + 'on' => 'Show', + 'off' => 'Hide', + ); my $clickerchg = 'on'; if ($displayclickers eq 'on') { $clickerchg = 'off'; } - $output .= ' <th>'."\n".' '. - '<a href="javascript:document.studentform.displayclickers.value='. - "'".$clickerchg."'".';document.studentform.submit();">'. - $clicker_options{$clickerchg}.'</a> '.$lt{'clicker'}."\n". - ' </th>'."\n"; + $output .= ' <th>'."\n".' ' + .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id' + ,'<a href="javascript:document.'.$formname.'.displayclickers.value=' + ."'".$clickerchg."'".';document.'.$formname.'.submit();">' + ,'</a>') + ."\n".' </th>'."\n"; # Photo display on or off? if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) { @@ -2222,8 +2339,8 @@ END $photochg = 'off'; } $output .= ' <th>'."\n".' '. - '<a href="javascript:document.studentform.displayphotos.value='. - "'".$photochg."'".';document.studentform.submit();">'. + '<a href="javascript:document.'.$formname.'.displayphotos.value='. + "'".$photochg."'".';document.'.$formname.'.submit();">'. $photo_options{$photochg}.'</a> '.$lt{'photo'}."\n". ' </th>'."\n"; } @@ -2239,18 +2356,20 @@ END 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."); + $r->print(&mt('Problems occurred in writing the CSV file. ' + .'This error has been logged. ' + .'Please alert your LON-CAPA administrator.')); $CSVfile = undef; } # + push @cols,'clicker'; # Write headers and data to file print $CSVfile '"'.$results_description.'"'."\n"; print $CSVfile '"'.join('","',map { &Apache::loncommon::csv_translate($lt{$_}) - } (@cols)).'"'."\n"; + } (@cols))."\"\n"; } elsif ($mode eq 'excel') { + push @cols,'clicker'; # Create the excel spreadsheet ($excel_workbook,$excel_filename,$format) = &Apache::loncommon::create_workbook($r); @@ -2259,6 +2378,7 @@ END $excel_sheet->write($row++,0,$results_description,$format->{'h2'}); # my @colnames = map {$lt{$_}} (@cols); + $excel_sheet->write($row++,0,\@colnames,$format->{'bold'}); } @@ -2280,6 +2400,11 @@ END $grpfilter = 'all'; } } + my %ltstatus = &Apache::lonlocal::texthash( + Active => 'Active', + Future => 'Future', + Expired => 'Expired', + ); # Get groups, role, permanent e-mail so we can sort on them if # necessary. foreach my $user (keys(%{$userlist})) { @@ -2410,7 +2535,10 @@ END foreach my $item (@{$keylist}) { $in{$item} = $sdata->[$index{$item}]; } - my $role = $in{'role'}; + my $clickers = (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1]; + if ($clickers!~/\w/) { $clickers='-'; } + $in{'clicker'} = $clickers; + my $role = $in{'role'}; $in{'role'}=&Apache::lonnet::plaintext($sdata->[$index{'role'}]); if (! defined($in{'start'}) || $in{'start'} == 0) { $in{'start'} = &mt('none'); @@ -2422,7 +2550,7 @@ END } else { $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'}); } - if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') { + if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') { $r->print(&Apache::loncommon::start_data_table_row()); my $checkval; if ($mode eq 'autoenroll') { @@ -2431,7 +2559,7 @@ END $cellentry = '<b>'.&mt('auto').'</b> <label><input type="checkbox" name="chgauto" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label>'; $autocount ++; } else { - $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><nobr><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label></nobr></td></tr><tr><td><nobr>'; + $cellentry = '<table border="0" cellspacing="0"><tr><td rowspan="2"><b>'.&mt('manual').'</b></td><td><span class="LC_nobreak"><label><input type="checkbox" name="chgmanual" value="'.$in{'username'}.':'.$in{'domain'}.'" /> Change</label></span></td></tr><tr><td><span class="LC_nobreak">'; $manualcount ++; if ($in{'lockedtype'}) { $cellentry .= '<label><input type="checkbox" name="unlockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Unlock').'</label>'; @@ -2440,11 +2568,13 @@ END $cellentry .= '<label><input type="checkbox" name="lockchg" value="'.$in{'username'}.':'.$in{'domain'}.'" /> '.&mt('Lock').'</label>'; $lockcount ++; } - $cellentry .= '</nobr></td></tr></table>'; + $cellentry .= '</span></td></tr></table>'; } $r->print("<td>$cellentry</td>\n"); } else { - $r->print("<td>$rowcount</td>\n"); + if ($mode ne 'pickauthor') { + $r->print("<td>$rowcount</td>\n"); + } if ($actionselect) { my $showcheckbox; if ($role =~ /^cr\//) { @@ -2474,10 +2604,12 @@ END } } $r->print('<td><input type="checkbox" name="'. - 'actionlist" value="'.$checkval.'"></td>'); + 'actionlist" value="'.$checkval.'" /></td>'); } else { $r->print('<td> </td>'); } + } elsif ($mode eq 'pickauthor') { + $r->print('<td><input type="button" name="chooseauthor" onclick="javascript:gochoose('."'$in{'username'}'".');" value="'.&mt('Select').'" /></td>'); } } foreach my $item (@cols) { @@ -2485,6 +2617,12 @@ END $r->print('<td>'.&print_username_link($mode,\%in).'</td>'); } elsif (($item eq 'start' || $item eq 'end') && ($actionselect)) { $r->print('<td>'.$in{$item}.'<input type="hidden" name="'.$checkval.'_'.$item.'" value="'.$sdata->[$index{$item}].'" /></td>'."\n"); + } elsif ($item eq 'status') { + my $showitem = $in{$item}; + if (defined($ltstatus{$in{$item}})) { + $showitem = $ltstatus{$in{$item}}; + } + $r->print('<td>'.$showitem.'</td>'."\n"); } else { $r->print('<td>'.$in{$item}.'</td>'."\n"); } @@ -2501,7 +2639,7 @@ END } if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) { if ($displayphotos eq 'on' && $role eq 'st' && $in{'photo'} ne '') { - $r->print(' <td align="right"><a href="javascript:photowindow('."'".$in{'photo'}."'".')"><img src="'.$in{'thumbnail'}.'" border="1"></a></td>'); + $r->print(' <td align="right"><a href="javascript:photowindow('."'".$in{'photo'}."'".')"><img src="'.$in{'thumbnail'}.'" border="1" alt="" /></a></td>'); } else { $r->print(' <td> </td> '); } @@ -2526,7 +2664,7 @@ END foreach my $item (@cols) { push @line,&Apache::loncommon::csv_translate($in{$item}); } - print $CSVfile '"'.join('","',@line).'"'."\n"; + print $CSVfile '"'.join('","',@line)."\"\n"; } elsif ($mode eq 'excel') { my $col = 0; foreach my $item (@cols) { @@ -2545,17 +2683,14 @@ END $row++; } } - if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll') { + if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') { $r->print(&Apache::loncommon::end_data_table().'<br />'); } elsif ($mode eq 'excel') { $excel_workbook->close(); - $r->print('<p><a href="'.$excel_filename.'">'. - &mt('Your Excel spreadsheet').'</a> '.&mt('is ready for download').'.</p>'."\n"); + $r->print(&mt('[_1]Your Excel spreadsheet[_2] is ready for download.', '<p><a href="'.$excel_filename.'">','</a>')."</p>\n"); } elsif ($mode eq 'csv') { close($CSVfile); - $r->print('<a href="'.$CSVfilename.'">'. - &mt('Your CSV file').'</a> is ready for download.'. - "\n"); + $r->print(&mt('[_1]Your CSV file[_2] is ready for download.', '<p><a href="'.$CSVfilename.'">','</a>')."</p>\n"); $r->rflush(); } if ($mode eq 'autoenroll') { @@ -2565,6 +2700,125 @@ END } } +sub bulkaction_javascript { + my ($formname,$caller) = @_; + my $docstart = 'document'; + if ($caller eq 'popup') { + $docstart = 'opener.document'; + } + my %lt = &Apache::lonlocal::texthash( + acwi => 'Access will be set to start immediately', + asyo => 'as you did not select an end date in the pop-up window', + accw => 'Access will be set to continue indefinitely', + asyd => 'as you did not select an end date in the pop-up window', + sewi => "Sections will be switched to 'No section'", + ayes => "as you either selected the 'No section' option", + oryo => 'or you did not select a section in the pop-up window', + arol => 'A role with no section will be added', + swbs => 'Sections will be switched to:', + rwba => 'Roles will be added for section(s):', + ); + my $alert = &mt("You must select at least one user by checking a user's 'Select' checkbox"); + my $noaction = &mt("You need to select an action to take for the user(s) you have selected"); + my $singconfirm = &mt(' for a single user?'); + my $multconfirm = &mt(' for multiple users?'); + my $output = <<"ENDJS"; +function verify_action (field) { + var numchecked = 0; + var singconf = '$singconfirm'; + var multconf = '$multconfirm'; + if ($docstart.$formname.elements[field].length > 0) { + for (i=0; i<$docstart.$formname.elements[field].length; i++) { + if ($docstart.$formname.elements[field][i].checked == true) { + numchecked ++; + } + } + } else { + if ($docstart.$formname.elements[field].checked == true) { + numchecked ++; + } + } + if (numchecked == 0) { + alert("$alert"); + return; + } else { + var message = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].text; + var choice = $docstart.$formname.bulkaction[$docstart.$formname.bulkaction.selectedIndex].value; + if (choice == '') { + alert("$noaction"); + return; + } else { + if (numchecked == 1) { + message += singconf; + } else { + message += multconf; + } +ENDJS + if ($caller ne 'popup') { + $output .= <<"NEWWIN"; + if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate' || choice == 'chgsec') { + opendatebrowser(document.$formname,'$formname','go'); + return; + + } else { + if (confirm(message)) { + document.$formname.phase.value = 'bulkchange'; + document.$formname.submit(); + return; + } + } +NEWWIN + } else { + $output .= <<"POPUP"; + if (choice == 'chgdates' || choice == 'reenable' || choice == 'activate') { + var datemsg = ''; + if (($docstart.$formname.startdate_month.value == '') && + ($docstart.$formname.startdate_day.value == '') && + ($docstart.$formname.startdate_year.value == '')) { + datemsg = "\\n$lt{'acwi'},\\n$lt{'asyo'}.\\n"; + } + if (($docstart.$formname.enddate_month.value == '') && + ($docstart.$formname.enddate_day.value == '') && + ($docstart.$formname.enddate_year.value == '')) { + datemsg += "\\n$lt{'accw'},\\n$lt{'asyd'}.\\n"; + } + if (datemsg != '') { + message += "\\n"+datemsg; + } + } + if (choice == 'chgsec') { + var rolefilter = $docstart.$formname.showrole.options[$docstart.$formname.showrole.selectedIndex].value; + var retained = $docstart.$formname.retainsec.value; + var secshow = $docstart.$formname.newsecs.value; + if (secshow == '') { + if (rolefilter == 'st' || retained == 0 || retained == "") { + message += "\\n\\n$lt{'sewi'},\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n"; + } else { + message += "\\n\\n$lt{'arol'}\\n$lt{'ayes'},\\n$lt{'oryo'}.\\n"; + } + } else { + if (rolefilter == 'st' || retained == 0 || retained == "") { + message += "\\n\\n$lt{'swbs'} "+secshow+".\\n"; + } else { + message += "\\n\\n$lt{'rwba'} "+secshow+".\\n"; + } + } + } + if (confirm(message)) { + $docstart.$formname.phase.value = 'bulkchange'; + $docstart.$formname.submit(); + window.close(); + } +POPUP + } + $output .= ' + } + } +} +'; + return $output; +} + sub print_username_link { my ($mode,$in) = @_; my $output; @@ -2588,7 +2842,7 @@ sub role_type_names { } sub select_actions { - my ($context,$setting,$statusmode) = @_; + my ($context,$setting,$statusmode,$formname) = @_; my %lt = &Apache::lonlocal::texthash( revoke => "Revoke user roles", delete => "Delete user roles", @@ -2649,7 +2903,7 @@ sub select_actions { } } if ($options) { - $output = '<select name="bulkaction" onchange="javascript:opendatebrowser(this.form,'."'studentform','change'".')" />'."\n". + $output = '<select name="bulkaction">'."\n". '<option value="" selected="selected">'. &mt('Please select').'</option>'."\n".$options."\n".'</select>'; if ($choices{'dates'}) { @@ -2665,14 +2919,15 @@ sub select_actions { '<input type="hidden" name="enddate_year" value="" />'."\n". '<input type="hidden" name="enddate_hour" value="" />'."\n". '<input type="hidden" name="enddate_minute" value="" />'."\n". - '<input type="hidden" name="enddate_second" value="" />'."\n"; + '<input type="hidden" name="enddate_second" value="" />'."\n". + '<input type="hidden" name="no_end_date" value="" />'."\n"; if ($context eq 'course') { $output .= '<input type="hidden" name="makedatesdefault" value="" />'."\n"; } } if ($choices{'sections'}) { - $output .= '<input type="hidden" name="retainsec" value= "" />'."\n". - '<input type="hidden" name="newsecs" value= "" />'."\n"; + $output .= '<input type="hidden" name="retainsec" value="" />'."\n". + '<input type="hidden" name="newsecs" value="" />'."\n"; } } return $output; @@ -2686,25 +2941,11 @@ sub date_section_javascript { delete => "Check the boxes for any users for whom roles are to be deleted, and click 'Proceed'", none => "Choose an action to take for selected users", ); - my $output = ' -<script type="text/javascript">'."\n"; - $output .= <<"ENDONE"; + my $output = <<"ENDONE"; +<script type="text/javascript"> +// <![CDATA[ function opendatebrowser(callingform,formname,calledby) { var bulkaction = callingform.bulkaction.options[callingform.bulkaction.selectedIndex].value; - if (bulkaction == 'revoke' || bulkaction == 'delete' || bulkaction == '') { - if (calledby == 'go') { - if (bulkaction == 'revoke') { - alert("$nopopup{'revoke'}"); - } - if (bulkaction == 'delete') { - alert("$nopopup{'delete'}"); - } - if (bulkaction == '') { - alert("$nopopup{'none'}"); - } - } - return; - } var url = '/adm/createuser?'; var type = ''; var showrole = callingform.showrole.options[callingform.showrole.selectedIndex].value; @@ -2725,6 +2966,7 @@ ENDONE stdeditbrowser = open(url,title,options,'1'); stdeditbrowser.focus(); } +// ]]> </script> ENDTWO return $output; @@ -2738,6 +2980,7 @@ sub date_section_selector { my $sec_js = &setsections_javascript($formname,$groupslist); my $output = <<"END"; <script type="text/javascript"> +// <![CDATA[ $sec_js @@ -2758,9 +3001,7 @@ END setSections(formname); if (seccheck == 'ok') { opener.document.$callingform.newsecs.value = formname.sections.value; - window.close(); } - return; END } else { if ($context eq 'course') { @@ -2794,13 +3035,23 @@ END opener.document.$callingform.enddate_hour.value = formname.enddate_hour.options[formname.enddate_hour.selectedIndex].value; opener.document.$callingform.enddate_minute.value = formname.enddate_minute.value; opener.document.$callingform.enddate_second.value = formname.enddate_second.value; - window.close(); + if (formname.no_end_date.checked) { + opener.document.$callingform.no_end_date.value = '1'; + } else { + opener.document.$callingform.no_end_date.value = '0'; + } END } - $output .= ' + my $verify_action_js = &bulkaction_javascript($callingform,'popup'); + $output .= <<"ENDJS"; + verify_action('actionlist'); } + +$verify_action_js + +// ]]> </script> -'; +ENDJS my %lt = &Apache::lonlocal::texthash ( chac => 'Access dates to apply for selected users', chse => 'Changes in section affiliation to apply to selected users', @@ -2857,7 +3108,6 @@ END $output .= $info.$secbox; } $output .= '<p>'. -&mt('Use "Save" to update the main window with your selections.').'<br /><br />'. '<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n". '</form>'; return $output; @@ -2871,7 +3121,7 @@ sub section_picker { if ($mode eq 'upload') { my ($options,$cb_script,$coursepick) = &default_role_selector($context,1); - $secbox .= &Apache::lonhtmlcommon::row_title('role','LC_oddrow_value'). + $secbox .= &Apache::lonhtmlcommon::row_title(&mt('role'),'LC_oddrow_value'). $options. &Apache::lonhtmlcommon::row_closure(1)."\n"; } $secbox .= &Apache::lonhtmlcommon::row_title($rowtitle,'LC_oddrow_value')."\n"; @@ -2901,7 +3151,7 @@ sub results_header_row { } if ($context eq 'course') { if ($mode eq 'csv' || $mode eq 'excel') { - $description = &mt('Course - ').$env{'course.'.$env{'request.course.id'}.'.description'}.': '; + $description = &mt('Course - [_1]:',$env{'course.'.$env{'request.course.id'}.'.description'}).' '; } if ($statusmode eq 'Expired') { $description .= &mt('Users in course with expired [_1] roles',$showfilter); @@ -2960,8 +3210,11 @@ sub results_header_row { } } elsif ($context eq 'author') { $description = - &mt('Author space for <span class="LC_cusr_emph">[_1]</span>', - &Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'})).': '; + &mt('Author space for [_1]' + ,'<span class="LC_cusr_emph">' + .&Apache::loncommon::plainname($env{'user.name'},$env{'user.domain'}) + .'</span>') + .': '; if ($statusmode eq 'Expired') { $description .= &mt('Co-authors with expired [_1] roles',$showfilter); } elsif ($statusmode eq 'Future') { @@ -2977,7 +3230,7 @@ sub results_header_row { } } elsif ($context eq 'domain') { my $domdesc = &Apache::lonnet::domain($env{'request.role.domain'},'description'); - $description = &mt('Domain - ').$domdesc.': '; + $description = &mt('Domain - [_1]:',$domdesc).' '; if ($env{'form.roletype'} eq 'domain') { if ($statusmode eq 'Expired') { $description .= &mt('Users in domain with expired [_1] roles',$showfilter); @@ -3073,10 +3326,12 @@ sub show_drop_list { <input type="hidden" name="action" value="$action" /> <input type="hidden" name="state" value="done" /> <script type="text/javascript" language="Javascript"> +// <![CDATA[ $check_uncheck_js +// ]]> </script> <p> -<input type="hidden" name="phase" value="four"> +<input type="hidden" name="phase" value="four" /> END my ($indexhash,$keylist) = &make_keylist_array(); my $studentcount = 0; @@ -3194,7 +3449,7 @@ END # $r->print(&Apache::loncommon::start_data_table_row()); $r->print(<<"END"); - <td><input type="checkbox" name="droplist" value="$studentkey"></td> + <td><input type="checkbox" name="droplist" value="$studentkey" /></td> <td>$username</td> <td>$domain</td> <td>$id</td> @@ -3213,10 +3468,14 @@ END 'ua' => "uncheck all", ); $r->print(<<"END"); -</p><p> -<input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)"> -<input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)"> -<p><input type=submit value="$lt{'dp'}"></p> +</p> +<p> +<input type="button" value="$lt{'ca'}" onclick="javascript:checkAll(document.studentform.droplist)" /> +<input type="button" value="$lt{'ua'}" onclick="javascript:uncheckAll(document.studentform.droplist)" /> +</p> +<p> +<input type="submit" value="$lt{'dp'}" /> +</p> END return; } @@ -3227,23 +3486,42 @@ END sub print_first_users_upload_form { my ($r,$context) = @_; my $str; - $str = '<input type="hidden" name="phase" value="two">'; + $str = '<input type="hidden" name="phase" value="two" />'; $str .= '<input type="hidden" name="action" value="upload" />'; $str .= '<input type="hidden" name="state" value="got_file" />'; - $str .= "<h3>".&mt('Upload a file containing information about users')."</h3>\n"; - $str .= &Apache::loncommon::upfile_select_html(); - $str .= "<p>\n"; - $str .= '<input type="submit" name="fileupload" value="'. - &mt('Upload file of users').'">'."\n"; - $str .= '<label><input type="checkbox" name="noFirstLine" /> '. - &mt('Ignore First Line')."</label></p>\n"; - $str .= &Apache::loncommon::help_open_topic("Course_Create_Class_List", - &mt("How do I create a users list from a spreadsheet")). - "<br />\n"; - $str .= &Apache::loncommon::help_open_topic("Course_Convert_To_CSV", - &mt("How do I create a CSV file from a spreadsheet")). - "<br />\n"; + + $str .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n"; + + # Excel and CSV Help + $str .= '<p>' + .&Apache::loncommon::help_open_topic("Course_Create_Class_List", + &mt("How do I create a users list from a spreadsheet")) + ."<br />\n" + .&Apache::loncommon::help_open_topic("Course_Convert_To_CSV", + &mt("How do I create a CSV file from a spreadsheet")) + ."</p>\n"; + + $str .= &Apache::lonhtmlcommon::start_pick_box() + .&Apache::lonhtmlcommon::row_title(&mt('File')) + .'<p class="LC_info">'."\n" + .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n" + .'</p>'."\n" + .&Apache::loncommon::upfile_select_html() + .&Apache::lonhtmlcommon::row_closure() + .&Apache::lonhtmlcommon::row_title( + '<label for="noFirstLine">' + .&mt('Ignore First Line') + .'</label>') + .'<input type="checkbox" name="noFirstLine" id="noFirstLine" />' + .&Apache::lonhtmlcommon::row_closure(1) + .&Apache::lonhtmlcommon::end_pick_box(); + + $str .= '<p>' + .'<input type="submit" name="fileupload" value="'.&mt('Next').'" />' + .'</p>'; + $str .= &Apache::loncommon::end_page(); + $r->print($str); return; } @@ -3272,7 +3550,7 @@ sub upfile_drop_add { # # Store the field choices away foreach my $field (qw/username names - fname mname lname gen id sec ipwd email role/) { + fname mname lname gen id sec ipwd email role domain/) { $env{'form.'.$field.'_choice'}=$fields{$field}; } &Apache::loncommon::store_course_settings('enrollment_upload', @@ -3286,19 +3564,27 @@ sub upfile_drop_add { 'sec_choice' => 'scalar', 'ipwd_choice' => 'scalar', 'email_choice' => 'scalar', - 'role_choice' => 'scalar' }); + 'role_choice' => 'scalar', + 'domain_choice' => 'scalar', + 'inststatus_choice' => 'scalar'}); # my ($startdate,$enddate) = &get_dates_from_form(); if ($env{'form.makedatesdefault'}) { $r->print(&make_dates_default($startdate,$enddate,$context)); } # Determine domain and desired host (home server) - my $domain=$env{'request.role.domain'}; + my $defdom=$env{'request.role.domain'}; + my $domain; + if ($env{'form.defaultdomain'} ne '') { + $domain = $env{'form.defaultdomain'}; + } else { + $domain = $defdom; + } my $desiredhost = $env{'form.lcserver'}; if (lc($desiredhost) eq 'default') { $desiredhost = undef; } else { - my %home_servers = &Apache::lonnet::get_servers($domain,'library'); + my %home_servers = &Apache::lonnet::get_servers($defdom,'library'); if (! exists($home_servers{$desiredhost})) { $r->print('<span class="LC_error">'.&mt('Error'). &mt('Invalid home server specified').'</span>'); @@ -3363,6 +3649,7 @@ sub upfile_drop_add { 'permanentemail','id'); my %canmodify; if (&Apache::lonnet::allowed('mau',$domain)) { + push(@userinfo,'inststatus'); foreach my $field (@userinfo) { $canmodify{$field} = 1; } @@ -3383,7 +3670,9 @@ sub upfile_drop_add { if ($context eq 'course') { my ($cnum,$cdom) = &get_course_identity(); my $roster = &Apache::loncoursedata::get_classlist(); - %userlist = %{$roster}; + if (ref($roster) eq 'HASH') { + %userlist = %{$roster}; + } my %advrolehash = &Apache::lonnet::get_my_roles($cnum,$cdom,undef, \@statuses,\@poss_roles); &gather_userinfo($context,'view',\%userlist,$indexhash,\%info, @@ -3409,6 +3698,8 @@ sub upfile_drop_add { } else { $r->print('<h3>'.&mt('Adding/Modifying Users')."</h3>\n<p>\n"); } + $r->rflush; + my %counts = ( user => 0, auth => 0, @@ -3484,21 +3775,30 @@ sub upfile_drop_add { if ($entries{$fields{'username'}} ne &LONCAPA::clean_username($entries{$fields{'username'}})) { $r->print('<br />'. - &mt('<b>[_1]</b>: Unacceptable username for user [_2] [_3] [_4] [_5]', - $entries{$fields{'username'}},$fname,$mname,$lname,$gen). - '</b>'); + &mt('[_1]: Unacceptable username for user [_2] [_3] [_4] [_5]', + '<b>'.$entries{$fields{'username'}}.'</b>',$fname,$mname,$lname,$gen)); next; } else { + if ($entries{$fields{'domain'}} + ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) { + $r->print('<br />'. '<b>'.$entries{$fields{'domain'}}. + '</b>: '.&mt('Unacceptable domain for user [_2] [_3] [_4] [_5]',$fname,$mname,$lname,$gen)); + next; + } my $username = $entries{$fields{'username'}}; + my $userdomain = $entries{$fields{'domain'}}; + if ($userdomain eq '') { + $userdomain = $domain; + } if (defined($fields{'sec'})) { if (defined($entries{$fields{'sec'}})) { $entries{$fields{'sec'}} =~ s/\W//g; my $item = $entries{$fields{'sec'}}; if ($item eq "none" || $item eq 'all') { - $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.',$username,$fname,$mname,$lname,$gen,$item)); + $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a reserved word.','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item)); next; } elsif (exists($curr_groups{$item})) { - $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.',$username,$fname,$mname,$lname,$gen,$item).' '.&mt('Section names and group names must be distinct.')); + $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]" - this is a course group.','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$item).' '.&mt('Section names and group names must be distinct.')); next; } else { push(@secs,$item); @@ -3507,10 +3807,10 @@ sub upfile_drop_add { } if ($env{'request.course.sec'} ne '') { @secs = ($env{'request.course.sec'}); - if (ref($userlist{$username.':'.$domain}) eq 'ARRAY') { - my $currsec = $userlist{$username.':'.$domain}[$secidx]; + if (ref($userlist{$username.':'.$userdomain}) eq 'ARRAY') { + my $currsec = $userlist{$username.':'.$userdomain}[$secidx]; if ($currsec ne $env{'request.course.sec'}) { - $r->print('<br />'.&mt('<b>[_1]</b>: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".',$username,$fname,$mname,$lname,$gen,$secs[0]).'<br />'); + $r->print('<br />'.&mt('[_1]: Unable to enroll user [_2] [_3] [_4] [_5] in a section named "[_6]".','<b>'.$username.'</b>',$fname,$mname,$lname,$gen,$secs[0]).'<br />'); if ($currsec eq '') { $r->print(&mt('This user already has an active/future student role in the course, unaffiliated to any section.')); @@ -3539,7 +3839,15 @@ sub upfile_drop_add { if (defined($fields{'email'})) { if (defined($entries{$fields{'email'}})) { $email=$entries{$fields{'email'}}; - unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } } + unless ($email=~/^[^\@]+\@[^\@]+$/) { $email=''; } + } + } + # determine affiliation + my $inststatus=''; + if (defined($fields{'inststatus'})) { + if (defined($entries{$fields{'inststatus'}})) { + $inststatus=$entries{$fields{'inststatus'}}; + } } # determine user password my $password = $genpwd; @@ -3560,8 +3868,13 @@ sub upfile_drop_add { } if ($role eq '') { my $rolestr = join(', ',@permitted_roles); - $r->print('<br />'. - &mt('<b>[_1]</b>: You do not have permission to add the requested role [_2] for the user.',$entries{$fields{'username'}},$entries{$fields{'role'}}).'<br />'.&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n"); + $r->print('<br />' + .&mt('[_1]: You do not have permission to add the requested role [_2] for the user.' + ,'<b>'.$entries{$fields{'username'}}.'</b>' + ,$entries{$fields{'role'}}) + .'<br />' + .&mt('Allowable role(s) is/are: [_1].',$rolestr)."\n" + ); next; } } @@ -3570,16 +3883,16 @@ sub upfile_drop_add { $role = $defaultrole; } # Clean up whitespace - foreach (\$domain,\$username,\$id,\$fname,\$mname, - \$lname,\$gen) { + foreach (\$id,\$fname,\$mname,\$lname,\$gen) { $$_ =~ s/(\s+$|^\s+)//g; } # check against rules my $checkid = 0; my $newuser = 0; my (%rulematch,%inst_results,%idinst_results); - my $uhome=&Apache::lonnet::homeserver($username,$domain); + my $uhome=&Apache::lonnet::homeserver($username,$userdomain); if ($uhome eq 'no_host') { + next if ($userdomain ne $domain); $checkid = 1; $newuser = 1; my $checkhash; @@ -3595,38 +3908,40 @@ sub upfile_drop_add { } } else { if ($context eq 'course' || $context eq 'author') { - if ($role eq '') { - my @checkroles; - foreach my $role (@poss_roles) { - my $endkey; - if ($role ne 'st') { - $endkey = ':'.$role; - } - if (exists($userlist{$username.':'.$domain.$endkey})) { - if (!grep(/^\Q$role\E$/,@checkroles)) { - push(@checkroles,$role); + if ($userdomain eq $domain ) { + if ($role eq '') { + my @checkroles; + foreach my $role (@poss_roles) { + my $endkey; + if ($role ne 'st') { + $endkey = ':'.$role; + } + if (exists($userlist{$username.':'.$userdomain.$endkey})) { + if (!grep(/^\Q$role\E$/,@checkroles)) { + push(@checkroles,$role); + } } } + if (@checkroles > 0) { + %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles); + } + } elsif (ref($modifiable_fields{$role}) eq 'HASH') { + %canmodify = %{$modifiable_fields{$role}}; } - if (@checkroles > 0) { - %canmodify = &can_modify_userinfo($context,$domain,\@userinfo,\@checkroles); - } - } elsif (ref($modifiable_fields{$role}) eq 'HASH') { - %canmodify = %{$modifiable_fields{$role}}; } - } - my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id); - for (my $i=0; $i<@userinfo; $i++) { - if (${$newinfo[$i]} ne '') { - if (!$canmodify{$userinfo[$i]}) { - ${$newinfo[$i]} = ''; + my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id); + for (my $i=0; $i<@newinfo; $i++) { + if (${$newinfo[$i]} ne '') { + if (!$canmodify{$userinfo[$i]}) { + ${$newinfo[$i]} = ''; + } } } } } if ($id ne '') { if (!$newuser) { - my %idhash = &Apache::lonnet::idrget($domain,($username)); + my %idhash = &Apache::lonnet::idrget($userdomain,($username)); if ($idhash{$username} ne $id) { $checkid = 1; } @@ -3634,14 +3949,14 @@ sub upfile_drop_add { if ($checkid) { my $checkhash; my $checks = { 'id' => 1 }; - $checkhash->{$username.':'.$domain} = { 'newuser' => $newuser, + $checkhash->{$username.':'.$userdomain} = { 'newuser' => $newuser, 'id' => $id }; &Apache::loncommon::user_rule_check($checkhash,$checks, \%alerts,\%rulematch,\%idinst_results,\%curr_rules, \%got_rules); if (ref($alerts{'id'}) eq 'HASH') { - if (ref($alerts{'id'}{$domain}) eq 'HASH') { - next if ($alerts{'id'}{$domain}{$id}); + if (ref($alerts{'id'}{$userdomain}) eq 'HASH') { + next if ($alerts{'id'}{$userdomain}{$id}); } } } @@ -3656,14 +3971,15 @@ sub upfile_drop_add { if (@secs > 0) { $sec = $secs[0]; } - &modifystudent($domain,$username,$cid,$sec, - $desiredhost); + &modifystudent($userdomain,$username,$cid,$sec, + $desiredhost,$context); $roleresult = &Apache::lonnet::modifystudent - ($domain,$username,$id,$amode,$password, + ($userdomain,$username,$id,$amode,$password, $fname,$mname,$lname,$gen,$sec,$enddate, $startdate,$env{'form.forceid'}, - $desiredhost,$email,'manual','',$cid); + $desiredhost,$email,'manual','',$cid, + '',$context,$inststatus); $userresult = $roleresult; } else { if ($role ne '') { @@ -3678,12 +3994,12 @@ sub upfile_drop_add { foreach my $sec (@secs) { ($userres{$sec},$authres{$sec},$roleres{$sec},$idres{$sec}) = &modifyuserrole($context,$setting, - $changeauth,$cid,$domain,$username, + $changeauth,$cid,$userdomain,$username, $id,$amode,$password,$fname, $mname,$lname,$gen,$sec, $env{'form.forceid'},$desiredhost, $email,$role,$enddate, - $startdate,$checkid); + $startdate,$checkid,$inststatus); } } elsif (@secs > 0) { $singlesec = $secs[0]; @@ -3694,11 +4010,12 @@ sub upfile_drop_add { if (!$multiple) { ($userresult,$authresult,$roleresult,$idresult) = &modifyuserrole($context,$setting, - $changeauth,$cid,$domain,$username, + $changeauth,$cid,$userdomain,$username, $id,$amode,$password,$fname, $mname,$lname,$gen,$singlesec, $env{'form.forceid'},$desiredhost, - $email,$role,$enddate,$startdate,$checkid); + $email,$role,$enddate,$startdate, + $checkid,$inststatus); } } if ($multiple) { @@ -3706,27 +4023,27 @@ sub upfile_drop_add { $flushc = &user_change_result($r,$userres{$sec},$authres{$sec}, $roleres{$sec},$idres{$sec},\%counts,$flushc, - $username,\%userchg); + $username,$userdomain,\%userchg); } } else { $flushc = &user_change_result($r,$userresult,$authresult, $roleresult,$idresult,\%counts,$flushc, - $username,\%userchg); + $username,$userdomain,\%userchg); } } else { if ($context eq 'course') { $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to enroll. No password specified.',$username) + &mt('[_1]: Unable to enroll. No password specified.','<b>'.$username.'</b>') ); } elsif ($context eq 'author') { $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add co-author. No password specified.',$username) + &mt('[_1]: Unable to add co-author. No password specified.','<b>'.$username.'</b>') ); } else { $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add user. No password specified.',$username) + &mt('[_1]: Unable to add user. No password specified.','<b>'.$username.'</b>') ); } } @@ -3761,7 +4078,7 @@ sub upfile_drop_add { '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'. &mt('There are no students with current/future access to the course.'). '</form>'."\n"); - } else { + } elsif (ref($classlist) eq 'HASH') { # Remove the students we just added from the list of students. foreach my $line (@userdata) { my %entries=&Apache::loncommon::record_sep($line); @@ -3823,13 +4140,13 @@ sub print_namespacing_alerts { sub user_change_result { my ($r,$userresult,$authresult,$roleresult,$idresult,$counts,$flushc, - $username,$userchg) = @_; + $username,$userdomain,$userchg) = @_; my $okresult = 0; if ($userresult ne 'ok') { if ($userresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add/modify: [_2]',$username,$error)); + &mt('[_1]: Unable to add/modify: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'user'} ++; @@ -3839,7 +4156,7 @@ sub user_change_result { if ($authresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to modify authentication: [_2]',$username,$error)); + &mt('[_1]: Unable to modify authentication: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'auth'} ++; @@ -3849,7 +4166,7 @@ sub user_change_result { if ($roleresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add role: [_2]',$username,$error)); + &mt('[_1]: Unable to add role: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'role'} ++; @@ -3857,7 +4174,7 @@ sub user_change_result { } if ($okresult) { $flushc++; - $userchg->{$username}=1; + $userchg->{$username.':'.$userdomain}=1; $r->print('. '); if ($flushc>15) { $r->rflush; @@ -3969,24 +4286,25 @@ sub update_user_list { $end = $now; $type = 'manual'; $result = - &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid); + &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context); } elsif ($choice eq 'revoke') { # revoke or delete user role $end = $now; if ($role eq 'st') { $result = - &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid); + &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context); } else { $result = - &Apache::lonnet::revokerole($udom,$uname,$scope,$role); + &Apache::lonnet::revokerole($udom,$uname,$scope,$role, + '','',$context); } } elsif ($choice eq 'delete') { if ($role eq 'st') { - &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid); + &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$now,$start,$type,$locktype,$cid,'',$context); } $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$now, - $start,1); + $start,1,'',$context); } else { #reenable, activate, change access dates or change section if ($choice ne 'chgsec') { @@ -3995,25 +4313,25 @@ sub update_user_list { } if ($choice eq 'reenable') { if ($role eq 'st') { - $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid); + $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context); } else { $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end, - $now); + $now,'','',$context); } } elsif ($choice eq 'activate') { if ($role eq 'st') { - $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid); + $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context); } else { $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end, - $now); + $now,'','',$context); } } elsif ($choice eq 'chgdates') { if ($role eq 'st') { - $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid); + $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,$type,$locktype,$cid,'',$context); } else { $result = &Apache::lonnet::assignrole($udom,$uname,$scope,$role,$end, - $start); + $start,'','',$context); } } elsif ($choice eq 'chgsec') { my (@newsecs,$revresult,$nochg,@retained); @@ -4029,7 +4347,8 @@ sub update_user_list { } else { $revresult = &Apache::lonnet::revokerole($udom,$uname, - $scope,$role); + $scope,$role, + '','',$context); } } else { if (@newsecs > 0) { @@ -4038,12 +4357,14 @@ sub update_user_list { } else { $revresult = &Apache::lonnet::revokerole($udom,$uname, - $scope,$role); + $scope,$role, + '','',$context); } } else { $revresult = &Apache::lonnet::revokerole($udom,$uname, - $scope,$role); + $scope,$role, + '','',$context); } } } else { @@ -4058,17 +4379,17 @@ sub update_user_list { if (!$nochg) { if ($role eq 'st') { $result = - &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid); + &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,undef,$end,$start,$type,$locktype,$cid,'',$context); } else { my $newscope = $scopestem; - $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start); + $result = &Apache::lonnet::assignrole($udom,$uname,$newscope,$role,$end,$start,'','',$context); } } } else { foreach my $newsec (@newsecs) { if (!grep(/^\Q$newsec\E$/,@retained)) { if ($role eq 'st') { - $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid); + $result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$newsec,$end,$start,$type,$locktype,$cid,'',$context); } else { my $newscope = $scopestem; if ($newsec ne '') { @@ -4115,7 +4436,7 @@ sub update_user_list { $r->print('<p><b>'.&mt("$result_text{'ok'}{$choice} role(s) for [quant,_1,user,users,no users].",$count).'</b></p>'); if ($count > 0) { if ($choice eq 'revoke' || $choice eq 'drop') { - $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.</p>')); + $r->print('<p>'.&mt('Re-enabling will re-activate data for the role.').'</p>'); } # Flush the course logs so reverse user roles immediately updated &Apache::lonnet::flushcourselogs(); @@ -4136,11 +4457,9 @@ sub classlist_drop { my ($scope,$uname,$udom,$now) = @_; my ($cdom,$cnum) = ($scope=~m{^/($match_domain)/($match_courseid)}); if (&Apache::lonnet::is_course($cdom,$cnum)) { - my $user = $uname.':'.$udom; if (!&active_student_roles($cnum,$cdom,$uname,$udom)) { - my $result = - &Apache::lonnet::cput('classlist', - { $user => $now },$cdom,$cnum); + my %user; + my $result = &update_classlist($cdom,$cnum,$udom,$uname,\%user,$now); return &mt('Drop from classlist: [_1]', '<b>'.$result.'</b>').'<br />'; } @@ -4207,17 +4526,29 @@ sub set_login { } sub course_sections { - my ($sections_count,$role) = @_; + my ($sections_count,$role,$current_sec) = @_; my $output = ''; my @sections = (sort {$a <=> $b} keys %{$sections_count}); my $numsec = scalar(@sections); + my $is_selected = ' selected="selected"'; if ($numsec <= 1) { $output = '<select name="currsec_'.$role.'" >'."\n". - ' <option value="">'.&mt('Select').'</option>'."\n". + ' <option value="">'.&mt('Select').'</option>'."\n"; + if ($current_sec eq 'none') { + $output .= + ' <option value=""'.$is_selected.'>'.&mt('No section').'</option>'."\n"; + } else { + $output .= ' <option value="">'.&mt('No section').'</option>'."\n"; + } if ($numsec == 1) { - $output .= + if ($current_sec eq $sections[0]) { + $output .= + ' <option value="'.$sections[0].'"'.$is_selected.'>'.$sections[0].'</option>'."\n"; + } else { + $output .= ' <option value="'.$sections[0].'" >'.$sections[0].'</option>'."\n"; + } } } else { $output = '<select name="currsec_'.$role.'" '; @@ -4225,13 +4556,23 @@ sub course_sections { if (scalar(@sections) < 4) { $multiple = scalar(@sections); } if ($role eq 'st') { $output .= '>'."\n". - ' <option value="">'.&mt('Select').'</option>'."\n". + ' <option value="">'.&mt('Select').'</option>'."\n"; + if ($current_sec eq 'none') { + $output .= + ' <option value=""'.$is_selected.'>'.&mt('No section')."</option>\n"; + } else { + $output .= ' <option value="">'.&mt('No section')."</option>\n"; + } } else { $output .= 'multiple="multiple" size="'.$multiple.'">'."\n"; } foreach my $sec (@sections) { - $output .= '<option value="'.$sec.'">'.$sec."</option>\n"; + if ($current_sec eq $sec) { + $output .= '<option value="'.$sec.'"'.$is_selected.'>'.$sec."</option>\n"; + } else { + $output .= '<option value="'.$sec.'">'.$sec."</option>\n"; + } } } $output .= '</select>'; @@ -4422,10 +4763,14 @@ sub can_modify_userinfo { if (ref($userroles) eq 'ARRAY') { foreach my $role (@{$userroles}) { my $testrole; - if ($role =~ /^cr\//) { - $testrole = 'cr'; - } else { + if ($context eq 'selfcreate') { $testrole = $role; + } else { + if ($role =~ /^cr\//) { + $testrole = 'cr'; + } else { + $testrole = $role; + } } if (ref($domconfig{'usermodification'}{$context}{$testrole}) eq 'HASH') { if ($domconfig{'usermodification'}{$context}{$testrole}{$field}) {