Merge branch 'MDL-54105-master-default_grade_on_mod_assign' of https://github.com/praxisdigital/moodle

This commit is contained in:
Huong Nguyen 2024-05-28 15:21:39 +07:00
commit 175e48bc08
No known key found for this signature in database
GPG Key ID: 40D88AB693A3E72A
12 changed files with 283 additions and 24 deletions

View File

@ -62,8 +62,8 @@ Feature: Manage scheduled tasks
And I press "Save changes"
Then I should see "Changes saved"
And the following should not exist in the "admintable" table:
| Name | Component | Minute | Hour | Day | Day of week | Month |
| Log table cleanup | Standard log | */5 | 1 | 2 | 4 | 3 |
| Name | Minute | Hour | Day | Day of week | Month |
| Log table cleanup | */5 | 1 | 2 | 4 | 3 |
And I should see "Log table cleanup" in the "tr.table-primary" "css_element"
Scenario: Disabled plugin's tasks are labelled as disabled too

View File

@ -60,8 +60,8 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group {
/** @var int $currentscaleid The current scale id */
public $currentscaleid = null;
/** @var string $currentgradetype The current gradetype - can either be 'none', 'scale', or 'point' */
public $currentgradetype = 'none';
/** @var ?string $currentgradetype The current gradetype - can either be 'none', 'scale', or 'point' */
public $currentgradetype = null;
/** @var boolean $useratings Set to true if the activity is using ratings, false otherwise */
public $useratings = false;
@ -514,18 +514,30 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group {
// This means that the subelements data (inc const and default values) can be overridden by form code.
// So - when we call this code really we can't be sure that will be the end value for the element.
if (!empty($this->_elements)) {
if (!empty($value)) {
if ($value < 0) {
$this->gradetypeformelement->setValue('scale');
$this->scaleformelement->setValue(($value * -1));
} else if ($value > 0) {
$this->gradetypeformelement->setValue('point');
$maxvalue = !empty($this->currentgrade) ? (string)unformat_float($this->currentgrade) : $value;
$this->maxgradeformelement->setValue($maxvalue);
if (!$this->currentgradetype) {
if (!empty($value)) {
$this->currentgradetype = $value < 0 ? 'scale' : 'point';
} else {
$this->currentgradetype = 'none';
}
} else {
$this->gradetypeformelement->setValue('none');
$this->maxgradeformelement->setValue(100);
}
$this->gradetypeformelement->setValue($this->currentgradetype);
switch ($this->currentgradetype) {
case 'scale':
if (!empty($value)) {
$this->currentscaleid = $value * -1;
}
$this->scaleformelement->setValue($this->currentscaleid);
break;
case 'point':
case 'none':
if (!empty($value)) {
$maxvalue = !empty($this->currentgrade) ? (string)unformat_float($this->currentgrade) : $value;
}
$this->maxgradeformelement->setValue($maxvalue ?? 100);
break;
}
}
break;

View File

@ -1453,7 +1453,8 @@ EOF;
// Get row xpath.
// Some drivers make XPath relative to the current context, so use descendant.
$rowxpath = $tablexpath . "/tbody/tr[descendant::*[@class='rowtitle'][normalize-space(.)=" . $rowliteral . "] | " . "
descendant::th[normalize-space(.)=" . $rowliteral . "] | descendant::td[normalize-space(.)=" . $rowliteral . "]]";
descendant::th[contains(normalize-space(.)," . $rowliteral . ")] | " . "
descendant::td[contains(normalize-space(.)," . $rowliteral . ")]]";
$columnvaluexpath = $rowxpath . $columnpositionxpath . "[contains(normalize-space(.)," . $valueliteral . ")]";

View File

@ -155,6 +155,10 @@ $string['cutoffdatecolon'] = 'Cut-off date: {$a}';
$string['cutoffdate_help'] = 'If set, submissions will not be accepted after this date without an extension. If not set, submissions will always be accepted.';
$string['cutoffdatevalidation'] = 'Cut-off date cannot be earlier than the due date.';
$string['cutoffdatefromdatevalidation'] = 'Cut-off date cannot be earlier than the allow submissions from date.';
$string['defaultgradescale'] = 'Default grade scale';
$string['defaultgradescale_help'] = 'The default grade scale to be used when creating new assignments. Only site level scales can be used as the default.';
$string['defaultgradetype'] = 'Default grade type';
$string['defaultgradetype_help'] = 'The default grade type to be used when creating new assignments';
$string['defaultlayout'] = 'Restore default layout';
$string['defaultsettings'] = 'Default assignment settings';
$string['defaultsettings_help'] = 'These settings define the defaults for all new assignments.';

View File

@ -945,20 +945,19 @@ function assign_print_recent_mod_activity($activity, $courseid, $detail, $modnam
}
/**
* Checks if scale is being used by any instance of assignment
* Checks if scale is being used by any instance of assignment or is the default scale used for assignments.
*
* This is used to find out if scale used anywhere
* @param int $scaleid
* @return boolean True if the scale is used by any assignment
* @return boolean True if the scale is used by any assignment or is the default scale used for assignments.
*/
function assign_scale_used_anywhere($scaleid) {
global $DB;
if ($scaleid and $DB->record_exists('assign', array('grade'=>-$scaleid))) {
return true;
} else {
return false;
}
return $scaleid && (
$DB->record_exists('assign', ['grade' => -(int)$scaleid]) ||
(int)get_config('mod_assign', 'defaultgradescale') === (int)$scaleid
);
}
/**

View File

@ -354,4 +354,52 @@ class mod_assign_mod_form extends moodleform_mod {
return !empty($data['completionsubmit' . $suffix]);
}
/**
* Get the list of admin settings for this module and apply any defaults/advanced/locked/required settings.
*
* @param array $datetimeoffsets - If passed, this is an array of fieldnames => times that the
* default date/time value should be relative to. If not passed, all
* date/time fields are set relative to the users current midnight.
* @return void
*/
public function apply_admin_defaults($datetimeoffsets = []): void {
parent::apply_admin_defaults($datetimeoffsets);
$isupdate = !empty($this->_cm);
if ($isupdate) {
return;
}
$settings = get_config('mod_assign');
$mform = $this->_form;
if ($mform->elementExists('grade')) {
$element = $mform->getElement('grade');
if (property_exists($settings, 'defaultgradetype')) {
switch ((int)$settings->defaultgradetype) {
case GRADE_TYPE_NONE :
$element->currentgradetype = 'none';
break;
case GRADE_TYPE_SCALE :
$element->currentgradetype = 'scale';
break;
case GRADE_TYPE_VALUE :
$element->currentgradetype = 'point';
break;
}
}
if (property_exists($settings, 'defaultgradescale')) {
/** @var grade_scale|false $gradescale */
$gradescale = grade_scale::fetch(['id' => (int)$settings->defaultgradescale, 'courseid' => 0]);
if ($gradescale) {
$element->currentscaleid = $gradescale->id;
}
}
$element->onQuickFormEvent('updateValue', null, $mform);
}
}
}

View File

@ -24,7 +24,9 @@
defined('MOODLE_INTERNAL') || die;
global $CFG;
require_once($CFG->dirroot . '/mod/assign/adminlib.php');
require_once($CFG->dirroot . '/grade/lib.php');
$ADMIN->add('modsettings', new admin_category('modassignfolder', new lang_string('pluginname', 'mod_assign'), $module->is_enabled() === false));
@ -163,6 +165,39 @@ if ($ADMIN->fulltree) {
);
$settings->add($setting);
$name = new lang_string('defaultgradetype', 'mod_assign');
$description = new lang_string('defaultgradetype_help', 'mod_assign');
$setting = new admin_setting_configselect('mod_assign/defaultgradetype',
$name,
$description,
GRADE_TYPE_VALUE, [
GRADE_TYPE_NONE => new lang_string('modgradetypenone', 'grades'),
GRADE_TYPE_SCALE => new lang_string('modgradetypescale', 'grades'),
GRADE_TYPE_VALUE => new lang_string('modgradetypepoint', 'grades'),
]);
$settings->add($setting);
/** @var grade_scale[] $scales */
$scales = grade_scale::fetch_all_global();
$choices = ['' => new lang_string('choosedots')];
foreach ($scales as $scale) {
$choices[$scale->id] = $scale->get_name();
}
$name = new lang_string('defaultgradescale', 'mod_assign');
$description = new lang_string('defaultgradescale_help', 'mod_assign');
if (count($choices) > 1) {
$setting = new admin_setting_configselect('mod_assign/defaultgradescale',
$name,
$description,
'', $choices);
} else {
$setting = new admin_setting_configempty('mod_assign/defaultgradescale',
$name,
$description
);
}
$settings->add($setting);
$name = new lang_string('gradingduedate', 'mod_assign');
$description = new lang_string('gradingduedate_help', 'mod_assign');
$setting = new admin_setting_configduration('assign/gradingduedate',

View File

@ -0,0 +1,76 @@
@mod @mod_assign
Feature: Assignments can have default grades and scales defined
In order to improve assignment creation
As a teacher
The grade and scale should be set by default
Background:
Given the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
@javascript
Scenario: When creating an assignment the default grade type and grade scale are set as default in the form
Given the following config values are set as admin:
| config | value | plugin |
| defaultgradetype | 2 | mod_assign |
| defaultgradescale | 2 | mod_assign |
When I am on the "Course 1" course page logged in as teacher1
And I wait until the page is ready
And I switch editing mode on
And I click on "Add an activity or resource" "button"
And I follow "Assignment"
And I set the following fields to these values:
| name | Test assignment |
Then the following fields match these values:
| grade[modgrade_type] | Scale |
| grade[modgrade_scale] | Default competence scale |
And I press "Save and return to course"
And I am on the "Test assignment" "assign activity editing" page
And the following fields match these values:
| grade[modgrade_type] | Scale |
| grade[modgrade_scale] | Default competence scale |
Scenario: Editing an assignment will save the selected grade type and grade scale
Given the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment |
| description | Assignment description |
| gradetype | 1 |
| gradescale | 1 |
When I am on the "Test assignment" "assign activity editing" page logged in as teacher1
And the following fields match these values:
| grade[modgrade_type] | Point |
| grade[modgrade_scale] | Default competence scale |
And I set the following fields to these values:
| grade[modgrade_type] | Scale |
| grade[modgrade_scale] | Separate and Connected ways of knowing |
And I press "Save and return to course"
And I am on the "Test assignment" "assign activity editing" page
Then the following fields match these values:
| grade[modgrade_type] | Scale |
| grade[modgrade_scale] | Separate and Connected ways of knowing |
Scenario: When a scale is set as the default grade scale it should be shown as in use
Given the following config values are set as admin:
| config | value | plugin |
| defaultgradetype | 2 | mod_assign |
| defaultgradescale | 2 | mod_assign |
When I log in as "admin"
And I navigate to "Grades > Scales" in site administration
Then "Default competence scale" row "Used" column of "generaltable" table should contain "Yes"
And "Separate and Connected ways of knowing" row "Used" column of "generaltable" table should contain "No"
And the following config values are set as admin:
| config | value | plugin |
| defaultgradetype | 2 | mod_assign |
| defaultgradescale | 1 | mod_assign |
And I navigate to "Grades > Scales" in site administration
And "Default competence scale" row "Used" column of "generaltable" table should contain "No"
And "Separate and Connected ways of knowing" row "Used" column of "generaltable" table should contain "Yes"

View File

@ -16,6 +16,9 @@
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/gradelib.php');
/**
* assign module data generator class
*
@ -66,6 +69,18 @@ class mod_assign_generator extends testing_module_generator {
$record->teamsubmissiongroupingid = $this->get_grouping_id($record->teamsubmissiongroupingid);
}
if (property_exists($record, 'gradetype')) {
if ((int)$record->gradetype === GRADE_TYPE_SCALE && property_exists($record, 'gradescale')) {
// Get the scale id and apply it.
$defaultsettings['grade[modgrade_type]'] = GRADE_TYPE_SCALE;
$defaultsettings['grade[modgrade_scale]'] = $record->gradescale;
$defaultsettings['grade'] = -$record->gradescale;
} else if ((int)$record->gradetype === GRADE_TYPE_NONE) {
$defaultsettings['grade[modgrade_type]'] = GRADE_TYPE_NONE;
$defaultsettings['grade'] = 0;
}
}
foreach ($defaultsettings as $name => $value) {
if (!isset($record->{$name})) {
$record->{$name} = $value;

View File

@ -0,0 +1,60 @@
<?php
// 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/>.
namespace mod_assign;
/**
* Test for mod assign generator.
* @package mod_assign
* @copyright Frederik Pytlick <fmp@moxis.dk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \mod_assign_generator
*/
final class generator_test extends \advanced_testcase {
/**
* Test creating an assignment instance using the mod_assign generator.
*/
public function test_create_instance(): void {
$this->resetAfterTest();
$datagenerator = self::getDataGenerator();
$course = $datagenerator->create_course();
$scale = $datagenerator->create_scale();
$generator = $datagenerator->get_plugin_generator('mod_assign');
$instance1 = $generator->create_instance([
'course' => $course,
'name' => 'Assign 1',
'gradetype' => GRADE_TYPE_SCALE,
'gradescale' => $scale->id,
]);
$instance2 = $generator->create_instance([
'course' => $course,
'name' => 'Assign 2',
'gradetype' => GRADE_TYPE_NONE,
]);
$instance3 = $generator->create_instance([
'course' => $course,
'name' => 'Assign 3',
'gradetype' => GRADE_TYPE_VALUE,
]);
$this->assertEquals(-$scale->id, $instance1->grade);
$this->assertEquals(0, $instance2->grade);
$this->assertEquals(100, $instance3->grade);
}
}

View File

@ -4,6 +4,15 @@ This file has been replaced by UPGRADING.md. See MDL-81125 for further informati
===
This files describes API changes in the assign code.
=== 4.5 ===
* Added 2 new settings:
- "mod_assign/defaultgradetype"
- The value of this setting dictates which of the GRADE_TYPE_X constants is the default option,
when creating new instances of the assignment.
- The default value is GRADE_TYPE_VALUE (Point)
- "mod_assign/defaultgradescale"
- The value of this setting dictates which of the existing scales is the default option,
when creating new instances of the assignment.
=== 4.3 ===
* The following deprecated methods have been removed and should not be used any more:

View File

@ -25,5 +25,5 @@
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'mod_assign'; // Full name of the plugin (used for diagnostics).
$plugin->version = 2024042201; // The current module version (Date: YYYYMMDDXX).
$plugin->version = 2024042202; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.