Diff for /loncom/interface/lonnavmaps.pm between versions 1.558 and 1.572

version 1.558, 2022/06/11 14:51:49 version 1.572, 2025/02/26 19:50:21
Line 48  described at http://www.lon-capa.org. Line 48  described at http://www.lon-capa.org.
   
 =head1 OVERVIEW  =head1 OVERVIEW
   
 X<lonnavmaps, overview> When a user enters a course, LON-CAPA examines the  X<lonnavmaps, overview>
   When a user enters a course, LON-CAPA examines the
 course structure and caches it in what is often referred to as the  course structure and caches it in what is often referred to as the
 "big hash" X<big hash>. You can see it if you are logged into  "big hash" X<big hash>. You can see it if you are logged into
 LON-CAPA, in a course, by going to /adm/test. The content of   LON-CAPA, in a course, by going to /adm/test. The content of 
Line 549  my %colormap = Line 550  my %colormap =
       $resObj->EXCUSED                => '#3333FF',        $resObj->EXCUSED                => '#3333FF',
       $resObj->PAST_DUE_ANSWER_LATER  => '',        $resObj->PAST_DUE_ANSWER_LATER  => '',
       $resObj->PAST_DUE_NO_ANSWER     => '',        $resObj->PAST_DUE_NO_ANSWER     => '',
         $resObj->PAST_DUE_ATMPT_ANS     => '',
         $resObj->PAST_DUE_ATMPT_NOANS   => '',
         $resObj->PAST_DUE_NO_ATMT_ANS   => '',
         $resObj->PAST_DUE_NO_ATMT_NOANS => '',
       $resObj->ANSWER_OPEN            => '#006600',        $resObj->ANSWER_OPEN            => '#006600',
       $resObj->OPEN_LATER             => '',        $resObj->OPEN_LATER             => '',
       $resObj->TRIES_LEFT             => '',        $resObj->TRIES_LEFT             => '',
Line 694  sub getDescription { Line 699  sub getDescription {
             return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part).$slotinfo;              return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part).$slotinfo;
         }          }
     }      }
     if ($status == $res->PAST_DUE_ANSWER_LATER) {      if (($status == $res->PAST_DUE_ANSWER_LATER) || ($status == $res->PAST_DUE_ATMPT_ANS) || ($status == $res->PAST_DUE_NO_ATMT_ANS)) {
         return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part));          return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part));
     }      }
     if ($status == $res->PAST_DUE_NO_ANSWER) {      if (($status == $res->PAST_DUE_NO_ANSWER) || ($status == $res->PAST_DUE_ATMPT_NOANS) || ($status == $res->PAST_DUE_NO_ATMT_NOANS)) {
  if ($res->is_practice()) {   if ($res->is_practice()) {
     return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part));      return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part));
  } else {   } else {
Line 1020  sub render_resource { Line 1025  sub render_resource {
         if ($it->{CONDITION}) {          if ($it->{CONDITION}) {
             $nowOpen = !$nowOpen;              $nowOpen = !$nowOpen;
         }          }
    my $folderType;
  my $folderType = $resource->is_sequence() ? 'folder' : 'page';   if (&advancedUser() && $resource->is_missing_map()) {
       $folderType = 'none';
    } else {
       $folderType = $resource->is_sequence() ? 'folder' : 'page';
    }
         my $title=$resource->title;          my $title=$resource->title;
  $title=~s/\"/\&qout;/g;   $title=~s/\"/\&qout;/g;
         if (!$params->{'resource_no_folder_link'}) {          if (!$params->{'resource_no_folder_link'}) {
Line 1112  sub render_resource { Line 1121  sub render_resource {
     }      }
   
     # Decide what to display      # Decide what to display
     $result .= "$newBranchText$linkopen$icon$linkclose";      $result .= "$newBranchText$linkopen$icon";
           
     my $curMarkerBegin = '';      my $curMarkerBegin = '';
     my $curMarkerEnd = '';      my $curMarkerEnd = '';
Line 1152  sub render_resource { Line 1161  sub render_resource {
             $linkopen = "<a href=\"$link\">";              $linkopen = "<a href=\"$link\">";
         }          }
     }      }
     $result .= "$curMarkerBegin$linkopen$title$partLabel$linkclose$curMarkerEnd$editmapLink$nonLinkedText</td>";      $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$linkclose$editmapLink$nonLinkedText</td>";
   
     return $result;      return $result;
 }  }
Line 1423  sub render { Line 1432  sub render {
     my $condition = 0;      my $condition = 0;
     if ($env{'form.condition'}) {      if ($env{'form.condition'}) {
         $condition = 1;          $condition = 1;
       } elsif (($env{'request.deeplink.login'}) && ($env{'request.course.id'}) && (!$userCanSeeHidden)) {
           if (!defined($navmap)) {
               $navmap = Apache::lonnavmaps::navmap->new();
           }
           if (defined($navmap)) {
               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
               my $symb = &Apache::loncommon::symb_from_tinyurl($env{'request.deeplink.login'},$cnum,$cdom);
               if ($symb) {
                   my $deeplink;
                   my $res = $navmap->getBySymb($symb);
                   if ($res->is_map()) {
                       my $mapname = &Apache::lonnet::declutter($res->src());
                       $mapname = &Apache::lonnet::deversion($mapname);
                       $deeplink = $navmap->get_mapparam(undef,$mapname,"0.deeplink");
                   } else {
                       $deeplink = $res->deeplink();
                   }
                   if ($deeplink ne '') {
                       if ((split(/,/,$deeplink))[1] eq 'hide') {
                           if ($res->is_map()) {
                               map { $filterHash->{$_} = 1 if $_ } split(/,/,$res->map_hierarchy());
                           } else {
                               my $mapurl = (&Apache::lonnet::decode_symb($symb))[0];
                               my $map = $navmap->getResourceByUrl($mapurl);
                               map { $filterHash->{$_} = 1 if $_ } split(/,/,$map->map_hierarchy());
                           }
                       }
                   }
               }
           }
     }      }
   
     if (!$env{'form.folderManip'} && !defined($args->{'iterator'}) && !$args->{'nocurrloc'}) {      if (!$env{'form.folderManip'} && !defined($args->{'iterator'}) && !$args->{'nocurrloc'}) {
Line 1533  sub render { Line 1573  sub render {
     my $curRes;      my $curRes;
     my $foundJump = 0;      my $foundJump = 0;
     my $counter = 0;      my $counter = 0;
       
     while (($curRes = $mapIterator->next()) && !$foundJump) {      while (($curRes = $mapIterator->next()) && !$foundJump) {
         if (ref($curRes)) { $counter++; }          if (ref($curRes)) { $counter++; }
                   # Speed up display after course initialization
           # when $jump is empty. Note: we still need
           # $counter to be 1 in that case if there is at
           # least one resource.
           last if (($jump eq '') && ($counter));
   
         if (ref($curRes) && $jump eq $curRes->symb()) {          if (ref($curRes) && $jump eq $curRes->symb()) {
                           
             # This is why we have to use the main iterator instead of the              # This is why we have to use the main iterator instead of the
Line 1555  sub render { Line 1600  sub render {
     my $printKey = $args->{'printKey'};      my $printKey = $args->{'printKey'};
     my $printCloseAll = $args->{'printCloseAll'};      my $printCloseAll = $args->{'printCloseAll'};
     if (!defined($printCloseAll)) { $printCloseAll = 1; }      if (!defined($printCloseAll)) { $printCloseAll = 1; }
      
     # Print key?      # Print key?
     if ($printKey) {      if ($printKey) {
         $result .= '<table border="0" cellpadding="2" cellspacing="0">';          my $location = &Apache::loncommon::lonhttpdurl("/adm/lonMisc");
         $result.='<tr><td align="right" valign="bottom">Key:&nbsp;&nbsp;</td>';          $result .= '<div class="LC_navtools">'."\n".
  my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc");                     '<span class="LC_middle LC_right">'.&mt('Key').':</span>'.
         if ($navmap->{LAST_CHECK}) {                     '<span class="LC_middle LC_center">&nbsp;&nbsp;'.
             $result .=                      '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('Unread Discussion').
                 '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('New discussion since').' '.                     '&nbsp;&nbsp;'.
                 strftime("%A, %b %e at %I:%M %P", localtime($navmap->{LAST_CHECK})).                     '<img src="'.$location.'/feedback.gif" alt="" /> '.
                 '</td><td align="center" valign="bottom">&nbsp;&nbsp;'.                     &mt('New message (click to open)').
                 '<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').'<p>'.                     '</span></div>'.
                 '</td>';                      '<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
         } else {  
             $result .= '<td align="center" valign="bottom">&nbsp;&nbsp;'.  
                 '<img src="'.$location.'/chat.gif" alt="" /> '.&mt('Discussions').'</td><td align="center" valign="bottom">'.  
                 '&nbsp;&nbsp;<img src="'.$location.'/feedback.gif" alt="" /> '.&mt('New message (click to open)').  
                 '</td>';   
         }  
   
         $result .= '</tr></table>';  
     }      }
   
     if ($printCloseAll && !$args->{'resource_no_folder_link'}) {      if ($printCloseAll && !$args->{'resource_no_folder_link'}) {
Line 1602  sub render { Line 1639  sub render {
   
     # Check for any unread discussions in all resources.      # Check for any unread discussions in all resources.
     if (($args->{'caller'} eq 'navmapsdisplay') && (!$args->{'notools'})) {      if (($args->{'caller'} eq 'navmapsdisplay') && (!$args->{'notools'})) {
           my $markread = 'Mark all posts read';
  &add_linkitem($args->{'linkitems'},'clearbubbles',   &add_linkitem($args->{'linkitems'},'clearbubbles',
       'document.clearbubbles.submit()',        'document.clearbubbles.submit()',
       'Mark all posts read');        $markread);
  my $time=time;   my $time=time;
           my $submit = &mt($markread);
         my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"');          my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"');
  $result .= (<<END);   $result .= (<<END);
     <form name="clearbubbles" method="post" action="/adm/feedback">      <form name="clearbubbles" method="post" action="/adm/feedback" aria-hidden="true">
  <input type="hidden" name="navurl" value="$querystr" />   <input type="hidden" name="navurl" value="$querystr" />
  <input type="hidden" name="navtime" value="$time" />   <input type="hidden" name="navtime" value="$time" />
 END  END
         if ($args->{'sort'} eq 'discussion') {           if ($args->{'sort'} eq 'discussion') {
     my $totdisc = 0;      my $totdisc = 0;
     my $haveDisc = '';      my $haveDisc = '';
     my @allres=$navmap->retrieveResources();      my @allres=$navmap->retrieveResources();
Line 1626  END Line 1665  END
  $haveDisc =~ s/:$//;   $haveDisc =~ s/:$//;
  $result .= (<<END);   $result .= (<<END);
  <input type="hidden" name="navmaps" value="$haveDisc" />   <input type="hidden" name="navmaps" value="$haveDisc" />
     </form>  
 END  END
             }              }
  }   }
  $result.='</form>';   $result .= <<END;
           <input type="submit" value="$submit" class="LC_visually_hidden" tabindex="-1" disabled="disabled" />
       </form>
   END
     }      }
     if (($args->{'caller'} eq 'navmapsdisplay') && ($env{'request.course.id'})) {      if (($args->{'caller'} eq 'navmapsdisplay') && ($env{'request.course.id'})) {
         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
Line 1668  END Line 1709  END
     $result .= "<br />\n";      $result .= "<br />\n";
   
     # Data      # Data
     $result.=&Apache::loncommon::start_data_table("LC_tableOfContent");          if ($counter) {
           $result.=&Apache::loncommon::start_data_table("LC_tableOfContent").
                    &Apache::loncommon::start_data_table_header_row('LC_visually_hidden').
                    '<th>'.&mt('Resource or Folder').'</th>'.
                    '<th>'.&mt('Alerts').'</th>'.
                    '<th>'.&mt('Status Icon').'</th>'.
                    '<th>'.&mt('Date/Completion Status').'</th>'.
                    &Apache::loncommon::end_data_table_row()."\n";
       }
   
     my $res = "Apache::lonnavmaps::resource";      my $res = "Apache::lonnavmaps::resource";
     my %condenseStatuses =      my %condenseStatuses =
Line 1693  END Line 1742  END
     # mark as hidden for users who have $userCanSeeHidden.        # mark as hidden for users who have $userCanSeeHidden.  
     # Use DFS for speed, since structure actually doesn't matter,      # Use DFS for speed, since structure actually doesn't matter,
     # except what map has what resources.      # except what map has what resources.
       #
       # To ensure the "Selected Resources from selected folder in course"
       # printout generation option will work in sessions launched via a
       # deep link, the value of $args->{'filterFunc'} included in the 
       # call to lonnavmaps::render() is omitted from the filter function
       # used with the DFS Iterator when $args->{'caller'} is 'printout'.
       #
       # As a result $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} can be
       # set to 1 for folder(s) which include resources only accessible
       # for sessions launched via a deep link, when the current session 
       # is of that type.
   
     my $dfsit = Apache::lonnavmaps::DFSiterator->new($navmap,      my $dfsit = Apache::lonnavmaps::DFSiterator->new($navmap,
                                                      $it->{FIRST_RESOURCE},                                                       $it->{FIRST_RESOURCE},
                                                      $it->{FINISH_RESOURCE},                                                       $it->{FINISH_RESOURCE},
                                                      {}, undef, 1);                                                       {}, undef, 1);
       my $dfsFilterFunc;
       if ($args->{'caller'} eq 'printout') {
           $dfsFilterFunc = sub { my $res = shift; return !$res->randomout() &&
                                 ($res->deeplink($args->{'caller'}) ne 'absent') &&
                                 ($res->deeplink($args->{'caller'}) ne 'grades') &&
                                 !$res->deeplinkout();};
       } else {
           $dfsFilterFunc = $filterFunc;
       }
     my $depth = 0;      my $depth = 0;
     $dfsit->next();      $dfsit->next();
     my $curRes = $dfsit->next();      my $curRes = $dfsit->next();
Line 1716  END Line 1785  END
             } elsif ($curRes->src()) {              } elsif ($curRes->src()) {
                 # Not a sequence: if it's filtered, ignore it, otherwise                  # Not a sequence: if it's filtered, ignore it, otherwise
                 # rise up the stack and mark the sequences as having children                  # rise up the stack and mark the sequences as having children
                 if (&$filterFunc($curRes)) {                  if (&$dfsFilterFunc($curRes)) {
                     for my $sequence (@{$dfsit->getStack()}) {                      for my $sequence (@{$dfsit->getStack()}) {
                           next unless ($sequence->is_map());
                         $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} = 1;                          $sequence->{DATA}->{HAS_VISIBLE_CHILDREN} = 1;
                     }                      }
                 }                  }
Line 2045  END Line 2115  END
  }   }
     }      }
   
     $result.=&Apache::loncommon::end_data_table();      if ($counter) {
           $result.=&Apache::loncommon::end_data_table();
       }
           
     # Print out the part that jumps to #curloc if it exists      # Print out the part that jumps to #curloc if it exists
     # delay needed because the browser is processing the jump before      # delay needed because the browser is processing the jump before
Line 2084  sub show_linkitems_toolbar { Line 2156  sub show_linkitems_toolbar {
         if (ref($args->{'linkitems'}) eq 'HASH') {          if (ref($args->{'linkitems'}) eq 'HASH') {
             my $numlinks = scalar(keys(%{$args->{'linkitems'}}));              my $numlinks = scalar(keys(%{$args->{'linkitems'}}));
             if ($numlinks > 1) {              if ($numlinks > 1) {
                 $result = '<td>'.                  $result = '<div class="LC_navtools">'.
                           &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',                            &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',
                                                              undef,'RAT').                                                               undef,'RAT').
                           '</td>'.                            '</div><div class="LC_navtools">&nbsp;'.&mt('Tools:').'</div>';
                           '<td>&nbsp;</td>'.  
                           '<td class="LC_middle">'.&mt('Tools:').'</td>';  
             }              }
             $result .= '<td align="left">'."\n".              $result .= '<div class="LC_navtools">'."\n".
                        '<ul id="LC_toolbar">';                         '<ul id="LC_toolbar">';
             my @linkorder = ('firsthomework','everything','uncompleted',              my @linkorder = ('firsthomework','everything','uncompleted',
                              'changefolder','clearbubbles','printout','edittoplevel');                               'changefolder','clearbubbles','printout','edittoplevel');
Line 2119  sub show_linkitems_toolbar { Line 2189  sub show_linkitems_toolbar {
                 }                  }
             }              }
             $result .= '</ul>'.              $result .= '</ul>'.
                        '</td>';                         '</div>';
             if (($numlinks==1) && (exists($args->{'linkitems'}{'edittoplevel'}))) {              if (($numlinks==1) && (exists($args->{'linkitems'}{'edittoplevel'}))) {
                 $result .= '<td><a href="'.$args->{'linkitems'}{'edittoplevel'}{'cmd'}.'">'.                  $result .= '<div class="LC_navtools">'.
                            &mt('Content Editor').'</a></td>';                             '&nbsp;<a href="'.$args->{'linkitems'}{'edittoplevel'}{'cmd'}.'">'.
                              &mt('Content Editor').'</a></div>';
             }              }
         }          }
         if ($args->{'sort_html'}) {          if ($args->{'sort_html'}) {
             $result .= '<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>'.              $result .= '<div class="LC_navtools">&nbsp;&nbsp;&nbsp;'.
                        '<td align="right">'.$args->{'sort_html'}.'</td>';                         $args->{'sort_html'}.'</div>';
         }          }
     }      }
     if ($result) {      if ($result) {
         $result = "<table><tr>$result</tr></table>";          $result = '<div class="LC_navtools">'.$result.'</div>'."\n".
                     '<div style="padding:0;clear:both;margin:0;border:0"></div>'."\n";
     }      }
     return $result;      return $result;
 }  }
Line 2226  sub new { Line 2298  sub new {
   
     $self->{USERNAME} = shift || $env{'user.name'};      $self->{USERNAME} = shift || $env{'user.name'};
     $self->{DOMAIN}   = shift || $env{'user.domain'};      $self->{DOMAIN}   = shift || $env{'user.domain'};
       $self->{SECTION}  = shift;
     $self->{CODE}     = shift;      $self->{CODE}     = shift;
     $self->{NOHIDE} = shift;      $self->{NOHIDE}   = shift;
   
   
       if (($self->{SECTION} eq '') && ($env{'request.course.sec'} ne '')) {
           if (($self->{USERNAME} eq $env{'user.name'}) &&
               ($self->{USERNAME} eq $env{'user.domain'})) {
               $self->{SECTION} = $env{'request.course.sec'};
           }
       }
   
     # Resource cache stores navmap resources as we reference them. We generate      # Resource cache stores navmap resources as we reference them. We generate
     # them on-demand so we don't pay for creating resources unless we use them.      # them on-demand so we don't pay for creating resources unless we use them.
Line 2271  sub new { Line 2350  sub new {
  $self->{PARM_HASH} = \%parmhash;   $self->{PARM_HASH} = \%parmhash;
  $self->{PARM_CACHE} = {};   $self->{PARM_CACHE} = {};
     } else {      } else {
  $self->change_user($self->{USERNAME}, $self->{DOMAIN},  $self->{CODE}, $self->{NOHIDE});   $self->change_user($self->{USERNAME}, $self->{DOMAIN}, $self->{SECTION}, $self->{CODE}, $self->{NOHIDE});
     }      }
   
     return $self;      return $self;
Line 2282  sub new { Line 2361  sub new {
 # username/domain associated with a navmap (e.g. to navigate for someone  # username/domain associated with a navmap (e.g. to navigate for someone
 # else besides the current user...if sufficiently privileged.  # else besides the current user...if sufficiently privileged.
 # Parameters:  # Parameters:
 #    user  - New user.  #    user    - New user.
 #    domain- Domain the user belongs to.  #    domain  - Domain to which the user belongs.
 #    code  - Anonymous CODE in use.  #    section - Section to which the user belongs.
   #    code    - Anonymous CODE in use.
 # Implicit inputs:  # Implicit inputs:
 #     #   
 sub change_user {  sub change_user {
     my $self = shift;      my $self = shift;
     $self->{USERNAME} = shift;      $self->{USERNAME} = shift;
     $self->{DOMAIN}   = shift;      $self->{DOMAIN}   = shift;
       $self->{SECTION}  = shift;
     $self->{CODE}     = shift;      $self->{CODE}     = shift;
     $self->{NOHIDE}   = shift;      $self->{NOHIDE}   = shift;
   
Line 2797  sub parmval_real { Line 2878  sub parmval_real {
     $self->generate_course_user_opt();      $self->generate_course_user_opt();
   
     my $cid=$env{'request.course.id'};      my $cid=$env{'request.course.id'};
     my $csec=$env{'request.course.sec'};      my $csec=$self->{SECTION};
     my $cgroup='';      my $cgroup='';
     my @cgrps=split(/:/,$env{'request.course.groups'});      my @cgrps=split(/:/,$env{'request.course.groups'});
     if (@cgrps > 0) {      if (@cgrps > 0) {
Line 2986  sub parmval_real { Line 3067  sub parmval_real {
 }  }
   
 sub recurseup_maps {  sub recurseup_maps {
     my ($self,$mapname) = @_;      my ($self,$mapname,$getsymb) = @_;
     my @recurseup;      my @recurseup;
     if ($mapname) {      if ($mapname) {
         my $res = $self->getResourceByUrl($mapname);          my $res = $self->getResourceByUrl($mapname);
Line 2994  sub recurseup_maps { Line 3075  sub recurseup_maps {
             my @pcs = split(/,/,$res->map_hierarchy());              my @pcs = split(/,/,$res->map_hierarchy());
             shift(@pcs);              shift(@pcs);
             if (@pcs) {              if (@pcs) {
                 @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->src()); } reverse(@pcs);                  if ($getsymb) {
                       @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->symb()); } reverse(@pcs);
                   } else {
                       @recurseup = map { &Apache::lonnet::declutter($self->getByMapPc($_)->src()); } reverse(@pcs);
                   }
             }              }
         }          }
     }      }
Line 3026  sub recursed_crumbs { Line 3111  sub recursed_crumbs {
         my $pc = $map->map_pc();          my $pc = $map->map_pc();
         next if ((!$pc) || ($pc == 1));          next if ((!$pc) || ($pc == 1));
         push(@links,$map);          push(@links,$map);
         push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $map->title(),'no_mt' => 1,});          my $text = $map->title();
         $totallength += length($map->title());          if ($text eq '') {
               $text = '...';
           }
           push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $text,'no_mt' => 1,});
           $totallength += length($text);
     }      }
     my $numlinks = scalar(@links);      my $numlinks = scalar(@links);
     if ($numlinks) {      if ($numlinks) {
Line 3039  sub recursed_crumbs { Line 3128  sub recursed_crumbs {
             }              }
             @revmapinfo = ();              @revmapinfo = ();
             foreach my $map (@links) {              foreach my $map (@links) {
                 my $showntitle = &truncate_crumb_text($map->title(),$avg);                  my $title = $map->title();
                   if ($title eq '') {
                       $title = '...';
                   }
                   my $showntitle = &truncate_crumb_text($title,$avg);
                 if ($showntitle ne '') {                  if ($showntitle ne '') {
                     push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,});                      push(@revmapinfo,{'href' => $env{'request.use_absolute'}.$map->link().'?navmap=1','text' => $showntitle,'no_mt' => 1,});
                 }                  }
Line 3114  sub get_mapparam { Line 3207  sub get_mapparam {
     # Get the course id and section if there is one.      # Get the course id and section if there is one.
   
     my $cid=$env{'request.course.id'};      my $cid=$env{'request.course.id'};
     my $csec=$env{'request.course.sec'};      my $csec=$self->{SECTION};
     my $cgroup='';      my $cgroup='';
     my @cgrps=split(/:/,$env{'request.course.groups'});      my @cgrps=split(/:/,$env{'request.course.groups'});
     if (@cgrps > 0) {      if (@cgrps > 0) {
Line 3315  sub getcourseparam { Line 3408  sub getcourseparam {
   
     my $uname = $self->{USERNAME};      my $uname = $self->{USERNAME};
     my $udom  = $self->{DOMAIN};      my $udom  = $self->{DOMAIN};
       my $csec  = $self->{SECTION};
           
     # Course, section, group ids come from the env:      # Course and group ids come from the env:
   
     my $cid   = $env{'request.course.id'};      my $cid   = $env{'request.course.id'};
     my $csec  = $env{'request.course.sec'};  
     my $cgroup = ''; # Assume no group      my $cgroup = ''; # Assume no group
   
     my @cgroups = split(/:/, $env{'request.course.groups'});      my @cgroups = split(/:/, $env{'request.course.groups'});
Line 4745  sub is_sequence { Line 4838  sub is_sequence {
     return $self->navHash("is_map_", 1) &&       return $self->navHash("is_map_", 1) && 
     $self->navHash("map_type_" . $self->map_pc()) eq 'sequence';      $self->navHash("map_type_" . $self->map_pc()) eq 'sequence';
 }  }
   sub is_missing_map {
       my $self=shift;
       return $self->navHash("is_map_", 1) &&
       $self->navHash("map_type_" . $self->map_pc()) eq 'none';
   }
 sub is_survey {  sub is_survey {
     my $self = shift();      my $self = shift();
     my $part = shift();      my $part = shift();
Line 5172  sub weight { Line 5270  sub weight {
     my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',      my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',
                                 $self->{SYMB}, $self->{DOMAIN},                                  $self->{SYMB}, $self->{DOMAIN},
                                 $self->{USERNAME},                                  $self->{USERNAME},
                                 $env{'request.course.sec'});                                  $self->{SECTION});  
     return $weight;      return $weight;
 }  }
 sub part_display {  sub part_display {
Line 5646  The problem will be opened later. Line 5744  The problem will be opened later.
   
 Open and not yet due.  Open and not yet due.
   
   
 =item * B<PAST_DUE_ANSWER_LATER>:  =item * B<PAST_DUE_ANSWER_LATER>:
   
 The due date has passed, but the answer date has not yet arrived.  The due date has passed, but the answer date has not yet arrived.
Line 5659  The due date has passed and there is no Line 5756  The due date has passed and there is no
   
 The answer date is here.  The answer date is here.
   
   =item * B<NOTHING_SET>:
   
   No dates have been set for this problem at all.
   
   =item * B<PAST_DUE_ATMPT_ANS>:
   
   The due date has passed, feedback is suppressed, the problem was attempted, and the answer date has not yet arrived.
   
   =item * B<PAST_DUE_ATMPT_NOANS>:
   
   The due date has passed, feedback is suppressed, the problem was attempted, and there is no answer opening date set.
   
   =item * B<PAST_DUE_NO_ATMT_ANS>:
   
   The due date has passed, feedback is suppressed, the problem was not attempted, and the answer date has not yet arrived.
   
   =item * B<PAST_DUE_NO_ATMT_NOANS>:
   
   The due date has passed, feedback is suppressed, the problem was not attempted, and there is no answer opening date set.
   
 =item * B<NETWORK_FAILURE>:  =item * B<NETWORK_FAILURE>:
   
 The information is unknown due to network failure.  The information is unknown due to network failure.
Line 5674  sub PAST_DUE_NO_ANSWER     { return 2; } Line 5791  sub PAST_DUE_NO_ANSWER     { return 2; }
 sub PAST_DUE_ANSWER_LATER  { return 3; }  sub PAST_DUE_ANSWER_LATER  { return 3; }
 sub ANSWER_OPEN            { return 4; }  sub ANSWER_OPEN            { return 4; }
 sub NOTHING_SET            { return 5; }  sub NOTHING_SET            { return 5; }
   sub PAST_DUE_ATMPT_ANS     { return 6; }
   sub PAST_DUE_ATMPT_NOANS   { return 7; }
   sub PAST_DUE_NO_ATMT_ANS   { return 8; }
   sub PAST_DUE_NO_ATMT_NOANS { return 9; }
 sub NETWORK_FAILURE        { return 100; }  sub NETWORK_FAILURE        { return 100; }
   
 # getDateStatus gets the date status for a given problem part.   # getDateStatus gets the date status for a given problem part. 
Line 5877  set. Line 5998  set.
 The problem is past due, not considered correct, and an answer date in  The problem is past due, not considered correct, and an answer date in
 the future is set.  the future is set.
   
   =item * B<PAST_DUE_ATMPT_ANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   attempted and an answer date in the future is set.
   
   =item * B<PAST_DUE_ATMPT_NOANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   attempted and no answer date is set.
   
   =item * B<PAST_DUE_NO_ATMT_ANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   not attempted and an answer date in the future is set.
   
   =item * B<PAST_DUE_NO_ATMT_NOANS>:
   
   The problem is past due, feedback is suppressed, the problem was
   not attempted and no answer date is set.
   
 =item * B<ANSWER_OPEN>:  =item * B<ANSWER_OPEN>:
   
 The problem is past due, not correct, and the answer is now available.  The problem is past due, not correct, and the answer is now available.
Line 5960  sub status { Line 6101  sub status {
     if ($completionStatus == CORRECT ||      if ($completionStatus == CORRECT ||
         $completionStatus == CORRECT_BY_OVERRIDE ||          $completionStatus == CORRECT_BY_OVERRIDE ||
         $completionStatus == CORRECT_BY_PASSBACK ) {          $completionStatus == CORRECT_BY_PASSBACK ) {
  if ( $suppressFeedback ) { return ANSWER_SUBMITTED }   if ( $suppressFeedback ) {
               if ($dateStatus == PAST_DUE_ANSWER_LATER ||
                   $dateStatus == PAST_DUE_NO_ANSWER ) {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_ATMPT_ANS;
                   } else {
                       return PAST_DUE_ATMPT_NOANS;
                   }
               } else {
                   return ANSWER_SUBMITTED;
               }
           }
  my $awarded=$self->awarded($part);   my $awarded=$self->awarded($part);
  if ($awarded < 1 && $awarded > 0) {   if ($awarded < 1 && $awarded > 0) {
             return PARTIALLY_CORRECT;              return PARTIALLY_CORRECT;
Line 6000  sub status { Line 6152  sub status {
   
     if ($dateStatus == PAST_DUE_ANSWER_LATER ||      if ($dateStatus == PAST_DUE_ANSWER_LATER ||
         $dateStatus == PAST_DUE_NO_ANSWER ) {          $dateStatus == PAST_DUE_NO_ANSWER ) {
         return $suppressFeedback ? ANSWER_SUBMITTED : $dateStatus;           if ($suppressFeedback) {
               if ($completionStatus == NOT_ATTEMPTED) {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_NO_ATMT_ANS;
                   } else {
                       return PAST_DUE_NO_ATMT_NOANS;
                   }
               } else {
                   if ($dateStatus == PAST_DUE_ANSWER_LATER) {
                       return PAST_DUE_ATMPT_ANS;
                   } else {
                       return PAST_DUE_ATMPT_NOANS;
                   }
               }
           } else {
               return $dateStatus;
           }
     }      }
   
     if ($dateStatus == ANSWER_OPEN) {      if ($dateStatus == ANSWER_OPEN) {
Line 6246  my %compositeToSimple = Line 6414  my %compositeToSimple =
       EXCUSED()               => CORRECT,        EXCUSED()               => CORRECT,
       PAST_DUE_NO_ANSWER()    => INCORRECT,        PAST_DUE_NO_ANSWER()    => INCORRECT,
       PAST_DUE_ANSWER_LATER() => INCORRECT,        PAST_DUE_ANSWER_LATER() => INCORRECT,
         PAST_DUE_ATMPT_ANS()    => ATTEMPTED,
         PAST_DUE_ATMPT_NOANS()  => ATTEMPTED,
         PAST_DUE_NO_ATMT_ANS()  => CLOSED,
         PAST_DUE_NO_ATMT_NOANS() => CLOSED,
       ANSWER_OPEN()           => INCORRECT,        ANSWER_OPEN()           => INCORRECT,
       OPEN_LATER()            => CLOSED,        OPEN_LATER()            => CLOSED,
       TRIES_LEFT()            => OPEN,        TRIES_LEFT()            => OPEN,

Removed from v.1.558  
changed lines
  Added in v.1.572


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>