--- loncom/interface/lonhelper.pm 2006/05/09 22:43:19 1.147 +++ loncom/interface/lonhelper.pm 2008/12/13 04:36:28 1.166.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # .helper XML handler to implement the LON-CAPA helper # -# $Id: lonhelper.pm,v 1.147 2006/05/09 22:43:19 foxr Exp $ +# $Id: lonhelper.pm,v 1.166.2.1 2008/12/13 04:36:28 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -81,25 +81,28 @@ State tags are also required to have an human name of the state, and will be displayed as the header on top of 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 An example of the tags so far: - + -Of course this does nothing. In order for the wizard to do something, it is -necessary to put actual elements into the wizard. Documentation for each +Of course this does nothing. In order for the helper to do something, it is +necessary to put actual elements into the helper. Documentation for each of these elements follows. =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 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. @@ -183,7 +186,9 @@ use Apache::File; use Apache::lonxml; 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 # push and pop them @@ -332,7 +337,8 @@ sub start_state { } Apache::lonhelper::state->new($token->[2]{'name'}, - $token->[2]{'title'}); + $token->[2]{'title'}, + $token->[2]{'help'}); return ''; } @@ -362,6 +368,7 @@ use Apache::loncommon; use Apache::File; use Apache::lonlocal; use Apache::lonnet; +use LONCAPA; sub new { my $proto = shift; @@ -467,9 +474,8 @@ sub _saveVars { sub _varsInFile { my $self = shift; my @vars = (); - for my $key (keys %{$self->{VARS}}) { - push @vars, &Apache::lonnet::escape($key) . '=' . - &Apache::lonnet::escape($self->{VARS}->{$key}); + for my $key (keys(%{$self->{VARS}})) { + push(@vars, &escape($key) . '=' . &escape($self->{VARS}->{$key})); } return join ('&', @vars); } @@ -484,7 +490,7 @@ sub declareVar { $self->{VARS}->{$var} = ''; } - my $envname = 'form.' . $var . '.forminput'; + my $envname = 'form.' . $var . '_forminput'; if (defined($env{$envname})) { if (ref($env{$envname})) { $self->{VARS}->{$var} = join('|||', @{$env{$envname}}); @@ -575,6 +581,7 @@ sub display { # Phase 4: Display. my $stateTitle=&mt($state->title()); + my $stateHelp= $state->help(); my $browser_searcher_js = ' - + RADIO $env{'form.condition'} = !$self->{'toponly'}; @@ -2204,6 +2430,7 @@ RADIO 'resource_no_folder_link' => 1, 'closeAllPages' => $self->{'closeallpages'}, 'suppressEmptySequences' => $self->{'suppressEmptySequences'}, + 'include_top_level_map' => $self->{'include_top_level_map'}, 'iterator_map' => $mapUrl } ); @@ -2274,357 +2501,6 @@ no strict; use strict; use Apache::lonlocal; use Apache::lonnet; -# -# Utility function used when rendering tags. -# This function produces a list references to four -# arrays: -# (\@course_personel, \@current_members, \@expired_members, \@future_members) -# -# Where: -# course_personnel - Each element of this array is itself a reference to an array -# containing information about a member of the course staff. -# current_members - Each element of this array is itself a reference to an -# array that contains information about current students in -# the course. -# expired_members - Each element of this array is itself a reference to an -# array that contains information about students whose -# status has expired. -# future_members - Each element of this arrya is itself a reference to an -# array that contains information about students who will -# become active at a future date. -# -# Course personnel elements include: -# [0] Last, First of the user. -# [1] Role held by the user. -# [2] Empty. -# [3] Empty -# [4] username:domain of the user. -# -# Student member array elements are: -# [0] Last, First of the user. -# [1] Status of the user one of ("Active", "Future", or "Expired') -# depending on which array the user was put in. -# [2] Section the student is in. -# [3] Role of the member (student). -# [4] username:domain of the user. -# -sub get_people_in_class { - my %coursepersonnel = &Apache::lonnet::get_course_adv_roles(); - # - # Enumerate the course_personnel. - # - my @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 @course_personnel, [join(':', @$person), $person->[0], '', $_]; - } - } - } - # Students must be split into the three categories: - - my @current_members; - my @future_members; - my @expired_members; - - # Indices into the coures data elements. - - my $section = &Apache::loncoursedata::CL_SECTION(); - my $fullname = &Apache::loncoursedata::CL_FULLNAME(); - my $status = &Apache::loncoursedata::CL_STATUS(); - my $start_date = &Apache::loncoursedata::CL_START(); - - - my $classlist = &Apache::loncoursedata::get_classlist(); - my @keys = keys %{$classlist}; - # Sort by: Section, name - @keys = sort { - if ($classlist->{$a}->[$section] ne $classlist->{$b}->[$section]) { - return $classlist->{$a}->[$section] cmp $classlist->{$b}->[$section]; - } - return $classlist->{$a}->[$fullname] cmp $classlist->{$b}->[$fullname]; - } @keys; - - - - - for (@keys) { - - if ( $classlist->{$_}->[$status] eq - 'Active') { - push @current_members, [$_, $classlist->{$_}->[$fullname], - $classlist->{$_}->[$section], - $classlist->{$_}->[$status], 'Student']; - } else { - # Need to figure out if this user is future or - # Expired... If the start date is in the future - # the user is future...else expired. - - my $now = time; - if ($classlist->{$_}->[$start_date] > $now) { - push @future_members, [$_, $classlist->{$_}->[$fullname], - $classlist->{$_}->[$section], - "Future", "Student"]; - } else { - push @expired_members, [$_, $classlist->{$_}->[$fullname], - $classlist->{$_}->[$section], - "Expired", "Student"]; - } - - } - } - return (\@course_personnel, - \@current_members, - \@expired_members, - \@future_members); - -} - -# -# Utility function used when rendering the tag. -# This function renders a segment of course personel -# Personel are broken up by the helper into past, current and -# future...each one gets is own subpage of selection. -# This sub renders one of these pages. -# Parameters: -# $students - Students in the section. (ref to array of references -# to arrays). -# $formprefix - form path prefix for form element names -# This is used to make each form element -# so that the segments having to do with each -# set of students won't collide. -# $defaultusers - reference to a hash containng -# the set of users that should be on or off. -# $multiselect - True if multiselect allowed. -# $resultname - Name of result variable. -# $javascript - If true, the javascript to run this is output -# This should be true for the first call for a page -# and false for all other calls... only matters if -# multiselect is true. -# Returns: -# HTML text to add to the rendering of the helper. -# -sub render_student_list { - my ($students, $formprefix, $defaultusers, - $multiselect, $resultname, $javascript) = @_; - - my $result = ""; - - if ($javascript && $multiselect) { - $result .= < -// - -SCRIPT - - } - - # If multiple selections are allowed, we have a listbox - # at the top which allows quick selections from each section - # as well as from categories of personnel. - - if ($multiselect) { - # Make a section hash so we can add sections to the choice: - - my %sections; - for my $student (@$students) { - my $sect = $student->[2]; - if ($sect ne "") { - $sections{$sect} = 1; - } - } - - $result .= ''; - $result .= '
'; - - my $size = scalar(keys(%sections)); - $size += 3; # We have allstudents allpersonel nosection too. - if ($size > 5) { - $size = 5; - } - $result .= ''; - $result .= '
'; - } - - # Now we list the students, but the form element type - # will depend on whether or not multiselect is true. - # True -> checkboxes. - # False -> radiobuttons. - - $result .= "\n"; - $result .= ''."\n"; - $result .= ' '."\n"; - $result .= ' '."\n"; - $result .= ' '."\n"; - $result .= ' '."\n"; - - my $input_type; - if ($multiselect) { - $input_type = "checkbox"; - } else { - $input_type = "radio"; - } - - my $checked = 0; - for my $student (@$students) { - $result .= ''."\n"; - } - $result .="
NameSectionStatusRoleUsername : Domain
[0]; - - # Figure out which students are checked by default... - - if(%$defaultusers) { - if (exists ($defaultusers->{$user})) { - $result .= ' checked ="checked" '; - $checked = 1; - } - } elsif (!$multiselect && !$checked) { - $result .= ' checked="checked" '; - $checked = 1; # First one for radio if no default specified. - } - $result .= ' value="'. HTML::Entities::encode($user . ':' - .$student->[2] . ':' - .$student->[1] . ':' - .$student->[3] . ':' - .$student->[4] . ":" - .$formprefix, "<>&\"'") - ."\" />\n"; - $result .= HTML::Entities::encode($student->[1], '<>&"') - . ''."\n"; - $result .= HTML::Entities::encode($student->[2], '<>&"') - . ''."\n"; - $result .= HTML::Entities::encode($student->[3], '<>&"') - . ''."\n"; - $result .= HTML::Entities::encode($student->[4], '<>&"') - . ''."\n"; - $result .= HTML::Entities::encode($student->[0], '<>&"') - . '


\n"; - - return $result; -} BEGIN { &Apache::lonhelper::register('Apache::lonhelper::student', @@ -2692,7 +2568,8 @@ sub render { my ($course_personnel, $current_members, $expired_members, - $future_members) = &get_people_in_class(); + $future_members) = + &Apache::lonselstudent::get_people_in_class($env{'request.course.sec'}); @@ -2705,34 +2582,43 @@ sub render { # Current personel - $result .= &render_student_list( $current_members, - "current", - \%defaultUsers, - $self->{'multichoice'}, - $self->{'variable'}, - 1); + $result .= '

'.&mt('Select Currently Enrolled Students and Active Course Personnel').'

'; + $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 @$expired_members) > 0)) { + if (!$self->{'activeonly'} && ((scalar(@$future_members)) > 0)) { # And future. - $result .= &render_student_list( $future_members, - "future", - \%defaultUsers, - $self->{'multichoice'}, - $self->{'variable'}, - 0); + $result .= '

'.&mt('Select Future Enrolled Students and Future Course Personnel').'

'; + + $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 .= &render_student_list($expired_members, - "past", - \%defaultUsers, - $self->{'multichoice'}, - $self->{'variable'}, - 0); + $result .= '

'.&mt('Select Previously Enrolled Students and Inactive Course Personnel').'

'; + $result .= &Apache::lonselstudent::render_student_list($expired_members, + "helpform", + "past", + \%defaultUsers, + $self->{'multichoice'}, + $self->{'variable'}, + 0); } @@ -2743,7 +2629,7 @@ sub render { sub postprocess { my $self = shift; - my $result = $env{'form.' . $self->{'variable'} . '.forminput'}; + my $result = $env{'form.' . $self->{'variable'} . '_forminput'}; if (!$result && !$self->{'emptyallowed'}) { if ($self->{'coursepersonnel'}) { $self->{ERROR_MSG} = @@ -2928,7 +2814,7 @@ sub render { function checkall(value, checkName) { for (i=0; i" . "{'multichoice'} && $choices == 0) { $result .= ' checked="checked"'; @@ -3106,7 +2992,7 @@ sub fileState { sub postprocess { my $self = shift; - my $result = $env{'form.' . $self->{'variable'} . '.forminput'}; + my $result = $env{'form.' . $self->{'variable'} . '_forminput'}; if (!$result) { $self->{ERROR_MSG} = 'You must choose at least one file '. 'to continue.'; @@ -3196,7 +3082,7 @@ sub start_section { return if ($token->[2]{'onlysections'}); # add in groups to the end of the list - my %curr_groups = &Apache::loncommon::coursegroups(); + my %curr_groups = &Apache::longroup::coursegroups(); foreach my $group_name (sort(keys(%curr_groups))) { push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); } @@ -3260,7 +3146,7 @@ sub start_group { # Populate the CHOICES element my %choices; - my %curr_groups = &Apache::loncommon::coursegroups(); + my %curr_groups = &Apache::longroup::coursegroups(); foreach my $group_name (sort {lc($a) cmp lc($b)} (keys(%curr_groups))) { push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]); } @@ -3342,7 +3228,7 @@ sub render { $result .= '

' . $self->{ERROR_MSG} . '

'; } - $result .= '{'variable'} . '_forminput"'; if (defined($self->{'size'})) { $result .= ' size="' . $self->{'size'} . '"'; @@ -3475,7 +3361,8 @@ sub start_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); + my $end_tag = $paramHash->{SKIPTAG} || '/condition'; + &Apache::lonxml::get_all_text($end_tag, $parser); } } @@ -3680,7 +3567,7 @@ sub overrideForm { 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. # It is represented with , and # should later be moved to lonparmset.pm . @@ -3748,8 +3635,10 @@ sub render { if ($vars->{GRANULARITY} eq 'whole_course') { $resourceString .= '
  • '.&mt('for all resources in the course').'
  • '; if ($vars->{TARGETS} eq 'course') { - $level = 11; # general course, see lonparmset.pm perldoc + $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; @@ -3764,8 +3653,10 @@ sub render { $symb = $res->symb(); $resourceString .= '
  • '.&mt('for the map named [_1]',"$title").'
  • '; if ($vars->{TARGETS} eq 'course') { - $level = 10; # general course, see lonparmset.pm perldoc + $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; @@ -3781,8 +3672,10 @@ sub render { my $title = $res->compTitle(); $resourceString .= '
  • '.&mt('for the resource named [_1] part [_2]',"$title","$part").'
  • '; if ($vars->{TARGETS} eq 'course') { - $level = 7; # general course, see lonparmset.pm perldoc + $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; @@ -3881,7 +3774,8 @@ 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"; } # print pres_marker