--- loncom/interface/lonnavmaps.pm 2002/10/01 19:39:11 1.60 +++ loncom/interface/lonnavmaps.pm 2002/10/03 19:40:33 1.63 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.60 2002/10/01 19:39:11 bowersj2 Exp $ +# $Id: lonnavmaps.pm,v 1.63 2002/10/03 19:40:33 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -878,8 +878,7 @@ sub new_handle { my %condenseStatuses = ( $res->NETWORK_FAILURE => 1, $res->NOTHING_SET => 1, - $res->CORRECT => 1, - $res->OPEN => 1 ); + $res->CORRECT => 1 ); my %filterHash; # Figure out what we're not displaying @@ -889,15 +888,23 @@ sub new_handle { } } + my $currenturl = $ENV{'form.postdata'}; + $currenturl=~s/^http\:\/\///; + $currenturl=~s/^[^\/]+//; + my $queryAdd = "postdata=" . &Apache::lonnet::escape($currenturl); + + $r->print("$currenturl
"); + + # Begin the HTML table # four cols: resource + indent, chat+feedback, icon, text string $r->print('' ."\n"); - my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash); + my $mapIterator = $navmap->getIterator(undef, undef, \%filterHash, 0); my $curRes = $mapIterator->next(); undef $res; # so we don't accidentally use it later my $indentLevel = -1; - my $indentString = ""; + my $indentString = "\"\""; my $isNewBranch = 0; my $now = time(); @@ -919,13 +926,13 @@ sub new_handle { if (ref($curRes) && $curRes->src()) { # Step one: Decide which parts to show - my @parts; + my @parts = @{$curRes->parts()}; + my $multipart = scalar(@parts) > 1; + my $condensed = 0; + if ($curRes->is_problem()) { # Is it multipart? - @parts = @{$curRes->parts()}; - my $multipart = scalar(@parts) > 1; - if ($multipart) { # If it's multipart, see if part 0 is "open" # if it is, display all parts, if it isn't, @@ -935,7 +942,7 @@ sub new_handle { } else { # Otherwise, only display part 0 if we want to # attach feedback or email information to it - if (!$curRes->hasDiscussion() && !$curRes->getFeedback()) { + if ($curRes->hasDiscussion() || $curRes->getFeedback()) { shift @parts; } else { # If there's discussion or feedback, that counts @@ -943,20 +950,36 @@ sub new_handle { # Now, we decide whether to condense the # parts due to similarity - my $status = $curRes->status($parts[0]); - my $allSame = 1; - for (my $i = 1; $i < scalar(@parts); $i++) { + 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){ - $allSame = 0; + $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, then - # only display part 0. - if ($allSame && defined($condenseStatuses{$status})){ - @parts = ("0"); + # 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; } } } @@ -999,9 +1022,13 @@ sub new_handle { my $linkopen = ""; my $linkclose = ""; - my $icon = "html.gif"; + my $icon = "\"\""; if ($curRes->is_problem()) { - $icon = "problem.gif"; + if ($part eq "0" || $condensed) { + $icon = ''; + } else { + $icon = $indentString; + } } # Display the correct icon, link to open or shut map @@ -1009,12 +1036,13 @@ sub new_handle { my $mapId = $curRes->map_pc(); my $nowOpen = !defined($filterHash{$mapId}); $icon = $nowOpen ? - "folder_opened.gif" : "folder_closed.gif"; + "folder_closed.gif" : "folder_opened.gif"; + $icon = "\"\""; $linkopen = ""; + $linkopen .= "&$queryAdd\">"; $linkclose = ""; } @@ -1036,10 +1064,12 @@ sub new_handle { $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)"; } + if ($curRes->is_problem() && $part != "0" && !$condensed) { + $partLabel = " (Part $part)"; + $title = ""; + } $r->print(" $title$partLabel"); @@ -1066,9 +1096,15 @@ sub new_handle { $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()) { - my $icon = $statusIconMap{$curRes->status()}; + if ($curRes->is_problem() && + !$firstDisplayed) { + my $icon = $statusIconMap{$curRes->status($part)}; if ($icon) { $r->print("\n"); } else { @@ -1081,8 +1117,9 @@ sub new_handle { # FOURTH ROW: Text description $r->print("
$discussionHTML$feedbackHTML$linkopen$linkclose\n"); - if ($curRes->kind() eq "res" and - $curRes->is_problem() ) { + if ($curRes->kind() eq "res" && + $curRes->is_problem() && + !$firstDisplayed) { $r->print (getDescription($curRes, $part)); } @@ -1399,7 +1436,7 @@ sub courseMapDefined { sub getIterator { my $self = shift; my $iterator = Apache::lonnavmaps::iterator->new($self, shift, shift, - shift, shift); + shift, undef, shift); return $iterator; } @@ -1608,7 +1645,7 @@ getIterator behaves as follows: =over 4 -=item B(nav_map, firstResource, finishResource, filterHash): All parameters are optional. firstResource is a resource reference corresponding to where the iterator should start. It defaults to navmap->firstResource() for the corresponding nav map. finishResource corresponds to where you want the iterator to end, defaulting to navmap->finishResource(). It is your responsibility to ensure that the iterator will actually get there. filterHash is a hash used as a set containing strings representing the resource IDs, defaulting to empty. Condition is a 1 or 0 that sets what to do with the filter hash: If a 1, then only resource that exist IN the filterHash will be recursed on. If it is a 0, only resources NOT in the filterHash will be recursed on. Defaults to 0. +=item B(nav_map, firstResource, finishResource, filterHash, condition): All parameters are optional. firstResource is a resource reference corresponding to where the iterator should start. It defaults to navmap->firstResource() for the corresponding nav map. finishResource corresponds to where you want the iterator to end, defaulting to navmap->finishResource(). It is your responsibility to ensure that the iterator will actually get there. filterHash is a hash used as a set containing strings representing the resource IDs, defaulting to empty. Condition is a 1 or 0 that sets what to do with the filter hash: If a 0, then only resource that exist IN the filterHash will be recursed on. If it is a 1, only resources NOT in the filterHash will be recursed on. Defaults to 0, which is to say, do not recurse unless explicitly asked to. Thus, by default, all resources will be shown. Change the condition to a 1 without changing the hash, and only the top level of the map will be shown. Changing the condition to 1 and including some values in the hash will allow you to selectively examine parts of the navmap, while leaving it on 0 and adding things to the hash will allow you to selectively ignore parts of the nav map. See the handler code for examples. @@ -1660,6 +1697,7 @@ sub new { # A hash, used as a set, of resource already seen $self->{ALREADY_SEEN} = shift; if (!defined($self->{ALREADY_SEEN})) { $self->{ALREADY_SEEN} = {} }; + $self->{CONDITION} = shift; # Flag: Have we started yet? If not, the first action is to return BEGIN_MAP. $self->{STARTED} = 0; @@ -1830,7 +1868,7 @@ sub next { # If this is a map and we want to recurse down it... (not filtered out) if ($self->{HERE}->is_map() && - !defined($self->{FILTER}->{$self->{HERE}->map_pc()})) { + (defined($self->{FILTER}->{$self->{HERE}->map_pc()}) xor $self->{CONDITION})) { $self->{RECURSIVE_ITERATOR_FLAG} = 1; my $firstResource = $self->{HERE}->map_start(); my $finishResource = $self->{HERE}->map_finish(); @@ -1840,9 +1878,8 @@ sub next { # isn't MAIN::new, __PACKAGE__::new or Apache::lonnavmaps::iterator->new $self->{RECURSIVE_ITERATOR} = Apache::lonnavmaps::iterator->new ($self->{NAV_MAP}, $firstResource, - $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}); - # prime the new iterator with the first resource - #push @{$self->{RECURSIVE_ITERATOR}->{BRANCH_STACK}}, $firstResource; + $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}, + $self->{CONDITION}); } return $self->{HERE}; @@ -2509,9 +2546,12 @@ sub getNext { my $next = $choice->goesto(); $next = $self->{NAV_MAP}->getById($next); - # Don't remember it if we've already seen it + # 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); if (!defined($alreadySeenHash) || - !defined($alreadySeenHash->{$next->{ID}})) { + !defined($alreadySeenHash->{$next->{ID}}) || + ($browsePriv ne '2' && $browsePriv ne 'F')) { push @branches, $next; } }