--- loncom/interface/lonhelper.pm 2003/09/02 20:58:31 1.44 +++ loncom/interface/lonhelper.pm 2003/10/09 16:27:26 1.57 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.44 2003/09/02 20:58:31 bowersj2 Exp $ +# $Id: lonhelper.pm,v 1.57 2003/10/09 16:27:26 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -172,12 +172,20 @@ before parsing XML fragments and Bheader_only) { if ($ENV{'browser.mathml'}) { - $r->content_type('text/xml'); + $r->content_type('text/xml; charset=UTF-8'); } else { - $r->content_type('text/html'); + $r->content_type('text/html; charset=UTF-8'); } $r->send_http_header; return OK; @@ -359,9 +367,10 @@ sub end_state { package Apache::lonhelper::helper; use Digest::MD5 qw(md5_hex); -use HTML::Entities; +use HTML::Entities(); use Apache::loncommon; use Apache::File; +use Apache::lonlocal; sub new { my $proto = shift; @@ -523,7 +532,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 "Next ->") { + if ($self->{STATE} ne "START" || $ENV{"form.SUBMIT"} eq &mt("Next ->")) { my $prevState = $self->{STATES}{$self->{STATE}}; $prevState->postprocess(); } @@ -574,13 +583,19 @@ sub display { } # Phase 4: Display. - my $stateTitle = $state->title(); - my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'',''); + my $stateTitle = &mt($state->title()); + my $helperTitle = &mt($self->{TITLE}); + my $bodytag = &Apache::loncommon::bodytag($helperTitle,'',''); + my $previous = HTML::Entities::encode(&mt("<- Previous"), '<>&"'); + my $next = HTML::Entities::encode(&mt("Next ->"), '<>&"'); + # FIXME: This should be parameterized, not concatenated - Jeremy + my $loncapaHelper = &mt("LON-CAPA Helper:"); $result .= < - LON-CAPA Helper: $self->{TITLE} + + $loncapaHelper: $helperTitle $bodytag HEADER @@ -607,12 +622,12 @@ HEADER } if ($self->{DONE}) { my $returnPage = $self->{RETURN_PAGE}; - $result .= "End Helper"; + $result .= "" . &mt("End Helper") . ""; } else { $result .= ' '; + $result .= ''; } } @@ -626,12 +641,12 @@ HEADER } if ($self->{DONE}) { my $returnPage = $self->{RETURN_PAGE}; - $result .= "End Helper"; + $result .= "" . &mt('End Helper') . ""; } else { $result .= ' '; + $result .= ''; } } @@ -883,6 +898,7 @@ sub start_defaultvalue { sub end_defaultvalue { return ''; } +# Validators may need to take language specifications sub start_validator { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; @@ -926,7 +942,9 @@ package Apache::lonhelper::message; =pod -=head1 Element: messageX +=head1 Elements + +=head2 Element: messageX Message elements display their contents, and transition directly to the state in the attribute. Example: @@ -950,11 +968,17 @@ within each other.) This is also a good template for creating your own new states, as it has very little code beyond the state template. +=head3 Localization + +The contents of the message tag 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::message', @@ -996,7 +1020,7 @@ sub end_message { sub render { my $self = shift; - return $self->{MESSAGE_TEXT}; + return &mtn($self->{MESSAGE_TEXT}); } # If a NEXTSTATE was given, switch to it sub postprocess { @@ -1098,6 +1122,7 @@ tag is stored in the {VARS} hash. no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::choices', @@ -1251,7 +1276,7 @@ BUTTONS $choiceLabel = eval($choiceLabel); $choiceLabel = &$choiceLabel($helper, $self); } - $result .= "/> " . $choiceLabel . "\n"; + $result .= "/> " . &mtn($choiceLabel) . "\n"; } $result .= "\n\n\n"; $result .= $buttons; @@ -1310,9 +1335,13 @@ the result is stored in. =cut +# This really ought to be a sibling class to "choice" which is itself +# a child of some abstract class.... *shrug* + no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::dropdown', @@ -1402,7 +1431,7 @@ sub render { $choiceLabel = eval($choiceLabel); $choiceLabel = &$choiceLabel($helper, $self); } - $result .= ">" . $choiceLabel . "\n"; + $result .= ">" . &mtn($choiceLabel) . "\n"; } $result .= "\n"; @@ -1471,6 +1500,7 @@ Example: no strict; @ISA = ("Apache::lonhelper::element"); use strict; +use Apache::lonlocal; # A localization nightmare use Time::localtime; @@ -1535,7 +1565,7 @@ sub render { } else { $result .= "\n"; + $result .= &mt($months[$i]) . "\n"; } $result .= "\n"; @@ -1622,17 +1652,26 @@ sub postprocess { $hour = $ENV{'form.' . $var . 'hour'}; } - my $chosenDate = Time::Local::timelocal(0, $min, $hour, $day, $month, $year); + 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 leapyear + # 3, depending on if it's a leap year my $checkDate = localtime($chosenDate); - if ($checkDate->mon != $month || $checkDate->mday != $day || + 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; + } + # 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."; + return 0; } @@ -1667,7 +1706,8 @@ resources in that sequence, or recurses to false. The "suppressEmptySequences" attribute reflects the suppressEmptySequences argument to the render routine, which will cause folders that have all of their contained resources filtered out to also -be filtered out. +be filtered out. The 'addstatus' attribute, if true, will add the icon +and long status display columns to the display. =head3 SUB-TAGS @@ -1695,7 +1735,10 @@ be filtered out. default, the value will be the resource ID of the object ($res->{ID}). =item * X: If the URL of a map is given here, only that map - will be displayed, instead of the whole course. + will be displayed, instead of the whole course. If the attribute + "evaluate" is given and is true, the contents of the mapurl will be + evaluated with "sub { my $helper = shift; my $state = shift;" and + "}", with the return value used as the mapurl. =back @@ -1730,6 +1773,7 @@ sub start_resource { $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; $paramHash->{'suppressEmptySequences'} = $token->[2]{'suppressEmptySequences'}; $paramHash->{'toponly'} = $token->[2]{'toponly'}; + $paramHash->{'addstatus'} = $token->[2]{'addstatus'}; return ''; } @@ -1806,6 +1850,7 @@ sub start_mapurl { my $contents = Apache::lonxml::get_all_text('/mapurl', $parser); + $paramHash->{EVAL_MAP_URL} = $token->[2]{'evaluate'}; $paramHash->{MAP_URL} = $contents; } @@ -1861,9 +1906,18 @@ BUTTONS my $filterFunc = $self->{FILTER_FUNC}; my $choiceFunc = $self->{CHOICE_FUNC}; my $valueFunc = $self->{VALUE_FUNC}; - my $mapUrl = $self->{MAP_URL}; my $multichoice = $self->{'multichoice'}; + # Evaluate the map url as needed + my $mapUrl; + if ($self->{EVAL_MAP_URL}) { + my $mapUrlFunc = eval('sub { my $helper = shift; my $state = shift; ' . + $self->{MAP_URL} . '}'); + $mapUrl = &$mapUrlFunc($helper, $self); + } else { + $mapUrl = $self->{MAP_URL}; + } + # 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 # - Jeremy (Pythonista) ;-) @@ -1895,9 +1949,13 @@ BUTTONS }; $ENV{'form.condition'} = !$self->{'toponly'}; + my $cols = [$renderColFunc, Apache::lonnavmaps::resource()]; + if ($self->{'addstatus'}) { + push @$cols, (Apache::lonnavmaps::part_status_summary()); + + } $result .= - &Apache::lonnavmaps::render( { 'cols' => [$renderColFunc, - Apache::lonnavmaps::resource()], + &Apache::lonnavmaps::render( { 'cols' => $cols, 'showParts' => 0, 'filterFunc' => $filterFunc, 'resource_no_folder_link' => 1, @@ -1936,10 +1994,30 @@ package Apache::lonhelper::student; Student elements display a choice of students enrolled in the current course. Currently it is primitive; this is expected to evolve later. -Student elements take three attributes: "variable", which means what -it usually does, "multichoice", which if true allows the user -to select multiple students, and "coursepersonnel" which if true -adds the course personnel to the top of the student selection. +Student elements take the following attributes: + +=over 4 + +=item * B: + +Does what it usually does: declare which helper variable to put the +result in. + +=item * B: + +If true allows the user to select multiple students. Defaults to false. + +=item * B: + +If true adds the course personnel to the top of the student +selection. Defaults to false. + +=item * B: + +If true, only active students and course personnel will be +shown. Defaults to false. + +=back =cut @@ -1970,6 +2048,7 @@ sub start_student { $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; $paramHash->{'coursepersonnel'} = $token->[2]{'coursepersonnel'}; + $paramHash->{'sctiveonly'} = $token->[2]{'activeonly'}; if (defined($token->[2]{'nextstate'})) { $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; } @@ -2002,12 +2081,30 @@ sub render { } } } + function checksec() { + for (i=0; i SCRIPT $buttons = < + + + 
BUTTONS } @@ -2042,6 +2139,7 @@ BUTTONS # Constants my $section = Apache::loncoursedata::CL_SECTION(); my $fullname = Apache::loncoursedata::CL_FULLNAME(); + my $status = Apache::loncoursedata::CL_STATUS(); # Load up the students my $classlist = &Apache::loncoursedata::get_classlist(); @@ -2056,8 +2154,13 @@ BUTTONS # username, fullname, section, type for (@keys) { - push @$choices, [$_, $classlist->{$_}->[$fullname], - $classlist->{$_}->[$section], 'Student']; + # Filter out inactive students if we've set "activeonly" + if (!$self->{'activeonly'} || $classlist->{$_}->[$status] eq + 'Active') { + push @$choices, [$_, $classlist->{$_}->[$fullname], + $classlist->{$_}->[$section], + $classlist->{$_}->[$status], 'Student']; + } } my $name = $self->{'coursepersonnel'} ? 'Name' : 'Student Name'; @@ -2066,7 +2169,9 @@ BUTTONS $result .= "\n"; $result .= "". "" . - ""; + "" . + "" . + ""; my $checked = 0; for my $choice (@$choices) { @@ -2078,13 +2183,18 @@ BUTTONS $checked = 1; } $result .= - " value='" . HTML::Entities::encode($choice->[0] . ':' . $choice->[2]) + " value='" . HTML::Entities::encode($choice->[0] . ':' . $choice->[2] . ':' . $choice->[1] . ':' . $choice->[3]) . "' />\n\n"; + . HTML::Entities::encode($choice->[3]) + . "\n\n\n"; } $result .= "
$nameSectionRole
StatusRoleUsername:Domain
" . HTML::Entities::encode($choice->[1]) . "" . HTML::Entities::encode($choice->[2]) . "" - . HTML::Entities::encode($choice->[3]) . "
" + . HTML::Entities::encode($choice->[4]) + . "" + . HTML::Entities::encode($choice->[0]) + . "
\n\n"; @@ -2302,9 +2412,17 @@ BUTTONS my @fileList; # If the subdirectory is in local CSTR space - if ($subdir =~ m|/home/([^/]+)/public_html|) { + my $metadir; + if ($subdir =~ m|/home/([^/]+)/public_html/(.*)|) { my $user = $1; my $domain = $Apache::lonnet::perlvar{'lonDefDomain'}; + $metadir='/res/'.$domain.'/'.$user.'/'.$2; + @fileList = &Apache::lonnet::dirlist($subdir, $domain, $user, ''); + } elsif ($subdir =~ m|^~([^/]+)/(.*)$|) { + $subdir='/home/'.$1.'/public_html/'.$2; + my $user = $1; + my $domain = $Apache::lonnet::perlvar{'lonDefDomain'}; + $metadir='/res/'.$domain.'/'.$user.'/'.$2; @fileList = &Apache::lonnet::dirlist($subdir, $domain, $user, ''); } else { # local library server resource space @@ -2343,7 +2461,7 @@ BUTTONS } # Get the title - my $title = Apache::lonpubdir::getTitleString($fileName); + my $title = Apache::lonpubdir::getTitleString(($metadir?$metadir:$subdir) .'/'. $file); # Netscape 4 is stupid and there's nowhere to put the # information on the input tag that the file is Published, @@ -2381,7 +2499,7 @@ BUTTONS $result .= "\n"; if (!$choices) { - $result .= 'There are no files available to select in this directory. Please go back and select another option.

'; + $result .= 'There are no files available to select in this directory ('.$subdir.'). Please go back and select another option.

'; } $result .= $buttons; @@ -2867,10 +2985,14 @@ sub render { } if ($self->{'restartCourse'}) { + my $targetURL = '/adm/menu'; + if ($ENV{'course.'.$ENV{'request.course.id'}.'.clonedfrom'}) { + $targetURL = '/adm/parmset?overview=1'; + } $result .= "
\n" . "
\n" . "" . - "" . + "" . "\n" . "\n\n" . @@ -2927,15 +3049,17 @@ sub render { my $vars = $helper->{VARS}; # FIXME: Unify my designators with the standard ones - my %dateTypeHash = ('open_date' => "Opening Date", - 'due_date' => "Due Date", - 'answer_date' => "Answer Date", - 'tries' => 'Number of Tries' + my %dateTypeHash = ('open_date' => "opening date", + 'due_date' => "due date", + 'answer_date' => "answer date", + 'tries' => 'number of tries', + 'weight' => 'problem weight' ); my %parmTypeHash = ('open_date' => "0_opendate", 'due_date' => "0_duedate", 'answer_date' => "0_answerdate", - 'tries' => '0_maxtries' ); + 'tries' => '0_maxtries', + 'weight' => '0_weight' ); my $affectedResourceId = ""; my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}}; @@ -2981,6 +3105,9 @@ sub render { if ($vars->{ACTION_TYPE} eq 'tries') { $result .= ' to ' . $vars->{TRIES} . ''; } + if ($vars->{ACTION_TYPE} eq 'weight') { + $result .= ' to ' . $vars->{WEIGHT} . ''; + } $result .= "\n"; if ($vars->{ACTION_TYPE} eq 'due_date' || $vars->{ACTION_TYPE} eq 'answer_date') { @@ -3001,6 +3128,9 @@ sub render { } elsif ($vars->{ACTION_TYPE} eq 'tries') { $result .= "\n"; + } elsif ($vars->{ACTION_TYPE} eq 'weight') { + $result .= "\n"; } $result .= $resourceString; @@ -3031,7 +3161,7 @@ sub render { } # Print value - if ($vars->{ACTION_TYPE} ne 'tries') { + if ($vars->{ACTION_TYPE} ne 'tries' && $vars->{ACTION_TYPE} ne 'weight') { $result .= "
  • to " . ctime($vars->{PARM_DATE}) . " (" . Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}) . ")
  • \n";