From 642059155c3972877868a2ac37da5f503ebd64ea Mon Sep 17 00:00:00 2001 From: Jun Pataleta Date: Tue, 23 Mar 2021 20:13:22 +0800 Subject: [PATCH] MDL-70821 course: Create manualCompletionToggled event Add a new "manualCompletionToggled" course event and dispatch this when the manual completion state for an activity is toggled. --- course/amd/build/events.min.js | 2 +- course/amd/build/events.min.js.map | 2 +- course/amd/build/manual_completion_toggle.min.js | 2 +- .../build/manual_completion_toggle.min.js.map | 2 +- course/amd/src/events.js | 11 +++++------ course/amd/src/manual_completion_toggle.js | 16 +++++++++++++++- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/course/amd/build/events.min.js b/course/amd/build/events.min.js index 1613e4265ba..f9dac2e1512 100644 --- a/course/amd/build/events.min.js +++ b/course/amd/build/events.min.js @@ -1,2 +1,2 @@ -define ("core_course/events",[],function(){return{favourited:"core_course:favourited",unfavorited:"core_course:unfavorited"}}); +define ("core_course/events",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={favourited:"core_course:favourited",unfavorited:"core_course:unfavorited",manualCompletionToggled:"core_course:manualcompletiontoggled"};return a.default}); //# sourceMappingURL=events.min.js.map diff --git a/course/amd/build/events.min.js.map b/course/amd/build/events.min.js.map index e451fda7f3b..045bcbe5eaa 100644 --- a/course/amd/build/events.min.js.map +++ b/course/amd/build/events.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/events.js"],"names":["define","favourited","unfavorited"],"mappings":"AAuBAA,OAAM,sBAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,UAAU,CAAE,wBADT,CAEHC,WAAW,CAAE,yBAFV,CAIV,CALK,CAAN","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 * Contain the events the course component can trigger.\n *\n * @module core_course/events\n * @package core_course\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n favourited: 'core_course:favourited',\n unfavorited: 'core_course:unfavorited',\n };\n});"],"file":"events.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/events.js"],"names":["favourited","unfavorited","manualCompletionToggled"],"mappings":"8IAuBe,CACXA,UAAU,CAAE,wBADD,CAEXC,WAAW,CAAE,yBAFF,CAGXC,uBAAuB,CAAE,qCAHd,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 * Contain the events the course component can trigger.\n *\n * @module core_course/events\n * @package core_course\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n favourited: 'core_course:favourited',\n unfavorited: 'core_course:unfavorited',\n manualCompletionToggled: 'core_course:manualcompletiontoggled',\n};\n"],"file":"events.min.js"} \ No newline at end of file diff --git a/course/amd/build/manual_completion_toggle.min.js b/course/amd/build/manual_completion_toggle.min.js index 5f6ef966684..0bd933bdf6b 100644 --- a/course/amd/build/manual_completion_toggle.min.js +++ b/course/amd/build/manual_completion_toggle.min.js @@ -1,2 +1,2 @@ -define ("core_course/manual_completion_toggle",["exports","core/templates","core/notification","core_course/repository"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=e(b);c=e(c);function e(a){return a&&a.__esModule?a:{default:a}}function f(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function g(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function g(a){f(i,d,e,g,h,"next",a)}function h(a){f(i,d,e,g,h,"throw",a)}g(void 0)})}}var h={MANUAL_TOGGLE:"button[data-action=toggle-manual-completion]"},i={TOGGLE_MARK_DONE:"manual:mark-done",TOGGLE_UNDO:"manual:undo"},j=!1,k=function(){if(j){return}document.addEventListener("click",function(a){var b=a.target.closest(h.MANUAL_TOGGLE);if(b){a.preventDefault();l(b).catch(c.default.exception)}});j=!0};a.init=k;var l=function(){var a=g(regeneratorRuntime.mark(function a(e){var f,g,h,j,k,l,m,n;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:f=e.innerHTML;e.setAttribute("disabled","disabled");g=e.getAttribute("data-toggletype");h=e.getAttribute("data-cmid");j=e.getAttribute("data-activityname");k=g===i.TOGGLE_MARK_DONE;a.next=8;return b.default.render("core/loading",{});case 8:l=a.sent;a.next=11;return b.default.replaceNodeContents(e,l,"");case 11:a.prev=11;a.next=14;return(0,d.toggleManualCompletion)(h,k);case 14:m={cmid:h,activityname:j,overallcomplete:k,overallincomplete:!k,istrackeduser:!0};a.next=17;return b.default.renderForPromise("core_course/completion_manual",m);case 17:n=a.sent;a.next=20;return b.default.replaceNode(e,n.html,n.js);case 20:a.next=27;break;case 22:a.prev=22;a.t0=a["catch"](11);e.removeAttribute("disabled");e.innerHTML=f;c.default.exception(a.t0);case 27:case"end":return a.stop();}}},a,null,[[11,22]])}));return function(){return a.apply(this,arguments)}}()}); +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_course/manual_completion_toggle",["exports","core/templates","core/notification","core_course/repository","core_course/events"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=h(b);c=h(c);e=g(e);function f(){if("function"!=typeof WeakMap)return null;var a=new WeakMap;f=function(){return a};return a}function g(a){if(a&&a.__esModule){return a}if(null===a||"object"!==_typeof(a)&&"function"!=typeof a){return{default:a}}var b=f();if(b&&b.has(a)){return b.get(a)}var c={},d=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var e in a){if(Object.prototype.hasOwnProperty.call(a,e)){var g=d?Object.getOwnPropertyDescriptor(a,e):null;if(g&&(g.get||g.set)){Object.defineProperty(c,e,g)}else{c[e]=a[e]}}}c.default=a;if(b){b.set(a,c)}return c}function h(a){return a&&a.__esModule?a:{default:a}}function i(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function j(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){i(h,d,e,f,g,"next",a)}function g(a){i(h,d,e,f,g,"throw",a)}f(void 0)})}}var k={MANUAL_TOGGLE:"button[data-action=toggle-manual-completion]"},l={TOGGLE_MARK_DONE:"manual:mark-done",TOGGLE_UNDO:"manual:undo"},m=!1,n=function(){if(m){return}document.addEventListener("click",function(a){var b=a.target.closest(k.MANUAL_TOGGLE);if(b){a.preventDefault();o(b).catch(c.default.exception)}});m=!0};a.init=n;var o=function(){var a=j(regeneratorRuntime.mark(function a(f){var g,h,i,j,k,m,n,o,p,q,r;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:g=f.innerHTML;f.setAttribute("disabled","disabled");h=f.getAttribute("data-toggletype");i=f.getAttribute("data-cmid");j=f.getAttribute("data-activityname");k=h===l.TOGGLE_MARK_DONE;a.next=8;return b.default.render("core/loading",{});case 8:m=a.sent;a.next=11;return b.default.replaceNodeContents(f,m,"");case 11:a.prev=11;a.next=14;return(0,d.toggleManualCompletion)(i,k);case 14:n={cmid:i,activityname:j,overallcomplete:k,overallincomplete:!k,istrackeduser:!0};a.next=17;return b.default.renderForPromise("core_course/completion_manual",n);case 17:o=a.sent;a.next=20;return b.default.replaceNode(f,o.html,o.js);case 20:p=a.sent;q=p.pop();r=new CustomEvent(e.manualCompletionToggled,{bubbles:!0,detail:{cmid:i,activityname:j,completed:k}});q.dispatchEvent(r);a.next=31;break;case 26:a.prev=26;a.t0=a["catch"](11);f.removeAttribute("disabled");f.innerHTML=g;c.default.exception(a.t0);case 31:case"end":return a.stop();}}},a,null,[[11,26]])}));return function(){return a.apply(this,arguments)}}()}); //# sourceMappingURL=manual_completion_toggle.min.js.map diff --git a/course/amd/build/manual_completion_toggle.min.js.map b/course/amd/build/manual_completion_toggle.min.js.map index e0720d18796..a82ad987a34 100644 --- a/course/amd/build/manual_completion_toggle.min.js.map +++ b/course/amd/build/manual_completion_toggle.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/manual_completion_toggle.js"],"names":["SELECTORS","MANUAL_TOGGLE","TOGGLE_TYPES","TOGGLE_MARK_DONE","TOGGLE_UNDO","registered","init","document","addEventListener","e","toggleButton","target","closest","preventDefault","toggleManualCompletionState","catch","Notification","exception","originalInnerHtml","innerHTML","setAttribute","toggleType","getAttribute","cmid","activityname","completed","Templates","render","loadingHtml","replaceNodeContents","templateContext","overallcomplete","overallincomplete","istrackeduser","renderForPromise","renderObject","replaceNode","html","js","removeAttribute"],"mappings":"uNAyBA,OACA,O,qXAQMA,CAAAA,CAAS,CAAG,CACdC,aAAa,CAAE,8CADD,C,CASZC,CAAY,CAAG,CACjBC,gBAAgB,CAAE,kBADD,CAEjBC,WAAW,CAAE,aAFI,C,CAUjBC,CAAU,G,CAKDC,CAAI,CAAG,UAAM,CACtB,GAAID,CAAJ,CAAgB,CACZ,MACH,CACDE,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAACC,CAAD,CAAO,CACtC,GAAMC,CAAAA,CAAY,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBZ,CAAS,CAACC,aAA3B,CAArB,CACA,GAAIS,CAAJ,CAAkB,CACdD,CAAC,CAACI,cAAF,GACAC,CAA2B,CAACJ,CAAD,CAA3B,CAA0CK,KAA1C,CAAgDC,UAAaC,SAA7D,CACH,CACJ,CAND,EAOAZ,CAAU,GACb,C,UAQD,GAAMS,CAAAA,CAA2B,4CAAG,WAAMJ,CAAN,uGAE1BQ,CAF0B,CAENR,CAAY,CAACS,SAFP,CAKhCT,CAAY,CAACU,YAAb,CAA0B,UAA1B,CAAsC,UAAtC,EAGMC,CAR0B,CAQbX,CAAY,CAACY,YAAb,CAA0B,iBAA1B,CARa,CAS1BC,CAT0B,CASnBb,CAAY,CAACY,YAAb,CAA0B,WAA1B,CATmB,CAU1BE,CAV0B,CAUXd,CAAY,CAACY,YAAb,CAA0B,mBAA1B,CAVW,CAY1BG,CAZ0B,CAYdJ,CAAU,GAAKnB,CAAY,CAACC,gBAZd,gBAeNuB,WAAUC,MAAV,CAAiB,cAAjB,CAAiC,EAAjC,CAfM,QAe1BC,CAf0B,wBAgB1BF,WAAUG,mBAAV,CAA8BnB,CAA9B,CAA4CkB,CAA5C,CAAyD,EAAzD,CAhB0B,mCAoBtB,6BAAuBL,CAAvB,CAA6BE,CAA7B,CApBsB,SAuBtBK,CAvBsB,CAuBJ,CACpBP,IAAI,CAAEA,CADc,CAEpBC,YAAY,CAAEA,CAFM,CAGpBO,eAAe,CAAEN,CAHG,CAIpBO,iBAAiB,CAAE,CAACP,CAJA,CAKpBQ,aAAa,GALO,CAvBI,iBA8BDP,WAAUQ,gBAAV,CAA2B,+BAA3B,CAA4DJ,CAA5D,CA9BC,SA8BtBK,CA9BsB,wBAiCtBT,WAAUU,WAAV,CAAsB1B,CAAtB,CAAoCyB,CAAY,CAACE,IAAjD,CAAuDF,CAAY,CAACG,EAApE,CAjCsB,+DAqC5B5B,CAAY,CAAC6B,eAAb,CAA6B,UAA7B,EACA7B,CAAY,CAACS,SAAb,CAAyBD,CAAzB,CAGAF,UAAaC,SAAb,OAzC4B,wDAAH,uD","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 * Provides the functionality for toggling the manual completion state of a course module through\n * the manual completion button.\n *\n * @module core_course/manual_completion_toggle\n * @package core_course\n * @copyright 2021 Jun Pataleta \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport {toggleManualCompletion} from 'core_course/repository';\n\n/**\n * Selectors in the manual completion template.\n *\n * @type {{MANUAL_TOGGLE: string}}\n */\nconst SELECTORS = {\n MANUAL_TOGGLE: 'button[data-action=toggle-manual-completion]',\n};\n\n/**\n * Toggle type values for the data-toggletype attribute in the core_course/completion_manual template.\n *\n * @type {{TOGGLE_UNDO: string, TOGGLE_MARK_DONE: string}}\n */\nconst TOGGLE_TYPES = {\n TOGGLE_MARK_DONE: 'manual:mark-done',\n TOGGLE_UNDO: 'manual:undo',\n};\n\n/**\n * Whether the event listener has already been registered for this module.\n *\n * @type {boolean}\n */\nlet registered = false;\n\n/**\n * Registers the click event listener for the manual completion toggle button.\n */\nexport const init = () => {\n if (registered) {\n return;\n }\n document.addEventListener('click', (e) => {\n const toggleButton = e.target.closest(SELECTORS.MANUAL_TOGGLE);\n if (toggleButton) {\n e.preventDefault();\n toggleManualCompletionState(toggleButton).catch(Notification.exception);\n }\n });\n registered = true;\n};\n\n/**\n * Toggles the manual completion state of the module for the given user.\n *\n * @param {HTMLElement} toggleButton\n * @returns {Promise}\n */\nconst toggleManualCompletionState = async(toggleButton) => {\n // Make a copy of the original content of the button.\n const originalInnerHtml = toggleButton.innerHTML;\n\n // Disable the button to prevent double clicks.\n toggleButton.setAttribute('disabled', 'disabled');\n\n // Get button data.\n const toggleType = toggleButton.getAttribute('data-toggletype');\n const cmid = toggleButton.getAttribute('data-cmid');\n const activityname = toggleButton.getAttribute('data-activityname');\n // Get the target completion state.\n const completed = toggleType === TOGGLE_TYPES.TOGGLE_MARK_DONE;\n\n // Replace the button contents with the loading icon.\n const loadingHtml = await Templates.render('core/loading', {});\n await Templates.replaceNodeContents(toggleButton, loadingHtml, '');\n\n try {\n // Call the webservice to update the manual completion status.\n await toggleManualCompletion(cmid, completed);\n\n // All good so far. Refresh the manual completion button to reflect its new state by re-rendering the template.\n const templateContext = {\n cmid: cmid,\n activityname: activityname,\n overallcomplete: completed,\n overallincomplete: !completed,\n istrackeduser: true, // We know that we're tracking completion for this user given the presence of this button.\n };\n const renderObject = await Templates.renderForPromise('core_course/completion_manual', templateContext);\n\n // Replace the toggle button with the newly loaded template.\n await Templates.replaceNode(toggleButton, renderObject.html, renderObject.js);\n\n } catch (exception) {\n // In case of an error, revert the original state and appearance of the button.\n toggleButton.removeAttribute('disabled');\n toggleButton.innerHTML = originalInnerHtml;\n\n // Show the exception.\n Notification.exception(exception);\n }\n};\n"],"file":"manual_completion_toggle.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/manual_completion_toggle.js"],"names":["SELECTORS","MANUAL_TOGGLE","TOGGLE_TYPES","TOGGLE_MARK_DONE","TOGGLE_UNDO","registered","init","document","addEventListener","e","toggleButton","target","closest","preventDefault","toggleManualCompletionState","catch","Notification","exception","originalInnerHtml","innerHTML","setAttribute","toggleType","getAttribute","cmid","activityname","completed","Templates","render","loadingHtml","replaceNodeContents","templateContext","overallcomplete","overallincomplete","istrackeduser","renderForPromise","renderObject","replaceNode","html","js","replacedNode","newToggleButton","pop","toggledEvent","CustomEvent","CourseEvents","manualCompletionToggled","bubbles","detail","dispatchEvent","removeAttribute"],"mappings":"ihBAyBA,OACA,OAEA,O,25BAOMA,CAAAA,CAAS,CAAG,CACdC,aAAa,CAAE,8CADD,C,CASZC,CAAY,CAAG,CACjBC,gBAAgB,CAAE,kBADD,CAEjBC,WAAW,CAAE,aAFI,C,CAUjBC,CAAU,G,CAKDC,CAAI,CAAG,UAAM,CACtB,GAAID,CAAJ,CAAgB,CACZ,MACH,CACDE,QAAQ,CAACC,gBAAT,CAA0B,OAA1B,CAAmC,SAACC,CAAD,CAAO,CACtC,GAAMC,CAAAA,CAAY,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBZ,CAAS,CAACC,aAA3B,CAArB,CACA,GAAIS,CAAJ,CAAkB,CACdD,CAAC,CAACI,cAAF,GACAC,CAA2B,CAACJ,CAAD,CAA3B,CAA0CK,KAA1C,CAAgDC,UAAaC,SAA7D,CACH,CACJ,CAND,EAOAZ,CAAU,GACb,C,UAQD,GAAMS,CAAAA,CAA2B,4CAAG,WAAMJ,CAAN,6GAE1BQ,CAF0B,CAENR,CAAY,CAACS,SAFP,CAKhCT,CAAY,CAACU,YAAb,CAA0B,UAA1B,CAAsC,UAAtC,EAGMC,CAR0B,CAQbX,CAAY,CAACY,YAAb,CAA0B,iBAA1B,CARa,CAS1BC,CAT0B,CASnBb,CAAY,CAACY,YAAb,CAA0B,WAA1B,CATmB,CAU1BE,CAV0B,CAUXd,CAAY,CAACY,YAAb,CAA0B,mBAA1B,CAVW,CAY1BG,CAZ0B,CAYdJ,CAAU,GAAKnB,CAAY,CAACC,gBAZd,gBAeNuB,WAAUC,MAAV,CAAiB,cAAjB,CAAiC,EAAjC,CAfM,QAe1BC,CAf0B,wBAgB1BF,WAAUG,mBAAV,CAA8BnB,CAA9B,CAA4CkB,CAA5C,CAAyD,EAAzD,CAhB0B,mCAoBtB,6BAAuBL,CAAvB,CAA6BE,CAA7B,CApBsB,SAuBtBK,CAvBsB,CAuBJ,CACpBP,IAAI,CAAEA,CADc,CAEpBC,YAAY,CAAEA,CAFM,CAGpBO,eAAe,CAAEN,CAHG,CAIpBO,iBAAiB,CAAE,CAACP,CAJA,CAKpBQ,aAAa,GALO,CAvBI,iBA8BDP,WAAUQ,gBAAV,CAA2B,+BAA3B,CAA4DJ,CAA5D,CA9BC,SA8BtBK,CA9BsB,wBAiCDT,WAAUU,WAAV,CAAsB1B,CAAtB,CAAoCyB,CAAY,CAACE,IAAjD,CAAuDF,CAAY,CAACG,EAApE,CAjCC,SAiCtBC,CAjCsB,QAkCtBC,CAlCsB,CAkCJD,CAAY,CAACE,GAAb,EAlCI,CAqCtBC,CArCsB,CAqCP,GAAIC,CAAAA,WAAJ,CAAgBC,CAAY,CAACC,uBAA7B,CAAsD,CACvEC,OAAO,GADgE,CAEvEC,MAAM,CAAE,CACJxB,IAAI,CAAJA,CADI,CAEJC,YAAY,CAAZA,CAFI,CAGJC,SAAS,CAATA,CAHI,CAF+D,CAAtD,CArCO,CA8C5Be,CAAe,CAACQ,aAAhB,CAA8BN,CAA9B,EA9C4B,sDAkD5BhC,CAAY,CAACuC,eAAb,CAA6B,UAA7B,EACAvC,CAAY,CAACS,SAAb,CAAyBD,CAAzB,CAGAF,UAAaC,SAAb,OAtD4B,wDAAH,uD","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 * Provides the functionality for toggling the manual completion state of a course module through\n * the manual completion button.\n *\n * @module core_course/manual_completion_toggle\n * @package core_course\n * @copyright 2021 Jun Pataleta \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport {toggleManualCompletion} from 'core_course/repository';\nimport * as CourseEvents from 'core_course/events';\n\n/**\n * Selectors in the manual completion template.\n *\n * @type {{MANUAL_TOGGLE: string}}\n */\nconst SELECTORS = {\n MANUAL_TOGGLE: 'button[data-action=toggle-manual-completion]',\n};\n\n/**\n * Toggle type values for the data-toggletype attribute in the core_course/completion_manual template.\n *\n * @type {{TOGGLE_UNDO: string, TOGGLE_MARK_DONE: string}}\n */\nconst TOGGLE_TYPES = {\n TOGGLE_MARK_DONE: 'manual:mark-done',\n TOGGLE_UNDO: 'manual:undo',\n};\n\n/**\n * Whether the event listener has already been registered for this module.\n *\n * @type {boolean}\n */\nlet registered = false;\n\n/**\n * Registers the click event listener for the manual completion toggle button.\n */\nexport const init = () => {\n if (registered) {\n return;\n }\n document.addEventListener('click', (e) => {\n const toggleButton = e.target.closest(SELECTORS.MANUAL_TOGGLE);\n if (toggleButton) {\n e.preventDefault();\n toggleManualCompletionState(toggleButton).catch(Notification.exception);\n }\n });\n registered = true;\n};\n\n/**\n * Toggles the manual completion state of the module for the given user.\n *\n * @param {HTMLElement} toggleButton\n * @returns {Promise}\n */\nconst toggleManualCompletionState = async(toggleButton) => {\n // Make a copy of the original content of the button.\n const originalInnerHtml = toggleButton.innerHTML;\n\n // Disable the button to prevent double clicks.\n toggleButton.setAttribute('disabled', 'disabled');\n\n // Get button data.\n const toggleType = toggleButton.getAttribute('data-toggletype');\n const cmid = toggleButton.getAttribute('data-cmid');\n const activityname = toggleButton.getAttribute('data-activityname');\n // Get the target completion state.\n const completed = toggleType === TOGGLE_TYPES.TOGGLE_MARK_DONE;\n\n // Replace the button contents with the loading icon.\n const loadingHtml = await Templates.render('core/loading', {});\n await Templates.replaceNodeContents(toggleButton, loadingHtml, '');\n\n try {\n // Call the webservice to update the manual completion status.\n await toggleManualCompletion(cmid, completed);\n\n // All good so far. Refresh the manual completion button to reflect its new state by re-rendering the template.\n const templateContext = {\n cmid: cmid,\n activityname: activityname,\n overallcomplete: completed,\n overallincomplete: !completed,\n istrackeduser: true, // We know that we're tracking completion for this user given the presence of this button.\n };\n const renderObject = await Templates.renderForPromise('core_course/completion_manual', templateContext);\n\n // Replace the toggle button with the newly loaded template.\n const replacedNode = await Templates.replaceNode(toggleButton, renderObject.html, renderObject.js);\n const newToggleButton = replacedNode.pop();\n\n // Build manualCompletionToggled custom event.\n const toggledEvent = new CustomEvent(CourseEvents.manualCompletionToggled, {\n bubbles: true,\n detail: {\n cmid,\n activityname,\n completed,\n }\n });\n // Dispatch the manualCompletionToggled custom event.\n newToggleButton.dispatchEvent(toggledEvent);\n\n } catch (exception) {\n // In case of an error, revert the original state and appearance of the button.\n toggleButton.removeAttribute('disabled');\n toggleButton.innerHTML = originalInnerHtml;\n\n // Show the exception.\n Notification.exception(exception);\n }\n};\n"],"file":"manual_completion_toggle.min.js"} \ No newline at end of file diff --git a/course/amd/src/events.js b/course/amd/src/events.js index 7609702c34a..ef9d24ed0ae 100644 --- a/course/amd/src/events.js +++ b/course/amd/src/events.js @@ -21,9 +21,8 @@ * @copyright 2018 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define([], function() { - return { - favourited: 'core_course:favourited', - unfavorited: 'core_course:unfavorited', - }; -}); \ No newline at end of file +export default { + favourited: 'core_course:favourited', + unfavorited: 'core_course:unfavorited', + manualCompletionToggled: 'core_course:manualcompletiontoggled', +}; diff --git a/course/amd/src/manual_completion_toggle.js b/course/amd/src/manual_completion_toggle.js index c14eb9be3a4..4429bee2d75 100644 --- a/course/amd/src/manual_completion_toggle.js +++ b/course/amd/src/manual_completion_toggle.js @@ -26,6 +26,7 @@ import Templates from 'core/templates'; import Notification from 'core/notification'; import {toggleManualCompletion} from 'core_course/repository'; +import * as CourseEvents from 'core_course/events'; /** * Selectors in the manual completion template. @@ -109,7 +110,20 @@ const toggleManualCompletionState = async(toggleButton) => { const renderObject = await Templates.renderForPromise('core_course/completion_manual', templateContext); // Replace the toggle button with the newly loaded template. - await Templates.replaceNode(toggleButton, renderObject.html, renderObject.js); + const replacedNode = await Templates.replaceNode(toggleButton, renderObject.html, renderObject.js); + const newToggleButton = replacedNode.pop(); + + // Build manualCompletionToggled custom event. + const toggledEvent = new CustomEvent(CourseEvents.manualCompletionToggled, { + bubbles: true, + detail: { + cmid, + activityname, + completed, + } + }); + // Dispatch the manualCompletionToggled custom event. + newToggleButton.dispatchEvent(toggledEvent); } catch (exception) { // In case of an error, revert the original state and appearance of the button.