version 1.50, 2002/07/02 15:13:06
|
version 1.51, 2002/07/02 21:34:40
|
Line 46
|
Line 46
|
# |
# |
### |
### |
|
|
|
=pod |
|
|
|
=cut |
|
|
package Apache::lonchart; |
package Apache::lonchart; |
|
|
use strict; |
use strict; |
Line 55 use Apache::loncommon();
|
Line 59 use Apache::loncommon();
|
use HTML::TokeParser; |
use HTML::TokeParser; |
use GDBM_File; |
use GDBM_File; |
|
|
my $jr; |
#my $jr; |
# ----- FORMAT PRINT DATA ---------------------------------------------- |
# ----- FORMAT PRINT DATA ---------------------------------------------- |
|
|
sub FormatStudentInformation { |
sub FormatStudentInformation { |
my ($cache,$name,$studentInformation,$reselected,$spacePadding)=@_; |
my ($cache,$name,$studentInformation,$spacePadding)=@_; |
my $Str=''; |
my $Str=''; |
|
|
for(my $index=0; $index<(scalar @$studentInformation); $index++) { |
for(my $index=0; $index<(scalar @$studentInformation); $index++) { |
if(!&ShouldShowColumn($reselected, 'heading', $index)) { |
if(!&ShouldShowColumn($cache, 'heading'.$index)) { |
next; |
next; |
} |
} |
my $data=$cache->{$name.':'.$studentInformation->[$index]}; |
my $data=$cache->{$name.':'.$studentInformation->[$index]}; |
Line 80 sub FormatStudentInformation {
|
Line 84 sub FormatStudentInformation {
|
} |
} |
|
|
sub FormatStudentData { |
sub FormatStudentData { |
my ($reselected,$name,$coid,$studentInformation,$spacePadding,$ChartDB)=@_; |
my ($name,$coid,$studentInformation,$spacePadding,$ChartDB)=@_; |
my ($sname,$sdom) = split(/\:/,$name); |
my ($sname,$sdom) = split(/\:/,$name); |
my $Str; |
my $Str; |
my %CacheData; |
my %CacheData; |
Line 91 sub FormatStudentData {
|
Line 95 sub FormatStudentData {
|
# Handle Student information ------------------------------------------ |
# Handle Student information ------------------------------------------ |
# Handle user data |
# Handle user data |
$Str=&FormatStudentInformation(\%CacheData, $name, $studentInformation, |
$Str=&FormatStudentInformation(\%CacheData, $name, $studentInformation, |
$reselected, $spacePadding); |
$spacePadding); |
|
|
# Handle errors |
# Handle errors |
if($CacheData{$name.':error'} =~ /environment/) { |
if($CacheData{$name.':error'} =~ /environment/) { |
Line 113 sub FormatStudentData {
|
Line 117 sub FormatStudentData {
|
my $problemsSolved = 0; |
my $problemsSolved = 0; |
my $numberOfParts = 0; |
my $numberOfParts = 0; |
foreach my $sequence (split(/\:/,$CacheData{'orderedSequences'})) { |
foreach my $sequence (split(/\:/,$CacheData{'orderedSequences'})) { |
if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { |
if(!&ShouldShowColumn(\%CacheData, 'sequence'.$sequence)) { |
next; |
next; |
} |
} |
|
|
Line 208 sub FormatStudentData {
|
Line 212 sub FormatStudentData {
|
$Str .= $spacePadding; |
$Str .= $spacePadding; |
} |
} |
|
|
$Str .= '<font color="#000088">'.$problemsSolved. |
my $outputProblemsSolved = sprintf( "%4d", $problemsSolved ); |
' / '.$totalProblems.'</font><br>'; |
my $outputTotalProblems = sprintf( "%4d", $totalProblems ); |
|
$Str .= '<font color="#000088">'.$outputProblemsSolved. |
|
' / '.$outputTotalProblems.'</font><br>'; |
|
|
untie(%CacheData); |
untie(%CacheData); |
return $Str; |
return $Str; |
} |
} |
|
|
sub CreateTableHeadings { |
sub CreateTableHeadings { |
my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; |
my ($CacheData,$studentInformation,$headings,$spacePadding)=@_; |
my $Str='<pre>'; |
my $Str='<pre>'; |
|
|
for(my $index=0; $index<(scalar @$headings); $index++) { |
for(my $index=0; $index<(scalar @$headings); $index++) { |
if(!&ShouldShowColumn($reselected, 'heading', $index)) { |
if(!&ShouldShowColumn($CacheData, 'heading'.$index)) { |
next; |
next; |
} |
} |
|
|
Line 235 sub CreateTableHeadings {
|
Line 241 sub CreateTableHeadings {
|
} |
} |
|
|
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { |
if(!&ShouldShowColumn($CacheData, 'sequence'.$sequence)) { |
next; |
next; |
} |
} |
|
|
Line 255 sub CreateTableHeadings {
|
Line 261 sub CreateTableHeadings {
|
} |
} |
|
|
sub CreateColumnSelectionBox { |
sub CreateColumnSelectionBox { |
my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; |
my ($CacheData,$studentInformation,$headings,$spacePadding)=@_; |
|
|
my $missing=0; |
my $missing=0; |
my $notThere='<tr><td align="right"><b>Select column to view:</b>'; |
my $notThere='<tr><td align="right"><b>Select column to view:</b>'; |
Line 264 sub CreateColumnSelectionBox {
|
Line 270 sub CreateColumnSelectionBox {
|
$notThere .= '<select name="reselect" size="4" multiple="true">'."\n"; |
$notThere .= '<select name="reselect" size="4" multiple="true">'."\n"; |
|
|
for(my $index=0; $index<(scalar @$headings); $index++) { |
for(my $index=0; $index<(scalar @$headings); $index++) { |
if(&ShouldShowColumn($reselected, 'heading', $index)) { |
if(&ShouldShowColumn($CacheData, 'heading'.$index)) { |
next; |
next; |
} |
} |
$name = $headings->[$index]; |
$name = $headings->[$index]; |
Line 274 sub CreateColumnSelectionBox {
|
Line 280 sub CreateColumnSelectionBox {
|
} |
} |
|
|
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
if(&ShouldShowColumn($reselected, 'sequence', $sequence)) { |
if(&ShouldShowColumn($CacheData, 'sequence'.$sequence)) { |
next; |
next; |
} |
} |
$name = $CacheData->{$sequence.':title'}; |
$name = $CacheData->{$sequence.':title'}; |
Line 293 sub CreateColumnSelectionBox {
|
Line 299 sub CreateColumnSelectionBox {
|
} |
} |
|
|
sub CreateColumnSelectors { |
sub CreateColumnSelectors { |
my ($CacheData,$studentInformation,$headings,$reselected,$spacePadding)=@_; |
my ($CacheData,$studentInformation,$headings,$spacePadding)=@_; |
|
|
my $found=0; |
my $found=0; |
my ($name, $length, $position); |
my ($name, $length, $position); |
my $present='<pre>'; |
my $present='<pre>'; |
for(my $index=0; $index<(scalar @$headings); $index++) { |
for(my $index=0; $index<(scalar @$headings); $index++) { |
if(!&ShouldShowColumn($reselected, 'heading', $index)) { |
if(!&ShouldShowColumn($CacheData, 'heading'.$index)) { |
next; |
next; |
} |
} |
$name = $headings->[$index]; |
$name = $headings->[$index]; |
Line 315 sub CreateColumnSelectors {
|
Line 321 sub CreateColumnSelectors {
|
} |
} |
|
|
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { |
if(!&ShouldShowColumn($reselected, 'sequence', $sequence)) { |
if(!&ShouldShowColumn($CacheData, 'sequence'.$sequence)) { |
next; |
next; |
} |
} |
$name = $CacheData->{$sequence.':title'}; |
$name = $CacheData->{$sequence.':title'}; |
Line 341 sub CreateColumnSelectors {
|
Line 347 sub CreateColumnSelectors {
|
} |
} |
|
|
sub CreateForm { |
sub CreateForm { |
|
my ($CacheData)=@_; |
my $OpSel1=''; |
my $OpSel1=''; |
my $OpSel2=''; |
my $OpSel2=''; |
my $OpSel3=''; |
my $OpSel3=''; |
my $Status = $ENV{'form.status'}; |
my $Status = $CacheData->{'form.status'}; |
if ( $Status eq 'Any' ) { $OpSel3='selected'; } |
if ( $Status eq 'Any' ) { $OpSel3='selected'; } |
elsif ($Status eq 'Expired' ) { $OpSel2 = 'selected'; } |
elsif ($Status eq 'Expired' ) { $OpSel2 = 'selected'; } |
else { $OpSel1 = 'selected'; } |
else { $OpSel1 = 'selected'; } |
Line 353 sub CreateForm {
|
Line 360 sub CreateForm {
|
$Ptr .= '<table border="0"><tbody>'; |
$Ptr .= '<table border="0"><tbody>'; |
$Ptr .= '<tr><td align="right">'; |
$Ptr .= '<tr><td align="right">'; |
$Ptr .= '</td><td align="left">'; |
$Ptr .= '</td><td align="left">'; |
$Ptr .= '<input type="submit" name="sort" '; |
$Ptr .= '<input type="submit" name="recalculate" '; |
$Ptr .= 'value="Recalculate Chart"/>'."\n"; |
$Ptr .= 'value="Recalculate Chart"/>'."\n"; |
$Ptr .= ' '; |
$Ptr .= ' '; |
$Ptr .= '<input type="submit" name="refresh" '; |
$Ptr .= '<input type="submit" name="refresh" '; |
$Ptr .= 'value="Refresh Chart"/></td>'."\n"; |
$Ptr .= 'value="Refresh Chart"/>'."\n"; |
|
$Ptr .= ' '; |
|
$Ptr .= '<input type="submit" name="reset" '; |
|
$Ptr .= 'value="Reset Selections"/></td>'."\n"; |
$Ptr .= '</tr><tr><td align="right">'; |
$Ptr .= '</tr><tr><td align="right">'; |
$Ptr .= '<b> Sort by: </b>'."\n"; |
$Ptr .= '<b> Sort by: </b>'."\n"; |
$Ptr .= '</td><td align="left">'; |
$Ptr .= '</td><td align="left">'; |
Line 404 sub StartDocument {
|
Line 414 sub StartDocument {
|
$Str .= '</pre></h1>'; |
$Str .= '</pre></h1>'; |
$Str .= '<h1>'.$ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
$Str .= '<h1>'.$ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
$Str .= '</h1>'; |
$Str .= '</h1>'; |
# $Str .= '<h3>'.localtime().'</h3>'; |
|
|
|
return $Str; |
return $Str; |
} |
} |
Line 514 sub ProcessTopResourceMap {
|
Line 523 sub ProcessTopResourceMap {
|
push(@finishResource, $lastResourceID); |
push(@finishResource, $lastResourceID); |
|
|
$currentSequence=$hash{'map_pc_'.$hash{'src_'.$currentResourceID}}; |
$currentSequence=$hash{'map_pc_'.$hash{'src_'.$currentResourceID}}; |
|
|
|
# Mark sequence as containing problems. If it doesn't, then |
|
# it will be removed when processing for this sequence is |
|
# complete. This allows the problems in a sequence |
|
# to be outputed before problems in the subsequences |
|
if(!defined($CacheData{'orderedSequences'})) { |
|
$CacheData{'orderedSequences'}=$currentSequence; |
|
} else { |
|
$CacheData{'orderedSequences'}.=':'.$currentSequence; |
|
} |
|
|
$lastResourceID=$hash{'map_finish_'. |
$lastResourceID=$hash{'map_finish_'. |
$hash{'src_'.$currentResourceID}}; |
$hash{'src_'.$currentResourceID}}; |
$currentResourceID=$hash{'map_start_'. |
$currentResourceID=$hash{'map_start_'. |
Line 575 sub ProcessTopResourceMap {
|
Line 595 sub ProcessTopResourceMap {
|
|
|
if(defined($CacheData{$currentSequence.':problems'})) { |
if(defined($CacheData{$currentSequence.':problems'})) { |
# Capture sequence information here |
# Capture sequence information here |
if(!defined($CacheData{'orderedSequences'})) { |
|
$CacheData{'orderedSequences'}=$currentSequence; |
|
} else { |
|
$CacheData{'orderedSequences'}.=':'.$currentSequence; |
|
} |
|
|
|
$CacheData{$currentSequence.':title'}= |
$CacheData{$currentSequence.':title'}= |
$hash{'title_'.$currentResourceID}; |
$hash{'title_'.$currentResourceID}; |
|
|
Line 606 sub ProcessTopResourceMap {
|
Line 620 sub ProcessTopResourceMap {
|
$CacheData{$currentSequence.':columnWidth'}= |
$CacheData{$currentSequence.':columnWidth'}= |
(scalar @titleLength); |
(scalar @titleLength); |
} |
} |
} |
} else { |
|
$CacheData{'orderedSequences'}=~s/$currentSequence//; |
|
$CacheData{'orderedSequences'}=~s/::/:/g; |
|
$CacheData{'orderedSequences'}=~s/^:|:$//g; |
|
} |
|
|
$currentSequence=pop(@sequences); |
$currentSequence=pop(@sequences); |
if($currentSequence eq $topLevelSequenceNumber) { |
if($currentSequence eq $topLevelSequenceNumber) { |
last; |
last; |
} |
} |
#else |
|
} |
} |
|
|
# MOVE!!! |
# MOVE!!! |
Line 723 sub ProcessStudentInformation {
|
Line 740 sub ProcessStudentInformation {
|
} |
} |
|
|
# Get student's section number |
# Get student's section number |
my $sec=&ProcessSection($section, $courseID, $ENV{'form.status'}); |
my $sec=&ProcessSection($section, $courseID, $CacheData->{'form.status'}); |
if($sec != -1) { |
if($sec != -1) { |
$CacheData->{$name.':section'}=$sec; |
$CacheData->{$name.':section'}=$sec; |
} else { |
} else { |
Line 841 sub SortStudents {
|
Line 858 sub SortStudents {
|
my ($end,$start)=split(/\:/,$CacheData->{$_.':date'}); |
my ($end,$start)=split(/\:/,$CacheData->{$_.':date'}); |
my $active=1; |
my $active=1; |
my $now=time; |
my $now=time; |
my $Status=$ENV{'form.status'}; |
my $Status=$CacheData->{'form.status'}; |
$Status = ($Status) ? $Status : 'Active'; |
$Status = ($Status) ? $Status : 'Active'; |
if((($end) && $now > $end) && (($Status eq 'Active'))) { |
if((($end) && $now > $end) && (($Status eq 'Active'))) { |
$active=0; |
$active=0; |
Line 854 sub SortStudents {
|
Line 871 sub SortStudents {
|
} |
} |
} |
} |
|
|
my $Pos = $ENV{'form.sort'}; |
my $Pos = $CacheData->{'form.sort'}; |
my %sortData; |
my %sortData; |
if($Pos eq 'Last Name') { |
if($Pos eq 'Last Name') { |
for(my $index=0; $index<scalar @sorted1Students; $index++) { |
for(my $index=0; $index<scalar @sorted1Students; $index++) { |
Line 887 sub TestCacheData {
|
Line 904 sub TestCacheData {
|
my %testData; |
my %testData; |
my $tieTries=0; |
my $tieTries=0; |
|
|
if ((-e "$ChartDB") && ($ENV{'form.sort'} ne 'Recalculate Chart')) { |
if ((-e "$ChartDB") && (!defined($ENV{'form.recalculate'}))) { |
$isCached = 1; |
$isCached = 1; |
} else { |
} else { |
$isCached = 0; |
$isCached = 0; |
} |
} |
|
|
while($tieTries < 3) { |
while($tieTries < 10) { |
my $result=0; |
my $result=0; |
if($isCached) { |
if($isCached) { |
$result=tie(%testData,'GDBM_File',$ChartDB,&GDBM_READER,0640); |
$result=tie(%testData,'GDBM_File',$ChartDB,&GDBM_READER,0640); |
Line 906 sub TestCacheData {
|
Line 923 sub TestCacheData {
|
$tieTries++; |
$tieTries++; |
sleep 1; |
sleep 1; |
} |
} |
if($tieTries >= 3) { |
if($tieTries >= 10) { |
return -1; |
return -1; |
} |
} |
|
|
Line 940 sub ExtractStudentData {
|
Line 957 sub ExtractStudentData {
|
} |
} |
|
|
sub ShouldShowColumn { |
sub ShouldShowColumn { |
my ($reselected,$type,$value)=@_; |
my ($cache,$test)=@_; |
|
|
if($ENV{'form.sort'} eq 'Recalculate Chart') { |
if($cache->{'form.reset'} eq 'true') { |
return 1; |
return 1; |
} |
} |
|
|
if(defined($ENV{'form.'.$type.$value})) { |
my $headings=$cache->{'form.headings'}; |
|
my $sequences=$cache->{'form.sequences'}; |
|
if($headings eq 'ALLHEADINGS' || $sequences eq 'ALLSEQUENCES' || |
|
$headings=~/$test/ || $sequences=~/$test/) { |
return 1; |
return 1; |
} |
} |
|
|
return &CheckForStringInArray($reselected, $type.$value); |
# my $reselected=$cache->{'form.reselect'}; |
|
# if($reselected=~/$test/) { |
|
# return 1; |
|
# } |
|
|
|
return 0; |
} |
} |
|
|
sub CheckForStringInArray { |
sub ProcessFormData { |
my ($inputArray,$checkString)=@_; |
my ($ChartDB)=@_; |
foreach (@$inputArray) { |
my %CacheData; |
if($_ eq $checkString) { |
|
return 1; |
if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) { |
|
if(defined($ENV{'form.sort'})) { |
|
$CacheData{'form.sort'}=$ENV{'form.sort'}; |
|
} elsif(!defined($CacheData{'form.sort'})) { |
|
$CacheData{'form.sort'}='username'; |
|
} |
|
|
|
# Ignore $ENV{'form.refresh'} |
|
# Ignore $ENV{'form.recalculate'} |
|
|
|
if(defined($ENV{'form.status'})) { |
|
$CacheData{'form.status'}=$ENV{'form.status'}; |
|
} elsif(!defined($CacheData{'form.status'})) { |
|
$CacheData{'form.status'}='Active'; |
|
} |
|
|
|
my @headings=(); |
|
my @sequences=(); |
|
my $found=0; |
|
foreach (keys(%ENV)) { |
|
if(/form\.heading/) { |
|
$found++; |
|
push(@headings, $_); |
|
} elsif(/form\.sequence/) { |
|
$found++; |
|
push(@sequences, $_); |
|
} elsif(/form\./) { |
|
$found++; |
|
} |
|
} |
|
|
|
if($found) { |
|
$CacheData{'form.headings'}=join(":::",@headings); |
|
$CacheData{'form.sequences'}=join(":::",@sequences); |
|
} |
|
|
|
if(defined($ENV{'form.reselect'})) { |
|
my @reselected = (ref($ENV{'form.reselect'}) ? |
|
@{$ENV{'form.reselect'}} |
|
: ($ENV{'form.reselect'})); |
|
foreach (@reselected) { |
|
if(/heading/) { |
|
$CacheData{'form.headings'}.=":::".$_; |
|
} elsif(/sequence/) { |
|
$CacheData{'form.sequences'}.=":::".$_; |
|
} |
|
} |
} |
} |
|
|
|
if(defined($ENV{'form.reset'})) { |
|
$CacheData{'form.reset'}='true'; |
|
$CacheData{'form.status'}='Active'; |
|
$CacheData{'form.sort'}='username'; |
|
$CacheData{'form.headings'}='ALLHEADINGS'; |
|
$CacheData{'form.sequences'}='ALLSEQUENCES'; |
|
} else { |
|
$CacheData{'form.reset'}='false'; |
|
} |
|
|
|
untie(%CacheData); |
} |
} |
return 0; |
|
|
return; |
} |
} |
|
|
# ----- END HELPER FUNCTIONS -------------------------------------------- |
# ----- END HELPER FUNCTIONS -------------------------------------------- |
Line 980 sub BuildChart {
|
Line 1064 sub BuildChart {
|
my $cid=$ENV{'request.course.id'}; |
my $cid=$ENV{'request.course.id'}; |
my $ChartDB = "/home/httpd/perl/tmp/$ENV{'user.name'}". |
my $ChartDB = "/home/httpd/perl/tmp/$ENV{'user.name'}". |
"_$ENV{'user.domain'}_$cid\_chart.db"; |
"_$ENV{'user.domain'}_$cid\_chart.db"; |
# $ENV{'form.domains'} can be either a scalar or an array reference. |
|
# We need an array. |
|
my @reselected = (ref($ENV{'form.reselect'}) ? @{$ENV{'form.reselect'}} |
|
: ($ENV{'form.reselect'})); |
|
|
|
$isCached=&TestCacheData($ChartDB); |
$isCached=&TestCacheData($ChartDB); |
if($isCached < 0) { |
if($isCached < 0) { |
Line 991 sub BuildChart {
|
Line 1071 sub BuildChart {
|
$r->rflush(); |
$r->rflush(); |
return; |
return; |
} |
} |
|
&ProcessFormData($ChartDB); |
|
|
# Download class list information if not using cached data |
# Download class list information if not using cached data |
my %CacheData; |
my %CacheData; |
Line 1031 sub BuildChart {
|
Line 1112 sub BuildChart {
|
' students</h1>'); } |
' students</h1>'); } |
if(!$c->aborted()) { $r->rflush(); } |
if(!$c->aborted()) { $r->rflush(); } |
if(!$c->aborted()) { $r->print(&CreateLegend()); } |
if(!$c->aborted()) { $r->print(&CreateLegend()); } |
if(!$c->aborted()) { $r->print(&CreateForm()); } |
if(!$c->aborted()) { $r->print(&CreateForm(\%CacheData)); } |
if(!$c->aborted()) { $r->print(&CreateColumnSelectionBox( |
if(!$c->aborted()) { $r->print(&CreateColumnSelectionBox( |
\%CacheData, |
\%CacheData, |
\@studentInformation, |
\@studentInformation, |
\@headings, |
\@headings, |
\@reselected, |
|
$spacePadding)); } |
$spacePadding)); } |
if(!$c->aborted()) { $r->print(&CreateColumnSelectors( |
if(!$c->aborted()) { $r->print(&CreateColumnSelectors( |
\%CacheData, |
\%CacheData, |
\@studentInformation, |
\@studentInformation, |
\@headings, |
\@headings, |
\@reselected, |
|
$spacePadding)); } |
$spacePadding)); } |
if(!$c->aborted()) { $r->print(&CreateTableHeadings( |
if(!$c->aborted()) { $r->print(&CreateTableHeadings( |
\%CacheData, |
\%CacheData, |
\@studentInformation, |
\@studentInformation, |
\@headings, |
\@headings, |
\@reselected, |
|
$spacePadding)); } |
$spacePadding)); } |
if(!$c->aborted()) { $r->rflush(); } |
if(!$c->aborted()) { $r->rflush(); } |
untie(%CacheData); |
untie(%CacheData); |
Line 1071 sub BuildChart {
|
Line 1149 sub BuildChart {
|
push(@updateStudentList, $_); |
push(@updateStudentList, $_); |
&ExtractStudentData($courseData, $_, $ChartDB); |
&ExtractStudentData($courseData, $_, $ChartDB); |
} |
} |
$r->print(&FormatStudentData(\@reselected, $_, $cid, |
$r->print(&FormatStudentData($_, $cid, \@studentInformation, |
\@studentInformation, |
|
$spacePadding, $ChartDB)); |
$spacePadding, $ChartDB)); |
$r->rflush(); |
$r->rflush(); |
} |
} |
Line 1094 sub BuildChart {
|
Line 1171 sub BuildChart {
|
|
|
sub handler { |
sub handler { |
my $r=shift; |
my $r=shift; |
$jr=$r; |
# $jr=$r; |
unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) { |
unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) { |
$ENV{'user.error.msg'}= |
$ENV{'user.error.msg'}= |
$r->uri.":vgr:0:0:Cannot view grades for complete course"; |
$r->uri.":vgr:0:0:Cannot view grades for complete course"; |