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