--- loncom/interface/lonuserutils.pm	2010/08/10 04:00:16	1.109.2.4
+++ loncom/interface/lonuserutils.pm	2010/01/20 16:46:23	1.114
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA user accounts
 #
-# $Id: lonuserutils.pm,v 1.109.2.4 2010/08/10 04:00:16 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.114 2010/01/20 16:46:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -36,7 +36,6 @@ use Apache::loncommon();
 use Apache::lonhtmlcommon;
 use Apache::lonlocal;
 use Apache::longroup;
-use Apache::lonnavmaps;
 use LONCAPA qw(:DEFAULT :match);
 
 ###############################################################
@@ -1186,10 +1185,8 @@ sub default_role_selector {
                     'exs'  => "Existing sections",
                     'new'  => "New section",
                   );
-    $options = '<select name="defaultrole">'."\n";
-    unless (($context eq 'course') && (&Apache::loncommon::needs_gci_custom())) {
-        $options .= ' <option value="">'.&mt('Please select').'</option>'."\n";
-    }
+    $options = '<select name="defaultrole">'."\n".
+               ' <option value="">'.&mt('Please select').'</option>'."\n"; 
     if ($context eq 'course') {
         $options .= &default_course_roles($context,$checkpriv,$crstype,%customroles);
     } elsif ($context eq 'author') {
@@ -1451,8 +1448,12 @@ sub print_userlist {
     }
     if (!(($context eq 'domain') && 
           (($env{'form.roletype'} eq 'course') || ($env{'form.roletype'} eq 'community')))) {
-        $r->print('&nbsp;'.&list_submit_button(&mt('Update Display')).
-                  "\n</p>\n");
+        $r->print(
+            "\n</p>\n"
+           .'<p>'
+           .&list_submit_button(&mt('Update Display'))
+           ."</p>\n"
+        );
     }
     my ($indexhash,$keylist) = &make_keylist_array();
     my (%userlist,%userinfo,$clearcoursepick);
@@ -1691,7 +1692,7 @@ sub role_filter {
         $role_select .= '</select>';
         $output = '<label><span class="LC_nobreak">'
                  .&mt('Role: [_1]',$role_select)
-                 .'</span></label>';
+                 .'</span></label> ';
     }
     return $output;
 }
@@ -1731,7 +1732,7 @@ sub section_group_filter {
         }
         if (@options > 0) {
             my $currsel;
-            $markup = '<select name="'.$name{$item}.'" />'."\n";
+            $markup = '<select name="'.$name{$item}.'">'."\n";
             foreach my $option ('all','none',@options) { 
                 $currsel = '';
                 if ($env{'form.'.$name{$item}} eq $option) {
@@ -1746,7 +1747,9 @@ sub section_group_filter {
                 $markup .= '</option>'."\n";
             }
             $markup .= '</select>'."\n";
-            $output .= ('&nbsp;'x3).'<label>'.$title{$item}.': '.$markup.'</label>';
+            $output .= ('&nbsp;'x3).'<span class="LC_nobreak">'
+                      .'<label>'.$title{$item}.': '.$markup.'</label>'
+                      .'</span> ';
         }
     }
     return $output;
@@ -2096,7 +2099,6 @@ sub process_date_info {
 
 sub show_users_list {
     my ($r,$context,$mode,$permission,$statusmode,$userlist,$keylist,$formname)=@_;
-    my $custommenu; 
     if ($formname eq '') {
         $formname = 'studentform';
     }
@@ -2121,17 +2123,11 @@ sub show_users_list {
         $sortby = 'username';
     }
     my $setting = $env{'form.roletype'};
-    my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers,$crstype,
-        $clickersupport,$displaygroups);
+    my ($cid,$cdom,$cnum,$classgroups,$displayphotos,$displayclickers,$crstype);
     if ($context eq 'course') {
         $cid = $env{'request.course.id'};
         $crstype = &Apache::loncommon::course_type();
         ($cnum,$cdom) = &get_course_identity($cid);
-        $custommenu = &Apache::loncommon::needs_gci_custom();
-        unless ($custommenu) {
-            $clickersupport = 1;
-            $displaygroups = 1;
-        }
         ($classgroups) = &Apache::loncoursedata::get_group_memberships(
                                      $userlist,$keylist,$cdom,$cnum);
         if ($mode eq 'autoenroll') {
@@ -2252,8 +2248,6 @@ END
                        'role'       => "role",
                        'type'       => "enroll type/action",
                        'email'      => "e-mail address",
-                       'lastlogin'  => "last login",
-                       'submissions' => "test status",
                        'photo'      => "photo",
                        'extent'     => "extent",
                        'pr'         => "Proceed",
@@ -2300,19 +2294,9 @@ END
             push(@cols,'status');
         }
         if ($context eq 'course') {
-            if ($displaygroups) {
-                push(@cols,'groups');
-            }
+            push(@cols,'groups');
         }
         push(@cols,'email');
-        if ($context eq 'course') {
-            if ($custommenu) {
-                push(@cols,'lastlogin');
-                if (($env{'form.showrole'} eq 'Any') || ($env{'form.showrole'} eq 'st')) {
-                    push(@cols,'submissions');
-                }
-            }
-        }
     }
 
     my $rolefilter = $env{'form.showrole'};
@@ -2419,7 +2403,7 @@ END
             if ($env{'form.userwin'}) {
                 $checkwin = ' checked="checked"';
             }
-            $output .= '</td><td valign="top"><span class="LC_nobreak"><input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}.'</span></td></tr></table></fieldset></div>';
+            $output .= '</td><td valign="top"  style="border-left: 1px solid;"><span class="LC_nobreak"><input type="checkbox" name="userwin" value="1"'.$checkwin.' />'.$lt{'owin'}.'</span></td></tr></table></fieldset></div>';
         }
         $output .= "\n".'<div class="LC_clear_float_footer">&nbsp;</div>'."\n".
                   &Apache::loncommon::start_data_table().
@@ -2435,32 +2419,27 @@ END
             }
         }
         foreach my $item (@cols) {
-            if (grep(/^\Q$item\E$/,@sortable)) {
-                $output .= "<th><a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\">$lt{$item}</a></th>\n";
-            } else {
-                $output .= "<th>$lt{$item}</th>\n";
-            }
+            $output .= "<th><a href=\"javascript:document.$formname.sortby.value='$item';document.$formname.submit();\">$lt{$item}</a></th>\n";
         }
         my %role_types = &role_type_names();
         if ($context eq 'course' && $mode ne 'autoenroll') {
             if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
                 # Clicker display on or off?
-                if ($clickersupport) {
-                    my %clicker_options = (
-                                            'on' => 'Show',
-                                            'off' => 'Hide',
-                                          );
-                    my $clickerchg = 'on';
-                    if ($displayclickers eq 'on') {
-                        $clickerchg = 'off';
-                    }
-                    $output .= '    <th>'."\n".'     '
-                       .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id'
+                my %clicker_options = (
+                                        'on' => 'Show',
+                                        'off' => 'Hide',
+                                      );
+                my $clickerchg = 'on';
+                if ($displayclickers eq 'on') {
+                    $clickerchg = 'off';
+                }
+                $output .= '    <th>'."\n".'     '
+                        .&mt('[_1]'.$clicker_options{$clickerchg}.'[_2] clicker id'
                             ,'<a href="javascript:document.'.$formname.'.displayclickers.value='
                              ."'".$clickerchg."'".';document.'.$formname.'.submit();">'
                             ,'</a>')
                         ."\n".'    </th>'."\n";
-                }
+
                 # Photo display on or off?
                 if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
                     my %photo_options = &Apache::lonlocal::texthash(
@@ -2499,18 +2478,14 @@ END
             $CSVfile = undef;
         }
         #
-        if ($clickersupport) {
-            push @cols,'clicker';
-        }
+        push @cols,'clicker';
         # Write headers and data to file
         print $CSVfile '"'.$results_description.'"'."\n"; 
         print $CSVfile '"'.join('","',map {
             &Apache::loncommon::csv_translate($lt{$_})
             } (@cols))."\"\n";
     } elsif ($mode eq 'excel') {
-        if ($clickersupport) {
-            push @cols,'clicker';
-        }
+        push @cols,'clicker';
         # Create the excel spreadsheet
         ($excel_workbook,$excel_filename,$format) =
             &Apache::loncommon::create_workbook($r);
@@ -2546,40 +2521,6 @@ END
                                                 Future  => 'Future',
                                                 Expired => 'Expired',
                                                );
-    # If this is for a single course get last course "log-in" and submissions.
-    my (%crslogins,%stusubmissions,%elapsed,$numparts,%nummultipart,$multipart);
-    my $now = time;
-    if ($context eq 'course') {
-        if ($custommenu) {
-            %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$cnum);
-            %stusubmissions=&Apache::lonnet::dump('nohist_submissiontracker',$cdom,$cnum);
-            %elapsed = &Apache::lonlocal::texthash(    
-                                         -1 => 'more than a month ago',
-                                    2592000 => 'within last 30 days',
-                                     604800 => 'within last 7 days',
-                                      86400 => 'within last 24 hours',
-                                   );
-            my $navmap = Apache::lonnavmaps::navmap->new();
-            if (defined($navmap)) {
-                my @allres=$navmap->retrieveResources('/uploaded/'.$cdom.'/'.$cnum.'/default_1261144274.sequence',sub { $_[0]->is_problem() },0);
-                foreach my $resource (@allres) {
-                    my @parts = $resource->parts();
-                    my $count = scalar(@parts);
-                    if ($count > 1) {
-                        $nummultipart{$count} ++;
-                    }
-                    $numparts += $count;
-                }
-                if (keys(%nummultipart) > 0) {
-                   $multipart = '<br />'.'contains';
-                   foreach my $key (sort {$a <=> $b} keys(%nummultipart)) {
-                       $multipart .= " nummultipart{$key} multipart questions (with $key parts)";
-                   }
-                }
-            }
-        }
-    }
-
     # Get groups, role, permanent e-mail so we can sort on them if
     # necessary.
     foreach my $user (keys(%{$userlist})) {
@@ -2726,34 +2667,6 @@ END
         } else {
             $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
         }
-        if ($context eq 'course') {
-            if ($custommenu) {
-                my $lastlogin = $crslogins{$in{'username'}.':'.$in{'domain'}.':'.$in{'section'}.':'.$role};
-                if ($lastlogin ne '') {
-                    my $sincelogin = $now - $lastlogin;
-                    if ($sincelogin < 86400) {
-                        $in{'lastlogin'} = $elapsed{'86400'};
-                    } elsif ($sincelogin < 604800) {
-                        $in{'lastlogin'} = $elapsed{'604800'};
-                    } elsif ($sincelogin < 2592000 ) {
-                        $in{'lastlogin'} = $elapsed{'2592000'};
-                    } else {
-                        $in{'lastlogin'} = $elapsed{'-1'};
-                    }
-                }
-            }
-            if ($role eq 'st') {
-                my $numsub = $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0attempts"} + 
-                             $stusubmissions{$in{'username'}.':'.$in{'domain'}."\0pilotsubs"};
-                if (!$numsub) {
-                    $in{'submissions'} = 'not attempted';
-                } elsif ($numsub < $numparts) {
-                    $in{'submissions'} = 'incomplete ('.$numsub.'/'.$numparts.')';
-                } else {
-                    $in{'submissions'} = 'completed';
-                }
-            }
-        }
         if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
             $r->print(&Apache::loncommon::start_data_table_row());
             my $checkval;
@@ -2827,27 +2740,19 @@ END
                         $showitem = $ltstatus{$in{$item}};
                     }
                     $r->print('<td>'.$showitem.'</td>'."\n");
-                } elsif ($item eq 'submissions') {
-                    if ($in{$item} =~ /^incomplete/) { 
-                        $r->print('<td>'.$in{$item}.$multipart.'</td>');
-                    } else {
-                        $r->print('<td>'.$in{$item}.'</td>'."\n");
-                    }
                 } else {
                     $r->print('<td>'.$in{$item}.'</td>'."\n");
                 }
             }
             if (($context eq 'course') && ($mode ne 'autoenroll')) {
                 if ($env{'form.showrole'} eq 'st' || $env{'form.showrole'} eq 'Any') {
-                    if ($clickersupport) {
-                        if ($displayclickers eq 'on') {
-                            my $clickers =
+                    if ($displayclickers eq 'on') {
+                        my $clickers =
                    (&Apache::lonnet::userenvironment($in{'domain'},$in{'username'},'clickers'))[1];
-                            if ($clickers!~/\w/) { $clickers='-'; }
-                            $r->print('<td>'.$clickers.'</td>');
-                        } else {
-                            $r->print('    <td>&nbsp;</td>  ');
-                        }
+                        if ($clickers!~/\w/) { $clickers='-'; }
+                        $r->print('<td>'.$clickers.'</td>');
+                    } else {
+                        $r->print('    <td>&nbsp;</td>  ');
                     }
                     if ($env{'course.'.$env{'request.course.id'}.'.internal.showphoto'}) {
                         if ($displayphotos eq 'on' && $role eq 'st' && $in{'photo'} ne '') {
@@ -3038,7 +2943,7 @@ sub print_username_link {
         $output = $in->{'username'};
     } else {
         $output = '<a href="javascript:username_display_launch('.
-                  "'$in->{'username'}','$in->{'domain'}'".')" />'.
+                  "'$in->{'username'}','$in->{'domain'}'".')">'.
                   $in->{'username'}.'</a>';
     }
     return $output;
@@ -3292,7 +3197,6 @@ ENDJS
                 $date_items;
     if ($context eq 'course' && $env{'form.bulkaction'} eq 'chgsec') {
         my ($cnum,$cdom) = &get_course_identity();
-        my $crstype = &Apache::loncommon::course_type();
         if ($crstype eq 'Community') {
             $lt{'fors'} = &mt('For member roles changing the section, will result in a section switch as members may only be in one section of a community at a time.');
             $lt{'forn'} = &mt('For a role in a community that is not a member role, a user may have roles in more than one section of a community at a time.');
@@ -3563,10 +3467,6 @@ sub show_drop_list {
     my ($r,$classlist,$nosort,$permission,$crstype) = @_;
     my $cid = $env{'request.course.id'};
     my ($cnum,$cdom) = &get_course_identity($cid);
-    my $displaygroups;
-    unless (&Apache::loncommon::needs_gci_custom()) {
-        $displaygroups = 1;
-    }
     if (! exists($env{'form.sortby'})) {
         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
                                                 ['sortby']);
@@ -3644,10 +3544,8 @@ END
     <th>$lt{'sec'}</th>
     <th>$lt{'start'}</th>
     <th>$lt{'end'}</th>
+    <th>$lt{'groups'}</th>
 END
-        if ($displaygroups) {
-            $r->print("    <th>$lt{'groups'}</th>\n");
-        }
         $r->print(&Apache::loncommon::end_data_table_header_row());
     } else  {
         $r->print(&Apache::loncommon::start_data_table().
@@ -3668,13 +3566,10 @@ END
        <a href="/adm/createuser?action=$action&sortby=start">$lt{'start'}</a>
     </th><th>
        <a href="/adm/createuser?action=$action&sortby=end">$lt{'end'}</a>
+    </th><th>
+       <a href="/adm/createuser?action=$action&sortby=groups">$lt{'groups'}</a>
     </th>
 END
-       if ($displaygroups) {
-           $r->print("<th>
-       <a href=\"/adm/createuser?action=$action&sortby=groups\">$lt{'groups'}</a>
-    </th>\n");
-        }
         $r->print(&Apache::loncommon::end_data_table_header_row());
     }
     #
@@ -3727,10 +3622,8 @@ END
     <td>$section</td>
     <td>$start $startitem</td>
     <td>$end</td>
+    <td>$active_groups</td>
 END
-        if ($displaygroups) {
-            $r->print("    <td>$active_groups</td>\n");
-        }
         $r->print(&Apache::loncommon::end_data_table_row());
     }
     $r->print(&Apache::loncommon::end_data_table().'<br />');
@@ -3767,7 +3660,7 @@ sub print_first_users_upload_form {
     $str .= '<input type="hidden" name="action" value="upload" />';
     $str .= '<input type="hidden" name="state"  value="got_file" />';
 
-    $str .= '<h3>'.&mt('Upload a file containing information about users').'</h3>'."\n";
+    $str .= '<h2>'.&mt('Upload a file containing information about users').'</h2>'."\n";
 
     # Excel and CSV Help
     $str .= '<div class="LC_left_float">'
@@ -3778,8 +3671,15 @@ sub print_first_users_upload_form {
                 &mt("How do I create a CSV file from a spreadsheet"))
            .'</div><br clear="all" />'."\n";
     $str .= &Apache::lonhtmlcommon::start_pick_box()
-           .&Apache::lonhtmlcommon::row_title(&mt('File'))
-           .&Apache::loncommon::upfile_select_html()
+           .&Apache::lonhtmlcommon::row_title(&mt('File'));
+    if (&Apache::lonlocal::current_language() ne 'en') {
+        if ($context eq 'course') { 
+            $str .= '<p class="LC_info">'."\n"
+                   .&mt('Please upload an UTF8 encoded file to ensure a correct character encoding in your classlist.')."\n"
+                   .'</p>'."\n";
+        }
+    }
+    $str .= &Apache::loncommon::upfile_select_html()
            .&Apache::lonhtmlcommon::row_closure()
            .&Apache::lonhtmlcommon::row_title(
                 '<label for="noFirstLine">'
@@ -4932,11 +4832,13 @@ sub setsections_javascript {
                     plch => 'Please choose a different section name.',
                     mnot => 'may not be used as a section name, as it is the name of a course group.',
                     secn => 'Section names and group names must be distinct. Please choose a different section name.',
+                    nonw => 'Section names may only contain letters or numbers.',
                  );                
     $setsection_js .= <<"ENDSECCODE";
 
 function setSections(formname,crstype) {
     var re1 = /^currsec_/;
+    var re2 =/\\W/;
     var groups = new Array($groupslist);
     for (var i=0;i<formname.elements.length;i++) {
         var str = formname.elements[i].name;
@@ -4980,9 +4882,22 @@ function setSections(formname,crstype) {
                     }
                     var newsecs = formname.elements[i+1].value;
                     var numsplit;
+                    var validsecs = new Array();
+                    var badsecs = new Array();
                     if (newsecs != null && newsecs != "") {
                         numsplit = newsecs.split(/,/g);
-                        numsec = numsec + numsplit.length;
+                        for (var i=0; i<numsplit.length; i++) {
+                            if (re2.test(numsplit[i]) == true) {
+                                badsecs.push(numsplit[i]);
+                            } else {
+                                validsecs.push(numsplit[i]);
+                            }
+                        }
+                        if (badsecs.length > 0) {
+                            alert("$alerts{'nonw'}\\n$alerts{'plch'}");
+                            return;
+                        }
+                        numsec = numsec + validsecs.length;
                     }
 
                     if ((role == 'st') && (numsec > 1)) {
@@ -5135,22 +5050,14 @@ sub roles_by_context {
         if ($env{'request.role'} =~ m{^dc\./}) {
             push(@allroles,'ad');
         }
-        if (&Apache::loncommon::needs_gci_custom()) {
-            if ($crstype eq 'Community') {
-                push(@allroles,'co');
-            } else {
-                push(@allroles,'cc');
-            }
+        push(@allroles,('ta','ep','in'));
+        if ($crstype eq 'Community') {
+            push(@allroles,'co');
         } else {
-            push(@allroles,('ta','ep','in'));
-            if ($crstype eq 'Community') {
-                push(@allroles,'co');
-            } else {
-                push(@allroles,'cc');
-            }
-            if ($custom) {
-                push(@allroles,'cr');
-            }
+            push(@allroles,'cc');
+        }
+        if ($custom) {
+            push(@allroles,'cr');
         }
     } elsif ($context eq 'author') {
         @allroles = ('ca','aa');