MDL-82225 cohort: convert single cohort deletion to JS & AJAX.

This commit is contained in:
Paul Holden 2024-07-08 13:11:52 +01:00
parent fd487cd3f2
commit 28ffd21d44
No known key found for this signature in database
GPG Key ID: A81A96D6045F6164
10 changed files with 87 additions and 50 deletions

View File

@ -1,10 +1,10 @@
define("core_cohort/actions",["exports","core/event_dispatcher","core/notification","core/pending","core/prefetch","core/str","core_cohort/repository","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core/local/inplace_editable/events"],(function(_exports,_event_dispatcher,_notification,_pending,_prefetch,_str,_repository,reportEvents,reportSelectors,_events2){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
define("core_cohort/actions",["exports","core/event_dispatcher","core/notification","core/pending","core/prefetch","core/str","core/toast","core_cohort/repository","core_reportbuilder/local/events","core_reportbuilder/local/selectors","core/local/inplace_editable/events"],(function(_exports,_event_dispatcher,_notification,_pending,_prefetch,_str,_toast,_repository,reportEvents,reportSelectors,_events2){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Cohorts actions.
*
* @module core_cohort/actions
* @copyright 2024 David Woloszyn <david.woloszyn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.registerEventListeners=_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const SELECTORS_CHECKBOXES='[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',SELECTORS_DELETEBUTTON='[data-action="cohort-delete-selected"]',SELECTORS_EDITNAME='[data-itemtype="cohortname"]';_exports.init=()=>{(0,_prefetch.prefetchStrings)("core_cohort",["delcohortsconfirm"]),(0,_prefetch.prefetchStrings)("core",["delete","deleteselected","selectitem"]),registerEventListeners()};const registerEventListeners=()=>{document.addEventListener(_events2.eventTypes.elementUpdated,(async event=>{if(event.target.closest(SELECTORS_EDITNAME)){const cohortId=event.target.dataset.itemid,checkbox=document.querySelector('input[value="'.concat(cohortId,'"][type="checkbox"]')),label=document.querySelector('label[for="'.concat(checkbox.id,'"]'));label&&(label.innerHTML=await(0,_str.getString)("selectitem","core",event.target.dataset.value))}})),document.addEventListener("click",(event=>{const cohortDeleteSelected=event.target.closest(SELECTORS_DELETEBUTTON);if(cohortDeleteSelected){event.preventDefault();const reportElement=document.querySelector(reportSelectors.regions.report),cohortDeleteChecked=reportElement.querySelectorAll(SELECTORS_CHECKBOXES);if(0===cohortDeleteChecked.length)return;_notification.default.saveCancelPromise((0,_str.getString)("deleteselected","core"),(0,_str.getString)("delcohortsconfirm","core_cohort"),(0,_str.getString)("delete","core"),{triggerElement:cohortDeleteSelected}).then((()=>{const pendingPromise=new _pending.default("core_cohort/cohorts:delete"),deleteCohortIds=[...cohortDeleteChecked].map((check=>check.value));return(0,_repository.deleteCohorts)(deleteCohortIds).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}}))};_exports.registerEventListeners=registerEventListeners}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.registerEventListeners=_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const SELECTORS_CHECKBOXES='[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',SELECTORS_DELETE='[data-action="cohort-delete"]',SELECTORS_DELETEBUTTON='[data-action="cohort-delete-selected"]',SELECTORS_EDITNAME='[data-itemtype="cohortname"]';_exports.init=()=>{(0,_prefetch.prefetchStrings)("core_cohort",["delcohortsconfirm","delcohortssuccess","delconfirm","delsuccess"]),(0,_prefetch.prefetchStrings)("core",["delete","deleteselected","selectitem"]),registerEventListeners()};const registerEventListeners=()=>{document.addEventListener(_events2.eventTypes.elementUpdated,(async event=>{if(event.target.closest(SELECTORS_EDITNAME)){const cohortId=event.target.dataset.itemid,checkbox=document.querySelector('input[value="'.concat(cohortId,'"][type="checkbox"]')),label=document.querySelector('label[for="'.concat(checkbox.id,'"]'));label&&(label.innerHTML=await(0,_str.getString)("selectitem","core",event.target.dataset.value))}})),document.addEventListener("click",(event=>{const cohortDeleteSingle=event.target.closest(SELECTORS_DELETE);if(cohortDeleteSingle){event.preventDefault();const{cohortId:cohortId,cohortName:cohortName}=cohortDeleteSingle.dataset;_notification.default.saveCancelPromise((0,_str.getString)("deleteselected","core"),(0,_str.getString)("delconfirm","core_cohort",cohortName),(0,_str.getString)("delete","core"),{triggerElement:cohortDeleteSingle}).then((()=>{const pendingPromise=new _pending.default("core_cohort/cohort:delete"),reportElement=event.target.closest(reportSelectors.regions.report);return(0,_repository.deleteCohort)(cohortId).then((()=>(0,_toast.add)((0,_str.getString)("delsuccess","core_cohort")))).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}const cohortDeleteMultiple=event.target.closest(SELECTORS_DELETEBUTTON);if(cohortDeleteMultiple){event.preventDefault();const reportElement=document.querySelector(reportSelectors.regions.report),cohortDeleteChecked=reportElement.querySelectorAll(SELECTORS_CHECKBOXES);if(0===cohortDeleteChecked.length)return;_notification.default.saveCancelPromise((0,_str.getString)("deleteselected","core"),(0,_str.getString)("delcohortsconfirm","core_cohort"),(0,_str.getString)("delete","core"),{triggerElement:cohortDeleteMultiple}).then((()=>{const pendingPromise=new _pending.default("core_cohort/cohorts:delete"),deleteCohortIds=[...cohortDeleteChecked].map((check=>check.value));return(0,_repository.deleteCohorts)(deleteCohortIds).then((()=>(0,_toast.add)((0,_str.getString)("delcohortssuccess","core_cohort")))).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}}))};_exports.registerEventListeners=registerEventListeners}));
//# sourceMappingURL=actions.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,6 @@ define("core_cohort/repository",["exports","core/ajax"],(function(_exports,_ajax
* @module core_cohort/repository
* @copyright 2024 David Woloszyn <david.woloszyn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.deleteCohorts=_exports.deleteCohort=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteCohort=cohort=>deleteCohorts([cohort]);const deleteCohorts=cohorts=>{const request={methodname:"core_cohort_delete_cohorts",args:{cohortids:cohorts}};return _ajax.default.call([request])[0]};_exports.deleteCohorts=deleteCohorts}));
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.deleteCohorts=_exports.deleteCohort=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteCohort=cohortid=>deleteCohorts([cohortid]);const deleteCohorts=cohortids=>{const request={methodname:"core_cohort_delete_cohorts",args:{cohortids:cohortids}};return _ajax.default.call([request])[0]};_exports.deleteCohorts=deleteCohorts}));
//# sourceMappingURL=repository.min.js.map

View File

@ -1 +1 @@
{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle cohort AJAX requests.\n *\n * @module core_cohort/repository\n * @copyright 2024 David Woloszyn <david.woloszyn@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete single cohort.\n *\n * @param {Number} cohort Cohort ID\n * @return {Promise}\n */\nexport const deleteCohort = cohort => deleteCohorts([cohort]);\n\n/**\n * Delete multiple cohorts.\n *\n * @param {Number[]} cohorts Cohort IDs\n * @return {Promise}\n */\nexport const deleteCohorts = cohorts => {\n const request = {\n methodname: 'core_cohort_delete_cohorts',\n args: {cohortids: cohorts}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["cohort","deleteCohorts","cohorts","request","methodname","args","cohortids","Ajax","call"],"mappings":";;;;;;;2LA+B4BA,QAAUC,cAAc,CAACD,eAQxCC,cAAgBC,gBACnBC,QAAU,CACZC,WAAY,6BACZC,KAAM,CAACC,UAAWJ,iBAGfK,cAAKC,KAAK,CAACL,UAAU"}
{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Module to handle cohort AJAX requests.\n *\n * @module core_cohort/repository\n * @copyright 2024 David Woloszyn <david.woloszyn@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete single cohort.\n *\n * @param {Number} cohortid\n * @return {Promise}\n */\nexport const deleteCohort = cohortid => deleteCohorts([cohortid]);\n\n/**\n * Delete multiple cohorts.\n *\n * @param {Number[]} cohortids\n * @return {Promise}\n */\nexport const deleteCohorts = cohortids => {\n const request = {\n methodname: 'core_cohort_delete_cohorts',\n args: {cohortids},\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["cohortid","deleteCohorts","cohortids","request","methodname","args","Ajax","call"],"mappings":";;;;;;;2LA+B4BA,UAAYC,cAAc,CAACD,iBAQ1CC,cAAgBC,kBACnBC,QAAU,CACZC,WAAY,6BACZC,KAAM,CAACH,UAAAA,mBAGJI,cAAKC,KAAK,CAACJ,UAAU"}

View File

@ -26,13 +26,15 @@ import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {getString} from 'core/str';
import {deleteCohorts} from 'core_cohort/repository';
import {add as addToast} from 'core/toast';
import {deleteCohort, deleteCohorts} from 'core_cohort/repository';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {eventTypes} from 'core/local/inplace_editable/events';
const SELECTORS = {
CHECKBOXES: '[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',
DELETE: '[data-action="cohort-delete"]',
DELETEBUTTON: '[data-action="cohort-delete-selected"]',
EDITNAME: '[data-itemtype="cohortname"]',
};
@ -44,6 +46,9 @@ export const init = () => {
prefetchStrings('core_cohort', [
'delcohortsconfirm',
'delcohortssuccess',
'delconfirm',
'delsuccess',
]);
prefetchStrings('core', [
@ -73,10 +78,40 @@ export const registerEventListeners = () => {
}
});
// Delete multiple cohorts.
document.addEventListener('click', event => {
const cohortDeleteSelected = event.target.closest(SELECTORS.DELETEBUTTON);
if (cohortDeleteSelected) {
// Delete single cohort.
const cohortDeleteSingle = event.target.closest(SELECTORS.DELETE);
if (cohortDeleteSingle) {
event.preventDefault();
const {cohortId, cohortName} = cohortDeleteSingle.dataset;
Notification.saveCancelPromise(
getString('deleteselected', 'core'),
getString('delconfirm', 'core_cohort', cohortName),
getString('delete', 'core'),
{triggerElement: cohortDeleteSingle}
).then(() => {
const pendingPromise = new Pending('core_cohort/cohort:delete');
const reportElement = event.target.closest(reportSelectors.regions.report);
// eslint-disable-next-line promise/no-nesting
return deleteCohort(cohortId)
.then(() => addToast(getString('delsuccess', 'core_cohort')))
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
// Delete multiple cohorts.
const cohortDeleteMultiple = event.target.closest(SELECTORS.DELETEBUTTON);
if (cohortDeleteMultiple) {
event.preventDefault();
const reportElement = document.querySelector(reportSelectors.regions.report);
@ -89,13 +124,14 @@ export const registerEventListeners = () => {
getString('deleteselected', 'core'),
getString('delcohortsconfirm', 'core_cohort'),
getString('delete', 'core'),
{triggerElement: cohortDeleteSelected}
{triggerElement: cohortDeleteMultiple}
).then(() => {
const pendingPromise = new Pending('core_cohort/cohorts:delete');
const deleteCohortIds = [...cohortDeleteChecked].map(check => check.value);
// eslint-disable-next-line promise/no-nesting
return deleteCohorts(deleteCohortIds)
.then(() => addToast(getString('delcohortssuccess', 'core_cohort')))
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();

View File

@ -26,21 +26,21 @@ import Ajax from 'core/ajax';
/**
* Delete single cohort.
*
* @param {Number} cohort Cohort ID
* @param {Number} cohortid
* @return {Promise}
*/
export const deleteCohort = cohort => deleteCohorts([cohort]);
export const deleteCohort = cohortid => deleteCohorts([cohortid]);
/**
* Delete multiple cohorts.
*
* @param {Number[]} cohorts Cohort IDs
* @param {Number[]} cohortids
* @return {Promise}
*/
export const deleteCohorts = cohorts => {
export const deleteCohorts = cohortids => {
const request = {
methodname: 'core_cohort_delete_cohorts',
args: {cohortids: cohorts}
args: {cohortids},
};
return Ajax.call([request])[0];

View File

@ -245,9 +245,9 @@ class cohorts extends system_report {
// Delete action. It will be only shown if user has 'moodle/cohort:manage' capabillity.
$this->add_action((new action(
new moodle_url('/cohort/edit.php', ['id' => ':id', 'delete' => 1, 'returnurl' => $returnurl]),
new moodle_url('#'),
new pix_icon('t/delete', '', 'core'),
['class' => 'text-danger'],
['class' => 'text-danger', 'data-action' => 'cohort-delete', 'data-cohort-id' => ':id', 'data-cohort-name' => ':name'],
false,
new lang_string('delete')
))->add_callback(function(stdClass $row): bool {

View File

@ -29,10 +29,8 @@ require_once($CFG->dirroot.'/cohort/edit_form.php');
$id = optional_param('id', 0, PARAM_INT);
$contextid = optional_param('contextid', 0, PARAM_INT);
$delete = optional_param('delete', 0, PARAM_BOOL);
$show = optional_param('show', 0, PARAM_BOOL);
$hide = optional_param('hide', 0, PARAM_BOOL);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$returnurl = optional_param('returnurl', '', PARAM_LOCALURL);
require_login();
@ -86,25 +84,6 @@ if ($context->contextlevel == CONTEXT_COURSECAT) {
$PAGE->set_heading($COURSE->fullname);
}
if ($delete and $cohort->id) {
$PAGE->url->param('delete', 1);
if ($confirm and confirm_sesskey()) {
cohort_delete_cohort($cohort);
redirect($returnurl);
}
$strheading = get_string('delcohort', 'cohort');
$PAGE->navbar->add($strheading);
$PAGE->set_title($strheading);
echo $OUTPUT->header();
echo $OUTPUT->heading($strheading);
$yesurl = new moodle_url('/cohort/edit.php', array('id' => $cohort->id, 'delete' => 1,
'confirm' => 1, 'sesskey' => sesskey(), 'returnurl' => $returnurl->out_as_local_url()));
$message = get_string('delconfirm', 'cohort', format_string($cohort->name));
echo $OUTPUT->confirm($message, $yesurl, $returnurl);
echo $OUTPUT->footer();
die;
}
if ($show && $cohort->id && confirm_sesskey()) {
if (!$cohort->visible) {
$record = (object)array('id' => $cohort->id, 'visible' => 1, 'contextid' => $cohort->contextid);

View File

@ -1,6 +1,6 @@
@core @core_cohort
Feature: Delete cohorts
In order to delete multiple cohorts
In order to delete cohorts
As an admin
I need to select specific cohorts and perform that action
@ -12,17 +12,37 @@ Feature: Delete cohorts
| Cohort 3 | cohort3 | System | | About cohort 3 |
@javascript
Scenario: I can delete multiple cohorts using the checkboxes
Scenario: Delete single cohort
Given I log in as "admin"
And I navigate to "Users > Accounts > Cohorts" in site administration
And I should see "Cohort 1"
And I should see "Cohort 2"
And I should see "Cohort 3"
And I click on "Select 'Cohort 1'" "checkbox"
And I click on "Select 'Cohort 2'" "checkbox"
When I click on "Delete selected" "button"
Then I should see "Do you really want to delete the selected cohorts?"
And the following should exist in the "Cohorts" table:
| Name | Cohort ID |
| Cohort 1 | cohort1 |
| Cohort 2 | cohort2 |
| Cohort 3 | cohort3 |
When I press "Delete" action in the "Cohort 1" report row
Then I should see "Do you really want to delete cohort 'Cohort 1'?" in the "Delete selected" "dialogue"
And I click on "Delete" "button" in the "Delete selected" "dialogue"
And I should not see "Cohort 1"
And I should not see "Cohort 2"
And I should see "Cohort 3"
And I should see "Deleted cohort"
And I should not see "Cohort 1" in the "Cohorts" "table"
And I should see "Cohort 2" in the "Cohorts" "table"
And I should see "Cohort 3" in the "Cohorts" "table"
@javascript
Scenario: Delete multiple cohorts
Given I log in as "admin"
And I navigate to "Users > Accounts > Cohorts" in site administration
And the following should exist in the "Cohorts" table:
| Name | Cohort ID |
| Cohort 1 | cohort1 |
| Cohort 2 | cohort2 |
| Cohort 3 | cohort3 |
When I click on "Select 'Cohort 1'" "checkbox"
And I click on "Select 'Cohort 2'" "checkbox"
And I click on "Delete selected" "button"
Then I should see "Do you really want to delete the selected cohorts?" in the "Delete selected" "dialogue"
And I click on "Delete" "button" in the "Delete selected" "dialogue"
And I should see "Deleted selected cohorts"
And I should not see "Cohort 1" in the "Cohorts" "table"
And I should not see "Cohort 2" in the "Cohorts" "table"
And I should see "Cohort 3" in the "Cohorts" "table"

View File

@ -48,7 +48,9 @@ $string['currentusersmatching'] = 'Current users matching';
$string['defaultcontext'] = 'Default context';
$string['delcohort'] = 'Delete cohort';
$string['delcohortsconfirm'] = 'Do you really want to delete the selected cohorts?';
$string['delcohortssuccess'] = 'Deleted selected cohorts';
$string['delconfirm'] = 'Do you really want to delete cohort \'{$a}\'?';
$string['delsuccess'] = 'Deleted cohort';
$string['description'] = 'Description';
$string['displayedrows'] = '{$a->displayed} rows displayed out of {$a->total}.';
$string['duplicateidnumber'] = 'Cohort with the same ID number already exists';