Skip to content

Commit

Permalink
MDL-82124 mod_assign: recalculate penalty
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathan Nguyen committed Aug 30, 2024
1 parent ca4f081 commit 10e78b6
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lang/en/grades.php
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,8 @@
$string['modgradeerrorbadpoint'] = 'Invalid grade value. This must be an integer between 1 and {$a}';
$string['modgradeerrorbadscale'] = 'Invalid scale selected. Please make sure you select a scale from the selections below.';
$string['modgrademaxgrade'] = 'Maximum grade';
$string['modgraderecalculatepenalty'] = 'Recalculate penalty';
$string['modgraderecalculatepenalty_help'] = 'The penalty will be recalculated for all users.';
$string['modgraderescalegrades'] = 'Rescale existing grades';
$string['modgraderescalegrades_help'] = 'When changing the maximum grades on a gradebook item you need to specify whether or not this will cause existing percentage grades to change as well.
Expand Down
3 changes: 3 additions & 0 deletions mod/assign/amd/build/override_delete_modal.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mod/assign/amd/build/override_delete_modal.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 43 additions & 0 deletions mod/assign/amd/src/override_delete_modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Modal from 'core/modal';

// Custom modal.
let modal = null;

/**
* Override Delete Modal
*/
export class OverrideDeleteModal extends Modal {
static TYPE = "mod_assign/override_delete_modal";
static TEMPLATE = "mod_assign/override_delete_modal";
}

/**
* Selectors
*/
const SELECTORS = {
DELETE_BUTTONS: '.delete-override',
};

export const init = async () => {

// Create the modal.
modal = await OverrideDeleteModal.create({});

// Add event listeners.
document.querySelectorAll(SELECTORS.DELETE_BUTTONS).forEach(button => {
button.addEventListener('click', async (event) => {
event.preventDefault();
show(event.target);
});
});

};

/**

Check failure on line 36 in mod/assign/amd/src/override_delete_modal.js

View workflow job for this annotation

GitHub Actions / Grunt

Missing JSDoc @param "target" declaration
* Show the modal.
*/
export const show = (target) => {

Check failure on line 39 in mod/assign/amd/src/override_delete_modal.js

View workflow job for this annotation

GitHub Actions / Grunt

'target' is defined but never used
//
modal.show();

};
1 change: 1 addition & 0 deletions mod/assign/lang/en/assign.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@
$string['page-mod-assign-view'] = 'Assignment module main and submission page';
$string['paramtimeremaining'] = '{$a} remaining';
$string['participant'] = 'Participant';
$string['penaltyduedatechangemessage'] = 'Some grades have already been awarded. In order to change the due date, disable/enable penalty, you must first choose whether or not to recalculate existing grades.';
$string['pluginadministration'] = 'Assignment administration';
$string['pluginname'] = 'Assignment';
$string['preventsubmissionnotingroup'] = 'Require group to make submission';
Expand Down
7 changes: 7 additions & 0 deletions mod/assign/locallib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,13 @@ public function update_instance($formdata) {
$update->nosubmissions = (!$this->is_any_submission_plugin_enabled()) ? 1: 0;
$DB->update_record('assign', $update);

// Check if we need to recalculate penalty for existing grades.
if (!empty($formdata->recalculatepenalty) && $formdata->recalculatepenalty === 'yes') {
$assign = clone $this->get_instance();
$assign->cmidnumber = $this->get_course_module()->idnumber;
assign_update_grades($assign);
}

return $result;
}

Expand Down
44 changes: 43 additions & 1 deletion mod/assign/mod_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class mod_assign_mod_form extends moodleform_mod {
* @return void
*/
public function definition() {
global $CFG, $COURSE, $DB;
global $CFG, $COURSE, $DB, $OUTPUT;;
$mform = $this->_form;

$mform->addElement('header', 'general', get_string('general', 'form'));
Expand Down Expand Up @@ -95,9 +95,24 @@ public function definition() {
$mform->addElement('date_time_selector', 'allowsubmissionsfromdate', $name, $options);
$mform->addHelpButton('allowsubmissionsfromdate', 'allowsubmissionsfromdate', 'assign');

// Add the option to recalculate the penalty if there is existing grade.
$penaltysettingmessage = '';
if (\mod_assign\penalty\helper::is_penalty_enabled($assignment->get_instance()->id) && $assignment->count_grades() > 0) {
// Create notification.
$penaltysettingmessage = $OUTPUT->notification(get_string('penaltyduedatechangemessage', 'assign'), 'warning', false);
$mform->addElement('html', $penaltysettingmessage);
$mform->addElement('select', 'recalculatepenalty', get_string('modgraderecalculatepenalty', 'grades'), [
'' => get_string('choose'),
'no' => get_string('no'),
'yes' => get_string('yes'),
]);
$mform->addHelpButton('recalculatepenalty', 'modgraderecalculatepenalty', 'grades');
}

$name = get_string('duedate', 'assign');
$mform->addElement('date_time_selector', 'duedate', $name, array('optional'=>true));
$mform->addHelpButton('duedate', 'duedate', 'assign');
$mform->disabledIf('duedate', 'recalculatepenalty', 'eq', '');

$name = get_string('cutoffdate', 'assign');
$mform->addElement('date_time_selector', 'cutoffdate', $name, array('optional'=>true));
Expand Down Expand Up @@ -246,6 +261,12 @@ public function definition() {

// Add Penalty settings if the module supports it.
if (\core_grades\local\penalty\manager::is_penalty_enabled_for_module('assign')) {
// Show the message if we need to change the penalty settings.
if (!empty($penaltysettingmessage)) {
$mform->addElement('html', $penaltysettingmessage);
}

// Enable or disable the penalty settings.
$mform->addElement('selectyesno', 'gradepenalty', get_string('gradepenalty', 'mod_assign'));
$mform->addHelpButton('gradepenalty', 'gradepenalty', 'mod_assign');
$mform->setDefault('gradepenalty', 0);
Expand All @@ -255,6 +276,9 @@ public function definition() {

// Hide if the grade type is not set to point.
$mform->hideIf('gradepenalty', 'grade[modgrade_type]', 'neq', 'point');

// Disable if the recalculate penalty is not set.
$mform->disabledIf('gradepenalty', 'recalculatepenalty', 'eq', '');
}

$this->standard_coursemodule_elements();
Expand All @@ -263,6 +287,24 @@ public function definition() {
$this->add_action_buttons();
}

/**
* Override definition after data has been set.
*
* The value of date time selector will be lost in a POST request, if the selector is disabled.
* So, we need to set the value again.
*
* return void
*/
function definition_after_data() {
$mform = $this->_form;

// The value of date time selector will be lost in a POST request.
$recalculatepenalty = optional_param('recalculatepenalty', null, PARAM_TEXT);
if ($recalculatepenalty === '') {
$mform->setConstant('duedate', $mform->_defaultValues['duedate']);
}
}

/**
* Perform minimal validation on the settings form
* @param array $data
Expand Down
32 changes: 32 additions & 0 deletions mod/assign/override_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,22 @@ protected function definition() {
get_string('allowsubmissionsfromdate', 'assign'), array('optional' => true));
$mform->setDefault('allowsubmissionsfromdate', $assigninstance->allowsubmissionsfromdate);

// Add the option to recalculate the penalty if there is existing grade.
if ($this->assign->count_grades() > 0) {
// Create notification.
$notice = $OUTPUT->notification(get_string('penaltyduedatechangemessage', 'assign'), 'warning', false);
$mform->addElement('html', $notice);
$mform->addElement('select', 'recalculatepenalty', get_string('modgraderecalculatepenalty', 'grades'), [
'' => get_string('choose'),
'no' => get_string('no'),
'yes' => get_string('yes'),
]);
$mform->addHelpButton('recalculatepenalty', 'modgraderecalculatepenalty', 'grades');
}

$mform->addElement('date_time_selector', 'duedate', get_string('duedate', 'assign'), array('optional' => true));
$mform->setDefault('duedate', $assigninstance->duedate);
$mform->disabledIf('duedate', 'recalculatepenalty', 'eq', '');

$mform->addElement('date_time_selector', 'cutoffdate', get_string('cutoffdate', 'assign'), array('optional' => true));
$mform->setDefault('cutoffdate', $assigninstance->cutoffdate);
Expand Down Expand Up @@ -286,6 +300,24 @@ protected function definition() {

}

/**
* Override definition after data has been set.
*
* The value of date time selector will be lost in a POST request, if the selector is disabled.
* So, we need to set the value again.
*
* return void
*/
function definition_after_data() {
$mform = $this->_form;

// The value of date time selector will be lost in a POST request.
$recalculatepenalty = optional_param('recalculatepenalty', null, PARAM_TEXT);
if ($recalculatepenalty === '') {
$mform->setConstant('duedate', $mform->_defaultValues['duedate']);
}
}

/**
* Validate the submitted form data.
*
Expand Down
16 changes: 16 additions & 0 deletions mod/assign/overrideedit.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,22 @@
$event->trigger();
}

// Check if we need to recalculate penalty for existing grades.
if (!empty($fromform->recalculatepenalty) && $fromform->recalculatepenalty === 'yes') {
$assignintance = clone $assign->get_instance();
$assignintance->cmidnumber = $assign->get_course_module()->idnumber;
// If it is user mode.
if (!$groupmode) {
assign_update_grades($assignintance, $fromform->userid);
} else {
// If it is group mode.
$groupmembers = groups_get_members($fromform->groupid);
foreach ($groupmembers as $groupmember) {
assign_update_grades($assignintance, $groupmember->id);
}
}
}

assign_update_events($assign, $fromform);

if (!empty($fromform->submitbutton)) {
Expand Down
5 changes: 4 additions & 1 deletion mod/assign/overrides.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,9 +232,12 @@
// Delete.
$deleteurlstr = $overridedeleteurl->out(true,
array('id' => $override->id, 'sesskey' => sesskey()));
$iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' .
$iconstr .= '<a title="' . get_string('delete') . '" href="#" class="delete-override" data-url="' . $deleteurlstr . '">' .
$OUTPUT->pix_icon('t/delete', get_string('delete')) . '</a> ';

// Add js script for "override delete" button.
$PAGE->requires->js_call_amd('mod_assign/override_delete_modal', 'init');

if ($groupmode) {
$usergroupstr = '<a href="' . $groupurl->out(true, ['group' => $override->groupid]) . '" >' .
format_string($override->name, true, ['context' => $context]) . '</a>';
Expand Down
49 changes: 49 additions & 0 deletions mod/assign/templates/override_delete_modal.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_assign/override_delete_modal
Example context (json):
{
}

}}
{{< core/modal }}
{{$title}}{{#str}} login {{/str}}{{/title}}
{{$body}}
<div class="container">
<form>
<div class="form-group row">
<label for="inputEmail" class="col-sm-2 col-form-label">{{#str}} email {{/str}}</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail" placeholder="{{#str}} email {{/str}}">
</div>
</div>
<div class="form-group row">
<label for="inputPassword" class="col-sm-2 col-form-label">{{#str}} password {{/str}}</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword" placeholder="{{#str}} password {{/str}}">
</div>
</div>
</form>
</div>
{{/body}}
{{$footer}}
<button type="button" class="btn btn-primary" data-action="login">{{#str}} login {{/str}}</button>
<button type="button" class="btn btn-secondary" data-action="cancel">{{#str}} cancel {{/str}}</button>
{{/footer}}
{{/ core/modal }}

0 comments on commit 10e78b6

Please sign in to comment.