--- loncom/homework/grades.pm 2002/08/02 21:10:03 1.44 +++ loncom/homework/grades.pm 2002/09/06 20:59:28 1.48 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.44 2002/08/02 21:10:03 ng Exp $ +# $Id: grades.pm,v 1.48 2002/09/06 20:59:28 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -103,17 +103,6 @@ sub response_type { return \@partlist,\%handgrade; } -#--- Prints a message on screen if a user did something wrong -#--- Operator error --- -sub userError { - my ($request, $reason, $step) = @_; - $request->print('<h3><font color="red">LON-CAPA User Error</font></h3><br />'."\n"); - $request->print('<b>Reason: </b>'.$reason.'<br /><br />'."\n"); - $request->print('<b>Step: </b>'.($step ne '' ? $step : 'Use your browser back button to correct') - .'<br /><br />'."\n"); - return ''; -} - #--- Dumps the class list with usernames,list of sections, #--- section, ids and fullnames for each user. sub getclasslist { @@ -224,11 +213,33 @@ sub student_gradeStatus { return %partstatus; } +# hidden form and javascript that calls the form +# Use by verifyscript and viewgrades +# Shows a student's view of problem and submission +sub jscriptNform { + my ($url,$symb) = @_; + my $jscript='<script type="text/javascript" language="javascript">'."\n". + ' function viewOneStudent(user,domain) {'."\n". + ' document.onestudent.student.value = user;'."\n". + ' document.onestudent.userdom.value = domain;'."\n". + ' document.onestudent.submit();'."\n". + ' }'."\n". + '</script>'."\n"; + $jscript.= '<form action="/adm/grades" method="post" name="onestudent">'."\n". + '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". + '<input type="hidden" name="url" value="'.$url.'" />'."\n". + '<input type="hidden" name="command" value="submission" />'."\n". + '<input type="hidden" name="student" value="" />'."\n". + '<input type="hidden" name="userdom" value="" />'."\n". + '</form>'."\n"; + return $jscript; +} #------------------ End of general use routines -------------------- #------------------------------------------------------------------- #------------------------------------ Receipt Verification Routines +# #--- Check whether a receipt number is valid.--- sub verifyreceipt { my $request = shift; @@ -243,23 +254,8 @@ sub verifyreceipt { $symb = &Apache::lonnet::symbread($url); } - my $jscript='<script type="text/javascript" language="javascript">'."\n". - ' function viewOneStudent(user,domain) {'."\n". - ' document.onestudent.student.value = user;'."\n". - ' document.onestudent.userdom.value = domain;'."\n". - ' document.onestudent.submit();'."\n". - ' }'."\n". - '</script>'."\n"; - $jscript.= '<form action="/adm/grades" method="post" name="onestudent">'."\n". - '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". - '<input type="hidden" name="command" value="submission" />'."\n". - '<input type="hidden" name="student" value="" />'."\n". - '<input type="hidden" name="userdom" value="" />'."\n". - '</form>'."\n"; - - my $title.='<h2><font color="#339933">Verifying Submission Receipt '. - $receipt.'</h2></font>'."\n". + my $title.='<h3><font color="#339933">Verifying Submission Receipt '. + $receipt.'</h3></font>'."\n". '<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br><br>'."\n"; my ($string,$contents,$matches) = ('','',0); @@ -281,7 +277,7 @@ sub verifyreceipt { if ($matches == 0) { $string = $title.'No match found for the above receipt.'; } else { - $string = $jscript.$title. + $string = &jscriptNform($url,$symb).$title. 'The above receipt matches the following student'. ($matches <= 1 ? '.' : 's.')."\n". '<table border="0"><tr><td bgcolor="#777777">'."\n". @@ -301,17 +297,45 @@ sub verifyreceipt { # on the problem page. sub listStudents { my ($request) = shift; + $request->print(<<LISTJAVASCRIPT); +<script type="text/javascript" language="javascript"> + function checkSelect(checkBox) { + var ctr=0; + var sense=""; + if (checkBox.length > 1) { + for (var i=0; i<checkBox.length; i++) { + if (checkBox[i].checked) { + ctr++; + } + } + sense = "a student or group of students"; + } else { + if (checkBox.checked) { + ctr = 1; + } + sense = "the student"; + } + if (ctr == 0) { + alert("Please select "+sense+" before clicking on the View/Grade button."); + return false; + } + document.gradesub.submit(); + } +</script> +LISTJAVASCRIPT + + my ($symb,$url) = &get_symb_and_url(); my $cdom = $ENV{"course.$ENV{'request.course.id'}.domain"}; my $cnum = $ENV{"course.$ENV{'request.course.id'}.num"}; my $getsec = $ENV{'form.section'} eq '' ? 'all' : $ENV{'form.section'}; my $submitonly= $ENV{'form.submitonly'} eq '' ? 'all' : $ENV{'form.submitonly'}; - my $result='<h2><font color="#339933"> '. - 'View Submissions for a Student or a Group of Students</font></h2>'; + my $result='<h3><font color="#339933"> '. + 'View/Grade Submissions for a Student or a Group of Students</font></h3>'; $result.='<table border="0">'; $result.='<tr><td colspan=3><font size=+1>'. - '<b>Resource: </b>'.$ENV{'form.url'}.'</font></td></tr>'; - my ($partlist,$handgrade) = &response_type($ENV{'form.url'}); + '<b>Resource: </b>'.$url.'</font></td></tr>'; + my ($partlist,$handgrade) = &response_type($url); for (sort keys(%$handgrade)) { my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); $ENV{'form.handgrade'} = 'yes' if ($handgrade eq 'yes'); @@ -322,60 +346,63 @@ sub listStudents { $result.='</table>'; $request->print($result); - $request->print(<<ENDTABLEST); -<form action="/adm/grades" method="post"> - <b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no -<input type="radio" name="vProb" value="yes"> yes <br /> - <b>Submissions: </b> -<input type="radio" name="lastSub" value="hdgrade" checked /> handgrade only -<input type="radio" name="lastSub" value="lastonly" /> last sub only -<input type="radio" name="lastSub" value="last" /> last sub & parts info -<input type="radio" name="lastSub" value="all" /> all details -<input type="hidden" name="section" value="$getsec" /> -<input type="hidden" name="submitonly" value="$submitonly" /> -<input type="hidden" name="response" value="$ENV{'form.response'}" /> -<input type="hidden" name="handgrade" value="$ENV{'form.handgrade'}" /><br /> -<input type="hidden" name="showgrading" value="$ENV{'form.showgrading'}" /><br /> -<input type="submit" name="submit" value="View/Grade" /> -ENDTABLEST - if ($ENV{'form.url'}) { - $request->print('<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'."\n"); - } - if ($ENV{'form.symb'}) { - $request->print('<input type="hidden" name="symb" value="'.$ENV{'form.symb'}.'" />'."\n"); - } - $request->print('<input type="hidden" name="command" value="processGroup" />'."\n"); + my $checkhdgrade = $ENV{'form.handgrade'} eq 'yes' ? 'checked' : ''; + my $checklastsub = $ENV{'form.handgrade'} eq 'yes' ? '' : 'checked'; + my $gradeTable='<form action="/adm/grades" method="post" name="gradesub">'."\n". + ' <b>View Problem: </b><input type="radio" name="vProb" value="no" checked> no '."\n". + '<input type="radio" name="vProb" value="yes"> yes <br />'."\n". + ' <b>Submissions: </b>'."\n". + '<input type="radio" name="lastSub" value="hdgrade" '.$checkhdgrade.' /> handgrade only'."\n". + '<input type="radio" name="lastSub" value="lastonly" '.$checklastsub.' /> last sub only'."\n". + '<input type="radio" name="lastSub" value="last" /> last sub & parts info'."\n". + '<input type="radio" name="lastSub" value="all" /> all details'."\n". + '<input type="hidden" name="section" value="'.$getsec.'" />'."\n". + '<input type="hidden" name="submitonly" value="'.$submitonly.'" />'."\n". + '<input type="hidden" name="response" value="'.$ENV{'form.response'}.'" />'."\n". + '<input type="hidden" name="handgrade" value="'.$ENV{'form.handgrade'}.'" /><br />'."\n". + '<input type="hidden" name="showgrading" value="'.$ENV{'form.showgrading'}.'" /><br />'."\n". + '<input type="hidden" name="url" value="'.$url.'" />'."\n". + '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". + 'To view/grade a submission, click on the check box next to the student\'s name. Then '."\n". + 'click on the View/Grade button. To view the submissions for a group of students, click'."\n". + ' on the check boxes for the group of students.<br />'."\n". + '<input type="hidden" name="command" value="processGroup" />'."\n". + '<input type="button" '."\n". + 'onClick="javascript:checkSelect(this.form.stuinfo);" '."\n". + 'value="View/Grade" />'."\n"; + my ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist($getsec,'0'); - $result='<table border="0"><tr><td bgcolor="#777777">'. + $gradeTable.='<table border="0"><tr><td bgcolor="#777777">'. '<table border="0"><tr bgcolor="#e6ffff">'. '<td><b> Select </b></td><td><b> Fullname </b></td>'. '<td><b> Username </b></td><td><b> Domain </b></td>'; foreach (sort(@$partlist)) { - $result.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; + $gradeTable.='<td><b> Part '.(split(/_/))[0].' Status </b></td>'; } - $request->print($result.'</tr>'."\n"); + $gradeTable.='</tr>'."\n"; + my $ctr = 0; foreach my $student (sort {$$fullname{$a} cmp $$fullname{$b} } keys %$fullname) { my ($uname,$udom) = split(/:/,$student); - my (%status) = &student_gradeStatus($ENV{'form.url'}, - $ENV{'form.symb'},$udom,$uname,$partlist); + my (%status) =&student_gradeStatus($url,$symb,$udom,$uname,$partlist); my $statusflg = ''; foreach (keys(%status)) { $statusflg = 1 if ($status{$_} ne 'nothing'); my ($foo,$partid,$foo1) = split(/\./,$_); if ($status{'resource.'.$partid.'.submitted_by'} ne '') { $statusflg = ''; - $request->print('<input type="hidden" name="'. - $student.':submitted_by" value="'. - $status{'resource.'.$partid.'.submitted_by'}.'" />'); + $gradeTable.='<input type="hidden" name="'. + $student.':submitted_by" value="'. + $status{'resource.'.$partid.'.submitted_by'}.'" />'; } } next if ($statusflg eq '' && $submitonly eq 'yes'); + $ctr++; if ( $Apache::grades::viewgrades eq 'F' ) { - $result='<tr bgcolor="#ffffe6">'. + $gradeTable.='<tr bgcolor="#ffffe6">'. '<td align="center"><input type=checkbox name="stuinfo" value="'. $student.':'.$$fullname{$student}.'"></td>'."\n". '<td> '.$$fullname{$student}.' </td>'."\n". @@ -384,13 +411,23 @@ ENDTABLEST foreach (sort keys(%status)) { next if (/^resource.*?submitted_by$/); - $result.='<td align="middle"> '.$status{$_}.' </td>'."\n"; + $gradeTable.='<td align="middle"> '.$status{$_}.' </td>'."\n"; } - $request->print($result.'</tr>'."\n"); + $gradeTable.='</tr>'."\n"; } } - $request->print('</table></td></tr></table>'); - $request->print('<input type="submit" name="submit" value="View/Grade" /><form />'); + $gradeTable.='</table></td></tr></table>'. + '<input type="button" '. + 'onClick="javascript:checkSelect(this.form.stuinfo);" '. + 'value="View/Grade" /><form />'."\n"; + if ($ctr == 0) { + $gradeTable='<br /> <font color="red">'. + 'No submission found for this resource.</font><br />'; + $gradeTable.=&show_grading_menu_form($symb,$url); + } elsif ($ctr == 1) { + $gradeTable =~ s/type=checkbox/type=checkbox checked/; + } + $request->print($gradeTable); return ''; } @@ -402,10 +439,7 @@ sub processGroup { my @stuchecked = (ref($ENV{'form.stuinfo'}) ? @{$ENV{'form.stuinfo'}} : ($ENV{'form.stuinfo'})); my $total = scalar(@stuchecked)-1; - if ($stuchecked[0] eq '') { - &userError($request,'No student was selected for viewing/grading.'); - return; - } + foreach (@stuchecked) { my ($uname,$udom,$fullname) = split(/:/); $ENV{'form.student'} = $uname; @@ -489,6 +523,30 @@ sub sub_page_js { return; } +//=================== Check that a point is assigned for all the parts ============== + function checksubmit(val,total,parttot) { + document.SCORE.gradeOpt.value = val; + if (val == "Save & Next") { + for (i=0;i<=total;i++) { + for (j=0;j<parttot;j++) { + var partid = eval("document.SCORE.partid"+i+"_"+j+".value"); + var selopt = eval("document.SCORE.GD_SEL"+i+"_"+partid); + if (selopt[0].selected) { + var points = eval("document.SCORE.GD_BOX"+i+"_"+partid+".value"); + if (points == "") { + var name = eval("document.SCORE.name"+i+".value"); + alert("Please assign a score for "+name+", part "+partid+"."); + return false; + } + } + + } + } + + } + document.SCORE.submit(); + } + //===================== Show list of keywords ==================== function keywords(keyform) { var keywds = keyform.value; @@ -519,7 +577,7 @@ sub sub_page_js { else return; var cleantxt = txt.replace(new RegExp('([\\f\\n\\r\\t\\v ])+', 'g')," "); if (cleantxt=="") { - alert("Select a word or group of words from document and then click this link."); + alert("Please select a word or group of words from document and then click this link."); return; } var nret = prompt("Add selection to keyword list? Edit if desired.",cleantxt); @@ -766,8 +824,8 @@ sub submission { # header info if ($counter == 0) { &sub_page_js($request); - $request->print('<h2> <font color="#339933">Submission Record</font></h2>'. - '<font size=+1> <b>Resource: </b>'.$url.'</font>'); + $request->print('<h3> <font color="#339933">Submission Record</font></h3>'."\n". + '<font size=+1> <b>Resource: </b>'.$url.'</font>'."\n"); # option to display problem, only once else it cause problems # with the form later since the problem has a form. @@ -778,7 +836,7 @@ sub submission { $ENV{'request.course.id'}); my $result.='<table border="0" width="100%"><tr><td bgcolor="#777777">'; $result.='<table border="0" width="100%"><tr><td bgcolor="#e6ffff">'; - $result.='<b> View of the problem for '.$ENV{'form.fullname'}. + $result.='<b> View of the problem - '.$ENV{'form.fullname'}. '</b></td></tr><tr><td bgcolor="#ffffff">'.$rendered.'<br />'; $result.='<b>Correct answer:</b><br />'.$companswer; $result.='</td></tr></table>'; @@ -851,16 +909,17 @@ KEYWORDS # Display student info $request->print(($counter == 0 ? '' : '<br />')); - my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'. - '<table border="0" width=100%><tr bgcolor="#edffff"><td>'; + my $result='<table border="0" width=100%><tr><td bgcolor="#777777">'."\n". + '<table border="0" width=100%><tr bgcolor="#edffff"><td>'."\n"; -# $result.='<table border="0"><tr bgcolor="#ffffff"><td><b>Fullname: </b>'.$ENV{'form.fullname'}. $result.='<b>Fullname: </b>'.$ENV{'form.fullname'}. '<font color="#999999"> Username: '.$uname.'</font>'. - '<font color="#999999"> Domain: '.$udom.'</font><br />'; + '<font color="#999999"> Domain: '.$udom.'</font><br />'."\n"; + $result.='<input type="hidden" name="name'.$counter. + '" value="'.$ENV{'form.fullname'}.'" />'."\n"; # If this is handgraded, then check for collaborators - my $col_flag = 0; + my @col_fullnames; if ($ENV{'form.handgrade'} eq 'yes') { my @col_list; ($classlist,$seclist,$ids,$stusec,$fullname) = &getclasslist('all','0'); @@ -883,8 +942,9 @@ KEYWORDS push @badcollaborators,$collaborator; next; } - $col_flag++; push @col_list, $collaborator; + my ($lastname,$givenn) = split(/,/,$$fullname{$collaborator.':'.$udom}); + push @col_fullnames, $givenn.' '.$lastname; $result.=$$fullname{$collaborator.':'.$udom}.' '; } $result.='<br />'."\n"; @@ -924,12 +984,12 @@ KEYWORDS $request->print($submitby); } else { my ($string,$timestamp)= - &get_last_submission ($symb,$uname,$udom,$ENV{'request.course.id'}); + &get_last_submission (%record); my $lastsubonly.=''. ($$timestamp eq '' ? '' : '<b>Date Submitted:</b> '. $$timestamp).''; if ($$timestamp eq '') { - $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>'; + $lastsubonly.='<tr><td bgcolor="#ffffe6">'.$$string[0].'</td></tr>'."\n"; } else { for my $part (sort keys(%$handgrade)) { foreach (@$string) { @@ -939,7 +999,7 @@ KEYWORDS $lastsubonly.='<tr><td bgcolor="#ffffe6"><b>Part '. $partid.'</b> <font color="#999999">( ID '.$respid. ' )</font> <b>Answer: </b>'. - &keywords_highlight($subval).'</td></tr>' + &keywords_highlight($subval).'</td></tr>'."\n" if ($ENV{'form.lastSub'} eq 'lastonly' || ($ENV{'form.lastSub'} eq 'hdgrade' && $$handgrade{$part} =~ /:yes$/)); @@ -947,7 +1007,7 @@ KEYWORDS } } } - $lastsubonly.='</td></tr><tr><td bgcolor="#ffffff">'."\n"; + $lastsubonly.='</td></tr>'."\n"; $request->print($lastsubonly); } } else { @@ -959,17 +1019,25 @@ KEYWORDS # return if view submission with no grading option if ($ENV{'form.showgrading'} eq '') { - $request->print('</td></tr></table></td></tr></table></form>'); + $request->print('</td></tr></table></td></tr></table></form>'."\n"); return; } # Grading options $result='<input type="hidden" name="newmsg'.$counter.'" value="" />'."\n". '<input type="hidden" name="includemsg'.$counter.'" value="" />'."\n". - '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':'.$udom.'" />'."\n"; - $result.=' <a href="javascript:msgCenter(document.SCORE,'.$counter. - ',\''.$ENV{'form.fullname'}.'\')"; TARGET=_self>'. - 'Compose Message to student'.($col_flag > 1 ? 's' : '').'</a>'. + '<input type="hidden" name="unamedom'.$counter.'" value="'.$uname.':' + .$udom.'" />'."\n"; + my ($lastname,$givenn) = split(/,/,$ENV{'form.fullname'}); + my $msgfor = $givenn.' '.$lastname; + if (scalar(@col_fullnames) > 0) { + my $lastone = pop @col_fullnames; + $msgfor .= ', '.(join ', ',@col_fullnames).' and '.$lastone.'.'; + } + $result.='<tr><td bgcolor="#ffffff">'."\n". + ' <a href="javascript:msgCenter(document.SCORE,'.$counter. + ',\''.$msgfor.'\')"; TARGET=_self>'. + 'Compose Message to student'.(scalar(@col_fullnames) >= 1 ? 's' : '').'</a>'. '<br /> (Message will be sent when you click on Save & Next below.)'."\n" if ($ENV{'form.handgrade'} eq 'yes'); $request->print($result); @@ -1022,26 +1090,44 @@ KEYWORDS '<option selected="on"> </option>'. '<option>excused</option></select>'."  \n"; $result.='<input type="hidden" name="stores'.$counter.'_'.$partid.'" value="0" />'; - $result.='</td></tr></table>'; + $result.='</td></tr></table>'."\n"; $request->print($result); } - $request->print('<input type="hidden" name="partlist'.$counter.'" value="'.(join ":",@partlist).'" />'."\n"); - $request->print('</td></tr></table></td></tr></table>'."\n"); + $result='<input type="hidden" name="partlist'.$counter. + '" value="'.(join ":",@partlist).'" />'."\n"; + my $ctr = 0; + while ($ctr < scalar(@partlist)) { + $result.='<input type="hidden" name="partid'.$counter.'_'.$ctr.'" value="'. + $partlist[$ctr].'" />'."\n"; + $ctr++; + } + $request->print($result.'</td></tr></table></td></tr></table>'."\n"); # print end of form if ($counter == $total) { - my $endform.='<table border="0"><tr><td><input type="submit" name="gradeOpt" value="Save & Next" />'; - my $ntstu ='<select name="NTSTU">'. - '<option>1</option><option>2</option>'. - '<option>3</option><option>5</option>'. - '<option>7</option><option>10</option></select>'."\n"; - my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); - $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</; - $endform.=$ntstu.'student(s) '. - '<input type="submit" name="gradeOpt" value="Next" /> '. - '<input type="submit" name="gradeOpt" value="Previous" /> '. - '(Next and Previous do not save the scores.)'. - '</td><tr></table></form>'; + my $endform='<table border="0"><tr><td>'. + '<input type="hidden" name="gradeOpt" value="" />'."\n"; + if ($ENV{'form.handgrade'} eq 'yes') { + $endform.='<input type="button" value="Save & Next" '. + 'onClick="javascript:checksubmit(\'Save & Next\','. + $total.','.scalar(@partlist).');" TARGET=_self> '."\n"; + my $ntstu ='<select name="NTSTU">'. + '<option>1</option><option>2</option>'. + '<option>3</option><option>5</option>'. + '<option>7</option><option>10</option></select>'."\n"; + my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); + $ntstu =~ s/<option>$nsel</<option selected="on">$nsel</; + $endform.=$ntstu.'student(s) '; + } else { + $endform.='<input type="hidden" name="NTSTU" value="1" />'."\n"; + } + $endform.='<input type="button" value="Next" '. + 'onClick="javascript:checksubmit(\'Next\');" TARGET=_self> '."\n". + '<input type="button" value="Previous" '. + 'onClick="javascript:checksubmit(\'Previous\');" TARGET=_self> '; + $endform.='(Next and Previous do not save the scores.)'."\n" + if ($ENV{'form.handgrade'} eq 'yes'); + $endform.='</td><tr></table></form>'; $request->print($endform); } return ''; @@ -1049,31 +1135,30 @@ KEYWORDS #--- Retrieve the last submission for all the parts sub get_last_submission { - my ($symb,$username,$domain,$course)=@_; - if ($symb) { - my (@string,$timestamp); - my (%returnhash)=&Apache::lonnet::restore($symb,$course,$domain,$username); - if ($returnhash{'version'}) { - my %lasthash=(); - my ($version); - for ($version=1;$version<=$returnhash{'version'};$version++) { - foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) { - $lasthash{$_}=$returnhash{$version.':'.$_}; - } - } - foreach ((keys %lasthash)) { - if ($_ =~ /\.submission$/) { - my ($partid,$foo) = split(/submission$/,$_); - my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? - '<font color="red">Draft Copy</font> ' : ''; - push @string, (join(':',$_,$draft.$lasthash{$_})); - } - if ($_ =~ /timestamp/) {$timestamp = scalar(localtime($lasthash{$_}))}; + my (%returnhash)=@_; + my (@string,$timestamp); + if ($returnhash{'version'}) { + my %lasthash=(); + my ($version); + for ($version=1;$version<=$returnhash{'version'};$version++) { + foreach (sort(split(/\:/,$returnhash{$version.':keys'}))) { + $lasthash{$_}=$returnhash{$version.':'.$_}; + if ($returnhash{$version.':'.$_} =~ /(SUBMITTED|DRAFT)$/) { + $timestamp = scalar(localtime($returnhash{$version.':timestamp'})); + } + } + } + foreach ((keys %lasthash)) { + if ($_ =~ /\.submission$/) { + my ($partid,$foo) = split(/submission$/,$_); + my $draft = $lasthash{$partid.'awarddetail'} eq 'DRAFT' ? + '<font color="red">Draft Copy</font> ' : ''; + push @string, (join(':',$_,$draft.$lasthash{$_})); } } - @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string; - return \@string,\$timestamp; } + @string = $string[0] eq '' ? 'Nothing submitted - no attempts.' : @string; + return \@string,\$timestamp; } #--- High light keywords, with style choosen by user. @@ -1102,8 +1187,7 @@ sub processHandGrade { my $ctr = 0; while ($ctr < $ngrade) { my ($uname,$udom) = split(/:/,$ENV{'form.unamedom'.$ctr}); - my ($errorflg) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr); - return '' if ($errorflg eq 'error'); + my ($errorflag) = &saveHandGrade($request,$url,$symb,$uname,$udom,$ctr); my $includemsg = $ENV{'form.includemsg'.$ctr}; my ($subject,$message,$msgstatus) = ('','',''); @@ -1263,11 +1347,6 @@ sub saveHandGrade { my $pts = ($ENV{'form.GD_BOX'.$newflg.'_'.$_} ne '' ? $ENV{'form.GD_BOX'.$newflg.'_'.$_} : $ENV{'form.RADVAL'.$newflg.'_'.$_}); - if ($pts eq '') { - &userError($request,'No point was assigned for part '.$_. - ' and for username '.$stuname.'.'); - return 'error'; - } my $wgt = $ENV{'form.WGT'.$newflg.'_'.$_} eq '' ? 1 : $ENV{'form.WGT'.$newflg.'_'.$_}; my $partial= $pts/$wgt; @@ -1304,13 +1383,7 @@ sub viewgrades_js { $request->print(<<VIEWJAVASCRIPT); <script type="text/javascript" language="javascript"> - function viewOneStudent(user,domain) { - document.onestudent.student.value = user; - document.onestudent.userdom.value = domain; - document.onestudent.submit(); - } - - function writePoint(partid,weight,point) { + function writePoint(partid,weight,point) { var radioButton = eval("document.classgrade.RADVAL_"+partid); var textbox = eval("document.classgrade.TEXTVAL_"+partid); if (point == "textval") { @@ -1480,18 +1553,12 @@ sub viewgrades { &viewgrades_js($request); my ($symb,$url) = ($ENV{'form.symb'},$ENV{'form.url'}); - my $result='<h2><font color="#339933">Manual Grading</font></h2>'; + my $result='<h3><font color="#339933">Manual Grading</font></h3>'; $result.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font>'."\n"; #view individual student submission form - called using Javascript viewOneStudent - $result.= '<form action="/adm/grades" method="post" name="onestudent">'."\n". - '<input type="hidden" name="symb" value="'.$symb.'" />'."\n". - '<input type="hidden" name="url" value="'.$url.'" />'."\n". - '<input type="hidden" name="command" value="submission" />'."\n". - '<input type="hidden" name="student" value="" />'."\n". - '<input type="hidden" name="userdom" value="" />'."\n". - '</form>'."\n"; + $result.=&jscriptNform($url,$symb); #beginning of class grading form $result.= '<form action="/adm/grades" method="post" name="classgrade">'."\n". @@ -1499,7 +1566,6 @@ sub viewgrades { '<input type="hidden" name="url" value="'.$url.'" />'."\n". '<input type="hidden" name="command" value="editgrades" />'."\n". '<input type="hidden" name="section" value="'.$ENV{'form.section'}.'" />'."\n"; - $result.='To assign the same score for all the students use the radio buttons or '. 'text box below. To assign scores individually fill in the score boxes for '. 'each student in the table below. <font color="red">A part that has already '. @@ -1512,9 +1578,12 @@ sub viewgrades { my %weight = (); my $ctsparts = 0; $result.='<table border="0">'; + my %seen = (); for (sort keys(%$handgrade)) { - my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); my ($partid,$respid) = split (/_/); + next if $seen{$partid}; + $seen{$partid}++; + my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); my $wgt = &Apache::lonnet::EXT('resource.'.$partid.'.weight',$symb); $weight{$partid} = $wgt eq '' ? '1' : $wgt; @@ -1547,9 +1616,8 @@ sub viewgrades { $result.='</table><input type="hidden" name="totalparts" value="'.$ctsparts.'" />'; $result.='<input type="button" value="Reset" '. 'onClick="javascript:resetEntry('.$ctsparts.');" TARGET=_self> '; -# $result.='<input type="button" value="Submit Changes" '. -# 'onClick="submit();" TARGET=_self />'."\n"; - $result.= '<input type="submit" name="submit" value="Submit Changes" />'."\n"; + $result.='<input type="button" value="Submit Changes" '. + 'onClick="javascript:submit();" TARGET=_self />'."\n"; #table listing all the students in a section/class #header of table @@ -1586,7 +1654,8 @@ sub viewgrades { } $result.='</table></td></tr></table>'; $result.='<input type="hidden" name="total" value="'.$ctr.'" />'."\n"; - $result.='<input type="submit" name="submit" value="Submit Changes" /></form>'; + $result.='<input type="button" value="Submit Changes" '. + 'onClick="javascript:submit();" TARGET=_self /></form>'."\n"; $result.=&show_grading_menu_form($symb,$url); return $result; } @@ -1638,7 +1707,7 @@ sub editgrades { my $symb=$ENV{'form.symb'}; my $url =$ENV{'form.url'}; - my $title='<h2><font color="#339933">Current Grade Status</font></h2>'; + my $title='<h3><font color="#339933">Current Grade Status</font></h3>'; $title.='<font size=+1><b>Resource: </b>'.$ENV{'form.url'}.'</font><br />'."\n"; $title.='<font size=+1><b>Section: </b>'.$ENV{'form.section'}.'</font>'."\n"; $title.= &show_grading_menu_form ($symb,$url); @@ -1810,16 +1879,30 @@ ENDPICK sub csvuploadmap_header { my ($request,$symb,$url,$datatoken,$distotal)= @_; - my $result; my $javascript; if ($ENV{'form.upfile_associate'} eq 'reverse') { $javascript=&csvupload_javascript_reverse_associate(); } else { $javascript=&csvupload_javascript_forward_associate(); } + + my $result='<table border="0">'; + $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>'; + my ($partlist,$handgrade) = &response_type($url); + my ($resptype,$hdgrade)=('','no'); + for (sort keys(%$handgrade)) { + my ($responsetype,$handgrade)=split(/:/,$$handgrade{$_}); + $resptype = $responsetype; + $hdgrade = $handgrade if ($handgrade eq 'yes'); + $result.='<tr><td><b>Part </b>'.(split(/_/))[0].'</td>'. + '<td><b>Type: </b>'.$responsetype.'</td>'. + '<td><b>Handgrade: </b>'.$handgrade.'</font></td></tr>'; + } + $result.='</table>'; $request->print(<<ENDPICK); <form method="post" enctype="multipart/form-data" action="/adm/grades" name="gradesupload"> -<h3>Uploading Class Grades for resource $url</h3> +<h3><font color="#339933">Uploading Class Grades</font></h3> +$result <hr> <h3>Identify fields</h3> Total number of records found in file: $distotal <hr /> @@ -1887,6 +1970,7 @@ sub csvuploadmap { my ($i,$keyfields); if (@records) { my @fields=&csvupload_fields($url); + if ($ENV{'form.upfile_associate'} eq 'reverse') { &Apache::loncommon::csv_print_samples($request,\@records); $i=&Apache::loncommon::csv_print_select_table($request,\@records, @@ -1926,8 +2010,6 @@ sub csvuploadassign { } $request->print('<h3>Assigning Grades</h3>'); my $courseid=$ENV{'request.course.id'}; -# my $cdom=$ENV{"course.$courseid.domain"}; -# my $cnum=$ENV{"course.$courseid.num"}; my ($classlist) = &getclasslist('all','1'); my @skipped; my $countdone=0; @@ -1987,7 +2069,7 @@ sub gradingmenu { my ($request) = @_; my ($symb,$url)=&get_symb_and_url($request); if (!$symb) {return '';} - my $result='<h2> <font color="#339933">Select a Grading Method</font></h2>'; + my $result='<h3> <font color="#339933">Select a Grading Method</font></h3>'; $result.='<table border="0">'; $result.='<tr><td colspan=3><font size=+1><b>Resource: </b>'.$url.'</font></td></tr>'; my ($partlist,$handgrade) = &response_type($url); @@ -2027,7 +2109,7 @@ sub view_edit_entire_class_form { $result.= '<option>'.$_.'</option>'."\n"; } $result.='<option selected="on">all</select>'."<br />\n"; - $result.=' <input type="submit" name="submit" value="View/Grade" /></form>'."\n"; + $result.=' <input type="button" onClick="submit();" value="View/Grade" /></form>'."\n"; $result.='</td></tr></table>'."\n"; $result.='</td></tr></table>'."\n"; return $result; @@ -2037,7 +2119,17 @@ sub view_edit_entire_class_form { sub upcsvScores_form { my ($symb,$url) = @_; if (!$symb) {return '';} - my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n"; + my $result = '<script type="text/javascript" language="javascript">'."\n". + ' function checkUpload(formname) {'."\n". + ' if (formname.upfile.value == "") {'."\n". + ' alert("Please use the browse button to select a file from your local directory.");'."\n". + ' return false;'."\n". + ' }'."\n". + ' formname.submit();'."\n". + ' }'."\n". + '</script>'."\n"; + + $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n"; $result.='<table width=100% border=0><tr bgcolor="#e6ffff"><td>'."\n"; $result.=' <b>Specify a file containing the class scores for above resource</b></td></tr>'."\n"; $result.='<tr bgcolor=#ffffe6><td>'."\n"; @@ -2048,7 +2140,7 @@ sub upcsvScores_form { <input type="hidden" name="url" value="$url" /> <input type="hidden" name="command" value="csvuploadmap" /> $upfile_select -<br /> <input type="submit" name="submit" value="Upload Grades" /> +<br /> <input type="button" onClick="javascript:checkUpload(this.form);" value="Upload Grades" /> </form> ENDUPFORM $result.='</td></tr></table>'."\n"; @@ -2082,8 +2174,8 @@ sub viewGradeaStu_form { '<input type="radio" name="submitonly" value="all"> everybody <br />'; $result.=' (Section "no" implies the students were not assigned a section.)<br />' if (grep /no/,@$sections); - - $result.='<br /> <input type="submit" name="submit" value="View/Grade" />'."\n". + + $result.='<br /> <input type="button" onClick="submit();" value="View/Grade" />'."\n". '</form>'."\n"; $result.='</td></tr></table>'."\n"; $result.='</td></tr></table>'."\n"; @@ -2093,17 +2185,27 @@ sub viewGradeaStu_form { #--- Form to input a receipt number --- sub verifyReceipt_form { my ($symb,$url) = @_; - my $cdom=$ENV{"course.$ENV{'request.course.id'}.domain"}; - my $cnum=$ENV{"course.$ENV{'request.course.id'}.num"}; + my $result = '<script type="text/javascript" language="javascript">'."\n". + ' function checkEntry(formname) {'."\n". + ' var receipt = formname.receipt.value;'."\n". + ' if (isNaN(receipt) || receipt == "") {'."\n". + ' alert("Please enter a receipt number given by a student in the box.");'."\n". + ' return false;'."\n". + ' }'."\n". + ' formname.submit();'."\n". + ' }'."\n". + '</script>'."\n"; + my $hostver=unpack("%32C*",$Apache::lonnet::perlvar{'lonHostID'}); - my $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n"; + $result.='<table width=100% border=0><tr><td bgcolor=#777777>'."\n"; $result.='<table width=100% border=0><tr><td bgcolor=#e6ffff>'."\n"; $result.=' <b>Verify a Submission Receipt Issued by this Server</td></tr>'."\n"; $result.='<tr bgcolor=#ffffe6><td>'."\n"; - $result.='<form action="/adm/grades" method="post">'."\n"; + $result.='<form action="/adm/grades" method="post" name="verifyform">'."\n"; $result.=' <tt>'.$hostver.'-<input type="text" name="receipt" size="4"></tt><br />'."\n"; - $result.=' <input type="submit" name="submit" value="Verify Receipt">'."\n"; + $result.=' <input type="button" onClick="javascript:checkEntry(this.form);"'. + ' value="Verify Receipt">'."\n"; $result.='<input type="hidden" name="command" value="verify">'."\n"; if ($ENV{'form.url'}) { $result.='<input type="hidden" name="url" value="'.$ENV{'form.url'}.'" />'; @@ -2155,17 +2257,16 @@ sub handler { 'grade_courseid' => $tcrsid, 'grade_symb' => $tsymb))); } else { - $request->print('<h2>Not authorized: '.$token.'</h2>'); + $request->print('<h3>Not authorized: '.$token.'</h3>'); } } else { - $request->print('<h2>Not a valid DocID: '.$token.'</h2>'); + $request->print('<h3>Not a valid DocID: '.$token.'</h3>'); } } else { $request->print(&Apache::lonxml::tokeninputfield()); } } } else { - #&Apache::lonhomework::showhashsubset(\%ENV,'^form'); $Apache::grades::viewgrades=&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'}); if ($command eq 'submission') { &listStudents($request) if ($ENV{'form.student'} eq ''); @@ -2215,7 +2316,7 @@ sub send_header { #remotewindow=open('','homeworkremote'); #remotewindow.close(); #</script>"); - $request->print('<body bgcolor="#FFFFFF">'); + $request->print(&Apache::loncommon::bodytag('Grading')); } sub send_footer {