version 1.315, 2005/02/05 06:52:50
|
version 1.339, 2005/09/23 22:18:26
|
Line 30
|
Line 30
|
package Apache::lonnavmaps; |
package Apache::lonnavmaps; |
|
|
use strict; |
use strict; |
|
use GDBM_File; |
use Apache::Constants qw(:common :http); |
use Apache::Constants qw(:common :http); |
use Apache::loncommon(); |
use Apache::loncommon(); |
use Apache::lonmenu(); |
use Apache::lonmenu(); |
Line 38 use Apache::lonlocal;
|
Line 39 use Apache::lonlocal;
|
use Apache::lonnet; |
use Apache::lonnet; |
use POSIX qw (floor strftime); |
use POSIX qw (floor strftime); |
use Data::Dumper; # for debugging, not always |
use Data::Dumper; # for debugging, not always |
|
use Time::HiRes qw( gettimeofday tv_interval ); |
|
|
# symbolic constants |
# symbolic constants |
sub SYMB { return 1; } |
sub SYMB { return 1; } |
Line 55 my %statusIconMap =
|
Line 57 my %statusIconMap =
|
$resObj->CLOSED => '', |
$resObj->CLOSED => '', |
$resObj->OPEN => 'navmap.open.gif', |
$resObj->OPEN => 'navmap.open.gif', |
$resObj->CORRECT => 'navmap.correct.gif', |
$resObj->CORRECT => 'navmap.correct.gif', |
|
$resObj->PARTIALLY_CORRECT => 'navmap.ellipsis.gif', |
$resObj->INCORRECT => 'navmap.wrong.gif', |
$resObj->INCORRECT => 'navmap.wrong.gif', |
$resObj->ATTEMPTED => 'navmap.ellipsis.gif', |
$resObj->ATTEMPTED => 'navmap.ellipsis.gif', |
$resObj->ERROR => '' |
$resObj->ERROR => '' |
Line 79 my %colormap =
|
Line 82 my %colormap =
|
$resObj->OPEN => '', |
$resObj->OPEN => '', |
$resObj->NOTHING_SET => '', |
$resObj->NOTHING_SET => '', |
$resObj->ATTEMPTED => '', |
$resObj->ATTEMPTED => '', |
$resObj->ANSWER_SUBMITTED => '' |
$resObj->ANSWER_SUBMITTED => '', |
|
$resObj->PARTIALLY_CORRECT => '#006600' |
); |
); |
# And a special case in the nav map; what to do when the assignment |
# And a special case in the nav map; what to do when the assignment |
# is not yet done and due in less then 24 hours |
# is not yet done and due in less then 24 hours |
my $hurryUpColor = "#FF0000"; |
my $hurryUpColor = "#FF0000"; |
|
|
sub launch_win { |
sub launch_win { |
my ($mode,$script,$toplinkitems)=@_; |
my ($mode,$script,$toplinkitems,$firsttime)=@_; |
my $result; |
my $result; |
if ($script ne 'no') { |
if ($script ne 'no') { |
$result.='<script type="text/javascript">'; |
$result.='<script type="text/javascript">'; |
} |
} |
$result.='function launch_navmapwin() { |
if ($firsttime) { |
|
$result.='function launch_navmapwin() { |
|
newWindow=open(\'/adm/navmaps?launchExternalRoles\',\'loncapanav\',\'width=400,height=600,scrollbars=1\'); |
|
}'; |
|
} else { |
|
$result.='function launch_navmapwin() { |
newWindow=open(\'/adm/navmaps?launchExternal\',\'loncapanav\',\'width=400,height=600,scrollbars=1\'); |
newWindow=open(\'/adm/navmaps?launchExternal\',\'loncapanav\',\'width=400,height=600,scrollbars=1\'); |
}'; |
}'; |
|
} |
if ($mode eq 'now') { |
if ($mode eq 'now') { |
$result.="\nlaunch_navmapwin();\n"; |
$result.="\nlaunch_navmapwin();\n"; |
} |
} |
Line 108 sub launch_win {
|
Line 118 sub launch_win {
|
} |
} |
|
|
sub close { |
sub close { |
if ($ENV{'environment.remotenavmap'} ne 'on') { return ''; } |
if ($env{'environment.remotenavmap'} ne 'on') { return ''; } |
return(<<ENDCLOSE); |
return(<<ENDCLOSE); |
<script type="text/javascript"> |
<script type="text/javascript"> |
window.status='Accessing Nav Control'; |
window.status='Accessing Nav Control'; |
Line 122 ENDCLOSE
|
Line 132 ENDCLOSE
|
} |
} |
|
|
sub update { |
sub update { |
if ($ENV{'environment.remotenavmap'} ne 'on') { return ''; } |
if ($env{'environment.remotenavmap'} ne 'on') { return ''; } |
if (!$ENV{'request.course.id'}) { return ''; } |
if (!$env{'request.course.id'}) { return ''; } |
if ($ENV{'REQUEST_URI'}=~m|^/adm/navmaps|) { return ''; } |
if ($ENV{'REQUEST_URI'}=~m|^/adm/navmaps|) { return ''; } |
return(<<ENDUPDATE); |
return(<<ENDUPDATE); |
<form name="navform"></form> |
<form name="navform"></form> |
Line 142 sub handler {
|
Line 152 sub handler {
|
|
|
sub real_handler { |
sub real_handler { |
my $r = shift; |
my $r = shift; |
|
#my $t0=[&gettimeofday()]; |
# Handle header-only request |
# Handle header-only request |
if ($r->header_only) { |
if ($r->header_only) { |
if ($ENV{'browser.mathml'}) { |
if ($env{'browser.mathml'}) { |
&Apache::loncommon::content_type($r,'text/xml'); |
&Apache::loncommon::content_type($r,'text/xml'); |
} else { |
} else { |
&Apache::loncommon::content_type($r,'text/html'); |
&Apache::loncommon::content_type($r,'text/html'); |
Line 155 sub real_handler {
|
Line 165 sub real_handler {
|
} |
} |
|
|
# Send header, don't cache this page |
# Send header, don't cache this page |
if ($ENV{'browser.mathml'}) { |
if ($env{'browser.mathml'}) { |
&Apache::loncommon::content_type($r,'text/xml'); |
&Apache::loncommon::content_type($r,'text/xml'); |
} else { |
} else { |
&Apache::loncommon::content_type($r,'text/html'); |
&Apache::loncommon::content_type($r,'text/html'); |
Line 184 MENU
|
Line 194 MENU
|
$navstatus |
$navstatus |
MENU |
MENU |
} |
} |
|
my $html=&Apache::lonxml::xmlbegin(); |
$r->print(<<"ENDSUBM"); |
$r->print(<<"ENDSUBM"); |
<html> |
$html |
<head> |
<head> |
<script type="text/javascript"> |
<script type="text/javascript"> |
function submitthis() { |
function submitthis() { |
Line 200 MENU
|
Line 211 MENU
|
ENDSUBM |
ENDSUBM |
return; |
return; |
} |
} |
if ($ENV{QUERY_STRING} eq 'launchExternal') { |
if ($ENV{QUERY_STRING} =~ /^launchExternal/) { |
&Apache::lonnet::put('environment',{'remotenavmap' => 'on'}); |
&Apache::lonnet::put('environment',{'remotenavmap' => 'on'}); |
&Apache::lonnet::appenv('environment.remotenavmap' => 'on'); |
&Apache::lonnet::appenv('environment.remotenavmap' => 'on'); |
|
my $menu=&Apache::lonmenu::reopenmenu(); |
|
my $navstatus=&Apache::lonmenu::get_nav_status(); |
|
if ($menu) { |
|
$r->print(<<MENU); |
|
<script type="text/javascript"> |
|
swmenu=$menu |
|
swmenu.clearTimeout(swmenu.menucltim); |
|
$navstatus |
|
</script> |
|
MENU |
|
} |
|
} |
|
if ($ENV{QUERY_STRING} eq 'turningOffExternal') { |
|
$env{'environment.remotenavmap'}='off'; |
} |
} |
|
|
# Create the nav map |
# Create the nav map |
Line 210 ENDSUBM
|
Line 235 ENDSUBM
|
|
|
if (!defined($navmap)) { |
if (!defined($navmap)) { |
my $requrl = $r->uri; |
my $requrl = $r->uri; |
$ENV{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; |
$env{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; |
return HTTP_NOT_ACCEPTABLE; |
return HTTP_NOT_ACCEPTABLE; |
} |
} |
|
my $html=&Apache::lonxml::xmlbegin(); |
$r->print("<html><head>\n"); |
$r->print("$html<head>\n"); |
$r->print("<title>".&mt('Navigate Course Contents')."</title>"); |
$r->print("<title>".&mt('Navigate Course Contents')."</title>"); |
# ------------------------------------------------------------ Get query string |
# ------------------------------------------------------------ Get query string |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); |
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); |
Line 223 ENDSUBM
|
Line 248 ENDSUBM
|
my $addentries=''; |
my $addentries=''; |
my $more_unload; |
my $more_unload; |
my $body_only=''; |
my $body_only=''; |
if ($ENV{'environment.remotenavmap'} eq 'on') { |
if ($env{'environment.remotenavmap'} eq 'on') { |
$r->print('<script type="text/javascript"> |
$r->print('<script type="text/javascript"> |
function collapse() { |
function collapse() { |
this.document.location="/adm/navmaps?collapseExternal"; |
this.document.location="/adm/navmaps?collapseExternal"; |
Line 233 ENDSUBM
|
Line 258 ENDSUBM
|
# $more_unload="collapse()" |
# $more_unload="collapse()" |
$body_only=1; |
$body_only=1; |
} |
} |
if ($ENV{'form.register'}) { |
if ($env{'form.register'}) { |
$addentries=' onLoad="'.&Apache::lonmenu::loadevents(). |
$addentries=' onLoad="'.&Apache::lonmenu::loadevents(). |
'" onUnload="'.&Apache::lonmenu::unloadevents().';'. |
'" onUnload="'.&Apache::lonmenu::unloadevents().';'. |
$more_unload.'"'; |
$more_unload.'"'; |
Line 246 ENDSUBM
|
Line 271 ENDSUBM
|
$r->print('</head>'. |
$r->print('</head>'. |
&Apache::loncommon::bodytag('Navigate Course Contents','', |
&Apache::loncommon::bodytag('Navigate Course Contents','', |
$addentries,$body_only,'', |
$addentries,$body_only,'', |
$ENV{'form.register'})); |
$env{'form.register'})); |
$r->print('<script>window.focus();</script>'); |
$r->print('<script>window.focus();</script>'); |
|
|
$r->rflush(); |
$r->rflush(); |
Line 277 ENDSUBM
|
Line 302 ENDSUBM
|
if ($sequenceCount == 1) { |
if ($sequenceCount == 1) { |
# The automatic iterator creation in the render call |
# The automatic iterator creation in the render call |
# will pick this up. We know the condition because |
# will pick this up. We know the condition because |
# the defined($ENV{'form.filter'}) also ensures this |
# the defined($env{'form.filter'}) also ensures this |
# is a fresh call. |
# is a fresh call. |
$ENV{'form.filter'} = "$sequenceId"; |
$env{'form.filter'} = "$sequenceId"; |
} |
} |
} |
} |
|
|
if ($ENV{QUERY_STRING} eq 'launchExternal') { |
if ($ENV{QUERY_STRING} eq 'launchExternal') { |
$r->print(' |
$r->print(' |
<form name="returnwin" action="/adm/flip?postdata=return%3a" |
<form name="returnwin" action="/adm/flip?postdata=navlaunch%3a" |
method="post" target="loncapaclient"> |
method="post" target="loncapaclient"> |
</form>'); |
</form>'); |
$r->print(' |
$r->print(' |
Line 294 ENDSUBM
|
Line 319 ENDSUBM
|
</script>'); |
</script>'); |
} |
} |
|
|
if ($ENV{'environment.remotenavmap'} ne 'on') { |
if ($env{'environment.remotenavmap'} ne 'on') { |
$r->print(&launch_win('link','yes',\%toplinkitems)); |
$r->print(&launch_win('link','yes',\%toplinkitems)); |
} |
} |
if ($ENV{'environment.remotenavmap'} eq 'on') { |
if ($env{'environment.remotenavmap'} eq 'on') { |
&add_linkitem(\%toplinkitems,'closenav','collapse()', |
&add_linkitem(\%toplinkitems,'closenav','collapse()', |
"Close navigation window"); |
"Close navigation window"); |
} |
} |
Line 324 ENDSUBM
|
Line 349 ENDSUBM
|
pop @$stack; # last resource in the stack is the problem |
pop @$stack; # last resource in the stack is the problem |
# itself, which we don't need in the map stack |
# itself, which we don't need in the map stack |
my @mapPcs = map {$_->map_pc()} @$stack; |
my @mapPcs = map {$_->map_pc()} @$stack; |
$ENV{'form.filter'} = join(',', @mapPcs); |
$env{'form.filter'} = join(',', @mapPcs); |
|
|
# Mark as both "here" and "jump" |
# Mark as both "here" and "jump" |
$ENV{'form.postsymb'} = $curRes->symb(); |
$env{'form.postsymb'} = $curRes->symb(); |
} |
} |
} |
} |
} |
} |
Line 348 ENDSUBM
|
Line 373 ENDSUBM
|
|
|
# Display only due homework. |
# Display only due homework. |
my $showOnlyHomework = 0; |
my $showOnlyHomework = 0; |
if ($ENV{'form.showOnlyHomework'} eq "1") { |
if ($env{'form.showOnlyHomework'} eq "1") { |
$showOnlyHomework = 1; |
$showOnlyHomework = 1; |
$suppressEmptySequences = 1; |
$suppressEmptySequences = 1; |
$filterFunc = sub { my $res = shift; |
$filterFunc = sub { my $res = shift; |
return $res->completable() || $res->is_map(); |
return $res->completable() || $res->is_map(); |
}; |
}; |
&add_linkitem(\%toplinkitems,'everything', |
&add_linkitem(\%toplinkitems,'everything', |
'location.href="navmaps?sort='.$ENV{'form.sort'}.'"', |
'location.href="navmaps?sort='.$env{'form.sort'}.'"', |
"Show Everything"); |
"Show Everything"); |
$r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>"); |
$r->print("<p><font size='+2'>".&mt("Uncompleted Homework")."</font></p>"); |
$ENV{'form.filter'} = ''; |
$env{'form.filter'} = ''; |
$ENV{'form.condition'} = 1; |
$env{'form.condition'} = 1; |
$resource_no_folder_link = 1; |
$resource_no_folder_link = 1; |
} else { |
} else { |
&add_linkitem(\%toplinkitems,'uncompleted', |
&add_linkitem(\%toplinkitems,'uncompleted', |
'location.href="navmaps?sort='.$ENV{'form.sort'}. |
'location.href="navmaps?sort='.$env{'form.sort'}. |
'&showOnlyHomework=1"', |
'&showOnlyHomework=1"', |
"Show Only Uncompleted Homework"); |
"Show Only Uncompleted Homework"); |
} |
} |
|
|
my %selected=($ENV{'form.sort'} => 'selected=on'); |
my %selected=($env{'form.sort'} => 'selected=on'); |
my $sort_html=("<form> |
my $sort_html=("<form> |
<nobr> |
<nobr> |
<input type=\"hidden\" name=\"showOnlyHomework\" value=\"".$ENV{'form.showOnlyHomework'}."\" /> |
<input type=\"hidden\" name=\"showOnlyHomework\" value=\"".$env{'form.showOnlyHomework'}."\" /> |
<input type=\"submit\" value=\"".&mt('Sort by:')."\" /> |
<input type=\"submit\" value=\"".&mt('Sort by:')."\" /> |
<select name=\"sort\"> |
<select name=\"sort\"> |
<option value=\"default\" $selected{'default'}>".&mt('Default')."</option> |
<option value=\"default\" $selected{'default'}>".&mt('Default')."</option> |
Line 383 ENDSUBM
|
Line 408 ENDSUBM
|
</form>"); |
</form>"); |
# renderer call |
# renderer call |
my $renderArgs = { 'cols' => [0,1,2,3], |
my $renderArgs = { 'cols' => [0,1,2,3], |
'sort' => $ENV{'form.sort'}, |
'sort' => $env{'form.sort'}, |
'url' => '/adm/navmaps', |
'url' => '/adm/navmaps', |
'navmap' => $navmap, |
'navmap' => $navmap, |
'suppressNavmap' => 1, |
'suppressNavmap' => 1, |
Line 405 ENDSUBM
|
Line 430 ENDSUBM
|
$r->print("<p><font size='+1'>This course is empty.</font></p>"); |
$r->print("<p><font size='+1'>This course is empty.</font></p>"); |
} |
} |
} |
} |
|
#my $td=&tv_interval($t0); |
|
#$r->print("<br />$td"); |
|
|
$r->print("</body></html>"); |
$r->print("</body></html>"); |
$r->rflush(); |
$r->rflush(); |
Line 502 sub getDescription {
|
Line 529 sub getDescription {
|
if ($status == $res->PAST_DUE_NO_ANSWER) { |
if ($status == $res->PAST_DUE_NO_ANSWER) { |
return &mt("Was due")." " . timeToHumanString($res->duedate($part)); |
return &mt("Was due")." " . timeToHumanString($res->duedate($part)); |
} |
} |
if ($status == $res->ANSWER_OPEN) { |
if ($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) { |
return &mt("Answer available"); |
return &mt("Answer available"); |
} |
} |
if ($status == $res->EXCUSED) { |
if ($status == $res->EXCUSED) { |
Line 560 sub lastTry {
|
Line 587 sub lastTry {
|
$res->duedate($part) > time(); |
$res->duedate($part) > time(); |
} |
} |
|
|
# This puts a human-readable name on the ENV variable. |
# This puts a human-readable name on the env variable. |
|
|
sub advancedUser { |
sub advancedUser { |
return $ENV{'request.role.adv'}; |
return $env{'request.role.adv'}; |
} |
} |
|
|
|
|
Line 653 sub timeToHumanString {
|
Line 680 sub timeToHumanString {
|
my $timeStr = strftime("%A, %b %e at %I:%M %P", localtime($time)); |
my $timeStr = strftime("%A, %b %e at %I:%M %P", localtime($time)); |
$timeStr =~ s/12:00 am/00:00/; |
$timeStr =~ s/12:00 am/00:00/; |
$timeStr =~ s/12:00 pm/noon/; |
$timeStr =~ s/12:00 pm/noon/; |
return ($inPast ? "last " : "next ") . |
return ($inPast ? "last " : "this ") . |
$timeStr; |
$timeStr; |
} |
} |
|
|
Line 866 automatically.
|
Line 893 automatically.
|
|
|
=over 4 |
=over 4 |
|
|
=item * B<iterator>: default: constructs one from %ENV |
=item * B<iterator>: default: constructs one from %env |
|
|
A reference to a fresh ::iterator to use from the navmaps. The |
A reference to a fresh ::iterator to use from the navmaps. The |
rendering will reflect the options passed to the iterator, so you can |
rendering will reflect the options passed to the iterator, so you can |
use that to just render a certain part of the course, if you like. If |
use that to just render a certain part of the course, if you like. If |
one is not passed, the renderer will attempt to construct one from |
one is not passed, the renderer will attempt to construct one from |
ENV{'form.filter'} and ENV{'form.condition'} information, plus the |
env{'form.filter'} and env{'form.condition'} information, plus the |
'iterator_map' parameter if any. |
'iterator_map' parameter if any. |
|
|
=item * B<iterator_map>: default: not used |
=item * B<iterator_map>: default: not used |
Line 882 instruct the renderer to render only a p
|
Line 909 instruct the renderer to render only a p
|
the source of the map you want to process, like |
the source of the map you want to process, like |
'/res/103/jerf/navmap.course.sequence'. |
'/res/103/jerf/navmap.course.sequence'. |
|
|
=item * B<navmap>: default: constructs one from %ENV |
=item * B<navmap>: default: constructs one from %env |
|
|
A reference to a navmap, used only if an iterator is not passed in. If |
A reference to a navmap, used only if an iterator is not passed in. If |
this is necessary to make an iterator but it is not passed in, a new |
this is necessary to make an iterator but it is not passed in, a new |
one will be constructed based on ENV info. This is useful to do basic |
one will be constructed based on env info. This is useful to do basic |
error checking before passing it off to render. |
error checking before passing it off to render. |
|
|
=item * B<r>: default: must be passed in |
=item * B<r>: default: must be passed in |
Line 912 then only one line will be displayed for
|
Line 939 then only one line will be displayed for
|
all parts will always be displayed. If showParts is 0, this is |
all parts will always be displayed. If showParts is 0, this is |
ignored. |
ignored. |
|
|
=item * B<jumpCount>: default: determined from %ENV |
=item * B<jumpCount>: default: determined from %env |
|
|
A string identifying the URL to place the anchor 'curloc' at. |
A string identifying the URL to place the anchor 'curloc' at. |
It is the responsibility of the renderer user to |
It is the responsibility of the renderer user to |
ensure that the #curloc is in the URL. By default, determined through |
ensure that the #curloc is in the URL. By default, determined through |
the use of the ENV{} 'jump' information, and should normally "just |
the use of the env{} 'jump' information, and should normally "just |
work" correctly. |
work" correctly. |
|
|
=item * B<here>: default: empty string |
=item * B<here>: default: empty string |
Line 945 are allowing the user to open and close
|
Line 972 are allowing the user to open and close
|
|
|
Describes the currently-open row number to cause the browser to jump |
Describes the currently-open row number to cause the browser to jump |
to, because the user just opened that folder. By default, pulled from |
to, because the user just opened that folder. By default, pulled from |
the Jump information in the ENV{'form.*'}. |
the Jump information in the env{'form.*'}. |
|
|
=item * B<printKey>: default: false |
=item * B<printKey>: default: false |
|
|
Line 1034 sub render_resource {
|
Line 1061 sub render_resource {
|
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); |
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonIcons"); |
# If this is a new branch, label it so |
# If this is a new branch, label it so |
if ($params->{'isNewBranch'}) { |
if ($params->{'isNewBranch'}) { |
$newBranchText = "<img src='$location/branch.gif' border='0' />"; |
$newBranchText = "<img src='$location/branch.gif' border='0' alt='Branch' />"; |
} |
} |
|
|
# links to open and close the folder |
# links to open and close the folder |
Line 1046 sub render_resource {
|
Line 1073 sub render_resource {
|
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
|
|
# Default icon: unknown page |
# Default icon: unknown page |
my $icon = "<img src='$location/unknown.gif' alt='' border='0' />"; |
my $icon = "<img src='$location/unknown.gif' alt='' border='0' alt=' ' ' />"; |
|
|
if ($resource->is_problem()) { |
if ($resource->is_problem()) { |
if ($part eq '0' || $params->{'condensed'}) { |
if ($part eq '0' || $params->{'condensed'}) { |
$icon ='<img src="'.$location.'/problem.gif" alt="" border="0" />'; |
$icon ='<img src="'.$location.'/problem.gif" alt=" " border="0" />'; |
} else { |
} else { |
$icon = $params->{'indentString'}; |
$icon = $params->{'indentString'}; |
} |
} |
} else { |
} else { |
$icon = "<img src='".&Apache::loncommon::lonhttpdurl(&Apache::loncommon::icon($resource->src))."' alt='' border='0' />"; |
$icon = "<img src='".&Apache::loncommon::icon($resource->src)."' alt=' ' border='0' />"; |
} |
} |
|
|
# Display the correct map icon to open or shut map |
# Display the correct map icon to open or shut map |
Line 1070 sub render_resource {
|
Line 1097 sub render_resource {
|
|
|
if (!$params->{'resource_no_folder_link'}) { |
if (!$params->{'resource_no_folder_link'}) { |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif'; |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif'; |
$icon = "<img src='$location/$icon' alt='' border='0' />"; |
$icon = "<img src='$location/$icon' alt='". |
|
($nowOpen ? 'Open Folder' : 'Close Folder')."' border='0' />"; |
|
|
$linkopen = "<a href='" . $params->{'url'} . '?' . |
$linkopen = "<a href='" . $params->{'url'} . '?' . |
$params->{'queryString'} . '&filter='; |
$params->{'queryString'} . '&filter='; |
Line 1088 sub render_resource {
|
Line 1116 sub render_resource {
|
# Don't allow users to manipulate folder |
# Don't allow users to manipulate folder |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . |
$icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . |
'.nomanip.gif'; |
'.nomanip.gif'; |
$icon = "<img src='$location/$icon' alt='' border='0' />"; |
$icon = "<img src='$location/$icon' alt='". |
|
($nowOpen ? 'Open Folder' : 'Close Folder')."' border='0' />"; |
|
|
$linkopen = ""; |
$linkopen = ""; |
$linkclose = ""; |
$linkclose = ""; |
Line 1138 sub render_resource {
|
Line 1167 sub render_resource {
|
} |
} |
|
|
my $target; |
my $target; |
if ($ENV{'environment.remotenavmap'} eq 'on') { |
if ($env{'environment.remotenavmap'} eq 'on') { |
$target=' target="loncapaclient" '; |
$target=' target="loncapaclient" '; |
} |
} |
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { |
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { |
Line 1155 sub render_communication_status {
|
Line 1184 sub render_communication_status {
|
my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = ""; |
my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = ""; |
|
|
my $link = $params->{"resourceLink"}; |
my $link = $params->{"resourceLink"}; |
my $linkopen = "<a href='$link'>"; |
my $target; |
|
if ($env{'environment.remotenavmap'} eq 'on') { |
|
$target=' target="loncapaclient" '; |
|
} |
|
my $linkopen = "<a $target href='$link'>"; |
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
if ($resource->hasDiscussion()) { |
if ($resource->hasDiscussion()) { |
Line 1168 sub render_communication_status {
|
Line 1201 sub render_communication_status {
|
my $feedback = $resource->getFeedback(); |
my $feedback = $resource->getFeedback(); |
foreach (split(/\,/, $feedback)) { |
foreach (split(/\,/, $feedback)) { |
if ($_) { |
if ($_) { |
$feedbackHTML .= ' <a href="/adm/email?display=' |
$feedbackHTML .= ' <a '.$target.' href="/adm/email?display=' |
. &Apache::lonnet::escape($_) . '">' |
. &Apache::lonnet::escape($_) . '">' |
. '<img src="'.$location.'/feedback.gif" ' |
. '<img src="'.$location.'/feedback.gif" ' |
. 'border="0" /></a>'; |
. 'border="0" /></a>'; |
Line 1183 sub render_communication_status {
|
Line 1216 sub render_communication_status {
|
last if ($errorcount>=10); # Only output 10 bombs maximum |
last if ($errorcount>=10); # Only output 10 bombs maximum |
if ($_) { |
if ($_) { |
$errorcount++; |
$errorcount++; |
$errorHTML .= ' <a href="/adm/email?display=' |
$errorHTML .= ' <a '.$target.' href="/adm/email?display=' |
. &Apache::lonnet::escape($_) . '">' |
. &Apache::lonnet::escape($_) . '">' |
. '<img src="'.$location.'/bomb.gif" ' |
. '<img src="'.$location.'/bomb.gif" ' |
. 'border="0" /></a>'; |
. 'border="0" /></a>'; |
Line 1205 sub render_quick_status {
|
Line 1238 sub render_quick_status {
|
$params->{'multipart'} && $part eq "0"; |
$params->{'multipart'} && $part eq "0"; |
|
|
my $link = $params->{"resourceLink"}; |
my $link = $params->{"resourceLink"}; |
my $linkopen = "<a href='$link'>"; |
my $target; |
|
if ($env{'environment.remotenavmap'} eq 'on') { |
|
$target=' target="loncapaclient" '; |
|
} |
|
my $linkopen = "<a $target href='$link'>"; |
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
|
|
if ($resource->is_problem() && |
if ($resource->is_problem() && |
Line 1364 sub render {
|
Line 1401 sub render {
|
# no columns, no nav maps. |
# no columns, no nav maps. |
return ''; |
return ''; |
} |
} |
my $mustCloseNavMap = 0; |
|
my $navmap; |
my $navmap; |
if (defined($args->{'navmap'})) { |
if (defined($args->{'navmap'})) { |
$navmap = $args->{'navmap'}; |
$navmap = $args->{'navmap'}; |
Line 1385 sub render {
|
Line 1421 sub render {
|
# marker |
# marker |
my $filterHash = {}; |
my $filterHash = {}; |
# Figure out what we're not displaying |
# Figure out what we're not displaying |
foreach (split(/\,/, $ENV{"form.filter"})) { |
foreach (split(/\,/, $env{"form.filter"})) { |
if ($_) { |
if ($_) { |
$filterHash->{$_} = "1"; |
$filterHash->{$_} = "1"; |
} |
} |
Line 1405 sub render {
|
Line 1441 sub render {
|
} |
} |
|
|
my $condition = 0; |
my $condition = 0; |
if ($ENV{'form.condition'}) { |
if ($env{'form.condition'}) { |
$condition = 1; |
$condition = 1; |
} |
} |
|
|
if (!$ENV{'form.folderManip'} && !defined($args->{'iterator'})) { |
if (!$env{'form.folderManip'} && !defined($args->{'iterator'})) { |
# Step 1: Check to see if we have a navmap |
# Step 1: Check to see if we have a navmap |
if (!defined($navmap)) { |
if (!defined($navmap)) { |
$navmap = Apache::lonnavmaps::navmap->new(); |
$navmap = Apache::lonnavmaps::navmap->new(); |
$mustCloseNavMap = 1; |
|
} |
} |
|
|
# Step two: Locate what kind of here marker is necessary |
# Step two: Locate what kind of here marker is necessary |
# Determine where the "here" marker is and where the screen jumps to. |
# Determine where the "here" marker is and where the screen jumps to. |
|
|
if ($ENV{'form.postsymb'}) { |
if ($env{'form.postsymb'} ne '') { |
$here = $jump = &Apache::lonnet::symbclean($ENV{'form.postsymb'}); |
$here = $jump = &Apache::lonnet::symbclean($env{'form.postsymb'}); |
} elsif ($ENV{'form.postdata'}) { |
} elsif ($env{'form.postdata'} ne '') { |
# couldn't find a symb, is there a URL? |
# couldn't find a symb, is there a URL? |
my $currenturl = $ENV{'form.postdata'}; |
my $currenturl = $env{'form.postdata'}; |
#$currenturl=~s/^http\:\/\///; |
#$currenturl=~s/^http\:\/\///; |
#$currenturl=~s/^[^\/]+//; |
#$currenturl=~s/^[^\/]+//; |
|
|
$here = $jump = &Apache::lonnet::symbread($currenturl); |
$here = $jump = &Apache::lonnet::symbread($currenturl); |
} |
} |
|
if ($here eq '') { |
|
my $last; |
|
if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db', |
|
&GDBM_READER(),0640)) { |
|
$last=$hash{'last_known'}; |
|
untie(%hash); |
|
} |
|
if ($last) { $here = $jump = $last; } |
|
} |
|
|
# Step three: Ensure the folders are open |
# Step three: Ensure the folders are open |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
my $mapIterator = $navmap->getIterator(undef, undef, undef, 1); |
Line 1455 sub render {
|
Line 1499 sub render {
|
} |
} |
} |
} |
|
|
if ( !defined($args->{'iterator'}) && $ENV{'form.folderManip'} ) { # we came from a user's manipulation of the nav page |
if ( !defined($args->{'iterator'}) && $env{'form.folderManip'} ) { # we came from a user's manipulation of the nav page |
# If this is a click on a folder or something, we want to preserve the "here" |
# If this is a click on a folder or something, we want to preserve the "here" |
# from the querystring, and get the new "jump" marker |
# from the querystring, and get the new "jump" marker |
$here = $ENV{'form.here'}; |
$here = $env{'form.here'}; |
$jump = $ENV{'form.jump'}; |
$jump = $env{'form.jump'}; |
} |
} |
|
|
my $it = $args->{'iterator'}; |
my $it = $args->{'iterator'}; |
if (!defined($it)) { |
if (!defined($it)) { |
# Construct a default iterator based on $ENV{'form.'} information |
# Construct a default iterator based on $env{'form.'} information |
|
|
# Step 1: Check to see if we have a navmap |
# Step 1: Check to see if we have a navmap |
if (!defined($navmap)) { |
if (!defined($navmap)) { |
$navmap = Apache::lonnavmaps::navmap->new(); |
$navmap = Apache::lonnavmaps::navmap->new(); |
$mustCloseNavMap = 1; |
|
} |
} |
|
|
# See if we're being passed a specific map |
# See if we're being passed a specific map |
Line 1575 END
|
Line 1618 END
|
my @allres=$navmap->retrieveResources(); |
my @allres=$navmap->retrieveResources(); |
foreach my $resource (@allres) { |
foreach my $resource (@allres) { |
if ($resource->hasDiscussion()) { |
if ($resource->hasDiscussion()) { |
my $ressymb; |
$haveDisc .= $resource->wrap_symb().':'; |
if ($resource->symb() =~ m-(___adm/\w+/\w+)/(\d+)/bulletinboard$-) { |
|
$ressymb = 'bulletin___'.$2.$1.'/'.$2.'/bulletinboard'; |
|
} else { |
|
$ressymb = $resource->symb(); |
|
} |
|
$haveDisc .= $ressymb.':'; |
|
$totdisc ++; |
$totdisc ++; |
} |
} |
} |
} |
Line 1599 END
|
Line 1636 END
|
if ($args->{'caller'} eq 'navmapsdisplay') { |
if ($args->{'caller'} eq 'navmapsdisplay') { |
$result .= '<table><tr><td>'. |
$result .= '<table><tr><td>'. |
&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').'</td>'; |
&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').'</td>'; |
if ($ENV{'environment.remotenavmap'} ne 'on') { |
if ($env{'environment.remotenavmap'} ne 'on') { |
$result .= '<td> </td>'; |
$result .= '<td> </td>'; |
} else { |
} else { |
$result .= '</tr><tr>'; |
$result .= '</tr><tr>'; |
} |
} |
$result.=&show_linkitems($args->{'linkitems'}); |
$result.=&show_linkitems($args->{'linkitems'}); |
if ($args->{'sort_html'}) { |
if ($args->{'sort_html'}) { |
if ($ENV{'environment.remotenavmap'} ne 'on') { |
if ($env{'environment.remotenavmap'} ne 'on') { |
$result.='<td> </td><td> </td><td> </td>'. |
$result.='<td> </td><td> </td><td> </td>'. |
'<td align="right">'.$args->{'sort_html'}.'</td></tr>'; |
'<td align="right">'.$args->{'sort_html'}.'</td></tr>'; |
} else { |
} else { |
Line 1643 END
|
Line 1680 END
|
$args->{'condensed'} = 0; |
$args->{'condensed'} = 0; |
my $location= |
my $location= |
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace1.gif"); |
&Apache::loncommon::lonhttpdurl("/adm/lonIcons/whitespace1.gif"); |
$args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' width='25' height='1' alt='' border='0' />"); |
$args->{'indentString'} = setDefault($args->{'indentString'}, "<img src='$location' width='25' height='1' alt=' ' border='0' />"); |
$args->{'displayedHereMarker'} = 0; |
$args->{'displayedHereMarker'} = 0; |
|
|
# If we're suppressing empty sequences, look for them here. Use DFS for speed, |
# If we're suppressing empty sequences, look for them here. Use DFS for speed, |
Line 2057 See iterator documentation below.
|
Line 2094 See iterator documentation below.
|
|
|
use strict; |
use strict; |
use GDBM_File; |
use GDBM_File; |
|
use Apache::lonnet; |
|
|
sub new { |
sub new { |
# magic invocation to create a class instance |
# magic invocation to create a class instance |
Line 2076 sub new {
|
Line 2114 sub new {
|
|
|
my %navmaphash; |
my %navmaphash; |
my %parmhash; |
my %parmhash; |
my $courseFn = $ENV{"request.course.fn"}; |
my $courseFn = $env{"request.course.fn"}; |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
&GDBM_READER(), 0640))) { |
&GDBM_READER(), 0640))) { |
return undef; |
return undef; |
Line 2102 sub generate_course_user_opt {
|
Line 2140 sub generate_course_user_opt {
|
my $self = shift; |
my $self = shift; |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
|
|
my $uname=$ENV{'user.name'}; |
my $uname=$env{'user.name'}; |
my $udom=$ENV{'user.domain'}; |
my $udom=$env{'user.domain'}; |
my $uhome=$ENV{'user.home'}; |
my $cid=$env{'request.course.id'}; |
my $cid=$ENV{'request.course.id'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $chome=$ENV{'course.'.$cid.'.home'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my ($cdom,$cnum)=split(/\_/,$cid); |
|
|
|
my $userprefix=$uname.'_'.$udom.'_'; |
|
|
|
my %courserdatas; my %useropt; my %courseopt; my %userrdatas; |
|
unless ($uhome eq 'no_host') { |
|
# ------------------------------------------------- Get coursedata (if present) |
# ------------------------------------------------- Get coursedata (if present) |
unless ((time-$courserdatas{$cid.'.last_cache'})<240) { |
my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom); |
my $reply=&Apache::lonnet::reply('dump:'.$cdom.':'.$cnum. |
# Check for network failure |
':resourcedata',$chome); |
if (!ref($courseopt)) { |
# Check for network failure |
if ( $courseopt =~ /no.such.host/i || $courseopt =~ /con_lost/i) { |
if ( $reply =~ /no.such.host/i || $reply =~ /con_lost/i) { |
$self->{NETWORK_FAILURE} = 1; |
$self->{NETWORK_FAILURE} = 1; |
|
} elsif ($reply!~/^error\:/) { |
|
$courserdatas{$cid}=$reply; |
|
$courserdatas{$cid.'.last_cache'}=time; |
|
} |
|
} |
|
foreach (split(/\&/,$courserdatas{$cid})) { |
|
my ($name,$value)=split(/\=/,$_); |
|
$courseopt{$userprefix.&Apache::lonnet::unescape($name)}= |
|
&Apache::lonnet::unescape($value); |
|
} |
} |
|
undef($courseopt); |
|
} |
|
|
# --------------------------------------------------- Get userdata (if present) |
# --------------------------------------------------- Get userdata (if present) |
unless ((time-$userrdatas{$uname.'___'.$udom.'.last_cache'})<240) { |
|
my $reply=&Apache::lonnet::reply('dump:'.$udom.':'.$uname.':resourcedata',$uhome); |
my $useropt=&Apache::lonnet::get_userresdata($uname,$udom); |
if ($reply!~/^error\:/) { |
# Check for network failure |
$userrdatas{$uname.'___'.$udom}=$reply; |
if (!ref($useropt)) { |
$userrdatas{$uname.'___'.$udom.'.last_cache'}=time; |
if ( $useropt =~ /no.such.host/i || $useropt =~ /con_lost/i) { |
} |
$self->{NETWORK_FAILURE} = 1; |
# check to see if network failed |
|
elsif ( $reply=~/no.such.host/i || $reply=~/con.*lost/i ) |
|
{ |
|
$self->{NETWORK_FAILURE} = 1; |
|
} |
|
} |
|
foreach (split(/\&/,$userrdatas{$uname.'___'.$udom})) { |
|
my ($name,$value)=split(/\=/,$_); |
|
$useropt{$userprefix.&Apache::lonnet::unescape($name)}= |
|
&Apache::lonnet::unescape($value); |
|
} |
} |
$self->{COURSE_OPT} = \%courseopt; |
undef($useropt); |
$self->{USER_OPT} = \%useropt; |
|
} |
} |
|
|
|
$self->{COURSE_OPT} = $courseopt; |
|
$self->{USER_OPT} = $useropt; |
|
|
$self->{COURSE_USER_OPT_GENERATED} = 1; |
$self->{COURSE_USER_OPT_GENERATED} = 1; |
|
|
return; |
return; |
Line 2162 sub generate_email_discuss_status {
|
Line 2180 sub generate_email_discuss_status {
|
my $symb = shift; |
my $symb = shift; |
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; } |
if ($self->{EMAIL_DISCUSS_GENERATED}) { return; } |
|
|
my $cid=$ENV{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
my ($cdom,$cnum)=split(/\_/,$cid); |
my $cdom=$env{'course.'.$cid.'.domain'}; |
|
my $cnum=$env{'course.'.$cid.'.num'}; |
|
|
my %emailstatus = &Apache::lonnet::dump('email_status'); |
my %emailstatus = &Apache::lonnet::dump('email_status'); |
my $logoutTime = $emailstatus{'logout'}; |
my $logoutTime = $emailstatus{'logout'}; |
my $courseLeaveTime = $emailstatus{'logout_'.$ENV{'request.course.id'}}; |
my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}}; |
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? |
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? |
$courseLeaveTime : $logoutTime); |
$courseLeaveTime : $logoutTime); |
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
$cdom, $cnum); |
$cdom, $cnum); |
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', |
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', |
$ENV{'user.domain'},$ENV{'user.name'},'lastread'); |
$env{'user.domain'},$env{'user.name'},'lastread'); |
my %lastreadtime = (); |
my %lastreadtime = (); |
foreach (keys %lastread) { |
foreach (keys %lastread) { |
my $key = $_; |
my $key = $_; |
Line 2183 sub generate_email_discuss_status {
|
Line 2202 sub generate_email_discuss_status {
|
|
|
my %feedback=(); |
my %feedback=(); |
my %error=(); |
my %error=(); |
my $keys = &Apache::lonnet::reply('keys:'. |
my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'}, |
$ENV{'user.domain'}.':'. |
$env{'user.name'}); |
$ENV{'user.name'}.':nohist_email', |
|
$ENV{'user.home'}); |
|
|
|
foreach my $msgid (split(/\&/, $keys)) { |
foreach my $msgid (@keys) { |
$msgid=&Apache::lonnet::unescape($msgid); |
|
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { |
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { |
my $plain= |
my $plain= |
&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid)); |
&Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid)); |
Line 2220 sub get_user_data {
|
Line 2236 sub get_user_data {
|
if ($self->{RETRIEVED_USER_DATA}) { return; } |
if ($self->{RETRIEVED_USER_DATA}) { return; } |
|
|
# Retrieve performance data on problems |
# Retrieve performance data on problems |
my %student_data = Apache::lonnet::currentdump($ENV{'request.course.id'}, |
my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, |
$ENV{'user.domain'}, |
$env{'user.domain'}, |
$ENV{'user.name'}); |
$env{'user.name'}); |
$self->{STUDENT_DATA} = \%student_data; |
$self->{STUDENT_DATA} = \%student_data; |
|
|
$self->{RETRIEVED_USER_DATA} = 1; |
$self->{RETRIEVED_USER_DATA} = 1; |
Line 2247 sub navhash {
|
Line 2263 sub navhash {
|
# Checks to see if coursemap is defined, matching test in old lonnavmaps |
# Checks to see if coursemap is defined, matching test in old lonnavmaps |
sub courseMapDefined { |
sub courseMapDefined { |
my $self = shift; |
my $self = shift; |
my $uri = &Apache::lonnet::clutter($ENV{'request.course.uri'}); |
my $uri = &Apache::lonnet::clutter($env{'request.course.uri'}); |
|
|
my $firstres = $self->navhash("map_start_$uri"); |
my $firstres = $self->navhash("map_start_$uri"); |
my $lastres = $self->navhash("map_finish_$uri"); |
my $lastres = $self->navhash("map_finish_$uri"); |
Line 2267 sub getIterator {
|
Line 2283 sub getIterator {
|
sub hasDiscussion { |
sub hasDiscussion { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
|
|
$self->generate_email_discuss_status(); |
$self->generate_email_discuss_status(); |
|
|
if (!defined($self->{DISCUSSION_TIME})) { return 0; } |
if (!defined($self->{DISCUSSION_TIME})) { return 0; } |
|
|
#return defined($self->{DISCUSSION_TIME}->{$symb}); |
#return defined($self->{DISCUSSION_TIME}->{$symb}); |
|
|
# backward compatibility (bulletin boards used to be 'wrapped') |
# backward compatibility (bulletin boards used to be 'wrapped') |
my $ressymb = $symb; |
my $ressymb = $self->wrap_symb($symb); |
if ($ressymb =~ m|adm/(\w+)/(\w+)/(\d+)/bulletinboard$|) { |
|
unless ($ressymb =~ m|adm/wrapper/adm|) { |
|
$ressymb = 'bulletin___'.$3.'___adm/wrapper/adm/'.$1.'/'.$2.'/'.$3.'/bulletinboard'; |
|
} |
|
} |
|
|
|
if ( defined ( $self->{LAST_READ}->{$ressymb} ) ) { |
if ( defined ( $self->{LAST_READ}->{$ressymb} ) ) { |
return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_READ}->{$ressymb}; |
return $self->{DISCUSSION_TIME}->{$ressymb} > $self->{LAST_READ}->{$ressymb}; |
} else { |
} else { |
Line 2290 sub hasDiscussion {
|
Line 2299 sub hasDiscussion {
|
} |
} |
} |
} |
|
|
|
sub wrap_symb { |
|
my $self = shift; |
|
my $symb = shift; |
|
if ($symb =~ m-___(adm/\w+/\w+/)(\d+)(/bulletinboard)$-) { |
|
unless ($symb =~ m|adm/wrapper/adm|) { |
|
$symb = 'bulletin___'.$2.'___adm/wrapper/'.$1.$2.$3; |
|
} |
|
} |
|
return $symb; |
|
} |
|
|
# Private method: Does the given resource (as a symb string) have |
# Private method: Does the given resource (as a symb string) have |
# current feedback? Returns the string in the feedback hash, which |
# current feedback? Returns the string in the feedback hash, which |
# will be false if it does not exist. |
# will be false if it does not exist. |
|
|
sub getFeedback { |
sub getFeedback { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
Line 2388 resource in the navmap.
|
Line 2409 resource in the navmap.
|
sub firstResource { |
sub firstResource { |
my $self = shift; |
my $self = shift; |
my $firstResource = $self->navhash('map_start_' . |
my $firstResource = $self->navhash('map_start_' . |
&Apache::lonnet::clutter($ENV{'request.course.uri'})); |
&Apache::lonnet::clutter($env{'request.course.uri'})); |
return $self->getById($firstResource); |
return $self->getById($firstResource); |
} |
} |
|
|
Line 2404 in the navmap.
|
Line 2425 in the navmap.
|
sub finishResource { |
sub finishResource { |
my $self = shift; |
my $self = shift; |
my $firstResource = $self->navhash('map_finish_' . |
my $firstResource = $self->navhash('map_finish_' . |
&Apache::lonnet::clutter($ENV{'request.course.uri'})); |
&Apache::lonnet::clutter($env{'request.course.uri'})); |
return $self->getById($firstResource); |
return $self->getById($firstResource); |
} |
} |
|
|
Line 2431 sub parmval_real {
|
Line 2452 sub parmval_real {
|
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
$self->generate_course_user_opt(); |
$self->generate_course_user_opt(); |
|
|
my $cid=$ENV{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
my $csec=$ENV{'request.course.sec'}; |
my $csec=$env{'request.course.sec'}; |
my $uname=$ENV{'user.name'}; |
my $uname=$env{'user.name'}; |
my $udom=$ENV{'user.domain'}; |
my $udom=$env{'user.domain'}; |
|
|
unless ($symb) { return ''; } |
unless ($symb) { return ''; } |
my $result=''; |
my $result=''; |
Line 2448 sub parmval_real {
|
Line 2469 sub parmval_real {
|
|
|
my $symbparm=$symb.'.'.$what; |
my $symbparm=$symb.'.'.$what; |
my $mapparm=$mapname.'___(all).'.$what; |
my $mapparm=$mapname.'___(all).'.$what; |
my $usercourseprefix=$uname.'_'.$udom.'_'.$cid; |
my $usercourseprefix=$cid; |
|
|
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
Line 2553 want to know is if I<any> resources matc
|
Line 2574 want to know is if I<any> resources matc
|
parameter will allow you to avoid potentially expensive enumeration of |
parameter will allow you to avoid potentially expensive enumeration of |
all matching resources. |
all matching resources. |
|
|
=item * B<hasResource>(map, filterFunc, recursive): |
=item * B<hasResource>(map, filterFunc, recursive, showall): |
|
|
Convience method for |
Convience method for |
|
|
scalar(retrieveResources($map, $filterFunc, $recursive, 1)) > 0 |
scalar(retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0 |
|
|
which will tell whether the map has resources matching the description |
which will tell whether the map has resources matching the description |
in the filter function. |
in the filter function. |
Line 2640 sub hasResource {
|
Line 2661 sub hasResource {
|
my $map = shift; |
my $map = shift; |
my $filterFunc = shift; |
my $filterFunc = shift; |
my $recursive = shift; |
my $recursive = shift; |
|
my $showall = shift; |
|
|
return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1)) > 0; |
return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0; |
} |
} |
|
|
1; |
1; |
|
|
package Apache::lonnavmaps::iterator; |
package Apache::lonnavmaps::iterator; |
use WeakRef; |
use WeakRef; |
|
use Apache::lonnet; |
|
|
=pod |
=pod |
|
|
=back |
=back |
Line 3127 sub populateStack {
|
Line 3151 sub populateStack {
|
|
|
package Apache::lonnavmaps::DFSiterator; |
package Apache::lonnavmaps::DFSiterator; |
use WeakRef; |
use WeakRef; |
|
use Apache::lonnet; |
|
|
# Not documented in the perldoc: This is a simple iterator that just walks |
# Not documented in the perldoc: This is a simple iterator that just walks |
# through the nav map and presents the resources in a depth-first search |
# through the nav map and presents the resources in a depth-first search |
# fashion, ignorant of conditionals, randomized resources, etc. It presents |
# fashion, ignorant of conditionals, randomized resources, etc. It presents |
Line 3504 sub shown_symb {
|
Line 3530 sub shown_symb {
|
if ($self->encrypted()) {return &Apache::lonenc::encrypted($self->symb());} |
if ($self->encrypted()) {return &Apache::lonenc::encrypted($self->symb());} |
return $self->symb(); |
return $self->symb(); |
} |
} |
|
sub id { |
|
my $self=shift; |
|
return $self->{ID}; |
|
} |
|
sub enclosing_map_src { |
|
my $self=shift; |
|
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; |
|
return $self->navHash('map_id_'.$first); |
|
} |
sub symb { |
sub symb { |
my $self=shift; |
my $self=shift; |
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; |
(my $first, my $second) = $self->{ID} =~ /(\d+).(\d+)/; |
Line 3512 sub symb {
|
Line 3547 sub symb {
|
. '___' . $second . '___' . $symbSrc; |
. '___' . $second . '___' . $symbSrc; |
return &Apache::lonnet::symbclean($symb); |
return &Apache::lonnet::symbclean($symb); |
} |
} |
|
sub wrap_symb { |
|
my $self = shift; |
|
return $self->{NAV_MAP}->wrap_symb($self->symb()); |
|
} |
sub title { |
sub title { |
my $self=shift; |
my $self=shift; |
if ($self->{ID} eq '0.0') { |
if ($self->{ID} eq '0.0') { |
# If this is the top-level map, return the title of the course |
# If this is the top-level map, return the title of the course |
# since this map can not be titled otherwise. |
# since this map can not be titled otherwise. |
return $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
return $env{'course.'.$env{'request.course.id'}.'.description'}; |
} |
} |
return $self->navHash("title_", 1); } |
return $self->navHash("title_", 1); } |
# considered private and undocumented |
# considered private and undocumented |
Line 3597 sub is_page {
|
Line 3636 sub is_page {
|
sub is_problem { |
sub is_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library)$/) |
return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) |
} |
} |
sub contains_problem { |
sub contains_problem { |
my $self=shift; |
my $self=shift; |
Line 3813 sub duedate {
|
Line 3852 sub duedate {
|
} |
} |
return $self->parmval("duedate", $part); |
return $self->parmval("duedate", $part); |
} |
} |
|
sub handgrade { |
|
(my $self, my $part) = @_; |
|
return $self->parmval("handgrade", $part); |
|
} |
sub maxtries { |
sub maxtries { |
(my $self, my $part) = @_; |
(my $self, my $part) = @_; |
return $self->parmval("maxtries", $part); |
return $self->parmval("maxtries", $part); |
Line 3851 sub weight {
|
Line 3894 sub weight {
|
my $self = shift; my $part = shift; |
my $self = shift; my $part = shift; |
if (!defined($part)) { $part = '0'; } |
if (!defined($part)) { $part = '0'; } |
return &Apache::lonnet::EXT('resource.'.$part.'.weight', |
return &Apache::lonnet::EXT('resource.'.$part.'.weight', |
$self->symb(), $ENV{'user.domain'}, |
$self->symb(), $env{'user.domain'}, |
$ENV{'user.name'}, |
$env{'user.name'}, |
$ENV{'request.course.sec'}); |
$env{'request.course.sec'}); |
} |
} |
sub part_display { |
sub part_display { |
my $self= shift(); my $partID = shift(); |
my $self= shift(); my $partID = shift(); |
Line 4097 sub extractParts {
|
Line 4140 sub extractParts {
|
return; |
return; |
} |
} |
foreach (split(/\,/,$metadata)) { |
foreach (split(/\,/,$metadata)) { |
if ($_ =~ /^part_(.*)$/) { |
if ($_ =~ /^(?:part|Task)_(.*)$/) { |
my $part = $1; |
my $part = $1; |
# This floods the logs if it blows up |
# This floods the logs if it blows up |
if (defined($parts{$part})) { |
if (defined($parts{$part})) { |
Line 4362 sub ATTEMPTED { return 16; }
|
Line 4405 sub ATTEMPTED { return 16; }
|
|
|
sub getCompletionStatus { |
sub getCompletionStatus { |
my $self = shift; |
my $self = shift; |
|
my $part = shift; |
return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE}); |
return $self->NETWORK_FAILURE if ($self->{NAV_MAP}->{NETWORK_FAILURE}); |
|
|
my $status = $self->queryRestoreHash('solved', shift); |
my $status = $self->queryRestoreHash('solved', $part); |
|
|
# Left as separate if statements in case we ever do more with this |
# Left as separate if statements in case we ever do more with this |
if ($status eq 'correct_by_student') {return $self->CORRECT;} |
if ($status eq 'correct_by_student') {return $self->CORRECT;} |
if ($status eq 'correct_by_scantron') {return $self->CORRECT;} |
if ($status eq 'correct_by_scantron') {return $self->CORRECT;} |
if ($status eq 'correct_by_override') {return $self->CORRECT_BY_OVERRIDE; } |
if ($status eq 'correct_by_override') { |
|
return $self->CORRECT_BY_OVERRIDE; |
|
} |
if ($status eq 'incorrect_attempted') {return $self->INCORRECT; } |
if ($status eq 'incorrect_attempted') {return $self->INCORRECT; } |
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; } |
if ($status eq 'incorrect_by_override') {return $self->INCORRECT_BY_OVERRIDE; } |
if ($status eq 'excused') {return $self->EXCUSED; } |
if ($status eq 'excused') {return $self->EXCUSED; } |
Line 4473 An answer has been submitted, but the st
|
Line 4519 An answer has been submitted, but the st
|
|
|
sub TRIES_LEFT { return 20; } |
sub TRIES_LEFT { return 20; } |
sub ANSWER_SUBMITTED { return 21; } |
sub ANSWER_SUBMITTED { return 21; } |
|
sub PARTIALLY_CORRECT{ return 22; } |
|
|
sub status { |
sub status { |
my $self = shift; |
my $self = shift; |
Line 4491 sub status {
|
Line 4538 sub status {
|
my $suppressFeedback = $self->problemstatus($part) eq 'no'; |
my $suppressFeedback = $self->problemstatus($part) eq 'no'; |
# If there's an answer date and we're past it, don't |
# If there's an answer date and we're past it, don't |
# suppress the feedback; student should know |
# suppress the feedback; student should know |
if ($self->answerdate($part) && $self->answerdate($part) < time()) { |
if ($self->duedate($part) && $self->duedate($part) < time() && |
|
$self->answerdate($part) && $self->answerdate($part) < time()) { |
$suppressFeedback = 0; |
$suppressFeedback = 0; |
} |
} |
|
|
# There are a few whole rows we can dispose of: |
# There are a few whole rows we can dispose of: |
if ($completionStatus == CORRECT || |
if ($completionStatus == CORRECT || |
$completionStatus == CORRECT_BY_OVERRIDE ) { |
$completionStatus == CORRECT_BY_OVERRIDE ) { |
return $suppressFeedback? ANSWER_SUBMITTED : CORRECT; |
if ( $suppressFeedback ) { return ANSWER_SUBMITTED } |
|
my $awarded=$self->awarded($part); |
|
if ($awarded < 1 && $awarded > 0) { |
|
return PARTIALLY_CORRECT; |
|
} elsif ($awarded<1) { |
|
return INCORRECT; |
|
} |
|
return CORRECT; |
} |
} |
|
|
if ($completionStatus == ATTEMPTED) { |
if ($completionStatus == ATTEMPTED) { |
Line 4585 my %compositeToSimple =
|
Line 4640 my %compositeToSimple =
|
NETWORK_FAILURE() => ERROR, |
NETWORK_FAILURE() => ERROR, |
NOTHING_SET() => CLOSED, |
NOTHING_SET() => CLOSED, |
CORRECT() => CORRECT, |
CORRECT() => CORRECT, |
|
PARTIALLY_CORRECT() => PARTIALLY_CORRECT, |
EXCUSED() => CORRECT, |
EXCUSED() => CORRECT, |
PAST_DUE_NO_ANSWER() => INCORRECT, |
PAST_DUE_NO_ANSWER() => INCORRECT, |
PAST_DUE_ANSWER_LATER() => INCORRECT, |
PAST_DUE_ANSWER_LATER() => INCORRECT, |