Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions conf/defaults.config
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@ $authen{admin_module} = ['WeBWorK::Authen::Basic_TheLastOption'];
change_password => "student",
change_email_address => "student",
change_pg_display_settings => "student",
view_own_answers_early => "nobody",

proctor_quiz_login => "login_proctor",
proctor_quiz_grade => "grade_proctor",
Expand Down
13 changes: 13 additions & 0 deletions lib/WeBWorK/ConfigValues.pm
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,19 @@ sub getConfigValues ($ce) {
),
type => 'permission'
},
{
var => 'permissionLevels{view_own_answers_early}',
doc => x('Allowed to view their own answer key early'),
doc2 => x(
'Users at this level and higher are given a button on the problem set page that lets them '
. 'override their own answer date for that set to the current time, immediately making the '
. 'correct answers to problems in that set available to them. If their close date and/or '
. 'reduced scoring date for the set are still in the future, those are also moved up to the '
. 'current time. This cannot be undone by the student. By default this is disabled '
. '("nobody").'
),
type => 'permission'
},
{
var => 'permissionLevels{navigation_allowed}',
doc => x('Allowed to view course home page'),
Expand Down
40 changes: 40 additions & 0 deletions lib/WeBWorK/ContentGenerator/ProblemSet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,46 @@ async sub initialize ($c) {
my $effectiveUser = $db->getUser($eUserID);
$c->{set} = $authz->{merged_set};

# Allow a student to view their own answer key early by overriding their answer date to now, if this is
# enabled via the view_own_answers_early permission. If the close date and/or reduced scoring date are still
# in the future, they are moved up to now as well, since they cannot be allowed to remain later than the new
# answer date.
if ($c->param('viewAnswersEarly')
&& $authz->hasPermissions($userID, 'view_own_answers_early')
&& $userID eq $eUserID
&& !$c->{viewSetCheck}
&& $c->{set}->assignment_type !~ /gateway/)
{
my $now = time;
if ($now < $c->{set}->answer_date) {
my $userSet = $db->getUserSet($eUserID, $c->{set}->set_id);
if ($userSet) {
my $dueDate = $c->{set}->due_date;
my $reducedScoringDate = $c->{set}->reduced_scoring_date;

$userSet->answer_date($now);
$userSet->due_date($now) if $dueDate > $now;
$userSet->reduced_scoring_date($now) if $reducedScoringDate && $reducedScoringDate > $now;

eval { $db->putUserSet($userSet) };
if ($@) {
$c->log->error("Unable to reveal answers early for set @{[$c->{set}->set_id]} for $eUserID: $@");
$c->addbadmessage(
$c->maketext(
'The answer key for this set was not made available due to an internal error.')
);
} else {
$c->{set}->answer_date($now);
$c->{set}->due_date($now) if $dueDate > $now;
$c->{set}->reduced_scoring_date($now) if $reducedScoringDate && $reducedScoringDate > $now;
$c->addgoodmessage($c->maketext('The answer key for this set is now available.'));
}
}
} else {
$c->addbadmessage($c->maketext('The answer key for this set is already available.'));
}
}

$c->{displayMode} = $user->displayMode || $ce->{pg}{options}{displayMode};

# Import problem records for assignments or test version records for tests now. Then initialize all
Expand Down
44 changes: 44 additions & 0 deletions templates/ContentGenerator/ProblemSet/auxiliary_tools.html.ep
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,50 @@
</span>
% }
% }
% if (
% $authz->hasPermissions(param('user'), 'view_own_answers_early')
% && $c->{set}->assignment_type !~ /gateway/
% && param('user') eq param('effectiveUser')
% && time < $c->{set}->answer_date
% ) {
<%= link_to maketext('Show Answers Now') => '#modal_view_answers_early',
role => 'button',
class => 'btn btn-primary',
id => 'popup_view_answers_early',
data => { bs_toggle => 'modal' }
=%>
<div id="modal_view_answers_early" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title h4"><%= maketext('Show Answers Now?') %></h1>
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="<%= maketext('close') %>"></button>
</div>
<div class="modal-body">
<p class="mb-0"><%= maketext(
'Are you sure you want to see the answer key now? This will change your answer date '
. 'for this set to the current time, making the correct answers to problems in this '
. 'set available to you immediately. If your close date and/or reduced scoring date '
. 'for this set are still in the future, those will also be changed to the current '
. 'time. This cannot be undone.'
) %></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
<%= maketext('Cancel') %>
</button>
<%= form_for current_route, method => 'POST', name => 'view_answers_early', begin =%>
<%= $c->hidden_authen_fields =%>
<%= submit_button maketext('Yes, Show Me the Answers'), name => 'viewAnswersEarly',
class => 'btn btn-primary' =%>
<%= end =%>
</div>
</div>
</div>
</div>
% }
%
% unless ($c->{set}->assignment_type =~ /gateway/) {
<%= link_to
maketext('Download Hardcopy') => $c->systemLink(url_for 'hardcopy_preselect_set'),
Expand Down