--- loncom/interface/lonnavmaps.pm 2005/02/05 06:52:50 1.315 +++ loncom/interface/lonnavmaps.pm 2006/04/20 04:30:11 1.378 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.315 2005/02/05 06:52:50 albertel Exp $ +# $Id: lonnavmaps.pm,v 1.378 2006/04/20 04:30:11 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -30,6 +30,7 @@ package Apache::lonnavmaps; use strict; +use GDBM_File; use Apache::Constants qw(:common :http); use Apache::loncommon(); use Apache::lonmenu(); @@ -38,6 +39,7 @@ 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 ); # symbolic constants sub SYMB { return 1; } @@ -55,6 +57,7 @@ my %statusIconMap = $resObj->CLOSED => '', $resObj->OPEN => 'navmap.open.gif', $resObj->CORRECT => 'navmap.correct.gif', + $resObj->PARTIALLY_CORRECT => 'navmap.partial.gif', $resObj->INCORRECT => 'navmap.wrong.gif', $resObj->ATTEMPTED => 'navmap.ellipsis.gif', $resObj->ERROR => '' @@ -79,21 +82,28 @@ my %colormap = $resObj->OPEN => '', $resObj->NOTHING_SET => '', $resObj->ATTEMPTED => '', - $resObj->ANSWER_SUBMITTED => '' + $resObj->ANSWER_SUBMITTED => '', + $resObj->PARTIALLY_CORRECT => '#006600' ); # 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"; sub launch_win { - my ($mode,$script,$toplinkitems)=@_; + my ($mode,$script,$toplinkitems,$firsttime)=@_; my $result; if ($script ne 'no') { $result.=' - - - ENDSUBM - return; + $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} eq 'launchExternal') { + 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 @@ -210,52 +237,41 @@ ENDSUBM if (!defined($navmap)) { my $requrl = $r->uri; - $ENV{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; + $env{'user.error.msg'} = "$requrl:bre:0:0:Course not initialized"; return HTTP_NOT_ACCEPTABLE; } + $r->send_http_header; - $r->print("\n"); - $r->print("".&mt('Navigate Course Contents').""); # ------------------------------------------------------------ Get query string &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']); # ----------------------------------------------------- Force menu registration - my $addentries=''; - my $more_unload; my $body_only=''; - if ($ENV{'environment.remotenavmap'} eq 'on') { - $r->print(''); -# FIXME need to be smarter to only catch window close events -# $more_unload="collapse()" + my $js; + if ($env{'environment.remotenavmap'} eq 'on') { + $js=''; $body_only=1; } - if ($ENV{'form.register'}) { - $addentries=' onLoad="'.&Apache::lonmenu::loadevents(). - '" onUnload="'.&Apache::lonmenu::unloadevents().';'. - $more_unload.'"'; - $r->print(&Apache::lonmenu::registerurl(1)); - } else { - $addentries=' onUnload="'.$more_unload.'"'; - } # Header - $r->print(''. - &Apache::loncommon::bodytag('Navigate Course Contents','', - $addentries,$body_only,'', - $ENV{'form.register'})); - $r->print(''); + $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('Coursemap undefined.' . - ''); + $r->print(''.&mt('Coursemap undefined.'). + '' . + &Apache::loncommon::end_page()); return OK; } @@ -277,15 +293,15 @@ ENDSUBM 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 + # the defined($env{'form.filter'}) also ensures this # is a fresh call. - $ENV{'form.filter'} = "$sequenceId"; + $env{'form.filter'} = "$sequenceId"; } } if ($ENV{QUERY_STRING} eq 'launchExternal') { $r->print(' -
'); $r->print(' @@ -294,40 +310,46 @@ ENDSUBM '); } - if ($ENV{'environment.remotenavmap'} ne 'on') { + if ($env{'environment.remotenavmap'} ne 'on') { $r->print(&launch_win('link','yes',\%toplinkitems)); } - if ($ENV{'environment.remotenavmap'} eq 'on') { + if ($env{'environment.remotenavmap'} eq 'on') { &add_linkitem(\%toplinkitems,'closenav','collapse()', "Close navigation window"); } - my $jumpToFirstHomework = 0; + # Check to see if the student is jumping to next open, do-able problem if ($ENV{QUERY_STRING} =~ /^jumpToFirstHomework/) { - $jumpToFirstHomework = 1; # Find the next homework problem that they can do. my $iterator = $navmap->getIterator(undef, undef, undef, 1); my $curRes; my $foundDoableProblem = 0; - my $problemRes; + my $minimumduedate; - while (($curRes = $iterator->next()) && !$foundDoableProblem) { + while ($curRes = $iterator->next()) { if (ref($curRes) && $curRes->is_problem()) { my $status = $curRes->status(); if ($curRes->completable()) { - $problemRes = $curRes; + my $thisduedate=$curRes->duedate(); + unless ($foundDoableProblem) { + $minimumduedate=$thisduedate; + } + $foundDoableProblem = 1; - # 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(); + 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; + } } } } @@ -339,7 +361,7 @@ ENDSUBM } else { &add_linkitem(\%toplinkitems,'firsthomework', 'location.href="navmaps?jumpToFirstHomework"', - "Show Me My First Homework Problem"); + "Show my first due problem"); } my $suppressEmptySequences = 0; @@ -348,30 +370,30 @@ ENDSUBM # Display only due homework. my $showOnlyHomework = 0; - if ($ENV{'form.showOnlyHomework'} eq "1") { + 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 Homework")."

"); - $ENV{'form.filter'} = ''; - $ENV{'form.condition'} = 1; + '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'}. + 'location.href="navmaps?sort='.$env{'form.sort'}. '&showOnlyHomework=1"', - "Show Only Uncompleted Homework"); + "Show only uncompleted problems"); } - my %selected=($ENV{'form.sort'} => 'selected=on'); + my %selected=($env{'form.sort'} => 'selected=on'); my $sort_html=("
- +