--- loncom/interface/lonnavmaps.pm 2002/10/04 15:38:22 1.65 +++ loncom/interface/lonnavmaps.pm 2002/10/04 20:34:04 1.66 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.65 2002/10/04 15:38:22 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.66 2002/10/04 20:34:04 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -841,12 +841,12 @@ sub new_handle { $r->print("

$date

\n"); $r->rflush(); if ($navmap->{LAST_CHECK}) { - $r->print(' New discussion since '. - timeToHumanString($navmap->{LAST_CHECK}). - '
New message (click to open)

'); + $r->print(' New discussion since '. + timeToHumanString($navmap->{LAST_CHECK}). + '
New message (click to open)

'); } else { - $r->print(' Discussions'. - '
New message (click to open)

'); + $r->print(' Discussions'. + '
New message (click to open)

'); } #if (($currenturl=~/^\/res/) && # ($currenturl!~/^\/res\/adm/)) { @@ -882,22 +882,22 @@ sub new_handle { my $hurryUpColor = "#FFCCCC"; 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->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' ); my %condenseStatuses = - ( $res->NETWORK_FAILURE => 1, - $res->NOTHING_SET => 1, - $res->CORRECT => 1 ); + ( $res->NETWORK_FAILURE => 1, + $res->NOTHING_SET => 1, + $res->CORRECT => 1 ); my %filterHash; # Figure out what we're not displaying @@ -912,14 +912,18 @@ sub new_handle { $currenturl=~s/^[^\/]+//; my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl); - $r->print("$currenturl
"); - + $r->print('Show All Resources

'); # Begin the HTML table # four cols: resource + indent, chat+feedback, icon, text string $r->print('' ."\n"); - my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0); + my $condition = 0; + if ($ENV{'form.condition'}) { + $condition = 1; + } + + my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, $condition); my $curRes = $mapIterator->next(); undef $res; # so we don't accidentally use it later my $indentLevel = -1; @@ -944,65 +948,66 @@ sub new_handle { if (ref($curRes) && $curRes->src()) { - # Step one: Decide which parts to show - my @parts = @{$curRes->parts()}; - my $multipart = scalar(@parts) > 1; - my $condensed = 0; - + # Step one: Decide which parts to show + my @parts = @{$curRes->parts()}; + my $multipart = scalar(@parts) > 1; + my $condensed = 0; + if ($curRes->is_problem()) { - # Is it multipart? + # Is it multipart? - if ($multipart) { - # If it's multipart, see if part 0 is "open" - # if it is, display all parts, if it isn't, - # just display first - if (!$curRes->opendate("0")) { - @parts = ("0"); # just display the zero-th part - } else { - # Otherwise, only display part 0 if we want to - # attach feedback or email information to it - if ($curRes->hasDiscussion() || $curRes->getFeedback()) { - shift @parts; - } else { - # If there's discussion or feedback, that counts - # as a difference, so display the parts. - - # Now, we decide whether to condense the - # parts due to similarity - my $status = $curRes->status($parts[1]); - my $due = $curRes->duedate($parts[1]); - my $open = $curRes->opendate($parts[1]); - my $statusAllSame = 1; - my $dueAllSame = 1; - my $openAllSame = 1; - for (my $i = 2; $i < scalar(@parts); $i++) { - if ($curRes->status($parts[$i]) != $status){ - $statusAllSame = 0; - } - if ($curRes->duedate($parts[$i]) != $due ) { - $dueAllSame = 0; - } - if ($curRes->opendate($parts[$i]) != $open) { - $openAllSame = 0; - } - } - - # $allSame is true if all the statuses were - # the same. Now, if they are all the same and - # match one of the statuses to condense, or they - # are all open with the same due date, or they are - # all OPEN_LATER with the same open date, display the - # status of the first non-zero part (to get the 'correct' - # status right, since 0 is never 'correct' or 'open'). - if (($statusAllSame && defined($condenseStatuses{$status})) || - ($dueAllSame && $status == $curRes->OPEN && $statusAllSame)|| - ($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){ - @parts = ($parts[1]); - $condensed = 1; - } - } - } - } + if ($multipart) { + # If it's multipart, see if part 0 is "open" + # if it is, display all parts, if it isn't, + # just display first + if (!$curRes->opendate("0")) { + @parts = ("0"); # just display the zero-th part + $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; + } else { + # If there's discussion or feedback, that counts + # as a difference, so display the parts. + + # Now, we decide whether to condense the + # parts due to similarity + my $status = $curRes->status($parts[1]); + my $due = $curRes->duedate($parts[1]); + my $open = $curRes->opendate($parts[1]); + my $statusAllSame = 1; + my $dueAllSame = 1; + my $openAllSame = 1; + for (my $i = 2; $i < scalar(@parts); $i++) { + if ($curRes->status($parts[$i]) != $status){ + $statusAllSame = 0; + } + if ($curRes->duedate($parts[$i]) != $due ) { + $dueAllSame = 0; + } + if ($curRes->opendate($parts[$i]) != $open) { + $openAllSame = 0; + } + } + + # $allSame is true if all the statuses were + # the same. Now, if they are all the same and + # match one of the statuses to condense, or they + # are all open with the same due date, or they are + # all OPEN_LATER with the same open date, display the + # status of the first non-zero part (to get the 'correct' + # status right, since 0 is never 'correct' or 'open'). + if (($statusAllSame && defined($condenseStatuses{$status})) || + ($dueAllSame && $status == $curRes->OPEN && $statusAllSame)|| + ($openAllSame && $status == $curRes->OPEN_LATER && $statusAllSame) ){ + @parts = ($parts[1]); + $condensed = 1; + } + } + } + } } else { @parts[0] = "0"; # this is to get past foreach loop below @@ -1010,10 +1015,17 @@ sub new_handle { # with only one part without loss } - # Step two: Show the parts + # Display one part, in event of network error. + # If this is a single part, we can at least show the correct + # status, but if it's multipart, we're lost. + if ($curRes->{RESOURCE_ERROR}) { + @parts = ("0"); + } + + # Step two: Show the parts foreach my $part (@parts) { - my $deltalevel = 0; # for inserting the branch icon + my $deltalevel = 0; # for inserting the branch icon # For each thing we're displaying... @@ -1034,7 +1046,7 @@ sub new_handle { if ($isNewBranch) { $newBranchText = ""; $isNewBranch = 0; - $deltalevel = 1; + $deltalevel = 1; } # links to open and close the folders @@ -1043,11 +1055,11 @@ sub new_handle { my $icon = "\"\""; if ($curRes->is_problem()) { - if ($part eq "0" || $condensed) { - $icon = ''; - } else { - $icon = $indentString; - } + if ($part eq "0" || $condensed) { + $icon = ''; + } else { + $icon = $indentString; + } } # Display the correct icon, link to open or shut map @@ -1056,12 +1068,12 @@ sub new_handle { my $nowOpen = !defined($filterHash{$mapId}); $icon = $nowOpen ? "folder_closed.gif" : "folder_opened.gif"; - $icon = "\"\""; + $icon = "\"\""; $linkopen = ""; + $linkopen .= "&condition=$condition&$queryAdd\">"; $linkclose = ""; } @@ -1075,8 +1087,8 @@ sub new_handle { } } - # FIRST ROW: The resource indentation, branch icon, and name - $r->print(" "); - - my $discussionHTML = ""; my $feedbackHTML = ""; - - # SECOND ROW: Is there text or feedback? - if ($curRes->hasDiscussion()) { - $discussionHTML = $linkopen . - '' . - $linkclose; - } - - if ($curRes->getFeedback()) { - my $feedback = $curRes->getFeedback(); - foreach (split(/\,/, $feedback)) { - if ($_) { - $feedbackHTML .= ' ' - . ''; - } - } - } - - $r->print(""); - - # 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 ROW: Problem status icon - if ($curRes->is_problem() && - !$firstDisplayed) { - my $icon = $statusIconMap{$curRes->status($part)}; - if ($icon) { - $r->print("\n"); - } else { - $r->print("\n"); - } - } else { # not problem, no icon - $r->print("\n"); - } + $partLabel = " (Part $part)"; + $title = ""; + } + if ($multipart && $condensed) { + $nonLinkedText = ' (' . $curRes->countParts() . ' parts)'; + } - # FOURTH ROW: Text description - $r->print(""); + + # 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 ROW: Problem status icon + if ($curRes->is_problem() && + !$firstDisplayed) { + my $icon = $statusIconMap{$curRes->status($part)}; + if ($icon) { + $r->print("\n"); + } else { + $r->print("\n"); + } + } else { # not problem, no icon + $r->print("\n"); + } + + # FOURTH ROW: Text description + $r->print("\n"); + $r->print("\n"); } } $curRes = $mapIterator->next(); @@ -1220,11 +1242,11 @@ sub getDescription { return "Opens: " . timeToHumanString($res->opendate($part)); } if ($status == $res->OPEN) { - if ($res->duedate()) { - return "Due: $status " . timeToHumanString($res->duedate($part)); - } else { - return "Open, no due date"; - } + if ($res->duedate()) { + return "Due: $status " . timeToHumanString($res->duedate($part)); + } else { + return "Open, no due date"; + } } if ($status == $res->PAST_DUE_ANSWER_LATER) { return "Answer opens: " . timeToHumanString($res->answerdate($part)); @@ -1236,18 +1258,18 @@ sub getDescription { return "Answer available"; } if ($status == $res->EXCUSED) { - return "Excused by instructor"; + return "Excused by instructor"; } if ($status == $res->TRIES_LEFT) { - my $tries = $res->tries(); - my $maxtries = $res->maxtries(); - my $triesString = "($tries of $maxtries tries used)"; - if ($res->duedate()) { - return "Due: $status " . timeToHumanString($res->duedate($part)) . - " $triesString"; - } else { - return "No due date $triesString"; - } + my $tries = $res->tries(); + my $maxtries = $res->maxtries(); + my $triesString = "($tries of $maxtries tries used)"; + if ($res->duedate()) { + return "Due: $status " . timeToHumanString($res->duedate($part)) . + " $triesString"; + } else { + return "No due date $triesString"; + } } } @@ -1258,9 +1280,9 @@ sub timeToHumanString { my ($time) = @_; # zero, '0' and blank are bad times if ($time) { - return localtime($time); + return localtime($time); } else { - return 'Never'; + return 'Never'; } } @@ -1328,7 +1350,7 @@ sub new { if (!(tie(%parmhash, 'GDBM_File', $self->{PARM_HASH_FILE}, &GDBM_READER(), 0640))) { - untie $self->{PARM_HASH}; + untie $self->{PARM_HASH}; return undef; } $self->{PARM_HASH} = \%parmhash; @@ -1481,7 +1503,7 @@ sub hasDiscussion { if (!defined($self->{DISCUSSION_TIME})) { return 0; } return $self->{DISCUSSION_TIME}->{$symb} > - $self->{LAST_CHECK}; + $self->{LAST_CHECK}; } # Private function: Does the given resource (as a symb string) have @@ -1898,7 +1920,7 @@ sub next { $self->{RECURSIVE_ITERATOR} = Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}, - $self->{CONDITION}); + $self->{CONDITION}); } return $self->{HERE}; @@ -1971,6 +1993,7 @@ sub new { # Store this new resource in the parent nav map's cache. $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; + $self->{RESOURCE_ERROR} = 0; # A hash that can be used by two-pass algorithms to store data # about this resource in. Not used by the resource object @@ -2271,8 +2294,12 @@ sub countParts { my $self = shift; my $parts = $self->parts(); - - if (scalar(@{$parts}) == 1) { return 1;} + + if ($self->{RESOURCE_ERROR}) { + return 0; + } + + if (scalar(@{$parts}) < 2) { return 1;} return scalar(@{$parts}) - 1; } @@ -2286,12 +2313,19 @@ sub extractParts { $self->{PARTS} = []; # Retrieve part count - foreach (split(/\,/,&Apache::lonnet::metadata($self->src(), - 'allpossiblekeys'))) { + my $metadata = &Apache::lonnet::metadata($self->src(), 'allpossiblekeys'); + if (!$metadata) { + $self->{RESOURCE_ERROR} = 1; + $self->{PARTS} = []; + return; + } + + foreach (split(/\,/,$metadata)) { if ($_ =~ /^parameter\_(.*)\_opendate$/) { push @{$self->{PARTS}}, $1; } } + # Is this possible to do in one line? - Jeremy my @sortedParts = sort @{$self->{PARTS}}; @@ -2566,11 +2600,11 @@ sub getNext { $next = $self->{NAV_MAP}->getById($next); # Don't remember it if we've already seen it or if - # the student doesn't have browse priviledges - my $browsePriv = &Apache::lonnet::allowed('bre', $self->src); + # the student doesn't have browse priviledges + my $browsePriv = &Apache::lonnet::allowed('bre', $self->src); if (!defined($alreadySeenHash) || !defined($alreadySeenHash->{$next->{ID}}) || - ($browsePriv ne '2' && $browsePriv ne 'F')) { + ($browsePriv ne '2' && $browsePriv ne 'F')) { push @branches, $next; } }
\n"); + # FIRST COL: The resource indentation, branch icon, and name + $r->print("
\n"); # print indentation for (my $i = 0; $i < $indentLevel - $deltalevel; $i++) { @@ -1085,64 +1097,74 @@ sub new_handle { $r->print(" ${newBranchText}${linkopen}$icon${linkclose}\n"); + my $nonLinkedText = ""; + if ($curRes->is_problem() && $part != "0" && !$condensed) { - $partLabel = " (Part $part)"; - $title = ""; - } - - $r->print(" $title$partLabel$discussionHTML$feedbackHTML$linkopen$linkclose\n"); + $r->print(" $title$partLabel $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 or feedback? + if ($curRes->hasDiscussion()) { + $discussionHTML = $linkopen . + '' . + $linkclose; + } + + if ($curRes->getFeedback()) { + my $feedback = $curRes->getFeedback(); + foreach (split(/\,/, $feedback)) { + if ($_) { + $feedbackHTML .= ' ' + . ''; + } + } + } + + $r->print("$discussionHTML$feedbackHTML$linkopen$linkclose\n"); if ($curRes->kind() eq "res" && $curRes->is_problem() && - !$firstDisplayed) { + !$firstDisplayed) { $r->print (getDescription($curRes, $part)); } - $r->print("