From a412d569e9516f1f7cb22f82558c3ec4fc583b19 Mon Sep 17 00:00:00 2001 From: Matt Davidson Date: Fri, 13 Dec 2024 16:50:53 -0500 Subject: [PATCH] Moodle 4.5 compatibility changes Add support for subsections. --- amd/build/checkboxmanager.min.js | 2 +- amd/build/checkboxmanager.min.js.map | 2 +- amd/build/massactionblock.min.js | 2 +- amd/build/massactionblock.min.js.map | 2 +- amd/src/checkboxmanager.js | 58 ++++++++++++++++++++++------ amd/src/massactionblock.js | 1 - version.php | 1 + 7 files changed, 52 insertions(+), 16 deletions(-) diff --git a/amd/build/checkboxmanager.min.js b/amd/build/checkboxmanager.min.js index f4d96c5..54f1129 100644 --- a/amd/build/checkboxmanager.min.js +++ b/amd/build/checkboxmanager.min.js @@ -7,6 +7,6 @@ define("block_massaction/checkboxmanager",["exports","core/templates","core/noti * @copyright 2022 ISB Bayern * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setSectionSelection=_exports.initCheckboxManager=_exports.getSelectedModIds=void 0,_templates=_interopRequireDefault(_templates),_events=_interopRequireDefault(_events);let localStateUpdating=!1,sectionsChanged=!1,sections=[],moduleNames=[];const sectionBoxes={};_exports.initCheckboxManager=()=>{const courseEditor=(0,_courseeditor.getCurrentCourseEditor)(),eventsToListen_SECTION_UPDATED="section:updated",eventsToListen_CHANGE_FINISHED="transaction:end";courseEditor.stateManager.target.addEventListener(_events.default.stateChanged,(event=>{event.detail.action===eventsToListen_SECTION_UPDATED&&(sectionsChanged=!0),event.detail.action===eventsToListen_CHANGE_FINISHED&&rebuildLocalState()})),sectionsChanged=!0,rebuildLocalState()};const rebuildLocalState=()=>{if(localStateUpdating)return;localStateUpdating=!0;const courseEditor=(0,_courseeditor.getCurrentCourseEditor)();sections=[];for(const prop of Object.getOwnPropertyNames(sectionBoxes))delete sectionBoxes[prop];sections=[...courseEditor.stateManager.state.section.values()].sort(((a,b)=>a.number>b.number?1:-1)),moduleNames=[...courseEditor.stateManager.state.cm.values()];const sectionsUnfiltered=sections;sections=filterVisibleSections(sections),updateSelectionAndMoveToDropdowns(sections,sectionsUnfiltered),addCheckboxesToDataStructure(),localStateUpdating=!1};_exports.getSelectedModIds=()=>{const moduleIds=[];for(let sectionNumber in sectionBoxes)for(let i=0;i{const boxIds=[];if(void 0===sectionNumber||sectionNumber!==_massactionblock.constants.SECTION_SELECT_DESCRIPTION_VALUE){if(void 0!==sectionNumber&§ionNumber===_massactionblock.constants.SECTION_NUMBER_ALL_PLACEHOLDER)for(const sectionId in sectionBoxes)for(let j=0;jboxIds.push(box.boxId)));for(let i=0;i{sections.forEach((section=>{sectionBoxes[section.number]=[];const moduleIds=section.cmlist;if(moduleIds&&moduleIds.length>0&&""!==moduleIds[0]){moduleNames.filter((modinfo=>moduleIds.includes(modinfo.id.toString()))).forEach((modinfo=>{const boxId=_massactionblock.usedMoodleCssClasses.BOX_ID_PREFIX+modinfo.id.toString();sectionBoxes[section.number].push({moduleId:modinfo.id.toString(),boxId:boxId})}))}}))},filterVisibleSections=sections=>sections.filter((section=>0!==section.cmlist.length)).filter((section=>section.cmlist.every((moduleid=>null!==document.getElementById(_massactionblock.usedMoodleCssClasses.MODULE_ID_PREFIX+moduleid))))),updateSelectionAndMoveToDropdowns=(sections,sectionsUnfiltered)=>{sectionsChanged?(_templates.default.renderForPromise("block_massaction/section_select",{sections:sectionsUnfiltered}).then((_ref=>{let{html:html,js:js}=_ref;return _templates.default.replaceNode("#"+_massactionblock.cssIds.SECTION_SELECT,html,js),disableInvisibleAndEmptySections(sections),document.getElementById(_massactionblock.cssIds.SECTION_SELECT).addEventListener("change",(event=>setSectionSelection(!0,event.target.value)),!1),!0})).catch((ex=>(0,_notification.exception)(ex))),_templates.default.renderForPromise("block_massaction/moveto_select",{sections:sectionsUnfiltered}).then((_ref2=>{let{html:html,js:js}=_ref2;return _templates.default.replaceNode("#"+_massactionblock.cssIds.MOVETO_SELECT,html,js),disableUnavailableSections(_massactionblock.cssIds.MOVETO_SELECT),!0})).catch((ex=>(0,_notification.exception)(ex))),_templates.default.renderForPromise("block_massaction/duplicateto_select",{sections:sectionsUnfiltered}).then((_ref3=>{let{html:html,js:js}=_ref3;return _templates.default.replaceNode("#"+_massactionblock.cssIds.DUPLICATETO_SELECT,html,js),disableUnavailableSections(_massactionblock.cssIds.DUPLICATETO_SELECT),!0})).catch((ex=>(0,_notification.exception)(ex)))):disableInvisibleAndEmptySections(sections),sectionsChanged=!1},disableInvisibleAndEmptySections=sections=>{Array.prototype.forEach.call(document.getElementById(_massactionblock.cssIds.SECTION_SELECT).options,(option=>{option.value===_massactionblock.constants.SECTION_SELECT_DESCRIPTION_VALUE||sections.some((section=>parseInt(option.value)===section.number))?option.disabled=!1:option.disabled=!0}))},disableUnavailableSections=elementId=>{if(null!==document.getElementById(elementId)){const sectionsAvailableInfo=document.querySelector(_massactionblock.cssIds.SECTION_FILTER_DATA).dataset.availabletargetsections,sectionsAvailable=Array.prototype.map.call(sectionsAvailableInfo.split(","),(sectionnum=>parseInt(sectionnum)));Array.prototype.forEach.call(document.getElementById(elementId).options,(option=>{sectionsAvailable.includes(parseInt(option.value))?option.disabled=!1:option.disabled=!0}))}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setSectionSelection=_exports.initCheckboxManager=_exports.getTitleOfSection=_exports.getSelectedModIds=void 0,_templates=_interopRequireDefault(_templates),_events=_interopRequireDefault(_events);let localStateUpdating=!1,sectionsChanged=!1,sections=[],moduleNames=[];const sectionBoxes={};_exports.initCheckboxManager=()=>{const courseEditor=(0,_courseeditor.getCurrentCourseEditor)(),eventsToListen_SECTION_UPDATED="section:updated",eventsToListen_CHANGE_FINISHED="transaction:end";courseEditor.stateManager.target.addEventListener(_events.default.stateChanged,(event=>{event.detail.action===eventsToListen_SECTION_UPDATED&&(sectionsChanged=!0),event.detail.action===eventsToListen_CHANGE_FINISHED&&rebuildLocalState()})),sectionsChanged=!0,rebuildLocalState()};const rebuildLocalState=()=>{if(localStateUpdating)return;localStateUpdating=!0;for(const prop of Object.getOwnPropertyNames(sectionBoxes))delete sectionBoxes[prop];const courseEditor=(0,_courseeditor.getCurrentCourseEditor)(),state=courseEditor.stateManager.state,courseItems=courseEditor.getExporter().allItemsArray(state);sections=[],courseItems.forEach((item=>{if("section"===item.type){let sectioninfo={...state.section.get(item.id)};sectioninfo.title=getTitleOfSection(sectioninfo),sections.push(sectioninfo)}})),moduleNames=[...courseEditor.stateManager.state.cm.values()];const sectionsUnfiltered=sections;sections=filterVisibleSections(sections),updateSelectionAndMoveToDropdowns(sections,sectionsUnfiltered),addCheckboxesToDataStructure(),localStateUpdating=!1},getTitleOfSection=section=>{let title=section.title;return"mod_subsection"===section.component&&(title=" - "+title),title};_exports.getTitleOfSection=getTitleOfSection;_exports.getSelectedModIds=()=>{const moduleIds=[];for(let sectionNumber in sectionBoxes)for(let i=0;i{const boxIds=[];if(void 0===sectionNumber||sectionNumber!==_massactionblock.constants.SECTION_SELECT_DESCRIPTION_VALUE){if(void 0!==sectionNumber&§ionNumber===_massactionblock.constants.SECTION_NUMBER_ALL_PLACEHOLDER)for(const sectionId in sectionBoxes)for(let j=0;jboxIds.push(box.boxId)));for(let i=0;i{sections.forEach((section=>{sectionBoxes[section.number]=[];const moduleIds=section.cmlist;if(moduleIds&&moduleIds.length>0&&""!==moduleIds[0]){moduleNames.filter((modinfo=>moduleIds.includes(modinfo.id.toString()))).forEach((modinfo=>{if("subsection"!==modinfo.module){const boxId=_massactionblock.usedMoodleCssClasses.BOX_ID_PREFIX+modinfo.id.toString();sectionBoxes[section.number].push({moduleId:modinfo.id.toString(),boxId:boxId})}}))}}))},filterVisibleSections=sections=>sections.filter((section=>0!==section.cmlist.length)).filter((section=>section.cmlist.every((moduleid=>null!==document.getElementById(_massactionblock.usedMoodleCssClasses.MODULE_ID_PREFIX+moduleid))))),updateSelectionAndMoveToDropdowns=(sections,sectionsUnfiltered)=>{sectionsChanged?(_templates.default.renderForPromise("block_massaction/section_select",{sections:sectionsUnfiltered}).then((_ref=>{let{html:html,js:js}=_ref;return _templates.default.replaceNode("#"+_massactionblock.cssIds.SECTION_SELECT,html,js),disableInvisibleAndEmptySections(sections),document.getElementById(_massactionblock.cssIds.SECTION_SELECT).addEventListener("change",(event=>setSectionSelection(!0,event.target.value)),!1),!0})).catch((ex=>(0,_notification.exception)(ex))),_templates.default.renderForPromise("block_massaction/moveto_select",{sections:sectionsUnfiltered}).then((_ref2=>{let{html:html,js:js}=_ref2;return _templates.default.replaceNode("#"+_massactionblock.cssIds.MOVETO_SELECT,html,js),disableUnavailableSections(_massactionblock.cssIds.MOVETO_SELECT),!0})).catch((ex=>(0,_notification.exception)(ex))),_templates.default.renderForPromise("block_massaction/duplicateto_select",{sections:sectionsUnfiltered}).then((_ref3=>{let{html:html,js:js}=_ref3;return _templates.default.replaceNode("#"+_massactionblock.cssIds.DUPLICATETO_SELECT,html,js),disableUnavailableSections(_massactionblock.cssIds.DUPLICATETO_SELECT),!0})).catch((ex=>(0,_notification.exception)(ex)))):disableInvisibleAndEmptySections(sections),sectionsChanged=!1},disableInvisibleAndEmptySections=sections=>{Array.prototype.forEach.call(document.getElementById(_massactionblock.cssIds.SECTION_SELECT).options,(option=>{option.value===_massactionblock.constants.SECTION_SELECT_DESCRIPTION_VALUE||sections.some((section=>parseInt(option.value)===section.number))?option.disabled=!1:option.disabled=!0}))},disableUnavailableSections=elementId=>{if(null!==document.getElementById(elementId)){const sectionsAvailableInfo=document.querySelector(_massactionblock.cssIds.SECTION_FILTER_DATA).dataset.availabletargetsections,sectionsAvailable=Array.prototype.map.call(sectionsAvailableInfo.split(","),(sectionnum=>parseInt(sectionnum)));Array.prototype.forEach.call(document.getElementById(elementId).options,(option=>{sectionsAvailable.includes(parseInt(option.value))?option.disabled=!1:option.disabled=!0}))}}})); //# sourceMappingURL=checkboxmanager.min.js.map \ No newline at end of file diff --git a/amd/build/checkboxmanager.min.js.map b/amd/build/checkboxmanager.min.js.map index f4e4a96..1cf8eec 100644 --- a/amd/build/checkboxmanager.min.js.map +++ b/amd/build/checkboxmanager.min.js.map @@ -1 +1 @@ -{"version":3,"file":"checkboxmanager.min.js","sources":["../src/checkboxmanager.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Checkbox manager amd module: Adds checkboxes to the activities for selecting and\n * generates a data structure of the activities and checkboxes.\n *\n * @module block_massaction/checkboxmanager\n * @copyright 2022 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport {exception as displayException} from 'core/notification';\nimport {cssIds, constants, usedMoodleCssClasses} from './massactionblock';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport events from 'core_course/events';\n\nlet localStateUpdating = false;\nlet sectionsChanged = false;\nlet sections = [];\nlet moduleNames = [];\n\n/* A registry of checkbox IDs, of the format:\n * 'section_number' => [{'moduleId' : ,\n * 'boxId' : }]\n */\nconst sectionBoxes = {};\n\n/**\n * The checkbox manager takes a given 'sections' data structure object and inserts a checkbox for each of the given\n * course modules in this data object into the DOM.\n * The checkbox manager returns another data object containing the ids of the added checkboxes.\n */\nexport const initCheckboxManager = () => {\n const courseEditor = getCurrentCourseEditor();\n\n const eventsToListen = {\n SECTION_UPDATED: 'section:updated',\n CHANGE_FINISHED: 'transaction:end'\n };\n\n courseEditor.stateManager.target.addEventListener(events.stateChanged, (event) => {\n if (event.detail.action === eventsToListen.SECTION_UPDATED) {\n // Listen to section updated events. We do not want to immediately react to the event, but wait for\n // everything to finish updating.\n sectionsChanged = true;\n }\n if (event.detail.action === eventsToListen.CHANGE_FINISHED) {\n // Before every change to the state there is a transaction:start event. After the change is being commited,\n // we receive an transaction:end event. That is the point we want to react to changes of the state.\n rebuildLocalState();\n }\n });\n // Trigger rendering of sections dropdowns a first time.\n sectionsChanged = true;\n // Get initial state.\n rebuildLocalState();\n};\n\n/**\n * This method rebuilds the local state maintained in this module based on the course editor state.\n *\n * It will be called whenever a change to the courseeditor state is being detected.\n */\nconst rebuildLocalState = () => {\n if (localStateUpdating) {\n return;\n }\n localStateUpdating = true;\n const courseEditor = getCurrentCourseEditor();\n\n // First we rebuild our data structures depending on the course editor state.\n sections = [];\n for (const prop of Object.getOwnPropertyNames(sectionBoxes)) {\n delete sectionBoxes[prop];\n }\n // The section map object is being sorted by section id. We have to sort after order in this course.\n sections = [...courseEditor.stateManager.state.section.values()].sort((a, b) => a.number > b.number ? 1 : -1);\n moduleNames = [...courseEditor.stateManager.state.cm.values()];\n\n // Now we use the new information to rebuild dropdowns and re-apply checkboxes.\n const sectionsUnfiltered = sections;\n sections = filterVisibleSections(sections);\n updateSelectionAndMoveToDropdowns(sections, sectionsUnfiltered);\n addCheckboxesToDataStructure();\n localStateUpdating = false;\n};\n\n/**\n * Returns the currently selected module ids.\n *\n * @returns {[]} Array of module ids currently being selected\n */\nexport const getSelectedModIds = () => {\n const moduleIds = [];\n for (let sectionNumber in sectionBoxes) {\n for (let i = 0; i < sectionBoxes[sectionNumber].length; i++) {\n const checkbox = document.getElementById(sectionBoxes[sectionNumber][i].boxId);\n if (checkbox.checked) {\n moduleIds.push(sectionBoxes[sectionNumber][i].moduleId);\n }\n }\n }\n return moduleIds;\n};\n\n/**\n * Select all module checkboxes in section(s).\n *\n * @param {boolean} value the checked value to set the checkboxes to\n * @param {string} sectionNumber the section number of the section which all modules should be checked/unchecked. Use \"all\" to\n * select/deselect modules in all sections.\n */\nexport const setSectionSelection = (value, sectionNumber) => {\n const boxIds = [];\n\n if (typeof sectionNumber !== 'undefined' && sectionNumber === constants.SECTION_SELECT_DESCRIPTION_VALUE) {\n // Description placeholder has been selected, do nothing.\n return;\n } else if (typeof sectionNumber !== 'undefined' && sectionNumber === constants.SECTION_NUMBER_ALL_PLACEHOLDER) {\n // See if we are toggling all sections.\n for (const sectionId in sectionBoxes) {\n for (let j = 0; j < sectionBoxes[sectionId].length; j++) {\n boxIds.push(sectionBoxes[sectionId][j].boxId);\n }\n }\n } else {\n // We select all boxes of the given section.\n sectionBoxes[sectionNumber].forEach(box => boxIds.push(box.boxId));\n }\n // Un/check the boxes.\n for (let i = 0; i < boxIds.length; i++) {\n document.getElementById(boxIds[i]).checked = value;\n }\n // Reset dropdown to standard placeholder so we trigger a change event when selecting a section, then deselecting\n // everything and again select the same section.\n document.getElementById(cssIds.SECTION_SELECT).value = constants.SECTION_SELECT_DESCRIPTION_VALUE;\n};\n\n/**\n * Scan all available checkboxes and add them to the data structure.\n */\nconst addCheckboxesToDataStructure = () => {\n sections.forEach(section => {\n sectionBoxes[section.number] = [];\n const moduleIds = section.cmlist;\n if (moduleIds && moduleIds.length > 0 && moduleIds[0] !== '') {\n const moduleNamesFiltered = moduleNames.filter(modinfo => moduleIds.includes(modinfo.id.toString()));\n moduleNamesFiltered.forEach(modinfo => {\n // Checkbox should already be created by moodle massactions. Just add it to our data structure.\n const boxId = usedMoodleCssClasses.BOX_ID_PREFIX + modinfo.id.toString();\n sectionBoxes[section.number].push({\n 'moduleId': modinfo.id.toString(),\n 'boxId': boxId,\n });\n });\n }\n });\n};\n\n/**\n * Filter the sections data object depending on the visibility of the course modules contained in\n * the data object. This is necessary, because some course formats only show specific section(s)\n * in editing mode.\n *\n * @param {[]} sections the sections data object\n * @returns {[]} the filtered sections object\n */\nconst filterVisibleSections = (sections) => {\n // Filter all sections with modules which no checkboxes have been created for.\n // This case should only occur in course formats where some sections are hidden.\n return sections.filter(section => section.cmlist.length !== 0)\n .filter(section => section.cmlist\n .every(moduleid => document.getElementById(usedMoodleCssClasses.MODULE_ID_PREFIX + moduleid) !== null));\n};\n\n/**\n * Update the selection, moveto and duplicateto dropdowns of the massaction block according to the\n * previously filtered sections.\n *\n * This method also has to be called whenever there is a module change event (moving around, adding file by Drag&Drop etc.).\n *\n * @param {[]} sections the sections object filtered before by {@link filterVisibleSections}\n * @param {[]} sectionsUnfiltered the same data object as 'sections', but still containing all sections\n */\nconst updateSelectionAndMoveToDropdowns = (sections, sectionsUnfiltered) => {\n if (sectionsChanged) {\n Templates.renderForPromise('block_massaction/section_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.SECTION_SELECT, html, js);\n disableInvisibleAndEmptySections(sections);\n // Re-register event listener.\n document.getElementById(cssIds.SECTION_SELECT).addEventListener('change',\n (event) => setSectionSelection(true, event.target.value), false);\n return true;\n })\n .catch(ex => displayException(ex));\n\n Templates.renderForPromise('block_massaction/moveto_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.MOVETO_SELECT, html, js);\n disableUnavailableSections(cssIds.MOVETO_SELECT);\n return true;\n })\n .catch(ex => displayException(ex));\n\n Templates.renderForPromise('block_massaction/duplicateto_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.DUPLICATETO_SELECT, html, js);\n disableUnavailableSections(cssIds.DUPLICATETO_SELECT);\n return true;\n })\n .catch(ex => displayException(ex));\n } else {\n // If there has not been an event about a section change we do not have to rebuild the sections dropdowns.\n // However, there is a chance a section is being emptied or not empty anymore due to drag&dropping of modules.\n // So we have to recalculate if we have to enable/disable the sections.\n disableInvisibleAndEmptySections(sections);\n }\n // Reset the flag.\n sectionsChanged = false;\n};\n\n/**\n * Sets the disabled/enabled status of sections in the section select dropdown:\n * Enabled if section is visible and contains modules.\n * Disabled if section is not visible or doesn't contain any modules.\n *\n * @param {[]} sections the section data structure\n */\nconst disableInvisibleAndEmptySections = (sections) => {\n Array.prototype.forEach.call(document.getElementById(cssIds.SECTION_SELECT).options, option => {\n // Disable every element which doesn't have a visible section, except the placeholder ('description').\n if (option.value !== constants.SECTION_SELECT_DESCRIPTION_VALUE\n && !sections.some(section => parseInt(option.value) === section.number)) {\n option.disabled = true;\n } else {\n option.disabled = false;\n }\n });\n};\n\n/**\n * Sets the disabled/enabled status of sections in the section select dropdown:\n * Disabled if the section is not available due to some restrictions in block_massaction itself (provided by hooks).\n *\n * @param {string} elementId elementId to apply the restriction\n */\nconst disableUnavailableSections = (elementId) => {\n if (document.getElementById(elementId) !== null) {\n const sectionsAvailableInfo = document.querySelector(cssIds.SECTION_FILTER_DATA).dataset.availabletargetsections;\n const sectionsAvailable = Array.prototype.map.call(sectionsAvailableInfo.split(','), (sectionnum) => parseInt(sectionnum));\n Array.prototype.forEach.call(document.getElementById(elementId).options, option => {\n // Disable every element which is not in the sectionsAvailable list.\n if (sectionsAvailable.includes(parseInt(option.value))) {\n option.disabled = false;\n } else {\n option.disabled = true;\n }\n });\n }\n};\n"],"names":["localStateUpdating","sectionsChanged","sections","moduleNames","sectionBoxes","courseEditor","eventsToListen","stateManager","target","addEventListener","events","stateChanged","event","detail","action","rebuildLocalState","prop","Object","getOwnPropertyNames","state","section","values","sort","a","b","number","cm","sectionsUnfiltered","filterVisibleSections","updateSelectionAndMoveToDropdowns","addCheckboxesToDataStructure","moduleIds","sectionNumber","i","length","document","getElementById","boxId","checked","push","moduleId","setSectionSelection","value","boxIds","constants","SECTION_SELECT_DESCRIPTION_VALUE","SECTION_NUMBER_ALL_PLACEHOLDER","sectionId","j","forEach","box","cssIds","SECTION_SELECT","cmlist","filter","modinfo","includes","id","toString","usedMoodleCssClasses","BOX_ID_PREFIX","every","moduleid","MODULE_ID_PREFIX","renderForPromise","then","_ref","html","js","replaceNode","disableInvisibleAndEmptySections","catch","ex","_ref2","MOVETO_SELECT","disableUnavailableSections","_ref3","DUPLICATETO_SELECT","Array","prototype","call","options","option","some","parseInt","disabled","elementId","sectionsAvailableInfo","querySelector","SECTION_FILTER_DATA","dataset","availabletargetsections","sectionsAvailable","map","split","sectionnum"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"checkboxmanager.min.js","sources":["../src/checkboxmanager.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Checkbox manager amd module: Adds checkboxes to the activities for selecting and\n * generates a data structure of the activities and checkboxes.\n *\n * @module block_massaction/checkboxmanager\n * @copyright 2022 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport {exception as displayException} from 'core/notification';\nimport {cssIds, constants, usedMoodleCssClasses} from './massactionblock';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport events from 'core_course/events';\n\nlet localStateUpdating = false;\nlet sectionsChanged = false;\nlet sections = [];\nlet moduleNames = [];\n\n/* A registry of checkbox IDs, of the format:\n * 'section_number' => [{'moduleId' : ,\n * 'boxId' : }]\n */\nconst sectionBoxes = {};\n\n/**\n * The checkbox manager takes a given 'sections' data structure object and inserts a checkbox for each of the given\n * course modules in this data object into the DOM.\n * The checkbox manager returns another data object containing the ids of the added checkboxes.\n */\nexport const initCheckboxManager = () => {\n const courseEditor = getCurrentCourseEditor();\n\n const eventsToListen = {\n SECTION_UPDATED: 'section:updated',\n CHANGE_FINISHED: 'transaction:end'\n };\n\n courseEditor.stateManager.target.addEventListener(events.stateChanged, (event) => {\n if (event.detail.action === eventsToListen.SECTION_UPDATED) {\n // Listen to section updated events. We do not want to immediately react to the event, but wait for\n // everything to finish updating.\n sectionsChanged = true;\n }\n if (event.detail.action === eventsToListen.CHANGE_FINISHED) {\n // Before every change to the state there is a transaction:start event. After the change is being commited,\n // we receive an transaction:end event. That is the point we want to react to changes of the state.\n rebuildLocalState();\n }\n });\n // Trigger rendering of sections dropdowns a first time.\n sectionsChanged = true;\n // Get initial state.\n rebuildLocalState();\n};\n\n/**\n * This method rebuilds the local state maintained in this module based on the course editor state.\n *\n * It will be called whenever a change to the courseeditor state is being detected.\n */\nconst rebuildLocalState = () => {\n if (localStateUpdating) {\n return;\n }\n localStateUpdating = true;\n\n // First we rebuild our data structures depending on the course editor state.\n for (const prop of Object.getOwnPropertyNames(sectionBoxes)) {\n delete sectionBoxes[prop];\n }\n\n const courseEditor = getCurrentCourseEditor();\n const state = courseEditor.stateManager.state;\n const exporter = courseEditor.getExporter();\n\n // Get all modules, sections and subsections in display order.\n const courseItems = exporter.allItemsArray(state);\n\n // Build sections array.\n sections = [];\n courseItems.forEach(item => {\n if (item.type === 'section') {\n // Get section info.\n let sectioninfo = {...state.section.get(item.id)};\n // Rename subsections for display purposes.\n sectioninfo.title = getTitleOfSection(sectioninfo);\n sections.push(sectioninfo);\n }\n });\n\n // Get all module names and parameters.\n moduleNames = [...courseEditor.stateManager.state.cm.values()];\n\n // Now we use the new information to rebuild dropdowns and re-apply checkboxes.\n const sectionsUnfiltered = sections;\n sections = filterVisibleSections(sections);\n updateSelectionAndMoveToDropdowns(sections, sectionsUnfiltered);\n addCheckboxesToDataStructure();\n localStateUpdating = false;\n};\n\n/**\n * Returns the title of a given section.\n * If the section is a subsection, a prefix with a dash is added.\n *\n * @param {Object} section the section object from the course editor\n * @returns {string} title of the section object corrected for subsections\n */\nexport const getTitleOfSection = (section) => {\n let title = section.title;\n if (section.component === 'mod_subsection') {\n title = ' - ' + title;\n }\n return title;\n};\n\n/**\n * Returns the currently selected module ids.\n *\n * @returns {[]} Array of module ids currently being selected\n */\nexport const getSelectedModIds = () => {\n const moduleIds = [];\n for (let sectionNumber in sectionBoxes) {\n for (let i = 0; i < sectionBoxes[sectionNumber].length; i++) {\n const checkbox = document.getElementById(sectionBoxes[sectionNumber][i].boxId);\n if (checkbox.checked) {\n moduleIds.push(sectionBoxes[sectionNumber][i].moduleId);\n }\n }\n }\n\n return moduleIds;\n};\n\n/**\n * Select all module checkboxes in section(s).\n *\n * @param {boolean} value the checked value to set the checkboxes to\n * @param {string} sectionNumber the section number of the section which all modules should be checked/unchecked. Use \"all\" to\n * select/deselect modules in all sections.\n */\nexport const setSectionSelection = (value, sectionNumber) => {\n const boxIds = [];\n if (typeof sectionNumber !== 'undefined' && sectionNumber === constants.SECTION_SELECT_DESCRIPTION_VALUE) {\n // Description placeholder has been selected, do nothing.\n return;\n } else if (typeof sectionNumber !== 'undefined' && sectionNumber === constants.SECTION_NUMBER_ALL_PLACEHOLDER) {\n // See if we are toggling all sections.\n for (const sectionId in sectionBoxes) {\n for (let j = 0; j < sectionBoxes[sectionId].length; j++) {\n boxIds.push(sectionBoxes[sectionId][j].boxId);\n }\n }\n } else {\n // We select all boxes of the given section.\n sectionBoxes[sectionNumber].forEach(box => boxIds.push(box.boxId));\n }\n\n // Un/check the boxes.\n for (let i = 0; i < boxIds.length; i++) {\n document.getElementById(boxIds[i]).checked = value;\n }\n // Reset dropdown to standard placeholder so we trigger a change event when selecting a section, then deselecting\n // everything and again select the same section.\n document.getElementById(cssIds.SECTION_SELECT).value = constants.SECTION_SELECT_DESCRIPTION_VALUE;\n};\n\n/**\n * Scan all available checkboxes and add them to the data structure.\n */\nconst addCheckboxesToDataStructure = () => {\n sections.forEach(section => {\n sectionBoxes[section.number] = [];\n const moduleIds = section.cmlist;\n\n if (moduleIds && moduleIds.length > 0 && moduleIds[0] !== '') {\n const moduleNamesFiltered = moduleNames.filter(modinfo => moduleIds.includes(modinfo.id.toString()));\n moduleNamesFiltered.forEach(modinfo => {\n if (modinfo.module !== 'subsection') {\n // Checkbox should already be created by moodle massactions. Just add it to our data structure.\n const boxId = usedMoodleCssClasses.BOX_ID_PREFIX + modinfo.id.toString();\n sectionBoxes[section.number].push({\n 'moduleId': modinfo.id.toString(),\n 'boxId': boxId,\n });\n }\n });\n }\n });\n};\n\n/**\n * Filter the sections data object depending on the visibility of the course modules contained in\n * the data object. This is necessary, because some course formats only show specific section(s)\n * in editing mode.\n *\n * @param {[]} sections the sections data object\n * @returns {[]} the filtered sections object\n */\nconst filterVisibleSections = (sections) => {\n // Filter all sections with modules which no checkboxes have been created for.\n // This case should only occur in course formats where some sections are hidden.\n return sections.filter(section => section.cmlist.length !== 0)\n .filter(section => section.cmlist\n .every(moduleid => document.getElementById(usedMoodleCssClasses.MODULE_ID_PREFIX + moduleid) !== null));\n};\n\n/**\n * Update the selection, moveto and duplicateto dropdowns of the massaction block according to the\n * previously filtered sections.\n *\n * This method also has to be called whenever there is a module change event (moving around, adding file by Drag&Drop etc.).\n *\n * @param {[]} sections the sections object filtered before by {@link filterVisibleSections}\n * @param {[]} sectionsUnfiltered the same data object as 'sections', but still containing all sections\n */\nconst updateSelectionAndMoveToDropdowns = (sections, sectionsUnfiltered) => {\n if (sectionsChanged) {\n Templates.renderForPromise('block_massaction/section_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.SECTION_SELECT, html, js);\n disableInvisibleAndEmptySections(sections);\n // Re-register event listener.\n document.getElementById(cssIds.SECTION_SELECT).addEventListener('change',\n (event) => setSectionSelection(true, event.target.value), false);\n return true;\n })\n .catch(ex => displayException(ex));\n\n Templates.renderForPromise('block_massaction/moveto_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.MOVETO_SELECT, html, js);\n disableUnavailableSections(cssIds.MOVETO_SELECT);\n return true;\n })\n .catch(ex => displayException(ex));\n\n Templates.renderForPromise('block_massaction/duplicateto_select', {'sections': sectionsUnfiltered})\n .then(({html, js}) => {\n Templates.replaceNode('#' + cssIds.DUPLICATETO_SELECT, html, js);\n disableUnavailableSections(cssIds.DUPLICATETO_SELECT);\n return true;\n })\n .catch(ex => displayException(ex));\n } else {\n // If there has not been an event about a section change we do not have to rebuild the sections dropdowns.\n // However, there is a chance a section is being emptied or not empty anymore due to drag&dropping of modules.\n // So we have to recalculate if we have to enable/disable the sections.\n disableInvisibleAndEmptySections(sections);\n }\n // Reset the flag.\n sectionsChanged = false;\n};\n\n/**\n * Sets the disabled/enabled status of sections in the section select dropdown:\n * Enabled if section is visible and contains modules.\n * Disabled if section is not visible or doesn't contain any modules.\n *\n * @param {[]} sections the section data structure\n */\nconst disableInvisibleAndEmptySections = (sections) => {\n Array.prototype.forEach.call(document.getElementById(cssIds.SECTION_SELECT).options, option => {\n // Disable every element which doesn't have a visible section, except the placeholder ('description').\n if (option.value !== constants.SECTION_SELECT_DESCRIPTION_VALUE\n && !sections.some(section => parseInt(option.value) === section.number)) {\n option.disabled = true;\n } else {\n option.disabled = false;\n }\n });\n};\n\n/**\n * Sets the disabled/enabled status of sections in the section select dropdown:\n * Disabled if the section is not available due to some restrictions in block_massaction itself (provided by hooks).\n *\n * @param {string} elementId elementId to apply the restriction\n */\nconst disableUnavailableSections = (elementId) => {\n if (document.getElementById(elementId) !== null) {\n const sectionsAvailableInfo = document.querySelector(cssIds.SECTION_FILTER_DATA).dataset.availabletargetsections;\n const sectionsAvailable = Array.prototype.map.call(sectionsAvailableInfo.split(','), (sectionnum) => parseInt(sectionnum));\n Array.prototype.forEach.call(document.getElementById(elementId).options, option => {\n // Disable every element which is not in the sectionsAvailable list.\n if (sectionsAvailable.includes(parseInt(option.value))) {\n option.disabled = false;\n } else {\n option.disabled = true;\n }\n });\n }\n};\n"],"names":["localStateUpdating","sectionsChanged","sections","moduleNames","sectionBoxes","courseEditor","eventsToListen","stateManager","target","addEventListener","events","stateChanged","event","detail","action","rebuildLocalState","prop","Object","getOwnPropertyNames","state","courseItems","getExporter","allItemsArray","forEach","item","type","sectioninfo","section","get","id","title","getTitleOfSection","push","cm","values","sectionsUnfiltered","filterVisibleSections","updateSelectionAndMoveToDropdowns","addCheckboxesToDataStructure","component","moduleIds","sectionNumber","i","length","document","getElementById","boxId","checked","moduleId","setSectionSelection","value","boxIds","constants","SECTION_SELECT_DESCRIPTION_VALUE","SECTION_NUMBER_ALL_PLACEHOLDER","sectionId","j","box","cssIds","SECTION_SELECT","number","cmlist","filter","modinfo","includes","toString","module","usedMoodleCssClasses","BOX_ID_PREFIX","every","moduleid","MODULE_ID_PREFIX","renderForPromise","then","_ref","html","js","replaceNode","disableInvisibleAndEmptySections","catch","ex","_ref2","MOVETO_SELECT","disableUnavailableSections","_ref3","DUPLICATETO_SELECT","Array","prototype","call","options","option","some","parseInt","disabled","elementId","sectionsAvailableInfo","querySelector","SECTION_FILTER_DATA","dataset","availabletargetsections","sectionsAvailable","map","split","sectionnum"],"mappings":"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"} \ No newline at end of file diff --git a/amd/build/massactionblock.min.js b/amd/build/massactionblock.min.js index d430460..ce71d63 100644 --- a/amd/build/massactionblock.min.js +++ b/amd/build/massactionblock.min.js @@ -6,6 +6,6 @@ define("block_massaction/massactionblock",["exports","block_massaction/checkboxm * @copyright 2022 ISB Bayern * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.usedMoodleCssClasses=_exports.init=_exports.cssIds=_exports.constants=void 0,checkboxmanager=_interopRequireWildcard(checkboxmanager),Str=_interopRequireWildcard(Str),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_events=_interopRequireDefault(_events);_exports.usedMoodleCssClasses={ACTIVITY_ITEM:".activity-item",SECTION_NAME:"sectionname",MODULE_ID_PREFIX:"module-",BOX_ID_PREFIX:"cmCheckbox"};const cssIds={BLOCK_CONTENT:"block-massaction",BULK_EDITING_DISABLED:"block-massaction-bulk-editing-disabled",SELECT_ALL_LINK:"block-massaction-control-selectall",DESELECT_ALL_LINK:"block-massaction-control-deselectall",HIDE_LINK:"block-massaction-action-hide",SHOW_LINK:"block-massaction-action-show",MAKE_AVAILABLE_LINK:"block-massaction-action-makeavailable",DUPLICATE_LINK:"block-massaction-action-duplicate",DELETE_LINK:"block-massaction-action-delete",SHOW_DESCRIPTION_LINK:"block-massaction-action-showdescription",HIDE_DESCRIPTION_LINK:"block-massaction-action-hidedescription",CONTENT_CHANGED_NOTIFICATION_LINK:"block-massaction-action-contentchangednotification",MOVELEFT_LINK:"block-massaction-action-moveleft",MOVERIGHT_LINK:"block-massaction-action-moveright",MOVETO_ICON_LINK:"block-massaction-action-moveto",DUPLICATETO_ICON_LINK:"block-massaction-action-duplicateto",DUPLICATE_TO_COURSE_ICON_LINK:"block-massaction-action-duplicatetocourse",SECTION_SELECT:"block-massaction-control-section-list-select",MOVETO_SELECT:"block-massaction-control-section-list-moveto",DUPLICATETO_SELECT:"block-massaction-control-section-list-duplicateto",HIDDEN_FIELD_REQUEST_INFORMATION:"block-massaction-control-request",ACTION_FORM:"block-massaction-control-form",SECTION_FILTER_DATA:'[data-block-massaction-data="availabletargetsections"]'};_exports.cssIds=cssIds;const constants={SECTION_SELECT_DESCRIPTION_VALUE:"description",SECTION_NUMBER_ALL_PLACEHOLDER:"all"};_exports.constants=constants;const actions_HIDE="hide",actions_SHOW="show",actions_MAKE_AVAILABLE="makeavailable",actions_DUPLICATE="duplicate",actions_DELETE="delete",actions_SHOW_DESCRIPTION="showdescription",actions_HIDE_DESCRIPTION="hidedescription",actions_MOVE_LEFT="moveleft",actions_MOVE_RIGHT="moveright",actions_CONTENT_CHANGED_NOTIFICATION="contentchangednotification",actions_MOVE_TO="moveto",actions_DUPLICATE_TO="duplicateto",actions_DUPLICATE_TO_COURSE="duplicatetocourse";_exports.init=async()=>{var _document$getElementB3,_document$getElementB4,_document$getElementB5,_document$getElementB6,_document$getElementB7,_document$getElementB8,_document$getElementB9,_document$getElementB10,_document$getElementB11,_document$getElementB12,_document$getElementB13,_document$getElementB14,_document$getElementB15,_document$getElementB16,_document$getElementB17;const pendingPromise=new _pending.default("block_massaction/init"),editor=(0,_courseeditor.getCurrentCourseEditor)();editor.stateManager.getInitialPromise().then((()=>{checkboxmanager.initCheckboxManager(),editor.stateManager.target.addEventListener(_events.default.stateChanged,(event=>{var _document$getElementB,_document$getElementB2;"bulk.enabled:updated"===event.detail.action&&(null===(_document$getElementB=document.getElementById(cssIds.BLOCK_CONTENT))||void 0===_document$getElementB||_document$getElementB.classList.toggle("d-none"),null===(_document$getElementB2=document.getElementById(cssIds.BULK_EDITING_DISABLED))||void 0===_document$getElementB2||_document$getElementB2.classList.toggle("d-none"))}));const enableBulkButton=document.getElementById("block-massaction-enable-bulk-editing");return enableBulkButton.disabled=!1,null==enableBulkButton||enableBulkButton.addEventListener("click",(()=>editor.dispatch("bulkEnable",!0))),!0})).catch((error=>_log.default.debug(error))),null===(_document$getElementB3=document.getElementById(cssIds.SELECT_ALL_LINK))||void 0===_document$getElementB3||_document$getElementB3.addEventListener("click",(()=>checkboxmanager.setSectionSelection(!0,constants.SECTION_NUMBER_ALL_PLACEHOLDER)),!1),null===(_document$getElementB4=document.getElementById(cssIds.DESELECT_ALL_LINK))||void 0===_document$getElementB4||_document$getElementB4.addEventListener("click",(()=>checkboxmanager.setSectionSelection(!1,constants.SECTION_NUMBER_ALL_PLACEHOLDER)),!1),null===(_document$getElementB5=document.getElementById(cssIds.HIDE_LINK))||void 0===_document$getElementB5||_document$getElementB5.addEventListener("click",(()=>submitAction(actions_HIDE)),!1),null===(_document$getElementB6=document.getElementById(cssIds.SHOW_LINK))||void 0===_document$getElementB6||_document$getElementB6.addEventListener("click",(()=>submitAction(actions_SHOW)),!1),null===(_document$getElementB7=document.getElementById(cssIds.MAKE_AVAILABLE_LINK))||void 0===_document$getElementB7||_document$getElementB7.addEventListener("click",(()=>submitAction(actions_MAKE_AVAILABLE)),!1),null===(_document$getElementB8=document.getElementById(cssIds.DUPLICATE_LINK))||void 0===_document$getElementB8||_document$getElementB8.addEventListener("click",(()=>submitAction(actions_DUPLICATE)),!1),null===(_document$getElementB9=document.getElementById(cssIds.DELETE_LINK))||void 0===_document$getElementB9||_document$getElementB9.addEventListener("click",(()=>submitAction(actions_DELETE)),!1),null===(_document$getElementB10=document.getElementById(cssIds.SHOW_DESCRIPTION_LINK))||void 0===_document$getElementB10||_document$getElementB10.addEventListener("click",(()=>submitAction(actions_SHOW_DESCRIPTION)),!1),null===(_document$getElementB11=document.getElementById(cssIds.HIDE_DESCRIPTION_LINK))||void 0===_document$getElementB11||_document$getElementB11.addEventListener("click",(()=>submitAction(actions_HIDE_DESCRIPTION)),!1),null===(_document$getElementB12=document.getElementById(cssIds.CONTENT_CHANGED_NOTIFICATION_LINK))||void 0===_document$getElementB12||_document$getElementB12.addEventListener("click",(()=>submitAction(actions_CONTENT_CHANGED_NOTIFICATION)),!1),null===(_document$getElementB13=document.getElementById(cssIds.MOVELEFT_LINK))||void 0===_document$getElementB13||_document$getElementB13.addEventListener("click",(()=>submitAction(actions_MOVE_LEFT)),!1),null===(_document$getElementB14=document.getElementById(cssIds.MOVERIGHT_LINK))||void 0===_document$getElementB14||_document$getElementB14.addEventListener("click",(()=>submitAction(actions_MOVE_RIGHT)),!1),null===(_document$getElementB15=document.getElementById(cssIds.MOVETO_ICON_LINK))||void 0===_document$getElementB15||_document$getElementB15.addEventListener("click",(()=>submitAction(actions_MOVE_TO)),!1),null===(_document$getElementB16=document.getElementById(cssIds.DUPLICATETO_ICON_LINK))||void 0===_document$getElementB16||_document$getElementB16.addEventListener("click",(()=>submitAction(actions_DUPLICATE_TO)),!1),null===(_document$getElementB17=document.getElementById(cssIds.DUPLICATE_TO_COURSE_ICON_LINK))||void 0===_document$getElementB17||_document$getElementB17.addEventListener("click",(()=>submitAction(actions_DUPLICATE_TO_COURSE)),!1),pendingPromise.resolve()};const submitAction=action=>{const submitData={action:action,moduleIds:[]};if(submitData.moduleIds=checkboxmanager.getSelectedModIds(),0===submitData.moduleIds.length)return displayError(Str.get_string("noitemselected","block_massaction")),!1;switch(action){case actions_HIDE:case actions_SHOW:case actions_MAKE_AVAILABLE:case actions_DUPLICATE:case actions_DUPLICATE_TO_COURSE:case actions_CONTENT_CHANGED_NOTIFICATION:case actions_MOVE_LEFT:case actions_MOVE_RIGHT:case actions_DELETE:case actions_SHOW_DESCRIPTION:case actions_HIDE_DESCRIPTION:break;case actions_MOVE_TO:if(submitData.moveToTarget=document.getElementById(cssIds.MOVETO_SELECT).value,""===submitData.moveToTarget.trim())return displayError(Str.get_string("nomovingtargetselected","block_massaction")),!1;break;case actions_DUPLICATE_TO:if(submitData.duplicateToTarget=document.getElementById(cssIds.DUPLICATETO_SELECT).value,""===submitData.duplicateToTarget.trim())return displayError(Str.get_string("nomovingtargetselected","block_massaction")),!1;break;default:return displayError("Unknown action: "+action+". Coding error."),!1}return document.getElementById(cssIds.HIDDEN_FIELD_REQUEST_INFORMATION).value=JSON.stringify(submitData),document.getElementById(cssIds.ACTION_FORM).submit(),!0},displayError=errorText=>{Promise.resolve([Str.get_string("error","core"),errorText,Str.get_string("back","core")]).then((text=>_notification.default.alert(text[0],text[1],text[2]))).catch((error=>_log.default.debug(error)))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.usedMoodleCssClasses=_exports.init=_exports.cssIds=_exports.constants=void 0,checkboxmanager=_interopRequireWildcard(checkboxmanager),Str=_interopRequireWildcard(Str),_log=_interopRequireDefault(_log),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),_events=_interopRequireDefault(_events);_exports.usedMoodleCssClasses={ACTIVITY_ITEM:".activity-item",MODULE_ID_PREFIX:"module-",BOX_ID_PREFIX:"cmCheckbox"};const cssIds={BLOCK_CONTENT:"block-massaction",BULK_EDITING_DISABLED:"block-massaction-bulk-editing-disabled",SELECT_ALL_LINK:"block-massaction-control-selectall",DESELECT_ALL_LINK:"block-massaction-control-deselectall",HIDE_LINK:"block-massaction-action-hide",SHOW_LINK:"block-massaction-action-show",MAKE_AVAILABLE_LINK:"block-massaction-action-makeavailable",DUPLICATE_LINK:"block-massaction-action-duplicate",DELETE_LINK:"block-massaction-action-delete",SHOW_DESCRIPTION_LINK:"block-massaction-action-showdescription",HIDE_DESCRIPTION_LINK:"block-massaction-action-hidedescription",CONTENT_CHANGED_NOTIFICATION_LINK:"block-massaction-action-contentchangednotification",MOVELEFT_LINK:"block-massaction-action-moveleft",MOVERIGHT_LINK:"block-massaction-action-moveright",MOVETO_ICON_LINK:"block-massaction-action-moveto",DUPLICATETO_ICON_LINK:"block-massaction-action-duplicateto",DUPLICATE_TO_COURSE_ICON_LINK:"block-massaction-action-duplicatetocourse",SECTION_SELECT:"block-massaction-control-section-list-select",MOVETO_SELECT:"block-massaction-control-section-list-moveto",DUPLICATETO_SELECT:"block-massaction-control-section-list-duplicateto",HIDDEN_FIELD_REQUEST_INFORMATION:"block-massaction-control-request",ACTION_FORM:"block-massaction-control-form",SECTION_FILTER_DATA:'[data-block-massaction-data="availabletargetsections"]'};_exports.cssIds=cssIds;const constants={SECTION_SELECT_DESCRIPTION_VALUE:"description",SECTION_NUMBER_ALL_PLACEHOLDER:"all"};_exports.constants=constants;const actions_HIDE="hide",actions_SHOW="show",actions_MAKE_AVAILABLE="makeavailable",actions_DUPLICATE="duplicate",actions_DELETE="delete",actions_SHOW_DESCRIPTION="showdescription",actions_HIDE_DESCRIPTION="hidedescription",actions_MOVE_LEFT="moveleft",actions_MOVE_RIGHT="moveright",actions_CONTENT_CHANGED_NOTIFICATION="contentchangednotification",actions_MOVE_TO="moveto",actions_DUPLICATE_TO="duplicateto",actions_DUPLICATE_TO_COURSE="duplicatetocourse";_exports.init=async()=>{var _document$getElementB3,_document$getElementB4,_document$getElementB5,_document$getElementB6,_document$getElementB7,_document$getElementB8,_document$getElementB9,_document$getElementB10,_document$getElementB11,_document$getElementB12,_document$getElementB13,_document$getElementB14,_document$getElementB15,_document$getElementB16,_document$getElementB17;const pendingPromise=new _pending.default("block_massaction/init"),editor=(0,_courseeditor.getCurrentCourseEditor)();editor.stateManager.getInitialPromise().then((()=>{checkboxmanager.initCheckboxManager(),editor.stateManager.target.addEventListener(_events.default.stateChanged,(event=>{var _document$getElementB,_document$getElementB2;"bulk.enabled:updated"===event.detail.action&&(null===(_document$getElementB=document.getElementById(cssIds.BLOCK_CONTENT))||void 0===_document$getElementB||_document$getElementB.classList.toggle("d-none"),null===(_document$getElementB2=document.getElementById(cssIds.BULK_EDITING_DISABLED))||void 0===_document$getElementB2||_document$getElementB2.classList.toggle("d-none"))}));const enableBulkButton=document.getElementById("block-massaction-enable-bulk-editing");return enableBulkButton.disabled=!1,null==enableBulkButton||enableBulkButton.addEventListener("click",(()=>editor.dispatch("bulkEnable",!0))),!0})).catch((error=>_log.default.debug(error))),null===(_document$getElementB3=document.getElementById(cssIds.SELECT_ALL_LINK))||void 0===_document$getElementB3||_document$getElementB3.addEventListener("click",(()=>checkboxmanager.setSectionSelection(!0,constants.SECTION_NUMBER_ALL_PLACEHOLDER)),!1),null===(_document$getElementB4=document.getElementById(cssIds.DESELECT_ALL_LINK))||void 0===_document$getElementB4||_document$getElementB4.addEventListener("click",(()=>checkboxmanager.setSectionSelection(!1,constants.SECTION_NUMBER_ALL_PLACEHOLDER)),!1),null===(_document$getElementB5=document.getElementById(cssIds.HIDE_LINK))||void 0===_document$getElementB5||_document$getElementB5.addEventListener("click",(()=>submitAction(actions_HIDE)),!1),null===(_document$getElementB6=document.getElementById(cssIds.SHOW_LINK))||void 0===_document$getElementB6||_document$getElementB6.addEventListener("click",(()=>submitAction(actions_SHOW)),!1),null===(_document$getElementB7=document.getElementById(cssIds.MAKE_AVAILABLE_LINK))||void 0===_document$getElementB7||_document$getElementB7.addEventListener("click",(()=>submitAction(actions_MAKE_AVAILABLE)),!1),null===(_document$getElementB8=document.getElementById(cssIds.DUPLICATE_LINK))||void 0===_document$getElementB8||_document$getElementB8.addEventListener("click",(()=>submitAction(actions_DUPLICATE)),!1),null===(_document$getElementB9=document.getElementById(cssIds.DELETE_LINK))||void 0===_document$getElementB9||_document$getElementB9.addEventListener("click",(()=>submitAction(actions_DELETE)),!1),null===(_document$getElementB10=document.getElementById(cssIds.SHOW_DESCRIPTION_LINK))||void 0===_document$getElementB10||_document$getElementB10.addEventListener("click",(()=>submitAction(actions_SHOW_DESCRIPTION)),!1),null===(_document$getElementB11=document.getElementById(cssIds.HIDE_DESCRIPTION_LINK))||void 0===_document$getElementB11||_document$getElementB11.addEventListener("click",(()=>submitAction(actions_HIDE_DESCRIPTION)),!1),null===(_document$getElementB12=document.getElementById(cssIds.CONTENT_CHANGED_NOTIFICATION_LINK))||void 0===_document$getElementB12||_document$getElementB12.addEventListener("click",(()=>submitAction(actions_CONTENT_CHANGED_NOTIFICATION)),!1),null===(_document$getElementB13=document.getElementById(cssIds.MOVELEFT_LINK))||void 0===_document$getElementB13||_document$getElementB13.addEventListener("click",(()=>submitAction(actions_MOVE_LEFT)),!1),null===(_document$getElementB14=document.getElementById(cssIds.MOVERIGHT_LINK))||void 0===_document$getElementB14||_document$getElementB14.addEventListener("click",(()=>submitAction(actions_MOVE_RIGHT)),!1),null===(_document$getElementB15=document.getElementById(cssIds.MOVETO_ICON_LINK))||void 0===_document$getElementB15||_document$getElementB15.addEventListener("click",(()=>submitAction(actions_MOVE_TO)),!1),null===(_document$getElementB16=document.getElementById(cssIds.DUPLICATETO_ICON_LINK))||void 0===_document$getElementB16||_document$getElementB16.addEventListener("click",(()=>submitAction(actions_DUPLICATE_TO)),!1),null===(_document$getElementB17=document.getElementById(cssIds.DUPLICATE_TO_COURSE_ICON_LINK))||void 0===_document$getElementB17||_document$getElementB17.addEventListener("click",(()=>submitAction(actions_DUPLICATE_TO_COURSE)),!1),pendingPromise.resolve()};const submitAction=action=>{const submitData={action:action,moduleIds:[]};if(submitData.moduleIds=checkboxmanager.getSelectedModIds(),0===submitData.moduleIds.length)return displayError(Str.get_string("noitemselected","block_massaction")),!1;switch(action){case actions_HIDE:case actions_SHOW:case actions_MAKE_AVAILABLE:case actions_DUPLICATE:case actions_DUPLICATE_TO_COURSE:case actions_CONTENT_CHANGED_NOTIFICATION:case actions_MOVE_LEFT:case actions_MOVE_RIGHT:case actions_DELETE:case actions_SHOW_DESCRIPTION:case actions_HIDE_DESCRIPTION:break;case actions_MOVE_TO:if(submitData.moveToTarget=document.getElementById(cssIds.MOVETO_SELECT).value,""===submitData.moveToTarget.trim())return displayError(Str.get_string("nomovingtargetselected","block_massaction")),!1;break;case actions_DUPLICATE_TO:if(submitData.duplicateToTarget=document.getElementById(cssIds.DUPLICATETO_SELECT).value,""===submitData.duplicateToTarget.trim())return displayError(Str.get_string("nomovingtargetselected","block_massaction")),!1;break;default:return displayError("Unknown action: "+action+". Coding error."),!1}return document.getElementById(cssIds.HIDDEN_FIELD_REQUEST_INFORMATION).value=JSON.stringify(submitData),document.getElementById(cssIds.ACTION_FORM).submit(),!0},displayError=errorText=>{Promise.resolve([Str.get_string("error","core"),errorText,Str.get_string("back","core")]).then((text=>_notification.default.alert(text[0],text[1],text[2]))).catch((error=>_log.default.debug(error)))}})); //# sourceMappingURL=massactionblock.min.js.map \ No newline at end of file diff --git a/amd/build/massactionblock.min.js.map b/amd/build/massactionblock.min.js.map index 7ff8e5a..6665f7e 100644 --- a/amd/build/massactionblock.min.js.map +++ b/amd/build/massactionblock.min.js.map @@ -1 +1 @@ -{"version":3,"file":"massactionblock.min.js","sources":["../src/massactionblock.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Main module for the massaction block.\n *\n * @module block_massaction/massactionblock\n * @copyright 2022 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as checkboxmanager from 'block_massaction/checkboxmanager';\nimport * as Str from 'core/str';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport events from \"core_course/events\";\n\nexport const usedMoodleCssClasses = {\n ACTIVITY_ITEM: '.activity-item',\n SECTION_NAME: 'sectionname',\n MODULE_ID_PREFIX: 'module-',\n BOX_ID_PREFIX: 'cmCheckbox'\n};\n\nexport const cssIds = {\n BLOCK_CONTENT: 'block-massaction',\n BULK_EDITING_DISABLED: 'block-massaction-bulk-editing-disabled',\n SELECT_ALL_LINK: 'block-massaction-control-selectall',\n DESELECT_ALL_LINK: 'block-massaction-control-deselectall',\n HIDE_LINK: 'block-massaction-action-hide',\n SHOW_LINK: 'block-massaction-action-show',\n MAKE_AVAILABLE_LINK: 'block-massaction-action-makeavailable',\n DUPLICATE_LINK: 'block-massaction-action-duplicate',\n DELETE_LINK: 'block-massaction-action-delete',\n SHOW_DESCRIPTION_LINK: 'block-massaction-action-showdescription',\n HIDE_DESCRIPTION_LINK: 'block-massaction-action-hidedescription',\n CONTENT_CHANGED_NOTIFICATION_LINK: 'block-massaction-action-contentchangednotification',\n MOVELEFT_LINK: 'block-massaction-action-moveleft',\n MOVERIGHT_LINK: 'block-massaction-action-moveright',\n MOVETO_ICON_LINK: 'block-massaction-action-moveto',\n DUPLICATETO_ICON_LINK: 'block-massaction-action-duplicateto',\n DUPLICATE_TO_COURSE_ICON_LINK: 'block-massaction-action-duplicatetocourse',\n SECTION_SELECT: 'block-massaction-control-section-list-select',\n MOVETO_SELECT: 'block-massaction-control-section-list-moveto',\n DUPLICATETO_SELECT: 'block-massaction-control-section-list-duplicateto',\n HIDDEN_FIELD_REQUEST_INFORMATION: 'block-massaction-control-request',\n ACTION_FORM: 'block-massaction-control-form',\n SECTION_FILTER_DATA: `[data-block-massaction-data=\"availabletargetsections\"]`\n};\n\nexport const constants = {\n SECTION_SELECT_DESCRIPTION_VALUE: 'description',\n SECTION_NUMBER_ALL_PLACEHOLDER: 'all',\n};\n\nconst actions = {\n HIDE: 'hide',\n SHOW: 'show',\n MAKE_AVAILABLE: 'makeavailable',\n DUPLICATE: 'duplicate',\n DELETE: 'delete',\n SHOW_DESCRIPTION: 'showdescription',\n HIDE_DESCRIPTION: 'hidedescription',\n MOVE_LEFT: 'moveleft',\n MOVE_RIGHT: 'moveright',\n CONTENT_CHANGED_NOTIFICATION: 'contentchangednotification',\n MOVE_TO: 'moveto',\n DUPLICATE_TO: 'duplicateto',\n DUPLICATE_TO_COURSE: 'duplicatetocourse',\n};\n\n/**\n * Initialize the mass-action block.\n */\nexport const init = async() => {\n const pendingPromise = new Pending('block_massaction/init');\n\n const editor = getCurrentCourseEditor();\n // As soon as courseeditor is available, do some initial setup.\n editor.stateManager.getInitialPromise()\n .then(() => {\n // Initialize the checkbox manager.\n checkboxmanager.initCheckboxManager();\n\n // Show block depending on if the moodle bulk editing util has been activated.\n editor.stateManager.target.addEventListener(events.stateChanged, (event) => {\n // Listen to the event that bulk editing mode has been enabled/disabled.\n if (event.detail.action === 'bulk.enabled:updated') {\n // Hide/show block content depending on the bulk editing enabled state.\n document.getElementById(cssIds.BLOCK_CONTENT)?.classList.toggle('d-none');\n document.getElementById(cssIds.BULK_EDITING_DISABLED)?.classList.toggle('d-none');\n }\n });\n\n // Register click handler for the button in the placeholder text if bulk editing is still disabled.\n const enableBulkButton = document.getElementById('block-massaction-enable-bulk-editing');\n // Remove the initial disabled attribute which is there to avoid too early clicks by users.\n enableBulkButton.disabled = false;\n enableBulkButton?.addEventListener('click', () => editor.dispatch('bulkEnable', true));\n return true;\n })\n .catch(error => Log.debug(error));\n\n document.getElementById(cssIds.SELECT_ALL_LINK)?.addEventListener('click',\n () => checkboxmanager.setSectionSelection(true, constants.SECTION_NUMBER_ALL_PLACEHOLDER), false);\n\n document.getElementById(cssIds.DESELECT_ALL_LINK)?.addEventListener('click',\n () => checkboxmanager.setSectionSelection(false, constants.SECTION_NUMBER_ALL_PLACEHOLDER), false);\n\n document.getElementById(cssIds.HIDE_LINK)?.addEventListener('click',\n () => submitAction(actions.HIDE), false);\n\n document.getElementById(cssIds.SHOW_LINK)?.addEventListener('click',\n () => submitAction(actions.SHOW), false);\n\n document.getElementById(cssIds.MAKE_AVAILABLE_LINK)?.addEventListener('click',\n () => submitAction(actions.MAKE_AVAILABLE), false);\n\n document.getElementById(cssIds.DUPLICATE_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE), false);\n\n document.getElementById(cssIds.DELETE_LINK)?.addEventListener('click',\n () => submitAction(actions.DELETE), false);\n\n document.getElementById(cssIds.SHOW_DESCRIPTION_LINK)?.addEventListener('click',\n () => submitAction(actions.SHOW_DESCRIPTION), false);\n\n document.getElementById(cssIds.HIDE_DESCRIPTION_LINK)?.addEventListener('click',\n () => submitAction(actions.HIDE_DESCRIPTION), false);\n\n document.getElementById(cssIds.CONTENT_CHANGED_NOTIFICATION_LINK)?.addEventListener('click',\n () => submitAction(actions.CONTENT_CHANGED_NOTIFICATION), false);\n\n document.getElementById(cssIds.MOVELEFT_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_LEFT), false);\n\n document.getElementById(cssIds.MOVERIGHT_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_RIGHT), false);\n\n document.getElementById(cssIds.MOVETO_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_TO), false);\n\n document.getElementById(cssIds.DUPLICATETO_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE_TO), false);\n\n document.getElementById(cssIds.DUPLICATE_TO_COURSE_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE_TO_COURSE), false);\n\n pendingPromise.resolve();\n};\n\n/**\n * Submit the selected action to server.\n *\n * @param {string} action\n * @return {boolean} true if action was successful, false otherwise\n */\nconst submitAction = (action) => {\n const submitData = {\n 'action': action,\n 'moduleIds': []\n };\n\n submitData.moduleIds = checkboxmanager.getSelectedModIds();\n\n // Verify that at least one checkbox is checked.\n if (submitData.moduleIds.length === 0) {\n displayError(Str.get_string('noitemselected', 'block_massaction'));\n return false;\n }\n\n // Prep the submission.\n switch (action) {\n case actions.HIDE:\n case actions.SHOW:\n case actions.MAKE_AVAILABLE:\n case actions.DUPLICATE:\n case actions.DUPLICATE_TO_COURSE:\n case actions.CONTENT_CHANGED_NOTIFICATION:\n case actions.MOVE_LEFT:\n case actions.MOVE_RIGHT:\n case actions.DELETE:\n case actions.SHOW_DESCRIPTION:\n case actions.HIDE_DESCRIPTION:\n break;\n\n case actions.MOVE_TO:\n // Get the target section.\n submitData.moveToTarget = document.getElementById(cssIds.MOVETO_SELECT).value;\n if (submitData.moveToTarget.trim() === '') {\n displayError(Str.get_string('nomovingtargetselected', 'block_massaction'));\n return false;\n }\n break;\n\n case actions.DUPLICATE_TO:\n // Get the target section.\n submitData.duplicateToTarget = document.getElementById(cssIds.DUPLICATETO_SELECT).value;\n if (submitData.duplicateToTarget.trim() === '') {\n displayError(Str.get_string('nomovingtargetselected', 'block_massaction'));\n return false;\n }\n break;\n default:\n displayError('Unknown action: ' + action + '. Coding error.');\n return false;\n }\n // Set the form value and submit.\n document.getElementById(cssIds.HIDDEN_FIELD_REQUEST_INFORMATION).value = JSON.stringify(submitData);\n document.getElementById(cssIds.ACTION_FORM).submit();\n return true;\n};\n\nconst displayError = (errorText) => {\n Promise.resolve([Str.get_string('error', 'core'), errorText, Str.get_string('back', 'core')])\n .then(text => Notification.alert(text[0], text[1], text[2]))\n .catch(error => Log.debug(error));\n};\n"],"names":["ACTIVITY_ITEM","SECTION_NAME","MODULE_ID_PREFIX","BOX_ID_PREFIX","cssIds","BLOCK_CONTENT","BULK_EDITING_DISABLED","SELECT_ALL_LINK","DESELECT_ALL_LINK","HIDE_LINK","SHOW_LINK","MAKE_AVAILABLE_LINK","DUPLICATE_LINK","DELETE_LINK","SHOW_DESCRIPTION_LINK","HIDE_DESCRIPTION_LINK","CONTENT_CHANGED_NOTIFICATION_LINK","MOVELEFT_LINK","MOVERIGHT_LINK","MOVETO_ICON_LINK","DUPLICATETO_ICON_LINK","DUPLICATE_TO_COURSE_ICON_LINK","SECTION_SELECT","MOVETO_SELECT","DUPLICATETO_SELECT","HIDDEN_FIELD_REQUEST_INFORMATION","ACTION_FORM","SECTION_FILTER_DATA","constants","SECTION_SELECT_DESCRIPTION_VALUE","SECTION_NUMBER_ALL_PLACEHOLDER","actions","async","pendingPromise","Pending","editor","stateManager","getInitialPromise","then","checkboxmanager","initCheckboxManager","target","addEventListener","events","stateChanged","event","detail","action","document","getElementById","classList","toggle","enableBulkButton","disabled","dispatch","catch","error","Log","debug","setSectionSelection","submitAction","resolve","submitData","moduleIds","getSelectedModIds","length","displayError","Str","get_string","moveToTarget","value","trim","duplicateToTarget","JSON","stringify","submit","errorText","Promise","text","Notification","alert"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"massactionblock.min.js","sources":["../src/massactionblock.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Main module for the massaction block.\n *\n * @module block_massaction/massactionblock\n * @copyright 2022 ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as checkboxmanager from 'block_massaction/checkboxmanager';\nimport * as Str from 'core/str';\nimport Log from 'core/log';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport events from \"core_course/events\";\n\nexport const usedMoodleCssClasses = {\n ACTIVITY_ITEM: '.activity-item',\n MODULE_ID_PREFIX: 'module-',\n BOX_ID_PREFIX: 'cmCheckbox'\n};\n\nexport const cssIds = {\n BLOCK_CONTENT: 'block-massaction',\n BULK_EDITING_DISABLED: 'block-massaction-bulk-editing-disabled',\n SELECT_ALL_LINK: 'block-massaction-control-selectall',\n DESELECT_ALL_LINK: 'block-massaction-control-deselectall',\n HIDE_LINK: 'block-massaction-action-hide',\n SHOW_LINK: 'block-massaction-action-show',\n MAKE_AVAILABLE_LINK: 'block-massaction-action-makeavailable',\n DUPLICATE_LINK: 'block-massaction-action-duplicate',\n DELETE_LINK: 'block-massaction-action-delete',\n SHOW_DESCRIPTION_LINK: 'block-massaction-action-showdescription',\n HIDE_DESCRIPTION_LINK: 'block-massaction-action-hidedescription',\n CONTENT_CHANGED_NOTIFICATION_LINK: 'block-massaction-action-contentchangednotification',\n MOVELEFT_LINK: 'block-massaction-action-moveleft',\n MOVERIGHT_LINK: 'block-massaction-action-moveright',\n MOVETO_ICON_LINK: 'block-massaction-action-moveto',\n DUPLICATETO_ICON_LINK: 'block-massaction-action-duplicateto',\n DUPLICATE_TO_COURSE_ICON_LINK: 'block-massaction-action-duplicatetocourse',\n SECTION_SELECT: 'block-massaction-control-section-list-select',\n MOVETO_SELECT: 'block-massaction-control-section-list-moveto',\n DUPLICATETO_SELECT: 'block-massaction-control-section-list-duplicateto',\n HIDDEN_FIELD_REQUEST_INFORMATION: 'block-massaction-control-request',\n ACTION_FORM: 'block-massaction-control-form',\n SECTION_FILTER_DATA: `[data-block-massaction-data=\"availabletargetsections\"]`\n};\n\nexport const constants = {\n SECTION_SELECT_DESCRIPTION_VALUE: 'description',\n SECTION_NUMBER_ALL_PLACEHOLDER: 'all',\n};\n\nconst actions = {\n HIDE: 'hide',\n SHOW: 'show',\n MAKE_AVAILABLE: 'makeavailable',\n DUPLICATE: 'duplicate',\n DELETE: 'delete',\n SHOW_DESCRIPTION: 'showdescription',\n HIDE_DESCRIPTION: 'hidedescription',\n MOVE_LEFT: 'moveleft',\n MOVE_RIGHT: 'moveright',\n CONTENT_CHANGED_NOTIFICATION: 'contentchangednotification',\n MOVE_TO: 'moveto',\n DUPLICATE_TO: 'duplicateto',\n DUPLICATE_TO_COURSE: 'duplicatetocourse',\n};\n\n/**\n * Initialize the mass-action block.\n */\nexport const init = async() => {\n const pendingPromise = new Pending('block_massaction/init');\n\n const editor = getCurrentCourseEditor();\n // As soon as courseeditor is available, do some initial setup.\n editor.stateManager.getInitialPromise()\n .then(() => {\n // Initialize the checkbox manager.\n checkboxmanager.initCheckboxManager();\n\n // Show block depending on if the moodle bulk editing util has been activated.\n editor.stateManager.target.addEventListener(events.stateChanged, (event) => {\n // Listen to the event that bulk editing mode has been enabled/disabled.\n if (event.detail.action === 'bulk.enabled:updated') {\n // Hide/show block content depending on the bulk editing enabled state.\n document.getElementById(cssIds.BLOCK_CONTENT)?.classList.toggle('d-none');\n document.getElementById(cssIds.BULK_EDITING_DISABLED)?.classList.toggle('d-none');\n }\n });\n\n // Register click handler for the button in the placeholder text if bulk editing is still disabled.\n const enableBulkButton = document.getElementById('block-massaction-enable-bulk-editing');\n // Remove the initial disabled attribute which is there to avoid too early clicks by users.\n enableBulkButton.disabled = false;\n enableBulkButton?.addEventListener('click', () => editor.dispatch('bulkEnable', true));\n return true;\n })\n .catch(error => Log.debug(error));\n\n document.getElementById(cssIds.SELECT_ALL_LINK)?.addEventListener('click',\n () => checkboxmanager.setSectionSelection(true, constants.SECTION_NUMBER_ALL_PLACEHOLDER), false);\n\n document.getElementById(cssIds.DESELECT_ALL_LINK)?.addEventListener('click',\n () => checkboxmanager.setSectionSelection(false, constants.SECTION_NUMBER_ALL_PLACEHOLDER), false);\n\n document.getElementById(cssIds.HIDE_LINK)?.addEventListener('click',\n () => submitAction(actions.HIDE), false);\n\n document.getElementById(cssIds.SHOW_LINK)?.addEventListener('click',\n () => submitAction(actions.SHOW), false);\n\n document.getElementById(cssIds.MAKE_AVAILABLE_LINK)?.addEventListener('click',\n () => submitAction(actions.MAKE_AVAILABLE), false);\n\n document.getElementById(cssIds.DUPLICATE_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE), false);\n\n document.getElementById(cssIds.DELETE_LINK)?.addEventListener('click',\n () => submitAction(actions.DELETE), false);\n\n document.getElementById(cssIds.SHOW_DESCRIPTION_LINK)?.addEventListener('click',\n () => submitAction(actions.SHOW_DESCRIPTION), false);\n\n document.getElementById(cssIds.HIDE_DESCRIPTION_LINK)?.addEventListener('click',\n () => submitAction(actions.HIDE_DESCRIPTION), false);\n\n document.getElementById(cssIds.CONTENT_CHANGED_NOTIFICATION_LINK)?.addEventListener('click',\n () => submitAction(actions.CONTENT_CHANGED_NOTIFICATION), false);\n\n document.getElementById(cssIds.MOVELEFT_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_LEFT), false);\n\n document.getElementById(cssIds.MOVERIGHT_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_RIGHT), false);\n\n document.getElementById(cssIds.MOVETO_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.MOVE_TO), false);\n\n document.getElementById(cssIds.DUPLICATETO_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE_TO), false);\n\n document.getElementById(cssIds.DUPLICATE_TO_COURSE_ICON_LINK)?.addEventListener('click',\n () => submitAction(actions.DUPLICATE_TO_COURSE), false);\n\n pendingPromise.resolve();\n};\n\n/**\n * Submit the selected action to server.\n *\n * @param {string} action\n * @return {boolean} true if action was successful, false otherwise\n */\nconst submitAction = (action) => {\n const submitData = {\n 'action': action,\n 'moduleIds': []\n };\n\n submitData.moduleIds = checkboxmanager.getSelectedModIds();\n\n // Verify that at least one checkbox is checked.\n if (submitData.moduleIds.length === 0) {\n displayError(Str.get_string('noitemselected', 'block_massaction'));\n return false;\n }\n\n // Prep the submission.\n switch (action) {\n case actions.HIDE:\n case actions.SHOW:\n case actions.MAKE_AVAILABLE:\n case actions.DUPLICATE:\n case actions.DUPLICATE_TO_COURSE:\n case actions.CONTENT_CHANGED_NOTIFICATION:\n case actions.MOVE_LEFT:\n case actions.MOVE_RIGHT:\n case actions.DELETE:\n case actions.SHOW_DESCRIPTION:\n case actions.HIDE_DESCRIPTION:\n break;\n\n case actions.MOVE_TO:\n // Get the target section.\n submitData.moveToTarget = document.getElementById(cssIds.MOVETO_SELECT).value;\n if (submitData.moveToTarget.trim() === '') {\n displayError(Str.get_string('nomovingtargetselected', 'block_massaction'));\n return false;\n }\n break;\n\n case actions.DUPLICATE_TO:\n // Get the target section.\n submitData.duplicateToTarget = document.getElementById(cssIds.DUPLICATETO_SELECT).value;\n if (submitData.duplicateToTarget.trim() === '') {\n displayError(Str.get_string('nomovingtargetselected', 'block_massaction'));\n return false;\n }\n break;\n default:\n displayError('Unknown action: ' + action + '. Coding error.');\n return false;\n }\n // Set the form value and submit.\n document.getElementById(cssIds.HIDDEN_FIELD_REQUEST_INFORMATION).value = JSON.stringify(submitData);\n document.getElementById(cssIds.ACTION_FORM).submit();\n return true;\n};\n\nconst displayError = (errorText) => {\n Promise.resolve([Str.get_string('error', 'core'), errorText, Str.get_string('back', 'core')])\n .then(text => Notification.alert(text[0], text[1], text[2]))\n .catch(error => Log.debug(error));\n};\n"],"names":["ACTIVITY_ITEM","MODULE_ID_PREFIX","BOX_ID_PREFIX","cssIds","BLOCK_CONTENT","BULK_EDITING_DISABLED","SELECT_ALL_LINK","DESELECT_ALL_LINK","HIDE_LINK","SHOW_LINK","MAKE_AVAILABLE_LINK","DUPLICATE_LINK","DELETE_LINK","SHOW_DESCRIPTION_LINK","HIDE_DESCRIPTION_LINK","CONTENT_CHANGED_NOTIFICATION_LINK","MOVELEFT_LINK","MOVERIGHT_LINK","MOVETO_ICON_LINK","DUPLICATETO_ICON_LINK","DUPLICATE_TO_COURSE_ICON_LINK","SECTION_SELECT","MOVETO_SELECT","DUPLICATETO_SELECT","HIDDEN_FIELD_REQUEST_INFORMATION","ACTION_FORM","SECTION_FILTER_DATA","constants","SECTION_SELECT_DESCRIPTION_VALUE","SECTION_NUMBER_ALL_PLACEHOLDER","actions","async","pendingPromise","Pending","editor","stateManager","getInitialPromise","then","checkboxmanager","initCheckboxManager","target","addEventListener","events","stateChanged","event","detail","action","document","getElementById","classList","toggle","enableBulkButton","disabled","dispatch","catch","error","Log","debug","setSectionSelection","submitAction","resolve","submitData","moduleIds","getSelectedModIds","length","displayError","Str","get_string","moveToTarget","value","trim","duplicateToTarget","JSON","stringify","submit","errorText","Promise","text","Notification","alert"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/checkboxmanager.js b/amd/src/checkboxmanager.js index d5459f5..7a2f81d 100644 --- a/amd/src/checkboxmanager.js +++ b/amd/src/checkboxmanager.js @@ -81,15 +81,32 @@ const rebuildLocalState = () => { return; } localStateUpdating = true; - const courseEditor = getCurrentCourseEditor(); // First we rebuild our data structures depending on the course editor state. - sections = []; for (const prop of Object.getOwnPropertyNames(sectionBoxes)) { delete sectionBoxes[prop]; } - // The section map object is being sorted by section id. We have to sort after order in this course. - sections = [...courseEditor.stateManager.state.section.values()].sort((a, b) => a.number > b.number ? 1 : -1); + + const courseEditor = getCurrentCourseEditor(); + const state = courseEditor.stateManager.state; + const exporter = courseEditor.getExporter(); + + // Get all modules, sections and subsections in display order. + const courseItems = exporter.allItemsArray(state); + + // Build sections array. + sections = []; + courseItems.forEach(item => { + if (item.type === 'section') { + // Get section info. + let sectioninfo = {...state.section.get(item.id)}; + // Rename subsections for display purposes. + sectioninfo.title = getTitleOfSection(sectioninfo); + sections.push(sectioninfo); + } + }); + + // Get all module names and parameters. moduleNames = [...courseEditor.stateManager.state.cm.values()]; // Now we use the new information to rebuild dropdowns and re-apply checkboxes. @@ -100,6 +117,21 @@ const rebuildLocalState = () => { localStateUpdating = false; }; +/** + * Returns the title of a given section. + * If the section is a subsection, a prefix with a dash is added. + * + * @param {Object} section the section object from the course editor + * @returns {string} title of the section object corrected for subsections + */ +export const getTitleOfSection = (section) => { + let title = section.title; + if (section.component === 'mod_subsection') { + title = ' - ' + title; + } + return title; +}; + /** * Returns the currently selected module ids. * @@ -115,6 +147,7 @@ export const getSelectedModIds = () => { } } } + return moduleIds; }; @@ -127,7 +160,6 @@ export const getSelectedModIds = () => { */ export const setSectionSelection = (value, sectionNumber) => { const boxIds = []; - if (typeof sectionNumber !== 'undefined' && sectionNumber === constants.SECTION_SELECT_DESCRIPTION_VALUE) { // Description placeholder has been selected, do nothing. return; @@ -142,6 +174,7 @@ export const setSectionSelection = (value, sectionNumber) => { // We select all boxes of the given section. sectionBoxes[sectionNumber].forEach(box => boxIds.push(box.boxId)); } + // Un/check the boxes. for (let i = 0; i < boxIds.length; i++) { document.getElementById(boxIds[i]).checked = value; @@ -158,15 +191,18 @@ const addCheckboxesToDataStructure = () => { sections.forEach(section => { sectionBoxes[section.number] = []; const moduleIds = section.cmlist; + if (moduleIds && moduleIds.length > 0 && moduleIds[0] !== '') { const moduleNamesFiltered = moduleNames.filter(modinfo => moduleIds.includes(modinfo.id.toString())); moduleNamesFiltered.forEach(modinfo => { - // Checkbox should already be created by moodle massactions. Just add it to our data structure. - const boxId = usedMoodleCssClasses.BOX_ID_PREFIX + modinfo.id.toString(); - sectionBoxes[section.number].push({ - 'moduleId': modinfo.id.toString(), - 'boxId': boxId, - }); + if (modinfo.module !== 'subsection') { + // Checkbox should already be created by moodle massactions. Just add it to our data structure. + const boxId = usedMoodleCssClasses.BOX_ID_PREFIX + modinfo.id.toString(); + sectionBoxes[section.number].push({ + 'moduleId': modinfo.id.toString(), + 'boxId': boxId, + }); + } }); } }); diff --git a/amd/src/massactionblock.js b/amd/src/massactionblock.js index 36c5294..cb958d5 100644 --- a/amd/src/massactionblock.js +++ b/amd/src/massactionblock.js @@ -32,7 +32,6 @@ import events from "core_course/events"; export const usedMoodleCssClasses = { ACTIVITY_ITEM: '.activity-item', - SECTION_NAME: 'sectionname', MODULE_ID_PREFIX: 'module-', BOX_ID_PREFIX: 'cmCheckbox' }; diff --git a/version.php b/version.php index 3ef0dd1..70ba388 100644 --- a/version.php +++ b/version.php @@ -29,3 +29,4 @@ $plugin->component = 'block_massaction'; $plugin->maturity = MATURITY_STABLE; $plugin->release = 'v7.3.1'; +$plugin->supported = [404, 405];