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