MDL-82681 mod_assign: Add Suspended participants to Advanced filters

Adds 'Suspended participants' filter to the 'Advanced' filters
component on the assignment submissions page.
This commit is contained in:
Mihail Geshoski
2024-09-19 23:16:49 +08:00
parent ac1d386443
commit 9265ab5ca8
9 changed files with 168 additions and 6 deletions
@@ -5,6 +5,6 @@ define("mod_assign/actionbar/grading/extra_filters_dropdown",["exports","core/lo
* @module mod_assign/actionbar/grading/extra_filters_dropdown
* @copyright 2024 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const Selectors_extraFiltersDropdown=".dropdown.extrafilters",Selectors_extraFiltersClose='a[data-action="close"]',Selectors_workflowFilterElement='select[name="workflowfilter"]',Selectors_markerFilterElement='select[name="markingallocationfilter"]',restoreAppliedWorkflowFilter=async extraFiltersDropdown=>{const appliedWorkflowFilter=await(0,_repository.getUserPreference)("assign_workflowfilter");extraFiltersDropdown.getElement().querySelector(Selectors_workflowFilterElement).value=appliedWorkflowFilter},restoreAppliedMarkerFilter=async extraFiltersDropdown=>{const markerFilterSelect=extraFiltersDropdown.getElement().querySelector(Selectors_markerFilterElement);if(markerFilterSelect){const appliedMarkerFilter=await(0,_repository.getUserPreference)("assign_markerfilter");markerFilterSelect.value=appliedMarkerFilter}};_exports.init=()=>{const extraFiltersDropdown=(0,_dialog.getDropdownDialog)(Selectors_extraFiltersDropdown);extraFiltersDropdown&&(extraFiltersDropdown=>{extraFiltersDropdown.getElement().addEventListener("click",(e=>{e.target.closest(Selectors_extraFiltersClose)&&(e.preventDefault(),extraFiltersDropdown.setVisible(!1))})),(0,_jquery.default)(extraFiltersDropdown.getElement()).on("hide.bs.dropdown",(()=>{restoreAppliedWorkflowFilter(extraFiltersDropdown),restoreAppliedMarkerFilter(extraFiltersDropdown)}))})(extraFiltersDropdown)}}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=(obj=_jquery)&&obj.__esModule?obj:{default:obj};const Selectors_extraFiltersDropdown=".dropdown.extrafilters",Selectors_extraFiltersClose='a[data-action="close"]',Selectors_workflowFilterElement='select[name="workflowfilter"]',Selectors_markerFilterElement='select[name="markingallocationfilter"]',Selectors_suspendedParticipantsFilterCheckbox='input[type="checkbox"][name="suspendedparticipantsfilter"]',Selectors_suspendedParticipantsFilterHidden='input[type="hidden"][name="suspendedparticipantsfilter"]',restoreAppliedWorkflowFilter=async extraFiltersDropdown=>{const appliedWorkflowFilter=await(0,_repository.getUserPreference)("assign_workflowfilter");extraFiltersDropdown.getElement().querySelector(Selectors_workflowFilterElement).value=appliedWorkflowFilter},restoreAppliedMarkerFilter=async extraFiltersDropdown=>{const markerFilterSelect=extraFiltersDropdown.getElement().querySelector(Selectors_markerFilterElement);if(markerFilterSelect){const appliedMarkerFilter=await(0,_repository.getUserPreference)("assign_markerfilter");markerFilterSelect.value=appliedMarkerFilter}},restoreAppliedSuspendedParticipantsFilter=async extraFiltersDropdown=>{const suspendedParticipantsFilterCheckbox=extraFiltersDropdown.getElement().querySelector(Selectors_suspendedParticipantsFilterCheckbox);if(suspendedParticipantsFilterCheckbox){const suspendedParticipantsFilterHidden=suspendedParticipantsFilterCheckbox.parentNode.querySelector(Selectors_suspendedParticipantsFilterHidden),showOnlyActiveParticipants=await(0,_repository.getUserPreference)("grade_report_showonlyactiveenrol");suspendedParticipantsFilterCheckbox.checked=!showOnlyActiveParticipants,suspendedParticipantsFilterHidden.disabled=!showOnlyActiveParticipants}};_exports.init=()=>{const extraFiltersDropdown=(0,_dialog.getDropdownDialog)(Selectors_extraFiltersDropdown);extraFiltersDropdown&&(extraFiltersDropdown=>{extraFiltersDropdown.getElement().addEventListener("click",(e=>{e.target.closest(Selectors_extraFiltersClose)&&(e.preventDefault(),extraFiltersDropdown.setVisible(!1))})),extraFiltersDropdown.getElement().addEventListener("change",(e=>{const suspendedParticipantsFilterCheckbox=e.target.closest(Selectors_suspendedParticipantsFilterCheckbox);suspendedParticipantsFilterCheckbox&&(suspendedParticipantsFilterCheckbox.parentNode.querySelector(Selectors_suspendedParticipantsFilterHidden).disabled=suspendedParticipantsFilterCheckbox.checked)})),(0,_jquery.default)(extraFiltersDropdown.getElement()).on("hide.bs.dropdown",(()=>{restoreAppliedWorkflowFilter(extraFiltersDropdown),restoreAppliedMarkerFilter(extraFiltersDropdown),restoreAppliedSuspendedParticipantsFilter(extraFiltersDropdown)}))})(extraFiltersDropdown)}}));
//# sourceMappingURL=extra_filters_dropdown.min.js.map
File diff suppressed because one or more lines are too long
@@ -30,7 +30,9 @@ const Selectors = {
extraFiltersDropdown: '.dropdown.extrafilters',
extraFiltersClose: 'a[data-action="close"]',
workflowFilterElement: 'select[name="workflowfilter"]',
markerFilterElement: 'select[name="markingallocationfilter"]'
markerFilterElement: 'select[name="markingallocationfilter"]',
suspendedParticipantsFilterCheckbox: 'input[type="checkbox"][name="suspendedparticipantsfilter"]',
suspendedParticipantsFilterHidden: 'input[type="hidden"][name="suspendedparticipantsfilter"]'
};
/**
@@ -47,11 +49,27 @@ const registerEventListeners = (extraFiltersDropdown) => {
extraFiltersDropdown.setVisible(false);
}
});
// Change event listener to the extra filters dropdown element.
extraFiltersDropdown.getElement().addEventListener('change', e => {
const suspendedParticipantsFilterCheckbox = e.target.closest(Selectors.suspendedParticipantsFilterCheckbox);
// The target is the 'Suspended participants' filter checkbox.
if (suspendedParticipantsFilterCheckbox) {
// The 'Suspended participants' filter uses a hidden input and a checkbox. The hidden input is used to
// submit '0' as a workaround when the checkbox is unchecked since unchecked checkboxes are not submitted
// with the form. Therefore, we need to enable or disable the hidden input based on the checkbox state.
const suspendedParticipantsFilterHidden = suspendedParticipantsFilterCheckbox.parentNode
.querySelector(Selectors.suspendedParticipantsFilterHidden);
suspendedParticipantsFilterHidden.disabled = suspendedParticipantsFilterCheckbox.checked;
}
});
// Event listener triggered upon hiding of the dropdown.
$(extraFiltersDropdown.getElement()).on('hide.bs.dropdown', () => {
// Restore the filters to their stored preference values once the dropdown is closed.
restoreAppliedWorkflowFilter(extraFiltersDropdown);
restoreAppliedMarkerFilter(extraFiltersDropdown);
restoreAppliedSuspendedParticipantsFilter(extraFiltersDropdown);
});
};
@@ -79,6 +97,23 @@ const restoreAppliedMarkerFilter = async(extraFiltersDropdown) => {
}
};
/**
* Restores the currently suspended participants filter to its stored preference value.
*
* @param {DropdownDialog} extraFiltersDropdown The dropdown dialog instance.
*/
const restoreAppliedSuspendedParticipantsFilter = async(extraFiltersDropdown) => {
const suspendedParticipantsFilterCheckbox = extraFiltersDropdown.getElement()
.querySelector(Selectors.suspendedParticipantsFilterCheckbox);
if (suspendedParticipantsFilterCheckbox) {
const suspendedParticipantsFilterHidden = suspendedParticipantsFilterCheckbox.parentNode
.querySelector(Selectors.suspendedParticipantsFilterHidden);
const showOnlyActiveParticipants = await getUserPreference('grade_report_showonlyactiveenrol');
suspendedParticipantsFilterCheckbox.checked = !showOnlyActiveParticipants;
suspendedParticipantsFilterHidden.disabled = !showOnlyActiveParticipants;
}
};
/**
* Initialize module.
*/
@@ -318,6 +318,12 @@ class grading_actionmenu implements templatable, renderable {
}
}
if (has_capability('moodle/course:viewsuspendedusers', $this->assign->get_context())) {
$dropdowncontentdata['filters']['suspendedparticipants'] = [
'active' => !$this->assign->show_only_active_users(),
];
}
// If there are no available filters, return null.
if (empty($dropdowncontentdata['filters'])) {
return null;
@@ -365,7 +371,11 @@ class grading_actionmenu implements templatable, renderable {
if ($canallocatemarker && get_user_preferences('assign_markerfilter')) {
$appliedextrafilterscount++;
}
}
// If suspended participants are included.
if (!$this->assign->show_only_active_users()) {
$appliedextrafilterscount++;
}
return $appliedextrafilterscount;
+1
View File
@@ -344,6 +344,7 @@ Note that this setting has no effect on the comments box on the grading page.';
$string['hideshow'] = 'Hide/Show';
$string['hiddenuser'] = 'Participant ';
$string['inactiveoverridehelp'] = '* This override is inactive because the user\'s access to the activity is restricted. This can be due to group or role assignments, other access restrictions, or the activity being hidden.';
$string['includesuspendedparticipants'] = 'Include suspended participants';
$string['indicator:cognitivedepth'] = 'Assignment cognitive';
$string['indicator:cognitivedepth_help'] = 'This indicator is based on the cognitive depth reached by the student in an assignment activity.';
$string['indicator:cognitivedepthdef'] = 'Assignment cognitive';
+8
View File
@@ -4534,6 +4534,14 @@ class assign {
set_user_preference('assign_markerfilter', $markingallocationfilter);
}
// Retrieve the 'suspendedparticipantsfilter' parameter, or set it to null if not provided.
$suspendedparticipantsfilter = optional_param('suspendedparticipantsfilter', null, PARAM_BOOL);
if ($suspendedparticipantsfilter !== null &&
has_capability('moodle/course:viewsuspendedusers', $this->get_context())) {
// Save the 'suspendedparticipantsfilter' value as a user preference.
set_user_preference('grade_report_showonlyactiveenrol', !$suspendedparticipantsfilter);
}
$controller = $gradingmanager->get_active_controller();
$showquickgrading = empty($controller) && $this->can_grade();
$quickgrading = get_user_preferences('assign_quickgrading', false);
@@ -30,6 +30,8 @@
* key - The key of the marking allocation filter option
* name - The name of the marking allocation filter option
* active - Whether the marking allocation filter option is currently active
* suspendedparticipants
* active - Whether the suspended participants filter is currently active
Example context (json):
{
@@ -55,6 +57,9 @@
"active": true
}
]
},
"suspendedparticipants": {
"active": true
}
}
]
@@ -89,6 +94,13 @@
</select>
</div>
{{/markingallocation}}
{{#suspendedparticipants}}
<div class="row m-0 pb-3 pt-2 mx-1 align-items-center">
<input type="hidden" name="suspendedparticipantsfilter" value="0" {{#active}}disabled{{/active}}>
<input type="checkbox" id="filter-suspended-participants-{{uniqid}}" name="suspendedparticipantsfilter" value="1" {{#active}}checked{{/active}}>
<label for="filter-suspended-participants-{{uniqid}}" class='m-0' >{{#str}} includesuspendedparticipants, mod_assign {{/str}}</label>
</div>
{{/suspendedparticipants}}
{{/filters}}
<div class="d-flex flex-row justify-content-end align-items-center pt-2">
<a href="#" class="pull-right mx-3 text-decoration-none text-dark" data-action="close">{{#str}}closebuttontitle{{/str}}</a>
@@ -30,15 +30,13 @@ Feature: In an assignment, teachers can filter displayed submissions by marking
Given I am on the "Test assignment" Activity page logged in as teacher1
And I navigate to "Submissions" in current page administration
And I change window size to "large"
And "Advanced" "button" should not exist in the ".tertiary-navigation" "css_element"
When I am on the "Test assignment" "assign activity editing" page
And I expand all fieldsets
And I set the field "Use marking workflow" to "Yes"
And I press "Save and display"
And I navigate to "Submissions" in current page administration
Then "Advanced" "button" should exist in the ".tertiary-navigation" "css_element"
And I click on "Advanced" "button" in the ".tertiary-navigation" "css_element"
And "Marking state" "select" should exist in the ".extrafilters .dropdown-menu" "css_element"
Then "Marking state" "select" should exist in the ".extrafilters .dropdown-menu" "css_element"
And the field "Marking state" matches value "No filter"
And the "Marking state" select box should contain "No filter"
And the "Marking state" select box should contain "Not marked"
@@ -0,0 +1,98 @@
@mod @mod_assign
Feature: In an assignment, teachers can include or exclude submissions from suspended participants
In order to manage submissions more easily
As a teacher
I need to be able to include or exclude submissions from suspended participants.
Background:
Given the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| student1 | Student | 1 | student1@example.com |
| student2 | Student | 2 | student2@example.com |
And the following "course enrolments" exist:
| user | course | role | status |
| teacher1 | C1 | editingteacher | 0 |
| student1 | C1 | student | 0 |
| student2 | C1 | student | 1 |
And the following "activity" exists:
| activity | assign |
| course | C1 |
| name | Test assignment name |
@javascript
Scenario: The suspended participants filter is available only when the teacher has the capability to view suspended participants
Given the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/course:viewsuspendedusers | Prevent | editingteacher | Course | C1 |
And I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Submissions" in current page administration
When I change window size to "large"
# Ensure the Advanced filters component is not available. This validates that the Suspended participants filer is
# not available as well since it's part of this component.
Then "Advanced" "button" should not exist in the ".tertiary-navigation" "css_element"
And the following "permission overrides" exist:
| capability | permission | role | contextlevel | reference |
| moodle/course:viewsuspendedusers | Allow | editingteacher | Course | C1 |
And I reload the page
And "Advanced" "button" should exist in the ".tertiary-navigation" "css_element"
And I click on "Advanced" "button" in the ".tertiary-navigation" "css_element"
And "Include suspended participants" "checkbox" should exist in the ".extrafilters .dropdown-menu" "css_element"
And the field "Include suspended participants" matches value ""
@javascript
Scenario: Teacher can include or exclude submissions from suspended participants
Given I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Submissions" in current page administration
And I change window size to "large"
And the following should exist in the "submissions" table:
| -2- |
| Student 1 |
And the following should not exist in the "submissions" table:
| -2- |
| Student 2 |
# Set to include submissions from suspended participants.
And I click on "Advanced" "button" in the ".tertiary-navigation" "css_element"
When I click on "Include suspended participants" "checkbox" in the ".extrafilters .dropdown-menu" "css_element"
And I click on "Apply" "button" in the ".extrafilters .dropdown-menu" "css_element"
# Ensure that the suspended Student 2 is now also displayed in the submissions table.
Then the following should exist in the "submissions" table:
| -2- |
| Student 1 |
| Student 2 |
# Ensure the badge indicating the number of applied filters is present.
And ".badge" "css_element" should exist in the ".extrafilters .dropdown-toggle" "css_element"
And I should see "+1" in the ".extrafilters .badge" "css_element"
# Ensure the filter remains applied when navigating away from and returning to the assignment submissions page.
And I am on the "Test assignment name" Activity page
And I navigate to "Submissions" in current page administration
And the following should exist in the "submissions" table:
| -2- |
| Student 1 |
| Student 2 |
And I click on "Advanced" "button" in the ".tertiary-navigation" "css_element"
And the field "Include suspended participants" matches value "1"
# Ensure the filter is not applied unless the 'Apply' button is pressed.
And I click on "Include suspended participants" "checkbox" in the ".extrafilters .dropdown-menu" "css_element"
And the field "Include suspended participants" matches value ""
And I click on "Close" "link" in the ".extrafilters .dropdown-menu" "css_element"
And the following should exist in the "submissions" table:
| -2- |
| Student 1 |
| Student 2 |
And I click on "Advanced" "button" in the ".tertiary-navigation" "css_element"
And the field "Include suspended participants" matches value "1"
# Set to exclude submissions from suspended participants.
And I click on "Include suspended participants" "checkbox" in the ".extrafilters .dropdown-menu" "css_element"
And the field "Include suspended participants" matches value ""
And I click on "Apply" "button" in the ".extrafilters .dropdown-menu" "css_element"
# Ensure only Student 1 is now displayed in the submissions table.
And the following should exist in the "submissions" table:
| -2- |
| Student 1 |
And the following should not exist in the "submissions" table:
| -2- |
| Student 2 |