--- loncom/interface/lonnavmaps.pm 2002/09/30 16:45:01 1.56 +++ loncom/interface/lonnavmaps.pm 2002/10/29 20:17:39 1.91 @@ -1,7 +1,8 @@ + # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.56 2002/09/30 16:45:01 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.91 2002/10/29 20:17:39 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -44,8 +45,8 @@ use strict; use Apache::Constants qw(:common :http); use Apache::lonnet(); use Apache::loncommon(); -use HTML::TokeParser; use GDBM_File; +use POSIX qw (floor strftime); # -------------------------------------------------------------- Module Globals my %hash; @@ -124,32 +125,32 @@ sub parmval { my $courselevelm=$usercourseprefix.'.'.$mapparm; # ---------------------------------------------------------- first, check user - if ($uname) { - if ($useropt{$courselevelr}) { return $useropt{$courselevelr}; } - if ($useropt{$courselevelm}) { return $useropt{$courselevelm}; } - if ($useropt{$courselevel}) { return $useropt{$courselevel}; } + if (defined($uname)) { + if (defined($useropt{$courselevelr})) { return $useropt{$courselevelr}; } + if (defined($useropt{$courselevelm})) { return $useropt{$courselevelm}; } + if (defined($useropt{$courselevel})) { return $useropt{$courselevel}; } } # ------------------------------------------------------- second, check course - if ($csec) { - if ($courseopt{$seclevelr}) { return $courseopt{$seclevelr}; } - if ($courseopt{$seclevelm}) { return $courseopt{$seclevelm}; } - if ($courseopt{$seclevel}) { return $courseopt{$seclevel}; } + if (defined($csec)) { + if (defined($courseopt{$seclevelr})) { return $courseopt{$seclevelr}; } + if (defined($courseopt{$seclevelm})) { return $courseopt{$seclevelm}; } + if (defined($courseopt{$seclevel})) { return $courseopt{$seclevel}; } } - if ($courseopt{$courselevelr}) { return $courseopt{$courselevelr}; } - if ($courseopt{$courselevelm}) { return $courseopt{$courselevelm}; } - if ($courseopt{$courselevel}) { return $courseopt{$courselevel}; } + if (defined($courseopt{$courselevelr})) { return $courseopt{$courselevelr}; } + if (defined($courseopt{$courselevelm})) { return $courseopt{$courselevelm}; } + if (defined($courseopt{$courselevel})) { return $courseopt{$courselevel}; } # ----------------------------------------------------- third, check map parms my $thisparm=$parmhash{$symbparm}; - if ($thisparm) { return $thisparm; } + if (defined($thisparm)) { return $thisparm; } # ----------------------------------------------------- fourth , check default my $default=&Apache::lonnet::metadata($fn,$rwhat.'.default'); - if ($default) { return $default} + if (defined($default)) { return $default} # --------------------------------------------------- fifth , cascade up parts @@ -159,10 +160,10 @@ sub parmval { my ($part,$id)=split(/\_/,$space); if ($id) { my $partgeneral=&parmval($part.".$qualifier",$symb); - if ($partgeneral) { return $partgeneral; } + if (defined($partgeneral)) { return $partgeneral; } } else { my $resourcegeneral=&parmval("0.$qualifier",$symb); - if ($resourcegeneral) { return $resourcegeneral; } + if (defined($resourcegeneral)) { return $resourcegeneral; } } } return ''; @@ -819,13 +820,10 @@ sub new_handle { &Apache::loncommon::no_cache($r); $r->send_http_header; - # Header - $r->print(&Apache::loncommon::bodytag('Navigate Course Map','', - '')); # Initialize the nav map my $navmap = Apache::lonnavmaps::navmap->new( $ENV{"request.course.fn"}.".db", - $ENV{"request.course.fn"}."_parms.db", 1); + $ENV{"request.course.fn"}."_parms.db", 1, 1); if (!defined($navmap)) { @@ -834,6 +832,24 @@ sub new_handle { return HTTP_NOT_ACCEPTABLE; } + # Header + $r->print(&Apache::loncommon::bodytag('Navigate Course Map','', + '')); + $r->print(''); + my $desc=$ENV{'course.'.$ENV{'request.course.id'}.'.description'}; + if (defined($desc)) { $r->print("
');
+ } else {
+ $r->print(' Discussions'.
+ '
New message (click to open)
');
+ }
+
# Check that it's defined
if (!($navmap->courseMapDefined())) {
$r->print('Coursemap undefined.' .
@@ -848,16 +864,43 @@ sub new_handle {
# Defines a status->color mapping, null string means don't color
my %colormap =
( $res->NETWORK_FAILURE => '',
- $res->CORRECT => '#BBFFBB',
+ $res->CORRECT => '',
$res->EXCUSED => '#BBBBFF',
- $res->PAST_DUE_ANSWER_LATER => '#FFAA00',
- $res->PAST_DUE_NO_ANSWER => '#FFAA00',
- $res->ANSWER_OPEN => '#FF00AA',
+ $res->PAST_DUE_ANSWER_LATER => '',
+ $res->PAST_DUE_NO_ANSWER => '',
+ $res->ANSWER_OPEN => '#CCFFCC',
$res->OPEN_LATER => '',
- $res->TRIES_LEFT => '#FFFF00',
- $res->INCORRECT => '#FFAA00',
- $res->OPEN => '#FFFF88',
+ $res->TRIES_LEFT => '',
+ $res->INCORRECT => '',
+ $res->OPEN => '',
$res->NOTHING_SET => '' );
+ # 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
+ my $hurryUpColor = "#FF0000";
+
+ my %statusIconMap =
+ ( $res->NETWORK_FAILURE => '',
+ $res->NOTHING_SET => '',
+ $res->CORRECT => 'navmap.correct.gif',
+ $res->EXCUSED => 'navmap.correct.gif',
+ $res->PAST_DUE_NO_ANSWER => 'navmap.wrong.gif',
+ $res->PAST_DUE_ANSWER_LATER => 'navmap.wrong.gif',
+ $res->ANSWER_OPEN => 'navmap.wrong.gif',
+ $res->OPEN_LATER => '',
+ $res->TRIES_LEFT => 'navmap.open.gif',
+ $res->INCORRECT => 'navmap.wrong.gif',
+ $res->OPEN => 'navmap.open.gif',
+ $res->ATTEMPTED => 'navmap.open.gif' );
+
+ my %iconAltTags =
+ ( 'navmap.correct.gif' => 'Correct',
+ 'navmap.wrong.gif' => 'Incorrect',
+ 'navmap.open.gif' => 'Open' );
+
+ my %condenseStatuses =
+ ( $res->NETWORK_FAILURE => 1,
+ $res->NOTHING_SET => 1,
+ $res->CORRECT => 1 );
my %filterHash;
# Figure out what we're not displaying
@@ -867,19 +910,133 @@ sub new_handle {
}
}
+ # 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 $currenturl = $ENV{'form.postdata'};
+ $currenturl=~s/^http\:\/\///;
+ $currenturl=~s/^[^\/]+//;
+ # 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 $condition = 0;
+ if ($ENV{'form.condition'}) {
+ $condition = 1;
+ }
+
+ if ($condition) {
+ $r->print('Close All Folders
');
+ } else {
+ $r->print('Open All Folders
');
+ }
+
# Begin the HTML table
- # two columns: the title/icon on the left, the info on the right
- $r->print('
\n"); + if ($curRes->randomout()) { + $nonLinkedText .= ' (hidden) '; + } + + $rowNum++; + my $backgroundColor = $backgroundColors[$rowNum % scalar(@backgroundColors)]; + + # FIRST COL: The resource indentation, branch icon, name, and anchor + $r->print(" | |||||||
\n"); + + # anchor for current resource... - 5 is deliberate: If it's that + # high on the screen, don't bother focusing on it. Also this will + # print multiple anchors if this is an expanded multi-part problem... + # who cares? + if ($counter == $currentUrlIndex - 5) { + $r->print(''); + } # print indentation - for (my $i = 0; $i < $indentLevel; $i++) { + for (my $i = 0; $i < $indentLevel - $deltalevel + $deltadepth; $i++) { $r->print($indentString); } - $r->print(" ${newBranchText}${linkopen}${linkclose}\n"); + $r->print(" ${newBranchText}${linkopen}$icon${linkclose}\n"); - if ($curRes->is_problem() && $part != "0") { $partLabel = " (Part $part)"; } + my $curMarkerBegin = ""; + my $curMarkerEnd = ""; - $r->print(" $title$partLabel | ". - "\n"); + # Is this the current resource? + if ($curRes->src() eq $currenturl && !$displayedHereMarker) { + $curMarkerBegin = '> '; + $curMarkerEnd = ' <'; + $displayedHereMarker = 1; + } + + if ($curRes->is_problem() && $part ne "0" && !$condensed) { + $partLabel = " (Part $part)"; + $title = ""; + } + if ($multipart && $condensed) { + $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')); + } + + my $discussionHTML = ""; my $feedbackHTML = ""; + + # SECOND COL: Is there text, feedback, errors?? + if ($curRes->hasDiscussion()) { + $discussionHTML = $linkopen . + '' . + $linkclose; + } + + if ($curRes->getFeedback()) { + my $feedback = $curRes->getFeedback(); + foreach (split(/\,/, $feedback)) { + if ($_) { + $feedbackHTML .= ' ' + . ''; + } + } + } + + $r->print(" | $discussionHTML$feedbackHTML | "); + + # Is this the first displayed part of a multi-part problem + # that has not been condensed, so we should suppress these two + # columns? + my $firstDisplayed = !$condensed && $multipart && $part eq "0"; + + # THIRD COL: Problem status icon + if ($curRes->is_problem() && + !$firstDisplayed) { + my $icon = $statusIconMap{$curRes->status($part)}; + my $alt = $iconAltTags{$icon}; + if ($icon) { + $r->print("$linkopen$linkclose | \n"); + } else { + $r->print("\n"); + } + } else { # not problem, no icon + $r->print(" | \n"); + } + + # FOURTH COL: Text description + #$r->print(" | \n"); + $r->print(" | \n"); - if ($curRes->kind() eq "res" and - $curRes->is_problem() ) { + if ($curRes->kind() eq "res" && + $curRes->is_problem() && + !$firstDisplayed) { + $r->print ("") if ($color); $r->print (getDescription($curRes, $part)); + $r->print ("") if ($color); + } + if ($curRes->is_map() && advancedUser() && $curRes->randompick()) { + $r->print('(randomly select ' . $curRes->randompick() .')'); } + + $r->print(" |