Annotation of loncom/interface/lonaccesstimes.pm, revision 1.2
1.1 raeburn 1: # The LearningOnline Network with CAPA
2: # Display first access times for timed (interval) items for active
3: # students in a course.
4: #
1.2 ! raeburn 5: # $Id: lonaccesstimes.pm,v 1.1 2016/10/22 02:03:31 raeburn Exp $
1.1 raeburn 6: #
7: # Copyright Michigan State University Board of Trustees
8: #
9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
10: #
11: # LON-CAPA is free software; you can redistribute it and/or modify
12: # it under the terms of the GNU General Public License as published by
13: # the Free Software Foundation; either version 2 of the License, or
14: # (at your option) any later version.
15: #
16: # LON-CAPA is distributed in the hope that it will be useful,
17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: # GNU General Public License for more details.
20: #
21: # You should have received a copy of the GNU General Public License
22: # along with LON-CAPA; if not, write to the Free Software
23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24: #
25: # /home/httpd/html/adm/gpl.txt
26: #
27: # http://www.lon-capa.org/
28: #
29: ##############################################################
30: ##############################################################
31:
32: =pod
33:
34: =head1 NAME
35:
36: lonaccesstimes - Handler to display first access times for timed (interval)
37: items.
38:
39: =head1 SYNOPSIS
40:
41: lonaccess times provides an interface for displaying first access times
42: for timed (interval) items for active students in a course.
43:
44: =head1 DESCRIPTION
45:
46: This module is used to display first access times for items in a course
47: set when a student pushes "Show Resource" to begin a timed (interval) quiz.
48:
49: =head1 OVERVIEW
50:
51: Users with the vgr privilege in a course can use /adm/accesstimes to view
52: first access times set by users with unexpired student roles in a course,
53: for all resources or maps for which the interval parameter is set.
54:
55: The first access is stored when a student pushed the "Show Resource" button
56: to start the timer to gain access to a timed quiz or exam.
57:
58: Users with the mgr privilege can use the "Reset Student Access Times" helper
59: to reset access times, in case of network trouble having prevented a student
60: from completing a timed quiz/exam.
61:
62: This module is provided for use by helpdesk staff who may receive the vgr
63: privilege in a course, but not the mgr privilege, so they can advise students
64: or faculty who contact the helpdesk on what to do if access to a timed quiz
65: needs to be provided to a student after the clock has run out.
66:
67: =head1 INTERNAL SUBROUTINES
68:
69: =over
70:
71: =item &print_selectors()
72:
73: Prints page used to select a single item using the interval parameter, and
74: one or more enrolled students/members for whom first access times are to
75: be displayed for that item (specific resource, map, or course-wide).
76:
77: Inputs: 2
78: $r - Request object.
79:
80: $crstype - Course type (either Course or Community).
81:
82: Outputs: none
83:
84: Side Effects: prints web page containing items for which timed (interval)
85: parameters have been set (use radio buttons to select one),
86: and also a table of users with active student roles, with
87: checkboxes to select users.
88:
89: =item &print_results()
90:
91: Prints first access times found for specified item (resource, map or course)
92: and specified students.
93:
94: Inputs: 2
95: $r - Request object.
96:
97: $crstype - Course type (either Course or Community).
98:
99: Outputs: none
100:
101: Side Effects: prints web page containing first access times.
102:
103:
104: =back
105:
106: =cut
107:
108: package Apache::lonaccesstimes;
109:
110: use strict;
111: use Apache::lonnet;
112: use Apache::Constants qw(:common :http);
113: use Apache::loncommon();
114: use Apache::lonblockingmenu();
115: use Apache::lonselstudent();
116: use Apache::lonlocal;
117: use lib '/home/httpd/lib/perl/';
118: use LONCAPA qw(:DEFAULT :match);
119:
120: sub handler {
121: my $r = shift;
122:
123: &Apache::loncommon::content_type($r,'text/html');
124: $r->send_http_header;
125:
126: return OK if $r->header_only;
127:
128: # Needs to be in a course
129: if (! ($env{'request.course.fn'})) {
130: # Not in a course
131: $env{'user.error.msg'}=
132: "/adm/accesstimes:vgr:0:0:Cannot view first access times for timed items in a course";
133: return HTTP_NOT_ACCEPTABLE;
134: }
135:
136: # ----------------------------------------------------------- Permissions check
137:
138: unless ((&Apache::lonnet::allowed('vgr',$env{'request.course.id'})) ||
139: (&Apache::lonnet::allowed('vgr',$env{'request.course.id'}.
140: '/'.$env{'request.course.sec'}))) {
141: $env{'user.error.msg'}=
142: "/adm/setblock:vgr:0:0:Cannot view first access times for timed items in a course";
143: return HTTP_NOT_ACCEPTABLE;
144: }
145:
146: # ------------------------------------------------------------------ Breadcrumbs
147: &Apache::lonhtmlcommon::clear_breadcrumbs();
148: &Apache::lonhtmlcommon::add_breadcrumb
149: ({href=>'/adm/parmset',
150: text=>'Content and Problem Settings'});
151: &Apache::lonhtmlcommon::add_breadcrumb
152: ({href=>'/adm/accesstimes',
153: text=>'First Access times for timed quizzes/exams'});
154:
155: my $phase = $env{'form.phase'};
156: my $crstype = &Apache::loncommon::course_type();
157:
158: # ------------------------------------------------------- Show first access times
159: if ($phase eq 'display') {
160: &Apache::lonhtmlcommon::add_breadcrumb
161: ({href=>'/adm/accesstimes',
162: text=>'Results'});
163: $r->print(
164: &Apache::loncommon::start_page('Display first access times').
165: &Apache::lonhtmlcommon::breadcrumbs('First access times'));
166: &print_results($r,$crstype);
167: } else {
168: my $js = &Apache::lonblockingmenu::details_javascript();
169: $r->print(
170: &Apache::loncommon::start_page('Filters for first access times',$js).
171: &Apache::lonhtmlcommon::breadcrumbs('First access times'));
172: &print_selectors($r,$crstype);
173: }
174: $r->print(&Apache::loncommon::end_page());
175: return OK;
176: }
177:
178: sub print_selectors {
179: my ($r,$crstype) = @_;
180:
181: # ------------------------------------------------------ Retrieve active students
182:
183: my ($course_personnel,
184: $current_members,
185: $expired_members,
186: $future_members) =
187: &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'});
188:
189: # ---------------------------------------------------- Get Time Limit parameters
190:
191: my %intervals = &Apache::lonblockingmenu::get_timed_items();
192:
193: # ------------------------------------------------------------- Display selectors
194:
195: $r->print('<form name="accessform" method="post" action="/adm/accesstimes">');
196:
197: if ((ref($current_members) eq 'ARRAY') && (@{$current_members} > 0) && (keys(%intervals) > 0)) {
198: my %titles = &Apache::lonlocal::texthash(
199: 'intervals' => 'Select timed interval setting (for course, folder or resource)',
200: 'active' => 'Select from currently enrolled students',
201: );
202: if ($crstype eq 'Community') {
203: $titles{'active'} = &mt('Select from current community members');
204: }
205:
206: if ($env{'request.course.sec'}) {
207: $titles{'active'} = &mt('Select from currently enrolled students in section: [_1]',
208: $env{'request.course.sec'});
209: if ($crstype eq 'Community') {
210: $titles{'active'} = &mt('Select from current community members in section: [_1]',
211: $env{'request.course.sec'});
212: }
213: }
214: my $navmap = Apache::lonnavmaps::navmap->new();
215:
216: if (!ref($navmap)) {
217: $r->print('<p class="LC_error">'.&mt('Failed to retrieve course contents').'</p>');
218: } else {
219: my $parmcount = 0;
220: $r->print('<h4>'.$titles{'intervals'}.'</h4>'.
221: &Apache::lonblockingmenu::create_interval_form(\%intervals,$parmcount,$navmap,'accesstimes').
222: '<hr />');
223: my %default;
224: $r->print(
225: '<h4>'.$titles{'active'}.'</h4>'.
226: &Apache::lonselstudent::render_student_list( $current_members,
227: 'accessform',
228: 'current',
229: \%default,1,'firstaccess',1,
230: 'accesstimes'));
231: }
232: $r->print('<input type="hidden" name="phase" value="display" />'.
233: '<input type="submit" name="display" value="'.&mt('Display First Access Times').'" />');
234: } else {
235: if ((ref($current_members) eq 'ARRAY') && (@{$current_members} == 0)) {
236: if ($env{'request.course.sec'}) {
237: if ($crstype eq 'Community') {
238: $r->print('<p class="LC_info">'.&mt('No current community members in section [_1]',
239: $env{'request.course.sec'}).'</p>');
240: } else {
241: $r->print('<p class="LC_info">'.&mt('No students currently enrolled in section [_1]',
242: $env{'request.course.sec'}).'</p>');
243: }
244: } else {
245: if ($crstype eq 'Community') {
246: $r->print('<p class="LC_info">'.&mt('No current community members').'</p>');
247: } else {
248: $r->print('<p class="LC_info">'.&mt('No students currently enrolled').'</p>');
249: }
250: }
251: }
252: if (keys(%intervals) == 0) {
253: $r->print('<p class="LC_info">'.&mt('No timed interval settings currently apply to course, folder(s) or resource(s)').'</p>');
254: }
255: }
256: $r->print('</form>');
257: }
258:
259: sub print_results {
260: my ($r,$crstype) = @_;
261: my $usertype = &Apache::lonnet::plaintext('st',$crstype);
262: my $item = $env{'form.firstaccess_0'};
263: my $title;
264: if ($item ne '') {
265: my $symb;
266: if ($item =~ /\.(sequence|page)$/) {
267: if (&Apache::lonnet::is_on_map($item)) {
268: my $navmap = Apache::lonnavmaps::navmap->new();
269: if (ref($navmap)) {
270: my $mapres = $navmap->getResourceByUrl($item);
271: if (ref($mapres)) {
272: $symb = $mapres->symb();
273: $title = $mapres->compTitle();
274: } else {
275: $title = &Apache::lonnet::gettitle($item);
276: }
277: my ($path,$hierarchy);
278: $hierarchy = &Apache::lonblockingmenu::show_timer_path('map',$item,$navmap);
279: if ($hierarchy) {
280: $path = ' <span style="font-size:90%;">'.
281: &mt('(in: [_1])',$hierarchy).
282: '</span>';
283: }
284: $title = &mt('Timer for all items in folder: [_1]',
285: '<i>'.$title.'</i>').$path;
286: } else {
287: $r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
288: }
289: } else {
290: $r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
291: }
292: } elsif ($item eq 'course') {
293: $symb = $item;
294: $title = &mt('Timer for all items in course');
295: } else {
296: my $navmap = Apache::lonnavmaps::navmap->new();
297: if (ref($navmap)) {
298: my $resobj = $navmap->getBySymb($item);
299: my ($path,$hierarchy);
300: if (ref($resobj)) {
301: $symb = $item;
302: $title = $resobj->compTitle();
303: }
304: if ($title eq '') {
305: $title = &Apache::lonnet::gettitle($item);
306: }
1.2 ! raeburn 307: $hierarchy = &Apache::lonblockingmenu::show_timer_path('resource',$item,$navmap);
1.1 raeburn 308: if ($hierarchy) {
309: $path = ' <span style="font-size:90%;">'.
310: &mt('(in: [_1])',$hierarchy).
311: '</span>';
312: }
313: $title = &mt('Timer for resource: [_1]','<i>'.$title.'</i>').
314: $path;
315: }
316: }
317: if ($symb) {
318: if ($title) {
319: $r->print('<h3>'.$title.'</h3>');
320: }
321: my @students = &Apache::loncommon::get_env_multiple('form.firstaccess_forminput');
322: if (@students) {
323: my ($course_personnel,
324: $current_members,
325: $expired_members,
326: $future_members) =
327: &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'});
328: my %active;
329: if (ref($current_members) eq 'ARRAY') {
330: map { $active{$_->[0]} = 1; } @{$current_members};
331: }
332: my (@hasaccess,@noaccess);
333: my $key=$env{'request.course.id'}."\0".$symb;
334: foreach my $name (sort(@students)) {
335: my ($uname,$udom,$sec,$fullname)=split(':',$name);
336: next unless ($active{$uname.':'.$udom});
337: if (!$fullname) { $fullname="$uname:$udom"; }
338: my %times=&Apache::lonnet::get('firstaccesstimes',
339: [$key],$udom,$uname);
340: if (!$times{$key}) {
341: push(@noaccess,[$name,$fullname]);
342: } else {
343: push(@hasaccess,[$name,$fullname,$times{$key}]);
344: }
345: }
346: if ((@hasaccess == 0) && (@noaccess == 0)) {
347: $r->print('<p class="LC_warning">'.&mt('No valid users selected to check for first access times').'</p>');
348: } else {
349: if (@hasaccess > 0) {
350: $r->print('<h4>'.&mt("Access times found for [quant,_1,$usertype]",scalar(@hasaccess)).'</h4>'.
351: '<p>'.&Apache::loncommon::start_data_table().
352: &Apache::loncommon::start_data_table_header_row().
353: '<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
354: '<th>'.&mt('First access time').'</th>'.
355: &Apache::loncommon::end_data_table_header_row());
356: foreach my $item (@hasaccess) {
357: if (ref($item) eq 'ARRAY') {
358: $r->print(&Apache::loncommon::start_data_table_row().
359: '<td>'.$item->[0].'</td>'.
360: '<td>'.$item->[1].'</td>'.
361: '<td>'.&Apache::lonlocal::locallocaltime($item->[2]).'</td>'.
362: &Apache::loncommon::start_data_table_row());
363: }
364: }
365: $r->print(&Apache::loncommon::end_data_table().'</p>');
366: }
367: if (@noaccess > 0) {
368: $r->print('<h4>'.&mt("No access times found for [quant,_1,$usertype]",scalar(@noaccess)).'</h4>'.
369: '<p>'.&Apache::loncommon::start_data_table().
370: &Apache::loncommon::start_data_table_header_row().
371: '<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
372: &Apache::loncommon::end_data_table_header_row());
373: foreach my $item (@noaccess) {
374: if (ref($item) eq 'ARRAY') {
375: $r->print(&Apache::loncommon::start_data_table_row().
376: '<td>'.$item->[0].'</td>'.
377: '<td>'.$item->[1].'</td>'.
378: &Apache::loncommon::start_data_table_row());
379: }
380: }
381: $r->print(&Apache::loncommon::end_data_table().'</p>');
382: }
383: }
384: } else {
385: if ($crstype eq 'Community') {
386: $r->print('<p class="LC_warning">'.&mt('No members selected to check for first access times').'</p>');
387: } else {
388: $r->print('<p class="LC_warning">'.&mt('No students selected to check for first access times').'</p>');
389: }
390: }
391: } else {
392: $r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
393: }
394: } else {
395: $r->print('<p class="LC_warning">'.&mt('No item selected to check for first access times').'</p>');
396: }
397: return;
398: }
399:
400: 1;
401:
402: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>