--- loncom/interface/lonhelper.pm 2008/09/06 00:47:16 1.165 +++ loncom/interface/lonhelper.pm 2009/06/15 11:18:11 1.176 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.165 2008/09/06 00:47:16 raeburn Exp $ +# $Id: lonhelper.pm,v 1.176 2009/06/15 11:18:11 bisitz Exp $ # # Copyright Michigan State University Board of Trustees # @@ -188,6 +188,8 @@ 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 @@ -529,7 +531,7 @@ sub process { # 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 # 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}}; $prevState->postprocess(); } @@ -587,78 +589,75 @@ sub display { &Apache::loncommon::browser_and_searcher_javascript(). "\n".''; + # 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); - - my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"'); - my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"'); + $browser_searcher_js, + {'bread_crumbs' => $brcrum,}); + + my $previous = HTML::Entities::encode(&mt("Back"), '<>&"'); + my $next = HTML::Entities::encode(&mt("Next"), '<>&"'); # FIXME: This should be parameterized, not concatenated - Jeremy - if (!$state->overrideForm()) { $result.="
"; } + if (!$state->overrideForm()) { $result.=''; } if ($stateHelp) { - $stateHelp = &Apache::loncommon::help_open_topic($stateHelp); + $stateHelp = &Apache::loncommon::help_open_topic($stateHelp); } - $result .= < -

$stateTitle$stateHelp

-HEADER - - $result .= "
"; - if (!$state->overrideForm()) { - $result .= $self->_saveVars(); - } - $result .= $state->render(); - - $result .= ""; - - # Warning: Copy and pasted from below, because it's too much trouble to - # turn this into a subroutine + # Prepare buttons + my $buttons; if (!$state->overrideForm()) { if ($self->{STATE} ne $self->{START_STATE}) { #$result .= '  '; } + $buttons = '

'; # '

'; if ($self->{DONE}) { my $returnPage = $self->{RETURN_PAGE}; - $result .= "" . &mt("End Helper") . ""; + $buttons .= ''.&mt('End Helper').''; } else { - $result .= ' '; - $result .= ''; + $buttons .= '' + .' ' + .'' + .''; } + $buttons .= '

'; # '
'; } - $result .= "
"; - # Warning: Copy and pasted from above, because it's too much trouble to - # turn this into a subroutine + + $result .= '

'.$stateTitle.$stateHelp.'

'; + +# $result .= '
'; + + # Top buttons + $result .= $buttons; + + # Main content of current helper screen if (!$state->overrideForm()) { - if ($self->{STATE} ne $self->{START_STATE}) { - #$result .= '  '; - } - if ($self->{DONE}) { - my $returnPage = $self->{RETURN_PAGE}; - $result .= "" . &mt('End Helper') . ""; - } - else { - $result .= ' '; - $result .= ''; - } + $result .= $self->_saveVars(); } + $result .= $state->render(); + + # Bottom buttons + $result .= $buttons; + #foreach my $key (keys %{$self->{VARS}}) { # $result .= "|$key| -> " . $self->{VARS}->{$key} . "
"; #} - $result .= "
"; +# $result .= ''; $result .= < - - FOOTER @@ -1508,12 +1507,15 @@ sub postprocess { my $self = shift; my $chosenValue = $env{'form.' . $self->{'variable'} . '_forminput'}; + if (!defined($chosenValue) && !$self->{'allowempty'}) { $self->{ERROR_MSG} = &mt("You must choose one or more choices to continue."); return 0; } + + if (ref($chosenValue)) { $helper->{VARS}->{$self->{'variable'}} = join('|||', @$chosenValue); } @@ -1725,7 +1727,7 @@ no strict; use strict; use Apache::lonlocal; # A localization nightmare use Apache::lonnet; -use Time::localtime; +use DateTime; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::date', @@ -1775,14 +1777,13 @@ sub render { 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 = localtime($helper->{VARS}{$var}); + $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 ' . @@ -1790,17 +1791,17 @@ sub render { $time = &$valueFunc($helper, $self); if (lc($time) eq 'anytime') { $anytime=1; - $date = localtime(time); + $date = &get_date_object(time); $date->min(0); } elsif (defined($time) && $time ne 0) { - $date = localtime($time); + $date = &get_date_object($time); } else { # leave date undefined so it'll default to now } } if (!defined($date)) { - $date = localtime(time); + $date = &get_date_object(time); $date->min(0); } @@ -1817,12 +1818,12 @@ sub render { my $i; $result .= "\n"; @@ -1841,7 +1842,7 @@ sub render { # Year $result .= "\n"; } + $result .= ' '.$date->time_zone_short_name().' '; if ($self->{'anytime'}) { $result.=(< @@ -1923,7 +1925,8 @@ sub postprocess { if ($env{'form.' . $var . 'anytime'}) { $helper->{VARS}->{$var} = undef; } else { - my $month = $env{'form.' . $var . 'month'}; + my $month = $env{'form.' . $var . 'month'}; + $month ++; my $day = $env{'form.' . $var . 'day'}; my $year = $env{'form.' . $var . 'year'}; my $min = 0; @@ -1933,25 +1936,40 @@ sub postprocess { $hour = $env{'form.' . $var . 'hour'}; } - my $chosenDate; - eval {$chosenDate = Time::Local::timelocal(0, $min, $hour, $day, $month, $year);}; + 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 - my $checkDate = localtime($chosenDate); if ($error || $checkDate->mon != $month || $checkDate->mday != $day || - $checkDate->year + 1900 != $year) { + $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[$month] . " $day, $year as a " - . "date because it doesn't exist. Please enter a valid date."; + $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."; return 0; } @@ -1974,6 +1992,20 @@ sub postprocess { 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; package Apache::lonhelper::resource; @@ -2416,6 +2448,21 @@ sub postprocess { $self->{ERROR_MSG} = 'You must choose at least one resource to continue.'; 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})) { $helper->changeState($self->{NEXTSTATE}); @@ -3391,7 +3438,7 @@ snippets and collecting the results. Fin helper, going to a provided page. 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 the old values taking effect. @@ -3498,7 +3545,7 @@ sub render { my $actionURL = $self->{EXIT_PAGE}; my $targetURL = ''; - my $finish=&mt('Finish'); + my $finish=&mt('Save'); if ($self->{'restartCourse'}) { $actionURL = '/adm/roles'; $targetURL = '/adm/menu'; @@ -3510,21 +3557,19 @@ sub render { if ($env{'course.'.$env{'request.course.id'}.'.clonedfrom'}) { $targetURL = '/adm/parmset?overview=1'; } - my $finish=&mt('Finish Course Initialization'); } - my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"'); - my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"'); + my $previous = HTML::Entities::encode(&mt("Back"), '<>&"'); + my $next = HTML::Entities::encode(&mt("Next"), '<>&"'); my $target = " target='loncapaclient'"; - if (($env{'browser.interface'} eq 'textual') || - ($env{'environment.remote'} eq 'off')) { $target=''; } - $result .= "
\n" . + if ($env{'environment.remote'} eq 'off') { $target=''; } + $result .= "

\n" . "

\n" . "" . "" . "\n" . "\n\n" . - "
"; + "

\n"; return $result; } @@ -3603,7 +3648,7 @@ sub render { # Print the granularity, depending on the action if ($vars->{GRANULARITY} eq 'whole_course') { - $resourceString .= '
  • '.&mt('for all resources in the course').'
  • '; + $resourceString .= '
  • '.&mt('for [_1]all resources in the course[_2]','','').'
  • '; if ($vars->{TARGETS} eq 'course') { $level = 14; # general course, see lonparmset.pm perldoc } elsif ($vars->{TARGETS} eq 'section') { @@ -3618,10 +3663,16 @@ sub render { $paramlevel = 'general'; } elsif ($vars->{GRANULARITY} eq 'map') { my $navmap = Apache::lonnavmaps::navmap->new(); - my $res = $navmap->getByMapPc($vars->{RESOURCE_ID}); - my $title = $res->compTitle(); - $symb = $res->symb(); - $resourceString .= '
  • '.&mt('for the map named [_1]',"$title").'
  • '; + if (defined($navmap)) { + my $res = $navmap->getByMapPc($vars->{RESOURCE_ID}); + my $title = $res->compTitle(); + $symb = $res->symb(); + $resourceString .= '
  • '.&mt('for the map named [_1]',"$title").'
  • '; + } else { + $resourceString .= '
  • '.&mt('for the map ID [_1] (name unavailable)',''.$vars->{RESOURCE_ID}.'').'
  • '; + &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') { @@ -3634,13 +3685,18 @@ sub render { $affectedResourceId = $vars->{RESOURCE_ID}; $paramlevel = 'map'; } else { - my $navmap = Apache::lonnavmaps::navmap->new(); - my $res = $navmap->getById($vars->{RESOURCE_ID}); my $part = $vars->{RESOURCE_ID_part}; if ($part ne 'All Parts' && $part) { $parm_name=~s/^0/$part/; } else { $part=&mt('All Parts'); } - $symb = $res->symb(); - my $title = $res->compTitle(); - $resourceString .= '
  • '.&mt('for the resource named [_1] part [_2]',"$title","$part").'
  • '; + my $navmap = Apache::lonnavmaps::navmap->new(); + if (defined($navmap)) { + my $res = $navmap->getById($vars->{RESOURCE_ID}); + $symb = $res->symb(); + my $title = $res->compTitle(); + $resourceString .= '
  • '.&mt('for the resource named [_1], part [_2]',"$title","$part").'
  • '; + } else { + $resourceString .= '
  • '.&mt('for the resource ID [_1] (name unavailable), part [_2]',''.$vars->{RESOURCE_ID}.'',"$part").'
  • '; + &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') { @@ -3654,7 +3710,7 @@ sub render { $paramlevel = 'full'; } - my $result = "
    \n"; + my $result = "\n"; $result .= "\n"; $result .= "\n"; $result .= "&\"") . "' />\n"; - $result .= '

    '.&mt('Confirm that this information is correct, then click "Finish Helper" to complete setting the parameter.').'

      '; + $result .= '

      ' + .&mt('Confirm that this information is correct, then click "Save" to complete setting the parameter.') + .'

      ' + .'
        '; # Print the type of manipulation: my $extra; @@ -3719,7 +3778,7 @@ sub render { # Print targets if ($vars->{TARGETS} eq 'course') { - $result .= '
      • '.&mt('for all students in course').'
      • '; + $result .= '
      • '.&mt('for [_1]all students in course[_2]','','').'
      • '; } elsif ($vars->{TARGETS} eq 'section') { my $section = $vars->{SECTION_NAME}; $result .= '
      • '.&mt('for section [_1]',"$section").'
      • '; @@ -3744,9 +3803,21 @@ sub render { # Print value if ($vars->{ACTION_TYPE} ne 'tries' && $vars->{ACTION_TYPE} ne 'weight') { - $result .= '
      • '.&mt('to [_1] ([_2])',"".ctime($vars->{PARM_DATE})."",Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}))."
      • \n"; + my $showdate = &Apache::lonlocal::locallocaltime($vars->{PARM_DATE}); + $result .= '
      • '.&mt('to [_1] ([_2])',"".$showdate."",Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}))."
      • \n"; } + + $result .= '
      '; +# 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 .= '

      ' +# .'' + .' ' # Finish Helper + .'

      '."\n"; + # print pres_marker $result .= "\n\n"; @@ -3756,7 +3827,7 @@ sub render { $result .= "\n"; $result .= "\n"; - $result .= "

      \n"; + $result .= $buttons; return $result; }