Annotation of loncom/interface/lontrackstudent.pm, revision 1.17

1.1       matthew     1: # The LearningOnline Network with CAPA
                      2: #
1.17    ! www         3: # $Id: lontrackstudent.pm,v 1.16 2005/06/30 17:56:28 albertel Exp $
1.1       matthew     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);
1.13      matthew    47: use Apache::lonmysql;
1.15      albertel   48: use Apache::lonnet;
1.1       matthew    49: use Apache::lonlocal;
                     50: use Time::HiRes;
                     51: 
1.16      albertel   52: my $num_records=500;
                     53: 
1.5       matthew    54: sub get_data {
                     55:     my ($r,$prog_state,$navmap,$mode) = @_;
1.2       matthew    56:     ##
                     57:     ## Compose the query
                     58:     &Apache::lonhtmlcommon::Update_PrgWin
                     59:         ($r,$prog_state,&mt('Composing Query'));
                     60:     #
1.9       matthew    61:     # Allow the other server to begin processing the data before we ask for it.
                     62:     sleep(5);
1.10      matthew    63:     #
                     64:     my $max_time = &get_max_time_in_db($r,$prog_state);
                     65:     if (defined($max_time)) {
1.17    ! www        66:         $r->print('<h3>'.&mt('Activity data compiled up to [_1]',
1.10      matthew    67:                              &Apache::lonlocal::locallocaltime($max_time)).
1.17    ! www        68:                   '</h3>'.&mt('While data is processed, periodically reload this page for more recent activity').'<br />');
1.10      matthew    69:         $r->rflush();
                     70:     } else {
                     71:         $r->print('<h3>'.&mt('Unable to retrieve any data.  Please reload this page and try again.').'</h3>');
                     72:         return;
                     73:     }
                     74:     my $query = &build_query($mode);
1.2       matthew    75:     ##
                     76:     ## Send it along
1.15      albertel   77:     my $home = $env{'course.'.$env{'request.course.id'}.'.home'};
1.2       matthew    78:     my $reply=&Apache::lonnet::metadata_query($query,undef,undef,[$home]);
                     79:     if (ref($reply) ne 'HASH') {
                     80:         $r->print('<h2>'.
                     81:                   &mt('Error contacting home server for course: [_1]',
                     82:                       $reply).
                     83:                   '</h2>');
                     84:         return;
                     85:     }
                     86:     my $results_file = $r->dir_config('lonDaemons').'/tmp/'.$reply->{$home};
                     87:     my $endfile = $results_file.'.end';
                     88:     ##
                     89:     ## Check for the results
                     90:     &Apache::lonhtmlcommon::Update_PrgWin
                     91:         ($r,$prog_state,&mt('Waiting for results'));
                     92:     my $maxtime = 500;
                     93:     my $starttime = time;
                     94:     while (! -e $endfile && (time-$starttime < $maxtime)) {
1.4       matthew    95:         &Apache::lonhtmlcommon::Update_PrgWin
                     96:             ($r,$prog_state,&mt('Waiting up to [_1] seconds for results',
                     97:                                 $starttime+$maxtime-time));
1.2       matthew    98:         sleep(1);
                     99:     }
                    100:     if (! -e $endfile) {
                    101:         $r->print('<h2>'.
                    102:                   &mt('Unable to retrieve data.').'</h2>');
                    103:         $r->print(&mt('Please try again in a few minutes.'));
                    104:         return;
                    105:     }
1.5       matthew   106:     $r->rflush();
1.10      matthew   107:     #
1.2       matthew   108:     &Apache::lonhtmlcommon::Update_PrgWin
                    109:         ($r,$prog_state,&mt('Parsing results'));
1.10      matthew   110:     #
1.5       matthew   111:     &output_results($r,$results_file,$navmap,$mode);
1.16      albertel  112:     my ($sname,$sdom) = ($mode=~/^student:(.*):(.*)$/);
                    113:     $r->print(&Apache::loncommon::track_student_link(
                    114: 				  'View more activity by this student',
                    115: 				  $sname,$sdom,undef,
                    116: 				  ($env{'form.start'}+$num_records)));
                    117: 
1.5       matthew   118:     &Apache::lonhtmlcommon::Update_PrgWin($r,$prog_state,&mt('Finished!'));
1.4       matthew   119:     return;
                    120: }
                    121: 
1.10      matthew   122: sub table_names {
1.15      albertel  123:     my $cid = $env{'request.course.id'};
                    124:     my $domain = $env{'course.'.$cid.'.domain'};
                    125:     my $home = $env{'course.'.$cid.'.home'};
                    126:     my $course = $env{'course.'.$cid.'.num'};
1.10      matthew   127:     my $prefix = $course.'_'.$domain.'_';
                    128:     #
                    129:     my %tables = 
1.13      matthew   130:         ( student =>&Apache::lonmysql::fix_table_name($prefix.'students'),
                    131:           res     =>&Apache::lonmysql::fix_table_name($prefix.'resource'),
                    132:           machine =>&Apache::lonmysql::fix_table_name($prefix.'machine_table'),
                    133:           activity=>&Apache::lonmysql::fix_table_name($prefix.'activity'),
1.10      matthew   134:           );
                    135:     return %tables;
                    136: }
                    137: 
                    138: sub get_max_time_in_db {
                    139:     my ($r,$prog_state) = @_;
                    140:     my %table = &table_names();
                    141:     my $query = qq{SELECT MAX(time) FROM $table{'activity'} };
                    142:     #
1.15      albertel  143:     my $home = $env{'course.'.$env{'request.course.id'}.'.home'};
1.10      matthew   144:     my $reply=&Apache::lonnet::metadata_query($query,undef,undef,[$home]);
                    145:     if (ref($reply) ne 'HASH') {
                    146:         return undef;
                    147:     }
                    148:     my $results_file = $r->dir_config('lonDaemons').'/tmp/'.$reply->{$home};
                    149:     my $endfile = $results_file.'.end';
                    150:     ##
                    151:     ## Check for the results
                    152:     &Apache::lonhtmlcommon::Update_PrgWin
                    153:         ($r,$prog_state,&mt('Waiting for results'));
                    154:     my $maxtime = 500;
                    155:     my $starttime = time;
                    156:     while (! -e $endfile && (time-$starttime < $maxtime)) {
                    157:         &Apache::lonhtmlcommon::Update_PrgWin
                    158:             ($r,$prog_state,&mt('Waiting up to [_1] seconds for results',
                    159:                                 $starttime+$maxtime-time));
                    160:         sleep(1);
                    161:     }
                    162:     if (! -e $endfile) {
                    163:         $r->print('<h2>'.
                    164:                   &mt('Unable to retrieve data.').'</h2>');
                    165:         $r->print(&mt('Please try again in a few minutes.'));
                    166:         return undef;
                    167:     }
                    168:     $r->rflush();
                    169:     #
                    170:     &Apache::lonhtmlcommon::Update_PrgWin
                    171:         ($r,$prog_state,&mt('Parsing results'));
                    172:     #
                    173:     if (! open(TIMEDATA,$results_file)) {
                    174:         $r->print('<h2>'.&mt('Unable to read results file.').'</h2>'.
                    175:                   '<p>'.
                    176:                   &mt('This is a serious error and has been logged.  '.
                    177:                       'You should contact your system administrator '.
                    178:                       'to resolve this issue.').
                    179:                   '</p>');
                    180:         return;
                    181:     }
                    182:     #
                    183:     my $timestr = '';
                    184:     while (my $line = <TIMEDATA>) {
                    185:         chomp($line);
                    186:         $timestr = &Apache::lonnet::unescape($line);
                    187:     }
                    188:     close(TIMEDATA);
1.12      matthew   189:     return &Apache::lonmysql::unsqltime($timestr);
1.10      matthew   190: }
                    191: 
1.5       matthew   192: sub build_query {
                    193:     my ($mode) = @_;
1.15      albertel  194:     my $cid = $env{'request.course.id'};
                    195:     my $domain = $env{'course.'.$cid.'.domain'};
                    196:     my $home = $env{'course.'.$cid.'.home'};
                    197:     my $course = $env{'course.'.$cid.'.num'};
1.5       matthew   198:     my $prefix = $course.'_'.$domain.'_';
1.16      albertel  199:     my $start = ($env{'form.start'}+0);
1.5       matthew   200:     #
1.10      matthew   201:     my %table = &table_names();
1.5       matthew   202:     #
                    203:     my $query;
                    204:     if ($mode eq 'full_class') {
                    205:         $query = qq{
                    206:         SELECT B.resource,A.time,C.student,A.action,E.machine,A.action_values 
1.10      matthew   207:             FROM $table{'activity'} AS A
                    208:             LEFT JOIN $table{'res'}      AS B ON B.res_id=A.res_id 
                    209:             LEFT JOIN $table{'student'}  AS C ON C.student_id=A.student_id 
                    210:             LEFT JOIN $table{'machine'}  AS E ON E.machine_id=A.machine_id
1.5       matthew   211:             ORDER BY A.time DESC
1.16      albertel  212:             LIMIT $start, $num_records
1.5       matthew   213:         };
                    214:     } elsif ($mode =~ /^student:(.*):(.*)$/) {
                    215:         my $student = $1.':'.$2;
                    216:         $query = qq{
1.6       matthew   217:             SELECT B.resource,A.time,A.action,E.machine,A.action_values 
1.10      matthew   218:                 FROM $table{'activity'} AS A
                    219:                 LEFT JOIN $table{'res'}      AS B ON B.res_id=A.res_id 
                    220:                 LEFT JOIN $table{'student'}  AS C ON C.student_id=A.student_id 
                    221:                 LEFT JOIN $table{'machine'}  AS E ON E.machine_id=A.machine_id
1.6       matthew   222:                 WHERE C.student='$student'
                    223:                 ORDER BY A.time DESC
1.16      albertel  224:                 LIMIT $start, $num_records
1.6       matthew   225:             };
1.5       matthew   226:     }
                    227:     $query =~ s|$/||g;
                    228:     return $query;
                    229: }
                    230: 
                    231: ###################################################################
                    232: ###################################################################
1.4       matthew   233: sub output_results {
1.5       matthew   234:     my ($r,$results_file,$navmap,$mode) = @_;
1.6       matthew   235:     ##
                    236:     ##
1.12      matthew   237:     if (! -s $results_file) {
                    238:         # results file is empty, just let them know there is no data
1.17    ! www       239:         $r->print('<h2>'.&mt('So far, no data has been returned for your request').'</h2>');
1.12      matthew   240:         return;
                    241:     }
1.2       matthew   242:     if (! open(ACTIVITYDATA,$results_file)) {
1.4       matthew   243:         $r->print('<h2>'.&mt('Unable to read results file.').'</h2>'.
                    244:                   '<p>'.
                    245:                   &mt('This is a serious error and has been logged.  '.
                    246:                       'You should contact your system administrator '.
                    247:                       'to resolve this issue.').
                    248:                   '</p>');
1.2       matthew   249:         return;
                    250:     }
1.6       matthew   251:     ##
                    252:     ##
1.5       matthew   253:     my $tableheader;
                    254:     if ($mode eq 'full_class') { 
                    255:         $tableheader = 
                    256:             '<table><tr>'.
                    257:             '<th>'.&mt('Resource').'</th>'.
                    258:             '<th>'.&mt('Time').'</th>'.
                    259:             '<th>'.&mt('Student').'</th>'.
                    260:             '<th>'.&mt('Action').'</th>'.
1.6       matthew   261:  #           '<th>'.&mt('Originating Server').'</th>'.
                    262:             '<th align="left">'.&mt('Data').'</th>'.
                    263:             '</tr>'.$/;
                    264:     } elsif ($mode =~ /^student:(.*):(.*)$/) {
                    265:         $tableheader = 
                    266:             '<table><tr>'.
                    267:             '<th>'.&mt('Resource').'</th>'.
                    268:             '<th>'.&mt('Time').'</th>'.
                    269:             '<th>'.&mt('Action').'</th>'.
                    270:  #           '<th>'.&mt('Originating Server').'</th>'.
                    271:             '<th align="left">'.&mt('Data').'</th>'.
1.5       matthew   272:             '</tr>'.$/;
                    273:     }
1.16      albertel  274:     my $count = $env{'form.start'}-1;
1.2       matthew   275:     $r->rflush();
1.6       matthew   276:     ##
                    277:     ##
1.2       matthew   278:     while (my $line = <ACTIVITYDATA>) {
1.10      matthew   279:         # FIXME: does not pass symbs along :(
1.6       matthew   280:         chomp($line);
1.2       matthew   281:         $line = &Apache::lonnet::unescape($line);
                    282:         if (++$count % 50 == 0) {
1.5       matthew   283:             if ($count != 0) { 
                    284:                 $r->print('</table>'.$/);
                    285:                 $r->rflush();
                    286:             }
1.2       matthew   287:             $r->print($tableheader);
                    288:         }
1.5       matthew   289:         my ($symb,$timestamp,$student,$action,$machine,$values);
                    290:         if ($mode eq 'full_class') {
1.11      albertel  291:             ($symb,$timestamp,$student,$action,$machine,$values) = split(',',$line,6);
1.5       matthew   292:         } else {
1.11      albertel  293:             ($symb,$timestamp,$action,$machine,$values) = split(',',$line,5);
1.5       matthew   294:         }
1.11      albertel  295: 	foreach ($symb,$timestamp,$student,$action,$machine) {
                    296: 	    $_=&Apache::lonnet::unescape($_);
                    297: 	}
1.2       matthew   298:         my ($title,$src);
1.4       matthew   299:         if ($symb =~ m:^/adm/:) {
1.2       matthew   300:             $title = $symb;
                    301:             $src = $symb;
                    302:         } else {
1.4       matthew   303:             my $nav_res = $navmap->getBySymb($symb);
                    304:             if (defined($nav_res)) {
1.11      albertel  305:                 $title = $nav_res->compTitle();
1.4       matthew   306:                 $src   = $nav_res->src();
                    307:             } else {
1.6       matthew   308:                 if ($src =~ m|^/res|) {
                    309:                     $title = $src;
                    310:                 } elsif ($values =~ /^\s*$/ && 
                    311:                          (! defined($src) || $src =~ /^\s*$/)) {
                    312:                     next;
                    313:                 } elsif ($values =~ /^\s*$/) {
                    314:                     $values = $src;
                    315:                 } else {
                    316:                     $title = 'unable to retrieve title';
                    317:                     $src   = '/dev/null';
                    318:                 }
1.4       matthew   319:             }
1.2       matthew   320:         }
1.6       matthew   321:         my %classes;
                    322:         my $class_count=0;
                    323:         if (! exists($classes{$symb})) {
                    324:             $classes{$symb} = $class_count++;
                    325:         }
                    326:         my $class = 'a';#.$classes{$symb};
1.4       matthew   327:         #
1.5       matthew   328:         if ($symb eq '/prtspool/') {
1.4       matthew   329:             $class = 'print';
                    330:             $title = 'retrieve printout';
                    331:         } elsif ($symb =~ m|^/adm/([^/]+)|) {
                    332:             $class = $1;
                    333:         } elsif ($symb =~ m|^/adm/|) {
                    334:             $class = 'adm';
                    335:         }
                    336:         if ($title eq 'unable to retrieve title') {
                    337:             $title =~ s/ /\&nbsp;/g;
                    338:             $class = 'warning';
                    339:         }
                    340:         if (! defined($title) || $title eq '') {
                    341:             $title = 'untitled';
                    342:             $class = 'warning';
                    343:         }
1.6       matthew   344:         # Clean up the values
1.11      albertel  345: 	$values = &display_values($action,$values);
1.6       matthew   346:         #
                    347:         # Build the row for output
1.16      albertel  348:         my $tablerow = qq{<tr class="$class"><td>}.($count+1).qq{</td>};
1.6       matthew   349:         if ($src =~ m|^/adm/|) {
                    350:             $tablerow .= 
1.11      albertel  351:                 '<td valign="top"><nobr>'.$title.'</nobr></td>';
1.6       matthew   352:         } else {
                    353:             $tablerow .= 
1.11      albertel  354:                 '<td valign="top"><nobr>'.
1.6       matthew   355:                 '<a href="'.$src.'">'.$title.'</a>'.
                    356:                 '</nobr></td>';
1.5       matthew   357:         }
1.11      albertel  358:         $tablerow .= '<td valign="top"><nobr>'.$timestamp.'</nobr></td>';
1.5       matthew   359:         if ($mode eq 'full_class') {
1.11      albertel  360:             $tablerow.='<td valign="top">'.$student.'</td>';
1.5       matthew   361:         }
1.6       matthew   362:         $tablerow .= 
1.11      albertel  363:             '<td valign="top">'.$action.'</td>'.
1.6       matthew   364: #            '<td>'.$machine.'</td>'.
1.11      albertel  365:             '<td valign="top">'.$values.'</td>'.
1.6       matthew   366:             '</tr>';
                    367:         $r->print($tablerow.$/);
1.2       matthew   368:     }
1.16      albertel  369:     $r->print('</table>'.$/);### if (! $count % 50);
1.2       matthew   370:     close(ACTIVITYDATA);
                    371:     return;
                    372: }
                    373: 
1.5       matthew   374: ###################################################################
                    375: ###################################################################
1.11      albertel  376: sub display_values {
                    377:     my ($action,$values)=@_;
                    378:     my $result='<table>';
                    379:     if ($action eq 'CSTORE') {
                    380: 	my %values=map {split('=',$_,-1)} split(/\&/,$values);
                    381: 	foreach my $key (sort(keys(%values))) {
                    382: 	    $result.='<tr><td align="right">'.
                    383: 		&Apache::lonnet::unescape($key).
                    384: 		'</td><td>=</td><td align="left">'.
                    385: 		&Apache::lonnet::unescape($values{$key}).'</td></tr>';
                    386: 	}
                    387: 	$result.='</table>';
                    388:     } elsif ($action eq 'POST') {
                    389: 	my %values=
                    390: 	    map {split('=',&Apache::lonnet::unescape($_),-1)} split(/\&/,$values);
                    391: 	foreach my $key (sort(keys(%values))) {
                    392: 	    if ($key eq 'counter') { next; }
                    393: 	    $result.='<tr><td align="right">'.$key.'</td>'.
                    394: 		'<td>=</td><td align="left">'.$values{$key}.'</td></tr>';
                    395: 	}
                    396: 	$result.='</table>';
                    397:     } else {
                    398: 	$result=&Apache::lonnet::unescape($values)
                    399:     }
                    400:     return $result;
                    401: }
                    402: ###################################################################
                    403: ###################################################################
1.1       matthew   404: sub request_data_update {
                    405:     my $command = 'prepare activity log';
1.15      albertel  406:     my $cid = $env{'request.course.id'};
                    407:     my $domain = $env{'course.'.$cid.'.domain'};
                    408:     my $home = $env{'course.'.$cid.'.home'};
                    409:     my $course = $env{'course.'.$cid.'.num'};
1.6       matthew   410: #    &Apache::lonnet::logthis($command.' '.$course.' '.$domain.' '.$home);
1.1       matthew   411:     my $result = &Apache::lonnet::metadata_query($command,$course,$domain,
                    412:                                                  [$home]);
                    413:     return $result;
                    414: }
                    415: 
                    416: ###################################################################
                    417: ###################################################################
1.5       matthew   418: sub pick_student {
                    419:     my ($r) = @_;
                    420:     $r->print("Sorry, cannot display classlist at this time.  Come back another time.");
                    421:     return;
                    422: }
1.1       matthew   423: 
1.5       matthew   424: ###################################################################
                    425: ###################################################################
1.4       matthew   426: sub styles {
                    427:     return <<END;
1.5       matthew   428: <style type="text/css">
1.6       matthew   429:     tr.warning   { background-color: \#CCCCCC; }
                    430:     tr.chat      { background-color: \#CCCCCC; }
                    431:     tr.chatfetch { background-color: \#CCCCCC; }
                    432:     tr.navmaps   { background-color: \#CCCCCC; }
                    433:     tr.roles     { background-color: \#CCCCCC; }
                    434:     tr.flip      { background-color: \#CCCCCC; }
                    435:     tr.adm       { background-color: \#CCCCCC; }
                    436:     tr.print     { background-color: \#CCCCCC; }
                    437:     tr.printout  { background-color: \#CCCCCC; }
                    438:     tr.parmset   { background-color: \#CCCCCC; }
                    439:     tr.grades    { background-color: \#CCCCCC; }
                    440: </style>
                    441: END
                    442: } 
                    443: 
                    444: sub developer_centric_styles {
                    445:     return <<END;
                    446: <style type="text/css">
1.4       matthew   447:     tr.warning   { background-color: red; }
                    448:     tr.chat      { background-color: yellow; }
                    449:     tr.chatfetch { background-color: yellow; }
1.7       matthew   450:     tr.evaluate  { background-color: red; }
1.4       matthew   451:     tr.navmaps   { background-color: \#777777; }
                    452:     tr.roles     { background-color: \#999999; }
                    453:     tr.flip      { background-color: \#BBBBBB; }
                    454:     tr.adm       { background-color: green; }
                    455:     tr.print     { background-color: blue; }
1.6       matthew   456:     tr.parmset   { background-color: \#000088; }
1.4       matthew   457:     tr.printout  { background-color: blue; }
1.6       matthew   458:     tr.grades    { background-color: \#CCCCCC; }
1.5       matthew   459: </style>
1.4       matthew   460: END
                    461: }
1.1       matthew   462: 
                    463: ###################################################################
                    464: ###################################################################
                    465: sub handler {
                    466:     my $r=shift;
                    467:     my $c = $r->connection();
                    468:     #
                    469:     # Check for overloading here and on the course home server
                    470:     my $loaderror=&Apache::lonnet::overloaderror($r);
                    471:     if ($loaderror) { return $loaderror; }
                    472:     $loaderror=
                    473:         &Apache::lonnet::overloaderror
                    474:         ($r,
1.15      albertel  475:          $env{'course.'.$env{'request.course.id'}.'.home'});
1.1       matthew   476:     if ($loaderror) { return $loaderror; }
                    477:     #
                    478:     # Check for access
1.15      albertel  479:     if (! &Apache::lonnet::allowed('vsa',$env{'request.course.id'})) {
                    480:         $env{'user.error.msg'}=
1.1       matthew   481:             $r->uri.":vsa:0:0:Cannot student activity for complete course";
                    482:         if (! 
                    483:             &Apache::lonnet::allowed('vsa',
1.15      albertel  484:                                      $env{'request.course.id'}.'/'.
                    485:                                      $env{'request.course.sec'})) {
                    486:             $env{'user.error.msg'}=
1.1       matthew   487:                 $r->uri.":vsa:0:0:Cannot view student activity with given role";
                    488:             return HTTP_NOT_ACCEPTABLE;
                    489:         }
                    490:     }
                    491:     #
                    492:     # Send the header
                    493:     &Apache::loncommon::no_cache($r);
                    494:     &Apache::loncommon::content_type($r,'text/html');
                    495:     $r->send_http_header;
                    496:     if ($r->header_only) { return OK; }
                    497:     #
                    498:     # Extract form elements from query string
                    499:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.16      albertel  500:                                             ['selected_student','start']);
1.1       matthew   501:     #
1.2       matthew   502:     # We will almost always need this...
                    503:     my $navmap = Apache::lonnavmaps::navmap->new();
1.1       matthew   504:     # 
                    505:     &Apache::lonhtmlcommon::clear_breadcrumbs();
                    506:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/studentactivity',
                    507:                                             title=>'Student Activity',
                    508:                                             text =>'Student Activity',
                    509:                                             faq=>139,
                    510:                                             bug=>'instructor interface'});
                    511:     #
1.2       matthew   512:     # Give the LON-CAPA page header
1.14      albertel  513:     my $html=&Apache::lonxml::xmlbegin();
                    514:     $r->print($html.'<head>'.&styles().'<title>'.
1.2       matthew   515:               &mt('Student Activity').
                    516:               "</title></head>\n".
                    517:               &Apache::loncommon::bodytag('Student Activity').
                    518:               &Apache::lonhtmlcommon::breadcrumbs(undef,'Student Activity'));
                    519:     $r->rflush();
                    520:     #
1.1       matthew   521:     # Begin form output
1.2       matthew   522:     $r->print('<form name="trackstudent" method="post" action="/adm/trackstudent">');
                    523:     $r->print('<br />');
                    524:     $r->print('<div name="statusline">'.
                    525:               &mt('Status:[_1]',
                    526:                   '<input type="text" name="status" size="60" value="" />').
                    527:               '</div>');
1.1       matthew   528:     $r->rflush();
1.2       matthew   529:     my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
                    530:         ($r,&mt('Student Activity Retrieval'),
                    531:          &mt('Student Activity Retrieval'),undef,'inline',undef,
                    532:          'trackstudent','status');
                    533:     &Apache::lonhtmlcommon::Update_PrgWin
                    534:         ($r,\%prog_state,&mt('Contacting course home server'));
1.1       matthew   535:     #
                    536:     my $result = &request_data_update();
                    537:     #
1.15      albertel  538:     if (exists($env{'form.selected_student'})) {
1.4       matthew   539:         # For now, just show all the data, in the future allow selection of
                    540:         # a student
1.15      albertel  541:         my ($sname,$sdom) = split(':',$env{'form.selected_student'});
1.6       matthew   542:         if ($sname =~ /^\w*$/ && $sdom =~ /^\w*$/) {
                    543:             $r->print('<h2>'.
                    544:                       &mt('Recent activity of [_1]@[_2]',$sname,$sdom).
                    545:                       '</h2>');
1.8       matthew   546:             $r->print('<p>'.&mt(<<END).'</p>');
                    547: Compiling student activity data can take a long time.
1.17    ! www       548: Your request continues to be processed while results are displayed.
1.8       matthew   549: END
1.6       matthew   550:             &get_data($r,\%prog_state,$navmap,
1.15      albertel  551:                       'student:'.$env{'form.selected_student'});
1.6       matthew   552:         } else {
                    553:             $r->print('<h2>'.&mt('Unable to process for [_1]@[_2]',
                    554:                                  $sname,$sdom).'</h2>');
                    555:         }
1.1       matthew   556:     } else {
1.4       matthew   557:         # For now, just show all the data instead of limiting it to one student
1.5       matthew   558:         &get_data($r,\%prog_state,$navmap,'full_class');
1.1       matthew   559:     }
                    560:     #
1.4       matthew   561:     &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Done'));
                    562:     &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
1.2       matthew   563:     #
1.1       matthew   564:     $r->print("</form>\n");
                    565:     $r->print("</body>\n</html>\n");
                    566:     $r->rflush();
                    567:     #
                    568:     return OK;
                    569: }
                    570: 
                    571: 1;
                    572: 
                    573: #######################################################
                    574: #######################################################
                    575: 
                    576: =pod
                    577: 
                    578: =back
                    579: 
                    580: =cut
                    581: 
                    582: #######################################################
                    583: #######################################################
                    584: 
                    585: __END__
                    586: 

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