--- loncom/interface/lonhelper.pm	2006/04/06 22:30:52	1.136
+++ loncom/interface/lonhelper.pm	2006/05/18 01:08:51	1.151
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # .helper XML handler to implement the LON-CAPA helper
 #
-# $Id: lonhelper.pm,v 1.136 2006/04/06 22:30:52 foxr Exp $
+# $Id: lonhelper.pm,v 1.151 2006/05/18 01:08:51 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -183,6 +183,8 @@ use Apache::File;
 use Apache::lonxml;
 use Apache::lonlocal;
 use Apache::lonnet;
+use Apache::longroup;
+use Apache::lonselstudent;
 
 # Register all the tags with the helper, so the helper can 
 # push and pop them
@@ -1576,23 +1578,39 @@ sub render {
     my $date;
 
     my $time=time;
-    $date = localtime($time);
-    $date->min(0);
     my ($anytime,$onclick);
 
-    if (defined($self->{DEFAULT_VALUE})) {
+
+    # 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});
+    } 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;
-	} else {
+	    $date = localtime(time);
+	    $date->min(0);
+	} elsif (defined($time) && $time ne 0) {
 	    $date = localtime($time);
+	} else {
+	    # leave date undefined so it'll default to now
 	}
-    } else {
+    }
 
+    if (!defined($date)) {
+	$date = localtime(time);
+	$date->min(0);
     }
+
+    &Apache::lonnet::logthis("date mode ");
+
     if ($anytime) {
 	$onclick = "onclick=\"javascript:updateCheck(this.form,'${var}anytime',false)\"";
     }
@@ -1700,7 +1718,7 @@ CHECK
 	if ($anytime) {
 	    $result.=' checked="checked" '
 	}
-	$result.="name='${var}anytime'/>".&mt('Anytime').'</label>'
+	$result.="name='${var}anytime'/>".&mt('Any time').'</label>'
     }
     return $result;
 
@@ -1747,6 +1765,16 @@ sub postprocess {
 	$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})) {
         $helper->changeState($self->{NEXTSTATE});
     }
@@ -2292,113 +2320,6 @@ sub render {
     my $buttons = '';
     my $var = $self->{'variable'};
 
-    if ($self->{'multichoice'}) {
-        $result = <<SCRIPT;
-<script type="text/javascript">
-// <!--
-    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) {
-		if (document.forms.helpform.elements[i].value.indexOf(':Active') != -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;
-            } 
-        }
-    }
-    function checkexpired()  {
-	for (i=0; i<document.forms.helpform.elements.length; i++) {
-            if (document.forms.helpform.elements[i].value.indexOf(':Expired') != -1) {
-                document.forms.helpform.elements[i].checked=true;
-            } 
-        }
-    }
-    function uncheckexpired() {
-	for (i=0; i<document.forms.helpform.elements.length; i++) {
-            if (document.forms.helpform.elements[i].value.indexOf(':Expired') != -1) {
-                document.forms.helpform.elements[i].checked=false;
-            } 
-        }
-    }
-    function getDesiredState() {     // Return desired person state radio value.
-        numRadio = document.forms.helpform.personstate.length;
-        for (i =0; i < numRadio; i++) {
-	    if (document.forms.helpform.personstate[i].checked) {
-                return document.forms.helpform.personstate[i].value;
-            }
-        }
-        return "";
-    }
-
-    function checksections(value) {    // Check selected sections.
-        numSections  = document.forms.helpform.chosensections.length;
-	desiredState = getDesiredState();
-
-	for (var option = 0; option < numSections; option++) {
-	    if(document.forms.helpform.chosensections.options[option].selected) {
-		section = document.forms.helpform.chosensections.options[option].text;
-		if (section == "none") {
-		    section ="";
-		}
-		for (i = 0; i < document.forms.helpform.elements.length; i++ ) {
-		    if (document.forms.helpform.elements[i].value.indexOf(':') != -1) {
-			info = document.forms.helpform.elements[i].value.split(':');
-			hisSection = info[2];
-			hisState   = info[4];
-			if (desiredState == hisState ||
-			    desiredState == "All") {
-			    if(hisSection == section ||
-			       section =="" ) {
-				document.forms.helpform.elements[i].checked = value;
-			    }
-			}
-		    }
-		}
-            }
-	}
-				   }
-// -->
-</script>
-SCRIPT
-
-        my %lt=&Apache::lonlocal::texthash(
-                    'ocs'  => "Select Only Current Students",
-                    'ues'  => "Unselect Expired Students",
-                    'sas'  => "Select All Students",
-                    'uas'  => "Unselect All Students",
-                    'sfsg' => "Select Current Students for Section/Group",
-		    'ufsg' => "Unselect for Section/Group");
- 
-        $buttons = <<BUTTONS;
-<br />
-<table>
-  
-  <tr>
-     <td><input type="button" onclick="checkall(true, '$var')" value="$lt{'sas'}" /></td>
-     <td> <input type="button" onclick="checkall(false, '$var')" value="$lt{'uas'}" /><br /></td>
-  </tr>
-  
-</table>
-<br />
-BUTTONS
-    $result .= $buttons;   
-
-    }
 
     if (defined $self->{ERROR_MSG}) {
         $result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />';
@@ -2416,203 +2337,55 @@ BUTTONS
 	%defaultUsers = map { if ($_) {($_,1) } } @defaultUsers;
 	delete($defaultUsers{''});
     }
-    my $choices = [];
-    my $expired_students = [];	# Will hold expired students.
 
-    # Load up the non-students, if necessary
-    if ($self->{'coursepersonnel'}) {
-	my %coursepersonnel = Apache::lonnet::get_course_adv_roles();
-	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 $section = Apache::loncoursedata::CL_SECTION();
-    my $fullname = Apache::loncoursedata::CL_FULLNAME();
-    my $status = Apache::loncoursedata::CL_STATUS();
+    my ($course_personnel, 
+	$current_members, 
+	$expired_members, 
+	$future_members) = &Apache::lonselstudent::get_people_in_class();
 
-    # Load up the students
-    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;
-    #
-    #  now add the fancy section choice... first enumerate the sections:
-    if ($self->{'multichoice'}) {
-	my %sections;
-	for my $key (@keys) {
-	    my $section_name = $classlist->{$key}->[$section];
-	    if ($section_name ne "") {
-		$sections{$section_name} = 1;
-	    }
-	}
-	#  The variable $choice_widget will have the html to make the choice 
-	#  selector.
-	my $size=5;
-	if (scalar(keys(%sections)) < 5) {
-	    $size=scalar(keys(%sections));
-	}
-	my $choice_widget = '<select multiple name="chosensections" size="'.$size.'">'."\n";
-	foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%sections))) {
-	    $choice_widget .= "<option name=\"$sec\">$sec</option>\n";
-	}
-	$choice_widget .= "<option>none</option></select>\n";
-
-	# Build a table without any borders to contain the section based
-	# selection:
-
-	my $section_selectors =<<SECTIONSELECT;
-<table border="0">
-  <tr valign="top">
-   <td>For Sections:</td><td>$choice_widget</td>
-   <td><label><input type="radio" name="personstate" value="Active" checked />
-               Current Students</label></td>
-   <td><label><input type="radio" name="personstate" value="All" />
-               All students</label></td>
-   <td><label><input type="radio" name="personstate" value="Expired" />
-               Expired Students</label></td>
-  </tr>
-  <tr>
-   <td><input type="button" value="Select" onclick="checksections(true);" /></td>
-   <td><input type="button" value="Unselect" onclick="checksections(false);" /></td></tr>
-</table>
-<br />
-SECTIONSELECT
-         $result .= $section_selectors;
-    }
 
-    # username, fullname, section, type
-    for (@keys) {
 
-	# We split the active students into the choices array and
-        # inactive ones into expired_students so that we can put them in 2 separate
-	# tables.
-
-	if ( $classlist->{$_}->[$status] eq
-	    'Active') {
-	    push @$choices, [$_, $classlist->{$_}->[$fullname], 
-			     $classlist->{$_}->[$section],
-			     $classlist->{$_}->[$status], 'Student'];
-	} else {
-	    push @$expired_students, [$_, $classlist->{$_}->[$fullname], 
-				      $classlist->{$_}->[$section],
-				      $classlist->{$_}->[$status], 'Student'];
-	}
+    # Load up the non-students, if necessary
+
+    if ($self->{'coursepersonnel'}) {
+	unshift @$current_members, (@$course_personnel);
     }
 
-    my $name = $self->{'coursepersonnel'} ? &mt('Name') : &mt('Student 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;
-    #
-    # Give the active students and staff:
-    #
-    for my $choice (@$choices) {
-        $result .= "<tr><td><input type='$type' name='" .
-            $self->{'variable'} . '.forminput' . "'";
-            
-	if (%defaultUsers) {
-	    my $user=$choice->[0];
-	    if (exists($defaultUsers{$user})) {
-		$result .= " checked='checked' ";
-		$checked = 1;
-	    }
-	} elsif (!$self->{'multichoice'} && !$checked) {
-            $result .= " checked='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";
+    #   Current personel
+
+    $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_students) > 0)) {
-	$result .= "<p>Inactive students: </p>\n";
-	$result .= <<INACTIVEBUTTONS;
-	   <table>
-              <tr>
-                 <td><input type="button" value="Select expired" onclick="checkexpired();" /> </td>
-		 <td><input type="button" value="Unselect expired" onclick="uncheckexpired();" /></td>
-              </tr>
-           </table>
-INACTIVEBUTTONS
-	$result .= "<table>\n";
-
-	for my $choice (@$expired_students) {
-        $result .= "<tr><td><input type='$type' name='" .
-            $self->{'variable'} . '.forminput' . "'";
-            
-	if (%defaultUsers) {
-	    my $user=$choice->[0];
-	    if (exists($defaultUsers{$user})) {
-		$result .= " checked='checked' ";
-		$checked = 1;
-	    }
-	} elsif (!$self->{'multichoice'} && !$checked) {
-            $result .= " checked='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";
-	
+    if (!$self->{'activeonly'} && ((scalar @$expired_members) > 0)) {
+
+	# And future.
+
+	$result .= &Apache::lonselstudent::render_student_list( $future_members,
+								"helpform",
+								"future",
+								\%defaultUsers,
+								$self->{'multichoice'},
+								$self->{'variable'},
+								0);
+	# Past 
+
+	$result .= &Apache::lonselstudent::render_student_list($expired_members,
+							       "helpform",
+							       "past",
+							       \%defaultUsers,
+							       $self->{'multichoice'},
+							       $self->{'variable'},
+							       0);
     }
 
 
@@ -3056,26 +2829,29 @@ sub start_section {
 
     my $section = Apache::loncoursedata::CL_SECTION();
     my $classlist = Apache::loncoursedata::get_classlist();
-    foreach (keys %$classlist) {
-        my $sectionName = $classlist->{$_}->[$section];
-        if (!$sectionName) {
+    foreach my $user (keys(%$classlist)) {
+        my $section_name = $classlist->{$user}[$section];
+        if (!$section_name) {
             $choices{"No section assigned"} = "";
         } else {
-            $choices{$sectionName} = $sectionName;
+            $choices{$section_name} = $section_name;
         }
     } 
    
-    for my $sectionName (sort(keys(%choices))) {
-	push @{$paramHash->{CHOICES}}, [$sectionName, $sectionName];
+    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))) {
+	push @{$paramHash->{CHOICES}}, [$section_name, $section_name];
     }
     return if ($token->[2]{'onlysections'});
 
     # add in groups to the end of the list
-    my %curr_groups;
-    if (&Apache::loncommon::coursegroups(\%curr_groups)) {
-	foreach my $group_name (sort(keys(%curr_groups))) {
-	    push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]);
-	}
+    my %curr_groups = &Apache::longroup::coursegroups();
+    foreach my $group_name (sort(keys(%curr_groups))) {
+	push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]);
     }
 }    
 
@@ -3137,11 +2913,9 @@ sub start_group {
     # Populate the CHOICES element
     my %choices;
 
-    my %curr_groups;
-    if (&Apache::loncommon::coursegroups(\%curr_groups)) {
-	foreach my $group_name (sort(keys(%curr_groups))) {
-	    push(@{$paramHash->{CHOICES}}, [$group_name, $group_name]);
-	}
+    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]);
     }
 }
 
@@ -3248,7 +3022,7 @@ sub postprocess {
 
     if (defined($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());
 	if ($invalid) {
 	    $self->{ERROR_MSG} = $invalid;
@@ -3627,8 +3401,10 @@ sub render {
     if ($vars->{GRANULARITY} eq 'whole_course') {
         $resourceString .= '<li>'.&mt('for <b>all resources in the course</b>').'</li>';
 	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;
@@ -3643,8 +3419,10 @@ sub render {
         $symb = $res->symb();
         $resourceString .= '<li>'.&mt('for the map named [_1]',"<b>$title</b>").'</li>';
 	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;
@@ -3660,8 +3438,10 @@ sub render {
         my $title = $res->compTitle();
         $resourceString .= '<li>'.&mt('for the resource named [_1] part [_2]',"<b>$title</b>","<b>$part</b>").'</li>';
 	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;