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

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

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