[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom loncapa_apache.conf startup.pl loncom/interface lonaccesstimes.pm lonblockingmenu.pm lonselstudent.pm
raeburn
raeburn at source.lon-capa.org
Fri Oct 21 22:05:53 EDT 2016
raeburn Sat Oct 22 02:05:53 2016 EDT
Added files:
/loncom/interface lonaccesstimes.pm
Modified files:
/loncom/interface lonblockingmenu.pm lonselstudent.pm
/loncom loncapa_apache.conf startup.pl
/doc/loncapafiles loncapafiles.lpml
Log:
- Users with vgr priv can display first access times for students for
course, map/folder, or resource with interval (timer) parameter set.
-------------- next part --------------
Index: loncom/interface/lonblockingmenu.pm
diff -u loncom/interface/lonblockingmenu.pm:1.20 loncom/interface/lonblockingmenu.pm:1.21
--- loncom/interface/lonblockingmenu.pm:1.20 Sat Oct 22 01:49:10 2016
+++ loncom/interface/lonblockingmenu.pm Sat Oct 22 02:03:31 2016
@@ -2,7 +2,7 @@
# Routines for configuring blocking of access to collaborative functions,
# and specific resources during an exam
#
-# $Id: lonblockingmenu.pm,v 1.20 2016/10/22 01:49:10 raeburn Exp $
+# $Id: lonblockingmenu.pm,v 1.21 2016/10/22 02:03:31 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -318,13 +318,16 @@
items in the course for use in an exam block of type: "Triggered by
Activating Timer".
-Inputs: 7 (three required, last four optional)
+Inputs: 8 (four required, last four optional)
- $intervals - Reference to hash of parameters for timed intervals
- $parmcount - numeric ID of current block
- $navmap - navmaps object
+ - $context - this will be "accesstimes" if called by lonaccesstimes.pm,
+ or "blocking" if called internally by lonblockingmenu.pm
+
- $currkey - current interval (where this is a block already using
an interval-based trigger).
@@ -339,6 +342,9 @@
Outputs: 1 - $intervalform - web form elements used to select a time interval
+=item &interval_details()
+
+
=item &trigger_details_toggle()
Creates link used to expand item showing information about timer for current
@@ -348,6 +354,7 @@
Outputs: 1 - returns HTML for link to display contents of information item
+
=item &show_timer_path()
Display hierarchy of names of folders/sub-folders containing the current
@@ -392,11 +399,20 @@
=item * for action to take -- add or modify block
-=item * for display of detailed information about intervals
-
=back
+=item &details_javascript()
+
+Create Javascript to toggle visibility of unordered list item
+containing details about item with timed interval parameter.
+
+Inputs: none
+
+Output: 1 Javascript (with <script></script> tags) for functions used to:
+ toggle visibility of unordered list for display of detailed
+ information about intervals.
+
=back
=cut
@@ -520,7 +536,8 @@
({href=>'/adm/setblock',
text=>'Blocking communication/content access'});
- my $js = &blockingmenu_javascript($blockcount);
+ my $js = &blockingmenu_javascript($blockcount).
+ &details_javascript();
$r->print(
&Apache::loncommon::start_page('Blocking communication/content access',$js).
@@ -1094,7 +1111,6 @@
$ltext->{'endd'}.': '.$endform.'</fieldset></td>');
} elsif ($record =~ /^firstaccess____(.+)$/) {
my $item = $1;
- my ($itemname,$iteminfo,$skipdetails);
my $type = 'map';
my $url;
if ($item eq 'course') {
@@ -1106,118 +1122,8 @@
$url = $item;
}
$r->print('<td><fieldset><legend>'.$ltext->{'trig'}.'</legend>');
- if ($type eq 'course') {
- $itemname = &mt('Timer for all items in course.');
- } else {
- if (&Apache::lonnet::is_on_map($url)) {
- if ($type eq 'map') {
- if (ref($navmap)) {
- my $title;
- my $resobj = $navmap->getResourceByUrl($item);
- if (ref($resobj)) {
- $title = $resobj->compTitle();
- } else {
- $title = &Apache::lonnet::gettitle($item);
- }
- $itemname = &mt('Timer for all items in folder: [_1]',
- '<span style="font-style:italic">'.
- $title.'</span>');
- }
- } else {
- if (ref($navmap)) {
- my $title;
- my $resobj = $navmap->getBySymb($item);
- if (ref($resobj)) {
- $title = $resobj->compTitle();
- } else {
- $title = &Apache::lonnet::gettitle($item);
- }
- $itemname = &mt('Timer for resource: [_1]',
- '<span style="font-style:italic">'.
- $title.'</span>');
- }
- }
- if (ref($navmap)) {
- my $path = &show_timer_path($type,$item);
- if ($path) {
- $iteminfo = ' <span style="font-size:90%;">'.
- &mt('(in: [_1])',$path).
- '</span>';
- }
- }
- } else {
- $skipdetails = 1;
- $itemname = '<span style="LC_warning">'.
- &mt('Timer folder/resource not in course').
- '</span>';
- }
- }
- if ((!$skipdetails) && (ref($intervals) eq 'HASH')) {
- if (ref($intervals->{$type}) eq 'HASH') {
- $iteminfo .= &trigger_details_toggle($parmcount).
- '<ul id="trigdetails_'.$parmcount.'" style="display:none">';
- if ($type eq 'course') {
- foreach my $scope (keys(%{$intervals->{$type}})) {
- if ($scope eq 'all') {
- $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
- &convlim($intervals->{$type}->{$scope})).'</li>';
- } elsif ($scope eq 'secgrp') {
- if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
- $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
- foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
- $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$item,
- &convlim($intervals->{$type}->{$scope}->{$item})).
- '</li>';
- }
- $iteminfo .= '</ul></li>';
- }
- } elsif ($scope eq 'users') {
- if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
- $iteminfo .= '<li>'.&mt('Users').'<ul>';
- foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
- $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',
- &convlim($item,$intervals->{$type}->{$scope}->{$item})).
- '</li>';
- }
- $iteminfo .= '</ul></li>';
- }
- }
- }
- } elsif (($type eq 'map') || ($type eq 'resource')) {
- if (ref($intervals->{$type}->{$item}) eq 'HASH') {
- foreach my $scope (keys(%{$intervals->{$type}->{$item}})) {
- if ($scope eq 'all') {
- $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
- &convlim($intervals->{$type}->{$item}->{$scope})).
- '</li>';
- } elsif ($scope eq 'secgrp') {
- if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
- $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
- foreach my $sec (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
- $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$sec,
- &convlim($intervals->{$type}->{$item}->{$scope}->{$sec})).
- '</li>';
- }
- $iteminfo .= '</ul></li>';
- }
- } elsif ($scope eq 'users') {
- if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
- $iteminfo .= '<li>'.&mt('Users').'<ul>';
- foreach my $user (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
- $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$user,
- &convlim($intervals->{$type}->{$item}->{$scope}->{$user})).
- '</li>';
- }
- $iteminfo .= '</ul></li>';
- }
- }
- }
- }
- }
- $iteminfo .= '</ul>';
- }
- }
- $r->print(&create_interval_form($intervals,$parmcount,$navmap,$item,$jschg,
+ my ($itemname,$iteminfo) = &interval_details($item,$type,$url,$navmap,$intervals,$parmcount);
+ $r->print(&create_interval_form($intervals,$parmcount,$navmap,'blocking',$item,$jschg,
$itemname,$iteminfo,$disabled).'</fieldset></td>');
}
$r->print(<<"END");
@@ -1281,7 +1187,7 @@
my %lt = &Apache::lonlocal::texthash(
'exam' => 'e.g., Exam 1',
);
- my $intervalform = &create_interval_form($intervals,$parmcount,$navmap);
+ my $intervalform = &create_interval_form($intervals,$parmcount,$navmap,'blocking');
if ($intervalform ne '') {
$intervalform = '<fieldset>'.
'<legend>'.$ltext->{'chtr'}.'</legend>'.
@@ -1405,9 +1311,10 @@
}
sub create_interval_form {
- my ($intervals,$parmcount,$navmap,$currkey,$jschg,$itemname,$iteminfo,$disabled) = @_;
+ my ($intervals,$parmcount,$navmap,$context,$currkey,$jschg,$itemname,$iteminfo,$disabled) = @_;
return unless ((ref($intervals) eq 'HASH') && (ref($navmap)));
my $intervalform;
+ my $counter = 0;
if (keys(%{$intervals}) > 0) {
foreach my $type (sort(keys(%{$intervals}))) {
if ($type eq 'course') {
@@ -1427,8 +1334,14 @@
$intervalform .= '</label>';
if ($currkey eq 'course') {
$intervalform .= $iteminfo;
+ } elsif ($context eq 'accesstimes') {
+ (undef,$iteminfo) = &interval_details('course',$type,'',$navmap,$intervals,$counter);
+ if ($iteminfo) {
+ $intervalform .= ' '.$iteminfo;
+ }
}
$intervalform .= '<br />';
+ $counter ++;
} elsif ($type eq 'map') {
if (ref($intervals->{$type}) eq 'HASH') {
if (ref($navmap)) {
@@ -1463,8 +1376,15 @@
$intervalform .= &mt('Timer for all items in folder: [_1]',
'<i>'.$title.'</i>').
'</label>'.$path;
+ if ($context eq 'accesstimes') {
+ (undef,$iteminfo) = &interval_details($map,$type,$map,$navmap,$intervals,$counter);
+ if ($iteminfo) {
+ $intervalform .= ' '.$iteminfo;
+ }
+ }
}
$intervalform .= '<br />';
+ $counter ++;
}
}
}
@@ -1491,7 +1411,8 @@
my ($title,$path,$hierarchy);
if (ref($resobj)) {
$title = $resobj->compTitle();
- } else {
+ }
+ if ($title eq '') {
$title = &Apache::lonnet::gettitle($resource);
}
$hierarchy = &show_timer_path($type,$resource,$navmap);
@@ -1503,8 +1424,19 @@
$intervalform .= &mt('Timer for resource: [_1]','<i>'.$title.'</i>').
'</label>'.
$path;
+ if ($context eq 'accesstimes') {
+ if (ref($resobj)) {
+ my $url = $resobj->src();
+ if ($url eq '') {
+ (my $map, my $resid, $url) = &Apache::lonnet::decode_symb($resource);
+ }
+ ($itemname,$iteminfo) = &interval_details($resource,$type,$url,$navmap,$intervals,$counter);
+ $intervalform .= ' '.$iteminfo;
+ }
+ }
}
$intervalform .= '<br />';
+ $counter ++;
}
}
}
@@ -1532,6 +1464,121 @@
'style="text-decoration: none;"><b>'.&mt('(More ...)').'</b></a></span>';
}
+sub interval_details {
+ my ($item,$type,$url,$navmap,$intervals,$parmcount) = @_;
+ my ($itemname,$iteminfo,$skipdetails);
+ if ($type eq 'course') {
+ $itemname = &mt('Timer for all items in course.');
+ } else {
+ if (&Apache::lonnet::is_on_map($url)) {
+ if ($type eq 'map') {
+ if (ref($navmap)) {
+ my $title;
+ my $resobj = $navmap->getResourceByUrl($item);
+ if (ref($resobj)) {
+ $title = $resobj->compTitle();
+ } else {
+ $title = &Apache::lonnet::gettitle($item);
+ }
+ $itemname = &mt('Timer for all items in folder: [_1]',
+ '<span style="font-style:italic">'.
+ $title.'</span>');
+ }
+ } else {
+ if (ref($navmap)) {
+ my $title;
+ my $resobj = $navmap->getBySymb($item);
+ if (ref($resobj)) {
+ $title = $resobj->compTitle();
+ } else {
+ $title = &Apache::lonnet::gettitle($item);
+ }
+ $itemname = &mt('Timer for resource: [_1]',
+ '<span style="font-style:italic">'.
+ $title.'</span>');
+ }
+ }
+ if (ref($navmap)) {
+ my $path = &show_timer_path($type,$item);
+ if ($path) {
+ $iteminfo = ' <span style="font-size:90%;">'.
+ &mt('(in: [_1])',$path).
+ '</span>';
+ }
+ }
+ } else {
+ $skipdetails = 1;
+ $itemname = '<span style="LC_warning">'.
+ &mt('Timer folder/resource not in course').
+ '</span>';
+ }
+ }
+ if ((!$skipdetails) && (ref($intervals) eq 'HASH') && (ref($intervals->{$type}) eq 'HASH')) {
+ $iteminfo = &trigger_details_toggle($parmcount).
+ '<ul id="trigdetails_'.$parmcount.'" style="display:none">';
+ if ($type eq 'course') {
+ foreach my $scope (keys(%{$intervals->{$type}})) {
+ if ($scope eq 'all') {
+ $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
+ &convlim($intervals->{$type}->{$scope})).'</li>';
+ } elsif ($scope eq 'secgrp') {
+ if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
+ $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
+ foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
+ $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$item,
+ &convlim($intervals->{$type}->{$scope}->{$item})).
+ '</li>';
+ }
+ $iteminfo .= '</ul></li>';
+ }
+ } elsif ($scope eq 'users') {
+ if (ref($intervals->{$type}->{$scope}) eq 'HASH') {
+ $iteminfo .= '<li>'.&mt('Users').'<ul>';
+ foreach my $item (sort(keys(%{$intervals->{$type}->{$scope}}))) {
+ $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',
+ &convlim($item,$intervals->{$type}->{$scope}->{$item})).
+ '</li>';
+ }
+ $iteminfo .= '</ul></li>';
+ }
+ }
+ }
+ } elsif (($type eq 'map') || ($type eq 'resource')) {
+ if (ref($intervals->{$type}->{$item}) eq 'HASH') {
+ foreach my $scope (keys(%{$intervals->{$type}->{$item}})) {
+ if ($scope eq 'all') {
+ $iteminfo .= '<li>'.&mt('All users -- time limit: [_1]',
+ &convlim($intervals->{$type}->{$item}->{$scope})).
+ '</li>';
+ } elsif ($scope eq 'secgrp') {
+ if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
+ $iteminfo .= '<li>'.&mt('Sections/groups').'<ul>';
+ foreach my $sec (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
+ $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$sec,
+ &convlim($intervals->{$type}->{$item}->{$scope}->{$sec})).
+ '</li>';
+ }
+ $iteminfo .= '</ul></li>';
+ }
+ } elsif ($scope eq 'users') {
+ if (ref($intervals->{$type}->{$item}->{$scope}) eq 'HASH') {
+ $iteminfo .= '<li>'.&mt('Users').'<ul>';
+ foreach my $user (sort(keys(%{$intervals->{$type}->{$item}->{$scope}}))) {
+ $iteminfo .= '<li>'.&mt('[_1] -- time limit: [_2]',$user,
+ &convlim($intervals->{$type}->{$item}->{$scope}->{$user})).
+ '</li>';
+ }
+ $iteminfo .= '</ul></li>';
+ }
+ }
+ }
+ }
+ }
+ $iteminfo .= '</ul>';
+ }
+ return ($itemname,$iteminfo);
+}
+
sub show_timer_path {
my ($type,$item,$navmap) = @_;
return unless(ref($navmap));
@@ -1568,10 +1615,6 @@
sub blockingmenu_javascript {
my ($blockcount) = @_;
- my %lt = &Apache::lonlocal::texthash (
- more => 'More ...',
- less => 'Less ...',
- );
return <<ENDSCRIPT;
<script type="text/javascript">
// <![CDATA[
@@ -1627,6 +1670,22 @@
return;
}
+// ]]>
+</script>
+ENDSCRIPT
+
+}
+
+sub details_javascript {
+ my %lt = &Apache::lonlocal::texthash (
+ more => 'More ...',
+ less => 'Less ...',
+ );
+ return <<ENDSCRIPT;
+
+<script type="text/javascript">
+// <![CDATA[
+
function showTriggerDetails(item) {
document.getElementById('trigdetails_'+item).style.display='block';
document.getElementById('trigdetails_'+item).style.textAlign='left';
Index: loncom/interface/lonselstudent.pm
diff -u loncom/interface/lonselstudent.pm:1.16 loncom/interface/lonselstudent.pm:1.17
--- loncom/interface/lonselstudent.pm:1.16 Sat Oct 22 01:53:27 2016
+++ loncom/interface/lonselstudent.pm Sat Oct 22 02:03:31 2016
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# lonselstudent.pm : Reusable subs for student selection.
#
-# $Id: lonselstudent.pm,v 1.16 2016/10/22 01:53:27 raeburn Exp $
+# $Id: lonselstudent.pm,v 1.17 2016/10/22 02:03:31 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -324,14 +324,20 @@
$result .= '<table><tr><td>';
my $size = scalar(keys(%sections));
- $size += 3; # We have allstudents allpersonel nosection too.
- if ($size > 5) {
+ if ($context eq 'accesstimes') {
+ $size += 2;
+ } else {
+ $size += 3; # We have allstudents allpersonel nosection too.
+ }
+ if ($size > 5) {
$size = 5;
}
$result .= '<select multiple="multiple" name="'.$formprefix
.'.chosensections" size="'.$size.'">'."\n";
$result .= '<option value="allstudents">'.&mt('All Students').'</option>';
- $result .= '<option value="allpersonnel">'.&mt('All Course Personnel').'</option>';
+ unless ($context eq 'accesstimes') {
+ $result .= '<option value="allpersonnel">'.&mt('All Course Personnel').'</option>';
+ }
$result .= '<option value="nosection">'.&mt('No Section').'</option>';
$result .= "\n";
foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%sections))) {
Index: loncom/loncapa_apache.conf
diff -u loncom/loncapa_apache.conf:1.248 loncom/loncapa_apache.conf:1.249
--- loncom/loncapa_apache.conf:1.248 Mon Jul 25 19:49:45 2016
+++ loncom/loncapa_apache.conf Sat Oct 22 02:04:32 2016
@@ -2,7 +2,7 @@
## loncapa_apache.conf -- Apache HTTP LON-CAPA configuration file
##
-# $Id: loncapa_apache.conf,v 1.248 2016/07/25 19:49:45 raeburn Exp $
+# $Id: loncapa_apache.conf,v 1.249 2016/10/22 02:04:32 raeburn Exp $
#
# LON-CAPA Section (extensions to httpd.conf daemon configuration)
@@ -1440,6 +1440,17 @@
PerlHandler Apache::lonblockingstatus
</Location>
+<Location /adm/accesstimes>
+AuthType LONCAPA
+Require valid-user
+PerlAuthzHandler Apache::lonacc
+SetHandler perl-script
+PerlHandler Apache::lonaccesstimes
+ErrorDocument 403 /adm/login
+ErrorDocument 406 /adm/roles
+ErrorDocument 500 /adm/errorhandler
+</Location>
+
<Location /adm/errorhandler>
SetHandler perl-script
PerlHandler Apache::lonerrorhandler
@@ -1691,7 +1702,7 @@
# ******** THESE "SHOULD" NEVER BE ALTERED BY THE USER ************************
# ====================================== Internal Settings / Perl Configuration
-PerlSetVar lonVersion '<!-- VERSION -->'
+PerlSetVar lonVersion '2.12.CVS_HEAD-2016091320'
PerlSetVar lonIDsDir /home/httpd/lonIDs
PerlSetVar lonDAVsessDir /home/httpd/webdav/sessionIDs
PerlSetVar lonTabDir /home/httpd/lonTabs
Index: loncom/startup.pl
diff -u loncom/startup.pl:1.41 loncom/startup.pl:1.42
--- loncom/startup.pl:1.41 Mon Mar 5 21:18:21 2012
+++ loncom/startup.pl Sat Oct 22 02:04:32 2016
@@ -1,5 +1,5 @@
#!/usr/bin/perl
-# $Id: startup.pl,v 1.41 2012/03/05 21:18:21 raeburn Exp $
+# $Id: startup.pl,v 1.42 2016/10/22 02:04:32 raeburn Exp $
BEGIN {
eval "use Apache2::compat();";
@@ -154,6 +154,7 @@
use Apache::courseprefs();
use Apache::domainprefs();
use Apache::lonblockingmenu();
+use Apache::lonaccesstimes();
use Apache::lonshibauth();
use Apache::lonshibacc();
1;
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.941 doc/loncapafiles/loncapafiles.lpml:1.942
--- doc/loncapafiles/loncapafiles.lpml:1.941 Mon Sep 19 03:19:25 2016
+++ doc/loncapafiles/loncapafiles.lpml Sat Oct 22 02:05:53 2016
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.941 2016/09/19 03:19:25 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.942 2016/10/22 02:05:53 raeburn Exp $ -->
<!--
@@ -8768,6 +8768,17 @@
<status>works/unverified</status>
</file>
<file>
+<source>loncom/interface/lonaccesstimes.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/lonaccesstimes.pm</target>
+<categoryname>handler</categoryname>
+<description>
+ Handler to display first access times for selected students for a
+specified folder, resource or course-wide, for roles with rights to
+view grades, but not edit them.
+</description>
+<status>works/unverified</status>
+</file>
+<file>
<source>loncom/automation/Autocreate.pl</source>Autocreate.pl
<target dist='default'>home/httpd/perl/Autocreate.pl</target>
<categoryname>script</categoryname>
Index: loncom/interface/lonaccesstimes.pm
+++ loncom/interface/lonaccesstimes.pm
# The LearningOnline Network with CAPA
# Display first access times for timed (interval) items for active
# students in a course.
#
# $Id: lonaccesstimes.pm,v 1.1 2016/10/22 02:03:31 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
##############################################################
##############################################################
=pod
=head1 NAME
lonaccesstimes - Handler to display first access times for timed (interval)
items.
=head1 SYNOPSIS
lonaccess times provides an interface for displaying first access times
for timed (interval) items for active students in a course.
=head1 DESCRIPTION
This module is used to display first access times for items in a course
set when a student pushes "Show Resource" to begin a timed (interval) quiz.
=head1 OVERVIEW
Users with the vgr privilege in a course can use /adm/accesstimes to view
first access times set by users with unexpired student roles in a course,
for all resources or maps for which the interval parameter is set.
The first access is stored when a student pushed the "Show Resource" button
to start the timer to gain access to a timed quiz or exam.
Users with the mgr privilege can use the "Reset Student Access Times" helper
to reset access times, in case of network trouble having prevented a student
from completing a timed quiz/exam.
This module is provided for use by helpdesk staff who may receive the vgr
privilege in a course, but not the mgr privilege, so they can advise students
or faculty who contact the helpdesk on what to do if access to a timed quiz
needs to be provided to a student after the clock has run out.
=head1 INTERNAL SUBROUTINES
=over
=item &print_selectors()
Prints page used to select a single item using the interval parameter, and
one or more enrolled students/members for whom first access times are to
be displayed for that item (specific resource, map, or course-wide).
Inputs: 2
$r - Request object.
$crstype - Course type (either Course or Community).
Outputs: none
Side Effects: prints web page containing items for which timed (interval)
parameters have been set (use radio buttons to select one),
and also a table of users with active student roles, with
checkboxes to select users.
=item &print_results()
Prints first access times found for specified item (resource, map or course)
and specified students.
Inputs: 2
$r - Request object.
$crstype - Course type (either Course or Community).
Outputs: none
Side Effects: prints web page containing first access times.
=back
=cut
package Apache::lonaccesstimes;
use strict;
use Apache::lonnet;
use Apache::Constants qw(:common :http);
use Apache::loncommon();
use Apache::lonblockingmenu();
use Apache::lonselstudent();
use Apache::lonlocal;
use lib '/home/httpd/lib/perl/';
use LONCAPA qw(:DEFAULT :match);
sub handler {
my $r = shift;
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
# Needs to be in a course
if (! ($env{'request.course.fn'})) {
# Not in a course
$env{'user.error.msg'}=
"/adm/accesstimes:vgr:0:0:Cannot view first access times for timed items in a course";
return HTTP_NOT_ACCEPTABLE;
}
# ----------------------------------------------------------- Permissions check
unless ((&Apache::lonnet::allowed('vgr',$env{'request.course.id'})) ||
(&Apache::lonnet::allowed('vgr',$env{'request.course.id'}.
'/'.$env{'request.course.sec'}))) {
$env{'user.error.msg'}=
"/adm/setblock:vgr:0:0:Cannot view first access times for timed items in a course";
return HTTP_NOT_ACCEPTABLE;
}
# ------------------------------------------------------------------ Breadcrumbs
&Apache::lonhtmlcommon::clear_breadcrumbs();
&Apache::lonhtmlcommon::add_breadcrumb
({href=>'/adm/parmset',
text=>'Content and Problem Settings'});
&Apache::lonhtmlcommon::add_breadcrumb
({href=>'/adm/accesstimes',
text=>'First Access times for timed quizzes/exams'});
my $phase = $env{'form.phase'};
my $crstype = &Apache::loncommon::course_type();
# ------------------------------------------------------- Show first access times
if ($phase eq 'display') {
&Apache::lonhtmlcommon::add_breadcrumb
({href=>'/adm/accesstimes',
text=>'Results'});
$r->print(
&Apache::loncommon::start_page('Display first access times').
&Apache::lonhtmlcommon::breadcrumbs('First access times'));
&print_results($r,$crstype);
} else {
my $js = &Apache::lonblockingmenu::details_javascript();
$r->print(
&Apache::loncommon::start_page('Filters for first access times',$js).
&Apache::lonhtmlcommon::breadcrumbs('First access times'));
&print_selectors($r,$crstype);
}
$r->print(&Apache::loncommon::end_page());
return OK;
}
sub print_selectors {
my ($r,$crstype) = @_;
# ------------------------------------------------------ Retrieve active students
my ($course_personnel,
$current_members,
$expired_members,
$future_members) =
&Apache::lonselstudent::get_people_in_class($env{'request.course.sec'});
# ---------------------------------------------------- Get Time Limit parameters
my %intervals = &Apache::lonblockingmenu::get_timed_items();
# ------------------------------------------------------------- Display selectors
$r->print('<form name="accessform" method="post" action="/adm/accesstimes">');
if ((ref($current_members) eq 'ARRAY') && (@{$current_members} > 0) && (keys(%intervals) > 0)) {
my %titles = &Apache::lonlocal::texthash(
'intervals' => 'Select timed interval setting (for course, folder or resource)',
'active' => 'Select from currently enrolled students',
);
if ($crstype eq 'Community') {
$titles{'active'} = &mt('Select from current community members');
}
if ($env{'request.course.sec'}) {
$titles{'active'} = &mt('Select from currently enrolled students in section: [_1]',
$env{'request.course.sec'});
if ($crstype eq 'Community') {
$titles{'active'} = &mt('Select from current community members in section: [_1]',
$env{'request.course.sec'});
}
}
my $navmap = Apache::lonnavmaps::navmap->new();
if (!ref($navmap)) {
$r->print('<p class="LC_error">'.&mt('Failed to retrieve course contents').'</p>');
} else {
my $parmcount = 0;
$r->print('<h4>'.$titles{'intervals'}.'</h4>'.
&Apache::lonblockingmenu::create_interval_form(\%intervals,$parmcount,$navmap,'accesstimes').
'<hr />');
my %default;
$r->print(
'<h4>'.$titles{'active'}.'</h4>'.
&Apache::lonselstudent::render_student_list( $current_members,
'accessform',
'current',
\%default,1,'firstaccess',1,
'accesstimes'));
}
$r->print('<input type="hidden" name="phase" value="display" />'.
'<input type="submit" name="display" value="'.&mt('Display First Access Times').'" />');
} else {
if ((ref($current_members) eq 'ARRAY') && (@{$current_members} == 0)) {
if ($env{'request.course.sec'}) {
if ($crstype eq 'Community') {
$r->print('<p class="LC_info">'.&mt('No current community members in section [_1]',
$env{'request.course.sec'}).'</p>');
} else {
$r->print('<p class="LC_info">'.&mt('No students currently enrolled in section [_1]',
$env{'request.course.sec'}).'</p>');
}
} else {
if ($crstype eq 'Community') {
$r->print('<p class="LC_info">'.&mt('No current community members').'</p>');
} else {
$r->print('<p class="LC_info">'.&mt('No students currently enrolled').'</p>');
}
}
}
if (keys(%intervals) == 0) {
$r->print('<p class="LC_info">'.&mt('No timed interval settings currently apply to course, folder(s) or resource(s)').'</p>');
}
}
$r->print('</form>');
}
sub print_results {
my ($r,$crstype) = @_;
my $usertype = &Apache::lonnet::plaintext('st',$crstype);
my $item = $env{'form.firstaccess_0'};
my $title;
if ($item ne '') {
my $symb;
if ($item =~ /\.(sequence|page)$/) {
if (&Apache::lonnet::is_on_map($item)) {
my $navmap = Apache::lonnavmaps::navmap->new();
if (ref($navmap)) {
my $mapres = $navmap->getResourceByUrl($item);
if (ref($mapres)) {
$symb = $mapres->symb();
$title = $mapres->compTitle();
} else {
$title = &Apache::lonnet::gettitle($item);
}
my ($path,$hierarchy);
$hierarchy = &Apache::lonblockingmenu::show_timer_path('map',$item,$navmap);
if ($hierarchy) {
$path = ' <span style="font-size:90%;">'.
&mt('(in: [_1])',$hierarchy).
'</span>';
}
$title = &mt('Timer for all items in folder: [_1]',
'<i>'.$title.'</i>').$path;
} else {
$r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
}
} else {
$r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
}
} elsif ($item eq 'course') {
$symb = $item;
$title = &mt('Timer for all items in course');
} else {
my $navmap = Apache::lonnavmaps::navmap->new();
if (ref($navmap)) {
my $resobj = $navmap->getBySymb($item);
my ($path,$hierarchy);
if (ref($resobj)) {
$symb = $item;
$title = $resobj->compTitle();
}
if ($title eq '') {
$title = &Apache::lonnet::gettitle($item);
}
$hierarchy = &show_timer_path('resource',$item,$navmap);
if ($hierarchy) {
$path = ' <span style="font-size:90%;">'.
&mt('(in: [_1])',$hierarchy).
'</span>';
}
$title = &mt('Timer for resource: [_1]','<i>'.$title.'</i>').
$path;
}
}
if ($symb) {
if ($title) {
$r->print('<h3>'.$title.'</h3>');
}
my @students = &Apache::loncommon::get_env_multiple('form.firstaccess_forminput');
if (@students) {
my ($course_personnel,
$current_members,
$expired_members,
$future_members) =
&Apache::lonselstudent::get_people_in_class($env{'request.course.sec'});
my %active;
if (ref($current_members) eq 'ARRAY') {
map { $active{$_->[0]} = 1; } @{$current_members};
}
#my $shownheader = 0;
my (@hasaccess, at noaccess);
my $key=$env{'request.course.id'}."\0".$symb;
foreach my $name (sort(@students)) {
my ($uname,$udom,$sec,$fullname)=split(':',$name);
next unless ($active{$uname.':'.$udom});
if (!$fullname) { $fullname="$uname:$udom"; }
my %times=&Apache::lonnet::get('firstaccesstimes',
[$key],$udom,$uname);
# unless ($shownheader) {
# $r->print('<ul>');
# $shownheader = 1;
# }
if (!$times{$key}) {
push(@noaccess,[$name,$fullname]);
# $r->print('<li>'.&mt("No access times found for $usertype [_1]",$fullname).'</li>');
} else {
push(@hasaccess,[$name,$fullname,$times{$key}]);
# $r->print('<li>'.&mt("First access time: [_1] found for $usertype [_2]",
# &Apache::lonlocal::locallocaltime($times{$key}),$fullname).'</li>');
}
}
if ((@hasaccess == 0) && (@noaccess == 0)) {
$r->print('<p class="LC_warning">'.&mt('No valid users selected to check for first access times').'</p>');
} else {
if (@hasaccess > 0) {
$r->print('<h4>'.&mt("Access times found for [quant,_1,$usertype]",scalar(@hasaccess)).'</h4>'.
'<p>'.&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
'<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
'<th>'.&mt('First access time').'</th>'.
&Apache::loncommon::end_data_table_header_row());
foreach my $item (@hasaccess) {
if (ref($item) eq 'ARRAY') {
$r->print(&Apache::loncommon::start_data_table_row().
'<td>'.$item->[0].'</td>'.
'<td>'.$item->[1].'</td>'.
'<td>'.&Apache::lonlocal::locallocaltime($item->[2]).'</td>'.
&Apache::loncommon::start_data_table_row());
}
}
$r->print(&Apache::loncommon::end_data_table().'</p>');
}
if (@noaccess > 0) {
$r->print('<h4>'.&mt("No access times found for [quant,_1,$usertype]",scalar(@noaccess)).'</h4>'.
'<p>'.&Apache::loncommon::start_data_table().
&Apache::loncommon::start_data_table_header_row().
'<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
&Apache::loncommon::end_data_table_header_row());
foreach my $item (@noaccess) {
if (ref($item) eq 'ARRAY') {
$r->print(&Apache::loncommon::start_data_table_row().
'<td>'.$item->[0].'</td>'.
'<td>'.$item->[1].'</td>'.
&Apache::loncommon::start_data_table_row());
}
}
$r->print(&Apache::loncommon::end_data_table().'</p>');
}
}
# if ($shownheader) {
# $r->print('</ul>');
# } else {
# $r->print('<p class="LC_warning">'.&mt('No valid users selected').'</p>');
# }
} else {
if ($crstype eq 'Community') {
$r->print('<p class="LC_warning">'.&mt('No members selected to check for first access times').'</p>');
} else {
$r->print('<p class="LC_warning">'.&mt('No students selected to check for first access times').'</p>');
}
}
} else {
$r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
}
} else {
$r->print('<p class="LC_warning">'.&mt('No item selected to check for first access times').'</p>');
}
return;
}
1;
__END__
More information about the LON-CAPA-cvs
mailing list