Annotation of loncom/interface/lonaccesstimes.pm, revision 1.1
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: #
! 5: # $Id: lonaccesstimes.pm,v 1.1 2016/10/20 23:00:00 raeburn Exp $
! 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: }
! 307: $hierarchy = &show_timer_path('resource',$item,$navmap);
! 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 $shownheader = 0;
! 333: my (@hasaccess,@noaccess);
! 334: my $key=$env{'request.course.id'}."\0".$symb;
! 335: foreach my $name (sort(@students)) {
! 336: my ($uname,$udom,$sec,$fullname)=split(':',$name);
! 337: next unless ($active{$uname.':'.$udom});
! 338: if (!$fullname) { $fullname="$uname:$udom"; }
! 339: my %times=&Apache::lonnet::get('firstaccesstimes',
! 340: [$key],$udom,$uname);
! 341: # unless ($shownheader) {
! 342: # $r->print('<ul>');
! 343: # $shownheader = 1;
! 344: # }
! 345: if (!$times{$key}) {
! 346: push(@noaccess,[$name,$fullname]);
! 347: # $r->print('<li>'.&mt("No access times found for $usertype [_1]",$fullname).'</li>');
! 348: } else {
! 349: push(@hasaccess,[$name,$fullname,$times{$key}]);
! 350: # $r->print('<li>'.&mt("First access time: [_1] found for $usertype [_2]",
! 351: # &Apache::lonlocal::locallocaltime($times{$key}),$fullname).'</li>');
! 352: }
! 353: }
! 354: if ((@hasaccess == 0) && (@noaccess == 0)) {
! 355: $r->print('<p class="LC_warning">'.&mt('No valid users selected to check for first access times').'</p>');
! 356: } else {
! 357: if (@hasaccess > 0) {
! 358: $r->print('<h4>'.&mt("Access times found for [quant,_1,$usertype]",scalar(@hasaccess)).'</h4>'.
! 359: '<p>'.&Apache::loncommon::start_data_table().
! 360: &Apache::loncommon::start_data_table_header_row().
! 361: '<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
! 362: '<th>'.&mt('First access time').'</th>'.
! 363: &Apache::loncommon::end_data_table_header_row());
! 364: foreach my $item (@hasaccess) {
! 365: if (ref($item) eq 'ARRAY') {
! 366: $r->print(&Apache::loncommon::start_data_table_row().
! 367: '<td>'.$item->[0].'</td>'.
! 368: '<td>'.$item->[1].'</td>'.
! 369: '<td>'.&Apache::lonlocal::locallocaltime($item->[2]).'</td>'.
! 370: &Apache::loncommon::start_data_table_row());
! 371: }
! 372: }
! 373: $r->print(&Apache::loncommon::end_data_table().'</p>');
! 374: }
! 375: if (@noaccess > 0) {
! 376: $r->print('<h4>'.&mt("No access times found for [quant,_1,$usertype]",scalar(@noaccess)).'</h4>'.
! 377: '<p>'.&Apache::loncommon::start_data_table().
! 378: &Apache::loncommon::start_data_table_header_row().
! 379: '<th>'.&mt('User').'</th><th>'.&mt('Fullname').'</th>'.
! 380: &Apache::loncommon::end_data_table_header_row());
! 381: foreach my $item (@noaccess) {
! 382: if (ref($item) eq 'ARRAY') {
! 383: $r->print(&Apache::loncommon::start_data_table_row().
! 384: '<td>'.$item->[0].'</td>'.
! 385: '<td>'.$item->[1].'</td>'.
! 386: &Apache::loncommon::start_data_table_row());
! 387: }
! 388: }
! 389: $r->print(&Apache::loncommon::end_data_table().'</p>');
! 390: }
! 391: }
! 392: # if ($shownheader) {
! 393: # $r->print('</ul>');
! 394: # } else {
! 395: # $r->print('<p class="LC_warning">'.&mt('No valid users selected').'</p>');
! 396: # }
! 397: } else {
! 398: if ($crstype eq 'Community') {
! 399: $r->print('<p class="LC_warning">'.&mt('No members selected to check for first access times').'</p>');
! 400: } else {
! 401: $r->print('<p class="LC_warning">'.&mt('No students selected to check for first access times').'</p>');
! 402: }
! 403: }
! 404: } else {
! 405: $r->print('<p class="LC_warning">'.&mt('Could not find time interval setting for selected item').'</p>');
! 406: }
! 407: } else {
! 408: $r->print('<p class="LC_warning">'.&mt('No item selected to check for first access times').'</p>');
! 409: }
! 410: return;
! 411: }
! 412:
! 413: 1;
! 414:
! 415: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>