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>