Diff for /loncom/interface/lonhelper.pm between versions 1.71 and 1.197.2.2.2.2

version 1.71, 2004/04/21 17:29:57 version 1.197.2.2.2.2, 2023/02/03 14:15:09
Line 25 Line 25
 #  #
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
 # (Page Handler  
 #  
 # (.helper handler  
 #  
   
 =pod  =pod
   
Line 68  messages, resource selections, or date q Line 64  messages, resource selections, or date q
   
 The helper tag is required to have one attribute, "title", which is the name  The helper tag is required to have one attribute, "title", which is the name
 of the helper itself, such as "Parameter helper". The helper tag may optionally  of the helper itself, such as "Parameter helper". The helper tag may optionally
 have a "requiredpriv" attribute, specifying the priviledge a user must have  have a "requiredpriv" attribute, specifying the privilege a user must have
 to use the helper, or get denied access. See loncom/auth/rolesplain.tab for  to use the helper, or get denied access. See loncom/auth/rolesplain.tab for
 useful privs. Default is full access, which is often wrong!  useful privs. You may add the modifier &S at the end of the three letter priv
   if you want to grant access to users for whom the corresponding privilege is 
   section-specific. The default is full access, which is often wrong!
   
 =head2 State tags  =head2 State tags
   
Line 85  State tags are also required to have an Line 83  State tags are also required to have an
 human name of the state, and will be displayed as the header on top of   human name of the state, and will be displayed as the header on top of 
 the screen for the user.  the screen for the user.
   
   State tags may also optionally have an attribute "help" which should be
   the filename of a help file, this will add a blue ? to the title.
   
 =head2 Example Helper Skeleton  =head2 Example Helper Skeleton
   
 An example of the tags so far:  An example of the tags so far:
   
  <helper title="Example Helper">   <helper title="Example Helper">
    <state name="START" title="Demonstrating the Example Helper">     <state name="START" title="Demonstrating the Example Helper">
      <!-- notice this is the START state the wizard requires -->       <!-- notice this is the START state the helper requires -->
      </state>       </state>
    <state name="GET_NAME" title="Enter Student Name">     <state name="GET_NAME" title="Enter Student Name">
      </state>       </state>
    </helper>     </helper>
   
 Of course this does nothing. In order for the wizard to do something, it is  Of course this does nothing. In order for the helper to do something, it is
 necessary to put actual elements into the wizard. Documentation for each  necessary to put actual elements into the helper. Documentation for each
 of these elements follows.  of these elements follows.
   
 =head1 Creating a Helper With Code, Not XML  =head1 Creating a Helper With Code, Not XML
   
 In some situations, such as the printing wizard (see lonprintout.pm),   In some situations, such as the printing helper (see lonprintout.pm), 
 writing the helper in XML would be too complicated, because of scope   writing the helper in XML would be too complicated, because of scope 
 issues or the fact that the code actually outweighs the XML. It is  issues or the fact that the code actually outweighs the XML. It is
 possible to create a helper via code, though it is a little odd.  possible to create a helper via code, though it is a little odd.
Line 186  use Apache::Constants qw(:common); Line 187  use Apache::Constants qw(:common);
 use Apache::File;  use Apache::File;
 use Apache::lonxml;  use Apache::lonxml;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   use Apache::longroup;
   use Apache::lonselstudent;
   
   
   use LONCAPA;
   
 # Register all the tags with the helper, so the helper can   # Register all the tags with the helper, so the helper can 
 # push and pop them  # push and pop them
Line 255  sub real_handler { Line 262  sub real_handler {
     my $r = shift;      my $r = shift;
     my $uri = shift;      my $uri = shift;
     if (!defined($uri)) { $uri = $r->uri(); }      if (!defined($uri)) { $uri = $r->uri(); }
     $ENV{'request.uri'} = $uri;      $env{'request.uri'} = $uri;
     my $filename = '/home/httpd/html' . $uri;      my $filename = $r->dir_config('lonDocRoot').$uri;
     my $fh = Apache::File->new($filename);      my $fh = Apache::File->new($filename);
     my $file;      my $file;
     read $fh, $file, 100000000;      read $fh, $file, 100000000;
   
   
     # Send header, don't cache this page      # Send header, don't cache this page
     if ($ENV{'browser.mathml'}) {      if ($env{'browser.mathml'}) {
  &Apache::loncommon::content_type($r,'text/xml');   &Apache::loncommon::content_type($r,'text/xml');
     } else {      } else {
  &Apache::loncommon::content_type($r,'text/html');   &Apache::loncommon::content_type($r,'text/html');
Line 278  sub real_handler { Line 285  sub real_handler {
   
     my $allowed = $helper->allowedCheck();      my $allowed = $helper->allowedCheck();
     if (!$allowed) {      if (!$allowed) {
         $ENV{'user.error.msg'} = $ENV{'request.uri'}.':'.$helper->{REQUIRED_PRIV}.          my ($priv,$modifier) = split(/\&/,$helper->{REQUIRED_PRIV});
           $env{'user.error.msg'} = $env{'request.uri'}.':'.$priv.
             ":0:0:Permission denied to access this helper.";              ":0:0:Permission denied to access this helper.";
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
Line 334  sub start_state { Line 342  sub start_state {
     }      }
   
     Apache::lonhelper::state->new($token->[2]{'name'},      Apache::lonhelper::state->new($token->[2]{'name'},
                                   $token->[2]{'title'});                                    $token->[2]{'title'},
     $token->[2]{'help'});
     return '';      return '';
 }  }
   
Line 363  use HTML::Entities(); Line 372  use HTML::Entities();
 use Apache::loncommon;  use Apache::loncommon;
 use Apache::File;  use Apache::File;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   use LONCAPA;
   
 sub new {  sub new {
     my $proto = shift;      my $proto = shift;
Line 374  sub new { Line 385  sub new {
           
     # If there is a state from the previous form, use that. If there is no      # If there is a state from the previous form, use that. If there is no
     # state, use the start state parameter.      # state, use the start state parameter.
     if (defined $ENV{"form.CURRENT_STATE"})      if (defined $env{"form.CURRENT_STATE"})
     {      {
  $self->{STATE} = $ENV{"form.CURRENT_STATE"};   $self->{STATE} = $env{"form.CURRENT_STATE"};
     }      }
     else      else
     {      {
  $self->{STATE} = "START";   $self->{STATE} = "START";
     }      }
   
     $self->{TOKEN} = $ENV{'form.TOKEN'};      $self->{TOKEN} = $env{'form.TOKEN'};
     # If a token was passed, we load that in. Otherwise, we need to create a       # If a token was passed, we load that in. Otherwise, we need to create a 
     # new storage file      # new storage file
     # Tried to use standard Tie'd hashes, but you can't seem to take a       # Tried to use standard Tie'd hashes, but you can't seem to take a 
Line 416  sub new { Line 427  sub new {
             return undef;              return undef;
         }          }
         # Must create the storage          # Must create the storage
         $self->{TOKEN} = md5_hex($ENV{'user.name'} . $ENV{'user.domain'} .          $self->{TOKEN} = md5_hex($env{'user.name'} . $env{'user.domain'} .
                                  time() . rand());                                   time() . rand());
         $self->{FILENAME} = $Apache::lonnet::tmpdir . md5_hex($self->{TOKEN});          $self->{FILENAME} = $Apache::lonnet::tmpdir . md5_hex($self->{TOKEN});
     }      }
   
     # OK, we now have our persistent storage.      # OK, we now have our persistent storage.
   
     if (defined $ENV{"form.RETURN_PAGE"})      if (defined $env{"form.RETURN_PAGE"})
     {      {
  $self->{RETURN_PAGE} = $ENV{"form.RETURN_PAGE"};   $self->{RETURN_PAGE} = $env{"form.RETURN_PAGE"};
     }      }
     else      else
     {      {
Line 468  sub _saveVars { Line 479  sub _saveVars {
 sub _varsInFile {  sub _varsInFile {
     my $self = shift;      my $self = shift;
     my @vars = ();      my @vars = ();
     for my $key (keys %{$self->{VARS}}) {      for my $key (keys(%{$self->{VARS}})) {
         push @vars, &Apache::lonnet::escape($key) . '=' .          push(@vars, &escape($key) . '=' . &escape($self->{VARS}->{$key}));
             &Apache::lonnet::escape($self->{VARS}->{$key});  
     }      }
     return join ('&', @vars);      return join ('&', @vars);
 }  }
Line 485  sub declareVar { Line 495  sub declareVar {
         $self->{VARS}->{$var} = '';          $self->{VARS}->{$var} = '';
     }      }
   
     my $envname = 'form.' . $var . '.forminput';      my $envname = 'form.' . $var . '_forminput';
     if (defined($ENV{$envname})) {      if (defined($env{$envname})) {
         if (ref($ENV{$envname})) {          if (ref($env{$envname})) {
             $self->{VARS}->{$var} = join('|||', @{$ENV{$envname}});              $self->{VARS}->{$var} = join('|||', @{$env{$envname}});
         } else {          } else {
             $self->{VARS}->{$var} = $ENV{$envname};              $self->{VARS}->{$var} = $env{$envname};
         }          }
     }      }
 }  }
Line 501  sub allowedCheck { Line 511  sub allowedCheck {
     if (!defined($self->{REQUIRED_PRIV})) {       if (!defined($self->{REQUIRED_PRIV})) { 
         return 1;          return 1;
     }      }
       my ($priv,$modifier) = split(/\&/,$self->{REQUIRED_PRIV});
     return Apache::lonnet::allowed($self->{REQUIRED_PRIV}, $ENV{'request.course.id'});      my $allowed = &Apache::lonnet::allowed($priv,$env{'request.course.id'});
       if ((!$allowed) && ($modifier eq 'S') && ($env{'request.course.sec'} ne '')) {
           $allowed = &Apache::lonnet::allowed($priv,$env{'request.course.id'}.'/'.
                                                     $env{'request.course.sec'});
       }
       return $allowed;
 }  }
   
 sub changeState {  sub changeState {
Line 524  sub process { Line 539  sub process {
     # Phase 1: Post processing for state of previous screen (which is actually      # Phase 1: Post processing for state of previous screen (which is actually
     # the "current state" in terms of the helper variables), if it wasn't the       # the "current state" in terms of the helper variables), if it wasn't the 
     # beginning state.      # beginning state.
     if ($self->{STATE} ne "START" || $ENV{"form.SUBMIT"} eq &mt("Next ->")) {      if ($self->{STATE} ne "START" || $env{"form.SUBMIT"} eq &mt("Next")) {
  my $prevState = $self->{STATES}{$self->{STATE}};   my $prevState = $self->{STATES}{$self->{STATE}};
         $prevState->postprocess();          $prevState->postprocess();
     }      }
Line 564  sub process { Line 579  sub process {
 # 4: Render the current state to the screen as an HTML page.  # 4: Render the current state to the screen as an HTML page.
 sub display {  sub display {
     my $self = shift;      my $self = shift;
       my $footer = shift;
     my $state = $self->{STATES}{$self->{STATE}};      my $state = $self->{STATES}{$self->{STATE}};
   
     my $result = "";      my $result = "";
Line 576  sub display { Line 591  sub display {
   
     # Phase 4: Display.      # Phase 4: Display.
     my $stateTitle=&mt($state->title());      my $stateTitle=&mt($state->title());
     my $helperTitle = &mt($self->{TITLE});      my $stateHelp=     $state->help();
     my $bodytag = &Apache::loncommon::bodytag($helperTitle,'','');      my $browser_searcher_js = 
     my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"');   '<script type="text/javascript">'."\n".
     my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"');   &Apache::loncommon::browser_and_searcher_javascript().
     # FIXME: This should be parameterized, not concatenated - Jeremy   "\n".'</script>';
     my $loncapaHelper = &mt("LON-CAPA Helper:");  
       # Breadcrumbs
       my $brcrum = [{'href' => '',
                      'text' => 'Helper'}];
       # FIXME: Dynamically add context sensitive breadcrumbs
       #        depending on the caller,
       #        e.g. printing, parametrization, etc.
       # FIXME: Add breadcrumbs to reflect current helper state
   
       $result .= &Apache::loncommon::start_page($self->{TITLE},
                                                 $browser_searcher_js,
                                                 {'bread_crumbs' => $brcrum,});
   
     $result .= <<HEADER;      my $previous = HTML::Entities::encode(&mt("Back"), '<>&"');
 <html>      my $next = HTML::Entities::encode(&mt("Next"), '<>&"');
 <script type="text/javascript" language="Javascript" >      # FIXME: This should be parameterized, not concatenated - Jeremy
     var editbrowser;  
     function openbrowser(formname,elementname,only,omit) {  
         var url = '/res/?';  
         if (editbrowser == null) {  
             url += 'launch=1&';  
         }  
         url += 'catalogmode=interactive&';  
         url += 'mode=parmset&';  
         url += 'form=' + formname + '&';  
         if (only != null) {  
             url += 'only=' + only + '&';  
         }   
         if (omit != null) {  
             url += 'omit=' + omit + '&';  
         }  
         url += 'element=' + elementname + '';  
         var title = 'Browser';  
         var options = 'scrollbars=1,resizable=1,menubar=0';  
         options += ',width=700,height=600';  
         editbrowser = open(url,title,options,'1');  
         editbrowser.focus();  
     }  
 </script>  
     <head>  
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />  
         <title>$loncapaHelper: $helperTitle</title>  
     </head>  
     $bodytag  
 HEADER  
     if (!$state->overrideForm()) { $result.="<form name='helpform' method='POST'>"; }  
     $result .= <<HEADER;  
         <table border="0" width='100%'><tr><td>  
         <h2><i>$stateTitle</i></h2>  
 HEADER  
   
     $result .= "<table cellpadding='10' width='100%'><tr><td rowspan='2' valign='top'>";  
   
     if (!$state->overrideForm()) {      if (!$state->overrideForm()) { $result.='<form name="helpform" method="post" action="">'; }
         $result .= $self->_saveVars();      if ($stateHelp) {
           $stateHelp = &Apache::loncommon::help_open_topic($stateHelp);
     }      }
     $result .= $state->render();  
   
     $result .= "</td><td valign='top' align='right'>";  
   
     # Warning: Copy and pasted from below, because it's too much trouble to       # Prepare buttons
     # turn this into a subroutine      my $buttons;
     if (!$state->overrideForm()) {      if (!$state->overrideForm()) {
         if ($self->{STATE} ne $self->{START_STATE}) {          if ($self->{STATE} ne $self->{START_STATE}) {
             #$result .= '<input name="SUBMIT" type="submit" value="&lt;- Previous" />&nbsp;&nbsp;';              #$result .= '<input name="SUBMIT" type="submit" value="&lt;- Previous" />&nbsp;&nbsp;';
         }          }
           $buttons = '<p>'; # '<fieldset>';
         if ($self->{DONE}) {          if ($self->{DONE}) {
             my $returnPage = $self->{RETURN_PAGE};              my $returnPage = $self->{RETURN_PAGE};
             $result .= "<a href=\"$returnPage\">" . &mt("End Helper") . "</a>";              $buttons .= '<a href="'.$returnPage.'">'.&mt('End Helper').'</a>';
         }          }
         else {          else {
             $result .= '<nobr><input name="back" type="button" ';              $buttons .= '<span class="LC_nobreak">'
             $result .= 'value="' . $previous . '" onclick="history.go(-1)" /> ';                         .'<input name="back" type="button" '
             $result .= '<input name="SUBMIT" type="submit" value="' . $next . '" /></nobr>';                         .'value="'.$previous.'" onclick="history.go(-1)" /> '
                          .'<input name="SUBMIT" type="submit" value="'.$next.'" />'
                          .'</span>';
         }          }
       $buttons .= '</p>'; # '</fieldset>';
     }      }
   
     $result .= "</td></tr><tr><td valign='bottom' align='right'>";  
   
     # Warning: Copy and pasted from above, because it's too much trouble to   
     # turn this into a subroutine      $result .= '<h2>'.$stateTitle.$stateHelp.'</h2>';
   
   #   $result .= '<div>';
   
       # Top buttons
       $result .= $buttons;
   
       # Main content of current helper screen
     if (!$state->overrideForm()) {      if (!$state->overrideForm()) {
         if ($self->{STATE} ne $self->{START_STATE}) {          $result .= $self->_saveVars();
             #$result .= '<input name="SUBMIT" type="submit" value="&lt;- Previous" />&nbsp;&nbsp;';  
         }  
         if ($self->{DONE}) {  
             my $returnPage = $self->{RETURN_PAGE};  
             $result .= "<a href=\"$returnPage\">" . &mt('End Helper') . "</a>";  
         }  
         else {  
             $result .= '<nobr><input name="back" type="button" ';  
             $result .= 'value="' . $previous . '" onclick="history.go(-1)" /> ';  
             $result .= '<input name="SUBMIT" type="submit" value="' . $next . '" /></nobr>';  
         }  
     }      }
       $result .= $state->render();
   
     #foreach my $key (keys %{$self->{VARS}}) {      # Bottom buttons
       $result .= $buttons;
   
   
       #foreach my $key (keys(%{$self->{VARS}})) {
     #    $result .= "|$key| -> " . $self->{VARS}->{$key} . "<br />";      #    $result .= "|$key| -> " . $self->{VARS}->{$key} . "<br />";
     #}      #}
   
     $result .= "</td></tr></table>";  #   $result .= '</div>';
   
     $result .= <<FOOTER;      $result .= <<FOOTER;
               </td>  
             </tr>  
           </table>  
         </form>          </form>
     </body>  
 </html>  
 FOOTER  FOOTER
   
       $result .= $footer.&Apache::loncommon::end_page();
     # Handle writing out the vars to the file      # Handle writing out the vars to the file
     my $file = Apache::File->new('>'.$self->{FILENAME});      my $file = Apache::File->new('>'.$self->{FILENAME});
     print $file $self->_varsInFile();      print $file $self->_varsInFile();
Line 706  sub new { Line 695  sub new {
   
     $self->{NAME} = shift;      $self->{NAME} = shift;
     $self->{TITLE} = shift;      $self->{TITLE} = shift;
       $self->{HELP} = shift;
     $self->{ELEMENTS} = [];      $self->{ELEMENTS} = [];
   
     bless($self, $class);      bless($self, $class);
Line 727  sub title { Line 717  sub title {
     return $self->{TITLE};      return $self->{TITLE};
 }  }
   
   sub help {
       my $self = shift;
       return $self->{HELP};
   }
   
 sub preprocess {  sub preprocess {
     my $self = shift;      my $self = shift;
     for my $element (@{$self->{ELEMENTS}}) {      for my $element (@{$self->{ELEMENTS}}) {
Line 818  the element. How this value is interpret Line 813  the element. How this value is interpret
 the element itself, and possibly the settings the element has (such as   the element itself, and possibly the settings the element has (such as 
 multichoice vs. single choice for <choices> tags).   multichoice vs. single choice for <choices> tags). 
   
 This is also intended for things like the course initialization wizard, where the  This is also intended for things like the course initialization helper, where the
 user is setting various parameters. By correctly grabbing current settings   user is setting various parameters. By correctly grabbing current settings 
 and including them into the helper, it allows the user to come back to the  and including them into the helper, it allows the user to come back to the
 helper later and re-execute it, without needing to worry about overwriting  helper later and re-execute it, without needing to worry about overwriting
Line 1020  sub start_message { Line 1015  sub start_message {
     if (defined($token->[2]{'nextstate'})) {      if (defined($token->[2]{'nextstate'})) {
         $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};          $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
     }      }
       if (defined($token->[2]{'type'})) {
           $paramHash->{TYPE} = $token->[2]{'type'};
       }
     return '';      return '';
 }  }
   
Line 1035  sub end_message { Line 1033  sub end_message {
   
 sub render {  sub render {
     my $self = shift;      my $self = shift;
       
     return &mtn($self->{MESSAGE_TEXT});      if ($self->{TYPE} =~ /^\s*warning\s*$/i) {
    $self->{MESSAGE_TEXT} = 
        '<span class="LC_warning">'. $self->{MESSAGE_TEXT}.'</span>';
       }
       if ($self->{TYPE} =~ /^\s*error\s*$/i) {
    $self->{MESSAGE_TEXT} = 
        '<span class="LC_error">'. $self->{MESSAGE_TEXT}.'</span>';
       }
       return $self->{MESSAGE_TEXT};
 }  }
 # If a NEXTSTATE was given, switch to it  # If a NEXTSTATE was given, switch to it
 sub postprocess {  sub postprocess {
Line 1049  sub postprocess { Line 1055  sub postprocess {
 }  }
 1;  1;
   
   package Apache::lonhelper::helpicon;
   
   =pod
   
   =head1 Elements
   
   =head2 Element: helpiconX<helpicon, helper element>
   
   Helpicon elements add a help icon at the current location.
   Example:
   
      <helpicon file="Help">
        General Help
      </helpicon>
   
   In this example will generate a help icon to the Help.hlp url with a
   description of 'General Help'. The description is not required and if
   left out (Example: <helpicon file="Help" /> only the icon will be
   added.)
   
   =head3 Localization
   
   The description text will be run through the normalize_string function
   and that will be used as a call to &mt.
   
   =cut
   
   no strict;
   @ISA = ("Apache::lonhelper::element");
   use strict;
   use Apache::lonlocal;
   
   BEGIN {
       &Apache::lonhelper::register('Apache::lonhelper::helpicon',
    ('helpicon'));
   }
   
   sub new {
       my $ref = Apache::lonhelper::element->new();
       bless($ref);
   }
   
   # CONSTRUCTION: Construct the message element from the XML
   sub start_helpicon {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
   
       $paramHash->{HELP_TEXT} = &mtn(&Apache::lonxml::get_all_text('/helpicon',
    $parser));
   
       $paramHash->{HELP_TEXT} =~s/^\s+//;
       $paramHash->{HELP_TEXT} =~s/\s+$//;
   
       if (defined($token->[2]{'file'})) {
           $paramHash->{HELP_FILE} = $token->[2]{'file'};
       }
       return '';
   }
   
   sub end_helpicon {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       Apache::lonhelper::helpicon->new();
       return '';
   }
   
   sub render {
       my $self = shift;
   
       my $text;
       if ( $self->{HELP_TEXT} ne '') {
    $text=&mtn($self->{HELP_TEXT});
       }
   
       return &Apache::loncommon::help_open_topic($self->{HELP_FILE},
          $text);
   }
   sub postprocess {
       my $self = shift;
       if (defined($self->{NEXTSTATE})) {
           $helper->changeState($self->{NEXTSTATE});
       }
   
       return 1;
   }
   
   1;
   
   package Apache::lonhelper::skip;
   
   =pod
   
   =head1 Elements
   
   =head2 Element: skipX<skip>
   
   The <skip> tag allows you define conditions under which the current state 
   should be skipped over and define what state to skip to.
   
     <state name="SKIP">
       <skip>
          <clause>
            #some code that decides whether to skip the state or not
          </clause>
          <nextstate>FINISH</nextstate>
       </skip>
       <message nextstate="FINISH">A possibly skipped state</message>
     </state>
   
   =cut
   
   no strict;
   @ISA = ("Apache::lonhelper::element");
   use strict;
   
   BEGIN {
       &Apache::lonhelper::register('Apache::lonhelper::skip',
    ('skip'));
   }
   
   sub new {
       my $ref = Apache::lonhelper::element->new();
       bless($ref);
   }
   
   sub start_skip {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       # let <cluase> know what text to skip to
       $paramHash->{SKIPTAG}='/skip';
       return '';
   }
   
   sub end_skip {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       Apache::lonhelper::skip->new();
       return '';
   }
   
   sub render {
       my $self = shift;
       return '';
   }
   # If a NEXTSTATE is set, switch to it
   sub preprocess {
       my ($self) = @_;
   
       if (defined($self->{NEXTSTATE})) {
           $helper->changeState($self->{NEXTSTATE});
       }
   
       return 1;
   }
   
   1;
   
 package Apache::lonhelper::choices;  package Apache::lonhelper::choices;
   
 =pod  =pod
Line 1098  will be the state transistioned to if th Line 1273  will be the state transistioned to if th
 the choice is not multichoice. This will override the nextstate  the choice is not multichoice. This will override the nextstate
 passed to the parent C<choices> tag.  passed to the parent C<choices> tag.
   
   <choice> may optionally contain a 'relatedvalue' attribute, which
   if present will cause a text entry to appear to the right of the
   selection.  The value of the relatedvalue attribute is a variable
   into which the text entry will be stored e.g.:
   <choice computer='numberprovided" relatedvalue="num">Type the number in:</choice>
   
   <choice> may contain a relatededefault atribute which, if the
   relatedvalue attribute is present will be the initial value of the input
   box.
   
 =back  =back
   
 To create the choices programmatically, either wrap the choices in   To create the choices programmatically, either wrap the choices in 
Line 1139  no strict; Line 1324  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::choices',      &Apache::lonhelper::register('Apache::lonhelper::choices',
Line 1187  sub start_choice { Line 1373  sub start_choice {
     my $computer = $token->[2]{'computer'};      my $computer = $token->[2]{'computer'};
     my $human = &mt(&Apache::lonxml::get_all_text('/choice',      my $human = &mt(&Apache::lonxml::get_all_text('/choice',
                                               $parser));                                                $parser));
     my $nextstate = $token->[2]{'nextstate'};      my $nextstate  = $token->[2]{'nextstate'};
     my $evalFlag = $token->[2]{'eval'};      my $evalFlag   = $token->[2]{'eval'};
     push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate,       my $relatedVar = $token->[2]{'relatedvalue'}; 
                                     $evalFlag];      my $relatedDefault = $token->[2]{'relateddefault'};
       push @{$paramHash->{CHOICES}}, [&mtn($human), $computer, $nextstate, 
                                       $evalFlag, $relatedVar, $relatedDefault];
     return '';      return '';
 }  }
   
Line 1198  sub end_choice { Line 1386  sub end_choice {
     return '';      return '';
 }  }
   
   {
       # used to generate unique id attributes for <input> tags. 
       # internal use only.
       my $id = 0;
       sub new_id { return $id++; }
   }
   
 sub render {  sub render {
     my $self = shift;      my $self = shift;
     my $var = $self->{'variable'};      my $var = $self->{'variable'};
Line 1206  sub render { Line 1401  sub render {
   
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result .= <<SCRIPT;          $result .= <<SCRIPT;
 <script>  <script type="text/javascript">
   // <!--
     function checkall(value, checkName) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.helpform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             ele = document.forms.helpform.elements[i];              ele = document.forms.helpform.elements[i];
             if (ele.name == checkName + '.forminput') {              if (ele.name == checkName + '_forminput') {
                 document.forms.helpform.elements[i].checked=value;                  document.forms.helpform.elements[i].checked=value;
             }              }
         }          }
     }      }
   // -->
 </script>  </script>
 SCRIPT  SCRIPT
     }      }
Line 1280  BUTTONS Line 1477  BUTTONS
     my $type = "radio";      my $type = "radio";
     if ($self->{'multichoice'}) { $type = 'checkbox'; }      if ($self->{'multichoice'}) { $type = 'checkbox'; }
     foreach my $choice (@{$self->{CHOICES}}) {      foreach my $choice (@{$self->{CHOICES}}) {
           my $id = &new_id();
         $result .= "<tr>\n<td width='20'>&nbsp;</td>\n";          $result .= "<tr>\n<td width='20'>&nbsp;</td>\n";
         $result .= "<td valign='top'><input type='$type' name='$var.forminput'"          $result .= "<td valign='top'><input type='$type' name='${var}_forminput'"
             . "' value='" .               . " value='" . 
             HTML::Entities::encode($choice->[1],'<>&"')               HTML::Entities::encode($choice->[1],"<>&\"'") 
             . "'";              . "'";
         if ($checkedChoices{$choice->[1]}) {          if ($checkedChoices{$choice->[1]}) {
             $result .= " checked ";              $result .= " checked='checked'";
         }          }
           $result .= qq{ id="id$id"};
         my $choiceLabel = $choice->[0];          my $choiceLabel = $choice->[0];
         if ($choice->[4]) {  # if we need to evaluate this choice          if ($choice->[3]) {  # if we need to evaluate this choice
             $choiceLabel = "sub { my $helper = shift; my $state = shift;" .              $choiceLabel = "sub { my $helper = shift; my $state = shift;" .
                 $choiceLabel . "}";                  $choiceLabel . "}";
             $choiceLabel = eval($choiceLabel);              $choiceLabel = eval($choiceLabel);
             $choiceLabel = &$choiceLabel($helper, $self);              $choiceLabel = &$choiceLabel($helper, $self);
         }          }
  &Apache::lonnet::logthis("TITLE TRANSLATION >$choiceLabel<");          $result .= " /></td><td> ".qq{<label for="id$id">}.
         $result .= "/></td><td> " . &mtn($choiceLabel) . "</td></tr>\n";      $choiceLabel. "</label></td>";
    if ($choice->[4]) {
       $result .='<td><input type="text" size="5" name="'
    .$choice->[4].'_forminput" value="'
                   .$choice->[5].'" /></td>';
    }
    $result .= "</tr>\n";
     }      }
     $result .= "</table>\n\n\n";      $result .= "</table>\n\n\n";
     $result .= $buttons;      $result .= $buttons;
Line 1308  BUTTONS Line 1513  BUTTONS
 # given, switch to it  # given, switch to it
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
     my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'};      my $chosenValue = $env{'form.' . $self->{'variable'} . '_forminput'};
   
   
     if (!defined($chosenValue) && !$self->{'allowempty'}) {      if (!defined($chosenValue) && !$self->{'allowempty'}) {
         $self->{ERROR_MSG} =           $self->{ERROR_MSG} = 
Line 1316  sub postprocess { Line 1522  sub postprocess {
         return 0;          return 0;
     }      }
   
   
   
     if (ref($chosenValue)) {      if (ref($chosenValue)) {
         $helper->{VARS}->{$self->{'variable'}} = join('|||', @$chosenValue);          $helper->{VARS}->{$self->{'variable'}} = join('|||', @$chosenValue);
     }      }
Line 1330  sub postprocess { Line 1538  sub postprocess {
                 $helper->changeState($choice->[2]);                  $helper->changeState($choice->[2]);
             }              }
         }          }
    if ($choice->[4]) {
       my $varname = $choice->[4];
       $helper->{'VARS'}->{$varname} = $env{'form.'."${varname}_forminput"};
    }
     }      }
     return 1;      return 1;
 }  }
Line 1362  no strict; Line 1574  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::dropdown',      &Apache::lonhelper::register('Apache::lonhelper::dropdown',
Line 1436  sub render { Line 1649  sub render {
  $checkedChoices{$self->{CHOICES}->[0]->[1]} = 1;   $checkedChoices{$self->{CHOICES}->[0]->[1]} = 1;
     }      }
   
     $result .= "<select name='${var}.forminput'>\n";      $result .= "<select name='${var}_forminput'>\n";
     foreach my $choice (@{$self->{CHOICES}}) {      foreach my $choice (@{$self->{CHOICES}}) {
         $result .= "<option value='" .           $result .= "<option value='" . 
             HTML::Entities::encode($choice->[1],'<>&"')               HTML::Entities::encode($choice->[1],"<>&\"'") 
             . "'";              . "'";
         if ($checkedChoices{$choice->[1]}) {          if ($checkedChoices{$choice->[1]}) {
             $result .= " selected";              $result .= " selected='selected' ";
         }          }
         my $choiceLabel = $choice->[0];          my $choiceLabel = $choice->[0];
         if ($choice->[4]) {  # if we need to evaluate this choice          if ($choice->[4]) {  # if we need to evaluate this choice
Line 1451  sub render { Line 1664  sub render {
             $choiceLabel = eval($choiceLabel);              $choiceLabel = eval($choiceLabel);
             $choiceLabel = &$choiceLabel($helper, $self);              $choiceLabel = &$choiceLabel($helper, $self);
         }          }
         $result .= ">" . &mtn($choiceLabel) . "\n";          $result .= ">" . &mtn($choiceLabel) . "</option>\n";
     }      }
     $result .= "</select>\n";      $result .= "</select>\n";
   
Line 1462  sub render { Line 1675  sub render {
 # given, switch to it  # given, switch to it
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
     my $chosenValue = $ENV{'form.' . $self->{'variable'} . '.forminput'};      my $chosenValue = $env{'form.' . $self->{'variable'} . '_forminput'};
   
     if (!defined($chosenValue) && !$self->{'allowempty'}) {      if (!defined($chosenValue) && !$self->{'allowempty'}) {
         $self->{ERROR_MSG} = "You must choose one or more choices to" .          $self->{ERROR_MSG} = "You must choose one or more choices to" .
Line 1521  no strict; Line 1734  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal; # A localization nightmare  use Apache::lonlocal; # A localization nightmare
   use Apache::lonnet;
 use Time::localtime;  use DateTime;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::date',      &Apache::lonhelper::register('Apache::lonhelper::date',
Line 1549  sub start_date { Line 1762  sub start_date {
     $paramHash->{'variable'} = $token->[2]{'variable'};      $paramHash->{'variable'} = $token->[2]{'variable'};
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
     $paramHash->{'hoursminutes'} = $token->[2]{'hoursminutes'};      $paramHash->{'hoursminutes'} = $token->[2]{'hoursminutes'};
       $paramHash->{'anytime'} = $token->[2]{'anytime'};
 }  }
   
 sub end_date {  sub end_date {
Line 1567  sub render { Line 1781  sub render {
     my $var = $self->{'variable'};      my $var = $self->{'variable'};
   
     my $date;      my $date;
       
       my $time=time;
       my ($anytime,$onclick);
   
       # first check VARS for a valid new value from the user
       # then check DEFAULT_VALUE for a valid default time value
       # otherwise pick now as reasonably good time
   
       if (defined($helper->{VARS}{$var})
    &&  $helper->{VARS}{$var} > 0) {
           $date = &get_date_object($helper->{VARS}{$var}); 
       } elsif (defined($self->{DEFAULT_VALUE})) {
           my $valueFunc = eval($self->{DEFAULT_VALUE});
           die('Error in default value code for variable ' . 
               $self->{'variable'} . ', Perl said: ' . $@) if $@;
           $time = &$valueFunc($helper, $self);
    if (lc($time) eq 'anytime') {
       $anytime=1;
       $date = &get_date_object(time);
               $date->set_minute(0)
    } elsif (defined($time) && $time ne 0) {
       $date = &get_date_object($time);
    } else {
       # leave date undefined so it'll default to now
    }
       }
   
       if (!defined($date)) {
    $date = &get_date_object(time);
           $date->set_minute(0);
       }
   
       if ($anytime) {
    $onclick = "onclick=\"javascript:updateCheck(this.form,'${var}anytime',false)\"";
       }
     # Default date: The current hour.      # Default date: The current hour.
     $date = localtime();  
     $date->min(0);  
   
     if (defined $self->{ERROR_MSG}) {      if (defined $self->{ERROR_MSG}) {
         $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';          $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';
Line 1578  sub render { Line 1824  sub render {
   
     # Month      # Month
     my $i;      my $i;
     $result .= "<select name='${var}month'>\n";      $result .= "<select $onclick name='${var}month'>\n";
     for ($i = 0; $i < 12; $i++) {      for ($i = 0; $i < 12; $i++) {
         if ($i == $date->mon) {          if (($i + 1) == $date->mon) {
             $result .= "<option value='$i' selected>";              $result .= "<option value='$i' selected='selected'>";
         } else {          } else {
             $result .= "<option value='$i'>";              $result .= "<option value='$i'>";
         }          }
         $result .= &mt($months[$i]) . "</option>\n";          $result .= &mt($months[$i])."</option>\n";
     }      }
     $result .= "</select>\n";      $result .= "</select>\n";
   
     # Day      # Day
     $result .= "<select name='${var}day'>\n";      $result .= "<select $onclick name='${var}day'>\n";
     for ($i = 1; $i < 32; $i++) {      for ($i = 1; $i < 32; $i++) {
         if ($i == $date->mday) {          if ($i == $date->mday) {
             $result .= '<option selected>';              $result .= '<option selected="selected">';
         } else {          } else {
             $result .= '<option>';              $result .= '<option>';
         }          }
Line 1602  sub render { Line 1848  sub render {
     $result .= "</select>,\n";      $result .= "</select>,\n";
   
     # Year      # Year
     $result .= "<select name='${var}year'>\n";      $result .= "<select $onclick name='${var}year'>\n";
     for ($i = 2000; $i < 2030; $i++) { # update this after 64-bit dates      for ($i = 2000; $i < 2030; $i++) { # update this after 64-bit dates
         if ($date->year + 1900 == $i) {          if ($date->year == $i) {
             $result .= "<option selected>";              $result .= "<option selected='selected'>";
         } else {          } else {
             $result .= "<option>";              $result .= "<option>";
         }          }
Line 1619  sub render { Line 1865  sub render {
  my $am = &mt('a.m.');   my $am = &mt('a.m.');
  my $pm = &mt('p.m.');   my $pm = &mt('p.m.');
         # Build hour          # Build hour
         $result .= "<select name='${var}hour'>\n";          $result .= "<select $onclick name='${var}hour'>\n";
         $result .= "<option " . ($date->hour == 0 ? 'selected ':'') .          $result .= "<option " . ($date->hour == 0 ? 'selected="selected" ':'') .
             " value='0'>" . &mt('midnight') . "</option>\n";              " value='0'>" . &mt('midnight') . "</option>\n";
         for ($i = 1; $i < 12; $i++) {          for ($i = 1; $i < 12; $i++) {
             if ($date->hour == $i) {              if ($date->hour == $i) {
                 $result .= "<option selected value='$i'>$i $am</option>\n";                  $result .= "<option selected='selected' value='$i'>$i $am</option>\n";
             } else {              } else {
                 $result .= "<option value='$i'>$i $am</option>\n";                  $result .= "<option value='$i'>$i $am</option>\n";
             }              }
         }          }
         $result .= "<option " . ($date->hour == 12 ? 'selected ':'') .          $result .= "<option " . ($date->hour == 12 ? 'selected="selected" ':'') .
             " value='12'>" . &mt('noon') . "</option>\n";              " value='12'>" . &mt('noon') . "</option>\n";
         for ($i = 13; $i < 24; $i++) {          for ($i = 13; $i < 24; $i++) {
             my $printedHour = $i - 12;              my $printedHour = $i - 12;
             if ($date->hour == $i) {              if ($date->hour == $i) {
                 $result .= "<option selected value='$i'>$printedHour $pm</option>\n";                  $result .= "<option selected='selected' value='$i'>$printedHour $pm</option>\n";
             } else {              } else {
                 $result .= "<option value='$i'>$printedHour $pm</option>\n";                  $result .= "<option value='$i'>$printedHour $pm</option>\n";
             }              }
Line 1642  sub render { Line 1888  sub render {
   
         $result .= "</select> :\n";          $result .= "</select> :\n";
   
         $result .= "<select name='${var}minute'>\n";          $result .= "<select $onclick name='${var}minute'>\n";
         for ($i = 0; $i < 60; $i++) {   my $selected=0;
           for my $i ((0,15,30,45,59,undef,0..59)) {
             my $printedMinute = $i;              my $printedMinute = $i;
             if ($i < 10) {              if (defined($i) && $i < 10) {
                 $printedMinute = "0" . $printedMinute;                  $printedMinute = "0" . $printedMinute;
             }              }
             if ($date->min == $i) {              if (!$selected && $date->min == $i) {
                 $result .= "<option selected>";                  $result .= "<option selected='selected'>";
    $selected=1;
             } else {              } else {
                 $result .= "<option>";                  $result .= "<option>";
             }              }
Line 1657  sub render { Line 1905  sub render {
         }          }
         $result .= "</select>\n";          $result .= "</select>\n";
     }      }
       $result  .= ' '.$date->time_zone_short_name().' ';
       if ($self->{'anytime'}) {
    $result.=(<<CHECK);
   <script type="text/javascript">
   // <!--
       function updateCheck(form,name,value) {
    var checkbox=form[name];
    checkbox.checked = value;
       }
   // -->
   </script>
   CHECK
    $result.="&nbsp;or&nbsp;<label><input type='checkbox' ";
    if ($anytime) {
       $result.=' checked="checked" '
    }
           my $anytimetext = &mt('Any time');
           if (($var eq 'startreserve') || ($var eq 'endreserve')) {
               $anytimetext = &mt('Any time before slot starts');
           } elsif (($var eq 'startunique') || ($var eq 'endunique')) {
               $anytimetext = &mt('No restriction on uniqueness');     
           }
    $result.="name='${var}anytime'/>".$anytimetext.'</label>'
       }
     return $result;      return $result;
   
 }  }
Line 1665  sub render { Line 1936  sub render {
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
     my $var = $self->{'variable'};      my $var = $self->{'variable'};
     my $month = $ENV{'form.' . $var . 'month'};       if ($env{'form.' . $var . 'anytime'}) {
     my $day = $ENV{'form.' . $var . 'day'};    $helper->{VARS}->{$var} = undef;
     my $year = $ENV{'form.' . $var . 'year'};       } else {
     my $min = 0;    my $month = $env{'form.' . $var . 'month'};
     my $hour = 0;          $month ++;
     if ($self->{'hoursminutes'}) {   my $day = $env{'form.' . $var . 'day'}; 
         $min = $ENV{'form.' . $var . 'minute'};   my $year = $env{'form.' . $var . 'year'}; 
         $hour = $ENV{'form.' . $var . 'hour'};   my $min = 0; 
     }   my $hour = 0;
    if ($self->{'hoursminutes'}) {
       $min = $env{'form.' . $var . 'minute'};
       $hour = $env{'form.' . $var . 'hour'};
    }
   
    my ($chosenDate,$checkDate);
           my $timezone = &Apache::lonlocal::gettimezone();
           my $dt;
    eval {
                  $dt = DateTime->new( year   => $year,
                                       month  => $month,
                                       day    => $day,
                                       hour   => $hour,
                                       minute => $min,
                                       second => 0,
                                       time_zone => $timezone,
                                );
           };
   
    my $error = $@;
           if (!$error) {
               $chosenDate  = $dt->epoch;
               $checkDate = &get_date_object($chosenDate);
           }
   
    # Check to make sure that the date was not automatically co-erced into a 
    # valid date, as we want to flag that as an error
    # This happens for "Feb. 31", for instance, which is coerced to March 2 or
    # 3, depending on if it's a leap year
   
    if ($error || $checkDate->mon != $month || $checkDate->mday != $day ||
       $checkDate->year != $year) {
       unless (Apache::lonlocal::current_language()== ~/^en/) {
    $self->{ERROR_MSG} = &mt("Invalid date entry");
    return 0;
       }
       # LOCALIZATION FIXME: Needs to be parameterized
       $self->{ERROR_MSG} = "Can't use ".$months[$env{'form.'.$var.'month'}].                                 " $day, $year as a ".
                    "date because it doesn't exist. Please enter a valid date.";
   
     my $chosenDate;  
     eval {$chosenDate = Time::Local::timelocal(0, $min, $hour, $day, $month, $year);};  
     my $error = $@;  
   
     # Check to make sure that the date was not automatically co-erced into a   
     # valid date, as we want to flag that as an error  
     # This happens for "Feb. 31", for instance, which is coerced to March 2 or  
     # 3, depending on if it's a leap year  
     my $checkDate = localtime($chosenDate);  
   
     if ($error || $checkDate->mon != $month || $checkDate->mday != $day ||  
         $checkDate->year + 1900 != $year) {  
  unless (Apache::lonlocal::current_language()== ~/^en/) {  
     $self->{ERROR_MSG} = &mt("Invalid date entry");  
     return 0;      return 0;
  }   }
  # LOCALIZATION FIXME: Needs to be parameterized   $helper->{VARS}->{$var} = $chosenDate;
         $self->{ERROR_MSG} = "Can't use " . $months[$month] . " $day, $year as a "  
             . "date because it doesn't exist. Please enter a valid date.";  
   
         return 0;  
     }      }
   
     $helper->{VARS}->{$var} = $chosenDate;      if (defined($self->{VALIDATOR})) {
    my $validator = eval($self->{VALIDATOR});
    die 'Died during evaluation of validator code; Perl said: ' . $@ if $@;
    my $invalid = &$validator($helper, $state, $self, $self->getValue());
    if ($invalid) {
       $self->{ERROR_MSG} = $invalid;
       return 0;
    }
       }
   
     if (defined($self->{NEXTSTATE})) {      if (defined($self->{NEXTSTATE})) {
         $helper->changeState($self->{NEXTSTATE});          $helper->changeState($self->{NEXTSTATE});
Line 1706  sub postprocess { Line 2006  sub postprocess {
   
     return 1;      return 1;
 }  }
   
   sub get_date_object {
       my ($epoch) = @_;
       my $dt = DateTime->from_epoch(epoch => $epoch)
                        ->set_time_zone(&Apache::lonlocal::gettimezone());
       my $lang = Apache::lonlocal::current_language();
       if ($lang ne '') {
           eval {
               $dt->set_locale($lang);
           };
       }
       return $dt;
   }
   
 1;  1;
   
 package Apache::lonhelper::resource;  package Apache::lonhelper::resource;
Line 1730  to false. The "suppressEmptySequences" a Line 2044  to false. The "suppressEmptySequences" a
 suppressEmptySequences argument to the render routine, which will cause  suppressEmptySequences argument to the render routine, which will cause
 folders that have all of their contained resources filtered out to also  folders that have all of their contained resources filtered out to also
 be filtered out. The 'addstatus' attribute, if true, will add the icon  be filtered out. The 'addstatus' attribute, if true, will add the icon
 and long status display columns to the display.  and long status display columns to the display. The 'addparts'
   attribute will add in a part selector beside problems that have more
   than 1 part. The 'includecourse' attribute if true, will include
   the toplevel default.sequence in the results. The 'modalLink' attribute,
   if true, will cause links to be launched as modal pop-ups, instead of 
   replacing the resource selection listing, currently being displayed.
   
 =head3 SUB-TAGS  =head3 SUB-TAGS
   
Line 1763  and long status display columns to the d Line 2082  and long status display columns to the d
   evaluated with "sub { my $helper = shift; my $state = shift;" and    evaluated with "sub { my $helper = shift; my $state = shift;" and
   "}", with the return value used as the mapurl.    "}", with the return value used as the mapurl.
   
   =item * <option />: Allows you to add optional elements to the
     resource chooser currently these can be a checkbox, or a text entry
     or hidden (see the 'type' attribute below).
     the following attributes are supported by this tag:
   
   =over 4
   
   =item * type=control-type : determines the type of control displayed.
     This can be one of the following types: 'checkbox' provides a true/false
     checkbox.  'text' provides a text entry control. 'hidden' provides a
     hidden form element that returns the name of the resource for each
     element of the text box.
   
   =item * text=header-text : provides column header text for the option.
     
   =item * variable=helpervar : provides a helper variable to contain the
     value of the input control for each resource.  In general, the result
     will be a set of values separated by |||  for the checkbox the value between
     the |||'s will either be empty, if the box is not checked, or the resource
     name if checked.  For the text entry, the values will be the text in the
     text box.  This could be empty.  Hidden elements unconditionally provide
     the resource name for each row of the chooser and allow you to therefore
     correlate text entries to their resources.
     The helper variable can be initialized by the user code to pre-load values
     into the controls:
   
   =over 4
   
     
   =item * Preloading checkboxes : Set the helper variable to the value you
      would have gotten from the control if it had been manually set as desired.
   
   =item * Preloading text entries : Set the helper variable to triple pipe
      separated values where each value is of the form resource-name=value
   
   =item * Preloading hidden fields : These cannot be pre-loaded and will always
     be pipe separated resource names.
   
   =back
   
   
   =back
   
 =back  =back
   
 =cut  =cut
Line 1770  and long status display columns to the d Line 2132  and long status display columns to the d
 no strict;  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::resource',      &Apache::lonhelper::register('Apache::lonhelper::resource',
                               ('resource', 'filterfunc',                                 ('resource', 'filterfunc', 
                                'choicefunc', 'valuefunc',                                 'choicefunc', 'valuefunc',
                                'mapurl'));                                 'mapurl','option'));
 }  }
   
 sub new {  sub new {
Line 1797  sub start_resource { Line 2160  sub start_resource {
     $paramHash->{'suppressEmptySequences'} = $token->[2]{'suppressEmptySequences'};      $paramHash->{'suppressEmptySequences'} = $token->[2]{'suppressEmptySequences'};
     $paramHash->{'toponly'} = $token->[2]{'toponly'};      $paramHash->{'toponly'} = $token->[2]{'toponly'};
     $paramHash->{'addstatus'} = $token->[2]{'addstatus'};      $paramHash->{'addstatus'} = $token->[2]{'addstatus'};
       $paramHash->{'addparts'} = $token->[2]{'addparts'};
       $paramHash->{'modalLink'} = $token->[2]{'modallink'};
       $paramHash->{'nocurrloc'} = $token->[2]{'nocurrloc'};
       $paramHash->{'suppressNavmap'} = $token->[2]{'suppressNavmap'};
       if ($paramHash->{'addparts'}) {
    $helper->declareVar($paramHash->{'variable'}.'_part');
       }
     $paramHash->{'closeallpages'} = $token->[2]{'closeallpages'};      $paramHash->{'closeallpages'} = $token->[2]{'closeallpages'};
       $paramHash->{'include_top_level_map'} = $token->[2]{'includecourse'};
     return '';      return '';
 }  }
   
Line 1880  sub start_mapurl { Line 2251  sub start_mapurl {
   
 sub end_mapurl { return ''; }  sub end_mapurl { return ''; }
   
   
   sub start_option {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
       if (!defined($paramHash->{OPTION_TEXTS})) {
    $paramHash->{OPTION_TEXTS} = [ ];
    $paramHash->{OPTION_VARS}  = [ ];
    $paramHash->{OPTION_TYPES} = [ ];
   
       }
       #  We can have an attribute: type which can have the
       #  values: "checkbox" or "text" which defaults to 
       #           checkbox allowing us to change the type of input
       #           for the option:
       #
       my $input_widget_type = 'checkbox';
       if(defined($token->[2]{'type'})) {
    my $widget_type  = $token->[2]{'type'};
    if ($widget_type eq 'text') {          # only accept legal alternatives
       $input_widget_type = $widget_type; # Illegals are checks.
    } elsif ($widget_type eq 'hidden') {
       $input_widget_type = $widget_type;
    }
       }
   
       # OPTION_TEXTS is a list of the text attribute
       #               values used to create column headings.
       # OPTION_VARS is a list of the variable names, used to create the checkbox
       #             inputs.
       # OPTION_TYPES is a list of the option types:
       #
       #  We're ok with empty elements. as place holders
       # Although the 'variable' element should really exist.
       #
   
   
       my $option_texts  = $paramHash->{OPTION_TEXTS};
       my $option_vars   = $paramHash->{OPTION_VARS};
       my $option_types   = $paramHash->{OPTION_TYPES};
       push(@$option_texts,  $token->[2]{'text'});
       push(@$option_vars,   $token->[2]{'variable'});
       push(@$option_types,   $input_widget_type);
   
   
       #  Need to create and declare the option variables as well to make them
       # persistent.
       #
       my $varname = $token->[2]{'variable'};
       $helper->declareVar($varname);
   
   
       return '';
   }
   
   sub end_option {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
       return '';
   }
   
 # A note, in case I don't get to this before I leave.  # A note, in case I don't get to this before I leave.
 # If someone complains about the "Back" button returning them  # If someone complains about the "Back" button returning them
 # to the previous folder state, instead of returning them to  # to the previous folder state, instead of returning them to
Line 1902  sub render { Line 2331  sub render {
   
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result = <<SCRIPT;          $result = <<SCRIPT;
 <script>  <script type="text/javascript">
   // <!--
     function checkall(value, checkName) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.helpform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             ele = document.forms.helpform.elements[i];              ele = document.forms.helpform.elements[i];
             if (ele.name == checkName + '.forminput') {              if (ele.name == checkName + '_forminput') {
                 document.forms.helpform.elements[i].checked=value;                  document.forms.helpform.elements[i].checked=value;
             }              }
         }          }
     }      }
   // -->
 </script>  </script>
 SCRIPT  SCRIPT
         my %lt=&Apache::lonlocal::texthash(          my %lt=&Apache::lonlocal::texthash(
Line 1931  BUTTONS Line 2362  BUTTONS
   
     $result .= $buttons;      $result .= $buttons;
   
     my $filterFunc = $self->{FILTER_FUNC};      my $filterFunc     = $self->{FILTER_FUNC};
     my $choiceFunc = $self->{CHOICE_FUNC};      my $choiceFunc     = $self->{CHOICE_FUNC};
     my $valueFunc = $self->{VALUE_FUNC};      my $valueFunc      = $self->{VALUE_FUNC};
     my $multichoice = $self->{'multichoice'};      my $multichoice    = $self->{'multichoice'};
       my $option_vars    = $self->{OPTION_VARS};
       my $option_texts   = $self->{OPTION_TEXTS};
       my $option_types   = $self->{OPTION_TYPES};
       my $addparts       = $self->{'addparts'};
       my $modalLink      = $self->{'modalLink'};
       my $headings_done  = 0;
   
     # Evaluate the map url as needed      # Evaluate the map url as needed
     my $mapUrl;      my $mapUrl;
Line 1946  BUTTONS Line 2383  BUTTONS
  $mapUrl = $self->{MAP_URL};   $mapUrl = $self->{MAP_URL};
     }      }
   
       my %defaultSymbs;
       if (defined($self->{DEFAULT_VALUE})) {
           my $valueFunc = eval($self->{DEFAULT_VALUE});
           die 'Error in default value code for variable ' . 
               $self->{'variable'} . ', Perl said: ' . $@ if $@;
           my @defaultSymbs = &$valueFunc($helper, $self);
    if (!$multichoice && @defaultSymbs) { # only allowed 1
       @defaultSymbs = ($defaultSymbs[0]);
    }
    %defaultSymbs = map { if ($_) {($_,1) } } @defaultSymbs;
    delete($defaultSymbs{''});
       }
   
     # Create the composite function that renders the column on the nav map      # Create the composite function that renders the column on the nav map
     # have to admit any language that lets me do this can't be all bad      # have to admit any language that lets me do this can't be all bad
     #  - Jeremy (Pythonista) ;-)      #  - Jeremy (Pythonista) ;-)
     my $checked = 0;      my $checked = 0;
     my $renderColFunc = sub {      my $renderColFunc = sub {
         my ($resource, $part, $params) = @_;          my ($resource, $part, $params) = @_;
    my $result = "";
   
    if(!$headings_done) {
       if ($option_texts) {
    foreach my $text (@$option_texts) {
       $result .= "<th>$text</th>";
    }
       }
       $result .= '<th>'.&Apache::lonlocal::mt('Select').'</th>';
       $result .= "</tr><tr>"; # Close off the extra row and start a new one.
       $headings_done = 1;
    }
   
         my $inputType;          my $inputType;
         if ($multichoice) { $inputType = 'checkbox'; }          if ($multichoice) { $inputType = 'checkbox'; }
         else {$inputType = 'radio'; }          else {$inputType = 'radio'; }
   
         if (!&$choiceFunc($resource)) {          if (!&$choiceFunc($resource)) {
             return '<td>&nbsp;</td>';      $result .= '<td>&nbsp;</td>';
               return $result;
         } else {          } else {
             my $col = "<td><input type='$inputType' name='${var}.forminput' ";      my $col = "";
             if (!$checked && !$multichoice) {      my $raw_name = &$valueFunc($resource);
                 $col .= "checked ";      my $resource_name =   
                 $checked = 1;                     HTML::Entities::encode($raw_name,"<>&\"'");
             }      if($option_vars) {
     if ($multichoice) { # all resources start checked; see bug 1174   my $option_num = 0;
  $col .= "checked ";   foreach my $option_var (@$option_vars) {
  $checked = 1;      my $option_type = $option_types->[$option_num];
       $option_num++;
       my $var_value = "\|\|\|" . $helper->{VARS}->{$option_var} . 
    "\|\|\|";
       my $checked ="";
       if($var_value =~ /\Q|||$raw_name|||\E/) {
    $checked = "checked='checked'";
       }
       if ($option_type eq 'text') {
    #
    # For text's the variable value is a ||| separated set of
    # resource_name=value 
    #
    my @values = split(/\|\|\|/, $helper->{VARS}->{$option_var});
   
    # Normal practice would be to toss this in a hash but 
    # the only thing that saves is the compare in the loop
    # below and for all but one case we'll break out of the loop
    # before it completes.
   
    my $text_value = '';    # In case there's no match.
    foreach my $value (@values) {
       my ($res, $skip) = split(/=/, $value);
       if($res eq $resource_name) {
    $text_value = $skip;
    last;
       }
    }
    # TODO: add an attribute to <option> that allows the
    #       programmer to set the width of the tex entry box.
   
    $col .=
       "<td align='center'><input type='text' name ='$option_var".
       "_forminput' value='".$text_value."' size='5' /> </td>";
       } elsif ($option_type eq 'hidden') {
     $col .= "<td align='center'><input type='hidden' name ='$option_var".
       "_forminput' value='".
       $resource_name . "'/> </td>";
       } else {
    $col .= 
       "<td align='center'><input type='$option_type' name ='$option_var".
       "_forminput' value='".
       $resource_name . "' $checked /> </td>";
       }
    }
       }
   
               $col .= "<td align='center'><input type='$inputType' name='${var}_forminput' ";
       if (%defaultSymbs) {
    my $symb=$resource->symb();
    if (exists($defaultSymbs{$symb})) {
       $col .= "checked='checked' ";
       $checked = 1;
    }
       } else {
    if (!$checked && !$multichoice) {
       $col .= "checked='checked' ";
       $checked = 1;
    }
    if ($multichoice) { # all resources start checked; see bug 1174
       $col .= "checked='checked' ";
       $checked = 1;
    }
     }      }
             $col .= "value='" .               $col .= "value='" . $resource_name  . "' /></td>";
                 HTML::Entities::encode(&$valueFunc($resource),'<>&"')   
                 . "' /></td>";              return $result.$col;
             return $col;  
         }          }
     };      };
       my $renderPartsFunc = sub {
           my ($resource, $part, $params) = @_;
    my $col= "<td>";
    my $id=$resource->{ID};
    my $resource_name =   
       &HTML::Entities::encode(&$valueFunc($resource),"<>&\"'");
    if ($addparts && (scalar(@{$resource->parts}) > 1)) {
       $col .= "<select onclick=\"javascript:updateRadio(this.form,'${var}_forminput','$resource_name');updateHidden(this.form,'$id','${var}');\" name='part_${id}_forminput'>\n";
       $col .= "<option value=\"$part\">".&Apache::lonlocal::mt('All Parts')."</option>\n";
       foreach my $part (@{$resource->parts}) {
    $col .= "<option value=\"$part\">".&Apache::lonlocal::mt('Part: [_1]',$part)."</option>\n";
       }
       $col .= "</select>";
    }
    $col .= "</td>";
       };
       $result.=(<<RADIO);
   <script type="text/javascript">
   // <!--
       function updateRadio(form,name,value) {
    var radiobutton=form[name];
    for (var i=0; i<radiobutton.length; i++) {
       if (radiobutton[i].value == value) {
    radiobutton[i].checked = true;
    break;
       }
    }
       }
       function updateHidden(form,id,name) {
    var select=form['part_'+id+'_forminput'];
    var hidden=form[name+'_part_forminput'];
    var which=select.selectedIndex;
    hidden.value=select.options[which].value;
       }
   // -->
   </script>
   <input type="hidden" name="${var}_part_forminput" />
   
     $ENV{'form.condition'} = !$self->{'toponly'};  RADIO
     my $cols = [$renderColFunc, Apache::lonnavmaps::resource()];      $env{'form.condition'} = !$self->{'toponly'};
       my $cols = [$renderColFunc];
       if ($self->{'addparts'}) { push(@$cols, $renderPartsFunc); }
       push(@$cols, Apache::lonnavmaps::resource());
     if ($self->{'addstatus'}) {      if ($self->{'addstatus'}) {
  push @$cols, (Apache::lonnavmaps::part_status_summary());   push @$cols, (Apache::lonnavmaps::part_status_summary());
   
     }      }
       my $caller;
       if ($helper->{TITLE} eq 'Printing Helper') {
           $caller = 'printout';
       }
     $result .=       $result .= 
         &Apache::lonnavmaps::render( { 'cols' => $cols,          &Apache::lonnavmaps::render( { 'cols' => $cols,
                                        'showParts' => 0,                                         'showParts' => 0,
Line 1989  BUTTONS Line 2557  BUTTONS
                                        'resource_no_folder_link' => 1,                                         'resource_no_folder_link' => 1,
        'closeAllPages' => $self->{'closeallpages'},         'closeAllPages' => $self->{'closeallpages'},
                                        'suppressEmptySequences' => $self->{'suppressEmptySequences'},                                         'suppressEmptySequences' => $self->{'suppressEmptySequences'},
                                        'iterator_map' => $mapUrl }         'include_top_level_map' => $self->{'include_top_level_map'},
                                          'iterator_map' => $mapUrl,
                                          'map_no_edit_link' => 1,
                                          'modalLink' => $modalLink,
                                          'nocurrloc' => $self->{'nocurrloc'},
                                          'suppressNavmap' => $self->{'suppressNavmap'},
                                          'caller' => $caller, }
                                        );                                         );
   
     $result .= $buttons;      $result .= $buttons;
Line 2004  sub postprocess { Line 2578  sub postprocess {
         $self->{ERROR_MSG} = 'You must choose at least one resource to continue.';          $self->{ERROR_MSG} = 'You must choose at least one resource to continue.';
         return 0;          return 0;
     }      }
       # For each of the attached options.  If it's env var is undefined, set it to
       # an empty string instead.. an undef'd env var means no choices selected.
       #
   
       my $option_vars = $self->{OPTION_VARS};
       if ($option_vars) {
    foreach my $var (@$option_vars) {
       my $env_name = "form.".$var."_forminput";
       if (!defined($env{$env_name})) {
    $env{$env_name} = '';
    $helper->{VARS}->{$var} = '';
       }
    }
       }
   
   
     if (defined($self->{NEXTSTATE})) {      if (defined($self->{NEXTSTATE})) {
         $helper->changeState($self->{NEXTSTATE});          $helper->changeState($self->{NEXTSTATE});
Line 2046  selection. Defaults to false. Line 2635  selection. Defaults to false.
 If true, only active students and course personnel will be  If true, only active students and course personnel will be
 shown. Defaults to false.  shown. Defaults to false.
   
   =item * B<sectiononly>:
   
   If true, and user's role is in a specific section, only course personnel 
   will be shown if they also have a section-specific role in the same section.
   Defaults to false.
   
   =item * B<emptyallowed>:
   
   If true, the selection of no users is allowed. Defaults to false.
   
 =back  =back
   
 =cut  =cut
Line 2054  no strict; Line 2653  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::student',      &Apache::lonhelper::register('Apache::lonhelper::student',
Line 2077  sub start_student { Line 2676  sub start_student {
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
     $paramHash->{'multichoice'} = $token->[2]{'multichoice'};      $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
     $paramHash->{'coursepersonnel'} = $token->[2]{'coursepersonnel'};      $paramHash->{'coursepersonnel'} = $token->[2]{'coursepersonnel'};
     $paramHash->{'sctiveonly'} = $token->[2]{'activeonly'};      $paramHash->{'sectiononly'} = $token->[2]{'sectiononly'};
       $paramHash->{'activeonly'} = $token->[2]{'activeonly'};
     if (defined($token->[2]{'nextstate'})) {      if (defined($token->[2]{'nextstate'})) {
         $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};          $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
     }      }
       $paramHash->{'emptyallowed'} = $token->[2]{'emptyallowed'};
           
 }      }    
   
Line 2099  sub render { Line 2700  sub render {
     my $buttons = '';      my $buttons = '';
     my $var = $self->{'variable'};      my $var = $self->{'variable'};
   
     if ($self->{'multichoice'}) {  
         $result = <<SCRIPT;      if (defined $self->{ERROR_MSG}) {
 <script>          $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';
     function checkall(value, checkName) {  
  for (i=0; i<document.forms.helpform.elements.length; i++) {  
             ele = document.forms.helpform.elements[i];  
             if (ele.name == checkName + '.forminput') {  
                 document.forms.helpform.elements[i].checked=value;  
             }  
         }  
     }  
     function checksec(value) {  
  for (i=0; i<document.forms.helpform.elements.length; i++) {  
     comp = document.forms.helpform.elements.chksec.value;  
             if (document.forms.helpform.elements[i].value.indexOf(':'+comp+':') != -1) {  
                 document.forms.helpform.elements[i].checked=value;  
             }  
         }  
     }  
     function checkactive() {  
  for (i=0; i<document.forms.helpform.elements.length; i++) {  
             if (document.forms.helpform.elements[i].value.indexOf(':Active') != -1) {  
                 document.forms.helpform.elements[i].checked=true;  
             }  
         }  
     }      }
 </script>  
 SCRIPT  
   
         my %lt=&Apache::lonlocal::texthash(      my %defaultUsers;
                     'ocs'  => "Select Only Current Students",      if (defined($self->{DEFAULT_VALUE})) {
                     'sas'  => "Select All Students",          my $valueFunc = eval($self->{DEFAULT_VALUE});
                     'uas'  => "Unselect All Students",          die 'Error in default value code for variable ' . 
                     'sfsg' => "Select for Section/Group",              $self->{'variable'} . ', Perl said: ' . $@ if $@;
     'ufsg' => "Unselect for Section/Group");          my @defaultUsers = &$valueFunc($helper, $self);
     if (!$self->{'multichoice'} && @defaultUsers) { # only allowed 1
         $buttons = <<BUTTONS;      @defaultUsers = ($defaultUsers[0]);
 <br />   }
 <input type="button" onclick="checkactive()" value="$lt{'ocs'}" />   %defaultUsers = map { if ($_) {($_,1) } } @defaultUsers;
 <input type="button" onclick="checkall(true, '$var')" value="$lt{'sas'}" />   delete($defaultUsers{''});
 <input type="button" onclick="checkall(false, '$var')" value="$lt{'uas'}" />  
 <input type="button" onclick="checksec(true)" value="$lt{'sfsg'}">  
 <input type="text" size="5" name="chksec">&nbsp;  
 <input type="button" onclick="checksec(false)" value="$lt{'ufsg'}">  
 <br />  
 BUTTONS  
     }      }
   
     if (defined $self->{ERROR_MSG}) {      my $personnel_section;
         $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';      if ($self->{'sectiononly'}) {
           $personnel_section = $env{'request.course.sec'};
     }      }
   
     my $choices = [];      my ($course_personnel, 
    $current_members, 
    $expired_members, 
    $future_members) = 
       &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'},
                                                   $personnel_section);
   
     # Load up the non-students, if necessary      # Load up the non-students, if necessary
   
     if ($self->{'coursepersonnel'}) {      if ($self->{'coursepersonnel'}) {
  my %coursepersonnel = Apache::lonnet::get_course_adv_roles();   unshift @$current_members, (@$course_personnel);
  for (sort keys %coursepersonnel) {  
     for my $role (split /,/, $coursepersonnel{$_}) {  
  # extract the names so we can sort them  
  my @people;  
   
  for (split /,/, $role) {  
     push @people, [split /:/, $role];  
  }  
   
  @people = sort { $a->[0] cmp $b->[0] } @people;  
   
  for my $person (@people) {  
     push @$choices, [join(':', @$person), $person->[0], '', $_];  
  }  
     }  
  }  
     }      }
   
     # Constants      my %titles = &Apache::lonlocal::texthash(
     my $section = Apache::loncoursedata::CL_SECTION();                     'active'  => 'Select Currently Enrolled Students and Active Course Personnel',
     my $fullname = Apache::loncoursedata::CL_FULLNAME();                     'future'  => 'Select Future Enrolled Students',
     my $status = Apache::loncoursedata::CL_STATUS();                     'expired' => 'Select Previously Enrolled Students',
                    );
     # Load up the students  
     my $classlist = &Apache::loncoursedata::get_classlist();      if ($env{'request.course.sec'}) {
     my @keys = keys %{$classlist};          if ($self->{'sectiononly'}) {
     # Sort by: Section, name              $titles{'active'} = &mt('Select Currently Enrolled Students and Active Course Personnel in Section: [_1]',
     @keys = sort {                                  $env{'request.course.sec'});
         if ($classlist->{$a}->[$section] ne $classlist->{$b}->[$section]) {          } else {
             return $classlist->{$a}->[$section] cmp $classlist->{$b}->[$section];              $titles{'active'} = &mt('Select Currently Enrolled Students in Section: [_1], and Active Course Personnel',
         }                                      $env{'request.course.sec'});
         return $classlist->{$a}->[$fullname] cmp $classlist->{$b}->[$fullname];          }
     } @keys;          $titles{'future'} = &mt('Select Future Enrolled Students in Section: [_1]',
                                   $env{'request.course.sec'});
     # username, fullname, section, type          $titles{'expired'} = &mt('Select Previously Enrolled Students in Section: [_1]',
     for (@keys) {                                   $env{'request.course.sec'});
  # Filter out inactive students if we've set "activeonly"      }
  if (!$self->{'activeonly'} || $classlist->{$_}->[$status] eq  
     'Active') {      #   Current personnel
     push @$choices, [$_, $classlist->{$_}->[$fullname],   
      $classlist->{$_}->[$section],      $result .= '<h4>'.$titles{'active'}.'</h4>';
      $classlist->{$_}->[$status], 'Student'];      $result .= &Apache::lonselstudent::render_student_list( $current_members,
  }      "helpform",
       "current",
       \%defaultUsers,
       $self->{'multichoice'},
       $self->{'variable'},
       1);
   
       # If activeonly is not set then we can also give the expired students:
       #
       if (!$self->{'activeonly'} && ((scalar(@$future_members)) > 0)) {
   
    # And future.
   
    $result .= '<h4>'.$titles{'future'}.'</h4>';
          
    $result .= &Apache::lonselstudent::render_student_list( $future_members,
    "helpform",
    "future",
    \%defaultUsers,
    $self->{'multichoice'},
    $self->{'variable'},
    0);
       }
       if (!$self->{'activeonly'} && ((scalar(@$expired_members)) > 0)) {
    # Past 
   
    $result .= '<h4>'.$titles{'expired'}.'</h4>';
    $result .= &Apache::lonselstudent::render_student_list($expired_members,
          "helpform",
          "past",
          \%defaultUsers,
          $self->{'multichoice'},
          $self->{'variable'},
          0);
     }      }
   
     my $name = $self->{'coursepersonnel'} ? &mt('Name') : &mt('Student Name');  
     &Apache::lonnet::logthis("THE NAME IS >$name<");  
     my $type = 'radio';  
     if ($self->{'multichoice'}) { $type = 'checkbox'; }  
     $result .= "<table cellspacing='2' cellpadding='2' border='0'>\n";  
     $result .= "<tr><td></td><td align='center'><b>$name</b></td>".  
         "<td align='center'><b>" . &mt('Section') . "</b></td>" .   
  "<td align='center'><b>".&mt('Status')."</b></td>" .   
  "<td align='center'><b>" . &mt("Role") . "</b></td>" .  
  "<td align='center'><b>".&mt('Username').":".&mt('Domain')."</b></td></tr>";  
   
     my $checked = 0;  
     for my $choice (@$choices) {  
         $result .= "<tr><td><input type='$type' name='" .  
             $self->{'variable'} . '.forminput' . "'";  
               
         if (!$self->{'multichoice'} && !$checked) {  
             $result .= " checked ";  
             $checked = 1;  
         }  
         $result .=  
             " value='" . HTML::Entities::encode($choice->[0] . ':' . $choice->[2] . ':' . $choice->[1] . ':' . $choice->[3],'<>&"')  
             . "' /></td><td>"  
             . HTML::Entities::encode($choice->[1],'<>&"')  
             . "</td><td align='center'>"   
             . HTML::Entities::encode($choice->[2],'<>&"')  
             . "</td>\n<td>"   
     . HTML::Entities::encode($choice->[3],'<>&"')  
             . "</td>\n<td>"   
     . HTML::Entities::encode($choice->[4],'<>&"')  
             . "</td>\n<td>"   
     . HTML::Entities::encode($choice->[0],'<>&"')  
     . "</td></tr>\n";  
     }  
   
     $result .= "</table>\n\n";  
     $result .= $buttons;      
       
     return $result;      return $result;
 }  }
   
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
   
     my $result = $ENV{'form.' . $self->{'variable'} . '.forminput'};      my $result = $env{'form.' . $self->{'variable'} . '_forminput'};
     if (!$result) {      if (!$result && !$self->{'emptyallowed'}) {
         $self->{ERROR_MSG} =    if ($self->{'coursepersonnel'}) {
     &mt('You must choose at least one student to continue.');      $self->{ERROR_MSG} = 
    &mt('You must choose at least one user to continue.');
    } else {
       $self->{ERROR_MSG} = 
    &mt('You must choose at least one student to continue.');
    }
         return 0;          return 0;
     }      }
   
Line 2315  no strict; Line 2879  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
 use Apache::lonpubdir; # for getTitleString  use Apache::lonpubdir; # for getTitleString
   
 BEGIN {  BEGIN {
Line 2390  sub start_filefilter { Line 2954  sub start_filefilter {
   
 sub end_filefilter { return ''; }  sub end_filefilter { return ''; }
   
   { 
       # used to generate unique id attributes for <input> tags. 
       # internal use only.
       my $id=0;
       sub new_id { return $id++;}
   }
   
 sub render {  sub render {
     my $self = shift;      my $self = shift;
     my $result = '';      my $result = '';
Line 2413  sub render { Line 2984  sub render {
   
     if ($self->{'multichoice'}) {      if ($self->{'multichoice'}) {
         $result = <<SCRIPT;          $result = <<SCRIPT;
 <script>  <script type="text/javascript">
   // <!--
     function checkall(value, checkName) {      function checkall(value, checkName) {
  for (i=0; i<document.forms.helpform.elements.length; i++) {   for (i=0; i<document.forms.helpform.elements.length; i++) {
             ele = document.forms.helpform.elements[i];              ele = document.forms.helpform.elements[i];
             if (ele.name == checkName + '.forminput') {              if (ele.name == checkName + '_forminput') {
                 document.forms.helpform.elements[i].checked=value;                  document.forms.helpform.elements[i].checked=value;
             }              }
         }          }
Line 2431  sub render { Line 3003  sub render {
             }              }
         }          }
     }      }
   // -->
 </script>  </script>
 SCRIPT  SCRIPT
        my %lt=&Apache::lonlocal::texthash(         my %lt=&Apache::lonlocal::texthash(
Line 2455  BUTTONS Line 3028  BUTTONS
     }      }
   
     # Get the list of files in this directory.      # Get the list of files in this directory.
     my @fileList;      my (@fileList,$listref,$listerror);
   
     # If the subdirectory is in local CSTR space      # If the subdirectory is in local CSTR space
     my $metadir;      my $metadir;
     if ($subdir =~ m|/home/([^/]+)/public_html/(.*)|) {      my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
         my $user = $1;      if ($subdir =~ m{^(?:\Q$londocroot\E)*/priv/[^/]+/[^/]+/(.*)$}) {
         my $domain = $Apache::lonnet::perlvar{'lonDefDomain'};          my $innerpath=$1;
  $metadir='/res/'.$domain.'/'.$user.'/'.$2;          unless ($subdir=~m{^\Q$londocroot\E}) {
         @fileList = &Apache::lonnet::dirlist($subdir, $domain, $user, '');             $subdir=$londocroot.$subdir;
     } elsif ($subdir =~ m|^~([^/]+)/(.*)$|) {          }
  $subdir='/home/'.$1.'/public_html/'.$2;   my ($user,$domain)= 
         my $user = $1;      &Apache::lonnet::constructaccess($subdir);
         my $domain = $Apache::lonnet::perlvar{'lonDefDomain'};   $metadir='/res/'.$domain.'/'.$user.'/'.$innerpath;
  $metadir='/res/'.$domain.'/'.$user.'/'.$2;          ($listref,$listerror) =
         @fileList = &Apache::lonnet::dirlist($subdir, $domain, $user, '');              &Apache::lonnet::dirlist($subdir,$domain,$user,undef,undef,'/');
     } else {      } else {
         # local library server resource space          # local library server resource space
         @fileList = &Apache::lonnet::dirlist($subdir, $ENV{'user.domain'}, $ENV{'user.name'}, '');          ($listref,$listerror) = 
               &Apache::lonnet::dirlist($subdir,$env{'user.domain'},$env{'user.name'},undef,undef,'/');
     }      }
   
     # Sort the fileList into order      # Sort the fileList into order
     @fileList = sort @fileList;      if (ref($listref) eq 'ARRAY') {
           @fileList = sort {lc($a) cmp lc($b)} @{$listref};
       }
   
     $result .= $buttons;      $result .= $buttons;
   
Line 2528  BUTTONS Line 3104  BUTTONS
             if ($status eq 'Published' && $helper->{VARS}->{'construction'}) {              if ($status eq 'Published' && $helper->{VARS}->{'construction'}) {
                 $onclick = 'onclick="a=1" ';                  $onclick = 'onclick="a=1" ';
             }              }
               my $id = &new_id();
             $result .= '<tr><td align="right"' . " bgcolor='$color'>" .              $result .= '<tr><td align="right"' . " bgcolor='$color'>" .
                 "<input $onclick type='$type' name='" . $var                  "<input $onclick type='$type' name='" . $var
             . ".forminput' value='" . HTML::Entities::encode($fileName,'<>&"').              . "_forminput' ".qq{id="$id"}." value='" . HTML::Entities::encode($fileName,"<>&\"'").
                 "'";                  "'";
             if (!$self->{'multichoice'} && $choices == 0) {              if (!$self->{'multichoice'} && $choices == 0) {
                 $result .= ' checked';                  $result .= ' checked="checked"';
             }              }
             $result .= "/></td><td bgcolor='$color'>" . $file . "</td>" .              $result .= "/></td><td bgcolor='$color'>".
                   qq{<label for="$id">}. $file . "</label></td>" .
                 "<td bgcolor='$color'>$title</td>" .                  "<td bgcolor='$color'>$title</td>" .
                 "<td bgcolor='$color'>$status</td>" . "</tr>\n";                  "<td bgcolor='$color'>$status</td>" . "</tr>\n";
             $choices++;              $choices++;
Line 2563  sub fileState { Line 3141  sub fileState {
     my $constructionSpaceDir = shift;      my $constructionSpaceDir = shift;
     my $file = shift;      my $file = shift;
           
       my ($uname,$udom)=($env{'user.name'},$env{'user.domain'});
       if ($env{'request.role'}=~/^ca\./) {
    (undef,$udom,$uname)=split(/\//,$env{'request.role'});
       }
     my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};      my $docroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     my $subdirpart = $constructionSpaceDir;      my $subdirpart = $constructionSpaceDir;
     $subdirpart =~ s/^\/home\/$ENV{'user.name'}\/public_html//;      $subdirpart =~ s{^\Q$docroot/priv/$udom/$uname\E}{};
     my $resdir = $docroot . '/res/' . $ENV{'user.domain'} . '/' . $ENV{'user.name'} .      my $resdir = $docroot . '/res/' . $udom . '/' . $uname .
         $subdirpart;          $subdirpart;
   
     my @constructionSpaceFileStat = stat($constructionSpaceDir . '/' . $file);      my @constructionSpaceFileStat = stat($constructionSpaceDir . '/' . $file);
Line 2586  sub fileState { Line 3168  sub fileState {
   
 sub postprocess {  sub postprocess {
     my $self = shift;      my $self = shift;
     my $result = $ENV{'form.' . $self->{'variable'} . '.forminput'};      my $result = $env{'form.' . $self->{'variable'} . '_forminput'};
     if (!$result) {      if (!$result) {
         $self->{ERROR_MSG} = 'You must choose at least one file '.          $self->{ERROR_MSG} = 'You must choose at least one file '.
             'to continue.';              'to continue.';
Line 2611  package Apache::lonhelper::section; Line 3193  package Apache::lonhelper::section;
 <section> allows the user to choose one or more sections from the current  <section> allows the user to choose one or more sections from the current
 course.  course.
   
 It takes the standard attributes "variable", "multichoice", and  It takes the standard attributes "variable", "multichoice",
 "nextstate", meaning what they do for most other elements.  "allowempty" and "nextstate", meaning what they do for most other
   elements.
   
   also takes a boolean 'onlysections' which will restrict this to only
   have sections and not include groups
   
 =cut  =cut
   
Line 2642  sub start_section { Line 3228  sub start_section {
     $paramHash->{'variable'} = $token->[2]{'variable'};      $paramHash->{'variable'} = $token->[2]{'variable'};
     $helper->declareVar($paramHash->{'variable'});      $helper->declareVar($paramHash->{'variable'});
     $paramHash->{'multichoice'} = $token->[2]{'multichoice'};      $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
       $paramHash->{'allowempty'} = $token->[2]{'allowempty'};
     if (defined($token->[2]{'nextstate'})) {      if (defined($token->[2]{'nextstate'})) {
         $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};          $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
     }      }
   
     # Populate the CHOICES element      # Populate the CHOICES element
     my %choices;      my %choices;
       my $usersec = $Apache::lonnet::env{'request.course.sec'};
   
     my $section = Apache::loncoursedata::CL_SECTION();      if ($usersec ne '') {
     my $classlist = Apache::loncoursedata::get_classlist();          $choices{$usersec} = $usersec;
     foreach (keys %$classlist) {      } else {
         my $sectionName = $classlist->{$_}->[$section];          my $section = Apache::loncoursedata::CL_SECTION();
         if (!$sectionName) {          my $classlist = Apache::loncoursedata::get_classlist();
             $choices{"No section assigned"} = "";          foreach my $user (keys(%$classlist)) {
         } else {              my $section_name = $classlist->{$user}[$section];
             $choices{$sectionName} = $sectionName;              if (!$section_name) {
                   $choices{"No section assigned"} = "";
               } else {
                   $choices{$section_name} = $section_name;
               }
           }
    
           if (exists($choices{"No section assigned"})) {
       push(@{$paramHash->{CHOICES}}, 
            ['No section assigned','No section assigned']);
       delete($choices{"No section assigned"});
         }          }
     }       }
          for my $section_name (sort {lc($a) cmp lc($b) } (keys(%choices))) {
     for my $sectionName (sort(keys(%choices))) {   push @{$paramHash->{CHOICES}}, [$section_name, $section_name];
               }
         push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName];      return if ($token->[2]{'onlysections'});
   
       # add in groups to the end of the list
       my %curr_groups = &Apache::longroup::coursegroups();
       foreach my $group_name (sort(keys(%curr_groups))) {
    push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]);
     }      }
 }      }    
   
Line 2676  sub end_section { Line 3279  sub end_section {
 }      }    
 1;  1;
   
   package Apache::lonhelper::group;
   
   =pod
    
   =head2 Element: groupX<group, helper element>
    
   <group> allows the user to choose one or more groups from the current course.
   
   It takes the standard attributes "variable", "multichoice",
    "allowempty" and "nextstate", meaning what they do for most other
    elements.
   
   also takes a boolean grouponly, which if true, will restrict choice to
   groups in which user is a member, unless user has the mdg priv in the course,
   in which case all groups will be possible choices. Defaults to false.
   
   =cut
   
   no strict;
   @ISA = ("Apache::lonhelper::choices");
   use strict;
   
   BEGIN {
       &Apache::lonhelper::register('Apache::lonhelper::group',
                                    ('group'));
   }
   
   sub new {
       my $ref = Apache::lonhelper::choices->new();
       bless($ref);
   }
    
   sub start_group {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
    
       if ($target ne 'helper') {
           return '';
       }
   
       $paramHash->{CHOICES} = [];
   
       $paramHash->{'variable'} = $token->[2]{'variable'};
       $helper->declareVar($paramHash->{'variable'});
       $paramHash->{'multichoice'} = $token->[2]{'multichoice'};
       $paramHash->{'allowempty'} = $token->[2]{'allowempty'};
       $paramHash->{'grouponly'} = $token->[2]{'grouponly'};
       if (defined($token->[2]{'nextstate'})) {
           $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'};
       }
   
       # Populate the CHOICES element
       my %choices;
   
       my %curr_groups;
       if ((!$paramHash->{'grouponly'}) || (&Apache::lonnet::allowed('mdg',$Apache::lonnet::env{'request.course.id'}))) {
           %curr_groups = &Apache::longroup::coursegroups();
       } elsif ($Apache::lonnet::env{'request.course.groups'} ne '') {
           map { $curr_groups{$_} = 1; } split(/:/,$Apache::lonnet::env{'request.course.groups'});
       }
       foreach my $group_name (sort {lc($a) cmp lc($b)} (keys(%curr_groups))) {
    push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]);
       }
   }
   
   sub end_group {
       my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
       if ($target ne 'helper') {
           return '';
       }
       Apache::lonhelper::group->new();
   }
   1;
   
 package Apache::lonhelper::string;  package Apache::lonhelper::string;
   
 =pod  =pod
Line 2685  package Apache::lonhelper::string; Line 3362  package Apache::lonhelper::string;
 string elements provide a string entry field for the user. string elements  string elements provide a string entry field for the user. string elements
 take the usual 'variable' and 'nextstate' parameters. string elements  take the usual 'variable' and 'nextstate' parameters. string elements
 also pass through 'maxlength' and 'size' attributes to the input tag.  also pass through 'maxlength' and 'size' attributes to the input tag.
   Since you could have multiple strings in a helper state, each with its own
   validator, all but the last string should have
   noproceed='1' so that _all_ validators are evaluated before the next
   state can be reached.
   
 string honors the defaultvalue tag, if given.  string honors the defaultvalue tag, if given.
   
Line 2695  string honors the validation function, i Line 3376  string honors the validation function, i
 no strict;  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
   use Apache::lonlocal;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::string',      &Apache::lonhelper::register('Apache::lonhelper::string',
Line 2703  BEGIN { Line 3385  BEGIN {
   
 sub new {  sub new {
     my $ref = Apache::lonhelper::element->new();      my $ref = Apache::lonhelper::element->new();
       $ref->{'PROCEED'} = 1;      # By default postprocess goes to next state.
     bless($ref);      bless($ref);
 }  }
   
Line 2719  sub start_string { Line 3402  sub start_string {
     $paramHash->{'nextstate'} = $token->[2]{'nextstate'};      $paramHash->{'nextstate'} = $token->[2]{'nextstate'};
     $paramHash->{'maxlength'} = $token->[2]{'maxlength'};      $paramHash->{'maxlength'} = $token->[2]{'maxlength'};
     $paramHash->{'size'} = $token->[2]{'size'};      $paramHash->{'size'} = $token->[2]{'size'};
   
     return '';      return '';
 }  }
   
 sub end_string {  sub end_string {
     my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   
   
     if ($target ne 'helper') {      if ($target ne 'helper') {
         return '';          return '';
     }      }
     Apache::lonhelper::string->new();      my $state = Apache::lonhelper::string->new();
   
   
       if(&Apache::lonxml::get_param('noproceed', $parstack, $safeeval, undef, 1)) {
    $state->noproceed();
       }
   
      
   
     return '';      return '';
 }  }
   
   sub noproceed() {
       my $self = shift;
       $self->{PROCEED}  = 0;
   }
   
 sub render {  sub render {
     my $self = shift;      my $self = shift;
     my $result = '';      my $result = '';
   
     if (defined $self->{ERROR_MSG}) {      if (defined $self->{ERROR_MSG}) {
         $result .= '<br /><font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';          $result .= '<p><font color="#FF0000">' . $self->{ERROR_MSG} . '</font></p>';
     }      }
   
     $result .= '<input type="string" name="' . $self->{'variable'} . '.forminput"';      $result .= '<input type="text" name="' . $self->{'variable'} . '_forminput"';
   
     if (defined($self->{'size'})) {      if (defined($self->{'size'})) {
         $result .= ' size="' . $self->{'size'} . '"';          $result .= ' size="' . $self->{'size'} . '"';
Line 2768  sub postprocess { Line 3464  sub postprocess {
   
     if (defined($self->{VALIDATOR})) {      if (defined($self->{VALIDATOR})) {
  my $validator = eval($self->{VALIDATOR});   my $validator = eval($self->{VALIDATOR});
  die 'Died during evaluation of evaulation code; Perl said: ' . $@ if $@;   die 'Died during evaluation of validator code; Perl said: ' . $@ if $@;
  my $invalid = &$validator($helper, $state, $self, $self->getValue());   my $invalid = &$validator($helper, $state, $self, $self->getValue());
  if ($invalid) {   if ($invalid) {
     $self->{ERROR_MSG} = $invalid;      $self->{ERROR_MSG} = $invalid;
Line 2776  sub postprocess { Line 3472  sub postprocess {
  }   }
     }      }
   
     if (defined($self->{'nextstate'})) {      if (defined($self->{'nextstate'}) && $self->{PROCEED}) {
         $helper->changeState($self->{'nextstate'});          $helper->changeState($self->{'nextstate'});
     }      }
   
Line 2792  package Apache::lonhelper::general; Line 3488  package Apache::lonhelper::general;
 =head2 General-purpose tag: <exec>X<exec, helper tag>  =head2 General-purpose tag: <exec>X<exec, helper tag>
   
 The contents of the exec tag are executed as Perl code, B<not> inside a   The contents of the exec tag are executed as Perl code, B<not> inside a 
 safe space, so the full range of $ENV and such is available. The code  safe space, so the full range of $env and such is available. The code
 will be executed as a subroutine wrapped with the following code:  will be executed as a subroutine wrapped with the following code:
   
 "sub { my $helper = shift; my $state = shift;" and  "sub { my $helper = shift; my $state = shift;" and
Line 2813  be able to call methods on it. Line 3509  be able to call methods on it.
   
 =cut  =cut
   
   use Apache::lonlocal;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::general',      &Apache::lonhelper::register('Apache::lonhelper::general',
                                  'exec', 'condition', 'clause',                                   'exec', 'condition', 'clause',
Line 2871  sub start_clause { Line 3570  sub start_clause {
     die 'Error in clause of condition, Perl said: ' . $@ if $@;      die 'Error in clause of condition, Perl said: ' . $@ if $@;
     if (!&$clause($helper, $paramHash)) {      if (!&$clause($helper, $paramHash)) {
         # Discard all text until the /condition.          # Discard all text until the /condition.
         &Apache::lonxml::get_all_text('/condition', $parser);   my $end_tag = $paramHash->{SKIPTAG} || '/condition';
           &Apache::lonxml::get_all_text($end_tag, $parser);
     }      }
 }  }
   
Line 2930  snippets and collecting the results. Fin Line 3630  snippets and collecting the results. Fin
 helper, going to a provided page.  helper, going to a provided page.
   
 If the parameter "restartCourse" is true, this will override the buttons and  If the parameter "restartCourse" is true, this will override the buttons and
 will make a "Finish Helper" button that will re-initialize the course for them,  will make a Save button (Finish Helper) that will re-initialize the course for them,
 which is useful for the Course Initialization helper so the users never see  which is useful for the Course Initialization helper so the users never see
 the old values taking effect.  the old values taking effect.
   
   If the parameter "restartCourse" is not true a 'Finish' Button will be
   presented that takes the user back to whatever was defined as <exitpage>
   
 =cut  =cut
   
 no strict;  no strict;
 @ISA = ("Apache::lonhelper::element");  @ISA = ("Apache::lonhelper::element");
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::final',      &Apache::lonhelper::register('Apache::lonhelper::final',
                                  ('final', 'exitpage'));                                   ('final', 'exitpage'));
Line 2995  sub render { Line 3699  sub render {
     my @results;      my @results;
   
     # Collect all the results      # Collect all the results
     for my $stateName (keys %{$helper->{STATES}}) {      for my $stateName (keys(%{$helper->{STATES}})) {
         my $state = $helper->{STATES}->{$stateName};          my $state = $helper->{STATES}->{$stateName};
                   
         for my $element (@{$state->{ELEMENTS}}) {          for my $element (@{$state->{ELEMENTS}}) {
Line 3031  sub render { Line 3735  sub render {
  $result .= '</ul>';   $result .= '</ul>';
     }      }
   
       my $actionURL = $self->{EXIT_PAGE};
       my $targetURL = '';
    my $finish=&mt('Save');
     if ($self->{'restartCourse'}) {      if ($self->{'restartCourse'}) {
  my $targetURL = '/adm/menu';   $actionURL = '/adm/roles';
  if ($ENV{'course.'.$ENV{'request.course.id'}.'.url'}=~/^uploaded/) {   $targetURL = '/adm/menu';
    if ($env{'course.'.$env{'request.course.id'}.'.url'}=~/^uploaded/) {
     $targetURL = '/adm/coursedocs';      $targetURL = '/adm/coursedocs';
  } else {   } else {
     $targetURL = '/adm/navmaps';      $targetURL = '/adm/navmaps';
  }   }
  if ($ENV{'course.'.$ENV{'request.course.id'}.'.clonedfrom'}) {   if ($env{'course.'.$env{'request.course.id'}.'.clonedfrom'}) {
     $targetURL = '/adm/parmset?overview=1';      $targetURL = '/adm/parmset?overview=1';
  }   }
  my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"');  
  my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"');  
         $result .= "<center>\n" .  
             "<form action='/adm/roles' method='post' target='loncapaclient'>\n" .  
             "<input type='button' onclick='history.go(-1)' value='$previous' />" .  
             "<input type='hidden' name='orgurl' value='$targetURL' />" .  
             "<input type='hidden' name='selectrole' value='1' />\n" .  
             "<input type='hidden' name='" . $ENV{'request.role'} .   
             "' value='1' />\n<input type='submit' value='" .  
     &mt('Finish Course Initialization') . "' />\n" .  
             "</form></center>";  
     }      }
       my $previous = HTML::Entities::encode(&mt("Back"), '<>&"');
       my $next = HTML::Entities::encode(&mt("Next"), '<>&"');
       $result .= "<p>\n" .
    "<form action='".$actionURL."' method='post' >\n" .
    "<input type='button' onclick='history.go(-1)' value='$previous' />" .
    "<input type='hidden' name='orgurl' value='$targetURL' />" .
    "<input type='hidden' name='selectrole' value='1' />\n" .
    "<input type='hidden' name='" . $env{'request.role'} . 
    "' value='1' />\n<input type='submit' value='" . $finish . "' />\n" .
    "</form></p>\n";
   
     return $result;      return $result;
 }  }
   
 sub overrideForm {  sub overrideForm {
     my $self = shift;      return 1;
     return $self->{'restartCourse'};  
 }  }
   
 1;  1;
   
 package Apache::lonhelper::parmwizfinal;  package Apache::lonhelper::parmwizfinal;
   
 # This is the final state for the parmwizard. It is not generally useful,  # This is the final state for the parm helper. It is not generally useful,
 # so it is not perldoc'ed. It does its own processing.  # so it is not perldoc'ed. It does its own processing.
 # It is represented with <parmwizfinal />, and  # It is represented with <parmwizfinal />, and
 # should later be moved to lonparmset.pm .  # should later be moved to lonparmset.pm .
Line 3075  no strict; Line 3781  no strict;
 @ISA = ('Apache::lonhelper::element');  @ISA = ('Apache::lonhelper::element');
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
   use Apache::lonnet;
   
 BEGIN {  BEGIN {
     &Apache::lonhelper::register('Apache::lonhelper::parmwizfinal',      &Apache::lonhelper::register('Apache::lonhelper::parmwizfinal',
Line 3116  sub render { Line 3823  sub render {
                         'answer_date' => "0_answerdate",                          'answer_date' => "0_answerdate",
  'tries' => '0_maxtries',   'tries' => '0_maxtries',
  'weight' => '0_weight' );   'weight' => '0_weight' );
       my %realParmName = ('open_date' => "opendate",
                           'due_date' => "duedate",
                           'answer_date' => "answerdate",
    'tries' => 'maxtries',
    'weight' => 'weight' );
           
     my $affectedResourceId = "";      my $affectedResourceId = "";
     my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}};      my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}};
Line 3123  sub render { Line 3835  sub render {
     my $resourceString;      my $resourceString;
     my $symb;      my $symb;
     my $paramlevel;      my $paramlevel;
       
     # Print the granularity, depending on the action      # Print the granularity, depending on the action
     if ($vars->{GRANULARITY} eq 'whole_course') {      if ($vars->{GRANULARITY} eq 'whole_course') {
         $resourceString .= '<li>for <b>all resources in the course</b></li>';          $resourceString .= '<li>'.&mt('for [_1]all resources in the course[_2]','<b>','</b>').'</li>';
         $level = 9; # general course, see lonparmset.pm perldoc   if ($vars->{TARGETS} eq 'course') {
       $level = 14; # general course, see lonparmset.pm perldoc
    } elsif ($vars->{TARGETS} eq 'section') {
       $level = 9;
    } elsif ($vars->{TARGETS} eq 'group') {
       $level = 6;
    } else {
       $level = 3;
    }
         $affectedResourceId = "0.0";          $affectedResourceId = "0.0";
         $symb = 'a';          $symb = 'a';
         $paramlevel = 'general';          $paramlevel = 'general';
     } elsif ($vars->{GRANULARITY} eq 'map') {      } elsif ($vars->{GRANULARITY} eq 'map') {
         my $navmap = Apache::lonnavmaps::navmap->new();          my $navmap = Apache::lonnavmaps::navmap->new();
         my $res = $navmap->getByMapPc($vars->{RESOURCE_ID});          if (defined($navmap)) {
         my $title = $res->compTitle();               my $res = $navmap->getByMapPc($vars->{RESOURCE_ID});
         $symb = $res->symb();               my $title = $res->compTitle();
         $navmap->untieHashes();               $symb = $res->symb();
         $resourceString .= "<li>for the map named <b>$title</b></li>";               $resourceString .= '<li>'.&mt('for the map named [_1]',"<b>$title</b>").'</li>';
         $level = 8;          } else {
               $resourceString .= '<li>'.&mt('for the map ID [_1] (name unavailable)','<b>'.$vars->{RESOURCE_ID}.'</b>').'</li>';
               &Apache::lonnet::logthis('Retrieval of map title failed in lonhelper.pm - could not create navmap object for course.');
   
           }
    if ($vars->{TARGETS} eq 'course') {
       $level = 13; # general course, see lonparmset.pm perldoc
    } elsif ($vars->{TARGETS} eq 'section') {
       $level = 8;
    } elsif ($vars->{TARGETS} eq 'group') {
       $level = 5;
    } else {
       $level = 2;
    }
         $affectedResourceId = $vars->{RESOURCE_ID};          $affectedResourceId = $vars->{RESOURCE_ID};
         $paramlevel = 'map';          $paramlevel = 'map';
     } else {      } else {
           my $part = $vars->{RESOURCE_ID_part};
    if ($part ne 'All Parts' && $part) { $parm_name=~s/^0/$part/; } else { $part=&mt('All Parts'); }
         my $navmap = Apache::lonnavmaps::navmap->new();          my $navmap = Apache::lonnavmaps::navmap->new();
         my $res = $navmap->getById($vars->{RESOURCE_ID});          if (defined($navmap)) {
         $symb = $res->symb();              my $res = $navmap->getById($vars->{RESOURCE_ID});
         my $title = $res->compTitle();              $symb = $res->symb();
         $navmap->untieHashes();              my $title = $res->compTitle();
         $resourceString .= "<li>for the resource named <b>$title</b></li>";              $resourceString .= '<li>'.&mt('for the resource named [_1], part [_2]',"<b>$title</b>","<b>$part</b>").'</li>';
         $level = 7;          } else {
               $resourceString .= '<li>'.&mt('for the resource ID [_1] (name unavailable), part [_2]','<b>'.$vars->{RESOURCE_ID}.'</b>',"<b>$part</b>").'</li>';
               &Apache::lonnet::logthis('Retrieval of resource title failed in lonhelper.pm - could not create navmap object for course.');
           }
    if ($vars->{TARGETS} eq 'course') {
       $level = 10; # general course, see lonparmset.pm perldoc
    } elsif ($vars->{TARGETS} eq 'section') {
       $level = 7;
    } elsif ($vars->{TARGETS} eq 'group') {
       $level = 4;
    } else {
       $level = 1;
    }
         $affectedResourceId = $vars->{RESOURCE_ID};          $affectedResourceId = $vars->{RESOURCE_ID};
         $paramlevel = 'full';          $paramlevel = 'full';
     }      }
   
     my $result = "<form name='helpform' method='get' action='/adm/parmset#$affectedResourceId&$parm_name&$level'>\n";      my $result = "<form name='helpform' method='post' action='/adm/parmset#$affectedResourceId&$parm_name&$level'>\n";
     $result .= '<p>'.&mt('Confirm that this information is correct, then click &quot;Finish Helper&quot; to complete setting the parameter.').'<ul>';      $result .= "<input type='hidden' name='action' value='settable' />\n";
       $result .= "<input type='hidden' name='dis' value='helper' />\n";
       $result .= "<input type='hidden' name='pscat' value='".
    $realParmName{$vars->{ACTION_TYPE}}."' />\n";
       if ($vars->{GRANULARITY} eq 'resource') {
    $result .= "<input type='hidden' name='symb' value='".
       HTML::Entities::encode($symb,"'<>&\"") . "' />\n";
       } elsif ($vars->{GRANULARITY} eq 'map') {
    $result .= "<input type='hidden' name='pschp' value='".
       $affectedResourceId."' />\n";
       }
       my $part = $vars->{RESOURCE_ID_part};
       if ($part eq 'All Parts' || !$part) { $part=0; }
       $result .= "<input type='hidden' name='psprt' value='".
    HTML::Entities::encode($part,"'<>&\"") . "' />\n";
   
       $result .= '<p class="LC_info">'
                 .&mt('Confirm that this information is correct, then click &quot;Save&quot; to complete setting the parameter.')
                 .'</p>'
                 .'<ul>';
           
     # Print the type of manipulation:      # Print the type of manipulation:
     $result .= '<li>'.&mt('Setting the').' <b>' . &mt($dateTypeHash{$vars->{ACTION_TYPE}}) . '</b>';      my $extra;
     if ($vars->{ACTION_TYPE} eq 'tries') {      if ($vars->{ACTION_TYPE} eq 'tries') {
  $result .= ' '.&mt('to').' <b>' . $vars->{TRIES} . '</b>';   $extra =  $vars->{TRIES};
     }      }
     if ($vars->{ACTION_TYPE} eq 'weight') {      if ($vars->{ACTION_TYPE} eq 'weight') {
  $result .= ' '.&mt('to').' <b>' . $vars->{WEIGHT} . '</b>';   $extra =  $vars->{WEIGHT};
       }
       $result .= "<li>";
       my $what = &mt($dateTypeHash{$vars->{ACTION_TYPE}});
       if ($extra) {
    $result .= &mt('Setting the [_1] to [_2]',"<b>$what</b>",$extra);
       } else {
    $result .= &mt('Setting the [_1]',"<b>$what</b>");
     }      }
     $result .= "</li>\n";      $result .= "</li>\n";
     if ($vars->{ACTION_TYPE} eq 'due_date' ||       if ($vars->{ACTION_TYPE} eq 'due_date' || 
Line 3184  sub render { Line 3957  sub render {
     } elsif ($vars->{ACTION_TYPE} eq 'tries') {      } elsif ($vars->{ACTION_TYPE} eq 'tries') {
  $result .= "<input type='hidden' name='pres_value' " .   $result .= "<input type='hidden' name='pres_value' " .
     "value='" . $vars->{TRIES} . "' />\n";      "value='" . $vars->{TRIES} . "' />\n";
           $result .= "<input type='hidden' name='pres_type' " .
               "value='int_pos' />\n";
     } elsif ($vars->{ACTION_TYPE} eq 'weight') {      } elsif ($vars->{ACTION_TYPE} eq 'weight') {
  $result .= "<input type='hidden' name='pres_value' " .   $result .= "<input type='hidden' name='pres_value' " .
     "value='" . $vars->{WEIGHT} . "' />\n";      "value='" . $vars->{WEIGHT} . "' />\n";
Line 3193  sub render { Line 3968  sub render {
           
     # Print targets      # Print targets
     if ($vars->{TARGETS} eq 'course') {      if ($vars->{TARGETS} eq 'course') {
         $result .= '<li>'.&mt('for').' <b>'.&mt('all students in course').'</b></li>';          $result .= '<li>'.&mt('for [_1]all students in course[_2]','<b>','</b>').'</li>';
     } elsif ($vars->{TARGETS} eq 'section') {      } elsif ($vars->{TARGETS} eq 'section') {
         my $section = $vars->{SECTION_NAME};          my $section = $vars->{SECTION_NAME};
         $result .= "<li>for section <b>$section</b></li>";          $result .= '<li>'.&mt('for section [_1]',"<b>$section</b>").'</li>';
         $level -= 3;   $result .= "<input type='hidden' name='csec' value='" .
         $result .= "<input type='hidden' name='csec' value='" .              HTML::Entities::encode($section,"'<>&\"") . "' />\n";
             HTML::Entities::encode($section,'<>&"') . "' />\n";      } elsif ($vars->{TARGETS} eq 'group') {
           my $group = $vars->{GROUP_NAME};
           $result .= '<li>'.&mt('for group [_1]',"<b>$group</b>").'</li>';
           $result .= "<input type='hidden' name='cgroup' value='" .
               HTML::Entities::encode($group,"'<>&\"") . "' />\n";
     } else {      } else {
         # FIXME: This is probably wasteful! Store the name!          # FIXME: This is probably wasteful! Store the name!
         my $classlist = Apache::loncoursedata::get_classlist();          my $classlist = Apache::loncoursedata::get_classlist();
         my $username = $vars->{USER_NAME};   my ($uname,$udom)=split(':',$vars->{USER_NAME});
         # Chop off everything after the last colon (section)          my $name = $classlist->{$uname.':'.$udom}->[6];
         $username = substr($username, 0, rindex($username, ':'));          $result .= '<li>'.&mt('for [_1]',"<b>$name</b>").'</li>';
         my $name = $classlist->{$username}->[6];  
         $result .= "<li>for <b>$name</b></li>";  
         $level -= 6;  
         my ($uname, $udom) = split /:/, $vars->{USER_NAME};  
         $result .= "<input type='hidden' name='uname' value='".          $result .= "<input type='hidden' name='uname' value='".
             HTML::Entities::encode($uname,'<>&"') . "' />\n";              HTML::Entities::encode($uname,"'<>&\"") . "' />\n";
         $result .= "<input type='hidden' name='udom' value='".          $result .= "<input type='hidden' name='udom' value='".
             HTML::Entities::encode($udom,'<>&"') . "' />\n";              HTML::Entities::encode($udom,"'<>&\"") . "' />\n";
     }      }
   
     # Print value      # Print value
     if ($vars->{ACTION_TYPE} ne 'tries' && $vars->{ACTION_TYPE} ne 'weight') {      if ($vars->{ACTION_TYPE} ne 'tries' && $vars->{ACTION_TYPE} ne 'weight') {
  $result .= "<li>to <b>" . ctime($vars->{PARM_DATE}) . "</b> (" .          my $showdate = &Apache::lonlocal::locallocaltime($vars->{PARM_DATE});
     Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE})    $result .= '<li>'.&mt('to [_1] ([_2])',"<b>".$showdate."</b>",Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}))."</li>\n";
     . ")</li>\n";  
     }      }
   
    $result .= '</ul>';
     
   # FIXME: Make previous button working
   #        Found to be dysfunctional when used to change the selected student
   #   my $previous = HTML::Entities::encode(&mt("Back"), '<>&"');
       my $buttons .= '<p><span class="LC_nobreak">'
   #                 .'<input name="back" type="button"'
   #                 .' value="'.$previous.'" onclick="history.go(-1)" />'
                     .' <input type="submit" value="'.&mt('Save').'" />' # Finish Helper
                     .'</span></p>'."\n";
   
     # print pres_marker      # print pres_marker
     $result .= "\n<input type='hidden' name='pres_marker'" .      $result .= "\n<input type='hidden' name='pres_marker'" .
         " value='$affectedResourceId&$parm_name&$level' />\n";          " value='$affectedResourceId&$parm_name&$level' />\n";
           
     # Make the table appear      # Make the table appear
     $result .= "\n<input type='hidden' value='true' name='prevvisit' />";      $result .= "\n<input type='hidden' value='true' name='prevvisit' />";
     $result .= "\n<input type='hidden' value='all' name='pschp' />";  
     $result .= "\n<input type='hidden' value='$symb' name='pssymb' />";      $result .= "\n<input type='hidden' value='$symb' name='pssymb' />";
     $result .= "\n<input type='hidden' value='$paramlevel' name='parmlev' />";      $result .= "\n<input type='hidden' value='$paramlevel' name='parmlev' />";
   
     $result .= "<br /><br /><center><input type='submit' value='".&mt('Finish Helper')."' /></center></form>\n";      $result .= $buttons;
   
     return $result;      return $result;
 }  }

Removed from v.1.71  
changed lines
  Added in v.1.197.2.2.2.2


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