From 9abf7e1a72b3dd3a2c455303c6eedd697941887b Mon Sep 17 00:00:00 2001 From: Ferran Recio Date: Tue, 22 Jun 2021 15:39:16 +0200 Subject: [PATCH] MDL-71727 course: sync dragged elements Two new mutations are added to indicate that a section or a cm is being dragged. The logic related to refresh a section or a cm has been moved to components to simplify the code. --- .../amd/build/local/content/section.min.js | 2 +- .../build/local/content/section.min.js.map | 2 +- .../build/local/content/section/cmitem.min.js | 2 +- .../local/content/section/cmitem.min.js.map | 2 +- .../build/local/courseeditor/dndcmitem.min.js | 2 +- .../local/courseeditor/dndcmitem.min.js.map | 2 +- .../local/courseeditor/dndsection.min.js | 2 +- .../local/courseeditor/dndsection.min.js.map | 2 +- .../local/courseeditor/dndsectionitem.min.js | 2 +- .../courseeditor/dndsectionitem.min.js.map | 2 +- .../build/local/courseeditor/mutations.min.js | 2 +- .../local/courseeditor/mutations.min.js.map | 2 +- .../amd/build/local/courseindex/cm.min.js | 2 +- .../amd/build/local/courseindex/cm.min.js.map | 2 +- .../local/courseindex/courseindex.min.js | 2 +- .../local/courseindex/courseindex.min.js.map | 2 +- .../build/local/courseindex/section.min.js | 2 +- .../local/courseindex/section.min.js.map | 2 +- .../format/amd/src/local/content/section.js | 28 +++++++++++- .../amd/src/local/content/section/cmitem.js | 13 ++++++ .../amd/src/local/courseeditor/dndcmitem.js | 18 ++++++++ .../amd/src/local/courseeditor/dndsection.js | 18 ++++++++ .../src/local/courseeditor/dndsectionitem.js | 18 ++++++++ .../amd/src/local/courseeditor/mutations.js | 33 ++++++++++++++ course/format/amd/src/local/courseindex/cm.js | 21 +++++++++ .../amd/src/local/courseindex/courseindex.js | 43 ------------------- .../amd/src/local/courseindex/section.js | 35 +++++++++++++++ 27 files changed, 201 insertions(+), 62 deletions(-) diff --git a/course/format/amd/build/local/content/section.min.js b/course/format/amd/build/local/content/section.min.js index 7b7a8ee2518..175f41892ea 100644 --- a/course/format/amd/build/local/content/section.min.js +++ b/course/format/amd/build/local/content/section.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/content/section",["exports","core_courseformat/local/content/section/header","core_courseformat/local/courseeditor/dndsection"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function g(a){for(var b=1,c;b.\n\n/**\n * Course section format component.\n *\n * @module core_courseformat/local/content/section\n * @class core_courseformat/local/content/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Header from 'core_courseformat/local/content/section/header';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'content_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_title']`,\n CM: `[data-for=\"cmitem\"]`,\n };\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Section zero and other formats sections may not have a title to drag.\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n if (sectionItem) {\n // Init the inner dragable element.\n const headerComponent = new Header({\n ...this,\n element: sectionItem,\n fullregion: this.element,\n });\n this.configDragDrop(headerComponent);\n }\n }\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n const cms = this.getElements(this.selectors.CM);\n // DndUpload may add extra elements so :last-child selector cannot be used.\n if (!cms || cms.length === 0) {\n return null;\n }\n return cms[cms.length - 1];\n }\n}"],"file":"section.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/content/section.js"],"names":["name","selectors","SECTION_ITEM","CM","classes","id","element","dataset","state","configState","reactive","isEditing","supportComponents","sectionItem","getElement","headerComponent","Header","fullregion","configDragDrop","watch","handler","_refreshSection","cms","getElements","length","classList","toggle","DRAGGING","dragging","DndSection"],"mappings":"gQAwBA,OACA,O,8/EAOa,CAEL,KAAKA,IAAL,CAAY,iBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,YAAY,6BADC,CAEbC,EAAE,wBAFW,CAAjB,CAKA,KAAKC,OAAL,CAAe,EAAf,CAGA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,8CAOUG,C,CAAO,CACd,KAAKC,WAAL,CAAiBD,CAAjB,EAEA,GAAI,KAAKE,QAAL,CAAcC,SAAd,EAA2B,KAAKD,QAAL,CAAcE,iBAA7C,CAAgE,CAE5D,GAAMC,CAAAA,CAAW,CAAG,KAAKC,UAAL,CAAgB,KAAKb,SAAL,CAAeC,YAA/B,CAApB,CACA,GAAIW,CAAJ,CAAiB,CAEb,GAAME,CAAAA,CAAe,CAAG,GAAIC,UAAJ,MACjB,IADiB,EAEpBV,OAAO,CAAEO,CAFW,CAGpBI,UAAU,CAAE,KAAKX,OAHG,GAAxB,CAKA,KAAKY,cAAL,CAAoBH,CAApB,CACH,CACJ,CACJ,C,iDAOa,CACV,MAAO,CACH,CAACI,KAAK,mBAAa,KAAKd,EAAlB,aAAN,CAAuCe,OAAO,CAAE,KAAKC,eAArD,CADG,CAGV,C,6CAOW,CACR,GAAMC,CAAAA,CAAG,CAAG,KAAKC,WAAL,CAAiB,KAAKtB,SAAL,CAAeE,EAAhC,CAAZ,CAEA,GAAI,CAACmB,CAAD,EAAuB,CAAf,GAAAA,CAAG,CAACE,MAAhB,CAA8B,CAC1B,MAAO,KACV,CACD,MAAOF,CAAAA,CAAG,CAACA,CAAG,CAACE,MAAJ,CAAa,CAAd,CACb,C,0DAO0B,OAAVlB,CAAU,GAAVA,OAAU,CAEvB,KAAKA,OAAL,CAAamB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKtB,OAAL,CAAauB,QAA3C,WAAqDrB,CAAO,CAACsB,QAA7D,mBACH,C,cA5EwBC,S","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 * Course section format component.\n *\n * @module core_courseformat/local/content/section\n * @class core_courseformat/local/content/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Header from 'core_courseformat/local/content/section/header';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'content_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_title']`,\n CM: `[data-for=\"cmitem\"]`,\n };\n // All classes will be loaded later by DndCmItem.\n this.classes = {};\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Section zero and other formats sections may not have a title to drag.\n const sectionItem = this.getElement(this.selectors.SECTION_ITEM);\n if (sectionItem) {\n // Init the inner dragable element.\n const headerComponent = new Header({\n ...this,\n element: sectionItem,\n fullregion: this.element,\n });\n this.configDragDrop(headerComponent);\n }\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n const cms = this.getElements(this.selectors.CM);\n // DndUpload may add extra elements so :last-child selector cannot be used.\n if (!cms || cms.length === 0) {\n return null;\n }\n return cms[cms.length - 1];\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshSection({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n }\n}\n"],"file":"section.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/content/section/cmitem.min.js b/course/format/amd/build/local/content/section/cmitem.min.js index 3e2eb525384..bcf7af37a29 100644 --- a/course/format/amd/build/local/content/section/cmitem.min.js +++ b/course/format/amd/build/local/content/section/cmitem.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/content/section/cmitem",["exports","core_courseformat/local/courseeditor/dndcmitem"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Course course module item component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/content/section/cmitem\n * @class core_courseformat/local/content/section/cmitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\n\nexport default class extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'content_section_cmitem';\n // Default query selectors.\n this.selectors = {\n DRAGICON: `.editing_move`,\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n this.configDragDrop(this.id);\n this.getElement(this.selectors.DRAGICON)?.classList.add(this.classes.DRAGICON);\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.unregister},\n ];\n }\n}"],"file":"cmitem.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../../src/local/content/section/cmitem.js"],"names":["name","selectors","DRAGICON","classes","id","element","dataset","configDragDrop","getElement","classList","add","watch","handler","unregister","_refreshCm","toggle","DRAGGING","dragging","DndCmItem"],"mappings":"mNA0BA,uD,gwDAOa,CAEL,KAAKA,IAAL,CAAY,wBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,QAAQ,gBADK,CAAjB,CAIA,KAAKC,OAAL,CAAe,EAAf,CAEA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,+CAKY,OACT,KAAKG,cAAL,CAAoB,KAAKH,EAAzB,EACA,eAAKI,UAAL,CAAgB,KAAKP,SAAL,CAAeC,QAA/B,wBAA0CO,SAA1C,CAAoDC,GAApD,CAAwD,KAAKP,OAAL,CAAaD,QAArE,CACH,C,iDAOa,CACV,MAAO,CACH,CAACS,KAAK,cAAQ,KAAKP,EAAb,aAAN,CAAkCQ,OAAO,CAAE,KAAKC,UAAhD,CADG,CAEH,CAACF,KAAK,cAAQ,KAAKP,EAAb,aAAN,CAAkCQ,OAAO,CAAE,KAAKE,UAAhD,CAFG,CAIV,C,gDAOqB,OAAVT,CAAU,GAAVA,OAAU,CAElB,KAAKA,OAAL,CAAaI,SAAb,CAAuBM,MAAvB,CAA8B,KAAKZ,OAAL,CAAaa,QAA3C,WAAqDX,CAAO,CAACY,QAA7D,mBACH,C,cA9CwBC,S","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 * Course course module item component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/content/section/cmitem\n * @class core_courseformat/local/content/section/cmitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\n\nexport default class extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'content_section_cmitem';\n // Default query selectors.\n this.selectors = {\n DRAGICON: `.editing_move`,\n };\n // All classes will be loaded later by DndCmItem.\n this.classes = {};\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n this.configDragDrop(this.id);\n this.getElement(this.selectors.DRAGICON)?.classList.add(this.classes.DRAGICON);\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.unregister},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n }\n}"],"file":"cmitem.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseeditor/dndcmitem.min.js b/course/format/amd/build/local/courseeditor/dndcmitem.min.js index 7bd1d49c60f..209d3b4306f 100644 --- a/course/format/amd/build/local/courseeditor/dndcmitem.min.js +++ b/course/format/amd/build/local/courseeditor/dndcmitem.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseeditor/dndcmitem",["exports","core/reactive"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndcmitem\n * @class core_courseformat/local/courseeditor/dndcmitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Configure the component drag and drop.\n *\n * @param {number} cmid course module id\n */\n configDragDrop(cmid) {\n\n this.id = cmid;\n\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init element drag and drop.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n // Drag and drop methods.\n\n /**\n * Get the draggable data of this component.\n *\n * @returns {Object} exported course module drop data\n */\n getDraggableData() {\n const exporter = this.reactive.getExporter();\n return exporter.cmDraggableData(this.reactive.state, this.id);\n }\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n return dropdata?.type === 'cm';\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone(dropdata) {\n // If we are the next cmid of the dragged element we accept the drop because otherwise it\n // will get captured by the section. However, we won't trigger any mutation.\n if (dropdata.nextcmid != this.id && dropdata.id != this.id) {\n this.element.classList.add(this.classes.DROPUP);\n }\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.element.classList.remove(this.classes.DROPUP);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation if necessary.\n if (dropdata.id != this.id && dropdata.nextcmid != this.id) {\n this.reactive.dispatch('cmMove', [dropdata.id], null, this.id);\n }\n }\n\n}\n"],"file":"dndcmitem.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseeditor/dndcmitem.js"],"names":["cmid","id","reactive","isEditing","supportComponents","dragdrop","DragDrop","classes","getClasses","unregister","dropdata","dispatch","exporter","getExporter","cmDraggableData","state","type","nextcmid","element","classList","add","DROPUP","remove","BaseComponent"],"mappings":"i8DAoCmBA,C,CAAM,CAEjB,KAAKC,EAAL,CAAUD,CAAV,CAGA,GAAI,KAAKE,QAAL,CAAcC,SAAd,EAA2B,KAAKD,QAAL,CAAcE,iBAA7C,CAAgE,CAE5D,KAAKC,QAAL,CAAgB,GAAIC,WAAJ,CAAa,IAAb,CAAhB,CAEA,KAAKC,OAAL,CAAe,KAAKF,QAAL,CAAcG,UAAd,EAClB,CACJ,C,yCAKS,CACN,GAAI,KAAKH,QAAL,SAAJ,CAAiC,CAC7B,KAAKA,QAAL,CAAcI,UAAd,EACH,CACJ,C,4CASSC,C,CAAU,CAChB,KAAKR,QAAL,CAAcS,QAAd,CAAuB,QAAvB,CAAiC,CAACD,CAAQ,CAACT,EAAV,CAAjC,IACH,C,wCAOOS,C,CAAU,CACd,KAAKR,QAAL,CAAcS,QAAd,CAAuB,QAAvB,CAAiC,CAACD,CAAQ,CAACT,EAAV,CAAjC,IACH,C,2DAOkB,CACf,GAAMW,CAAAA,CAAQ,CAAG,KAAKV,QAAL,CAAcW,WAAd,EAAjB,CACA,MAAOD,CAAAA,CAAQ,CAACE,eAAT,CAAyB,KAAKZ,QAAL,CAAca,KAAvC,CAA8C,KAAKd,EAAnD,CACV,C,0DAQgBS,C,CAAU,CACvB,MAA0B,IAAnB,WAAAA,CAAQ,WAARA,SAAAA,CAAQ,CAAEM,IAAV,CACV,C,kDAOYN,C,CAAU,CAGnB,GAAIA,CAAQ,CAACO,QAAT,EAAqB,KAAKhB,EAA1B,EAAgCS,CAAQ,CAACT,EAAT,EAAe,KAAKA,EAAxD,CAA4D,CACxD,KAAKiB,OAAL,CAAaC,SAAb,CAAuBC,GAAvB,CAA2B,KAAKb,OAAL,CAAac,MAAxC,CACH,CACJ,C,mDAKc,CACX,KAAKH,OAAL,CAAaC,SAAb,CAAuBG,MAAvB,CAA8B,KAAKf,OAAL,CAAac,MAA3C,CACH,C,kCAOIX,C,CAAU,CAEX,GAAIA,CAAQ,CAACT,EAAT,EAAe,KAAKA,EAApB,EAA0BS,CAAQ,CAACO,QAAT,EAAqB,KAAKhB,EAAxD,CAA4D,CACxD,KAAKC,QAAL,CAAcS,QAAd,CAAuB,QAAvB,CAAiC,CAACD,CAAQ,CAACT,EAAV,CAAjC,CAAgD,IAAhD,CAAsD,KAAKA,EAA3D,CACH,CACJ,C,cAnGwBsB,e","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 * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndcmitem\n * @class core_courseformat/local/courseeditor/dndcmitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Configure the component drag and drop.\n *\n * @param {number} cmid course module id\n */\n configDragDrop(cmid) {\n\n this.id = cmid;\n\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init element drag and drop.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n // Drag and drop methods.\n\n /**\n * The element drop start hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragStart(dropdata) {\n this.reactive.dispatch('cmDrag', [dropdata.id], true);\n }\n\n /**\n * The element drop end hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragEnd(dropdata) {\n this.reactive.dispatch('cmDrag', [dropdata.id], false);\n }\n\n /**\n * Get the draggable data of this component.\n *\n * @returns {Object} exported course module drop data\n */\n getDraggableData() {\n const exporter = this.reactive.getExporter();\n return exporter.cmDraggableData(this.reactive.state, this.id);\n }\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n return dropdata?.type === 'cm';\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone(dropdata) {\n // If we are the next cmid of the dragged element we accept the drop because otherwise it\n // will get captured by the section. However, we won't trigger any mutation.\n if (dropdata.nextcmid != this.id && dropdata.id != this.id) {\n this.element.classList.add(this.classes.DROPUP);\n }\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.element.classList.remove(this.classes.DROPUP);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation if necessary.\n if (dropdata.id != this.id && dropdata.nextcmid != this.id) {\n this.reactive.dispatch('cmMove', [dropdata.id], null, this.id);\n }\n }\n\n}\n"],"file":"dndcmitem.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseeditor/dndsection.min.js b/course/format/amd/build/local/courseeditor/dndsection.min.js index df8e2755369..18cc61a9eef 100644 --- a/course/format/amd/build/local/courseeditor/dndsection.min.js +++ b/course/format/amd/build/local/courseeditor/dndsection.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseeditor/dndsection",["exports","core/reactive"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;ca.number){this.element.classList.remove(this.classes.DROPUP);this.element.classList.add(this.classes.DROPDOWN)}else{this.element.classList.add(this.classes.DROPUP);this.element.classList.remove(this.classes.DROPDOWN)}}}},{key:"hideDropZone",value:function hideDropZone(){var a;null===(a=this.getLastCm())||void 0===a?void 0:a.classList.remove(this.classes.DROPDOWN);this.element.classList.remove(this.classes.DROPUP);this.element.classList.remove(this.classes.DROPDOWN)}},{key:"drop",value:function drop(a){if("cm"==a.type){this.reactive.dispatch("cmMove",[a.id],this.id)}if("section"==a.type){this.reactive.dispatch("sectionMove",[a.id],this.id)}}}]);return c}(b.BaseComponent);a.default=n;return a.default}); +define ("core_courseformat/local/courseeditor/dndsection",["exports","core/reactive"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;ca.number){this.element.classList.remove(this.classes.DROPUP);this.element.classList.add(this.classes.DROPDOWN)}else{this.element.classList.add(this.classes.DROPUP);this.element.classList.remove(this.classes.DROPDOWN)}}}},{key:"hideDropZone",value:function hideDropZone(){var a;null===(a=this.getLastCm())||void 0===a?void 0:a.classList.remove(this.classes.DROPDOWN);this.element.classList.remove(this.classes.DROPUP);this.element.classList.remove(this.classes.DROPDOWN)}},{key:"drop",value:function drop(a){if("cm"==a.type){this.reactive.dispatch("cmMove",[a.id],this.id)}if("section"==a.type){this.reactive.dispatch("sectionMove",[a.id],this.id)}}}]);return c}(b.BaseComponent);a.default=n;return a.default}); //# sourceMappingURL=dndsection.min.js.map diff --git a/course/format/amd/build/local/courseeditor/dndsection.min.js.map b/course/format/amd/build/local/courseeditor/dndsection.min.js.map index 0e1b3ff474e..061f5d8b889 100644 --- a/course/format/amd/build/local/courseeditor/dndsection.min.js.map +++ b/course/format/amd/build/local/courseeditor/dndsection.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../../src/local/courseeditor/dndsection.js"],"names":["state","id","element","dataset","section","get","course","sectionitem","reactive","isEditing","supportComponents","dragdrop","DragDrop","classes","getClasses","unregister","dropdata","type","sectionzeroid","sectionlist","getLastCm","classList","add","DROPDOWN","number","remove","DROPUP","dispatch","BaseComponent"],"mappings":"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","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 * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndsection\n * @class core_courseformat/local/courseeditor/dndsection\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Save some values form the state.\n *\n * @param {Object} state the current state\n */\n configState(state) {\n this.id = this.element.dataset.id;\n this.section = state.section.get(this.id);\n this.course = state.course;\n }\n\n /**\n * Register state values and the drag and drop subcomponent.\n *\n * @param {BaseComponent} sectionitem section item component\n */\n configDragDrop(sectionitem) {\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element.\n this.sectionitem = sectionitem;\n // Init the dropzone.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.sectionitem !== undefined) {\n this.sectionitem.unregister();\n }\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null} the las course module element of the section.\n */\n getLastCm() {\n return null;\n }\n\n // Drag and drop methods.\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n // We accept any course module.\n if (dropdata?.type === 'cm') {\n return true;\n }\n // We accept any section bu the section 0 or ourself\n if (dropdata?.type === 'section') {\n const sectionzeroid = this.course.sectionlist[0];\n return dropdata?.id != this.id && dropdata?.id != sectionzeroid && this.id != sectionzeroid;\n }\n return false;\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone(dropdata) {\n if (dropdata.type == 'cm') {\n this.getLastCm()?.classList.add(this.classes.DROPDOWN);\n }\n if (dropdata.type == 'section') {\n // The relative move of section depends on the section number.\n if (this.section.number > dropdata.number) {\n this.element.classList.remove(this.classes.DROPUP);\n this.element.classList.add(this.classes.DROPDOWN);\n } else {\n this.element.classList.add(this.classes.DROPUP);\n this.element.classList.remove(this.classes.DROPDOWN);\n }\n }\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.getLastCm()?.classList.remove(this.classes.DROPDOWN);\n this.element.classList.remove(this.classes.DROPUP);\n this.element.classList.remove(this.classes.DROPDOWN);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation.\n if (dropdata.type == 'cm') {\n this.reactive.dispatch('cmMove', [dropdata.id], this.id);\n }\n if (dropdata.type == 'section') {\n this.reactive.dispatch('sectionMove', [dropdata.id], this.id);\n }\n }\n}\n"],"file":"dndsection.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseeditor/dndsection.js"],"names":["state","id","element","dataset","section","get","course","sectionitem","reactive","isEditing","supportComponents","dragdrop","DragDrop","classes","getClasses","unregister","dropdata","dispatch","type","sectionzeroid","sectionlist","getLastCm","classList","add","DROPDOWN","number","remove","DROPUP","BaseComponent"],"mappings":"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","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 * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndsection\n * @class core_courseformat/local/courseeditor/dndsection\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Save some values form the state.\n *\n * @param {Object} state the current state\n */\n configState(state) {\n this.id = this.element.dataset.id;\n this.section = state.section.get(this.id);\n this.course = state.course;\n }\n\n /**\n * Register state values and the drag and drop subcomponent.\n *\n * @param {BaseComponent} sectionitem section item component\n */\n configDragDrop(sectionitem) {\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element.\n this.sectionitem = sectionitem;\n // Init the dropzone.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.sectionitem !== undefined) {\n this.sectionitem.unregister();\n }\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null} the las course module element of the section.\n */\n getLastCm() {\n return null;\n }\n\n // Drag and drop methods.\n\n /**\n * The element drop start hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragStart(dropdata) {\n this.reactive.dispatch('sectionDrag', [dropdata.id], true);\n }\n\n /**\n * The element drop end hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragEnd(dropdata) {\n this.reactive.dispatch('sectionDrag', [dropdata.id], false);\n }\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n // We accept any course module.\n if (dropdata?.type === 'cm') {\n return true;\n }\n // We accept any section bu the section 0 or ourself\n if (dropdata?.type === 'section') {\n const sectionzeroid = this.course.sectionlist[0];\n return dropdata?.id != this.id && dropdata?.id != sectionzeroid && this.id != sectionzeroid;\n }\n return false;\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone(dropdata) {\n if (dropdata.type == 'cm') {\n this.getLastCm()?.classList.add(this.classes.DROPDOWN);\n }\n if (dropdata.type == 'section') {\n // The relative move of section depends on the section number.\n if (this.section.number > dropdata.number) {\n this.element.classList.remove(this.classes.DROPUP);\n this.element.classList.add(this.classes.DROPDOWN);\n } else {\n this.element.classList.add(this.classes.DROPUP);\n this.element.classList.remove(this.classes.DROPDOWN);\n }\n }\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.getLastCm()?.classList.remove(this.classes.DROPDOWN);\n this.element.classList.remove(this.classes.DROPUP);\n this.element.classList.remove(this.classes.DROPDOWN);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation.\n if (dropdata.type == 'cm') {\n this.reactive.dispatch('cmMove', [dropdata.id], this.id);\n }\n if (dropdata.type == 'section') {\n this.reactive.dispatch('sectionMove', [dropdata.id], this.id);\n }\n }\n}\n"],"file":"dndsection.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseeditor/dndsectionitem.min.js b/course/format/amd/build/local/courseeditor/dndsectionitem.min.js index b8638579b77..682a810fd09 100644 --- a/course/format/amd/build/local/courseeditor/dndsectionitem.min.js +++ b/course/format/amd/build/local/courseeditor/dndsectionitem.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseeditor/dndsectionitem",["exports","core/reactive"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Course index section title draggable component.\n *\n * This component is used to control specific course section interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndsectionitem\n * @class core_courseformat/local/courseeditor/dndsectionitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Initial state ready method.\n *\n * @param {number} sectionid the section id\n * @param {Object} state the initial state\n * @param {Element} fullregion the complete section region to mark as dragged\n */\n configDragDrop(sectionid, state, fullregion) {\n\n this.id = sectionid;\n if (this.section === undefined) {\n this.section = state.section.get(this.id);\n }\n if (this.course === undefined) {\n this.course = state.course;\n }\n\n // Prevent topic zero from being draggable.\n if (this.section.number > 0) {\n this.getDraggableData = this._getDraggableData;\n }\n\n this.fullregion = fullregion;\n\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the dropzone.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n // Drag and drop methods.\n\n /**\n * Get the draggable data of this component.\n *\n * @returns {Object} exported course module drop data\n */\n _getDraggableData() {\n const exporter = this.reactive.getExporter();\n return exporter.sectionDraggableData(this.reactive.state, this.id);\n }\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n // Course module validation.\n if (dropdata?.type === 'cm') {\n // The first section element is already there so we can ignore it.\n const firstcmid = this.section?.cmlist[0];\n return dropdata.id !== firstcmid;\n }\n return false;\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone() {\n this.element.classList.add(this.classes.DROPZONE);\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.element.classList.remove(this.classes.DROPZONE);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation.\n if (dropdata.type == 'cm') {\n this.reactive.dispatch('cmMove', [dropdata.id], this.id, this.section?.cmlist[0]);\n }\n }\n}\n"],"file":"dndsectionitem.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseeditor/dndsectionitem.js"],"names":["sectionid","state","fullregion","id","section","get","course","number","getDraggableData","_getDraggableData","reactive","isEditing","supportComponents","dragdrop","DragDrop","classes","getClasses","unregister","dropdata","dispatch","exporter","getExporter","sectionDraggableData","type","firstcmid","cmlist","element","classList","add","DROPZONE","remove","BaseComponent"],"mappings":"s8DAsCmBA,C,CAAWC,C,CAAOC,C,CAAY,CAEzC,KAAKC,EAAL,CAAUH,CAAV,CACA,GAAI,KAAKI,OAAL,SAAJ,CAAgC,CAC5B,KAAKA,OAAL,CAAeH,CAAK,CAACG,OAAN,CAAcC,GAAd,CAAkB,KAAKF,EAAvB,CAClB,CACD,GAAI,KAAKG,MAAL,SAAJ,CAA+B,CAC3B,KAAKA,MAAL,CAAcL,CAAK,CAACK,MACvB,CAGD,GAA0B,CAAtB,MAAKF,OAAL,CAAaG,MAAjB,CAA6B,CACzB,KAAKC,gBAAL,CAAwB,KAAKC,iBAChC,CAED,KAAKP,UAAL,CAAkBA,CAAlB,CAGA,GAAI,KAAKQ,QAAL,CAAcC,SAAd,EAA2B,KAAKD,QAAL,CAAcE,iBAA7C,CAAgE,CAE5D,KAAKC,QAAL,CAAgB,GAAIC,WAAJ,CAAa,IAAb,CAAhB,CAEA,KAAKC,OAAL,CAAe,KAAKF,QAAL,CAAcG,UAAd,EAClB,CACJ,C,yCAKS,CACN,GAAI,KAAKH,QAAL,SAAJ,CAAiC,CAC7B,KAAKA,QAAL,CAAcI,UAAd,EACH,CACJ,C,4CASSC,C,CAAU,CAChB,KAAKR,QAAL,CAAcS,QAAd,CAAuB,aAAvB,CAAsC,CAACD,CAAQ,CAACf,EAAV,CAAtC,IACH,C,wCAOOe,C,CAAU,CACd,KAAKR,QAAL,CAAcS,QAAd,CAAuB,aAAvB,CAAsC,CAACD,CAAQ,CAACf,EAAV,CAAtC,IACH,C,6DAOmB,CAChB,GAAMiB,CAAAA,CAAQ,CAAG,KAAKV,QAAL,CAAcW,WAAd,EAAjB,CACA,MAAOD,CAAAA,CAAQ,CAACE,oBAAT,CAA8B,KAAKZ,QAAL,CAAcT,KAA5C,CAAmD,KAAKE,EAAxD,CACV,C,0DAQgBe,C,CAAU,CAEvB,GAAuB,IAAnB,WAAAA,CAAQ,WAARA,SAAAA,CAAQ,CAAEK,IAAV,CAAJ,CAA6B,OAEnBC,CAAS,WAAG,KAAKpB,OAAR,qBAAG,EAAcqB,MAAd,CAAqB,CAArB,CAFO,CAGzB,MAAOP,CAAAA,CAAQ,CAACf,EAAT,GAAgBqB,CAC1B,CACD,QACH,C,mDAOc,CACX,KAAKE,OAAL,CAAaC,SAAb,CAAuBC,GAAvB,CAA2B,KAAKb,OAAL,CAAac,QAAxC,CACH,C,mDAKc,CACX,KAAKH,OAAL,CAAaC,SAAb,CAAuBG,MAAvB,CAA8B,KAAKf,OAAL,CAAac,QAA3C,CACH,C,kCAOIX,C,CAAU,CAEX,GAAqB,IAAjB,EAAAA,CAAQ,CAACK,IAAb,CAA2B,OACvB,KAAKb,QAAL,CAAcS,QAAd,CAAuB,QAAvB,CAAiC,CAACD,CAAQ,CAACf,EAAV,CAAjC,CAAgD,KAAKA,EAArD,WAAyD,KAAKC,OAA9D,qBAAyD,EAAcqB,MAAd,CAAqB,CAArB,CAAzD,CACH,CACJ,C,cApHwBM,e","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 * Course index section title draggable component.\n *\n * This component is used to control specific course section interactions like drag and drop\n * in both course index and course content.\n *\n * @module core_courseformat/local/courseeditor/dndsectionitem\n * @class core_courseformat/local/courseeditor/dndsectionitem\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent, DragDrop} from 'core/reactive';\n\nexport default class extends BaseComponent {\n\n /**\n * Initial state ready method.\n *\n * @param {number} sectionid the section id\n * @param {Object} state the initial state\n * @param {Element} fullregion the complete section region to mark as dragged\n */\n configDragDrop(sectionid, state, fullregion) {\n\n this.id = sectionid;\n if (this.section === undefined) {\n this.section = state.section.get(this.id);\n }\n if (this.course === undefined) {\n this.course = state.course;\n }\n\n // Prevent topic zero from being draggable.\n if (this.section.number > 0) {\n this.getDraggableData = this._getDraggableData;\n }\n\n this.fullregion = fullregion;\n\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the dropzone.\n this.dragdrop = new DragDrop(this);\n // Save dropzone classes.\n this.classes = this.dragdrop.getClasses();\n }\n }\n\n /**\n * Remove all subcomponents dependencies.\n */\n destroy() {\n if (this.dragdrop !== undefined) {\n this.dragdrop.unregister();\n }\n }\n\n // Drag and drop methods.\n\n /**\n * The element drop start hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragStart(dropdata) {\n this.reactive.dispatch('sectionDrag', [dropdata.id], true);\n }\n\n /**\n * The element end start hook.\n *\n * @param {Object} dropdata the dropdata\n */\n dragEnd(dropdata) {\n this.reactive.dispatch('sectionDrag', [dropdata.id], false);\n }\n\n /**\n * Get the draggable data of this component.\n *\n * @returns {Object} exported course module drop data\n */\n _getDraggableData() {\n const exporter = this.reactive.getExporter();\n return exporter.sectionDraggableData(this.reactive.state, this.id);\n }\n\n /**\n * Validate if the drop data can be dropped over the component.\n *\n * @param {Object} dropdata the exported drop data.\n * @returns {boolean}\n */\n validateDropData(dropdata) {\n // Course module validation.\n if (dropdata?.type === 'cm') {\n // The first section element is already there so we can ignore it.\n const firstcmid = this.section?.cmlist[0];\n return dropdata.id !== firstcmid;\n }\n return false;\n }\n\n /**\n * Display the component dropzone.\n *\n * @param {Object} dropdata the accepted drop data\n */\n showDropZone() {\n this.element.classList.add(this.classes.DROPZONE);\n }\n\n /**\n * Hide the component dropzone.\n */\n hideDropZone() {\n this.element.classList.remove(this.classes.DROPZONE);\n }\n\n /**\n * Drop event handler.\n *\n * @param {Object} dropdata the accepted drop data\n */\n drop(dropdata) {\n // Call the move mutation.\n if (dropdata.type == 'cm') {\n this.reactive.dispatch('cmMove', [dropdata.id], this.id, this.section?.cmlist[0]);\n }\n }\n}\n"],"file":"dndsectionitem.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseeditor/mutations.min.js b/course/format/amd/build/local/courseeditor/mutations.min.js index bafbd33d1a2..972730528a6 100644 --- a/course/format/amd/build/local/courseeditor/mutations.min.js +++ b/course/format/amd/build/local/courseeditor/mutations.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseeditor/mutations",["exports","core/ajax"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(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 d(a){return function(){var b=this,d=arguments;return new Promise(function(e,f){var i=a.apply(b,d);function g(a){c(i,e,f,g,h,"next",a)}function h(a){c(i,e,f,g,h,"throw",a)}g(void 0)})}}function e(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function f(a,b){for(var c=0,d;c.\n\nimport ajax from 'core/ajax';\n\n/**\n * Default mutation manager\n *\n * @module core_courseformat/local/courseeditor/mutations\n * @class core_courseformat/local/courseeditor/mutations\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default class {\n\n // All course editor mutations for Moodle 4.0 will be located in this file.\n\n /**\n * Private method to call core_courseformat_update_course webservice.\n *\n * @method _callEditWebservice\n * @param {string} action\n * @param {number} courseId\n * @param {array} ids\n * @param {number} targetSectionId optional target section id (for moving actions)\n * @param {number} targetCmId optional target cm id (for moving actions)\n */\n async _callEditWebservice(action, courseId, ids, targetSectionId, targetCmId) {\n const args = {\n action,\n courseid: courseId,\n ids,\n };\n if (targetSectionId) {\n args.targetsectionid = targetSectionId;\n }\n if (targetCmId) {\n args.targetcmid = targetCmId;\n }\n let ajaxresult = await ajax.call([{\n methodname: 'core_courseformat_update_course',\n args,\n }])[0];\n return JSON.parse(ajaxresult);\n }\n\n /**\n * Move course modules to specific course location.\n *\n * Note that one of targetSectionId or targetCmId should be provided in order to identify the\n * new location:\n * - targetCmId: the activities will be located avobe the target cm. The targetSectionId\n * value will be ignored in this case.\n * - targetSectionId: the activities will be appended to the section. In this case\n * targetSectionId should not be present.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} cmids the list of cm ids to move\n * @param {number} targetSectionId the target section id\n * @param {number} targetCmId the target course module id\n */\n async cmMove(stateManager, cmids, targetSectionId, targetCmId) {\n if (!targetSectionId && !targetCmId) {\n throw new Error(`Mutation cmMove requires targetSectionId or targetCmId`);\n }\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('cm_move', course.id, cmids, targetSectionId, targetCmId);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Move course modules to specific course location.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids to move\n * @param {number} targetSectionId the target section id\n */\n async sectionMove(stateManager, sectionIds, targetSectionId) {\n if (!targetSectionId) {\n throw new Error(`Mutation sectionMove requires targetSectionId`);\n }\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('section_move', course.id, sectionIds, targetSectionId);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Get updated state data related to some cm ids.\n *\n * @method cmState\n * @param {StateManager} stateManager the current state\n * @param {array} cmids the list of cm ids to update\n */\n async cmState(stateManager, cmids) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('cm_state', course.id, cmids);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Get updated state data related to some section ids.\n *\n * @method sectionState\n * @param {StateManager} stateManager the current state\n * @param {array} sectionIds the list of section ids to update\n */\n async sectionState(stateManager, sectionIds) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('section_state', course.id, sectionIds);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Get the full updated state data of the course.\n *\n * @param {StateManager} stateManager the current state\n */\n async courseState(stateManager) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('course_state', course.id);\n stateManager.processUpdates(updates);\n }\n\n}\n"],"file":"mutations.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseeditor/mutations.js"],"names":["action","courseId","ids","targetSectionId","targetCmId","args","courseid","targetsectionid","targetcmid","ajax","call","methodname","ajaxresult","JSON","parse","stateManager","cmids","Error","course","get","_callEditWebservice","id","updates","processUpdates","sectionIds","cmIds","dragValue","_setElementsValue","name","fieldName","newValue","setReadOnly","forEach","element"],"mappings":"8KAeA,uD,owBAwB8BA,C,CAAQC,C,CAAUC,C,CAAKC,C,CAAiBC,C,2FACxDC,C,CAAO,CACTL,MAAM,CAANA,CADS,CAETM,QAAQ,CAAEL,CAFD,CAGTC,GAAG,CAAHA,CAHS,C,CAKb,GAAIC,CAAJ,CAAqB,CACjBE,CAAI,CAACE,eAAL,CAAuBJ,CAC1B,CACD,GAAIC,CAAJ,CAAgB,CACZC,CAAI,CAACG,UAAL,CAAkBJ,CACrB,C,eACsBK,WAAKC,IAAL,CAAU,CAAC,CAC9BC,UAAU,CAAE,iCADkB,CAE9BN,IAAI,CAAJA,CAF8B,CAAD,CAAV,EAGnB,CAHmB,C,QAAnBO,C,iCAIGC,IAAI,CAACC,KAAL,CAAWF,CAAX,C,iMAkBEG,C,CAAcC,C,CAAOb,C,CAAiBC,C,gGAC3C,CAACD,CAAD,EAAoB,CAACC,C,uBACf,IAAIa,CAAAA,KAAJ,0D,QAEJC,C,CAASH,CAAY,CAACI,GAAb,CAAiB,QAAjB,C,gBACO,MAAKC,mBAAL,CAAyB,SAAzB,CAAoCF,CAAM,CAACG,EAA3C,CAA+CL,CAA/C,CAAsDb,CAAtD,CAAuEC,CAAvE,C,QAAhBkB,C,QACNP,CAAY,CAACQ,cAAb,CAA4BD,CAA5B,E,4LAUcP,C,CAAcS,C,CAAYrB,C,8FACnCA,C,sBACK,IAAIc,CAAAA,KAAJ,iD,QAEJC,C,CAASH,CAAY,CAACI,GAAb,CAAiB,QAAjB,C,gBACO,MAAKC,mBAAL,CAAyB,cAAzB,CAAyCF,CAAM,CAACG,EAAhD,CAAoDG,CAApD,CAAgErB,CAAhE,C,QAAhBmB,C,QACNP,CAAY,CAACQ,cAAb,CAA4BD,CAA5B,E,sJAUGP,C,CAAcU,C,CAAOC,C,CAAW,CACnC,KAAKC,iBAAL,CAAuBZ,CAAvB,CAAqC,IAArC,CAA2CU,CAA3C,CAAkD,UAAlD,CAA8DC,CAA9D,CACH,C,gDASWX,C,CAAcS,C,CAAYE,C,CAAW,CAC7C,KAAKC,iBAAL,CAAuBZ,CAAvB,CAAqC,SAArC,CAAgDS,CAAhD,CAA4D,UAA5D,CAAwEE,CAAxE,CACH,C,4DAEiBX,C,CAAca,C,CAAM1B,C,CAAK2B,C,CAAWC,C,CAAU,CAC5Df,CAAY,CAACgB,WAAb,KACA7B,CAAG,CAAC8B,OAAJ,CAAY,SAACX,CAAD,CAAQ,CAChB,GAAMY,CAAAA,CAAO,CAAGlB,CAAY,CAACI,GAAb,CAAiBS,CAAjB,CAAuBP,CAAvB,CAAhB,CACA,GAAIY,CAAJ,CAAa,CACTA,CAAO,CAACJ,CAAD,CAAP,CAAqBC,CACxB,CACJ,CALD,EAMAf,CAAY,CAACgB,WAAb,IACH,C,6EASahB,C,CAAcC,C,2FAClBE,C,CAASH,CAAY,CAACI,GAAb,CAAiB,QAAjB,C,gBACO,MAAKC,mBAAL,CAAyB,UAAzB,CAAqCF,CAAM,CAACG,EAA5C,CAAgDL,CAAhD,C,QAAhBM,C,QACNP,CAAY,CAACQ,cAAb,CAA4BD,CAA5B,E,8LAUeP,C,CAAcS,C,2FACvBN,C,CAASH,CAAY,CAACI,GAAb,CAAiB,QAAjB,C,gBACO,MAAKC,mBAAL,CAAyB,eAAzB,CAA0CF,CAAM,CAACG,EAAjD,CAAqDG,CAArD,C,QAAhBF,C,QACNP,CAAY,CAACQ,cAAb,CAA4BD,CAA5B,E,kMAQcP,C,2FACRG,C,CAASH,CAAY,CAACI,GAAb,CAAiB,QAAjB,C,gBACO,MAAKC,mBAAL,CAAyB,cAAzB,CAAyCF,CAAM,CAACG,EAAhD,C,QAAhBC,C,QACNP,CAAY,CAACQ,cAAb,CAA4BD,CAA5B,E","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\nimport ajax from 'core/ajax';\n\n/**\n * Default mutation manager\n *\n * @module core_courseformat/local/courseeditor/mutations\n * @class core_courseformat/local/courseeditor/mutations\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default class {\n\n // All course editor mutations for Moodle 4.0 will be located in this file.\n\n /**\n * Private method to call core_courseformat_update_course webservice.\n *\n * @method _callEditWebservice\n * @param {string} action\n * @param {number} courseId\n * @param {array} ids\n * @param {number} targetSectionId optional target section id (for moving actions)\n * @param {number} targetCmId optional target cm id (for moving actions)\n */\n async _callEditWebservice(action, courseId, ids, targetSectionId, targetCmId) {\n const args = {\n action,\n courseid: courseId,\n ids,\n };\n if (targetSectionId) {\n args.targetsectionid = targetSectionId;\n }\n if (targetCmId) {\n args.targetcmid = targetCmId;\n }\n let ajaxresult = await ajax.call([{\n methodname: 'core_courseformat_update_course',\n args,\n }])[0];\n return JSON.parse(ajaxresult);\n }\n\n /**\n * Move course modules to specific course location.\n *\n * Note that one of targetSectionId or targetCmId should be provided in order to identify the\n * new location:\n * - targetCmId: the activities will be located avobe the target cm. The targetSectionId\n * value will be ignored in this case.\n * - targetSectionId: the activities will be appended to the section. In this case\n * targetSectionId should not be present.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} cmids the list of cm ids to move\n * @param {number} targetSectionId the target section id\n * @param {number} targetCmId the target course module id\n */\n async cmMove(stateManager, cmids, targetSectionId, targetCmId) {\n if (!targetSectionId && !targetCmId) {\n throw new Error(`Mutation cmMove requires targetSectionId or targetCmId`);\n }\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('cm_move', course.id, cmids, targetSectionId, targetCmId);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Move course modules to specific course location.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids to move\n * @param {number} targetSectionId the target section id\n */\n async sectionMove(stateManager, sectionIds, targetSectionId) {\n if (!targetSectionId) {\n throw new Error(`Mutation sectionMove requires targetSectionId`);\n }\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('section_move', course.id, sectionIds, targetSectionId);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Mark or unmark course modules as dragging.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} cmIds the list of course modules ids\n * @param {bool} dragValue the new dragging value\n */\n cmDrag(stateManager, cmIds, dragValue) {\n this._setElementsValue(stateManager, 'cm', cmIds, 'dragging', dragValue);\n }\n\n /**\n * Mark or unmark course sections as dragging.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids\n * @param {bool} dragValue the new dragging value\n */\n sectionDrag(stateManager, sectionIds, dragValue) {\n this._setElementsValue(stateManager, 'section', sectionIds, 'dragging', dragValue);\n }\n\n _setElementsValue(stateManager, name, ids, fieldName, newValue) {\n stateManager.setReadOnly(false);\n ids.forEach((id) => {\n const element = stateManager.get(name, id);\n if (element) {\n element[fieldName] = newValue;\n }\n });\n stateManager.setReadOnly(true);\n }\n\n /**\n * Get updated state data related to some cm ids.\n *\n * @method cmState\n * @param {StateManager} stateManager the current state\n * @param {array} cmids the list of cm ids to update\n */\n async cmState(stateManager, cmids) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('cm_state', course.id, cmids);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Get updated state data related to some section ids.\n *\n * @method sectionState\n * @param {StateManager} stateManager the current state\n * @param {array} sectionIds the list of section ids to update\n */\n async sectionState(stateManager, sectionIds) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('section_state', course.id, sectionIds);\n stateManager.processUpdates(updates);\n }\n\n /**\n * Get the full updated state data of the course.\n *\n * @param {StateManager} stateManager the current state\n */\n async courseState(stateManager) {\n const course = stateManager.get('course');\n const updates = await this._callEditWebservice('course_state', course.id);\n stateManager.processUpdates(updates);\n }\n\n}\n"],"file":"mutations.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseindex/cm.min.js b/course/format/amd/build/local/courseindex/cm.min.js index 3e0d337a941..a481627cb34 100644 --- a/course/format/amd/build/local/courseindex/cm.min.js +++ b/course/format/amd/build/local/courseindex/cm.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseindex/cm",["exports","core_courseformat/local/courseeditor/dndcmitem"],function(a,b){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=function(a){return a&&a.__esModule?a:{default:a}}(b);function c(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){c=function(a){return typeof a}}else{c=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return c(a)}function d(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function e(a,b){for(var c=0,d;c.\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n this.configDragDrop(this.id);\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n ];\n }\n\n}\n"],"file":"cm.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseindex/cm.js"],"names":["Component","name","selectors","CM_NAME","classes","CMHIDDEN","id","element","dataset","configDragDrop","watch","handler","remove","_refreshCm","classList","toggle","visible","getElement","innerHTML","DRAGGING","dragging","target","document","getElementById","DndCmItem"],"mappings":"2MA0BA,uD,+nDAEqBA,CAAAA,C,+HAKR,CAEL,KAAKC,IAAL,CAAY,gBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,OAAO,uBADM,CAAjB,CAIA,KAAKC,OAAL,CAAe,CACXC,QAAQ,CAAE,QADC,CAAf,CAIA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,+CAmBY,CACT,KAAKG,cAAL,CAAoB,KAAKH,EAAzB,CACH,C,iDAOa,CACV,MAAO,CACH,CAACI,KAAK,cAAQ,KAAKJ,EAAb,aAAN,CAAkCK,OAAO,CAAE,KAAKC,MAAhD,CADG,CAEH,CAACF,KAAK,cAAQ,KAAKJ,EAAb,aAAN,CAAkCK,OAAO,CAAE,KAAKE,UAAhD,CAFG,CAIV,C,gDAOqB,OAAVN,CAAU,GAAVA,OAAU,CAElB,KAAKA,OAAL,CAAaO,SAAb,CAAuBC,MAAvB,CAA8B,KAAKX,OAAL,CAAaC,QAA3C,CAAqD,CAACE,CAAO,CAACS,OAA9D,EACA,KAAKC,UAAL,CAAgB,KAAKf,SAAL,CAAeC,OAA/B,EAAwCe,SAAxC,CAAoDX,CAAO,CAACN,IAA5D,CACA,KAAKM,OAAL,CAAaO,SAAb,CAAuBC,MAAvB,CAA8B,KAAKX,OAAL,CAAae,QAA3C,WAAqDZ,CAAO,CAACa,QAA7D,mBACH,C,oCApCWC,C,CAAQnB,C,CAAW,CAC3B,MAAO,IAAIF,CAAAA,CAAJ,CAAc,CACjBO,OAAO,CAAEe,QAAQ,CAACC,cAAT,CAAwBF,CAAxB,CADQ,CAEjBnB,SAAS,CAATA,CAFiB,CAAd,CAIV,C,cAhCkCsB,S","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 * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n this.configDragDrop(this.id);\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n }\n\n}\n"],"file":"cm.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseindex/courseindex.min.js b/course/format/amd/build/local/courseindex/courseindex.min.js index 2343e6c3fa0..12a21b3b8df 100644 --- a/course/format/amd/build/local/courseindex/courseindex.min.js +++ b/course/format/amd/build/local/courseindex/courseindex.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseindex/courseindex",["exports","core/reactive","core_courseformat/courseeditor"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function d(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){d=function(a){return typeof a}}else{d=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return d(a)}function e(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 f(a){return function(){var b=this,c=arguments;return new Promise(function(d,f){var i=a.apply(b,c);function g(a){e(i,d,f,g,h,"next",a)}function h(a){e(i,d,f,g,h,"throw",a)}g(void 0)})}}function g(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function h(a,b){for(var c=0,d;cb.length){a.removeChild(a.lastChild)}}},{key:"_deleteCm",value:function _deleteCm(a){var b=a.element;delete this.cms[b.id]}}],[{key:"init",value:function init(a,d){return new b({element:document.getElementById(a),reactive:(0,c.getCurrentCourseEditor)(),selectors:d})}}]);return b}(b.BaseComponent);a.default=q;return a.default}); +define ("core_courseformat/local/courseindex/courseindex",["exports","core/reactive","core_courseformat/courseeditor"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function d(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){d=function(a){return typeof a}}else{d=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return d(a)}function e(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 f(a){return function(){var b=this,c=arguments;return new Promise(function(d,f){var i=a.apply(b,c);function g(a){e(i,d,f,g,h,"next",a)}function h(a){e(i,d,f,g,h,"throw",a)}g(void 0)})}}function g(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function h(a,b){for(var c=0,d;cb.length){a.removeChild(a.lastChild)}}},{key:"_deleteCm",value:function _deleteCm(a){var b=a.element;delete this.cms[b.id]}}],[{key:"init",value:function init(a,d){return new b({element:document.getElementById(a),reactive:(0,c.getCurrentCourseEditor)(),selectors:d})}}]);return b}(b.BaseComponent);a.default=q;return a.default}); //# sourceMappingURL=courseindex.min.js.map diff --git a/course/format/amd/build/local/courseindex/courseindex.min.js.map b/course/format/amd/build/local/courseindex/courseindex.min.js.map index 3e11ef4827f..32bc9da7927 100644 --- a/course/format/amd/build/local/courseindex/courseindex.min.js.map +++ b/course/format/amd/build/local/courseindex/courseindex.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../../src/local/courseindex/courseindex.js"],"names":["Component","name","selectors","SECTION","SECTION_ITEM","SECTION_TITLE","SECTION_CMLIST","CM","CM_NAME","TOGGLER","COLLAPSE","classes","SECTIONHIDDEN","CMHIDDEN","SECTIONCURRENT","COLLAPSED","sections","cms","addEventListener","element","_setupSectionTogglers","getElements","forEach","section","dataset","id","cm","watch","handler","_refreshSection","_refreshCm","_createCm","_deleteCm","_refreshCourseSectionlist","_refreshSectionCmlist","event","sectionlink","target","closest","toggler","parentNode","querySelector","classList","contains","click","Error","sectionitem","toggle","visible","current","innerHTML","title","state","fakeelement","document","createElement","add","get","sectionid","exporter","reactive","getExporter","data","renderComponent","newcomponent","newelement","getElement","replaceChild","cmlist","listparent","_fixOrder","sectionlist","container","neworder","allitems","length","remove","itemid","index","item","currentitem","children","append","insertBefore","removeChild","lastChild","getElementById","BaseComponent"],"mappings":"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","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 * Course index main component.\n *\n * @module core_courseformat/local/courseindex/courseindex\n * @class core_courseformat/local/courseindex/courseindex\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent} from 'core/reactive';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\n\nexport default class Component extends BaseComponent {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex';\n // Default query selectors.\n this.selectors = {\n SECTION: `[data-for='section']`,\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n SECTION_CMLIST: `[data-for='cmlist']`,\n CM: `[data-for='cm']`,\n CM_NAME: `[data-for='cm_name']`,\n TOGGLER: `[data-action=\"togglecourseindexsection\"]`,\n COLLAPSE: `[data-toggle=\"collapse\"]`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n CMHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n COLLAPSED: `collapsed`,\n };\n // Arrays to keep cms and sections elements.\n this.sections = {};\n this.cms = {};\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n reactive: getCurrentCourseEditor(),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n // Activate section togglers.\n this.addEventListener(this.element, 'click', this._setupSectionTogglers);\n\n // Get cms and sections elements.\n const sections = this.getElements(this.selectors.SECTION);\n sections.forEach((section) => {\n this.sections[section.dataset.id] = section;\n });\n const cms = this.getElements(this.selectors.CM);\n cms.forEach((cm) => {\n this.cms[cm.dataset.id] = cm;\n });\n }\n\n getWatchers() {\n return [\n {watch: `section:updated`, handler: this._refreshSection},\n {watch: `cm:updated`, handler: this._refreshCm},\n {watch: `cm:created`, handler: this._createCm},\n {watch: `cm:deleted`, handler: this._deleteCm},\n // Sections and cm sorting.\n {watch: `course.sectionlist:updated`, handler: this._refreshCourseSectionlist},\n {watch: `section.cmlist:updated`, handler: this._refreshSectionCmlist},\n ];\n }\n\n /**\n * Setup sections toggler.\n *\n * Toggler click is delegated to the main course index element because new sections can\n * appear at any moment and this way we prevent accidental double bindings.\n *\n * @param {Event} event the triggered event\n */\n _setupSectionTogglers(event) {\n const sectionlink = event.target.closest(this.selectors.TOGGLER);\n if (sectionlink) {\n const toggler = sectionlink.parentNode.querySelector(this.selectors.COLLAPSE);\n if (toggler?.classList.contains(this.classes.COLLAPSED)) {\n toggler.click();\n }\n }\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshSection({element}) {\n // Find the element.\n const target = this.sections[element.id];\n if (!target) {\n throw new Error(`Unkown section with ID ${element.id}`);\n }\n // Update classes.\n const sectionitem = target.querySelector(this.selectors.SECTION_ITEM);\n sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n target.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n // Update title.\n target.querySelector(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshCm({element}) {\n // Find the element.\n const target = this.cms[element.id];\n if (!target) {\n throw new Error(`Unkown course module with ID ${element.id}`);\n }\n // Update classes.\n target.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n target.querySelector(this.selectors.CM_NAME).innerHTML = element.name;\n }\n\n /**\n * Create a newcm instance.\n *\n * @param {Object} details the update details.\n */\n async _createCm({state, element}) {\n // Create a fake node while the component is loading.\n const fakeelement = document.createElement('li');\n fakeelement.classList.add('bg-pulse-grey', 'w-100');\n fakeelement.innerHTML = ' ';\n this.cms[element.id] = fakeelement;\n // Place the fake node on the correct position.\n this._refreshSectionCmlist({\n state,\n element: state.section.get(element.sectionid),\n });\n // Collect render data.\n const exporter = this.reactive.getExporter();\n const data = exporter.cm(state, element);\n // Create the new content.\n const newcomponent = await this.renderComponent(fakeelement, 'core_courseformat/local/courseindex/cm', data);\n // Replace the fake node with the real content.\n const newelement = newcomponent.getElement();\n this.cms[element.id] = newelement;\n fakeelement.parentNode.replaceChild(newelement, fakeelement);\n }\n\n /**\n * Refresh a section cm list.\n *\n * @param {Object} details the update details.\n */\n _refreshSectionCmlist({element}) {\n const cmlist = element.cmlist ?? [];\n const listparent = this.getElement(this.selectors.SECTION_CMLIST, element.id);\n this._fixOrder(listparent, cmlist, this.cms);\n }\n\n /**\n * Refresh the section list.\n *\n * @param {Object} details the update details.\n */\n _refreshCourseSectionlist({element}) {\n const sectionlist = element.sectionlist ?? [];\n this._fixOrder(this.element, sectionlist, this.sections);\n }\n\n /**\n * Fix/reorder the section or cms order.\n *\n * @param {Element} container the HTML element to reorder.\n * @param {Array} neworder an array with the ids order\n * @param {Array} allitems the list of html elements that can be placed in the container\n */\n _fixOrder(container, neworder, allitems) {\n\n // Empty lists should not be visible.\n if (!neworder.length) {\n container.classList.add('hidden');\n container.innerHTML = '';\n return;\n }\n\n // Grant the list is visible (in case it was empty).\n container.classList.remove('hidden');\n\n // Move the elements in order at the beginning of the list.\n neworder.forEach((itemid, index) => {\n const item = allitems[itemid];\n // Get the current element at that position.\n const currentitem = container.children[index];\n if (currentitem === undefined) {\n container.append(item);\n return;\n }\n if (currentitem !== item) {\n container.insertBefore(item, currentitem);\n }\n });\n // Remove the remaining elements.\n while (container.children.length > neworder.length) {\n container.removeChild(container.lastChild);\n }\n }\n\n /**\n * Remove a cm from the list.\n *\n * The actual DOM element removal is delegated to the cm component.\n *\n * @param {Object} details the update details.\n */\n _deleteCm({element}) {\n delete this.cms[element.id];\n }\n}\n"],"file":"courseindex.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseindex/courseindex.js"],"names":["Component","name","selectors","SECTION","SECTION_CMLIST","CM","TOGGLER","COLLAPSE","classes","COLLAPSED","sections","cms","addEventListener","element","_setupSectionTogglers","getElements","forEach","section","dataset","id","cm","watch","handler","_createCm","_deleteCm","_refreshCourseSectionlist","_refreshSectionCmlist","event","sectionlink","target","closest","toggler","parentNode","querySelector","classList","contains","click","state","fakeelement","document","createElement","add","innerHTML","get","sectionid","exporter","reactive","getExporter","data","renderComponent","newcomponent","newelement","getElement","replaceChild","cmlist","listparent","_fixOrder","sectionlist","container","neworder","allitems","length","remove","itemid","index","item","currentitem","children","append","insertBefore","removeChild","lastChild","getElementById","BaseComponent"],"mappings":"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","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 * Course index main component.\n *\n * @module core_courseformat/local/courseindex/courseindex\n * @class core_courseformat/local/courseindex/courseindex\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent} from 'core/reactive';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\n\nexport default class Component extends BaseComponent {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex';\n // Default query selectors.\n this.selectors = {\n SECTION: `[data-for='section']`,\n SECTION_CMLIST: `[data-for='cmlist']`,\n CM: `[data-for='cm']`,\n TOGGLER: `[data-action=\"togglecourseindexsection\"]`,\n COLLAPSE: `[data-toggle=\"collapse\"]`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n COLLAPSED: `collapsed`,\n };\n // Arrays to keep cms and sections elements.\n this.sections = {};\n this.cms = {};\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n reactive: getCurrentCourseEditor(),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n */\n stateReady() {\n // Activate section togglers.\n this.addEventListener(this.element, 'click', this._setupSectionTogglers);\n\n // Get cms and sections elements.\n const sections = this.getElements(this.selectors.SECTION);\n sections.forEach((section) => {\n this.sections[section.dataset.id] = section;\n });\n const cms = this.getElements(this.selectors.CM);\n cms.forEach((cm) => {\n this.cms[cm.dataset.id] = cm;\n });\n }\n\n getWatchers() {\n return [\n {watch: `cm:created`, handler: this._createCm},\n {watch: `cm:deleted`, handler: this._deleteCm},\n // Sections and cm sorting.\n {watch: `course.sectionlist:updated`, handler: this._refreshCourseSectionlist},\n {watch: `section.cmlist:updated`, handler: this._refreshSectionCmlist},\n ];\n }\n\n /**\n * Setup sections toggler.\n *\n * Toggler click is delegated to the main course index element because new sections can\n * appear at any moment and this way we prevent accidental double bindings.\n *\n * @param {Event} event the triggered event\n */\n _setupSectionTogglers(event) {\n const sectionlink = event.target.closest(this.selectors.TOGGLER);\n if (sectionlink) {\n const toggler = sectionlink.parentNode.querySelector(this.selectors.COLLAPSE);\n if (toggler?.classList.contains(this.classes.COLLAPSED)) {\n toggler.click();\n }\n }\n }\n\n /**\n * Create a newcm instance.\n *\n * @param {Object} details the update details.\n */\n async _createCm({state, element}) {\n // Create a fake node while the component is loading.\n const fakeelement = document.createElement('li');\n fakeelement.classList.add('bg-pulse-grey', 'w-100');\n fakeelement.innerHTML = ' ';\n this.cms[element.id] = fakeelement;\n // Place the fake node on the correct position.\n this._refreshSectionCmlist({\n state,\n element: state.section.get(element.sectionid),\n });\n // Collect render data.\n const exporter = this.reactive.getExporter();\n const data = exporter.cm(state, element);\n // Create the new content.\n const newcomponent = await this.renderComponent(fakeelement, 'core_courseformat/local/courseindex/cm', data);\n // Replace the fake node with the real content.\n const newelement = newcomponent.getElement();\n this.cms[element.id] = newelement;\n fakeelement.parentNode.replaceChild(newelement, fakeelement);\n }\n\n /**\n * Refresh a section cm list.\n *\n * @param {Object} details the update details.\n */\n _refreshSectionCmlist({element}) {\n const cmlist = element.cmlist ?? [];\n const listparent = this.getElement(this.selectors.SECTION_CMLIST, element.id);\n this._fixOrder(listparent, cmlist, this.cms);\n }\n\n /**\n * Refresh the section list.\n *\n * @param {Object} details the update details.\n */\n _refreshCourseSectionlist({element}) {\n const sectionlist = element.sectionlist ?? [];\n this._fixOrder(this.element, sectionlist, this.sections);\n }\n\n /**\n * Fix/reorder the section or cms order.\n *\n * @param {Element} container the HTML element to reorder.\n * @param {Array} neworder an array with the ids order\n * @param {Array} allitems the list of html elements that can be placed in the container\n */\n _fixOrder(container, neworder, allitems) {\n\n // Empty lists should not be visible.\n if (!neworder.length) {\n container.classList.add('hidden');\n container.innerHTML = '';\n return;\n }\n\n // Grant the list is visible (in case it was empty).\n container.classList.remove('hidden');\n\n // Move the elements in order at the beginning of the list.\n neworder.forEach((itemid, index) => {\n const item = allitems[itemid];\n // Get the current element at that position.\n const currentitem = container.children[index];\n if (currentitem === undefined) {\n container.append(item);\n return;\n }\n if (currentitem !== item) {\n container.insertBefore(item, currentitem);\n }\n });\n // Remove the remaining elements.\n while (container.children.length > neworder.length) {\n container.removeChild(container.lastChild);\n }\n }\n\n /**\n * Remove a cm from the list.\n *\n * The actual DOM element removal is delegated to the cm component.\n *\n * @param {Object} details the update details.\n */\n _deleteCm({element}) {\n delete this.cms[element.id];\n }\n}\n"],"file":"courseindex.min.js"} \ No newline at end of file diff --git a/course/format/amd/build/local/courseindex/section.min.js b/course/format/amd/build/local/courseindex/section.min.js index 6f408af9f75..01e5a76b00c 100644 --- a/course/format/amd/build/local/courseindex/section.min.js +++ b/course/format/amd/build/local/courseindex/section.min.js @@ -1,2 +1,2 @@ -define ("core_courseformat/local/courseindex/section",["exports","core_courseformat/local/courseindex/sectiontitle","core_courseformat/local/courseeditor/dndsection"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function g(a){for(var b=1,c;b.\n\n/**\n * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: this.getElement(this.selectors.SECTION_ITEM),\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n}\n"],"file":"section.min.js"} \ No newline at end of file +{"version":3,"sources":["../../../src/local/courseindex/section.js"],"names":["Component","name","selectors","SECTION_ITEM","SECTION_TITLE","CM_LAST","classes","SECTIONHIDDEN","SECTIONCURRENT","id","element","dataset","state","configState","reactive","isEditing","supportComponents","titleitem","SectionTitle","getElement","fullregion","configDragDrop","watch","handler","_refreshSection","sectionitem","classList","toggle","visible","current","DRAGGING","dragging","innerHTML","title","target","document","getElementById","DndSection"],"mappings":"sQA0BA,OACA,O,63EAEqBA,CAAAA,C,+HAKR,CAEL,KAAKC,IAAL,CAAY,qBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,YAAY,4BADC,CAEbC,aAAa,6BAFA,CAGbC,OAAO,+BAHM,CAAjB,CAMA,KAAKC,OAAL,CAAe,CACXC,aAAa,CAAE,QADJ,CAEXC,cAAc,CAAE,SAFL,CAAf,CAMA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,8CAqBUG,C,CAAO,CACd,KAAKC,WAAL,CAAiBD,CAAjB,EAEA,GAAI,KAAKE,QAAL,CAAcC,SAAd,EAA2B,KAAKD,QAAL,CAAcE,iBAA7C,CAAgE,CAE5D,GAAMC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,MACX,IADW,EAEdR,OAAO,CAAE,KAAKS,UAAL,CAAgB,KAAKjB,SAAL,CAAeC,YAA/B,CAFK,CAGdiB,UAAU,CAAE,KAAKV,OAHH,GAAlB,CAKA,KAAKW,cAAL,CAAoBJ,CAApB,CACH,CACJ,C,iDAOa,CACV,MAAO,CACH,CAACK,KAAK,mBAAa,KAAKb,EAAlB,aAAN,CAAuCc,OAAO,CAAE,KAAKC,eAArD,CADG,CAGV,C,6CAOW,CACR,MAAO,MAAKL,UAAL,CAAgB,KAAKjB,SAAL,CAAeG,OAA/B,CACV,C,0DAO0B,OAAVK,CAAU,GAAVA,OAAU,CAEjBe,CAAW,CAAG,KAAKN,UAAL,CAAgB,KAAKjB,SAAL,CAAeC,YAA/B,CAFG,CAGvBsB,CAAW,CAACC,SAAZ,CAAsBC,MAAtB,CAA6B,KAAKrB,OAAL,CAAaC,aAA1C,CAAyD,CAACG,CAAO,CAACkB,OAAlE,EACA,KAAKlB,OAAL,CAAagB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKrB,OAAL,CAAaE,cAA3C,CAA2DE,CAAO,CAACmB,OAAnE,EACA,KAAKnB,OAAL,CAAagB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKrB,OAAL,CAAawB,QAA3C,WAAqDpB,CAAO,CAACqB,QAA7D,oBAEA,KAAKZ,UAAL,CAAgB,KAAKjB,SAAL,CAAeE,aAA/B,EAA8C4B,SAA9C,CAA0DtB,CAAO,CAACuB,KACrE,C,oCA3DWC,C,CAAQhC,C,CAAW,CAC3B,MAAO,IAAIF,CAAAA,CAAJ,CAAc,CACjBU,OAAO,CAAEyB,QAAQ,CAACC,cAAT,CAAwBF,CAAxB,CADQ,CAEjBhC,SAAS,CAATA,CAFiB,CAAd,CAIV,C,cApCkCmC,S","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 * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n };\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: this.getElement(this.selectors.SECTION_ITEM),\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} details the update details.\n */\n _refreshSection({element}) {\n // Update classes.\n const sectionitem = this.getElement(this.selectors.SECTION_ITEM);\n sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n // Update title.\n this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n}\n"],"file":"section.min.js"} \ No newline at end of file diff --git a/course/format/amd/src/local/content/section.js b/course/format/amd/src/local/content/section.js index 929dfbf8416..e7b7b242c71 100644 --- a/course/format/amd/src/local/content/section.js +++ b/course/format/amd/src/local/content/section.js @@ -38,6 +38,11 @@ export default class extends DndSection { SECTION_ITEM: `[data-for='section_title']`, CM: `[data-for="cmitem"]`, }; + // All classes will be loaded later by DndCmItem. + this.classes = {}; + + // We need our id to watch specific events. + this.id = this.element.dataset.id; } /** @@ -63,6 +68,17 @@ export default class extends DndSection { } } + /** + * Component watchers. + * + * @returns {Array} of watchers + */ + getWatchers() { + return [ + {watch: `section[${this.id}]:updated`, handler: this._refreshSection}, + ]; + } + /** * Get the last CM element of that section. * @@ -76,4 +92,14 @@ export default class extends DndSection { } return cms[cms.length - 1]; } -} \ No newline at end of file + + /** + * Update a course index section using the state information. + * + * @param {Object} details the update details. + */ + _refreshSection({element}) { + // Update classes. + this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); + } +} diff --git a/course/format/amd/src/local/content/section/cmitem.js b/course/format/amd/src/local/content/section/cmitem.js index 4bcfe9f46f1..f0aa05f73a5 100644 --- a/course/format/amd/src/local/content/section/cmitem.js +++ b/course/format/amd/src/local/content/section/cmitem.js @@ -38,6 +38,8 @@ export default class extends DndCmItem { this.selectors = { DRAGICON: `.editing_move`, }; + // All classes will be loaded later by DndCmItem. + this.classes = {}; // We need our id to watch specific events. this.id = this.element.dataset.id; } @@ -58,6 +60,17 @@ export default class extends DndCmItem { getWatchers() { return [ {watch: `cm[${this.id}]:deleted`, handler: this.unregister}, + {watch: `cm[${this.id}]:updated`, handler: this._refreshCm}, ]; } + + /** + * Update a course index cm using the state information. + * + * @param {Object} details the update details. + */ + _refreshCm({element}) { + // Update classes. + this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); + } } \ No newline at end of file diff --git a/course/format/amd/src/local/courseeditor/dndcmitem.js b/course/format/amd/src/local/courseeditor/dndcmitem.js index 19e3aef0ca4..4373e4d1ad7 100644 --- a/course/format/amd/src/local/courseeditor/dndcmitem.js +++ b/course/format/amd/src/local/courseeditor/dndcmitem.js @@ -58,6 +58,24 @@ export default class extends BaseComponent { // Drag and drop methods. + /** + * The element drop start hook. + * + * @param {Object} dropdata the dropdata + */ + dragStart(dropdata) { + this.reactive.dispatch('cmDrag', [dropdata.id], true); + } + + /** + * The element drop end hook. + * + * @param {Object} dropdata the dropdata + */ + dragEnd(dropdata) { + this.reactive.dispatch('cmDrag', [dropdata.id], false); + } + /** * Get the draggable data of this component. * diff --git a/course/format/amd/src/local/courseeditor/dndsection.js b/course/format/amd/src/local/courseeditor/dndsection.js index 9d6568f8989..581673965e8 100644 --- a/course/format/amd/src/local/courseeditor/dndsection.js +++ b/course/format/amd/src/local/courseeditor/dndsection.js @@ -80,6 +80,24 @@ export default class extends BaseComponent { // Drag and drop methods. + /** + * The element drop start hook. + * + * @param {Object} dropdata the dropdata + */ + dragStart(dropdata) { + this.reactive.dispatch('sectionDrag', [dropdata.id], true); + } + + /** + * The element drop end hook. + * + * @param {Object} dropdata the dropdata + */ + dragEnd(dropdata) { + this.reactive.dispatch('sectionDrag', [dropdata.id], false); + } + /** * Validate if the drop data can be dropped over the component. * diff --git a/course/format/amd/src/local/courseeditor/dndsectionitem.js b/course/format/amd/src/local/courseeditor/dndsectionitem.js index 850c6e5c93a..0f07c4609e9 100644 --- a/course/format/amd/src/local/courseeditor/dndsectionitem.js +++ b/course/format/amd/src/local/courseeditor/dndsectionitem.js @@ -73,6 +73,24 @@ export default class extends BaseComponent { // Drag and drop methods. + /** + * The element drop start hook. + * + * @param {Object} dropdata the dropdata + */ + dragStart(dropdata) { + this.reactive.dispatch('sectionDrag', [dropdata.id], true); + } + + /** + * The element end start hook. + * + * @param {Object} dropdata the dropdata + */ + dragEnd(dropdata) { + this.reactive.dispatch('sectionDrag', [dropdata.id], false); + } + /** * Get the draggable data of this component. * diff --git a/course/format/amd/src/local/courseeditor/mutations.js b/course/format/amd/src/local/courseeditor/mutations.js index 6b431d6e126..feecf413d16 100644 --- a/course/format/amd/src/local/courseeditor/mutations.js +++ b/course/format/amd/src/local/courseeditor/mutations.js @@ -96,6 +96,39 @@ export default class { stateManager.processUpdates(updates); } + /** + * Mark or unmark course modules as dragging. + * + * @param {StateManager} stateManager the current state manager + * @param {array} cmIds the list of course modules ids + * @param {bool} dragValue the new dragging value + */ + cmDrag(stateManager, cmIds, dragValue) { + this._setElementsValue(stateManager, 'cm', cmIds, 'dragging', dragValue); + } + + /** + * Mark or unmark course sections as dragging. + * + * @param {StateManager} stateManager the current state manager + * @param {array} sectionIds the list of section ids + * @param {bool} dragValue the new dragging value + */ + sectionDrag(stateManager, sectionIds, dragValue) { + this._setElementsValue(stateManager, 'section', sectionIds, 'dragging', dragValue); + } + + _setElementsValue(stateManager, name, ids, fieldName, newValue) { + stateManager.setReadOnly(false); + ids.forEach((id) => { + const element = stateManager.get(name, id); + if (element) { + element[fieldName] = newValue; + } + }); + stateManager.setReadOnly(true); + } + /** * Get updated state data related to some cm ids. * diff --git a/course/format/amd/src/local/courseindex/cm.js b/course/format/amd/src/local/courseindex/cm.js index f0e8b8cf5fb..a147a7e99f3 100644 --- a/course/format/amd/src/local/courseindex/cm.js +++ b/course/format/amd/src/local/courseindex/cm.js @@ -34,6 +34,14 @@ export default class Component extends DndCmItem { create() { // Optional component name for debugging. this.name = 'courseindex_cm'; + // Default query selectors. + this.selectors = { + CM_NAME: `[data-for='cm_name']`, + }; + // Default classes to toggle on refresh. + this.classes = { + CMHIDDEN: 'dimmed', + }; // We need our id to watch specific events. this.id = this.element.dataset.id; } @@ -67,7 +75,20 @@ export default class Component extends DndCmItem { getWatchers() { return [ {watch: `cm[${this.id}]:deleted`, handler: this.remove}, + {watch: `cm[${this.id}]:updated`, handler: this._refreshCm}, ]; } + /** + * Update a course index cm using the state information. + * + * @param {Object} details the update details. + */ + _refreshCm({element}) { + // Update classes. + this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible); + this.getElement(this.selectors.CM_NAME).innerHTML = element.name; + this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); + } + } diff --git a/course/format/amd/src/local/courseindex/courseindex.js b/course/format/amd/src/local/courseindex/courseindex.js index 28dfd18387f..909c3b0eee3 100644 --- a/course/format/amd/src/local/courseindex/courseindex.js +++ b/course/format/amd/src/local/courseindex/courseindex.js @@ -36,19 +36,13 @@ export default class Component extends BaseComponent { // Default query selectors. this.selectors = { SECTION: `[data-for='section']`, - SECTION_ITEM: `[data-for='section_item']`, - SECTION_TITLE: `[data-for='section_title']`, SECTION_CMLIST: `[data-for='cmlist']`, CM: `[data-for='cm']`, - CM_NAME: `[data-for='cm_name']`, TOGGLER: `[data-action="togglecourseindexsection"]`, COLLAPSE: `[data-toggle="collapse"]`, }; // Default classes to toggle on refresh. this.classes = { - SECTIONHIDDEN: 'dimmed', - CMHIDDEN: 'dimmed', - SECTIONCURRENT: 'current', COLLAPSED: `collapsed`, }; // Arrays to keep cms and sections elements. @@ -91,8 +85,6 @@ export default class Component extends BaseComponent { getWatchers() { return [ - {watch: `section:updated`, handler: this._refreshSection}, - {watch: `cm:updated`, handler: this._refreshCm}, {watch: `cm:created`, handler: this._createCm}, {watch: `cm:deleted`, handler: this._deleteCm}, // Sections and cm sorting. @@ -119,41 +111,6 @@ export default class Component extends BaseComponent { } } - /** - * Update a course index section using the state information. - * - * @param {Object} details the update details. - */ - _refreshSection({element}) { - // Find the element. - const target = this.sections[element.id]; - if (!target) { - throw new Error(`Unkown section with ID ${element.id}`); - } - // Update classes. - const sectionitem = target.querySelector(this.selectors.SECTION_ITEM); - sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible); - target.classList.toggle(this.classes.SECTIONCURRENT, element.current); - // Update title. - target.querySelector(this.selectors.SECTION_TITLE).innerHTML = element.title; - } - - /** - * Update a course index cm using the state information. - * - * @param {Object} details the update details. - */ - _refreshCm({element}) { - // Find the element. - const target = this.cms[element.id]; - if (!target) { - throw new Error(`Unkown course module with ID ${element.id}`); - } - // Update classes. - target.classList.toggle(this.classes.CMHIDDEN, !element.visible); - target.querySelector(this.selectors.CM_NAME).innerHTML = element.name; - } - /** * Create a newcm instance. * diff --git a/course/format/amd/src/local/courseindex/section.js b/course/format/amd/src/local/courseindex/section.js index 98b1a48205f..354d65d3ddb 100644 --- a/course/format/amd/src/local/courseindex/section.js +++ b/course/format/amd/src/local/courseindex/section.js @@ -38,8 +38,17 @@ export default class Component extends DndSection { // Default query selectors. this.selectors = { SECTION_ITEM: `[data-for='section_item']`, + SECTION_TITLE: `[data-for='section_title']`, CM_LAST: `[data-for="cm"]:last-child`, }; + // Default classes to toggle on refresh. + this.classes = { + SECTIONHIDDEN: 'dimmed', + SECTIONCURRENT: 'current', + }; + + // We need our id to watch specific events. + this.id = this.element.dataset.id; } /** @@ -75,6 +84,17 @@ export default class Component extends DndSection { } } + /** + * Component watchers. + * + * @returns {Array} of watchers + */ + getWatchers() { + return [ + {watch: `section[${this.id}]:updated`, handler: this._refreshSection}, + ]; + } + /** * Get the last CM element of that section. * @@ -83,4 +103,19 @@ export default class Component extends DndSection { getLastCm() { return this.getElement(this.selectors.CM_LAST); } + + /** + * Update a course index section using the state information. + * + * @param {Object} details the update details. + */ + _refreshSection({element}) { + // Update classes. + const sectionitem = this.getElement(this.selectors.SECTION_ITEM); + sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible); + this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current); + this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false); + // Update title. + this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title; + } }