[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