--- loncom/interface/lonuserutils.pm 2012/08/21 01:50:34 1.140
+++ loncom/interface/lonuserutils.pm 2021/08/23 20:10:40 1.208
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA user accounts
#
-# $Id: lonuserutils.pm,v 1.140 2012/08/21 01:50:34 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.208 2021/08/23 20:10:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -30,12 +30,29 @@
package Apache::lonuserutils;
+=pod
+
+=head1 NAME
+
+Apache::lonuserutils.pm
+
+=head1 SYNOPSIS
+
+ Utilities for management of users and custom roles
+
+ Provides subroutines called by loncreateuser.pm
+
+=head1 OVERVIEW
+
+=cut
+
use strict;
use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
use Apache::longroup;
+use HTML::Entities;
use LONCAPA qw(:DEFAULT :match);
###############################################################
@@ -237,6 +254,8 @@ sub domain_roles_select {
# Role types
my @roletypes = ('domain','author','course','community');
my %lt = &role_type_names();
+ my $onchangefirst = "updateCols('showrole')";
+ my $onchangesecond = "updateCols('showrole')";
#
# build up the menu information to be passed to
# &Apache::loncommon::linked_select_forms
@@ -283,7 +302,8 @@ sub domain_roles_select {
my $result = &Apache::loncommon::linked_select_forms
('studentform',(' 'x3).&mt('Role: '),$env{'form.roletype'},
'roletype','showrole',\%select_menus,
- ['domain','author','course','community']);
+ ['domain','author','course','community'],$onchangefirst,
+ $onchangesecond);
return $result;
}
@@ -335,13 +355,22 @@ sub print_upload_manager_header {
$env{'request.role.domain'},$context,
$groupslist,$crstype);
my $checked=(($env{'form.noFirstLine'})?' checked="checked"':'');
- $r->print('
'
- .&mt('Total number of records found in file: [_1]'
- ,''.$distotal.'')
- ."
\n");
- $r->print('
'.
- &mt('Identify fields in uploaded list')."
\n");
- $r->print(&mt('Enter as many fields as you can. The system will inform you and bring you back to this page, if the data selected are insufficient to add users.')." \n");
+ $r->print(
+ '
'.&mt('Identify fields in uploaded list')."
\n".
+ '
'.
+ &mt('Total number of records found in file: [_1]'
+ ,''.$distotal.'').
+ "
\n"
+ );
+ if ($distotal == 0) {
+ $r->print('
'.&mt('None found').'
');
+ }
+ $r->print(
+ '
'.
+ &mt('Enter as many fields as you can.').' '.
+ &mt('The system will inform you and bring you back to this page,[_1]if the data selected are insufficient to add users.',' ').
+ "
'
+ );
+ $r->print(
+ ''
+ );
}
###############################################################
@@ -381,6 +416,12 @@ sub javascript_validations {
$param{'curr_autharg'} = $curr_authfield;
}
+ my $showcredits;
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($domain);
+ if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
+ $showcredits = 1;
+ }
+
my ($setsection_call,$setsections_js);
my $finish = " vf.submit();\n";
if ($mode eq 'upload') {
@@ -390,13 +431,14 @@ sub javascript_validations {
$setsection_call = 'setSections(document.'.$param{'formname'}.",'$crstype'".');';
$setsections_js =
&setsections_javascript($param{'formname'},$groupslist,
- $mode,'',$crstype);
+ $mode,'',$crstype,$showcredits);
} else {
$setsection_call = "'ok'";
}
} elsif ($context eq 'domain') {
$setsection_call = 'setCourse()';
- $setsections_js = &dc_setcourse_js($param{'formname'},$mode,$context);
+ $setsections_js = &dc_setcourse_js($param{'formname'},$mode,
+ $context,$showcredits,$domain);
}
$finish = " var checkSec = $setsection_call\n".
" if (checkSec == 'ok') {\n".
@@ -419,13 +461,17 @@ sub javascript_validations {
domain => 'The optional domain field was not specified.',
continue => 'Continue adding users?',
);
+ if ($showcredits) {
+ $alert{'credits'} = &mt('The optional credits field was not specified');
+ }
if (($mode eq 'upload') && ($context eq 'domain')) {
$alert{'inststatus'} = &mt('The optional affiliation field was not specified');
}
+ &js_escape(\%alert);
my $function_name = <<"END";
$setsections_js
-function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus) {
+function verify_message (vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits) {
END
my ($authnum,%can_assign) = &Apache::loncommon::get_assignable_auth($domain);
my $auth_checks;
@@ -482,23 +528,29 @@ END
return;
}
}
+/* regexp here to check for non \d \. in credits */
END
} else {
+ my ($numrules,$intargjs) =
+ &passwd_validation_js('vf.elements[current.argfield].value',$domain);
$auth_checks .= (< 0) {
+$intargjs
+ }
}
END
}
@@ -554,6 +610,16 @@ END
message+='$alert{'domain'}';
}
END
+ if ($showcredits) {
+ $optional_checks .= < $min) {
+ $min = $passwdconf{'min'};
+ }
+ }
+ if ($passwdconf{'max'} =~ /^\d+$/) {
+ $max = $passwdconf{'max'};
+ $numrules ++;
+ }
+ @chars = @{$passwdconf{'chars'}};
+ if (@chars) {
+ $numrules ++;
+ }
+ }
+ if ($min > 0) {
+ $numrules ++;
+ }
+ if (($min > 0) || ($max ne '') || (@chars > 0)) {
+ my $alertmsg = &mt('Initial password did not satisfy requirement(s):').'\n\n';
+ if ($min) {
+ $alert{'min'} = &mt('minimum [quant,_1,character]',$min).'\n';
+ }
+ if ($max) {
+ $alert{'max'} = &mt('maximum [quant,_1,character]',$max).'\n';
+ }
+ my (@charalerts,@charrules);
+ if (@chars) {
+ if (grep(/^uc$/,@chars)) {
+ push(@charalerts,&mt('contain at least one upper case letter'));
+ push(@charrules,'uc');
+ }
+ if (grep(/^lc$/,@chars)) {
+ push(@charalerts,&mt('contain at least one lower case letter'));
+ push(@charrules,'lc');
+ }
+ if (grep(/^num$/,@chars)) {
+ push(@charalerts,&mt('contain at least one number'));
+ push(@charrules,'num');
+ }
+ if (grep(/^spec$/,@chars)) {
+ push(@charalerts,&mt('contain at least one non-alphanumeric'));
+ push(@charrules,'spec');
+ }
+ }
+ $intargjs = qq| var rulesmsg = '';\n|.
+ qq| var currpwval = $currpasswdval;\n|;
+ if ($min) {
+ $intargjs .= qq|
+ if (currpwval.length < $min) {
+ rulesmsg += ' - $alert{min}';
+ }
+|;
+ }
+ if ($max) {
+ $intargjs .= qq|
+ if (currpwval.length > $max) {
+ rulesmsg += ' - $alert{max}';
+ }
+|;
+ }
+ if (@chars > 0) {
+ my $charrulestr = '"'.join('","',@charrules).'"';
+ my $charalertstr = '"'.join('","',@charalerts).'"';
+ $intargjs .= qq| var brokerules = new Array();\n|.
+ qq| var charrules = new Array($charrulestr);\n|.
+ qq| var charalerts = new Array($charalertstr);\n|;
+ my %rules;
+ map { $rules{$_} = 1; } @chars;
+ if ($rules{'uc'}) {
+ $intargjs .= qq|
+ var ucRegExp = /[A-Z]/;
+ if (!ucRegExp.test(currpwval)) {
+ brokerules.push('uc');
+ }
+|;
+ }
+ if ($rules{'lc'}) {
+ $intargjs .= qq|
+ var lcRegExp = /[a-z]/;
+ if (!lcRegExp.test(currpwval)) {
+ brokerules.push('lc');
+ }
+|;
+ }
+ if ($rules{'num'}) {
+ $intargjs .= qq|
+ var numRegExp = /[0-9]/;
+ if (!numRegExp.test(currpwval)) {
+ brokerules.push('num');
+ }
+|;
+ }
+ if ($rules{'spec'}) {
+ $intargjs .= q|
+ var specRegExp = /[!"#$%&'()*+,\-.\/:;<=>?@[\\^\]_`{\|}~]/;
+ if (!specRegExp.test(currpwval)) {
+ brokerules.push('spec');
+ }
+|;
+ }
+ $intargjs .= qq|
+ if (brokerules.length > 0) {
+ for (var i=0; i{'int'}) {
- my $warning = &mt('You may not specify an initial password for each user, as this is only available when new users use LON-CAPA internal authentication.\n').
+ my $warning = &mt('You may not specify an initial password for each user, as this is only available when new users use LON-CAPA internal authentication.')."\n".
&mt('Your current role does not have rights to create users with that authentication type.');
+ &js_escape(\$warning);
$auth_update = <<"END";
// Currently the initial password field is only supported for internal auth
// (see bug 6368).
@@ -638,6 +837,7 @@ function verify(vf,sec_caller) {
var foundrole=0;
var founddomain=0;
var foundinststatus=0;
+ var foundcredits=0;
var tw;
for (i=0;i<=vf.nfields.value;i++) {
tw=eval('vf.f'+i+'.selectedIndex');
@@ -650,8 +850,9 @@ function verify(vf,sec_caller) {
if (tw==11) { foundrole=1; }
if (tw==12) { founddomain=1; }
if (tw==13) { foundinststatus=1; }
+ if (tw==14) { foundcredits=1; }
}
- verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus);
+ verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
}
//
@@ -674,6 +875,7 @@ function verify(vf,sec_caller) {
// 11 = role
// 12 = domain
// 13 = inststatus
+// 14 = foundcredits
function flip(vf,tf) {
var nw=eval('vf.f'+tf+'.selectedIndex');
@@ -739,6 +941,7 @@ sub upload_manager_javascript_reverse_as
if (!$can_assign->{'int'}) {
my $warning = &mt('You may not specify an initial password, as this is only available when new users use LON-CAPA internal authentication.\n').
&mt('Your current role does not have rights to create users with that authentication type.');
+ &js_escape(\$warning);
$auth_update = <<"END";
// Currently the initial password field is only supported for internal auth
// (see bug 6368).
@@ -771,6 +974,7 @@ function verify(vf,sec_caller) {
var foundrole=0;
var founddomain=0;
var foundinststatus=0;
+ var foundcredits=0;
var tw;
for (i=0;i<=vf.nfields.value;i++) {
tw=eval('vf.f'+i+'.selectedIndex');
@@ -783,8 +987,9 @@ function verify(vf,sec_caller) {
if (i==10 && tw!=0) { foundrole=1; }
if (i==11 && tw!=0) { founddomain=1; }
if (i==12 && tw!=0) { foundinstatus=1; }
+ if (i==13 && tw!=0) { foundcredits=1; }
}
- verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus);
+ verify_message(vf,founduname,foundpwd,foundname,foundid,foundsec,foundemail,foundrole,founddomain,foundinststatus,foundcredits);
}
function flip(vf,tf) {
@@ -816,7 +1021,8 @@ ENDPICK
###############################################################
###############################################################
sub print_upload_manager_footer {
- my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission,$crstype) = @_;
+ my ($r,$i,$keyfields,$defdom,$today,$halfyear,$context,$permission,$crstype,
+ $showcredits) = @_;
my $form = 'document.studentform';
my $formname = 'studentform';
my ($krbdef,$krbdefdom) =
@@ -833,6 +1039,7 @@ sub print_upload_manager_footer {
my $krbform = &Apache::loncommon::authform_kerberos(%param);
my $intform = &Apache::loncommon::authform_internal(%param);
my $locform = &Apache::loncommon::authform_local(%param);
+ my $ltiform = &Apache::loncommon::authform_lti(%param);
my $date_table = &date_setting_table(undef,undef,$context,undef,
$formname,$permission,$crstype);
@@ -861,7 +1068,7 @@ sub print_upload_manager_footer {
&Apache::loncommon::help_open_topic('Auth_Options').
"\n";
}
- $Str .= &set_login($defdom,$krbform,$intform,$locform);
+ $Str .= &set_login($defdom,$krbform,$intform,$locform,$ltiform);
my ($home_server_pick,$numlib) =
&Apache::loncommon::home_server_form_item($defdom,'lcserver',
@@ -878,8 +1085,14 @@ sub print_upload_manager_footer {
&Apache::lonhtmlcommon::row_closure();
}
+ my ($trusted,$untrusted);
+ if ($context eq 'course') {
+ ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('enroll',$defdom);
+ } elsif ($context eq 'author') {
+ ($trusted,$untrusted) = &Apache::lonnet::trusted_domains('othcoau',$defdom);
+ }
$Str .= &Apache::lonhtmlcommon::row_title(&mt('Default domain'))
- .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1)
+ .&Apache::loncommon::select_dom_form($defdom,'defaultdomain',undef,1,undef,$trusted,$untrusted)
.&Apache::lonhtmlcommon::row_closure();
$Str .= &Apache::lonhtmlcommon::row_title(&mt('Starting and Ending Dates'))
@@ -905,9 +1118,15 @@ sub print_upload_manager_footer {
&mt('Default role'))
.&mt('Choose the role to assign to users without a value specified in the uploaded file.')
} elsif ($context eq 'course') {
- $Str .= &Apache::lonhtmlcommon::row_title(
+ if ($showcredits) {
+ $Str .= &Apache::lonhtmlcommon::row_title(
+ &mt('Default role, section and credits'))
+ .&mt('Choose the role and/or section(s) and/or credits to assign to users without values specified in the uploaded file.');
+ } else {
+ $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.');
+ .&mt('Choose the role and/or section(s) to assign to users without values specified in the uploaded file.');
+ }
} else {
$Str .= &Apache::lonhtmlcommon::row_title(
&mt('Default role and/or section(s)'))
@@ -915,7 +1134,8 @@ sub print_upload_manager_footer {
}
if (($context eq 'domain') || ($context eq 'author')) {
$Str .= ' ';
- my ($options,$cb_script,$coursepick) = &default_role_selector($context,1);
+ my ($options,$cb_script,$coursepick) =
+ &default_role_selector($context,1,'',$showcredits);
if ($context eq 'domain') {
$Str .= '
'
.''.&mt('Domain Level').' '
@@ -932,8 +1152,13 @@ sub print_upload_manager_footer {
} else {
my ($cnum,$cdom) = &get_course_identity();
my $rowtitle = &mt('section');
- my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,
- $permission,$context,'upload',$crstype);
+ my $defaultcredits;
+ if ($showcredits) {
+ $defaultcredits = &get_defaultcredits();
+ }
+ my $secbox = §ion_picker($cdom,$cnum,'Any',$rowtitle,$permission,
+ $context,'upload',$crstype,$showcredits,
+ $defaultcredits);
$Str .= $secbox
.&Apache::lonhtmlcommon::row_closure();
my %lt;
@@ -956,7 +1181,9 @@ sub print_upload_manager_footer {
.&Apache::lonhtmlcommon::row_closure();
}
if ($context eq 'course' || $context eq 'domain') {
- $Str .= &forceid_change($context);
+ $Str .= &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID'))
+ .&forceid_change($context)
+ .&Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
}
$Str .= &Apache::lonhtmlcommon::end_pick_box();
@@ -979,35 +1206,78 @@ sub print_upload_manager_footer {
return;
}
+sub get_defaultcredits {
+ my ($cdom,$cnum) = @_;
+
+ if ($cdom eq '' || $cnum eq '') {
+ return unless ($env{'request.course.id'});
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ }
+ return unless(($cdom =~ /^$match_domain$/) && ($cnum =~ /^$match_courseid$/));
+ my ($defaultcredits,$domdefcredits);
+ my %domdefaults = &Apache::lonnet::get_domain_defaults($cdom);
+ if ($domdefaults{'officialcredits'} || $domdefaults{'unofficialcredits'} || $domdefaults{'textbookcredits'}) {
+ my $instcode = $env{'course.'.$cdom.'_'.$cnum.'.internal.coursecode'};
+ if ($instcode) {
+ $domdefcredits = $domdefaults{'officialcredits'};
+ } elsif ($env{'course.'.$cdom.'_'.$cnum.'.internal.textbook'}) {
+ $domdefcredits = $domdefaults{'textbookcredits'};
+ } else {
+ $domdefcredits = $domdefaults{'unofficialcredits'};
+ }
+ } else {
+ return;
+ }
+
+ if ($env{'request.course.id'} eq $cdom.'_'.$cnum) {
+ $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
+ } elsif (exists($env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'})) {
+ $defaultcredits = $env{'course.'.$cdom.'_'.$cnum.'.internal.defaultcredits'};
+ } else {
+ my %crsinfo =
+ &Apache::lonnet::coursedescription("$cdom/$cnum",{'one_time' => 1});
+ $defaultcredits = $crsinfo{'internal.defaultcredits'};
+ }
+ if ($defaultcredits eq '') {
+ $defaultcredits = $domdefcredits;
+ }
+ return $defaultcredits;
+}
+
sub forceid_change {
my ($context) = @_;
my $output =
- &Apache::lonhtmlcommon::row_title(&mt('Student/Employee ID'))
- .' '."\n"
- .&mt('(only do if you know what you are doing.)')."\n";
+ ''.&Apache::loncommon::help_open_topic('ForceIDChange')."\n";
if ($context eq 'domain') {
- $output .= ' '."\n";
+ $output .=
+ ' '
+ .''."\n";
}
- $output .= &Apache::lonhtmlcommon::row_closure(1); # last row in pick_box
return $output;
}
###############################################################
###############################################################
sub print_upload_manager_form {
- my ($r,$context,$permission,$crstype) = @_;
+ my ($r,$context,$permission,$crstype,$showcredits) = @_;
my $firstLine;
my $datatoken;
if (!$env{'form.datatoken'}) {
$datatoken=&Apache::loncommon::upfile_store($r);
} else {
- $datatoken=$env{'form.datatoken'};
- &Apache::loncommon::load_tmp_file($r);
+ $datatoken=&Apache::loncommon::valid_datatoken($env{'form.datatoken'});
+ if ($datatoken ne '') {
+ &Apache::loncommon::load_tmp_file($r,$datatoken);
+ }
+ }
+ if ($datatoken eq '') {
+ $r->print('
'.&mt('Error').': '.
+ &mt('Invalid datatoken').'
');
+ return 'missingdata';
}
my @records=&Apache::loncommon::upfile_record_sep();
if($env{'form.noFirstLine'}){
@@ -1033,7 +1303,9 @@ sub print_upload_manager_form {
'domain_choice' => 'scalar',
'inststatus_choice' => 'scalar',
};
- my $defdom = $env{'request.role.domain'};
+ if ($showcredits) {
+ $col_setting_names->{'credits_choice'} = 'scalar';
+ }
if ($context eq 'course') {
&Apache::loncommon::restore_course_settings('enrollment_upload',
$col_setting_names);
@@ -1041,6 +1313,7 @@ sub print_upload_manager_form {
&Apache::loncommon::restore_settings($context,'user_upload',
$col_setting_names);
}
+ my $defdom = $env{'request.role.domain'};
#
# Determine kerberos parameters as appropriate
my ($krbdef,$krbdefdom) =
@@ -1066,6 +1339,10 @@ sub print_upload_manager_form {
['role',&mt('Role'), $env{'form.role_choice'}],
['domain',&mt('Domain'), $env{'form.domain_choice'}],
['inststatus',&mt('Affiliation'), $env{'form.inststatus_choice'}]);
+ if ($showcredits) {
+ push(@field,
+ ['credits',&mt('Student Credits'), $env{'form.credits_choice'}]);
+ }
if ($env{'form.upfile_associate'} eq 'reverse') {
&Apache::loncommon::csv_print_samples($r,\@records);
$i=&Apache::loncommon::csv_print_select_table($r,\@records,
@@ -1082,9 +1359,9 @@ sub print_upload_manager_form {
$keyfields=join(',',sort(keys(%sone)));
}
}
- $r->print('
');
&print_upload_manager_footer($r,$i,$keyfields,$defdom,$today,$halfyear,
- $context,$permission,$crstype);
+ $context,$permission,$crstype,$showcredits);
+ return 'ok';
}
sub setup_date_selectors {
@@ -1241,7 +1518,7 @@ sub make_dates_default {
}
sub default_role_selector {
- my ($context,$checkpriv,$crstype) = @_;
+ my ($context,$checkpriv,$crstype,$showcredits) = @_;
my %customroles;
my ($options,$coursepick,$cb_jscript);
if ($context ne 'author') {
@@ -1253,6 +1530,7 @@ sub default_role_selector {
'grs' => "Section",
'exs' => "Existing sections",
'new' => "New section",
+ 'crd' => "Credits",
);
$options = '
'.$warning.''."\n");
@@ -1568,10 +1849,10 @@ sub print_userlist {
$clearcoursepick = 1;
}
if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
- $r->print(''.&mt('Searching').' ...
');
+ $r->print(''.&mt('Searching ...').'
');
}
} else {
- $r->print('
'.&mt('Searching').' ...
');
+ $r->print('
'.&mt('Searching ...').'
');
}
$r->rflush();
if ($context eq 'course') {
@@ -1606,6 +1887,12 @@ sub print_userlist {
\%cstr_roles,$permission);
} elsif ($context eq 'domain') {
if ($env{'form.roletype'} eq 'domain') {
+ if (grep(/^authorusage$/,@cols)) {
+ $needauthorusage = 1;
+ }
+ if (grep(/^authorquota$/,@cols)) {
+ $needauthorquota = 1;
+ }
%dom_roles = &Apache::lonnet::get_domain_roles($env{'request.role.domain'});
foreach my $key (keys(%dom_roles)) {
if (ref($dom_roles{$key}) eq 'HASH') {
@@ -1691,33 +1978,37 @@ sub print_userlist {
}
}
if (keys(%userlist) == 0) {
+ my $msg = '';
if ($context eq 'author') {
- $r->print(&mt('There are no co-authors to display.')."\n");
+ $msg = &mt('There are no co-authors to display.');
} elsif ($context eq 'domain') {
if ($env{'form.roletype'} eq 'domain') {
- $r->print(&mt('There are no users with domain roles to display.')."\n");
+ $msg = &mt('There are no users with domain roles to display.');
} elsif ($env{'form.roletype'} eq 'author') {
- $r->print(&mt('There are no authors or co-authors to display.')."\n");
+ $msg = &mt('There are no authors or co-authors to display.');
} elsif ($env{'form.roletype'} eq 'course') {
- $r->print(&mt('There are no course users to display')."\n");
+ $msg = &mt('There are no course users to display');
} elsif ($env{'form.roletype'} eq 'community') {
- $r->print(&mt('There are no community users to display')."\n");
+ $msg = &mt('There are no community users to display');
}
} elsif ($context eq 'course') {
$r->print(&mt('There are no course users to display.')."\n");
}
+ $r->print('
'.$msg.'
'."\n") if $msg;
} else {
# Print out the available choices
my $usercount;
if ($env{'form.action'} eq 'modifystudent') {
($usercount) = &show_users_list($r,$context,'view',$permission,
- $env{'form.Status'},\%userlist,$keylist);
+ $env{'form.Status'},\%userlist,$keylist,'',
+ $showcredits);
} else {
($usercount) = &show_users_list($r,$context,$env{'form.output'},
- $permission,$env{'form.Status'},\%userlist,$keylist);
+ $permission,$env{'form.Status'},\%userlist,
+ $keylist,'',$showcredits,$needauthorquota,$needauthorusage);
}
if (!$usercount) {
- $r->print(' '
+ $r->print(' '
.&mt('There are no users matching the search criteria.')
.''
);
@@ -1835,12 +2126,12 @@ sub section_group_filter {
}
sub infocolumns {
- my ($context,$mode) = @_;
+ my ($context,$mode,$showcredits) = @_;
my @cols;
if (($mode eq 'pickauthor') || ($mode eq 'autoenroll')) {
- @cols = &get_cols_array($context,$mode);
+ @cols = &get_cols_array($context,$mode,$showcredits);
} else {
- my @posscols = &get_cols_array($context,$mode);
+ my @posscols = &get_cols_array($context,$mode,$showcredits);
if ($env{'form.phase'} ne '') {
my @checkedcols = &Apache::loncommon::get_env_multiple('form.showcol');
foreach my $col (@checkedcols) {
@@ -1856,7 +2147,7 @@ sub infocolumns {
}
sub get_cols_array {
- my ($context,$mode) = @_;
+ my ($context,$mode,$showcredits) = @_;
my @cols;
if ($mode eq 'pickauthor') {
@cols = ('username','fullname','status','email');
@@ -1866,9 +2157,6 @@ sub get_cols_array {
push(@cols,'section');
}
push(@cols,('start','end','role'));
- if ($context eq 'domain') {
- push (@cols,'extent');
- }
unless (($mode eq 'autoenroll') && ($env{'form.Status'} ne 'Any')) {
push(@cols,'status');
}
@@ -1877,19 +2165,25 @@ sub get_cols_array {
}
push(@cols,'email');
if (($context eq 'course') && ($mode ne 'autoenroll')) {
+ if ($showcredits) {
+ push(@cols,'credits');
+ }
push(@cols,'lastlogin','clicker');
}
if (($context eq 'course') && ($mode ne 'autoenroll') &&
($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'})) {
- push(@cols,'photos');
+ push(@cols,'photo');
+ }
+ if ($context eq 'domain') {
+ push (@cols,('authorusage','authorquota','extent'));
}
}
return @cols;
}
sub column_checkboxes {
- my ($context,$mode,$formname) = @_;
- my @cols = &get_cols_array($context,$mode);
+ my ($context,$mode,$formname,$showcredits) = @_;
+ my @cols = &get_cols_array($context,$mode,$showcredits);
my @showncols = &Apache::loncommon::get_env_multiple('form.showcol');
my (%disabledchk,%unchecked);
if ($env{'form.phase'} eq '') {
@@ -1897,20 +2191,35 @@ sub column_checkboxes {
if ($context eq 'course') {
$disabledchk{'role'} = 1;
$unchecked{'photo'} = 1;
+ $unchecked{'clicker'} = 1;
+ if ($showcredits) {
+ $unchecked{'credits'} = 1;
+ }
+ } elsif ($context eq 'domain') {
+ $unchecked{'extent'} = 1;
}
- $unchecked{'clicker'} = 1;
$unchecked{'start'} = 1;
$unchecked{'end'} = 1;
} else {
if ($env{'form.Status'} ne 'Any') {
$disabledchk{'status'} = 1;
}
- if ($env{'form.showrole'} ne 'Any') {
- $disabledchk{'role'} = 1;
+ if (($env{'form.showrole'} ne 'Any') && ($env{'form.showrole'} ne 'cr')) {
+ $disabledchk{'role'} = 1;
+ }
+ if ($context eq 'domain') {
+ if (($env{'form.roletype'} eq 'course') ||
+ ($env{'form.roletype'} eq 'community')) {
+ $disabledchk{'status'} = 1;
+ $disabledchk{'authorusage'} = 1;
+ $disabledchk{'authorquota'} = 1;
+ } elsif ($env{'form.roletype'} eq 'domain') {
+ $disabledchk{'extent'} = 1;
+ }
}
}
my $numposs = scalar(@cols);
- my $numinrow = 8;
+ my $numinrow = 7;
my %lt = &get_column_names($context);
my $output = '';
return $output;
@@ -1976,21 +2296,25 @@ sub get_column_names {
'end' => "end date",
'status' => "status",
'role' => "role",
+ 'credits' => "credits",
'type' => "enroll type/action",
'email' => "e-mail address",
'photo' => "photo",
'lastlogin' => "last login",
'extent' => "extent",
+ 'authorusage' => "disk usage (%)",
+ 'authorquota' => "disk quota (MB)",
'ca' => "check all",
'ua' => "uncheck all",
'clicker' => "clicker-ID",
);
if ($context eq 'domain' && $env{'form.roletype'} eq 'course') {
- $lt{'extent'} = &mt('Course(s): description, section(s), status');
+ $lt{'extent'} = &mt('course(s): description, section(s), status');
} elsif ($context eq 'domain' && $env{'form.roletype'} eq 'community') {
- $lt{'extent'} = &mt('Communities: description, section(s), status');
- } elsif ($context eq 'author') {
- $lt{'extent'} = &mt('Author');
+ $lt{'extent'} = &mt('community(s): description, section(s), status');
+ } elsif (($context eq 'author') ||
+ ($context eq 'domain' && $env{'form.roletype'} eq 'author')) {
+ $lt{'extent'} = &mt('author');
}
return %lt;
}
@@ -2112,7 +2436,6 @@ sub build_user_record {
sub courses_selector {
my ($cdom,$formname) = @_;
- my %coursecodes = ();
my %codes = ();
my @codetitles = ();
my %cat_titles = ();
@@ -2125,14 +2448,15 @@ sub courses_selector {
my $jscript = '';
my $totcodes = 0;
- $totcodes =
- &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,
- $cdom,$totcodes);
- if ($totcodes > 0) {
- $format_reply =
- &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,
- \%codes,\@codetitles,\%cat_titles,\%cat_order);
- if ($format_reply eq 'ok') {
+ my $instcats = &Apache::lonnet::get_dom_instcats($cdom);
+ if (ref($instcats) eq 'HASH') {
+ if ((ref($instcats->{'codetitles'}) eq 'ARRAY') && (ref($instcats->{'codes'}) eq 'HASH') &&
+ (ref($instcats->{'cat_titles'}) eq 'HASH') && (ref($instcats->{'cat_order'}) eq 'HASH')) {
+ %codes = %{$instcats->{'codes'}};
+ @codetitles = @{$instcats->{'codetitles'}};
+ %cat_titles = %{$instcats->{'cat_titles'}};
+ %cat_order = %{$instcats->{'cat_order'}};
+ $totcodes = scalar(keys(%codes));
my $numtypes = @codetitles;
&Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles);
my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles);
@@ -2140,7 +2464,7 @@ sub courses_selector {
my $allidlist = $idlist{$codetitles[0]};
$jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist);
$jscript .= $scripttext;
- $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles);
+ $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,\@codetitles);
}
}
my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom);
@@ -2169,7 +2493,8 @@ function setCourseCat(formname) {
}
courseSet('$codetitles[1]');
for (var j=0; j'.&Apache::loncommon::start_data_table();
- foreach my $role (sort(keys(%coursepersonnel))) {
- next if ($role =~ /^\s*$/);
- $output .= &Apache::loncommon::start_data_table_row().
- '
'.&mt('[_1]Your CSV file[_2] is ready for download.', '','')."
\n");
$r->rflush();
}
if ($mode eq 'autoenroll') {
@@ -2973,6 +3378,10 @@ sub bulkaction_javascript {
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?');
+ &js_escape(\$alert);
+ &js_escape(\$noaction);
+ &js_escape(\$singconfirm);
+ &js_escape(\$multconfirm);
my $output = <<"ENDJS";
function verify_action (field) {
var numchecked = 0;
@@ -3103,6 +3512,7 @@ sub select_actions {
chgdates => "Change starting/ending dates",
chgsec => "Change section associated with user roles",
);
+ # FIXME Add an option to change credits for student roles.
my ($output,$options,%choices);
# FIXME Disable actions for now for roletype=course in domain context
if ($context eq 'domain' && $setting eq 'course') {
@@ -3110,15 +3520,20 @@ sub select_actions {
}
if ($context eq 'course') {
if ($env{'form.showrole'} ne 'Any') {
- if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},
- $env{'request.course.id'})) {
- if ($env{'request.course.sec'} eq '') {
- return;
- } else {
- if (!&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
- return;
- }
- }
+ my $showactions;
+ if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},
+ $env{'request.course.id'})) {
+ $showactions = 1;
+ } elsif ($env{'request.course.sec'} ne '') {
+ if (&Apache::lonnet::allowed('c'.$env{'form.showrole'},$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
+ $showactions = 1;
+ }
+ }
+ unless ($showactions) {
+ unless (&is_courseowner($env{'request.course.id'},
+ $env{'course.'.$env{'request.course.id'}.'.internal.courseowner'})) {
+ return;
+ }
}
}
}
@@ -3225,11 +3640,13 @@ ENDTWO
}
sub date_section_selector {
- my ($context,$permission,$crstype) = @_;
+ my ($context,$permission,$crstype,$showcredits) = @_;
my $callingform = $env{'form.callingform'};
my $formname = 'dateselect';
my $groupslist = &get_groupslist();
- my $sec_js = &setsections_javascript($formname,$groupslist);
+ my $sec_js =
+ &setsections_javascript($formname,$groupslist,undef,undef,$crstype,
+ $showcredits);
my $output = <<"END";
-
END
my ($indexhash,$keylist) = &make_keylist_array();
@@ -3644,17 +4073,20 @@ END
}
}
if (!$studentcount) {
+ my $msg = '';
if ($crstype eq 'Community') {
- $r->print(&mt('There are no members to drop.'));
+ $msg = &mt('There are no members to drop.');
} else {
- $r->print(&mt('There are no students to drop.'));
+ $msg = &mt('There are no students to drop.');
}
+ $r->print('
'.&mt('Upload a file containing information about users').'
'."\n";
# Excel and CSV Help
- $str .= '
'
+ $str .= '
'
.&Apache::loncommon::help_open_topic("Course_Create_Class_List",
&mt("How do I create a users list from a spreadsheet"))
- .'
'."\n"
- .&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
+ .' '.&Apache::loncommon::help_open_topic("Course_Convert_To_CSV",
&mt("How do I create a CSV file from a spreadsheet"))
- .'
'."\n";
+ ."
\n";
$str .= &Apache::lonhtmlcommon::start_pick_box()
.&Apache::lonhtmlcommon::row_title(&mt('File'));
if (&Apache::lonlocal::current_language() ne 'en') {
@@ -3824,7 +4256,8 @@ sub print_first_users_upload_form {
.&Apache::lonhtmlcommon::end_pick_box();
$str .= '
'
- .''
+ .''
.'
';
$r->print($str);
@@ -3833,8 +4266,11 @@ sub print_first_users_upload_form {
# ================================================= Drop/Add from uploaded file
sub upfile_drop_add {
- my ($r,$context,$permission) = @_;
- &Apache::loncommon::load_tmp_file($r);
+ my ($r,$context,$permission,$showcredits) = @_;
+ my $datatoken = &Apache::loncommon::valid_datatoken($env{'form.datatoken'});
+ if ($datatoken ne '') {
+ &Apache::loncommon::load_tmp_file($r,$datatoken);
+ }
my @userdata=&Apache::loncommon::upfile_record_sep();
if($env{'form.noFirstLine'}){shift(@userdata);}
my @keyfields = split(/\,/,$env{'form.keyfields'});
@@ -3848,42 +4284,32 @@ sub upfile_drop_add {
$fields{$env{'form.f'.$i}}=$keyfields[$i];
}
}
- if ($env{'form.fullup'} ne 'yes') {
- $r->print(''.
- ''.
+ $r->print('
'.
&mt('There are no students with current/future access to the course.').
- ''."\n");
+ '
'."\n");
} elsif (ref($classlist) eq 'HASH') {
# Remove the students we just added from the list of students.
foreach my $line (@userdata) {
@@ -4456,9 +5138,7 @@ sub upfile_drop_add {
}
}
} # end of unless
- if ($env{'form.fullup'} ne 'yes') {
- $r->print('');
- }
+ return 'ok';
}
sub print_namespacing_alerts {
@@ -4501,15 +5181,52 @@ sub print_namespacing_alerts {
}
}
+sub passwdrule_alerts {
+ my ($domain,$passwdrules) = @_;
+ my $warning;
+ if (ref($passwdrules) eq 'HASH') {
+ my %showrules = %{$passwdrules};
+ if (keys(%showrules)) {
+ my %passwdconf = &Apache::lonnet::get_passwdconf($domain);
+ $warning = ''.&mt('Password requirement(s) unmet for one or more users:').'
';
+ if ($showrules{'min'}) {
+ my $min = $passwdconf{'min'};
+ if ($min eq '') {
+ $min = $Apache::lonnet::passwdmin;
+ }
+ $warning .= '
'.&mt("$result_text{'ok'}{$choice} for [quant,_1,user role,user roles,no user roles].",$count).'
');
+ $r->print('
'.&mt("$result_text{'ok'}{$choice} [quant,_1,user role,user roles,no user roles].",$count).'
');
if ($count > 0) {
if ($choice eq 'revoke' || $choice eq 'drop') {
$r->print('
'.&mt('Re-enabling will re-activate data for the role.').'
');
@@ -4917,7 +5641,10 @@ sub update_user_list {
if ($choice eq 'drop') {
$linktext = &mt('Display current class roster');
}
- $r->print(''.$linktext.''."\n");
+ $r->print(
+ &Apache::lonhtmlcommon::actionbox(
+ [''.$linktext.''])
+ .''."\n");
}
sub dates_feedback {
@@ -4925,7 +5652,7 @@ sub dates_feedback {
my $dates;
if ($start < $now) {
if ($end == 0) {
- $dates .= &mt('role(s) active now; no end date');
+ $dates = &mt('role(s) active now; no end date');
} elsif ($end > $now) {
$dates = &mt('role(s) active now; ends [_1].',&Apache::lonlocal::locallocaltime($end));
} else {
@@ -4964,18 +5691,25 @@ sub active_student_roles {
sub section_check_js {
my $groupslist= &get_groupslist();
+ my %js_lt = &Apache::lonlocal::texthash(
+ mayn => 'may not be used as the name for a section, as it is a reserved word.',
+ plch => 'Please choose a different section name.',
+ mnot => 'may not be used as a section name, as it is the name of a course group.',
+ secn => 'Section names and group names must be distinct. Please choose a different section name.',
+ );
+ &js_escape(\%js_lt);
return <<"END";
function validate(caller) {
var groups = new Array($groupslist);
var secname = caller.value;
if ((secname == 'all') || (secname == 'none')) {
- alert("'"+secname+"' may not be used as the name for a section, as it is a reserved word.\\nPlease choose a different section name.");
+ alert("'"+secname+"' $js_lt{'mayn'}\\n$js_lt{'plch'}");
return 'error';
}
if (secname != '') {
for (var k=0; k'.$authformloc.''.
&Apache::loncommon::end_data_table_row()."\n";
}
+ if ($can_assign{'lti'}) {
+ $response .= &Apache::loncommon::start_data_table_row().
+ '
'.$authformlti.'
'.
+ &Apache::loncommon::end_data_table_row()."\n";
+ }
$response .= &Apache::loncommon::end_data_table();
}
return $response;
}
sub course_sections {
- my ($sections_count,$role,$current_sec) = @_;
+ my ($sections_count,$role,$current_sec,$disabled) = @_;
my $output = '';
- my @sections = (sort {$a <=> $b} keys %{$sections_count});
+ my @sections = (sort {$a <=> $b} keys(%{$sections_count}));
my $numsec = scalar(@sections);
my $is_selected = ' selected="selected"';
if ($numsec <= 1) {
- $output = '