--- loncom/interface/lonuserutils.pm 2008/07/12 23:56:13 1.60 +++ loncom/interface/lonuserutils.pm 2009/05/06 16:19:34 1.92 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Utility functions for managing LON-CAPA user accounts # -# $Id: lonuserutils.pm,v 1.60 2008/07/12 23:56:13 raeburn Exp $ +# $Id: lonuserutils.pm,v 1.92 2009/05/06 16:19:34 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -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,7 +124,7 @@ 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; @@ -169,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'}, @@ -180,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].':'; } @@ -306,8 +328,8 @@ 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). + my $checked=(($env{'form.noFirstLine'})?' checked="checked"':''); + $r->print(&mt('Total number of records found in file: [_1]','<b>'.$distotal.'</b>'). "<br />\n"); $r->print('<div class="LC_left_float"><h3>'. &mt('Identify fields in uploaded list')."</h3>\n"); @@ -319,11 +341,11 @@ 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 /><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('<label><input type="checkbox" name="noFirstLine"'.$checked.'/>'. - &mt('Ignore First Line').'</label>'); $r->print("<br /><br />\n". '<script type="text/javascript" language="Javascript">'."\n". $javascript."\n".$javascript_validations.'</script>'); @@ -381,15 +403,18 @@ sub javascript_validations { name => 'The optional name field was not specified.', snum => 'The optional ID number 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,foundrole,founddomain) { +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; @@ -516,6 +541,20 @@ END } 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)) { @@ -546,6 +585,7 @@ function verify(vf,sec_caller) { 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'); @@ -557,8 +597,9 @@ function verify(vf,sec_caller) { 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,founddom); + verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus); } // @@ -580,6 +621,7 @@ function verify(vf,sec_caller) { // 10 = email address // 11 = role // 12 = domain +// 13 = inststatus function flip(vf,tf) { var nw=eval('vf.f'+tf+'.selectedIndex'); @@ -644,6 +686,7 @@ function verify(vf,sec_caller) { 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'); @@ -654,8 +697,9 @@ function verify(vf,sec_caller) { 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,founddomain); + verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundrole,founddomain,foundinststatus); } function flip(vf,tf) { @@ -721,7 +765,7 @@ sub print_upload_manager_footer { $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'). + &mt('Note: This will not take effect if the user already exists.'). &Apache::loncommon::help_open_topic('Auth_Options'). "</p>\n"; } @@ -769,20 +813,23 @@ sub print_upload_manager_footer { 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">'. + '<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"; } 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="'.&mt('Update Users').'" />'."<br />\n"; - if ($context eq 'course') { - $Str .= &mt('Note: for large courses, this operation may be time '. - 'consuming'); - } $Str .= '</div>'; + $Str .= '<div class="LC_clear_float_footer">'; + if ($context eq 'course') { + $Str .= '<div class="LC_info">' + .&mt('Note: For large courses, this operation may be time consuming.') + .'</div>'; + } + $Str .= '<input type="button"' + .'onClick="javascript:verify(this.form,this.form.csec)" ' + .'value="'.&mt('Update Users').'" />'."\n" + .'</div>'; $r->print($Str); return; } @@ -790,15 +837,15 @@ 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". + "<h3>".&mt('Student/Employee ID')."</h3>\n". + "<p>\n".'<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>'; @@ -839,6 +886,7 @@ sub print_upload_manager_form { 'email_choice' => 'scalar', 'role_choice' => 'scalar', 'domain_choice' => 'scalar', + 'inststatus_choice' => 'scalar', }; my $defdom = $env{'request.role.domain'}; if ($context eq 'course') { @@ -865,12 +913,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'}], - ['domain',&mt('Domain'), $env{'form.domain_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, @@ -988,7 +1037,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') { @@ -1274,12 +1323,16 @@ sub print_userlist { $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 ($cnum,$cdom); $r->print(&role_filter($context)); @@ -1287,6 +1340,12 @@ sub print_userlist { ($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')). "\n</p>\n"); @@ -1316,7 +1375,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; @@ -1450,7 +1511,10 @@ 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="'. @@ -1462,12 +1526,14 @@ sub role_filter { my $output; my $roleselected = ''; if ($env{'form.showrole'} eq 'Any') { - $roleselected = ' selected="selected" '; + $roleselected = ' selected="selected"'; } my ($role_select); if ($context eq 'domain') { $role_select = &domain_roles_select(); - $output = '<label>'.&mt('Role Type: [_1]',$role_select).'</label>'; + $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.'>'. @@ -1476,7 +1542,7 @@ sub role_filter { foreach my $role (@poss_roles) { $roleselected = ''; if ($role eq $env{'form.showrole'}) { - $roleselected = ' selected="selected" '; + $roleselected = ' selected="selected"'; } my $plrole; if ($role eq 'cr') { @@ -1487,7 +1553,9 @@ sub role_filter { $role_select .= '<option value="'.$role.'"'.$roleselected.'>'.$plrole.'</option>'; } $role_select .= '</select>'; - $output = '<label>'.&mt('Role: [_1]',$role_select).'</label>'; + $output = '<label><span class="LC_nobreak">' + .&mt('Role: [_1]',$role_select) + .'</span></label>'; } return $output; } @@ -2012,7 +2080,7 @@ END 'status' => "status", 'role' => "role", 'type' => "enroll type/action", - 'email' => "email address", + 'email' => "e-mail address", 'photo' => "photo", 'extent' => "extent", 'pr' => "Proceed", @@ -2020,9 +2088,10 @@ END 'ua' => "uncheck all", 'ac' => "Action to take for selected users", 'link' => "Behavior of clickable username link for each user", - 'aboutme' => "Display a user's personal page", + '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'); @@ -2143,15 +2212,15 @@ END foreach my $item (@linkdests) { my $checkedstr = ''; if ($item eq $usernamelink) { - $checkedstr = ' checked="checked" '; + $checkedstr = ' checked="checked"'; } - $output .= '<span class="LC_nobreak"><label><input type="radio" name="usernamelink" value="'.$item.'"'.$checkedstr.'> '.$lt{$item}.'</label></span><br />'; + $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"'; + $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 .= '</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".'<div class="LC_clear_float_footer"> </div>'."\n". &Apache::loncommon::start_data_table(). @@ -2220,18 +2289,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); @@ -2240,6 +2311,7 @@ END $excel_sheet->write($row++,0,$results_description,$format->{'h2'}); # my @colnames = map {$lt{$_}} (@cols); + $excel_sheet->write($row++,0,\@colnames,$format->{'bold'}); } @@ -2261,6 +2333,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})) { @@ -2391,7 +2468,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'); @@ -2412,7 +2492,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>'; @@ -2421,7 +2501,7 @@ 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 { @@ -2457,7 +2537,7 @@ END } } $r->print('<td><input type="checkbox" name="'. - 'actionlist" value="'.$checkval.'"></td>'); + 'actionlist" value="'.$checkval.'" /></td>'); } else { $r->print('<td> </td>'); } @@ -2470,6 +2550,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"); } @@ -2486,7 +2572,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> '); } @@ -2511,7 +2597,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) { @@ -2534,13 +2620,10 @@ END $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') { @@ -2776,8 +2859,8 @@ sub select_actions { } } 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; @@ -2955,7 +3038,7 @@ ENDJS $output .= $info.$secbox; } $output .= '<p>'. -'<input type="button" name="dateselection" value="'.&mt('Make changes').'" onclick="javascript:saveselections(this.form)" /></p>'."\n". +'<input type="button" name="dateselection" value="'.&mt('Save').'" onclick="javascript:saveselections(this.form)" /></p>'."\n". '</form>'; return $output; } @@ -2998,7 +3081,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); @@ -3057,8 +3140,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') { @@ -3074,7 +3160,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); @@ -3173,7 +3259,7 @@ sub show_drop_list { $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; @@ -3291,7 +3377,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> @@ -3310,10 +3396,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; } @@ -3324,22 +3414,26 @@ 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 .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n"; + $str .= '<p class="LC_info">' + .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.') + .'</p>'."\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 .= '<p>'; $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"; + &mt("How do I create a CSV file from a spreadsheet")); + $str .= "</p>\n"; + $str .= "<p>\n"; + $str .= '<label><input type="checkbox" name="noFirstLine" /> '. + &mt('Ignore First Line')."</label></p>\n"; + $str .= '<input type="submit" name="fileupload" value="'. + &mt('Next').'" />'."<br />\n"; $str .= &Apache::loncommon::end_page(); $r->print($str); return; @@ -3384,7 +3478,8 @@ sub upfile_drop_add { 'ipwd_choice' => 'scalar', 'email_choice' => 'scalar', 'role_choice' => 'scalar', - 'domain_choice' => 'scalar'}); + 'domain_choice' => 'scalar', + 'inststatus_choice' => 'scalar'}); # my ($startdate,$enddate) = &get_dates_from_form(); if ($env{'form.makedatesdefault'}) { @@ -3467,6 +3562,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; } @@ -3487,7 +3583,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, @@ -3513,6 +3611,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, @@ -3588,23 +3688,14 @@ 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 { - my $baddom = 0; - if ($entries{$fields{'dom'}} + if ($entries{$fields{'domain'}} ne &LONCAPA::clean_domain($entries{$fields{'domain'}})) { - $baddom = 1; - } else { - if (&Apache::lonnet::domain($entries{$fields{'domain'}}) eq '') { - $baddom = 1; - } - } - if ($baddom) { $r->print('<br />'. '<b>'.$entries{$fields{'domain'}}. - '</b>: '.&mt('Unacceptable domain for user [_2] [_3] [_4] [_5]',$fname,$mname,$lname,$gen).'</b>'); + '</b>: '.&mt('Unacceptable domain for user [_2] [_3] [_4] [_5]',$fname,$mname,$lname,$gen)); next; } my $username = $entries{$fields{'username'}}; @@ -3617,10 +3708,10 @@ sub upfile_drop_add { $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); @@ -3632,7 +3723,7 @@ sub upfile_drop_add { 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.')); @@ -3661,7 +3752,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; @@ -3682,8 +3781,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; } } @@ -3739,7 +3843,7 @@ sub upfile_drop_add { } } my @newinfo = (\$fname,\$mname,\$lname,\$gen,\$email,\$id); - for (my $i=0; $i<@userinfo; $i++) { + for (my $i=0; $i<@newinfo; $i++) { if (${$newinfo[$i]} ne '') { if (!$canmodify{$userinfo[$i]}) { ${$newinfo[$i]} = ''; @@ -3788,7 +3892,7 @@ sub upfile_drop_add { $fname,$mname,$lname,$gen,$sec,$enddate, $startdate,$env{'form.forceid'}, $desiredhost,$email,'manual','',$cid, - '',$context); + '',$context,$inststatus); $userresult = $roleresult; } else { if ($role ne '') { @@ -3808,7 +3912,7 @@ sub upfile_drop_add { $mname,$lname,$gen,$sec, $env{'form.forceid'},$desiredhost, $email,$role,$enddate, - $startdate,$checkid); + $startdate,$checkid,$inststatus); } } elsif (@secs > 0) { $singlesec = $secs[0]; @@ -3823,7 +3927,8 @@ sub upfile_drop_add { $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) { @@ -3843,15 +3948,15 @@ sub upfile_drop_add { } 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>') ); } } @@ -3886,7 +3991,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); @@ -3954,7 +4059,7 @@ sub user_change_result { if ($userresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add/modify: [_2]',$username.':'.$userdomain,$error)); + &mt('[_1]: Unable to add/modify: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'user'} ++; @@ -3964,7 +4069,7 @@ sub user_change_result { if ($authresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to modify authentication: [_2]',$username.':'.$userdomain,$error)); + &mt('[_1]: Unable to modify authentication: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'auth'} ++; @@ -3974,7 +4079,7 @@ sub user_change_result { if ($roleresult =~ /^error:(.+)$/) { my $error = $1; $r->print('<br />'. - &mt('<b>[_1]</b>: Unable to add role: [_2]',$username.':'.$userdomain,$error)); + &mt('[_1]: Unable to add role: [_2]','<b>'.$username.':'.$userdomain.'</b>',$error)); } } else { $counts->{'role'} ++; @@ -4244,7 +4349,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(); @@ -4265,11 +4370,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 />'; } @@ -4340,7 +4443,7 @@ sub course_sections { my $output = ''; my @sections = (sort {$a <=> $b} keys %{$sections_count}); my $numsec = scalar(@sections); - my $is_selected = ' selected="selected" '; + my $is_selected = ' selected="selected"'; if ($numsec <= 1) { $output = '<select name="currsec_'.$role.'" >'."\n". ' <option value="">'.&mt('Select').'</option>'."\n";