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>