From 6dcb5eb8a576d2d4939e87d9142be5a2192a2334 Mon Sep 17 00:00:00 2001 From: Mathew May Date: Wed, 14 Jul 2021 14:44:25 +0800 Subject: [PATCH] MDL-71963 Core: Add toast for confirmation modal success --- lang/en/block.php | 3 ++- lib/amd/build/confirm.min.js | 2 +- lib/amd/build/confirm.min.js.map | 2 +- lib/amd/src/confirm.js | 11 ++++++++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lang/en/block.php b/lang/en/block.php index 6d545a932f7..6149c601d83 100644 --- a/lang/en/block.php +++ b/lang/en/block.php @@ -42,6 +42,7 @@ $string['deletecheck'] = 'Delete {$a} block?'; $string['deletecheck_modal'] = 'Delete block?'; $string['deleteblock'] = 'Delete {$a} block'; $string['deleteblockcheck'] = 'Are you sure that you want to delete this block titled {$a}?'; +$string['deleteblockinprogress'] = 'Block {$a} is currently being removed from this page'; $string['deleteblockwarning'] = '

You are about to delete a block that appears elsewhere.

Original block location: {$a->location}
Display on page types: {$a->pagetype}

Are you sure you want to continue?

'; $string['hideblock'] = 'Hide {$a} block'; $string['hidepanel'] = 'Hide panel'; @@ -79,4 +80,4 @@ $string['dockblock'] = 'Dock {$a} block'; $string['hidedockpanel'] = 'Hide the dock panel'; $string['undockall'] = 'Undock all'; $string['undockblock'] = 'Undock {$a} block'; -$string['undockitem'] = 'Undock this item'; \ No newline at end of file +$string['undockitem'] = 'Undock this item'; diff --git a/lib/amd/build/confirm.min.js b/lib/amd/build/confirm.min.js index 87ed5fa0fe4..143f0680a57 100644 --- a/lib/amd/build/confirm.min.js +++ b/lib/amd/build/confirm.min.js @@ -1,2 +1,2 @@ -function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/confirm",["core/notification","core/str"],function(a,b){"use strict";b=d(b);function c(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;c=function(){return a};return a}function d(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=c();if(b&&b.has(a)){return b.get(a)}var d={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(d,f,g)}else{d[f]=a[f]}}}d.default=a;if(b){b.set(a,d)}return d}var e=!1,f=function(b,c,d){return new Promise(function(e,f){(0,a.saveCancel)(b,c,d,e,f)})},g=function(a,c){if(a["confirmation".concat(c,"Str")]){return b.get_string.apply(null,JSON.parse(a["confirmation".concat(c,"Str")]))}return a["confirmation".concat(c)]},h=function(){document.addEventListener("click",function(a){var b=a.target.closest("[data-confirmation=\"modal\"]");if(b){a.preventDefault();f(g(b.dataset,"Title"),g(b.dataset,"Question"),g(b.dataset,"YesButton")).then(function(){window.location.href=b.dataset.confirmationDestination}).catch(function(){})}})};if(!e){h();e=!0}}); +function _typeof(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){_typeof=function(a){return typeof a}}else{_typeof=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return _typeof(a)}define ("core/confirm",["core/notification","core/str","core/toast"],function(a,b,c){"use strict";b=e(b);function d(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;d=function(){return a};return a}function e(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=d();if(b&&b.has(a)){return b.get(a)}var c={},e=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var f in a){if(Object.prototype.hasOwnProperty.call(a,f)){var g=e?Object.getOwnPropertyDescriptor(a,f):null;if(g&&(g.get||g.set)){Object.defineProperty(c,f,g)}else{c[f]=a[f]}}}c.default=a;if(b){b.set(a,c)}return c}var f=!1,g=function(b,c,d){return new Promise(function(e,f){(0,a.saveCancel)(b,c,d,e,f)})},h=function(a,c){if(a["confirmation".concat(c,"Str")]){return b.get_string.apply(null,JSON.parse(a["confirmation".concat(c,"Str")]))}return a["confirmation".concat(c)]},i=function(){document.addEventListener("click",function(b){var d=b.target.closest("[data-confirmation=\"modal\"]");if(d){b.preventDefault();g(h(d.dataset,"Title"),h(d.dataset,"Question"),h(d.dataset,"YesButton")).then(function(){if("true"===d.dataset.confirmationToast){var b=h(d.dataset,"ToastConfirmation");if("string"==typeof b){(0,c.add)(b)}else{b.then(function(a){return(0,c.add)(a)}).catch(function(b){return(0,a.exception)(b)})}}window.location.href=d.dataset.confirmationDestination}).catch(function(){})}})};if(!f){i();f=!0}}); //# sourceMappingURL=confirm.min.js.map diff --git a/lib/amd/build/confirm.min.js.map b/lib/amd/build/confirm.min.js.map index 51d05942900..3fc480e4751 100644 --- a/lib/amd/build/confirm.min.js.map +++ b/lib/amd/build/confirm.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/confirm.js"],"names":["registered","confirmedPromise","title","question","saveLabel","Promise","resolve","reject","getConfirmationString","dataset","field","Str","get_string","apply","JSON","parse","registerConfirmationListeners","document","addEventListener","e","confirmRequest","target","closest","preventDefault","then","window","location","href","confirmationDestination","catch"],"mappings":"sXA6CA,O,yiBAGIA,CAAAA,CAAU,G,CAYRC,CAAgB,CAAG,SAACC,CAAD,CAAQC,CAAR,CAAkBC,CAAlB,QAAgC,IAAIC,CAAAA,OAAJ,CAAY,SAACC,CAAD,CAAUC,CAAV,CAAqB,CACtF,iBAAWL,CAAX,CAAkBC,CAAlB,CAA4BC,CAA5B,CAAuCE,CAAvC,CAAgDC,CAAhD,CACH,CAFwD,CAAhC,C,CAcnBC,CAAqB,CAAG,SAACC,CAAD,CAAUC,CAAV,CAAoB,CAC9C,GAAID,CAAO,uBAAgBC,CAAhB,QAAX,CAAwC,CACpC,MAAOC,CAAAA,CAAG,CAACC,UAAJ,CAAeC,KAAf,CAAqB,IAArB,CAA2BC,IAAI,CAACC,KAAL,CAAWN,CAAO,uBAAgBC,CAAhB,QAAlB,CAA3B,CACV,CACD,MAAOD,CAAAA,CAAO,uBAAgBC,CAAhB,EACjB,C,CAQKM,CAA6B,CAAG,UAAM,CACxCC,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAC,CAAI,CACpC,GAAMC,CAAAA,CAAc,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiB,+BAAjB,CAAvB,CACA,GAAIF,CAAJ,CAAoB,CAChBD,CAAC,CAACI,cAAF,GACAtB,CAAgB,CACZO,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,OAAzB,CADT,CAEZD,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,UAAzB,CAFT,CAGZD,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,WAAzB,CAHT,CAAhB,CAKCe,IALD,CAKM,UAAM,CACRC,MAAM,CAACC,QAAP,CAAgBC,IAAhB,CAAuBP,CAAc,CAACX,OAAf,CAAuBmB,uBAEjD,CARD,EAQGC,KARH,CAQS,UAAM,CAAE,CARjB,CASH,CACJ,CAdD,CAeH,C,CAED,GAAI,CAAC7B,CAAL,CAAiB,CACbgB,CAA6B,GAC7BhB,CAAU,GACb,C","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 .\n\n/**\n * Javascript events for the `core_confirm` modal.\n *\n * @module core/confirm\n * @copyright 2021 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n *\n * @example Calling the confirmation modal to delete a block\n *\n * // The following is an example of how to use this module via an indirect PHP call with a button.\n *\n * $controls[] = new action_menu_link_secondary(\n * $deleteactionurl,\n * new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),\n * $str,\n * [\n * 'class' => 'editing_delete',\n * 'data-confirmation' => 'modal', // Needed so this module will pick it up in the click handler.\n * 'data-confirmation-title-str' => json_encode(['deletecheck_modal', 'block']),\n * 'data-confirmation-question-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),\n * 'data-confirmation-yes-button-str' => json_encode(['delete', 'core']),\n * 'data-confirmation-toast' => 'true', // Can be set to inform the user that their action was a success.\n * 'data-confirmation-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),\n * 'data-confirmation-destination' => $deleteconfirmationurl->out(false), // Where do you want to direct the user?\n * ]\n * );\n */\n\nimport {saveCancel} from 'core/notification';\nimport * as Str from 'core/str';\n\n// We want to ensure that we only initialize the listeners only once.\nlet registered = false;\n\n/**\n * Add all of the supplied notifications.\n *\n * @method confirmedPromise\n * @protected\n * @param {Promise|String} title The header of the modal\n * @param {Promise|String} question What do we want the user to confirm\n * @param {Promise|String} saveLabel The modal action link text\n * @return {Promise}\n */\nconst confirmedPromise = (title, question, saveLabel) => new Promise((resolve, reject) => {\n saveCancel(title, question, saveLabel, resolve, reject);\n});\n\n/**\n * Either fetch the string or return it from the dom node.\n *\n * @method getConfirmationString\n * @private\n * @param {HTMLElement} dataset The page element to fetch dataset items in\n * @param {String} field The dataset field name to fetch the contents of\n * @return {Promise|String}\n *\n */\nconst getConfirmationString = (dataset, field) => {\n if (dataset[`confirmation${field}Str`]) {\n return Str.get_string.apply(null, JSON.parse(dataset[`confirmation${field}Str`]));\n }\n return dataset[`confirmation${field}`];\n};\n\n/**\n * Set up the listeners for the confirmation modal widget within the page.\n *\n * @method registerConfirmationListeners\n * @private\n */\nconst registerConfirmationListeners = () => {\n document.addEventListener('click', e => {\n const confirmRequest = e.target.closest('[data-confirmation=\"modal\"]');\n if (confirmRequest) {\n e.preventDefault();\n confirmedPromise(\n getConfirmationString(confirmRequest.dataset, 'Title'),\n getConfirmationString(confirmRequest.dataset, 'Question'),\n getConfirmationString(confirmRequest.dataset, 'YesButton'),\n )\n .then(() => {\n window.location.href = confirmRequest.dataset.confirmationDestination;\n return;\n }).catch(() => {}); // Catch an empty function as the user cancelled rather than an actual error.\n }\n });\n};\n\nif (!registered) {\n registerConfirmationListeners();\n registered = true;\n}\n"],"file":"confirm.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/confirm.js"],"names":["registered","confirmedPromise","title","question","saveLabel","Promise","resolve","reject","getConfirmationString","dataset","field","Str","get_string","apply","JSON","parse","registerConfirmationListeners","document","addEventListener","e","confirmRequest","target","closest","preventDefault","then","stringForToast","str","catch","window","location","href","confirmationDestination"],"mappings":"qYA6CA,O,yiBAIIA,CAAAA,CAAU,G,CAYRC,CAAgB,CAAG,SAACC,CAAD,CAAQC,CAAR,CAAkBC,CAAlB,QAAgC,IAAIC,CAAAA,OAAJ,CAAY,SAACC,CAAD,CAAUC,CAAV,CAAqB,CACtF,iBAAWL,CAAX,CAAkBC,CAAlB,CAA4BC,CAA5B,CAAuCE,CAAvC,CAAgDC,CAAhD,CACH,CAFwD,CAAhC,C,CAcnBC,CAAqB,CAAG,SAACC,CAAD,CAAUC,CAAV,CAAoB,CAC9C,GAAID,CAAO,uBAAgBC,CAAhB,QAAX,CAAwC,CACpC,MAAOC,CAAAA,CAAG,CAACC,UAAJ,CAAeC,KAAf,CAAqB,IAArB,CAA2BC,IAAI,CAACC,KAAL,CAAWN,CAAO,uBAAgBC,CAAhB,QAAlB,CAA3B,CACV,CACD,MAAOD,CAAAA,CAAO,uBAAgBC,CAAhB,EACjB,C,CAQKM,CAA6B,CAAG,UAAM,CACxCC,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAAAC,CAAC,CAAI,CACpC,GAAMC,CAAAA,CAAc,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiB,+BAAjB,CAAvB,CACA,GAAIF,CAAJ,CAAoB,CAChBD,CAAC,CAACI,cAAF,GACAtB,CAAgB,CACZO,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,OAAzB,CADT,CAEZD,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,UAAzB,CAFT,CAGZD,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,WAAzB,CAHT,CAAhB,CAKCe,IALD,CAKM,UAAM,CACR,GAAoD,MAAhD,GAAAJ,CAAc,CAACX,OAAf,kBAAJ,CAA4D,CACxD,GAAMgB,CAAAA,CAAc,CAAGjB,CAAqB,CAACY,CAAc,CAACX,OAAhB,CAAyB,mBAAzB,CAA5C,CACA,GAA8B,QAA1B,QAAOgB,CAAAA,CAAX,CAAwC,CACpC,UAASA,CAAT,CACH,CAFD,IAEO,CACHA,CAAc,CAACD,IAAf,CAAoB,SAAAE,CAAG,QAAI,UAASA,CAAT,CAAJ,CAAvB,EAA0CC,KAA1C,CAAgD,SAAAR,CAAC,QAAI,gBAAUA,CAAV,CAAJ,CAAjD,CACH,CACJ,CACDS,MAAM,CAACC,QAAP,CAAgBC,IAAhB,CAAuBV,CAAc,CAACX,OAAf,CAAuBsB,uBAEjD,CAhBD,EAgBGJ,KAhBH,CAgBS,UAAM,CAAE,CAhBjB,CAiBH,CACJ,CAtBD,CAuBH,C,CAED,GAAI,CAAC3B,CAAL,CAAiB,CACbgB,CAA6B,GAC7BhB,CAAU,GACb,C","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 .\n\n/**\n * Javascript events for the `core_confirm` modal.\n *\n * @module core/confirm\n * @copyright 2021 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since 4.0\n *\n * @example Calling the confirmation modal to delete a block\n *\n * // The following is an example of how to use this module via an indirect PHP call with a button.\n *\n * $controls[] = new action_menu_link_secondary(\n * $deleteactionurl,\n * new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),\n * $str,\n * [\n * 'class' => 'editing_delete',\n * 'data-confirmation' => 'modal', // Needed so this module will pick it up in the click handler.\n * 'data-confirmation-title-str' => json_encode(['deletecheck_modal', 'block']),\n * 'data-confirmation-question-str' => json_encode(['deleteblockcheck', 'block', $blocktitle]),\n * 'data-confirmation-yes-button-str' => json_encode(['delete', 'core']),\n * 'data-confirmation-toast' => 'true', // Can be set to inform the user that their action was a success.\n * 'data-confirmation-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),\n * 'data-confirmation-destination' => $deleteconfirmationurl->out(false), // Where do you want to direct the user?\n * ]\n * );\n */\n\nimport {saveCancel, exception} from 'core/notification';\nimport * as Str from 'core/str';\nimport {add as addToast} from 'core/toast';\n\n// We want to ensure that we only initialize the listeners only once.\nlet registered = false;\n\n/**\n * Add all of the supplied notifications.\n *\n * @method confirmedPromise\n * @protected\n * @param {Promise|String} title The header of the modal\n * @param {Promise|String} question What do we want the user to confirm\n * @param {Promise|String} saveLabel The modal action link text\n * @return {Promise}\n */\nconst confirmedPromise = (title, question, saveLabel) => new Promise((resolve, reject) => {\n saveCancel(title, question, saveLabel, resolve, reject);\n});\n\n/**\n * Either fetch the string or return it from the dom node.\n *\n * @method getConfirmationString\n * @private\n * @param {HTMLElement} dataset The page element to fetch dataset items in\n * @param {String} field The dataset field name to fetch the contents of\n * @return {Promise|String}\n *\n */\nconst getConfirmationString = (dataset, field) => {\n if (dataset[`confirmation${field}Str`]) {\n return Str.get_string.apply(null, JSON.parse(dataset[`confirmation${field}Str`]));\n }\n return dataset[`confirmation${field}`];\n};\n\n/**\n * Set up the listeners for the confirmation modal widget within the page.\n *\n * @method registerConfirmationListeners\n * @private\n */\nconst registerConfirmationListeners = () => {\n document.addEventListener('click', e => {\n const confirmRequest = e.target.closest('[data-confirmation=\"modal\"]');\n if (confirmRequest) {\n e.preventDefault();\n confirmedPromise(\n getConfirmationString(confirmRequest.dataset, 'Title'),\n getConfirmationString(confirmRequest.dataset, 'Question'),\n getConfirmationString(confirmRequest.dataset, 'YesButton'),\n )\n .then(() => {\n if (confirmRequest.dataset[`confirmationToast`] === 'true') {\n const stringForToast = getConfirmationString(confirmRequest.dataset, 'ToastConfirmation');\n if (typeof stringForToast === \"string\") {\n addToast(stringForToast);\n } else {\n stringForToast.then(str => addToast(str)).catch(e => exception(e));\n }\n }\n window.location.href = confirmRequest.dataset.confirmationDestination;\n return;\n }).catch(() => {}); // Catch an empty function as the user cancelled rather than an actual error.\n }\n });\n};\n\nif (!registered) {\n registerConfirmationListeners();\n registered = true;\n}\n"],"file":"confirm.min.js"} \ No newline at end of file diff --git a/lib/amd/src/confirm.js b/lib/amd/src/confirm.js index 75d69624a82..22d5b935a29 100644 --- a/lib/amd/src/confirm.js +++ b/lib/amd/src/confirm.js @@ -42,8 +42,9 @@ * ); */ -import {saveCancel} from 'core/notification'; +import {saveCancel, exception} from 'core/notification'; import * as Str from 'core/str'; +import {add as addToast} from 'core/toast'; // We want to ensure that we only initialize the listeners only once. let registered = false; @@ -96,6 +97,14 @@ const registerConfirmationListeners = () => { getConfirmationString(confirmRequest.dataset, 'YesButton'), ) .then(() => { + if (confirmRequest.dataset[`confirmationToast`] === 'true') { + const stringForToast = getConfirmationString(confirmRequest.dataset, 'ToastConfirmation'); + if (typeof stringForToast === "string") { + addToast(stringForToast); + } else { + stringForToast.then(str => addToast(str)).catch(e => exception(e)); + } + } window.location.href = confirmRequest.dataset.confirmationDestination; return; }).catch(() => {}); // Catch an empty function as the user cancelled rather than an actual error.