--- loncom/interface/lonhelper.pm 2003/04/11 19:07:48 1.10 +++ loncom/interface/lonhelper.pm 2003/05/05 18:05:21 1.19 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.10 2003/04/11 19:07:48 bowersj2 Exp $ +# $Id: lonhelper.pm,v 1.19 2003/05/05 18:05:21 bowersj2 Exp $ # # Copyright Michigan State University Board of Trustees # @@ -84,6 +84,77 @@ Of course this does nothing. In order fo necessary to put actual elements into the wizard. Documentation for each of these elements follows. +=head2 Creating a Helper With Code, Not XML + +In some situations, such as the printing wizard (see lonprintout.pm), +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 +possible to create a helper via code, though it is a little odd. + +Creating a helper via code is more like issuing commands to create +a helper then normal code writing. For instance, elements will automatically +be added to the last state created, so it's important to create the +states in the correct order. + +First, create a new helper: + + use Apache::lonhelper; + + my $helper = Apache::lonhelper::new->("Helper Title"); + +Next you'll need to manually add states to the helper: + + Apache::lonhelper::state->new("STATE_NAME", "State's Human Title"); + +You don't need to save a reference to it because all elements up until +the next state creation will automatically be added to this state. + +Elements are created by populating the $paramHash in +Apache::lonhelper::paramhash. To prevent namespace issues, retrieve +a reference to that has with getParamHash: + + my $paramHash = Apache::lonhelper::getParamHash(); + +You will need to do this for each state you create. + +Populate the $paramHash with the parameters for the element you wish +to add next; the easiest way to find out what those entries are is +to read the code. Some common ones are 'variable' to record the variable +to store the results in, and NEXTSTATE to record a next state transition. + +Then create your element: + + $paramHash->{MESSAGETEXT} = "This is a message."; + Apache::lonhelper::message->new(); + +The creation will take the $paramHash and bless it into a +Apache::lonhelper::message object. To create the next element, you need +to get a reference to the new, empty $paramHash: + + $paramHash = Apache::lonhelper::getParamHash(); + +and you can repeat creating elements that way. You can add states +and elements as needed. + +See lonprintout.pm, subroutine printHelper for an example of this, where +we dynamically add some states to prevent security problems, for instance. + +Normally the machinery in the XML format is sufficient; dynamically +adding states can easily be done by wrapping the state in a +tag. This should only be used when the code dominates the XML content, +the code is so complicated that it is difficult to get access to +all of the information you need because of scoping issues, or so much +of the information used is persistent because would-be or + blocks that using the {DATA} mechanism results in hard-to-read +and -maintain code. + +It is possible to do some of the work with an XML fragment parsed by +lonxml; again, see lonprintout.pm for an example. In that case it is +imperative that you call B +before parsing XML fragments and B +when you are done. See lonprintout.pm for examples of this usage in the +printHelper subroutine. + =cut package Apache::lonhelper; @@ -122,16 +193,19 @@ my $substate; # end of the element tag is located. my $paramHash; +# For debugging purposes, one can send a second parameter into this +# function, the 'uri' of the helper you wish to have rendered, and +# call this from other handlers. sub handler { my $r = shift; - $ENV{'request.uri'} = $r->uri(); - my $filename = '/home/httpd/html' . $r->uri(); + my $uri = shift; + if (!defined($uri)) { $uri = $r->uri(); } + $ENV{'request.uri'} = $uri; + my $filename = '/home/httpd/html' . $uri; my $fh = Apache::File->new($filename); my $file; read $fh, $file, 100000000; - Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); - # Send header, don't cache this page if ($r->header_only) { if ($ENV{'browser.mathml'}) { @@ -154,10 +228,24 @@ sub handler { # xml parsing &Apache::lonxml::xmlparse($r, 'helper', $file); + $helper->process(); + $r->print($helper->display()); return OK; } +sub registerHelperTags { + for my $tagList (@helperTags) { + Apache::lonxml::register($tagList->[0], $tagList->[1]); + } +} + +sub unregisterHelperTags { + for my $tagList (@helperTags) { + Apache::lonxml::deregister($tagList->[0], $tagList->[1]); + } +} + sub start_helper { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; @@ -165,11 +253,9 @@ sub start_helper { return ''; } - for my $tagList (@helperTags) { - Apache::lonxml::register($tagList->[0], $tagList->[1]); - } - - $helper = Apache::lonhelper::helper->new($token->[2]{'title'}); + registerHelperTags(); + + Apache::lonhelper::helper->new($token->[2]{'title'}); return ''; } @@ -180,9 +266,7 @@ sub end_helper { return ''; } - for my $tagList (@helperTags) { - Apache::lonxml::deregister($tagList->[0], $tagList->[1]); - } + unregisterHelperTags(); return ''; } @@ -194,11 +278,22 @@ sub start_state { return ''; } - $state = Apache::lonhelper::state->new($token->[2]{'name'}, - $token->[2]{'title'}); + Apache::lonhelper::state->new($token->[2]{'name'}, + $token->[2]{'title'}); return ''; } +# Use this to get the param hash from other files. +sub getParamHash { + return $paramHash; +} + +# Use this to get the helper, if implementing elements in other files +# (like lonprintout.pm) +sub getHelper { + return $helper; +} + # don't need this, so ignore it sub end_state { return ''; @@ -231,6 +326,8 @@ sub new { $self->{STATE} = "START"; } + Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING}); + $self->{TOKEN} = $ENV{'form.TOKEN'}; # If a token was passed, we load that in. Otherwise, we need to create a # new storage file @@ -287,6 +384,11 @@ sub new { # for an example. $self->{DATA} = {}; + $helper = $self; + + # Establish the $paramHash + $paramHash = {}; + bless($self, $class); return $self; } @@ -347,23 +449,15 @@ sub registerState { $self->{STATES}{$stateName} = $state; } -# Done in four phases -# 1: Do the post processing for the previous state. -# 2: Do the preprocessing for the current state. -# 3: Check to see if state changed, if so, postprocess current and move to next. -# Repeat until state stays stable. -# 4: Render the current state to the screen as an HTML page. -sub display { +sub process { my $self = shift; - my $result = ""; - # 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 ->") { my $prevState = $self->{STATES}{$self->{STATE}}; - $prevState->postprocess(); + $prevState->postprocess(); } # Note, to handle errors in a state's input that a user must correct, @@ -372,25 +466,45 @@ sub display { # Phase 2: Preprocess current state my $startState = $self->{STATE}; - my $state = $self->{STATES}{$startState}; + my $state = $self->{STATES}->{$startState}; - # Error checking; it is intended that the developer will have - # checked all paths and the user can't see this! + # For debugging, print something here to determine if you're going + # to an undefined state. if (!defined($state)) { - $result .="Error! The state ". $startState ." is not defined."; - return $result; + return; } $state->preprocess(); # Phase 3: While the current state is different from the previous state, # keep processing. - while ( $startState ne $self->{STATE} ) + while ( $startState ne $self->{STATE} && + defined($self->{STATES}->{$self->{STATE}}) ) { $startState = $self->{STATE}; - $state = $self->{STATES}{$startState}; + $state = $self->{STATES}->{$startState}; $state->preprocess(); } + return; +} + +# 1: Do the post processing for the previous state. +# 2: Do the preprocessing for the current state. +# 3: Check to see if state changed, if so, postprocess current and move to next. +# Repeat until state stays stable. +# 4: Render the current state to the screen as an HTML page. +sub display { + my $self = shift; + + my $state = $self->{STATES}{$self->{STATE}}; + + my $result = ""; + + if (!defined($state)) { + $result = "Error: state '$state' not defined!"; + return $result; + } + # Phase 4: Display. my $stateTitle = $state->title(); my $bodytag = &Apache::loncommon::bodytag("$self->{TITLE}",'',''); @@ -402,7 +516,7 @@ sub display { $bodytag HEADER - if (!$state->overrideForm()) { $result.="
"; } + if (!$state->overrideForm()) { $result.=""; } $result .= <

$stateTitle

@@ -430,9 +544,9 @@ HEADER $result .= "\n"; } - foreach my $key (keys %{$self->{VARS}}) { - $result .= "|$key| -> " . $self->{VARS}->{$key} . "
"; - } + #foreach my $key (keys %{$self->{VARS}}) { + # $result .= "|$key| -> " . $self->{VARS}->{$key} . "
"; + #} $result .= < @@ -474,6 +588,8 @@ sub new { $helper->registerState($self); + $state = $self; + return $self; } @@ -517,7 +633,16 @@ sub postprocess { } } +# Override the form if any element wants to. +# two elements overriding the form will make a mess, but that should +# be considered helper author error ;-) sub overrideForm { + my $self = shift; + for my $element (@{$self->{ELEMENTS}}) { + if ($element->overrideForm()) { + return 1; + } + } return 0; } @@ -616,27 +741,28 @@ sub render { return ''; } +sub overrideForm { + return 0; +} + sub process_multiple_choices { my $self = shift; my $formname = shift; my $var = shift; - my $formvalue = $ENV{'form.' . $formname}; - if ($formvalue) { - # Must extract values from querystring directly, as there - # may be more then one. - my @values; - for my $formparam (split (/&/, $ENV{QUERY_STRING})) { - my ($name, $value) = split(/=/, $formparam); - if ($name ne $formname) { - next; - } - $value =~ tr/+/ /; - $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; - push @values, $value; + # Must extract values from data directly, as there + # may be more then one. + my @values; + for my $formparam (split (/&/, $ENV{QUERY_STRING})) { + my ($name, $value) = split(/=/, $formparam); + if ($name ne $formname) { + next; } - $helper->{VARS}->{$var} = join('|||', @values); + $value =~ tr/+/ /; + $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; + push @values, $value; } + $helper->{VARS}->{$var} = join('|||', @values); return; } @@ -766,6 +892,11 @@ B For example, Bobby McDormik. + can take a parameter "eval", which if set to + a true value, will cause the contents of the tag to be + evaluated as it would be in an tag; see tag + below. + may optionally contain a 'nextstate' attribute, which will be the state transisitoned to if the choice is made, if the choice is not multichoice. @@ -846,7 +977,9 @@ sub start_choice { my $human = &Apache::lonxml::get_all_text('/choice', $parser); my $nextstate = $token->[2]{'nextstate'}; - push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate]; + my $evalFlag = $token->[2]{'eval'}; + push @{$paramHash->{CHOICES}}, [$human, $computer, $nextstate, + $evalFlag]; return ''; } @@ -864,17 +997,20 @@ sub render { if ($self->{'multichoice'}) { $result .= < - function checkall(value) { - for (i=0; i SCRIPT $buttons = < - - + +
  BUTTONS } @@ -900,7 +1036,14 @@ BUTTONS $result .= " checked "; $checked = 1; } - $result .= "/> " . $choice->[0] . "\n"; + my $choiceLabel = $choice->[0]; + if ($choice->[4]) { # if we need to evaluate this choice + $choiceLabel = "sub { my $helper = shift; my $state = shift;" . + $choiceLabel . "}"; + $choiceLabel = eval($choiceLabel); + $choiceLabel = &$choiceLabel($helper, $self); + } + $result .= "/> " . $choiceLabel . "\n"; } $result .= "\n\n\n"; $result .= $buttons; @@ -1165,7 +1308,10 @@ the user can manipulate the folders. takes the standard variable attribute to control what helper variable stores the results. It also takes a "multichoice" attribute, -which controls whether the user can select more then one resource. +which controls whether the user can select more then one resource. The +"toponly" attribute controls whether the resource display shows just the +resources in that sequence, or recurses into all sub-sequences, defaulting +to false. B @@ -1192,6 +1338,9 @@ B "}" returns a string representing what you want to have as the value. By default, the value will be the resource ID of the object ($res->{ID}). +=item * : If the URL of a map is given here, only that map + will be displayed, instead of the whole course. + =back =cut @@ -1203,7 +1352,8 @@ use strict; BEGIN { &Apache::lonhelper::register('Apache::lonhelper::resource', ('resource', 'filterfunc', - 'choicefunc', 'valuefunc')); + 'choicefunc', 'valuefunc', + 'mapurl')); } sub new { @@ -1221,6 +1371,8 @@ sub start_resource { $paramHash->{'variable'} = $token->[2]{'variable'}; $helper->declareVar($paramHash->{'variable'}); + $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; + $paramHash->{'toponly'} = $token->[2]{'toponly'}; return ''; } @@ -1288,6 +1440,20 @@ sub start_valuefunc { sub end_valuefunc { return ''; } +sub start_mapurl { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + + my $contents = Apache::lonxml::get_all_text('/mapurl', + $parser); + $paramHash->{MAP_URL} = $contents; +} + +sub end_mapurl { return ''; } + # A note, in case I don't get to this before I leave. # If someone complains about the "Back" button returning them # to the previous folder state, instead of returning them to @@ -1306,13 +1472,40 @@ sub render { my $var = $self->{'variable'}; my $curVal = $helper->{VARS}->{$var}; + my $buttons = ''; + + if ($self->{'multichoice'}) { + $result = < + function checkall(value, checkName) { + for (i=0; i +SCRIPT + $buttons = <   + + +
  +BUTTONS + } + if (defined $self->{ERROR_MSG}) { - $result .= '' . $self->{ERROR_MSG} . '

'; + $result .= '
' . $self->{ERROR_MSG} . '

'; } + $result .= $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'}; # 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 @@ -1320,12 +1513,16 @@ sub render { my $checked = 0; my $renderColFunc = sub { my ($resource, $part, $params) = @_; - + + my $inputType; + if ($multichoice) { $inputType = 'checkbox'; } + else {$inputType = 'radio'; } + if (!&$choiceFunc($resource)) { return ' '; } else { - my $col = "{'toponly'}; $result .= &Apache::lonnavmaps::render( { 'cols' => [$renderColFunc, Apache::lonnavmaps::resource()], 'showParts' => 0, - 'url' => $helper->{URL}, 'filterFunc' => $filterFunc, - 'resource_no_folder_link' => 1 } + 'resource_no_folder_link' => 1, + 'iterator_map' => $mapUrl } ); + + $result .= $buttons; return $result; } sub postprocess { my $self = shift; + + if ($self->{'multichoice'}) { + $self->process_multiple_choices($self->{'variable'}.'.forminput', + $self->{'variable'}); + } + + if ($self->{'multichoice'} && !$helper->{VARS}->{$self->{'variable'}}) { + $self->{ERROR_MSG} = 'You must choose at least one resource to continue.'; + return 0; + } + if (defined($self->{NEXTSTATE})) { $helper->changeState($self->{NEXTSTATE}); } @@ -1401,6 +1611,10 @@ sub start_student { $paramHash->{'variable'} = $token->[2]{'variable'}; $helper->declareVar($paramHash->{'variable'}); $paramHash->{'multichoice'} = $token->[2]{'multichoice'}; + if (defined($token->[2]{'nextstate'})) { + $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; + } + } sub end_student { @@ -1416,21 +1630,25 @@ sub render { my $self = shift; my $result = ''; my $buttons = ''; + my $var = $self->{'variable'}; if ($self->{'multichoice'}) { $result = < - function checkall(value) { - for (i=0; i SCRIPT $buttons = < - - + +
BUTTONS } @@ -1441,7 +1659,6 @@ BUTTONS # Load up the students my $choices = &Apache::loncoursedata::get_classlist(); - my @keys = keys %{$choices}; # Constants @@ -1472,7 +1689,7 @@ BUTTONS $checked = 1; } $result .= - " value='" . HTML::Entities::encode($_) + " value='" . HTML::Entities::encode($_ . ':' . $choices->{$_}->[$section]) . "' />" . HTML::Entities::encode($choices->{$_}->[$fullname]) . "" @@ -1611,6 +1828,9 @@ sub render { my $var = $self->{'variable'}; my $subdirFunc = eval('sub {' . $self->{'filechoice'} . '}'); + die 'Error in resource filter code for variable ' . + {'variable'} . ', Perl said:' . $@ if $@; + my $subdir = &$subdirFunc(); my $filterFunc = $self->{FILTER_FUNC}; @@ -1619,20 +1839,20 @@ sub render { if ($self->{'multichoice'}) { $result = < - function checkall(value) { - for (i=0; i SCRIPT - my $buttons = <   - - + +
  BUTTONS } @@ -1718,6 +1938,80 @@ sub postprocess { 1; +package Apache::lonhelper::section; + +=pod + +=head2 Element: section + +
allows the user to choose one or more sections from the current +course. + +It takes the standard attributes "variable", "multichoice", and +"nextstate", meaning what they do for most other elements. + +=cut + +no strict; +@ISA = ("Apache::lonhelper::choices"); +use strict; + +BEGIN { + &Apache::lonhelper::register('Apache::lonhelper::section', + ('section')); +} + +sub new { + my $ref = Apache::lonhelper::choices->new(); + bless($ref); +} + +sub start_section { + 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'}; + if (defined($token->[2]{'nextstate'})) { + $paramHash->{NEXTSTATE} = $token->[2]{'nextstate'}; + } + + # Populate the CHOICES element + my %choices; + + my $section = Apache::loncoursedata::CL_SECTION(); + my $classlist = Apache::loncoursedata::get_classlist(); + foreach (keys %$classlist) { + my $sectionName = $classlist->{$_}->[$section]; + if (!$sectionName) { + $choices{"No section assigned"} = ""; + } else { + $choices{$sectionName} = $sectionName; + } + } + + for my $sectionName (sort(keys(%choices))) { + + push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName]; + } +} + +sub end_section { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + Apache::lonhelper::section->new(); +} +1; + package Apache::lonhelper::general; =pod @@ -1748,7 +2042,8 @@ be able to call methods on it. BEGIN { &Apache::lonhelper::register('Apache::lonhelper::general', - 'exec', 'condition', 'clause'); + 'exec', 'condition', 'clause', + 'eval'); } sub start_exec { @@ -1762,6 +2057,7 @@ sub start_exec { $code = eval ('sub { my $helper = shift; my $state = shift; ' . $code . "}"); + die 'Error in , Perl said: '. $@ if $@; &$code($helper, $paramHash); } @@ -1799,6 +2095,7 @@ sub start_clause { my $clause = Apache::lonxml::get_all_text('/clause', $parser); $clause = eval('sub { my $helper = shift; my $state = shift; ' . $clause . '}'); + die 'Error in clause of condition, Perl said: ' . $@ if $@; if (!&$clause($helper, $paramHash)) { # Discard all text until the /condition. &Apache::lonxml::get_all_text('/condition', $parser); @@ -1807,6 +2104,188 @@ sub start_clause { sub end_clause { return ''; } +=pod + +=head2 General-purpose tag: + +The tag will be evaluated as a subroutine call passed in the +current helper object and state hash as described in above, +but is expected to return a string to be printed directly to the +screen. This is useful for dynamically generating messages. + +=cut + +# This is basically a type of message. +# Programmatically setting $paramHash->{NEXTSTATE} would work, though +# it's probably bad form. + +sub start_eval { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + + my $program = Apache::lonxml::get_all_text('/eval', $parser); + $program = eval('sub { my $helper = shift; my $state = shift; ' + . $program . '}'); + die 'Error in eval code, Perl said: ' . $@ if $@; + $paramHash->{MESSAGE_TEXT} = &$program($helper, $paramHash); +} + +sub end_eval { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + + Apache::lonhelper::message->new(); +} + +1; + +package Apache::lonhelper::parmwizfinal; + +# This is the final state for the parmwizard. It is not generally useful, +# so it is not perldoc'ed. It does its own processing. +# It is represented with , and +# should later be moved to lonparmset.pm . + +no strict; +@ISA = ('Apache::lonhelper::element'); +use strict; + +BEGIN { + &Apache::lonhelper::register('Apache::lonhelper::parmwizfinal', + ('parmwizfinal')); +} + +use Time::localtime; + +sub new { + my $ref = Apache::lonhelper::choices->new(); + bless ($ref); +} + +sub start_parmwizfinal { return ''; } + +sub end_parmwizfinal { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + + if ($target ne 'helper') { + return ''; + } + Apache::lonhelper::parmwizfinal->new(); +} + +# Renders a form that, when submitted, will form the input to lonparmset.pm +sub render { + my $self = shift; + 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"); + my %parmTypeHash = ('open_date' => "0_opendate", + 'due_date' => "0_duedate", + 'answer_date' => "0_answerdate"); + + my $result = "\n"; + $result .= '

Confirm that this information is correct, then click "Finish Wizard" to complete setting the parameter.

    '; + my $affectedResourceId = ""; + my $parm_name = $parmTypeHash{$vars->{ACTION_TYPE}}; + my $level = ""; + + # Print the type of manipulation: + $result .= '
  • Setting the ' . $dateTypeHash{$vars->{ACTION_TYPE}} + . "
  • \n"; + if ($vars->{ACTION_TYPE} eq 'due_date' || + $vars->{ACTION_TYPE} eq 'answer_date') { + # for due dates, we default to "date end" type entries + $result .= "\n"; + $result .= "\n"; + $result .= "\n"; + } elsif ($vars->{ACTION_TYPE} eq 'open_date') { + $result .= "\n"; + $result .= "\n"; + $result .= "\n"; + } + + # Print the granularity, depending on the action + if ($vars->{GRANULARITY} eq 'whole_course') { + $result .= '
  • for all resources in the course
  • '; + $level = 9; # general course, see lonparmset.pm perldoc + $affectedResourceId = "0.0"; + } elsif ($vars->{GRANULARITY} eq 'map') { + my $navmap = Apache::lonnavmaps::navmap->new( + $ENV{"request.course.fn"}.".db", + $ENV{"request.course.fn"}."_parms.db", 0, 0); + my $res = $navmap->getById($vars->{RESOURCE_ID}); + my $title = $res->compTitle(); + $navmap->untieHashes(); + $result .= "
  • for the map named $title
  • "; + $level = 8; + $affectedResourceId = $vars->{RESOURCE_ID}; + } else { + my $navmap = Apache::lonnavmaps::navmap->new( + $ENV{"request.course.fn"}.".db", + $ENV{"request.course.fn"}."_parms.db", 0, 0); + my $res = $navmap->getById($vars->{RESOURCE_ID}); + my $title = $res->compTitle(); + $navmap->untieHashes(); + $result .= "
  • for the resource named $title
  • "; + $level = 7; + $affectedResourceId = $vars->{RESOURCE_ID}; + } + + # Print targets + if ($vars->{TARGETS} eq 'course') { + $result .= '
  • for all students in course
  • '; + } elsif ($vars->{TARGETS} eq 'section') { + my $section = $vars->{SECTION_NAME}; + $result .= "
  • for section $section
  • "; + $level -= 3; + $result .= "\n"; + } else { + # FIXME: This is probably wasteful! Store the name! + my $classlist = Apache::loncoursedata::get_classlist(); + my $name = $classlist->{$vars->{USER_NAME}}->[6]; + $result .= "
  • for $name
  • "; + $level -= 6; + my ($uname, $udom) = split /:/, $vars->{USER_NAME}; + $result .= "\n"; + $result .= "\n"; + } + + # Print value + $result .= "
  • to " . ctime($vars->{PARM_DATE}) . " (" . + Apache::lonnavmaps::timeToHumanString($vars->{PARM_DATE}) + . ")
  • \n"; + + # print pres_marker + $result .= "\n\n"; + + $result .= "

    \n"; + + return $result; +} + +sub overrideForm { + return 1; +} + 1; __END__