Diff for /loncom/interface/lonnavmaps.pm between versions 1.192 and 1.208

version 1.192, 2003/05/16 17:54:21 version 1.208, 2003/06/18 15:49:24
Line 72  my %statusIconMap = Line 72  my %statusIconMap =
       $resObj->TRIES_LEFT         => 'navmap.open.gif',        $resObj->TRIES_LEFT         => 'navmap.open.gif',
       $resObj->INCORRECT          => 'navmap.wrong.gif',        $resObj->INCORRECT          => 'navmap.wrong.gif',
       $resObj->OPEN               => 'navmap.open.gif',        $resObj->OPEN               => 'navmap.open.gif',
       $resObj->ATTEMPTED          => 'navmap.open.gif',        $resObj->ATTEMPTED          => 'navmap.ellipsis.gif',
       $resObj->ANSWER_SUBMITTED   => '' );        $resObj->ANSWER_SUBMITTED   => '' );
   
 my %iconAltTags =   my %iconAltTags = 
Line 92  my %colormap = Line 92  my %colormap =
       $resObj->TRIES_LEFT             => '',        $resObj->TRIES_LEFT             => '',
       $resObj->INCORRECT              => '',        $resObj->INCORRECT              => '',
       $resObj->OPEN                   => '',        $resObj->OPEN                   => '',
       $resObj->NOTHING_SET            => '' );        $resObj->NOTHING_SET            => '',
         $resObj->ATTEMPTED              => '',
         $resObj->ANSWER_SUBMITTED       => ''
         );
 # And a special case in the nav map; what to do when the assignment  # 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  # is not yet done and due in less then 24 hours
 my $hurryUpColor = "#FF0000";  my $hurryUpColor = "#FF0000";
Line 161  sub real_handler { Line 164  sub real_handler {
     # Now that we've displayed some stuff to the user, init the navmap      # Now that we've displayed some stuff to the user, init the navmap
     $navmap->init();      $navmap->init();
   
     $r->print('<br>&nbsp;');  
     $r->rflush();      $r->rflush();
   
     # Check that it's defined      # Check that it's defined
Line 244  sub real_handler { Line 246  sub real_handler {
         }          }
     } else {      } else {
         $r->print("<a href='navmaps?jumpToFirstHomework'>" .          $r->print("<a href='navmaps?jumpToFirstHomework'>" .
                   "Go To My First Homework Problem</a><br />");                    "Go To My First Homework Problem</a>&nbsp;&nbsp;&nbsp;&nbsp;");
     }      }
   
     my $suppressEmptySequences = 0;      my $suppressEmptySequences = 0;
     my $filterFunc = undef;      my $filterFunc = undef;
       my $resource_no_folder_link = 0;
   
     # Display only due homework.      # Display only due homework.
     my $showOnlyHomework = 0;      my $showOnlyHomework = 0;
     if ($ENV{QUERY_STRING} eq 'showOnlyHomework') {      if ($ENV{QUERY_STRING} eq 'showOnlyHomework') {
         $showOnlyHomework = 1;          $showOnlyHomework = 1;
         $suppressEmptySequences = 1;          $suppressEmptySequences = 1;
         $filterFunc = sub { my $res = shift;           $filterFunc = sub { my $res = shift; 
                             return $res->completable() || $res->is_sequence();                              return $res->completable() || $res->is_map();
                         };                          };
         $r->print("<p><font size='+2'>Uncompleted Homework</font></p>");          $r->print("<p><font size='+2'>Uncompleted Homework</font></p>");
         $ENV{'form.filter'} = '';          $ENV{'form.filter'} = '';
         $ENV{'form.condition'} = 1;          $ENV{'form.condition'} = 1;
    $resource_no_folder_link = 1;
     } else {      } else {
         $r->print("<a href='navmaps?showOnlyHomework'>" .          $r->print("<a href='navmaps?showOnlyHomework'>" .
                   "Show Only Uncompleted Homework</a><br />");                    "Show Only Uncompleted Homework</a>&nbsp;&nbsp;&nbsp;&nbsp;");
     }      }
   
     # renderer call      # renderer call
Line 272  sub real_handler { Line 277  sub real_handler {
                        'suppressNavmap' => 1,                         'suppressNavmap' => 1,
                        'suppressEmptySequences' => $suppressEmptySequences,                         'suppressEmptySequences' => $suppressEmptySequences,
                        'filterFunc' => $filterFunc,                         'filterFunc' => $filterFunc,
          'resource_no_folder_link' => $resource_no_folder_link,
                        'r' => $r};                         'r' => $r};
     my $render = render($renderArgs);      my $render = render($renderArgs);
     $navmap->untieHashes();      $navmap->untieHashes();
Line 378  sub getDescription { Line 384  sub getDescription {
         return "Excused by instructor";          return "Excused by instructor";
     }      }
     if ($status == $res->ATTEMPTED) {      if ($status == $res->ATTEMPTED) {
         return "Not yet graded.";          return "Answer submitted, not yet graded.";
     }      }
     if ($status == $res->TRIES_LEFT) {      if ($status == $res->TRIES_LEFT) {
         my $tries = $res->tries($part);          my $tries = $res->tries($part);
Line 410  sub dueInLessThen24Hours { Line 416  sub dueInLessThen24Hours {
     my $part = shift;      my $part = shift;
     my $status = $res->status($part);      my $status = $res->status($part);
   
     return ($status == $res->OPEN() || $status == $res->ATTEMPTED() ||      return ($status == $res->OPEN() ||
             $status == $res->TRIES_LEFT()) &&              $status == $res->TRIES_LEFT()) &&
            $res->duedate() && $res->duedate() < time()+(24*60*60) &&             $res->duedate() && $res->duedate() < time()+(24*60*60) &&
            $res->duedate() > time();             $res->duedate() > time();
Line 552  Apache::lonnavmap - Subroutines to handl Line 558  Apache::lonnavmap - Subroutines to handl
   
 The main handler generates the navigational listing for the course,  The main handler generates the navigational listing for the course,
 the other objects export this information in a usable fashion for  the other objects export this information in a usable fashion for
 other modules  other modules.
   
 =head1 Object: render  =head1 Subroutine: render
   
 The navmap renderer package provides a sophisticated rendering of the  The navmap renderer package provides a sophisticated rendering of the
 standard navigation maps interface into HTML. The provided nav map  standard navigation maps interface into HTML. The provided nav map
Line 568  understand then "undef, undef, undef, 1, Line 574  understand then "undef, undef, undef, 1,
 undef, 0" when you mostly want default behaviors.  undef, 0" when you mostly want default behaviors.
   
 The package provides a function called 'render', called as  The package provides a function called 'render', called as
 Apache::lonnavmaps::renderer->render({}).  Apache::lonnavmaps::render({}).
   
 =head2 Overview of Columns  =head2 Overview of Columns
   
Line 576  The renderer will build an HTML table fo Line 582  The renderer will build an HTML table fo
 it. The table is consists of several columns, and a row for each  it. The table is consists of several columns, and a row for each
 resource (or possibly each part). You tell the renderer how many  resource (or possibly each part). You tell the renderer how many
 columns to create and what to place in each column, optionally using  columns to create and what to place in each column, optionally using
 one or more of the preparent columns, and the renderer will assemble  one or more of the prepared columns, and the renderer will assemble
 the table.  the table.
   
 Any additional generally useful column types should be placed in the  Any additional generally useful column types should be placed in the
Line 594  argument hash passed to the renderer, an Line 600  argument hash passed to the renderer, an
 be inserted into the HTML representation as it.  be inserted into the HTML representation as it.
   
 The pre-packaged column names are refered to by constants in the  The pre-packaged column names are refered to by constants in the
 Apache::lonnavmaps::renderer namespace. The following currently exist:  Apache::lonnavmaps namespace. The following currently exist:
   
 =over 4  =over 4
   
Line 602  Apache::lonnavmaps::renderer namespace. Line 608  Apache::lonnavmaps::renderer namespace.
   
 The general info about the resource: Link, icon for the type, etc. The  The general info about the resource: Link, icon for the type, etc. The
 first column in the standard nav map display. This column also accepts  first column in the standard nav map display. This column also accepts
 the following parameter in the renderer hash:  the following parameters in the renderer hash:
   
 =over 4  =over 4
   
Line 835  sub render_resource { Line 841  sub render_resource {
     my $linkopen = "<a href='$link'>";      my $linkopen = "<a href='$link'>";
     my $linkclose = "</a>";      my $linkclose = "</a>";
   
     # Default icon: HTML page      # Default icon: unknown page
     my $icon = "<img src='/adm/lonIcons/html.gif' alt='' border='0' />";      my $icon = "<img src='/adm/lonIcons/unknown.gif' alt='' border='0' />";
           
     if ($resource->is_problem()) {      if ($resource->is_problem()) {
         if ($part eq '0' || $params->{'condensed'}) {          if ($part eq '0' || $params->{'condensed'}) {
Line 844  sub render_resource { Line 850  sub render_resource {
         } else {          } else {
             $icon = $params->{'indentString'};              $icon = $params->{'indentString'};
         }          }
       } else {
    my $curfext= (split (/\./,$resource->src))[-1];
    my $embstyle = &Apache::loncommon::fileembstyle($curfext);
    # The unless conditional that follows is a bit of overkill
    if (!(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn')) {
       $icon = "<img src='/adm/lonIcons/$curfext.gif' alt='' border='0' />";
    }
     }      }
   
     # Display the correct map icon to open or shut map      # Display the correct map icon to open or shut map
Line 854  sub render_resource { Line 867  sub render_resource {
             $nowOpen = !$nowOpen;              $nowOpen = !$nowOpen;
         }          }
   
    my $folderType = $resource->is_sequence() ? 'folder' : 'page';
   
         if (!$params->{'resource_no_folder_link'}) {          if (!$params->{'resource_no_folder_link'}) {
             $icon = 'navmap.folder.' . ($nowOpen ? 'closed' : 'open') . '.gif';              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
             $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";              $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";
   
             $linkopen = "<a href='" . $params->{'url'} . '?' .               $linkopen = "<a href='" . $params->{'url'} . '?' . 
Line 871  sub render_resource { Line 886  sub render_resource {
                 "&folderManip=1'>";                  "&folderManip=1'>";
         } else {          } else {
             # Don't allow users to manipulate folder              # Don't allow users to manipulate folder
             $icon = 'navmap.folder.' . ($nowOpen ? 'closed' : 'open') .              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .
                 '.nomanip.gif';                  '.nomanip.gif';
             $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";              $icon = "<img src='/adm/lonIcons/$icon' alt='' border='0' />";
   
Line 919  sub render_resource { Line 934  sub render_resource {
         $nonLinkedText .= ' (' . $resource->countParts() . ' parts)';          $nonLinkedText .= ' (' . $resource->countParts() . ' parts)';
     }      }
   
     if (!$params->{'resource_nolink'}) {      if (!$params->{'resource_nolink'} && $src !~ /^\/uploaded\// &&
    !$resource->is_sequence()) {
         $result .= "  $curMarkerBegin<a href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>";          $result .= "  $curMarkerBegin<a href='$link'>$title$partLabel</a>$curMarkerEnd $nonLinkedText</td>";
     } else {      } else {
         $result .= "  $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>";          $result .= "  $curMarkerBegin$title$partLabel$curMarkerEnd $nonLinkedText</td>";
Line 966  sub render_communication_status { Line 982  sub render_communication_status {
         }          }
     }      }
   
       if ($params->{'multipart'} && $part != '0') {
    $discussionHTML = $feedbackHTML = $errorHTML = '';
       }
   
     return "<td width=\"75\" align=\"left\" valign=\"center\">$discussionHTML$feedbackHTML$errorHTML&nbsp;</td>";      return "<td width=\"75\" align=\"left\" valign=\"center\">$discussionHTML$feedbackHTML$errorHTML&nbsp;</td>";
   
 }  }
Line 1001  sub render_long_status { Line 1021  sub render_long_status {
         $params->{'multipart'} && $part eq "0";          $params->{'multipart'} && $part eq "0";
                                   
     my $color;      my $color;
     if ($resource->is_problem() && ($resource->countParts() <= 1 || $part ne '') ) {      if ($resource->is_problem() && ($resource->countParts() <= 1) ) {
         $color = $colormap{$resource->status};          $color = $colormap{$resource->status};
                   
         if (dueInLessThen24Hours($resource, $part) ||          if (dueInLessThen24Hours($resource, $part) ||
Line 1021  sub render_long_status { Line 1041  sub render_long_status {
         $result .= '(randomly select ' . $resource->randompick() .')';          $result .= '(randomly select ' . $resource->randompick() .')';
     }      }
           
     $result .= "&nbsp;</td>\n";  
       
     return $result;      return $result;
 }  }
   
Line 1291  sub render { Line 1309  sub render {
   
             if (ref($curRes)) {               if (ref($curRes)) { 
                 # Parallel pre-processing: Do sequences have non-filtered-out children?                  # Parallel pre-processing: Do sequences have non-filtered-out children?
                 if ($curRes->is_sequence()) {                  if ($curRes->is_map()) {
                     $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0;                      $curRes->{DATA}->{HAS_VISIBLE_CHILDREN} = 0;
                     # Sequences themselves do not count as visible children,                      # Sequences themselves do not count as visible children,
                     # unless those sequences also have visible children.                      # unless those sequences also have visible children.
Line 1354  sub render { Line 1372  sub render {
         }           } 
   
         # If this is an empty sequence and we're filtering them, continue on          # If this is an empty sequence and we're filtering them, continue on
         if ($curRes->is_sequence() && $args->{'suppressEmptySequences'} &&          if ($curRes->is_map() && $args->{'suppressEmptySequences'} &&
             !$curRes->{DATA}->{HAS_VISIBLE_CHILDREN}) {              !$curRes->{DATA}->{HAS_VISIBLE_CHILDREN}) {
             next;              next;
         }          }
Line 1413  sub render { Line 1431  sub render {
                         @parts = ($parts[0]);                          @parts = ($parts[0]);
                         $args->{'condensed'} = 1;                          $args->{'condensed'} = 1;
                     }                      }
                       
                 }                  }
    # Multipart problem with one part: always "condense" (happens
    #  to match the desirable behavior)
    if ($curRes->countParts() == 1) {
       @parts = ($parts[0]);
       $args->{'condensed'} = 1;
    }
             }              }
         }           } 
                           
Line 1476  sub render { Line 1499  sub render {
         }          }
     } continue {      } continue {
         $curRes = $it->next();          $curRes = $it->next();
   
    if ($r) {
       # If we have the connection, make sure the user is still connected
       my $c = $r->connection;
       if ($c->aborted()) {
    Apache::lonnet::logthis("navmaps aborted");
    # Who cares what we do, nobody will see it anyhow.
    return '';
       }
    }
     }      }
           
     # Print out the part that jumps to #curloc if it exists      # Print out the part that jumps to #curloc if it exists
Line 1662  sub init { Line 1695  sub init {
         my %emailstatus = &Apache::lonnet::dump('email_status');          my %emailstatus = &Apache::lonnet::dump('email_status');
         my $logoutTime = $emailstatus{'logout'};          my $logoutTime = $emailstatus{'logout'};
         my $courseLeaveTime = $emailstatus{'logout_'.$ENV{'request.course.id'}};          my $courseLeaveTime = $emailstatus{'logout_'.$ENV{'request.course.id'}};
         $self->{LAST_CHECK} = ($courseLeaveTime < $logoutTime ?          $self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ?
                                $courseLeaveTime : $logoutTime);                                 $courseLeaveTime : $logoutTime);
         my %discussiontime = &Apache::lonnet::dump('discussiontimes',           my %discussiontime = &Apache::lonnet::dump('discussiontimes', 
                                                    $cdom, $cnum);                                                     $cdom, $cnum);
Line 1779  object for that resource. This method, o Line 1812  object for that resource. This method, o
 (as in the resource object) is the only proper way to obtain a  (as in the resource object) is the only proper way to obtain a
 resource object.  resource object.
   
   =item * B<getBySymb>(symb):
   
   Based on the symb of the resource, get a resource object for that
   resource. This is one of the proper ways to get a resource object.
   
   =item * B<getMapByMapPc>(map_pc):
   
   Based on the map_pc of the resource, get a resource object for
   the given map. This is one of the proper ways to get a resource object.
   
 =cut  =cut
   
 # The strategy here is to cache the resource objects, and only construct them  # The strategy here is to cache the resource objects, and only construct them
Line 1809  sub getBySymb { Line 1852  sub getBySymb {
     return $self->getById($map->map_pc() . '.' . $id);      return $self->getById($map->map_pc() . '.' . $id);
 }  }
   
   sub getByMapPc {
       my $self = shift;
       my $map_pc = shift;
       my $map_id = $self->{NAV_HASH}->{'map_id_' . $map_pc};
       $map_id = $self->{NAV_HASH}->{'ids_' . $map_id};
       return $self->getById($map_id);
   }
   
 =pod  =pod
   
 =item * B<firstResource>():  =item * B<firstResource>():
Line 2103  corresponds to where you want the iterat Line 2154  corresponds to where you want the iterat
 navmap->finishResource(). filterHash is a hash used as a set  navmap->finishResource(). filterHash is a hash used as a set
 containing strings representing the resource IDs, defaulting to  containing strings representing the resource IDs, defaulting to
 empty. Condition is a 1 or 0 that sets what to do with the filter  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  hash: If a 0, then only resources that exist IN the filterHash will be
 recursed on. If it is a 1, only resources NOT in the filterHash will  recursed on. If it is a 1, only resources NOT in the filterHash will
 be recursed on. Defaults to 0. forceTop is a boolean value. If it is  be recursed on. Defaults to 0. forceTop is a boolean value. If it is
 false (default), the iterator will only return the first level of map  false (default), the iterator will only return the first level of map
Line 2913  sub is_map { my $self=shift; return defi Line 2964  sub is_map { my $self=shift; return defi
 sub is_page {  sub is_page {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
     return ($src =~ /page$/);      return $self->navHash("is_map_", 1) && 
    $self->navHash("map_type_" . $self->map_pc()) eq 'page';
 }  }
 sub is_problem {  sub is_problem {
     my $self=shift;      my $self=shift;
Line 2923  sub is_problem { Line 2975  sub is_problem {
 sub is_sequence {  sub is_sequence {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
     return ($src =~ /sequence$/);      return $self->navHash("is_map_", 1) && 
    $self->navHash("map_type_" . $self->map_pc()) eq 'sequence';
 }  }
   
 # Private method: Shells out to the parmval in the nav map, handler parts.  # Private method: Shells out to the parmval in the nav map, handler parts.
Line 2998  sub map_type { Line 3051  sub map_type {
     return $self->navHash("map_type_$pc", 0);      return $self->navHash("map_type_$pc", 0);
 }  }
   
   
   
 #####  #####
 # Property queries  # Property queries
 #####  #####
Line 3211  sub getErrors { Line 3262  sub getErrors {
 =item * B<parts>():  =item * B<parts>():
   
 Returns a list reference containing sorted strings corresponding to  Returns a list reference containing sorted strings corresponding to
 each part of the problem. To count the number of parts, use the list  each part of the problem. Single part problems have only a part '0'.
 in a scalar context, and subtract one if greater than two. (One part  Multipart problems do not return their part '0', since they typically
 problems have a part 0. Multi-parts have a part 0, plus a part for  do not really matter. 
 each part. Filtering part 0 if you want it is up to you.)  
   
 =item * B<countParts>():  =item * B<countParts>():
   
 Returns the number of parts of the problem a student can answer. Thus,  Returns the number of parts of the problem a student can answer. Thus,
 for single part problems, returns 1. For multipart, it returns the  for single part problems, returns 1. For multipart, it returns the
 number of parts in the problem, not including psuedo-part 0. Thus,  number of parts in the problem, not including psuedo-part 0. 
 B<parts> may return an array with more parts in it then countParts  
 might lead you to believe.  
   
 =item * B<multipart>():  =item * B<multipart>():
   
 Returns true if the problem is multipart, false otherwise.  Returns true if the problem is multipart, false otherwise. Use this instead
   of countParts if all you want is multipart/not multipart.
   
 =item * B<responseType>($part):  =item * B<responseType>($part):
   
 Returns the response type of the part, without the word "response" on the  Returns the response type of the part, without the word "response" on the
 end. Example return values: 'string', 'essay', 'numeric', etc.  end. Example return values: 'string', 'essay', 'numeric', etc.
   
 =item * B<responseId>($part):  =item * B<responseIds>($part):
   
 Retreives the response ID for the given part, which may be an empty string.  Retreives the response IDs for the given part as an array reference containing
   strings naming the response IDs. This may be empty.
   
 =back  =back
   
Line 3281  sub responseType { Line 3331  sub responseType {
     return $self->{RESPONSE_TYPE}->{$part};      return $self->{RESPONSE_TYPE}->{$part};
 }  }
   
 sub responseId {  sub responseIds {
     my $self = shift;      my $self = shift;
     my $part = shift;      my $part = shift;
   

Removed from v.1.192  
changed lines
  Added in v.1.208


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