--- loncom/interface/lonnavmaps.pm 2006/04/20 04:30:11 1.378 +++ loncom/interface/lonnavmaps.pm 2006/10/23 22:48:27 1.392 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.378 2006/04/20 04:30:11 albertel Exp $ +# $Id: lonnavmaps.pm,v 1.392 2006/10/23 22:48:27 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -31,15 +31,15 @@ package Apache::lonnavmaps; use strict; use GDBM_File; -use Apache::Constants qw(:common :http); use Apache::loncommon(); -use Apache::lonmenu(); use Apache::lonenc(); use Apache::lonlocal; use Apache::lonnet; use POSIX qw (floor strftime); use Data::Dumper; # for debugging, not always use Time::HiRes qw( gettimeofday tv_interval ); +use lib '/home/httpd/lib/perl/'; +use LONCAPA; # symbolic constants sub SYMB { return 1; } @@ -89,34 +89,6 @@ my %colormap = # is not yet done and due in less then 24 hours my $hurryUpColor = "#FF0000"; -sub launch_win { - my ($mode,$script,$toplinkitems,$firsttime)=@_; - my $result; - if ($script ne 'no') { - $result.=''; - } - if ($mode eq 'link') { - &add_linkitem($toplinkitems,'launchnav','launch_navmapwin()', - "Launch navigation window"); - } - return $result; -} - sub close { if ($env{'environment.remotenavmap'} ne 'on') { return ''; } return(<header_only) { - if ($env{'browser.mathml'}) { - &Apache::loncommon::content_type($r,'text/xml'); - } else { - &Apache::loncommon::content_type($r,'text/html'); - } - $r->send_http_header; - return OK; - } - - # Send header, don't cache this page - if ($env{'browser.mathml'}) { - &Apache::loncommon::content_type($r,'text/xml'); - } else { - &Apache::loncommon::content_type($r,'text/html'); - } - &Apache::loncommon::no_cache($r); - - my %toplinkitems=(); - &add_linkitem(\%toplinkitems,'blank','',"Select Action"); - if ($ENV{QUERY_STRING} eq 'collapseExternal') { - &Apache::lonnet::put('environment',{'remotenavmap' => 'off'}); - &Apache::lonnet::appenv('environment.remotenavmap' => 'off'); - my $menu=&Apache::lonmenu::reopenmenu(); - my $navstatus=&Apache::lonmenu::get_nav_status(); - if ($menu) { - $menu=(<send_http_header; - my $js =<<"ENDSUBM"; - -ENDSUBM - $r->print(&Apache::loncommon::start_page(undef,$js, - {'only_body' => 1, - 'bgcolor' => '#FFFFFF', - 'add_entries' => - {'onload' => - "submitthis()"}}). - &Apache::loncommon::end_page()); - - return OK; - } - if ($ENV{QUERY_STRING} =~ /^launchExternal/) { - &Apache::lonnet::put('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(< - swmenu=$menu - swmenu.clearTimeout(swmenu.menucltim); - $navstatus - -MENU - } - } - if ($ENV{QUERY_STRING} eq 'turningOffExternal') { - $env{'environment.remotenavmap'}='off'; - } - - # Create the nav map - my $navmap = Apache::lonnavmaps::navmap->new(); - - if (!defined($navmap)) { - my $requrl = $r->uri; - $env{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; - return HTTP_NOT_ACCEPTABLE; - } - $r->send_http_header; - -# ------------------------------------------------------------ Get query string - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); - -# ----------------------------------------------------- Force menu registration - my $body_only=''; - my $js; - if ($env{'environment.remotenavmap'} eq 'on') { - $js=''; - $body_only=1; - } - - # Header - $r->print(&Apache::loncommon::start_page('Navigate Course Contents',$js, - {'only_body' => $body_only, - 'force_register' => - $env{'form.register'},})); - $r->print(''); - - $r->rflush(); - - # Check that it's defined - if (!($navmap->courseMapDefined())) { - $r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT')); - $r->print(''.&mt('Coursemap undefined.'). - '' . - &Apache::loncommon::end_page()); - return OK; - } - - # See if there's only one map in the top-level, if we don't - # already have a filter... if so, automatically display it - # (older code; should use retrieveResources) - if ($ENV{QUERY_STRING} !~ /filter/) { - my $iterator = $navmap->getIterator(undef, undef, undef, 0); - my $curRes; - my $sequenceCount = 0; - my $sequenceId; - while ($curRes = $iterator->next()) { - if (ref($curRes) && $curRes->is_sequence()) { - $sequenceCount++; - $sequenceId = $curRes->map_pc(); - } - } - - if ($sequenceCount == 1) { - # The automatic iterator creation in the render call - # will pick this up. We know the condition because - # the defined($env{'form.filter'}) also ensures this - # is a fresh call. - $env{'form.filter'} = "$sequenceId"; - } - } - - if ($ENV{QUERY_STRING} eq 'launchExternal') { - $r->print(' -
-
'); - $r->print(' - '); - } - - if ($env{'environment.remotenavmap'} ne 'on') { - $r->print(&launch_win('link','yes',\%toplinkitems)); - } - if ($env{'environment.remotenavmap'} eq 'on') { - &add_linkitem(\%toplinkitems,'closenav','collapse()', - "Close navigation window"); - } - - - # Check to see if the student is jumping to next open, do-able problem - if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) { - # Find the next homework problem that they can do. - my $iterator = $navmap->getIterator(undef, undef, undef, 1); - my $curRes; - my $foundDoableProblem = 0; - my $minimumduedate; - - while ($curRes = $iterator->next()) { - if (ref($curRes) && $curRes->is_problem()) { - my $status = $curRes->status(); - if ($curRes->completable()) { - my $thisduedate=$curRes->duedate(); - unless ($foundDoableProblem) { - $minimumduedate=$thisduedate; - } - - $foundDoableProblem = 1; - - if ($thisduedate<=$minimumduedate) { - # Pop open all previous maps - my $stack = $iterator->getStack(); - pop @$stack; # last resource in the stack is the problem - # itself, which we don't need in the map stack - my @mapPcs = map {$_->map_pc()} @$stack; - $env{'form.filter'} = join(',', @mapPcs); - - # Mark as both "here" and "jump" - $env{'form.postsymb'} = $curRes->symb(); - $minimumduedate=$thisduedate; - } - } - } - } - - # If we found no problems, print a note to that effect. - if (!$foundDoableProblem) { - $r->print("All homework assignments have been completed.

"); - } - } else { - &add_linkitem(\%toplinkitems,'firsthomework', - 'location.href="navmaps?jumpToFirstHomework"', - "Show my first due problem"); - } - - my $suppressEmptySequences = 0; - my $filterFunc = undef; - my $resource_no_folder_link = 0; - - # Display only due homework. - my $showOnlyHomework = 0; - if ($env{'form.showOnlyHomework'} eq "1") { - $showOnlyHomework = 1; - $suppressEmptySequences = 1; - $filterFunc = sub { my $res = shift; - return $res->completable() || $res->is_map(); - }; - &add_linkitem(\%toplinkitems,'everything', - 'location.href="navmaps?sort='.$env{'form.sort'}.'"', - "Show everything"); - $r->print("

".&mt("Uncompleted Problems")."

"); - $env{'form.filter'} = ''; - $env{'form.condition'} = 1; - $resource_no_folder_link = 1; - } else { - &add_linkitem(\%toplinkitems,'uncompleted', - 'location.href="navmaps?sort='.$env{'form.sort'}. - '&showOnlyHomework=1"', - "Show only uncompleted problems"); - } - - my %selected=($env{'form.sort'} => 'selected=on'); - my $sort_html=("
- - - - - -
"); - # renderer call - my $renderArgs = { 'cols' => [0,1,2,3], - 'sort' => $env{'form.sort'}, - 'url' => '/adm/navmaps', - 'navmap' => $navmap, - 'suppressNavmap' => 1, - 'suppressEmptySequences' => $suppressEmptySequences, - 'filterFunc' => $filterFunc, - 'resource_no_folder_link' => $resource_no_folder_link, - 'sort_html'=> $sort_html, - 'r' => $r, - 'caller' => 'navmapsdisplay', - 'linkitems' => \%toplinkitems}; - my $render = render($renderArgs); - - # If no resources were printed, print a reassuring message so the - # user knows there was no error. - if ($renderArgs->{'counter'} == 0) { - if ($showOnlyHomework) { - $r->print("

".&mt("All homework is currently completed").".

"); - } else { # both jumpToFirstHomework and normal use the same: course must be empty - $r->print("

This course is empty.

"); - } - } - #my $td=&tv_interval($t0); - #$r->print("
$td"); - - $r->print(&Apache::loncommon::end_page()); - $r->rflush(); - - return OK; -} - # Convenience functions: Returns a string that adds or subtracts # the second argument from the first hash, appropriate for the # query string that determines which folders to recurse on @@ -469,14 +150,14 @@ sub getLinkForResource { my $anchor; if ($res->is_page()) { foreach (@$stack) { if (defined($_)) { $anchor = $_; } } - $anchor=&Apache::lonnet::escape($anchor->shown_symb()); + $anchor=&escape($anchor->shown_symb()); return ($res->link(),$res->shown_symb(),$anchor); } # in case folder was skipped over as "only sequence" my ($map,$id,$src)=&Apache::lonnet::decode_symb($res->symb()); if ($map=~/\.page$/) { my $url=&Apache::lonnet::clutter($map); - $anchor=&Apache::lonnet::escape($src->shown_symb()); + $anchor=&escape($src->shown_symb()); return ($url,$res->shown_symb(),$anchor); } } @@ -1091,7 +772,13 @@ sub render_resource { if ($resource->is_problem()) { if ($part eq '0' || $params->{'condensed'}) { - $icon =''.&mt('Problem').''; + $icon = ''.&mt('Task');
+	    } else {
+		$icon .= 'problem.gif'; } else { $icon = $params->{'indentString'}; } @@ -1116,16 +803,16 @@ sub render_resource { ($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" border='0' />"; $linkopen = "{'url'} . '?' . - $params->{'queryString'} . '&filter='; + $params->{'queryString'} . '&filter='; $linkopen .= ($nowOpen xor $it->{CONDITION}) ? addToFilter($filter, $mapId) : removeFromFilter($filter, $mapId); - $linkopen .= "&condition=" . $it->{CONDITION} . '&hereType=' - . $params->{'hereType'} . '&here=' . - &Apache::lonnet::escape($params->{'here'}) . - '&jump=' . - &Apache::lonnet::escape($resource->symb()) . - "&folderManip=1\">"; + $linkopen .= "&condition=" . $it->{CONDITION} . '&hereType=' + . $params->{'hereType'} . '&here=' . + &escape($params->{'here'}) . + '&jump=' . + &escape($resource->symb()) . + "&folderManip=1\">"; } else { # Don't allow users to manipulate folder @@ -1147,7 +834,7 @@ sub render_resource { } # We're done preparing and finally ready to start the rendering - my $result = ""; + my $result = ""; my $indentLevel = $params->{'indentLevel'}; if ($newBranchText) { $indentLevel--; } @@ -1176,7 +863,7 @@ sub render_resource { !$params->{'condensed'}) { my $displaypart=$resource->part_display($part); $partLabel = " (".&mt('Part: [_1]', $displaypart).")"; - if ($link!~/\#/) { $link.='#'.&Apache::lonnet::escape($part); } + if ($link!~/\#/) { $link.='#'.&escape($part); } $title = ""; } @@ -1211,7 +898,7 @@ sub render_communication_status { my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); if ($resource->hasDiscussion()) { $discussionHTML = $linkopen . - '' . + ''.&mt('New Discussion').'' . $linkclose; } @@ -1220,8 +907,8 @@ sub render_communication_status { foreach (split(/\,/, $feedback)) { if ($_) { $feedbackHTML .= ' ' - . '' + . ''.&mt('New Email').''; } } @@ -1235,8 +922,8 @@ sub render_communication_status { if ($_) { $errorcount++; $errorHTML .= ' ' - . '' + . ''.&mt('New Error').''; } } @@ -1246,7 +933,7 @@ sub render_communication_status { $discussionHTML = $feedbackHTML = $errorHTML = ''; } - return "$discussionHTML$feedbackHTML$errorHTML "; + return "$discussionHTML$feedbackHTML$errorHTML "; } sub render_quick_status { @@ -1271,7 +958,7 @@ sub render_quick_status { if ($icon) { my $location= &Apache::loncommon::lonhttpdurl("/adm/lonIcons/$icon"); - $result .= "$linkopen$alt$linkclose\n"; + $result .= "$linkopen$alt$linkclose\n"; } else { $result .= " \n"; } @@ -1283,7 +970,7 @@ sub render_quick_status { } sub render_long_status { my ($resource, $part, $params) = @_; - my $result = "\n"; + my $result = "\n"; my $firstDisplayed = !$params->{'condensed'} && $params->{'multipart'} && $part eq "0"; @@ -1469,7 +1156,7 @@ sub render { $navmap = Apache::lonnavmaps::navmap->new(); if (!defined($navmap)) { # no londer in course - return ''.&mt('No course selected').'
+ return ''.&mt('No course selected').'
'.&mt('Select a course').'
'; } } @@ -1607,12 +1294,12 @@ sub render { if ($printCloseAll && !$args->{'resource_no_folder_link'}) { my ($link,$text); if ($condition) { - $link='"navmaps?condition=0&filter=&'.$queryString. - '&here='.&Apache::lonnet::escape($here).'"'; + $link='"navmaps?condition=0&filter=&'.$queryString. + '&here='.&escape($here).'"'; $text='Close all folders'; } else { - $link='"navmaps?condition=1&filter=&'.$queryString. - '&here='.&Apache::lonnet::escape($here).'"'; + $link='"navmaps?condition=1&filter=&'.$queryString. + '&here='.&escape($here).'"'; $text='Open all folders'; } if ($args->{'caller'} eq 'navmapsdisplay') { @@ -1658,7 +1345,7 @@ END if ($args->{'caller'} eq 'navmapsdisplay') { $result .= ''; + &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').''; if ($env{'environment.remotenavmap'} ne 'on') { $result .= ''; } else { @@ -1923,7 +1610,7 @@ END my $srcHasQuestion = $src =~ /\?/; $args->{"resourceLink"} = $src. ($srcHasQuestion?'&':'?') . - 'symb=' . &Apache::lonnet::escape($symb).$anchor; + 'symb=' . &escape($symb).$anchor; } # Now, we've decided what parts to show. Loop through them and # show them. @@ -2228,7 +1915,7 @@ sub generate_email_discuss_status { foreach my $msgid (@keys) { if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { my $plain= - &Apache::lonnet::unescape(&Apache::lonnet::unescape($msgid)); + &LONCAPA::unescape(&LONCAPA::unescape($msgid)); if ($plain=~/ \[([^\]]+)\]\:/) { my $url=$1; if ($plain=~/\:Error \[/) { @@ -2574,7 +2261,7 @@ sub parmval_real { my $result=''; my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb); - + $mapname = &Apache::lonnet::deversion($mapname); # ----------------------------------------------------- Cascading lookup scheme my $rwhat=$what; $what=~s/^parameter\_//; @@ -3830,7 +3517,6 @@ sub contains_problem { } sub is_sequence { my $self=shift; - my $src = $self->src(); return $self->navHash("is_map_", 1) && $self->navHash("map_type_" . $self->map_pc()) eq 'sequence'; } @@ -3905,7 +3591,7 @@ Returns a string with the type of the ma sub map_finish { my $self = shift; my $src = $self->src(); - $src = Apache::lonnet::clutter($src); + $src = &Apache::lonnet::clutter($src); my $res = $self->navHash("map_finish_$src", 0); $res = $self->{NAV_MAP}->getById($res); return $res; @@ -3918,7 +3604,7 @@ sub map_pc { sub map_start { my $self = shift; my $src = $self->src(); - $src = Apache::lonnet::clutter($src); + $src = &Apache::lonnet::clutter($src); my $res = $self->navHash("map_start_$src", 0); $res = $self->{NAV_MAP}->getById($res); return $res; @@ -4030,14 +3716,24 @@ sub awarded { if (!defined($part)) { $part = '0'; } return $self->{NAV_MAP}->{STUDENT_DATA}->{$self->symb()}->{'resource.'.$part.'.awarded'}; } +# this should work exactly like the copy in lonhomework.pm sub duedate { (my $self, my $part) = @_; + my $date; my $interval=$self->parmval("interval", $part); - if ($interval) { + my $due_date=$self->parmval("duedate", $part); + if ($interval =~ /\d+/) { my $first_access=&Apache::lonnet::get_first_access('map',$self->symb); - if ($first_access) { return ($first_access+$interval); } + if (defined($first_access)) { + $interval = $first_access+$interval; + $date = ($interval < $due_date)? $interval : $due_date; + } else { + $date = $due_date; + } + } else { + $date = $due_date; } - return $self->parmval("duedate", $part); + return $date; } sub handgrade { (my $self, my $part) = @_; @@ -4155,7 +3851,7 @@ email data was not extracted when the na used like this: for (split(/\,/, $res->getFeedback())) { - my $link = &Apache::lonnet::escape($_); + my $link = &escape($_); ... and use the link as appropriate. @@ -4385,9 +4081,9 @@ sub extractParts { # So we have to use our knowlege of part names to figure out # where the part names begin and end, and even then, it is possible # to construct ambiguous situations. - foreach (split /,/, $metadata) { - if ($_ =~ /^([a-zA-Z]+)response_(.*)/ - || $_ =~ /^(Task)_(.*)/) { + foreach my $data (split /,/, $metadata) { + if ($data =~ /^([a-zA-Z]+)response_(.*)/ + || $data =~ /^(Task)_(.*)/) { my $responseType = $1; my $partStuff = $2; my $partIdSoFar = ''; @@ -4399,8 +4095,15 @@ sub extractParts { if ($parts{$partIdSoFar}) { my @otherChunks = @partChunks[$i+1..$#partChunks]; my $responseId = join('_', @otherChunks); - push @{$responseIdHash{$partIdSoFar}}, $responseId; - push @{$responseTypeHash{$partIdSoFar}}, $responseType; + if ($self->is_task()) { + push(@{$responseIdHash{$partIdSoFar}}, + $partIdSoFar); + } else { + push(@{$responseIdHash{$partIdSoFar}}, + $responseId); + } + push(@{$responseTypeHash{$partIdSoFar}}, + $responseType); } } }
'. - &Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT').'