File:  [LON-CAPA] / loncom / interface / lontrackstudent.pm
Revision 1.27: download - view: text, annotated - select for diffs
Thu Mar 26 16:30:58 2009 UTC (15 years, 1 month ago) by bisitz
Branches: MAIN
CVS tags: HEAD
Little optimizations:
- Optimized &mt usage and related translation changes
- Use standard style for info message
- Added horizontal line before "Resubmit" link
  as a quick solution for a better separation of content and menu functions

    1: # The LearningOnline Network with CAPA
    2: #
    3: # $Id: lontrackstudent.pm,v 1.27 2009/03/26 16:30:58 bisitz Exp $
    4: #
    5: # Copyright Michigan State University Board of Trustees
    6: #
    7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    8: #
    9: # LON-CAPA is free software; you can redistribute it and/or modify
   10: # it under the terms of the GNU General Public License as published by
   11: # the Free Software Foundation; either version 2 of the License, or
   12: # (at your option) any later version.
   13: #
   14: # LON-CAPA is distributed in the hope that it will be useful,
   15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17: # GNU General Public License for more details.
   18: #
   19: # You should have received a copy of the GNU General Public License
   20: # along with LON-CAPA; if not, write to the Free Software
   21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: # http://www.lon-capa.org/
   26: #
   27: ###
   28: 
   29: =pod
   30: 
   31: =head1 NAME
   32: 
   33: lontrackstudent
   34: 
   35: =head1 SYNOPSIS
   36: 
   37: Track student progress through course materials
   38: 
   39: =over 4
   40: 
   41: =cut
   42: 
   43: package Apache::lontrackstudent;
   44: 
   45: use strict;
   46: use Apache::Constants qw(:common :http);
   47: use Apache::lonmysql;
   48: use Apache::lonnet;
   49: use Apache::lonlocal;
   50: use Time::HiRes;
   51: use DateTime();
   52: use lib '/home/httpd/lib/perl/';
   53: use LONCAPA;
   54: 
   55: my $num_records=500;
   56: 
   57: sub get_data {
   58:     my ($r,$prog_state,$navmap,$mode) = @_;
   59:     ##
   60:     ## Compose the query
   61:     &Apache::lonhtmlcommon::Update_PrgWin
   62:         ($r,$prog_state,&mt('Composing Query'));
   63:     #
   64:     # Allow the other server to begin processing the data before we ask for it.
   65:     sleep(5);
   66:     #
   67:     my $max_time = &get_max_time_in_db($r,$prog_state);
   68:     if (defined($max_time)) {
   69:         $r->print('<h3>'.&mt('Activity data compiled up to [_1]',
   70:                              &Apache::lonlocal::locallocaltime($max_time)).
   71:                   '</h3>'.&mt('While data is processed, periodically reload this page for more recent activity').'<br />');
   72:         $r->rflush();
   73:     } else {
   74:         $r->print('<h3>'.&mt('Unable to retrieve any data.  Please reload this page and try again.').'</h3>');
   75:         return;
   76:     }
   77:     my $query = &build_query($mode);
   78:     ##
   79:     ## Send it along
   80:     my $home = $env{'course.'.$env{'request.course.id'}.'.home'};
   81:     my $reply=&Apache::lonnet::metadata_query($query,undef,undef,[$home]);
   82:     if (ref($reply) ne 'HASH') {
   83:         $r->print('<h2>'.
   84:                   &mt('Error contacting home server for course: [_1]',
   85:                       $reply).
   86:                   '</h2>');
   87:         return;
   88:     }
   89:     my $results_file = $r->dir_config('lonDaemons').'/tmp/'.$reply->{$home};
   90:     my $endfile = $results_file.'.end';
   91:     ##
   92:     ## Check for the results
   93:     &Apache::lonhtmlcommon::Update_PrgWin
   94:         ($r,$prog_state,&mt('Waiting for results'));
   95:     my $maxtime = 500;
   96:     my $starttime = time;
   97:     while (! -e $endfile && (time-$starttime < $maxtime)) {
   98:         &Apache::lonhtmlcommon::Update_PrgWin
   99:             ($r,$prog_state,&mt('Waiting up to [_1] seconds for results',
  100:                                 $starttime+$maxtime-time));
  101:         sleep(1);
  102:     }
  103:     if (! -e $endfile) {
  104:         $r->print('<h2>'.
  105:                   &mt('Unable to retrieve data.').'</h2>');
  106:         $r->print(&mt('Please try again in a few minutes.'));
  107:         return;
  108:     }
  109:     $r->rflush();
  110:     #
  111:     &Apache::lonhtmlcommon::Update_PrgWin
  112:         ($r,$prog_state,&mt('Parsing results'));
  113:     #
  114:     my $last = &output_results($r,$results_file,$navmap,$mode);
  115:     my ($sname,$sdom) = ($mode=~/^student:(.*):(.*)$/);
  116:     
  117:     my ($text,$inc);
  118:     if ( $last > 0 && (($last+1) >= $env{'form.start'}+$num_records) ) {
  119: 	$text = 'View more activity by this student';
  120: 	$inc  = $num_records;
  121: 	$r->print(&Apache::loncommon::track_student_link($text,$sname,$sdom,undef,
  122: 							 ($env{'form.start'}+$inc)
  123: 							 ));
  124: 	$r->print('<br />');
  125:     }
  126:     $r->print('<hr />');
  127:     $text = 'Resubmit last request to check for newer data';
  128:     $r->print(&Apache::loncommon::track_student_link($text,$sname,$sdom,undef,
  129: 						     $env{'form.start'}));
  130: 
  131:     &Apache::lonhtmlcommon::Update_PrgWin($r,$prog_state,&mt('Finished!'));
  132:     return;
  133: }
  134: 
  135: sub table_names {
  136:     my $cid = $env{'request.course.id'};
  137:     my $domain = $env{'course.'.$cid.'.domain'};
  138:     my $home = $env{'course.'.$cid.'.home'};
  139:     my $course = $env{'course.'.$cid.'.num'};
  140:     my $prefix = $course.'_'.$domain.'_';
  141:     #
  142:     my %tables = 
  143:         ( student =>&Apache::lonmysql::fix_table_name($prefix.'students'),
  144:           res     =>&Apache::lonmysql::fix_table_name($prefix.'resource'),
  145:           machine =>&Apache::lonmysql::fix_table_name($prefix.'machine_table'),
  146:           activity=>&Apache::lonmysql::fix_table_name($prefix.'activity'),
  147:           );
  148:     return %tables;
  149: }
  150: 
  151: sub get_max_time_in_db {
  152:     my ($r,$prog_state) = @_;
  153:     my %table = &table_names();
  154:     my $query = qq{SELECT MAX(time) FROM $table{'activity'} };
  155:     #
  156:     my $home = $env{'course.'.$env{'request.course.id'}.'.home'};
  157:     my $reply=&Apache::lonnet::metadata_query($query,undef,undef,[$home]);
  158:     if (ref($reply) ne 'HASH') {
  159:         return undef;
  160:     }
  161:     my $results_file = $r->dir_config('lonDaemons').'/tmp/'.$reply->{$home};
  162:     my $endfile = $results_file.'.end';
  163:     ##
  164:     ## Check for the results
  165:     &Apache::lonhtmlcommon::Update_PrgWin
  166:         ($r,$prog_state,&mt('Waiting for results'));
  167:     my $maxtime = 500;
  168:     my $starttime = time;
  169:     while (! -e $endfile && (time-$starttime < $maxtime)) {
  170:         &Apache::lonhtmlcommon::Update_PrgWin
  171:             ($r,$prog_state,&mt('Waiting up to [_1] seconds for results',
  172:                                 $starttime+$maxtime-time));
  173:         sleep(1);
  174:     }
  175:     if (! -e $endfile) {
  176:         $r->print('<h2>'.
  177:                   &mt('Unable to retrieve data.').'</h2>');
  178:         $r->print(&mt('Please try again in a few minutes.'));
  179:         return undef;
  180:     }
  181:     $r->rflush();
  182:     #
  183:     &Apache::lonhtmlcommon::Update_PrgWin
  184:         ($r,$prog_state,&mt('Parsing results'));
  185:     #
  186:     if (! open(TIMEDATA,$results_file)) {
  187:         $r->print('<h2>'.&mt('Unable to read results file.').'</h2>'.
  188:                   '<p>'.
  189:                   &mt('This is a serious error and has been logged.  '.
  190:                       'You should contact your system administrator '.
  191:                       'to resolve this issue.').
  192:                   '</p>');
  193:         return;
  194:     }
  195:     #
  196:     my $timestr = '';
  197:     while (my $line = <TIMEDATA>) {
  198:         chomp($line);
  199:         $timestr = &unescape($line);
  200:     }
  201:     close(TIMEDATA);
  202:     return &Apache::lonmysql::unsqltime($timestr);
  203: }
  204: 
  205: sub build_query {
  206:     my ($mode) = @_;
  207:     my $cid = $env{'request.course.id'};
  208:     my $domain = $env{'course.'.$cid.'.domain'};
  209:     my $home = $env{'course.'.$cid.'.home'};
  210:     my $course = $env{'course.'.$cid.'.num'};
  211:     my $prefix = $course.'_'.$domain.'_';
  212:     my $start = ($env{'form.start'}+0);
  213:     #
  214:     my %table = &table_names();
  215:     #
  216:     my $query;
  217:     if ($mode eq 'full_class') {
  218:         $query = qq{
  219:         SELECT B.resource,A.time,C.student,A.action,E.machine,A.action_values 
  220:             FROM $table{'activity'} AS A
  221:             LEFT JOIN $table{'res'}      AS B ON B.res_id=A.res_id 
  222:             LEFT JOIN $table{'student'}  AS C ON C.student_id=A.student_id 
  223:             LEFT JOIN $table{'machine'}  AS E ON E.machine_id=A.machine_id
  224:             ORDER BY A.time DESC
  225:             LIMIT $start, $num_records
  226:         };
  227:     } elsif ($mode =~ /^student:(.*):(.*)$/) {
  228:         my $student = $1.':'.$2;
  229:         $query = qq{
  230:             SELECT B.resource,A.time,A.action,E.machine,A.action_values 
  231:                 FROM $table{'activity'} AS A
  232:                 LEFT JOIN $table{'res'}      AS B ON B.res_id=A.res_id 
  233:                 LEFT JOIN $table{'student'}  AS C ON C.student_id=A.student_id 
  234:                 LEFT JOIN $table{'machine'}  AS E ON E.machine_id=A.machine_id
  235:                 WHERE C.student='$student'
  236:                 ORDER BY A.time DESC
  237:                 LIMIT $start, $num_records
  238:             };
  239:     }
  240:     $query =~ s|$/||g;
  241:     return $query;
  242: }
  243: 
  244: ###################################################################
  245: ###################################################################
  246: sub output_results {
  247:     my ($r,$results_file,$navmap,$mode) = @_;
  248:     ##
  249:     ##
  250:     if (! -s $results_file) {
  251:         # results file is empty, just let them know there is no data
  252:         $r->print('<h2>'.&mt('So far, no data has been returned for your request').'</h2>');
  253:         return -1;
  254:     }
  255:     if (! open(ACTIVITYDATA,$results_file)) {
  256:         $r->print('<h2>'.&mt('Unable to read results file.').'</h2>'.
  257:                   '<p>'.
  258:                   &mt('This is a serious error and has been logged.  '.
  259:                       'You should contact your system administrator '.
  260:                       'to resolve this issue.').
  261:                   '</p>');
  262:         return -2;
  263:     }
  264:     ##
  265:     ##
  266:     my $tableheader;
  267:     if ($mode eq 'full_class') { 
  268:         $tableheader = 
  269:             '<table><tr>'.
  270:             '<th>&nbsp;</th>'.
  271:             '<th>'.&mt('Resource').'</th>'.
  272:             '<th>'.&mt('Time').'</th>'.
  273:             '<th>'.&mt('Student').'</th>'.
  274:             '<th>'.&mt('Action').'</th>'.
  275:  #           '<th>'.&mt('Originating Server').'</th>'.
  276:             '<th align="left">'.&mt('Data').'</th>'.
  277:             '</tr>'.$/;
  278:     } elsif ($mode =~ /^student:(.*):(.*)$/) {
  279:         $tableheader = 
  280:             '<table><tr>'.
  281:             '<th>&nbsp;</th>'.
  282:             '<th>'.&mt('Resource').'</th>'.
  283:             '<th>'.&mt('Time').'</th>'.
  284:             '<th>'.&mt('Action').'</th>'.
  285:  #           '<th>'.&mt('Originating Server').'</th>'.
  286:             '<th align="left">'.&mt('Data').'</th>'.
  287:             '</tr>'.$/;
  288:     }
  289:     my $count = $env{'form.start'}-1;
  290:     $r->rflush();
  291:     ##
  292:     ##
  293: 
  294:     my $cid = $env{'request.course.id'};
  295:     my $cnum = $env{'course.'.$cid.'.num'};
  296:     my $cdom = $env{'course.'.$cid.'.domain'};   
  297:     my $server_timezone = &Apache::lonnet::get_server_timezone($cnum,$cdom);
  298:     if ($server_timezone ne '') {
  299:         if (&Apache::lonlocal::gettimezone($server_timezone) eq 'local') {
  300:             $server_timezone = '';
  301:         }
  302:     }
  303: 
  304:     while (my $line = <ACTIVITYDATA>) {
  305:         # FIXME: does not pass symbs along :(
  306:         chomp($line);
  307:         $line = &unescape($line);
  308:         if (++$count % 50 == 0) {
  309:             if ($count != 0) { 
  310:                 $r->print('</table>'.$/);
  311:                 $r->rflush();
  312:             }
  313:             $r->print($tableheader);
  314:         }
  315:         my ($symb,$timestamp,$student,$action,$machine,$values);
  316:         if ($mode eq 'full_class') {
  317:             ($symb,$timestamp,$student,$action,$machine,$values) = split(',',$line,6);
  318:         } else {
  319:             ($symb,$timestamp,$action,$machine,$values) = split(',',$line,5);
  320:         }
  321: 	foreach ($symb,$timestamp,$student,$action,$machine) {
  322: 	    $_=&unescape($_);
  323: 	}
  324:         my ($title,$src);
  325:         if ($symb =~ m:^/adm/:) {
  326:             $title = $symb;
  327:             $src = $symb;
  328:         } else {
  329:             my $nav_res = $navmap->getBySymb($symb);
  330:             if (defined($nav_res)) {
  331:                 $title = $nav_res->compTitle();
  332:                 $src   = $nav_res->src();
  333:             } else {
  334: 		$src = $symb;
  335: 		if ($src !~ m{/adm}) {
  336: 		    $title = &Apache::lonnet::gettitle($src);
  337: 		} elsif ($values =~ /^\s*$/ && 
  338: 		    (! defined($src) || $src =~ /^\s*$/)) {
  339:                     next;
  340:                 } elsif ($values =~ /^\s*$/) {
  341:                     $values = $src;
  342:                 } else {
  343:                     $title = 'unable to retrieve title';
  344:                     $src   = '/dev/null';
  345:                 }
  346:             }
  347:         }
  348:         my %classes;
  349:         my $class_count=0;
  350:         if (! exists($classes{$symb})) {
  351:             $classes{$symb} = $class_count++;
  352:         }
  353:         my $class = 'a';#.$classes{$symb};
  354:         #
  355:         if ($symb eq '/prtspool/') {
  356:             $class = 'print';
  357:             $title = 'retrieve printout';
  358:         } elsif ($symb =~ m|^/adm/([^/]+)|) {
  359:             $class = $1;
  360:         } elsif ($symb =~ m|^/adm/|) {
  361:             $class = 'adm';
  362:         }
  363:         if ($title eq 'unable to retrieve title') {
  364:             $title =~ s/ /\&nbsp;/g;
  365:             $class = 'warning';
  366:         }
  367:         if (! defined($title) || $title eq '') {
  368:             $title = 'untitled';
  369:             $class = 'warning';
  370:         }
  371:         # Clean up the values
  372: 	$values = &display_values($action,$values);
  373:         #
  374:         # Build the row for output
  375:         my $tablerow = qq{<tr class="$class"><td>}.($count+1).qq{</td>};
  376:         if ($src =~ m|^/adm/|) {
  377:             $tablerow .= 
  378:                 '<td valign="top"><span class="LC_nobreak">'.$title.'</span></td>';
  379:         } else {
  380:             $tablerow .= 
  381:                 '<td valign="top"><span class="LC_nobreak">'.
  382:                 '<a href="'.$src.'">'.$title.'</a>'.
  383:                 '</span></td>';
  384:         }
  385:         if ($server_timezone ne '') {
  386:             $timestamp = &convert_timezone($server_timezone,$timestamp);
  387:         }
  388:         $tablerow .= '<td valign="top"><span class="LC_nobreak">'.$timestamp.'</span></td>';
  389:         if ($mode eq 'full_class') {
  390:             $tablerow.='<td valign="top">'.$student.'</td>';
  391:         }
  392:         $tablerow .= 
  393:             '<td valign="top">'.$action.'</td>'.
  394: #            '<td>'.$machine.'</td>'.
  395:             '<td valign="top">'.$values.'</td>'.
  396:             '</tr>';
  397:         $r->print($tablerow.$/);
  398:     }
  399:     $r->print('</table>'.$/);### if (! $count % 50);
  400:     close(ACTIVITYDATA);
  401:     return $count;
  402: }
  403: 
  404: sub convert_timezone {
  405:     my ($server_timezone,$timestamp) = @_;
  406:     if ($server_timezone && $timestamp) {
  407:         my ($date,$time) = split(/\s+/,$timestamp);
  408:         my ($year,$month,$day) = split(/\-/,$date);
  409:         my ($hour,$minute,$sec) = split(/:/,$time);
  410:         foreach ($month,$day,$hour,$minute,$sec) {
  411:             return $timestamp if $_ eq '';
  412:             $_ =~ s/^0//;
  413:         }
  414:         my $dt = DateTime->new(year      => $year,
  415:                                month     => $month,
  416:                                day       => $day,
  417:                                hour      => $hour,
  418:                                minute    => $minute,
  419:                                second    => $sec,
  420:                                time_zone => $server_timezone,
  421:                               );
  422:         my $unixtime = $dt->epoch;
  423:         $timestamp = &Apache::lonlocal::locallocaltime($unixtime);
  424:     }
  425:     return $timestamp;
  426: }
  427: 
  428: ###################################################################
  429: ###################################################################
  430: sub display_values {
  431:     my ($action,$values)=@_;
  432:     my $result='<table>';
  433:     if ($action eq 'CSTORE') {
  434: 	my %values=map {split('=',$_,-1)} split(/\&/,$values);
  435: 	foreach my $key (sort(keys(%values))) {
  436: 	    $result.='<tr><td align="right">'.
  437: 		&unescape($key).
  438: 		'</td><td>=</td><td align="left">'.
  439: 		&unescape($values{$key}).'</td></tr>';
  440: 	}
  441: 	$result.='</table>';
  442:     } elsif ($action eq 'POST') {
  443: 	my %values;
  444:         foreach my $pair (split(/\&/,$values)) {
  445:             my ($key,$value) = split('=',&unescape($pair),-1);
  446:             $values{$key} = $value;
  447:         }
  448: 	foreach my $key (sort(keys(%values))) {
  449: 	    if ($key eq 'counter') { next; }
  450: 	    $result.='<tr><td align="right">'.$key.'</td>'.
  451: 		'<td>=</td><td align="left">'.$values{$key}.'</td></tr>';
  452: 	}
  453: 	$result.='</table>';
  454:     } else {
  455: 	$result=&unescape($values)
  456:     }
  457:     return $result;
  458: }
  459: ###################################################################
  460: ###################################################################
  461: sub request_data_update {
  462:     my $command = 'prepare activity log';
  463:     my $cid = $env{'request.course.id'};
  464:     my $domain = $env{'course.'.$cid.'.domain'};
  465:     my $home = $env{'course.'.$cid.'.home'};
  466:     my $course = $env{'course.'.$cid.'.num'};
  467: #    &Apache::lonnet::logthis($command.' '.$course.' '.$domain.' '.$home);
  468:     my $result = &Apache::lonnet::metadata_query($command,$course,$domain,
  469:                                                  [$home]);
  470:     return $result;
  471: }
  472: 
  473: ###################################################################
  474: ###################################################################
  475: sub pick_student {
  476:     my ($r) = @_;
  477:     $r->print("Sorry, cannot display classlist at this time.  Come back another time.");
  478:     return;
  479: }
  480: 
  481: ###################################################################
  482: ###################################################################
  483: sub styles {
  484:     return <<END;
  485: <style type="text/css">
  486:     tr.warning   { background-color: \#CCCCCC; }
  487:     tr.chat      { background-color: \#CCCCCC; }
  488:     tr.chatfetch { background-color: \#CCCCCC; }
  489:     tr.navmaps   { background-color: \#CCCCCC; }
  490:     tr.roles     { background-color: \#CCCCCC; }
  491:     tr.flip      { background-color: \#CCCCCC; }
  492:     tr.adm       { background-color: \#CCCCCC; }
  493:     tr.print     { background-color: \#CCCCCC; }
  494:     tr.printout  { background-color: \#CCCCCC; }
  495:     tr.parmset   { background-color: \#CCCCCC; }
  496:     tr.grades    { background-color: \#CCCCCC; }
  497: </style>
  498: END
  499: } 
  500: 
  501: sub developer_centric_styles {
  502:     return <<END;
  503: <style type="text/css">
  504:     tr.warning   { background-color: red; }
  505:     tr.chat      { background-color: yellow; }
  506:     tr.chatfetch { background-color: yellow; }
  507:     tr.evaluate  { background-color: red; }
  508:     tr.navmaps   { background-color: \#777777; }
  509:     tr.roles     { background-color: \#999999; }
  510:     tr.flip      { background-color: \#BBBBBB; }
  511:     tr.adm       { background-color: green; }
  512:     tr.print     { background-color: blue; }
  513:     tr.parmset   { background-color: \#000088; }
  514:     tr.printout  { background-color: blue; }
  515:     tr.grades    { background-color: \#CCCCCC; }
  516: </style>
  517: END
  518: }
  519: 
  520: ###################################################################
  521: ###################################################################
  522: sub handler {
  523:     my $r=shift;
  524:     my $c = $r->connection();
  525:     #
  526:     # Check for overloading here and on the course home server
  527:     my $loaderror=&Apache::lonnet::overloaderror($r);
  528:     if ($loaderror) { return $loaderror; }
  529:     $loaderror=
  530:         &Apache::lonnet::overloaderror
  531:         ($r,
  532:          $env{'course.'.$env{'request.course.id'}.'.home'});
  533:     if ($loaderror) { return $loaderror; }
  534:     #
  535:     # Check for access
  536:     if (! &Apache::lonnet::allowed('vsa',$env{'request.course.id'})) {
  537:         $env{'user.error.msg'}=
  538:             $r->uri.":vsa:0:0:Cannot student activity for complete course";
  539:         if (! 
  540:             &Apache::lonnet::allowed('vsa',
  541:                                      $env{'request.course.id'}.'/'.
  542:                                      $env{'request.course.sec'})) {
  543:             $env{'user.error.msg'}=
  544:                 $r->uri.":vsa:0:0:Cannot view student activity with given role";
  545:             return HTTP_NOT_ACCEPTABLE;
  546:         }
  547:     }
  548:     #
  549:     # Send the header
  550:     &Apache::loncommon::no_cache($r);
  551:     &Apache::loncommon::content_type($r,'text/html');
  552:     $r->send_http_header;
  553:     if ($r->header_only) { return OK; }
  554:     #
  555:     # Extract form elements from query string
  556:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  557:                                             ['selected_student','start']);
  558:     #
  559:     # We will almost always need this...
  560:     my $navmap = Apache::lonnavmaps::navmap->new();
  561:     if (!defined($navmap)) {
  562:         my $requrl = $r->uri;
  563:         $env{'user.error.msg'} = "$requrl:bre:0:0:Navmap initialization failed.";
  564:         return HTTP_NOT_ACCEPTABLE;
  565:     }
  566:     # 
  567:     &Apache::lonhtmlcommon::clear_breadcrumbs();
  568:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/studentactivity',
  569:                                             title=>'Student Activity',
  570:                                             text =>'Student Activity',
  571:                                             faq=>139,
  572:                                             bug=>'instructor interface'});
  573:     #
  574:     # Give the LON-CAPA page header
  575:     $r->print(&Apache::loncommon::start_page('Student Activity',&styles()).
  576:               &Apache::lonhtmlcommon::breadcrumbs('Student Activity'));
  577:     $r->rflush();
  578:     #
  579:     # Begin form output
  580:     $r->print('<form name="trackstudent" method="post" action="/adm/trackstudent">');
  581:     $r->print('<br />');
  582:     $r->print('<div name="statusline">'.
  583:               &mt('Status:[_1]',
  584:                   '<input type="text" name="status" size="60" value="" />').
  585:               '</div>');
  586:     $r->rflush();
  587:     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
  588:         ($r,&mt('Student Activity Retrieval'),
  589:          &mt('Student Activity Retrieval'),undef,'inline',undef,
  590:          'trackstudent','status');
  591:     &Apache::lonhtmlcommon::Update_PrgWin
  592:         ($r,\%prog_state,&mt('Contacting course home server'));
  593:     #
  594:     my $result = &request_data_update();
  595:     #
  596:     if (exists($env{'form.selected_student'})) {
  597:         # For now, just show all the data, in the future allow selection of
  598:         # a student
  599:         my ($sname,$sdom) = split(':',$env{'form.selected_student'});
  600:         if ($sname =~ /^$LONCAPA::username_re$/ 
  601: 	    && $sdom =~ /^$LONCAPA::domain_re$/) {
  602:             $r->print('<h2>'.
  603:                       &mt('Recent activity of [_1]:[_2]',$sname,$sdom).
  604:                       '</h2>');
  605:             $r->print('<p class="LC_info">'
  606:                      .&mt('Compiling student activity data can take a long time.'
  607:                          .' Your request continues to be processed while results are displayed.')
  608:                      .'</p>'
  609:             );
  610:             &get_data($r,\%prog_state,$navmap,
  611:                       'student:'.$env{'form.selected_student'});
  612:         } else {
  613:             $r->print('<h2>'.&mt('Unable to process for [_1]:[_2]',
  614:                                  $sname,$sdom).'</h2>');
  615:         }
  616:     } else {
  617:         # For now, just show all the data instead of limiting it to one student
  618:         &get_data($r,\%prog_state,$navmap,'full_class');
  619:     }
  620:     #
  621:     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Done'));
  622:     &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
  623:     #
  624:     $r->print("</form>\n");
  625:     $r->print(&Apache::loncommon::end_page());
  626:     $r->rflush();
  627:     #
  628:     return OK;
  629: }
  630: 
  631: 1;
  632: 
  633: #######################################################
  634: #######################################################
  635: 
  636: =pod
  637: 
  638: =back
  639: 
  640: =cut
  641: 
  642: #######################################################
  643: #######################################################
  644: 
  645: __END__
  646: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>