Skip to content

Commit

Permalink
Updates to grading tests for other users.
Browse files Browse the repository at this point in the history
When able to grade a test of another user, change the "Grade Test"
button to "Grade Test for UserID" to make it clear the test is being
graded for another user.

Show the "Check Test" button along side the "Grade Test" button
for instructor who can use the problem grader but also have the
permission to submit the past due test.

Allow instructors who can use the problem grader to grade unsubmitted
tests for that user without needing the permission to submit test
versions or answers for another user. This way if for some reason
a student's test doesn't get submitted correctly (such as a user
closing their browser without grading the test or after reaching
a grade proctor screen), it can still be graded with their saved
answers.

Update the timer when acting as another user if it is being shown,
just only suppress warnings about running out of time in this case.

Update description of record_answers_when_acting_as_student to
state that it can also start and grade test versions. Also include
a warning about that permission should be disabled (set back to
"nobody") after using it as it can interfere with tests, and should
probably only be used temporarily.
  • Loading branch information
somiaj committed Nov 26, 2024
1 parent a9bc14a commit bdd47c6
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 27 deletions.
26 changes: 12 additions & 14 deletions htdocs/js/GatewayQuiz/gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,22 +158,20 @@

const remainingTime = serverDueTime - browserTime + timeDelta;

if (!timerDiv.dataset.acting) {
if (remainingTime <= 10 - gracePeriod) {
if (sessionStorage.getItem('gatewayAlertStatus')) {
sessionStorage.removeItem('gatewayAlertStatus');

// Submit the test if time is expired and near the end of grace period.
actuallySubmit = true;
submitAnswers.click();
}
} else {
// Set the timer text and check alerts at page load.
updateTimer();
if (!timerDiv.dataset.acting && remainingTime <= 10 - gracePeriod) {
if (sessionStorage.getItem('gatewayAlertStatus')) {
sessionStorage.removeItem('gatewayAlertStatus');

// Start the timer.
setInterval(updateTimer, 1000);
// Submit the test if time is expired and near the end of grace period.
actuallySubmit = true;
submitAnswers.click();
}
} else {
// Set the timer text and check alerts at page load.
updateTimer();

// Start the timer.
setInterval(updateTimer, 1000);
}
}

Expand Down
9 changes: 8 additions & 1 deletion lib/WeBWorK/ConfigValues.pm
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,14 @@ sub getConfigValues ($ce) {
var => 'permissionLevels{record_answers_when_acting_as_student}',
doc => x('Can submit answers for a student'),
doc2 => x(
'When acting as a student, this permission level and higher can submit answers for that student.'),
'When acting as a student, this permission level and higher can submit answers for that student, '
. 'which includes starting and grading test versions. This permission should only be turned '
. 'on temporarily and set back to "nobody" after you are done submitting answers for a '
. 'student, as it can interfere with tests. If you have this permission and are viewing a '
. 'test version for a student that is also working on that version, your answers will be '
. 'saved for that student when moving between pages, which could reset or change the answers '
. 'entered in by the student.'
),
type => 'permission'
},
{
Expand Down
28 changes: 24 additions & 4 deletions lib/WeBWorK/ContentGenerator/GatewayQuiz.pm
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,12 @@ sub can_recordAnswers ($c, $user, $permissionLevel, $effectiveUser, $set, $probl

if ($user->user_id ne $effectiveUser->user_id) {
# If the user is not allowed to record answers as another user, return that permission. If the user is allowed
# to record only set version answers, then allow that between the open and close dates, and so drop out of this
# conditional to the usual one.
return 1 if $authz->hasPermissions($user->user_id, 'record_answers_when_acting_as_student');
# to record an unsubmitted test, allow that. If the user is allowed to record only set version answers, then
# allow that between the open and close dates, and so drop out of this conditional to the usual one.
return 1
if $authz->hasPermissions($user->user_id, 'record_answers_when_acting_as_student')
|| $c->can_gradeUnsubmittedTest($user, $permissionLevel, $effectiveUser, $set, $problem, $tmplSet,
$submitAnswers);
return 0 if !$authz->hasPermissions($user->user_id, 'record_set_version_answers_when_acting_as_student');
}

Expand Down Expand Up @@ -225,6 +228,15 @@ sub can_checkAnswers ($c, $user, $permissionLevel, $effectiveUser, $set, $proble
return 0;
}

# If user can use the problem grader, and the test is past due and has not been submitted, allow them to submit.
sub can_gradeUnsubmittedTest ($c, $user, $permissionLevel, $effectiveUser, $set, $problem, $tmplSet, $submitAnswers = 0)
{
return
!$submitAnswers
&& $c->can_showProblemGrader($user, $permissionLevel, $effectiveUser, $set, $problem, $tmplSet)
&& (after($set->due_date + $c->ce->{gatewayGracePeriod}) && !$set->version_last_attempt_time);
}

sub can_showScore ($c, $user, $permissionLevel, $effectiveUser, $set, $problem, $tmplSet) {
return
$c->authz->hasPermissions($user->user_id, 'view_hidden_work')
Expand Down Expand Up @@ -642,7 +654,8 @@ async sub pre_header_initialize ($c) {
if (
($currentNumAttempts < $maxAttemptsPerVersion)
&& ($effectiveUserID eq $userID
|| $authz->hasPermissions($userID, 'record_set_version_answers_when_acting_as_student'))
|| $authz->hasPermissions($userID, 'record_set_version_answers_when_acting_as_student')
|| $authz->hasPermissions($userID, 'record_answers_when_acting_as_student'))
)
{
if (between($set->open_date(), $set->due_date() + $ce->{gatewayGracePeriod}, $c->submitTime)) {
Expand Down Expand Up @@ -741,6 +754,7 @@ async sub pre_header_initialize ($c) {
checkAnswers => $c->can_checkAnswers(@args),
recordAnswersNextTime => $c->can_recordAnswers(@args, $c->{submitAnswers}),
checkAnswersNextTime => $c->can_checkAnswers(@args, $c->{submitAnswers}),
gradeUnsubmittedTest => $c->can_gradeUnsubmittedTest(@args, $c->{submitAnswers}),
showScore => $c->can_showScore(@args),
showProblemScores => $c->can_showProblemScores(@args),
showWork => $c->can_showWork(@args),
Expand All @@ -755,6 +769,12 @@ async sub pre_header_initialize ($c) {
$c->{can} = \%can;
$c->{will} = \%will;

# Issue a warning if a test has not been submitted, but can still be graded by the instructor.
$c->addbadmessage(
$c->maketext(
'This test version is past due, but has not been graded. You can still grade the test for this user.')
) if $can{gradeUnsubmittedTest} && $userID ne $effectiveUserID;

# Set up problem numbering and multipage variables.

my @problemNumbers;
Expand Down
20 changes: 12 additions & 8 deletions templates/ContentGenerator/GatewayQuiz.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
% # Remaining output of test headers.
% # Display timer or information about elapsed time, output link, and information about any recorded score if not
% # submitAnswers or checkAnswers.
% if ($c->{can}{recordAnswersNextTime}) {
% if ($c->{can}{recordAnswersNextTime} || $c->{can}{gradeUnsubmittedTest}) {
% my $timeLeft = $c->{set}->due_date - int($submitTime); # This is in seconds
%
% # Print the timer if there is less than 24 hours left.
Expand Down Expand Up @@ -269,11 +269,13 @@
) =%>
% }
%
% if ($timeLeft < 60 && $timeLeft > 0 && !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) {
% if ($timeLeft < 60 && $timeLeft > 0 && !$c->{can}{gradeUnsubmittedTest}
% && !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) {
<div class="alert alert-danger d-inline-block mb-2 p-1">
<strong><%= maketext('You have less than 1 minute to complete this test.') %></strong>
</div>
% } elsif ($timeLeft <= 0 && !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) {
% } elsif ($timeLeft <= 0 && !$c->{can}{gradeUnsubmittedTest} &&
% !$authz->hasPermissions($userID, 'record_answers_when_acting_as_student')) {
<div class="alert alert-danger d-inline-block mb-2 p-1">
<strong>
<%= maketext('You are out of time!')
Expand Down Expand Up @@ -653,11 +655,16 @@
%
<div class="submit-buttons-container col-12 mb-2">
<%= submit_button maketext('Preview Test'), name => 'previewAnswers', class => 'btn btn-primary mb-1' =%>
% if ($c->{can}{recordAnswersNextTime}) {
% if ($c->{can}{checkAnswersNextTime}
% && (!$c->{can}{recordAnswersNextTime} || $c->{can}{showProblemGrader})) {
<%= submit_button maketext('Check Test'), name => 'checkAnswers', class => 'btn btn-primary mb-1' =%>
% }
% if ($c->{can}{recordAnswersNextTime} || $c->{can}{gradeUnsubmittedTest}) {
<%= tag('input',
type => 'submit',
name => 'submitAnswers',
value => maketext('Grade Test'),
value => $effectiveUserID ne $userID
? maketext('Grade Test for [_1]', $effectiveUserID) : maketext('Grade Test'),
class => 'btn btn-primary mb-1',
$c->{set}->attempts_per_version
? (
Expand Down Expand Up @@ -687,9 +694,6 @@
: ()
) =%>
% }
% if ($c->{can}{checkAnswersNextTime} && !$c->{can}{recordAnswersNextTime}) {
<%= submit_button maketext('Check Test'), name => 'checkAnswers', class => 'btn btn-primary mb-1' =%>
% }
</div>
% if ($numProbPerPage && $numPages > 1 && $c->{can}{recordAnswersNextTime}) {
<p><em><%= maketext('Note: grading the test grades all problems, not just those on this page.') %></em></p>
Expand Down

0 comments on commit bdd47c6

Please sign in to comment.