--- loncom/homework/grades.pm 2020/09/08 15:48:41 1.596.2.12.2.53 +++ loncom/homework/grades.pm 2023/03/10 23:36:22 1.596.2.12.2.60.2.3 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.596.2.12.2.53 2020/09/08 15:48:41 raeburn Exp $ +# $Id: grades.pm,v 1.596.2.12.2.60.2.3 2023/03/10 23:36:22 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -1143,8 +1143,33 @@ LISTJAVASCRIPT $nocompmsg = ''; } $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Submissions')) - .$submission_options - .&Apache::lonhtmlcommon::row_closure() + .$submission_options; +# Check if any gradable + my $showmore; + if ($perm{'mgr'}) { + my @sections; + if ($env{'request.course.sec'} ne '') { + @sections = ($env{'request.course.sec'}); + } elsif ($env{'form.section'} eq '') { + @sections = ('all'); + } else { + @sections = &Apache::loncommon::get_env_multiple('form.section'); + } + if (grep(/^all$/,@sections)) { + $showmore = 1; + } else { + foreach my $sec (@sections) { + if (&canmodify($sec)) { + $showmore = 1; + last; + } + } + } + } + + if ($showmore) { + $gradeTable .= + &Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title(&mt('Send Messages')) .'' .'' .&Apache::lonhtmlcommon::row_closure(); - $gradeTable .= &Apache::lonhtmlcommon::row_title(&mt('Grading Increments')) + $gradeTable .= + &Apache::lonhtmlcommon::row_title(&mt('Grading Increments')) .''; + } $gradeTable .= &build_section_inputs(). ''."\n". ''."\n". ''."\n"; if (exists($env{'form.Status'})) { - $gradeTable .= ''."\n"; + $gradeTable .= ''."\n"; } else { $gradeTable .= &Apache::lonhtmlcommon::row_closure() .&Apache::lonhtmlcommon::row_title(&mt('Student Status')) @@ -2151,7 +2178,7 @@ sub files_exist { my ($uname,$udom,$fullname) = split(/:/,$student); my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'}, $udom,$uname); - my ($string,$timestamp)= &get_last_submission(\%record); + my ($string)= &get_last_submission(\%record); foreach my $submission (@$string) { my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/); @@ -2496,16 +2523,28 @@ sub submission { # (3) All transactions (by date) # (4) The whole record (with detailed information for all transactions) - my ($string,$timestamp)= &get_last_submission(\%record); + my ($string,$timestamp,$lastgradetime,$lastsubmittime) = &get_last_submission(\%record); my $lastsubonly; - if ($$timestamp eq '') { - $lastsubonly.='
'.$$string[0].'
'; + if ($timestamp eq '') { + $lastsubonly.='
'.$string->[0].'
'; } else { + my ($shownsubmdate,$showngradedate); + if ($lastsubmittime && $lastgradetime) { + $shownsubmdate = &Apache::lonlocal::locallocaltime($lastsubmittime); + if ($lastgradetime > $lastsubmittime) { + $showngradedate = &Apache::lonlocal::locallocaltime($lastgradetime); + } + } else { + $shownsubmdate = $timestamp; + } $lastsubonly = '
' - .''.&mt('Date Submitted:').' '.$$timestamp."\n"; + .''.&mt('Date Submitted:').' '.$shownsubmdate."\n"; + if ($showngradedate) { + $lastsubonly .= '
'.&mt('Date Graded:').' '.$showngradedate."\n"; + } my %seenparts; my @part_response_id = &flatten_responseType($responseType); @@ -2830,17 +2869,45 @@ sub check_collaborators { #--- Retrieve the last submission for all the parts sub get_last_submission { my ($returnhash)=@_; - my (@string,$timestamp,%lasthidden); + my (@string,$timestamp,$lastgradetime,$lastsubmittime); if ($$returnhash{'version'}) { my %lasthash=(); - my ($version); + my %prevsolved=(); + my %solved=(); + my $version; for ($version=1;$version<=$$returnhash{'version'};$version++) { + my %handgraded = (); foreach my $key (sort(split(/\:/, $$returnhash{$version.':keys'}))) { $lasthash{$key}=$$returnhash{$version.':'.$key}; - $timestamp = - &Apache::lonlocal::locallocaltime($$returnhash{$version.':timestamp'}); - } + if ($key =~ /\.([^.]+)\.regrader$/) { + $handgraded{$1} = 1; + } elsif ($key =~ /\.portfiles$/) { + if (($$returnhash{$version.':'.$key} ne '') && + ($$returnhash{$version.':'.$key} !~ /\.\d+\.\w+$/)) { + $lastsubmittime = $$returnhash{$version.':timestamp'}; + } + } elsif ($key =~ /\.submission$/) { + if ($$returnhash{$version.':'.$key} ne '') { + $lastsubmittime = $$returnhash{$version.':timestamp'}; + } + } elsif ($key =~ /\.([^.]+)\.solved$/) { + $prevsolved{$1} = $solved{$1}; + $solved{$1} = $lasthash{$key}; + } + } + foreach my $partid (keys(%handgraded)) { + if (($prevsolved{$partid} eq 'ungraded_attempted') && + (($solved{$partid} eq 'incorrect_by_override') || + ($solved{$partid} eq 'correct_by_override'))) { + $lastgradetime = $$returnhash{$version.':timestamp'}; + } + if ($solved{$partid} ne '') { + $prevsolved{$partid} = $solved{$partid}; + } + } + $timestamp = + &Apache::lonlocal::locallocaltime($$returnhash{$version.':timestamp'}); } my (%typeparts,%randombytry); my $showsurv = @@ -2898,7 +2965,7 @@ sub get_last_submission { $string[0] = ''.&mt('Nothing submitted - no attempts.').''; } - return (\@string,\$timestamp); + return (\@string,$timestamp,$lastgradetime,$lastsubmittime); } #--- High light keywords, with style choosen by user. @@ -3104,13 +3171,31 @@ sub processHandGrade { my $ntstu = $env{'form.NTSTU'}; my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($res_error,%queueable); + my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error); + if ($res_error) { + $request->print(&navmap_errormsg()); + return; + } else { + foreach my $part (@{$partlist}) { + if (ref($responseType->{$part}) eq 'HASH') { + foreach my $id (keys(%{$responseType->{$part}})) { + if (($responseType->{$part}->{$id} eq 'essay') || + (lc($handgrade->{$part.'_'.$id}) eq 'yes')) { + $queueable{$part} = 1; + last; + } + } + } + } + } if ($button eq 'Save & Next') { my $ctr = 0; while ($ctr < $ngrade) { my ($uname,$udom) = split(/:/,$env{'form.unamedom'.$ctr}); my ($errorflag,$pts,$wgt,$numhidden) = - &saveHandGrade($request,$symb,$uname,$udom,$ctr); + &saveHandGrade($request,$symb,$uname,$udom,$ctr,undef,undef,\%queueable); if ($errorflag eq 'no_score') { $ctr++; next; @@ -3165,7 +3250,7 @@ sub processHandGrade { foreach my $collaborator (@collaborators) { my ($errorflag,$pts,$wgt) = &saveHandGrade($request,$symb,$collaborator,$udom,$ctr, - $env{'form.unamedom'.$ctr},$part); + $env{'form.unamedom'.$ctr},$part,\%queueable); if ($errorflag eq 'not_allowed') { $request->print("".&mt('Not allowed to modify grades for [_1]',"$collaborator:$udom").""); next; @@ -3187,13 +3272,6 @@ sub processHandGrade { } } - my $res_error; - my ($partlist,$handgrade,$responseType,$numresp,$numessay) = &response_type($symb,\$res_error); - if ($res_error) { - $request->print(&navmap_errormsg()); - return; - } - my %keyhash = (); if ($numessay) { # Keywords sorted in alphabatical order @@ -3345,7 +3423,7 @@ sub processHandGrade { #---- Save the score and award for each student, if changed sub saveHandGrade { - my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part) = @_; + my ($request,$symb,$stuname,$domain,$newflg,$submitter,$part,$queueable) = @_; my @version_parts; my $usec = &Apache::lonnet::getsection($domain,$stuname, $env{'request.course.id'}); @@ -3457,7 +3535,7 @@ sub saveHandGrade { &Apache::lonnet::cstore(\%newrecord,$symb, $env{'request.course.id'},$domain,$stuname); &check_and_remove_from_queue(\@parts,\%record,\%newrecord,$symb, - $cdom,$cnum,$domain,$stuname); + $cdom,$cnum,$domain,$stuname,$queueable); } if ($aggregateflag) { &Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, @@ -3497,7 +3575,7 @@ sub makehidden { } sub check_and_remove_from_queue { - my ($parts,$record,$newrecord,$symb,$cdom,$cnum,$domain,$stuname) = @_; + my ($parts,$record,$newrecord,$symb,$cdom,$cnum,$domain,$stuname,$queueable) = @_; my @ungraded_parts; foreach my $part (@{$parts}) { if ( $record->{ 'resource.'.$part.'.awarded'} eq '' @@ -3505,7 +3583,9 @@ sub check_and_remove_from_queue { && $newrecord->{'resource.'.$part.'.awarded'} eq '' && $newrecord->{'resource.'.$part.'.solved' } ne 'excused' ) { - push(@ungraded_parts, $part); + if ($queueable->{$part}) { + push(@ungraded_parts, $part); + } } } if ( !@ungraded_parts ) { @@ -3993,7 +4073,26 @@ sub viewgrades { } my ($common_header,$specific_header,@sections,$section_display); - @sections = &Apache::loncommon::get_env_multiple('form.section'); + if ($env{'request.course.sec'} ne '') { + @sections = ($env{'request.course.sec'}); + } else { + @sections = &Apache::loncommon::get_env_multiple('form.section'); + } + +# Check if Save button should be usable + my $disabled = ' disabled="disabled"'; + if ($perm{'mgr'}) { + if (grep(/^all$/,@sections)) { + undef($disabled); + } else { + foreach my $sec (@sections) { + if (&canmodify($sec)) { + undef($disabled); + last; + } + } + } + } if (grep(/^all$/,@sections)) { @sections = ('all'); if ($group_display) { @@ -4168,7 +4267,7 @@ sub viewgrades { } $result.=&Apache::loncommon::end_data_table(); $result.=''."\n"; - $result.=''."\n"; if ($ctr == 0) { my $stu_status = join(' or ',&Apache::loncommon::get_env_multiple('form.Status')); @@ -4428,6 +4527,7 @@ sub editgrades { &Apache::loncommon::end_data_table_header_row(); my @noupdate; my ($updateCtr,$noupdateCtr) = (1,1); + my ($got_types,%queueable); for ($i=0; $i<$env{'form.total'}; $i++) { my $user = $env{'form.ctr'.$i}; my ($uname,$udom)=split(/:/,$user); @@ -4527,12 +4627,32 @@ sub editgrades { $udom,$uname); my $all_graded = 1; my $none_graded = 1; + unless ($got_types) { + my $error; + my ($plist,$handgrd,$resptype) = &response_type($symb,\$error); + unless ($error) { + foreach my $part (@parts) { + if (ref($resptype->{$part}) eq 'HASH') { + foreach my $id (keys(%{$resptype->{$part}})) { + if (($resptype->{$part}->{$id} eq 'essay') || + (lc($handgrd->{$part.'_'.$id}) eq 'yes')) { + $queueable{$part} = 1; + last; + } + } + } + } + } + $got_types = 1; + } foreach my $part (@parts) { - if ( $record{'resource.'.$part.'.awarded'} eq '' ) { - $all_graded = 0; - } else { - $none_graded = 0; - } + if ($queueable{$part}) { + if ( $record{'resource.'.$part.'.awarded'} eq '' ) { + $all_graded = 0; + } else { + $none_graded = 0; + } + } } if ($all_graded || $none_graded) { @@ -5364,10 +5484,14 @@ sub displayPage { } $curRes = $iterator->next(); } + my $disabled; + unless (&canmodify($usec)) { + $disabled = ' disabled="disabled"'; + } $studentTable.= ''."\n". - ''. ''."\n"; $request->print($studentTable); @@ -5585,6 +5709,7 @@ sub updateGradeByPage { my @displayPts=(); my %aggregate = (); my $aggregateflag = 0; + my %queueable; if ($env{'form.HIDE'.$prob}) { my %record = &Apache::lonnet::restore($symbx,$env{'request.course.id'},$udom,$uname); my ($version,$parts) = split(/:/,$env{'form.HIDE'.$prob},2); @@ -5594,7 +5719,20 @@ sub updateGradeByPage { foreach my $partid (@{$parts}) { my $newpts = $env{'form.GD_BOX'.$question.'_'.$partid}; my $oldpts = $env{'form.oldpts'.$question.'_'.$partid}; - + my @types = $curRes->responseType($partid); + if (grep(/^essay$/,@types)) { + $queueable{$partid} = 1; + } else { + my @ids = $curRes->responseIds($partid); + for (my $i=0; $i < scalar(@ids); $i++) { + my $hndgrd = &Apache::lonnet::EXT('resource.'.$partid.'_'.$ids[$i]. + '.handgrade',$symb); + if (lc($hndgrd) eq 'yes') { + $queueable{$partid} = 1; + last; + } + } + } my $wgt = $env{'form.WGT'.$question.'_'.$partid} != 0 ? $env{'form.WGT'.$question.'_'.$partid} : 1; my $partial = $newpts/$wgt; @@ -5660,7 +5798,7 @@ sub updateGradeByPage { $env{'request.course.id'}, $udom,$uname); &check_and_remove_from_queue($parts,\%record,undef,$symbx, - $cdom,$cnum,$udom,$uname); + $cdom,$cnum,$udom,$uname,\%queueable); } if ($aggregateflag) { @@ -6569,9 +6707,12 @@ sub scantron_parse_scanline { } sub get_master_seq { - my ($resources,$master_seq,$symb_to_resource) = @_; + my ($resources,$master_seq,$symb_to_resource,$need_symb_in_map,$symb_for_examcode) = @_; return unless ((ref($resources) eq 'ARRAY') && (ref($master_seq) eq 'ARRAY') && (ref($symb_to_resource) eq 'HASH')); + if ($need_symb_in_map) { + return unless (ref($symb_for_examcode) eq 'HASH'); + } my $resource_error; foreach my $resource (@{$resources}) { my $ressymb; @@ -6579,6 +6720,14 @@ sub get_master_seq { $ressymb = $resource->symb(); push(@{$master_seq},$ressymb); $symb_to_resource->{$ressymb} = $resource; + if ($need_symb_in_map) { + unless ($resource->is_map()) { + my $map=(&Apache::lonnet::decode_symb($ressymb))[0]; + unless (exists($symb_for_examcode->{$map})) { + $symb_for_examcode->{$map} = $ressymb; + } + } + } } else { $resource_error = 1; last; @@ -8395,6 +8544,17 @@ sub scantron_validate_doublebubble { if (ref($map)) { $randomorder = $map->randomorder(); $randompick = $map->randompick(); + unless ($randomorder || $randompick) { + foreach my $res ($navmap->retrieveResources($map,sub { $_[0]->is_map() },1,0,1)) { + if ($res->randomorder()) { + $randomorder = 1; + } + if ($res->randompick()) { + $randompick = 1; + } + last if ($randomorder || $randompick); + } + } if ($randomorder || $randompick) { $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); if ($nav_error) { @@ -8578,6 +8738,17 @@ sub scantron_validate_missingbubbles { if (ref($map)) { $randomorder = $map->randomorder(); $randompick = $map->randompick(); + unless ($randomorder || $randompick) { + foreach my $res ($navmap->retrieveResources($map,sub { $_[0]->is_map() },1,0,1)) { + if ($res->randomorder()) { + $randomorder = 1; + } + if ($res->randompick()) { + $randompick = 1; + } + last if ($randomorder || $randompick); + } + } if ($randomorder || $randompick) { $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); if ($nav_error) { @@ -8719,10 +8890,21 @@ sub scantron_process_students { } my $map=$navmap->getResourceByUrl($sequence); my ($randomorder,$randompick,@master_seq,%symb_to_resource,%grader_partids_by_symb, - %grader_randomlists_by_symb); + %grader_randomlists_by_symb,%symb_for_examcode); if (ref($map)) { $randomorder = $map->randomorder(); $randompick = $map->randompick(); + unless ($randomorder || $randompick) { + foreach my $res ($navmap->retrieveResources($map,sub { $_[0]->is_map() },1,0,1)) { + if ($res->randomorder()) { + $randomorder = 1; + } + if ($res->randompick()) { + $randompick = 1; + } + last if ($randomorder || $randompick); + } + } } else { $r->print(&navmap_errormsg()); return ''; @@ -8730,7 +8912,7 @@ sub scantron_process_students { my $nav_error; my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); if ($randomorder || $randompick) { - $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); + $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource,1,\%symb_for_examcode); if ($nav_error) { $r->print(&navmap_errormsg()); return ''; @@ -8877,11 +9059,16 @@ SCANTRONFORM } if (($scancode) && ($randomorder || $randompick)) { - my $parmresult = - &Apache::lonparmset::storeparm_by_symb($symb, - '0_examcode',2,$scancode, - 'string_examcode',$uname, - $udom); + foreach my $key (keys(%symb_for_examcode)) { + my $symb_in_map = $symb_for_examcode{$key}; + if ($symb_in_map ne '') { + my $parmresult = + &Apache::lonparmset::storeparm_by_symb($symb_in_map, + '0_examcode',2,$scancode, + 'string_examcode',$uname, + $udom); + } + } } $completedstudents{$uname}={'line'=>$line}; if ($env{'form.verifyrecord'}) { @@ -9196,14 +9383,14 @@ END my @lines = &Apache::lonnet::get_scantronformat_file(); my $count = 0; foreach my $line (@lines) { - next if ($line =~ /^#/); + next if (($line =~ /^\#/) || ($line eq '')); $singleline = $line; $count ++; } if ($count > 1) { $formatextra = ''; $onclick = ' onclick="toggleScantab(this.form);"'; $formatjs = <<"END"; @@ -9358,7 +9545,7 @@ sub validate_uploaded_scantron_file { my %unique_formats; my @formatlines = &Apache::lonnet::get_scantronformat_file(); foreach my $line (@formatlines) { - chomp($line); + next if (($line =~ /^\#/) || ($line eq '')); my @config = split(/:/,$line); my $idstart = $config[5]; my $idlength = $config[6]; @@ -9520,6 +9707,17 @@ sub checkscantron_results { if (ref($map)) { $randomorder=$map->randomorder(); $randompick=$map->randompick(); + unless ($randomorder || $randompick) { + foreach my $res ($navmap->retrieveResources($map,sub { $_[0]->is_map() },1,0,1)) { + if ($res->randomorder()) { + $randomorder = 1; + } + if ($res->randompick()) { + $randompick = 1; + } + last if ($randomorder || $randompick); + } + } } my @resources=$navmap->retrieveResources($map,\&scantron_filter,1,0); my $nav_error = &get_master_seq(\@resources,\@master_seq,\%symb_to_resource); @@ -9873,37 +10071,47 @@ sub grading_menu { $fields{'command'} = 'initialverifyreceipt'; my $url5 = &Apache::lonhtmlcommon::build_url('grades/',\%fields); - + + my %permissions; + if ($perm{'mgr'}) { + $permissions{'either'} = 'F'; + $permissions{'mgr'} = 'F'; + } + if ($perm{'vgr'}) { + $permissions{'either'} = 'F'; + $permissions{'vgr'} = 'F'; + } + my @menu = ({ categorytitle=>'Hand Grading', items =>[ { linktext => 'Select individual students to grade', url => $url1a, - permission => 'F', + permission => $permissions{'either'}, icon => 'grade_students.png', linktitle => 'Grade current resource for a selection of students.' }, { linktext => 'Grade ungraded submissions', url => $url1b, - permission => 'F', + permission => $permissions{'either'}, icon => 'ungrade_sub.png', linktitle => 'Grade all submissions that have not been graded yet.' }, { linktext => 'Grading table', url => $url1c, - permission => 'F', + permission => $permissions{'either'}, icon => 'grading_table.png', linktitle => 'Grade current resource for all students.' }, { linktext => 'Grade page/folder for one student', url => $url1d, - permission => 'F', + permission => $permissions{'either'}, icon => 'grade_PageFolder.png', linktitle => 'Grade all resources in current page/sequence/folder for one student.' }, { linktext => 'Download submitted files', url => $url1e, - permission => 'F', + permission => $permissions{'either'}, icon => 'download_sub.png', linktitle => 'Download all files submitted by students.' }]}, @@ -9912,25 +10120,25 @@ sub grading_menu { { linktext => 'Upload Scores', url => $url2, - permission => 'F', + permission => $permissions{'mgr'}, icon => 'uploadscores.png', linktitle => 'Specify a file containing the class scores for current resource.' }, { linktext => 'Process Clicker', url => $url3, - permission => 'F', + permission => $permissions{'mgr'}, icon => 'addClickerInfoFile.png', linktitle => 'Specify a file containing the clicker information for this resource.' }, { linktext => 'Grade/Manage/Review Bubblesheets', url => $url4, - permission => 'F', + permission => $permissions{'mgr'}, icon => 'bubblesheet.png', linktitle => 'Grade bubblesheet exams, upload/download bubblesheet data files, and review previously graded bubblesheet exams.' }, { linktext => 'Verify Receipt Number', url => $url5, - permission => 'F', + permission => $permissions{'either'}, icon => 'receipt_number.png', linktitle => 'Verify a system-generated receipt number for correct problem solution.' } @@ -10055,6 +10263,14 @@ sub selectfield { my %options = (&substatus_options, 'select_form_order' => ['yes','queued','graded','incorrect','all']); + + # + # PrepareClasslist() needs to be called to avoid getting a sections list + # for a different course from the @Sections global in lonstatistics.pm, + # populated by an earlier request. + # + &Apache::lonstatistics::PrepareClasslist(); + my $result='
@@ -10781,7 +10997,7 @@ sub navmap_errormsg { } sub startpage { - my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$js,$onload,$divforres) = @_; + my ($r,$symb,$crumbs,$onlyfolderflag,$nodisplayflag,$stuvcurrent,$stuvdisp,$nomenu,$head_extra,$onload,$divforres) = @_; my %args; if ($onload) { my %loaditems = ( @@ -10791,11 +11007,13 @@ sub startpage { } if ($nomenu) { $args{'only_body'} = 1; - $r->print(&Apache::loncommon::start_page("Student's Version",$js,\%args)); + $r->print(&Apache::loncommon::start_page("Student's Version",$head_extra,\%args)); } else { - unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"}); + if ($env{'request.course.id'}) { + unshift(@$crumbs,{href=>&href_symb_cmd($symb,'gradingmenu'),text=>"Grading"}); + } $args{'bread_crumbs'} = $crumbs; - $r->print(&Apache::loncommon::start_page('Grading',$js,\%args)); + $r->print(&Apache::loncommon::start_page('Grading',$head_extra,\%args)); } unless ($nodisplayflag) { $r->print(&Apache::lonhtmlcommon::resource_info_box($symb,$onlyfolderflag,$stuvcurrent,$stuvdisp,$divforres)); @@ -10875,7 +11093,15 @@ sub handler { } else { $divforres = 1; } - &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef,$stuvcurrent,$stuvdisp,undef,$js,$onload,$divforres); + my $head_extra = $js; + unless ($env{'form.vProb'} eq 'no') { + my $csslinks = &Apache::loncommon::css_links($symb); + if ($csslinks) { + $head_extra .= "\n$csslinks"; + } + } + &startpage($request,$symb,[{href=>"", text=>"Student Submissions"}],undef,undef, + $stuvcurrent,$stuvdisp,undef,$head_extra,$onload,$divforres); if ($versionform) { if ($divforres) { $request->print('
'); @@ -10888,7 +11114,15 @@ sub handler { &choose_task_version_form($symb,$env{'form.student'}, $env{'form.userdom'}, $env{'form.inhibitmenu'}); - &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef,$stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$js); + my $head_extra = $js; + unless ($env{'form.vProb'} eq 'no') { + my $csslinks = &Apache::loncommon::css_links($symb); + if ($csslinks) { + $head_extra .= "\n$csslinks"; + } + } + &startpage($request,$symb,[{href=>"", text=>"Previous Student Version"}],undef,undef, + $stuvcurrent,$stuvdisp,$env{'form.inhibitmenu'},$head_extra); if ($versionform) { $request->print($versionform); } @@ -10899,10 +11133,14 @@ sub handler { {href=>'',text=>'Select student'}],1,1); &pickStudentPage($request,$symb); } elsif ($command eq 'displayPage' && $perm{'vgr'}) { + my $csslinks; + unless ($env{'form.vProb'} eq 'no') { + $csslinks = &Apache::loncommon::css_links($symb,'map'); + } &startpage($request,$symb, [{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'}, {href=>'',text=>'Select student'}, - {href=>'',text=>'Grade student'}],1,1); + {href=>'',text=>'Grade student'}],1,1,undef,undef,undef,$csslinks); &displayPage($request,$symb); } elsif ($command eq 'gradeByPage' && $perm{'mgr'}) { &startpage($request,$symb,[{href=>&href_symb_cmd($symb,'all_for_one'),text=>'Grade page/folder for one student'}, @@ -10911,8 +11149,12 @@ sub handler { {href=>'',text=>'Store grades'}],1,1); &updateGradeByPage($request,$symb); } elsif ($command eq 'processGroup' && $perm{'vgr'}) { + my $csslinks; + unless ($env{'form.vProb'} eq 'no') { + $csslinks = &Apache::loncommon::css_links($symb); + } &startpage($request,$symb,[{href=>'',text=>'...'}, - {href=>'',text=>'Modify grades'}],undef,undef,undef,undef,undef,undef,undef,1); + {href=>'',text=>'Modify grades'}],undef,undef,undef,undef,undef,$csslinks,undef,1); &processGroup($request,$symb); } elsif ($command eq 'gradingmenu' && $perm{'vgr'}) { &startpage($request,$symb); @@ -11138,8 +11380,8 @@ ssi_with_retries() - missingbubble - array ref of the bubble lines that have missing bubble errors - $randomorder - True if exam folder has randomorder set - $randompick - True if exam folder has randompick set + $randomorder - True if exam folder (or a sub-folder) has randomorder set + $randompick - True if exam folder (or a sub-folder) has randompick set $respnumlookup - Reference to HASH mapping question numbers in bubble lines for current line to question number used for same question in "Master Seqence" (as seen by Course Coordinator).