--- loncom/interface/lonnavmaps.pm 2002/11/18 21:12:39 1.114
+++ loncom/interface/lonnavmaps.pm 2003/03/20 22:30:38 1.129.2.3
@@ -2,7 +2,7 @@
# The LearningOnline Network with CAPA
# Navigate Maps Handler
#
-# $Id: lonnavmaps.pm,v 1.114 2002/11/18 21:12:39 bowersj2 Exp $
+# $Id: lonnavmaps.pm,v 1.129.2.3 2003/03/20 22:30:38 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -48,6 +48,11 @@ use POSIX qw (floor strftime);
sub handler {
my $r = shift;
+ real_handler($r);
+}
+
+sub real_handler {
+ my $r = shift;
&Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
@@ -84,13 +89,18 @@ sub handler {
}
$r->print("
\n");
- $r->print("Navigate Course Contents");
+ $r->print("Navigate Course Contents");
# Header
$r->print(&Apache::loncommon::bodytag('Navigate Course Contents','',
''));
$r->print('');
+ $r->rflush();
+
+ # Now that we've displayed some stuff to the user, init the navmap
+ $navmap->init();
+
$r->print('');
my $date=localtime;
$r->print('Key: | ');
@@ -116,30 +126,63 @@ sub handler {
$condition = 1;
}
- my $currenturl = $ENV{'form.postdata'};
- $currenturl=~s/^http\:\/\///;
- $currenturl=~s/^[^\/]+//;
+ # Determine where the "here" marker is and where the screen jumps to.
+ my $SYMB = 1; my $URL = 2; my $NOTHING = 3; # symbolic constants
+ my $hereType; # the type of marker, $SYMB, $URL, or $NOTHING
+ my $here; # the actual URL or SYMB for the here marker
+ my $jumpType; # The type of the thing we have a jump for, $SYMB or $URL
+ my $jump; # the SYMB/URL of the resource we need to jump to
+
+ if ( $ENV{'form.alreadyHere'} ) { # 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"
+ # from the querystring, and get the new "jump" marker
+ $hereType = $ENV{'form.hereType'};
+ $here = $ENV{'form.here'};
+ $jumpType = $ENV{'form.jumpType'} || $NOTHING;
+ $jump = $ENV{'form.jump'};
+ } else { # the user is visiting the nav map from the remote
+ # We're coming from the remote. We have either a url, a symb, or nothing,
+ # and we need to figure out what.
+ # Preference: Symb
+
+ if ($ENV{'form.symb'}) {
+ $hereType = $jumpType = $SYMB;
+ $here = $jump = $ENV{'form.symb'};
+ } elsif ($ENV{'form.postdata'}) {
+ # couldn't find a symb, is there a URL?
+ my $currenturl = $ENV{'form.postdata'};
+ $currenturl=~s/^http\:\/\///;
+ $currenturl=~s/^[^\/]+//;
+ $hereType = $jumpType = $URL;
+ $here = $jump = $currenturl;
+ } else {
+ # Nothing
+ $hereType = $jumpType = $NOTHING;
+ }
+ }
+
+
# alreadyHere allows us to only open the maps necessary to view
# the current location once, while at the same time remembering
# the current location. Without that check, the user would never
# be able to close those maps; the user would close it, and the
# currenturl scan would re-open it.
- my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl) .
- "&alreadyHere=1";
+ my $queryAdd = "&alreadyHere=1";
if ($condition) {
- $r->print("Close All Folders");
+ $r->print("Close All Folders");
} else {
- $r->print("Open All Folders");
+ $r->print("Open All Folders");
}
$r->print('
');
$r->rflush();
- # Now that we've displayed some stuff to the user, init the navmap
- $navmap->init();
-
# Check that it's defined
if (!($navmap->courseMapDefined())) {
$r->print('Coursemap undefined.' .
@@ -171,6 +214,8 @@ sub handler {
# is not yet done and due in less then 24 hours
my $hurryUpColor = "#FF0000";
+ # Keep these mappings in sync with lonquickgrades, which uses the colors
+ # instead of the icons.
my %statusIconMap =
( $res->NETWORK_FAILURE => '',
$res->NOTHING_SET => '',
@@ -206,8 +251,6 @@ sub handler {
# Is this a new-style course? If so, we want to suppress showing the top-level
# maps in their own folders, in favor of "inlining" them.
my $topResource = $navmap->getById("0.0");
- my $inlineTopLevelMaps = $topResource->src() =~ m|^/uploaded/.*default\.sequence$|;
- my $inlinedelta = $inlineTopLevelMaps? -1 : 0;
# Begin the HTML table
# four cols: resource + indent, chat+feedback, icon, text string
@@ -219,35 +262,31 @@ sub handler {
# Here's a simple example of the iterator.
# Preprocess the map: Look for current URL, force inlined maps to display
- my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 1);
+ my $mapIterator = $navmap->getIterator(undef, undef, undef, 1);
my $found = 0;
my $depth = 1;
- my $currentUrlIndex = 0; # keeps track of when the current resource is found,
+ my $currentJumpIndex = 0; # keeps track of when the current resource is found,
# so we can back up a few and put the anchor above the
# current resource
- my $currentUrlDelta = 5; # change this to change how many resources are displayed
+ my $currentJumpDelta = 2; # change this to change how many resources are displayed
# before the current resource when using #current
$mapIterator->next(); # discard the first BEGIN_MAP
my $curRes = $mapIterator->next();
my $counter = 0;
-
- while ($depth > 0) {
+ my $foundJump = ($jumpType == $NOTHING); # look for jump point if we have one
+ my $looped = 0;
+
+ # We only need to do this if we need to open the maps to show the
+ # current position. This will change the counter so we can't count
+ # for the jump marker with this loop.
+ while ($depth > 0 && !$ENV{'form.alreadyHere'}) {
if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; }
if ($curRes == $mapIterator->END_MAP()) { $depth--; }
- if (ref($curRes)) { $counter++; }
-
- my $mapStack = $mapIterator->getStack();
- if ($currenturl && !$ENV{'form.alreadyHere'} && ref($curRes) &&
- $curRes->src() eq $currenturl) {
- # If this is the correct resource, be sure to
- # show it by making sure the containing maps
- # are open.
-
- # This is why we have to use the main iterator instead of the
- # potentially faster DFS: The count has to be the same, so
- # the order has to be the same, which DFS won't give us.
- $currentUrlIndex = $counter;
+ if (ref($curRes) && !$ENV{'form.alreadyHere'} &&
+ ($hereType == $SYMB && $curRes->symb() eq $here) ||
+ (ref($curRes) && $hereType == $URL && $curRes->src() eq $here)) {
+ my $mapStack = $mapIterator->getStack();
# Ensure the parent maps are open
for my $map (@{$mapStack}) {
@@ -259,16 +298,33 @@ sub handler {
}
$ENV{'form.alreadyHere'} = 1;
}
-
- # Preprocessing: If we're inlining nav maps into the top-level display,
- # make sure we show this map!
- if ($inlineTopLevelMaps && ref($curRes) && $curRes->is_map &&
- scalar(@{$mapStack}) == 1) {
- if ($condition) {
- undef $filterHash{$curRes->map_pc()};
- } else {
- $filterHash{$curRes->map_pc()} = 1;
- }
+ $looped = 1;
+
+ $curRes = $mapIterator->next();
+ }
+
+ $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0);
+ $depth = 1;
+ $mapIterator->next();
+ $curRes = $mapIterator->next();
+
+ while ($depth > 0 && !$foundJump) {
+ if ($curRes == $mapIterator->BEGIN_MAP()) { $depth++; }
+ if ($curRes == $mapIterator->END_MAP()) { $depth--; }
+ if (ref($curRes)) { $counter++; }
+
+ if (ref($curRes) &&
+ (($jumpType == $SYMB && $curRes->symb() eq $jump) ||
+ ($jumpType == $URL && $curRes->src() eq $jump))) {
+ # If this is the correct resource, be sure to
+ # show it by making sure the containing maps
+ # are open.
+
+ # This is why we have to use the main iterator instead of the
+ # potentially faster DFS: The count has to be the same, so
+ # the order has to be the same, which DFS won't give us.
+ $currentJumpIndex = $counter;
+ $foundJump = 1;
}
$curRes = $mapIterator->next();
@@ -282,6 +338,7 @@ sub handler {
my $now = time();
my $in24Hours = $now + 24 * 60 * 60;
my $displayedHereMarker = 0;
+ my $displayedJumpMarker = 0;
# We know the first thing is a BEGIN_MAP (see "$self->{STARTED}"
# code in iterator->next), so ignore the first one
@@ -296,11 +353,6 @@ sub handler {
$counter = 0;
- # Print the 'current' anchor here if it would fall off the top
- if ($currentUrlIndex - $currentUrlDelta < 0) {
- $r->print('');
- }
-
while ($depth > 0) {
if ($curRes == $mapIterator->BEGIN_MAP() ||
$curRes == $mapIterator->BEGIN_BRANCH()) {
@@ -325,11 +377,11 @@ sub handler {
next; # if yes, then just ignore this resource
}
- if (ref($curRes) && $curRes->src()) {
+ if (ref($curRes)) {
my $deltalevel = $isNewBranch? 1 : 0; # reserves space for branch icon
- if ($indentLevel - $deltalevel + $inlinedelta < 0) {
+ if ($indentLevel - $deltalevel < 0) {
# If this would be at a negative depth (top-level maps in
# new-style courses, we want to suppress their title display)
# then ignore it.
@@ -351,13 +403,13 @@ sub handler {
# just display first
if (!$curRes->opendate("0")) {
# no parts are open, display as one part
- @parts = ("0");
+ @parts = ();
$condensed = 1;
} else {
# Otherwise, only display part 0 if we want to
# attach feedback or email information to it
if ($curRes->hasDiscussion() || $curRes->getFeedback()) {
- shift @parts;
+ #shift @parts;
} else {
# Now, we decide whether to condense the
# parts due to similarity
@@ -389,23 +441,19 @@ sub handler {
if (($statusAllSame && defined($condenseStatuses{$status})) ||
($dueAllSame && $status == $curRes->OPEN && $statusAllSame)||
($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){
- @parts = ($parts[1]);
+ @parts = ();
$condensed = 1;
}
}
}
}
- } else {
- $parts[0] = "0"; # this is to get past foreach loop below
- # you can consider a non-problem resource as a resource
- # with only one part without loss, and it simplifies the looping
}
# Is it a multipart problem with a single part, now in
# @parts with "0" filtered out? If so, 'forget' it's a multi-part
# problem and treat it like a single-part problem.
- if ( scalar(@parts) == 1 ) {
+ if ( scalar(@parts) == 0 ) {
$multipart = 0;
}
@@ -414,13 +462,16 @@ sub handler {
# status, but if it's multipart, we're lost, since we can't
# retreive the metadata to count the parts
if ($curRes->{RESOURCE_ERROR}) {
- @parts = ("0");
+ @parts = ();
}
# Step Two: Print the actual data.
# For each part we intend to display...
- foreach my $part (@parts) {
+ foreach my $part ('', @parts) {
+ if ($part eq '0') {
+ next;
+ }
my $nonLinkedText = ""; # unlinked stuff after title
@@ -436,6 +487,10 @@ sub handler {
'"';
my $title = $curRes->compTitle();
+ if ($src=~/^\/uploaded\//) {
+ $nonLinkedText=$title;
+ $title='';
+ }
my $partLabel = "";
my $newBranchText = "";
@@ -451,7 +506,7 @@ sub handler {
my $icon = "";
if ($curRes->is_problem()) {
- if ($part eq "0" || $condensed) {
+ if ($part eq "" || $condensed) {
$icon = '';
} else {
$icon = $indentString;
@@ -470,7 +525,10 @@ sub handler {
$linkopen .= ($nowOpen xor $condition) ?
addToFilter(\%filterHash, $mapId) :
removeFromFilter(\%filterHash, $mapId);
- $linkopen .= "&condition=$condition&$queryAdd\">";
+ $linkopen .= "&condition=$condition&$queryAdd" .
+ "&hereType=$hereType&here=" .
+ Apache::lonnet::escape($here) . "&jumpType=$SYMB&" .
+ "jump=" . Apache::lonnet::escape($curRes->symb()) ."\">";
$linkclose = "";
}
@@ -478,27 +536,13 @@ sub handler {
my $colorizer = "";
my $color;
if ($curRes->is_problem()) {
- my $status = $curRes->status($part);
- $color = $colormap{$status};
+ $color = $colormap{$curRes->status};
- # Special case in the navmaps: If in less then
- # 24 hours, give it a bit of urgency
- if (($status == $curRes->OPEN() || $status == $curRes->ATTEMPTED() ||
- $status == $curRes->TRIES_LEFT())
- && $curRes->duedate() &&
- $curRes->duedate() < time()+(24*60*60) &&
- $curRes->duedate() > time()) {
- $color = $hurryUpColor;
- }
- # Special case: If this is the last try, and there is
- # more then one available, and it's not due yet, give a bit of urgency
- my $tries = $curRes->tries($part);
- my $maxtries = $curRes->maxtries($part);
- if ($tries && $maxtries && $maxtries > 1 &&
- $maxtries - $tries == 1 && $curRes->duedate() &&
- $curRes->duedate() > time()) {
+ if (dueInLessThen24Hours($curRes, $part) ||
+ lastTry($curRes, $part)) {
$color = $hurryUpColor;
}
+
if ($color ne "") {
$colorizer = "bgcolor=\"$color\"";
}
@@ -512,15 +556,16 @@ sub handler {
my $backgroundColor = $backgroundColors[$rowNum % scalar(@backgroundColors)];
# FIRST COL: The resource indentation, branch icon, name, and anchor
- $r->print("
\n");
+ $r->print(" |
\n");
# Print the anchor if necessary
- if ($counter == $currentUrlIndex - $currentUrlDelta) {
- $r->print('');
+ if ($counter == $currentJumpIndex - $currentJumpDelta ) {
+ $r->print('');
+ $displayedJumpMarker = 1;
}
# print indentation
- for (my $i = 0; $i < $indentLevel - $deltalevel + $inlinedelta; $i++) {
+ for (my $i = 0; $i < $indentLevel - $deltalevel; $i++) {
$r->print($indentString);
}
@@ -530,31 +575,33 @@ sub handler {
my $curMarkerEnd = "";
# Is this the current resource?
- if ($curRes->src() eq $currenturl && !$displayedHereMarker) {
- $curMarkerBegin = '> ';
+ if (!$displayedHereMarker &&
+ (($hereType == $SYMB && $curRes->symb eq $here) ||
+ ($hereType == $URL && $curRes->src eq $here))) {
+ $curMarkerBegin = '> ';
$curMarkerEnd = ' <';
$displayedHereMarker = 1;
}
- if ($curRes->is_problem() && $part ne "0" && !$condensed) {
+ if ($curRes->is_problem() && $part ne "" && !$condensed) {
$partLabel = " (Part $part)";
$title = "";
}
- if ($multipart && $condensed) {
+ if ($condensed && $curRes->countParts() > 1) {
$nonLinkedText .= ' (' . $curRes->countParts() . ' parts)';
}
$r->print(" $curMarkerBegin$title$partLabel $curMarkerEnd $nonLinkedText");
- if ($curRes->{RESOURCE_ERROR}) {
- $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",
- 'Host down'));
- }
+ #if ($curRes->{RESOURCE_ERROR}) {
+ # $r->print(&Apache::loncommon::help_open_topic ("Navmap_Host_Down",
+ # 'Host down'));
+ # }
$r->print(" | \n");
# SECOND COL: Is there text, feedback, errors??
- my $discussionHTML = ""; my $feedbackHTML = "";
+ my $discussionHTML = ""; my $feedbackHTML = ""; my $errorHTML = "";
if ($curRes->hasDiscussion()) {
$discussionHTML = $linkopen .
@@ -574,7 +621,19 @@ sub handler {
}
}
- $r->print("$discussionHTML$feedbackHTML | ");
+ if ($curRes->getErrors()) {
+ my $errors = $curRes->getErrors();
+ foreach (split(/,/, $errors)) {
+ if ($_) {
+ $errorHTML .= ' '
+ . '';
+ }
+ }
+ }
+
+ $r->print("$discussionHTML$feedbackHTML$errorHTML | ");
# Is this the first displayed part of a multi-part problem
# that has not been condensed, so we should suppress these two
@@ -619,10 +678,17 @@ sub handler {
$curRes = $mapIterator->next();
}
- $r->print("