--- loncom/interface/lonuserutils.pm 2009/11/04 15:35:56 1.103
+++ loncom/interface/lonuserutils.pm 2010/08/10 04:00:16 1.109.2.4
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility functions for managing LON-CAPA user accounts
#
-# $Id: lonuserutils.pm,v 1.103 2009/11/04 15:35:56 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.109.2.4 2010/08/10 04:00:16 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,6 +36,7 @@ use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
use Apache::longroup;
+use Apache::lonnavmaps;
use LONCAPA qw(:DEFAULT :match);
###############################################################
@@ -386,7 +387,7 @@ sub javascript_validations {
if (($context eq 'course') || ($context eq 'domain')) {
if ($context eq 'course') {
if ($env{'request.course.sec'} eq '') {
- $setsection_call = 'setSections(document.'.$param{'formname'}."'$crstype'".');';
+ $setsection_call = 'setSections(document.'.$param{'formname'}.",'$crstype'".');';
$setsections_js =
&setsections_javascript($param{'formname'},$groupslist,
$mode,'',$crstype);
@@ -1176,7 +1177,7 @@ sub default_role_selector {
my %customroles;
my ($options,$coursepick,$cb_jscript);
if ($context ne 'author') {
- %customroles = &my_custom_roles();
+ %customroles = &my_custom_roles($crstype);
}
my %lt=&Apache::lonlocal::texthash(
@@ -1185,8 +1186,10 @@ sub default_role_selector {
'exs' => "Existing sections",
'new' => "New section",
);
- $options = ''."\n".
- ' '.&mt('Please select').' '."\n";
+ $options = ''."\n";
+ unless (($context eq 'course') && (&Apache::loncommon::needs_gci_custom())) {
+ $options .= ' '.&mt('Please select').' '."\n";
+ }
if ($context eq 'course') {
$options .= &default_course_roles($context,$checkpriv,$crstype,%customroles);
} elsif ($context eq 'author') {
@@ -1350,10 +1353,14 @@ sub curr_role_permissions {
# ======================================================= Existing Custom Roles
sub my_custom_roles {
+ my ($crstype) = @_;
my %returnhash=();
my %rolehash=&Apache::lonnet::dump('roles');
- foreach my $key (keys %rolehash) {
+ foreach my $key (keys(%rolehash)) {
if ($key=~/^rolesdef\_(\w+)$/) {
+ if ($crstype eq 'Community') {
+ next if ($rolehash{$key} =~ /bre\&S/);
+ }
$returnhash{$1}=$1;
}
}
@@ -1442,12 +1449,13 @@ sub print_userlist {
' ');
return;
}
- if (!(($context eq 'domain') && ($env{'form.roletype'} eq 'course'))) {
+ if (!(($context eq 'domain') &&
+ (($env{'form.roletype'} eq 'course') || ($env{'form.roletype'} eq 'community')))) {
$r->print(' '.&list_submit_button(&mt('Update Display')).
"\n
\n");
}
my ($indexhash,$keylist) = &make_keylist_array();
- my (%userlist,%userinfo);
+ my (%userlist,%userinfo,$clearcoursepick);
if (($context eq 'domain') &&
($env{'form.roletype'} eq 'course') ||
($env{'form.roletype'} eq 'community')) {
@@ -1472,9 +1480,15 @@ sub print_userlist {
$courseform."\n".
&Apache::lonhtmlcommon::row_closure(1).
&Apache::lonhtmlcommon::end_pick_box().''.
- ''.&list_submit_button(&mt('Update Display')).
+ '
'.
+ &list_submit_button(&mt('Update Display')).
"\n".'
'.$warning.' '."\n");
- if ($env{'form.coursepick'}) {
+ $clearcoursepick = 0;
+ if (($env{'form.origroletype'} ne '') &&
+ ($env{'form.origroletype'} ne $env{'form.roletype'})) {
+ $clearcoursepick = 1;
+ }
+ if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
$r->print(' '.&mt('Searching').' ... ');
}
} else {
@@ -1549,7 +1563,7 @@ sub print_userlist {
}
} elsif (($env{'form.roletype'} eq 'course') ||
($env{'form.roletype'} eq 'community')) {
- if ($env{'form.coursepick'}) {
+ if (($env{'form.coursepick'}) && (!$clearcoursepick)) {
my %courses = &process_coursepick();
my %allusers;
my $hidepriv = 1;
@@ -1952,13 +1966,17 @@ sub process_coursepick {
my $coursefilter = $env{'form.coursepick'};
my $cdom = $env{'request.role.domain'};
my %courses;
+ my $crssrch = 'Course';
+ if ($env{'form.roletype'} eq 'community') {
+ $crssrch = 'Community';
+ }
if ($coursefilter eq 'all') {
%courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.',
- undef,undef,'Course');
+ undef,undef,$crssrch);
} elsif ($coursefilter eq 'category') {
my $instcode = &instcode_from_coursefilter();
%courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.',
- undef,undef,'Course');
+ undef,undef,$crssrch);
} elsif ($coursefilter eq 'specific') {
if ($env{'form.coursetotal'} > 1) {
my @course_ids = split(/&&/,$env{'form.courselist'});
@@ -2078,6 +2096,7 @@ sub process_date_info {
sub show_users_list {
my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname)=@_;
+ my $custommenu;
if ($formname eq '') {
$formname = 'studentform';
}
@@ -2102,11 +2121,17 @@ sub show_users_list {
$sortby = 'username';
}
my $setting = $env{'form.roletype'};
- my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers,$crstype);
+ my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers,$crstype,
+ $clickersupport,$displaygroups);
if ($context eq 'course') {
$cid = $env{'request.course.id'};
$crstype = &Apache::loncommon::course_type();
($cnum,$cdom) = &get_course_identity($cid);
+ $custommenu = &Apache::loncommon::needs_gci_custom();
+ unless ($custommenu) {
+ $clickersupport = 1;
+ $displaygroups = 1;
+ }
($classgroups) = &Apache::loncoursedata::get_group_memberships(
$userlist,$keylist,$cdom,$cnum);
if ($mode eq 'autoenroll') {
@@ -2143,7 +2168,7 @@ END
} elsif ($context eq 'domain') {
if ($setting eq 'community') {
$crstype = 'Community';
- } elsif ($crstype eq 'course') {
+ } elsif ($setting eq 'course') {
$crstype = 'Course';
}
}
@@ -2227,6 +2252,8 @@ END
'role' => "role",
'type' => "enroll type/action",
'email' => "e-mail address",
+ 'lastlogin' => "last login",
+ 'submissions' => "test status",
'photo' => "photo",
'extent' => "extent",
'pr' => "Proceed",
@@ -2273,9 +2300,19 @@ END
push(@cols,'status');
}
if ($context eq 'course') {
- push(@cols,'groups');
+ if ($displaygroups) {
+ push(@cols,'groups');
+ }
}
push(@cols,'email');
+ if ($context eq 'course') {
+ if ($custommenu) {
+ push(@cols,'lastlogin');
+ if (($env{'form.showrole'} eq 'Any') || ($env{'form.showrole'} eq 'st')) {
+ push(@cols,'submissions');
+ }
+ }
+ }
}
my $rolefilter = $env{'form.showrole'};
@@ -2294,7 +2331,11 @@ END
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,$formname);
+ unless (($context eq 'domain') &&
+ (($setting eq 'course') || ($setting eq 'community'))) {
+ $actionselect =
+ &select_actions($context,$setting,$statusmode,$formname);
+ }
}
$r->print(<
@@ -2388,37 +2429,38 @@ END
$lt{'type'}
";
} else {
- if ($mode eq 'pickauthor') {
- $output .= "\n".' '."\n";
- } else {
- $output .= "\n".''.&mt('Count').' '."\n";
- }
+ $output .= "\n".' '."\n";
if ($actionselect) {
$output .= ''.&mt('Select').' '."\n";
}
}
foreach my $item (@cols) {
- $output .= "$lt{$item} \n";
+ if (grep(/^\Q$item\E$/,@sortable)) {
+ $output .= "$lt{$item} \n";
+ } else {
+ $output .= "$lt{$item} \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 = (
- 'on' => 'Show',
- 'off' => 'Hide',
- );
- my $clickerchg = 'on';
- if ($displayclickers eq 'on') {
- $clickerchg = 'off';
- }
- $output .= ' '."\n".' '
- .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id'
+ if ($clickersupport) {
+ my %clicker_options = (
+ 'on' => 'Show',
+ 'off' => 'Hide',
+ );
+ my $clickerchg = 'on';
+ if ($displayclickers eq 'on') {
+ $clickerchg = 'off';
+ }
+ $output .= ' '."\n".' '
+ .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id'
,''
,' ')
."\n".' '."\n";
-
+ }
# Photo display on or off?
if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
my %photo_options = &Apache::lonlocal::texthash(
@@ -2447,20 +2489,28 @@ END
time.'_'.rand(1000000000).'.csv';
unless ($CSVfile = Apache::File->new('>/home/httpd'.$CSVfilename)) {
$r->log_error("Couldn't open $CSVfilename for output $!");
- $r->print(&mt('Problems occurred 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.')
+ .' '.&mt('This error has been logged.')
+ .' '.&mt('Please alert your LON-CAPA administrator.')
+ .'
'
+ );
$CSVfile = undef;
}
#
- push @cols,'clicker';
+ if ($clickersupport) {
+ 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";
} elsif ($mode eq 'excel') {
- push @cols,'clicker';
+ if ($clickersupport) {
+ push @cols,'clicker';
+ }
# Create the excel spreadsheet
($excel_workbook,$excel_filename,$format) =
&Apache::loncommon::create_workbook($r);
@@ -2496,6 +2546,40 @@ END
Future => 'Future',
Expired => 'Expired',
);
+ # If this is for a single course get last course "log-in" and submissions.
+ my (%crslogins,%stusubmissions,%elapsed,$numparts,%nummultipart,$multipart);
+ my $now = time;
+ if ($context eq 'course') {
+ if ($custommenu) {
+ %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$cnum);
+ %stusubmissions=&Apache::lonnet::dump('nohist_submissiontracker',$cdom,$cnum);
+ %elapsed = &Apache::lonlocal::texthash(
+ -1 => 'more than a month ago',
+ 2592000 => 'within last 30 days',
+ 604800 => 'within last 7 days',
+ 86400 => 'within last 24 hours',
+ );
+ my $navmap = Apache::lonnavmaps::navmap->new();
+ if (defined($navmap)) {
+ my @allres=$navmap->retrieveResources('/uploaded/'.$cdom.'/'.$cnum.'/default_1261144274.sequence',sub { $_[0]->is_problem() },0);
+ foreach my $resource (@allres) {
+ my @parts = $resource->parts();
+ my $count = scalar(@parts);
+ if ($count > 1) {
+ $nummultipart{$count} ++;
+ }
+ $numparts += $count;
+ }
+ if (keys(%nummultipart) > 0) {
+ $multipart = ' '.'contains';
+ foreach my $key (sort {$a <=> $b} keys(%nummultipart)) {
+ $multipart .= " nummultipart{$key} multipart questions (with $key parts)";
+ }
+ }
+ }
+ }
+ }
+
# Get groups, role, permanent e-mail so we can sort on them if
# necessary.
foreach my $user (keys(%{$userlist})) {
@@ -2642,6 +2726,34 @@ END
} else {
$in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
}
+ if ($context eq 'course') {
+ if ($custommenu) {
+ my $lastlogin = $crslogins{$in{'username'}.':'.$in{'domain'}.':'.$in{'section'}.':'.$role};
+ if ($lastlogin ne '') {
+ my $sincelogin = $now - $lastlogin;
+ if ($sincelogin < 86400) {
+ $in{'lastlogin'} = $elapsed{'86400'};
+ } elsif ($sincelogin < 604800) {
+ $in{'lastlogin'} = $elapsed{'604800'};
+ } elsif ($sincelogin < 2592000 ) {
+ $in{'lastlogin'} = $elapsed{'2592000'};
+ } else {
+ $in{'lastlogin'} = $elapsed{'-1'};
+ }
+ }
+ }
+ if ($role eq 'st') {
+ my $numsub = $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0attempts"} +
+ $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0pilotsubs"};
+ if (!$numsub) {
+ $in{'submissions'} = 'not attempted';
+ } elsif ($numsub < $numparts) {
+ $in{'submissions'} = 'incomplete ('.$numsub.'/'.$numparts.')';
+ } else {
+ $in{'submissions'} = 'completed';
+ }
+ }
+ }
if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
$r->print(&Apache::loncommon::start_data_table_row());
my $checkval;
@@ -2715,19 +2827,27 @@ END
$showitem = $ltstatus{$in{$item}};
}
$r->print(''.$showitem.' '."\n");
+ } elsif ($item eq 'submissions') {
+ if ($in{$item} =~ /^incomplete/) {
+ $r->print(''.$in{$item}.$multipart.' ');
+ } else {
+ $r->print(''.$in{$item}.' '."\n");
+ }
} else {
$r->print(''.$in{$item}.' '."\n");
}
}
if (($context eq 'course') && ($mode ne 'autoenroll')) {
if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
- if ($displayclickers eq 'on') {
- my $clickers =
+ if ($clickersupport) {
+ if ($displayclickers eq 'on') {
+ my $clickers =
(&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
- if ($clickers!~/\w/) { $clickers='-'; }
- $r->print(''.$clickers.' ');
- } else {
- $r->print(' ');
+ if ($clickers!~/\w/) { $clickers='-'; }
+ $r->print(''.$clickers.' ');
+ } else {
+ $r->print(' ');
+ }
}
if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
if ($displayphotos eq 'on' && $role eq 'st' && $in{'photo'} ne '') {
@@ -3443,6 +3563,10 @@ sub show_drop_list {
my ($r,$classlist,$nosort,$permission,$crstype) = @_;
my $cid = $env{'request.course.id'};
my ($cnum,$cdom) = &get_course_identity($cid);
+ my $displaygroups;
+ unless (&Apache::loncommon::needs_gci_custom()) {
+ $displaygroups = 1;
+ }
if (! exists($env{'form.sortby'})) {
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['sortby']);
@@ -3520,8 +3644,10 @@ END
$lt{'sec'}
$lt{'start'}
$lt{'end'}
- $lt{'groups'}
END
+ if ($displaygroups) {
+ $r->print(" $lt{'groups'} \n");
+ }
$r->print(&Apache::loncommon::end_data_table_header_row());
} else {
$r->print(&Apache::loncommon::start_data_table().
@@ -3542,10 +3668,13 @@ END
$lt{'start'}
$lt{'end'}
-
- $lt{'groups'}
END
+ if ($displaygroups) {
+ $r->print("
+ $lt{'groups'}
+ \n");
+ }
$r->print(&Apache::loncommon::end_data_table_header_row());
}
#
@@ -3598,8 +3727,10 @@ END
$section
$start $startitem
$end
- $active_groups
END
+ if ($displaygroups) {
+ $r->print(" $active_groups \n");
+ }
$r->print(&Apache::loncommon::end_data_table_row());
}
$r->print(&Apache::loncommon::end_data_table().' ');
@@ -3636,27 +3767,19 @@ sub print_first_users_upload_form {
$str .= ' ';
$str .= ' ';
- $str .= ''.&mt('Upload a file containing information about users').' '."\n";
+ $str .= ''.&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"
+ .'
'."\n"
.&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') {
- if ($context eq 'course') {
- $str .= ''."\n"
- .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n"
- .'
'."\n";
- }
- }
- $str .= &Apache::loncommon::upfile_select_html()
+ .&Apache::lonhtmlcommon::row_title(&mt('File'))
+ .&Apache::loncommon::upfile_select_html()
.&Apache::lonhtmlcommon::row_closure()
.&Apache::lonhtmlcommon::row_title(
''
@@ -3670,8 +3793,6 @@ sub print_first_users_upload_form {
.' '
.'';
- $str .= &Apache::loncommon::end_page();
-
$r->print($str);
return;
}
@@ -3900,7 +4021,7 @@ sub upfile_drop_add {
}
}
my (%curr_rules,%got_rules,%alerts);
- my %customroles = &my_custom_roles();
+ my %customroles = &my_custom_roles($crstype);
my @permitted_roles =
&roles_on_upload($context,$setting,$crstype,%customroles);
# Get new users list
@@ -5014,14 +5135,22 @@ sub roles_by_context {
if ($env{'request.role'} =~ m{^dc\./}) {
push(@allroles,'ad');
}
- push(@allroles,('ta','ep','in'));
- if ($crstype eq 'Community') {
- push(@allroles,'co');
+ if (&Apache::loncommon::needs_gci_custom()) {
+ if ($crstype eq 'Community') {
+ push(@allroles,'co');
+ } else {
+ push(@allroles,'cc');
+ }
} else {
- push(@allroles,'cc');
- }
- if ($custom) {
- push(@allroles,'cr');
+ push(@allroles,('ta','ep','in'));
+ if ($crstype eq 'Community') {
+ push(@allroles,'co');
+ } else {
+ push(@allroles,'cc');
+ }
+ if ($custom) {
+ push(@allroles,'cr');
+ }
}
} elsif ($context eq 'author') {
@allroles = ('ca','aa');