{"version":3,"file":"actions.min.js","sources":["https:\/\/www.alsg.org\/home\/course\/format\/amd\/src\/local\/content\/actions.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 * Course state actions dispatcher.\n *\n * This module captures all data-dispatch links in the course content and dispatch the proper\n * state mutation, including any confirmation and modal required.\n *\n * @module core_courseformat\/local\/content\/actions\n * @class core_courseformat\/local\/content\/actions\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 ModalFactory from 'core\/modal_factory';\nimport ModalEvents from 'core\/modal_events';\nimport Templates from 'core\/templates';\nimport {prefetchStrings} from 'core\/prefetch';\nimport {get_string as getString} from 'core\/str';\nimport {getList} from 'core\/normalise';\nimport * as CourseEvents from 'core_course\/events';\nimport Pending from 'core\/pending';\nimport ContentTree from 'core_courseformat\/local\/courseeditor\/contenttree';\n\/\/ The jQuery module is only used for interacting with Boostrap 4. It can we removed when MDL-71979 is integrated.\nimport jQuery from 'jquery';\n\n\/\/ Load global strings.\nprefetchStrings('core', ['movecoursesection', 'movecoursemodule', 'confirm', 'delete']);\n\n\/\/ Mutations are dispatched by the course content actions.\n\/\/ Formats can use this module addActions static method to add custom actions.\n\/\/ Direct mutations can be simple strings (mutation) name or functions.\nconst directMutations = {\n sectionHide: 'sectionHide',\n sectionShow: 'sectionShow',\n cmHide: 'cmHide',\n cmShow: 'cmShow',\n cmStealth: 'cmStealth',\n cmMoveRight: 'cmMoveRight',\n cmMoveLeft: 'cmMoveLeft',\n};\n\nexport default class extends BaseComponent {\n\n \/**\n * Constructor hook.\n *\/\n create() {\n \/\/ Optional component name for debugging.\n this.name = 'content_actions';\n \/\/ Default query selectors.\n this.selectors = {\n ACTIONLINK: `[data-action]`,\n \/\/ Move modal selectors.\n SECTIONLINK: `[data-for='section']`,\n CMLINK: `[data-for='cm']`,\n SECTIONNODE: `[data-for='sectionnode']`,\n MODALTOGGLER: `[data-toggle='collapse']`,\n ADDSECTION: `[data-action='addSection']`,\n CONTENTTREE: `#destination-selector`,\n ACTIONMENU: `.action-menu`,\n ACTIONMENUTOGGLER: `[data-toggle=\"dropdown\"]`,\n };\n \/\/ Component css classes.\n this.classes = {\n DISABLED: `text-body`,\n ITALIC: `font-italic`,\n };\n }\n\n \/**\n * Add extra actions to the module.\n *\n * @param {array} actions array of methods to execute\n *\/\n static addActions(actions) {\n for (const [action, mutationReference] of Object.entries(actions)) {\n if (typeof mutationReference !== 'function' && typeof mutationReference !== 'string') {\n throw new Error(`${action} action must be a mutation name or a function`);\n }\n directMutations[action] = mutationReference;\n }\n }\n\n \/**\n * Initial state ready method.\n *\n * @param {Object} state the state data.\n *\n *\/\n stateReady(state) {\n \/\/ Delegate dispatch clicks.\n this.addEventListener(\n this.element,\n 'click',\n this._dispatchClick\n );\n \/\/ Check section limit.\n this._checkSectionlist({state});\n \/\/ Add an Event listener to recalculate limits it if a section HTML is altered.\n this.addEventListener(\n this.element,\n CourseEvents.sectionRefreshed,\n () => this._checkSectionlist({state})\n );\n }\n\n \/**\n * Return the component watchers.\n *\n * @returns {Array} of watchers\n *\/\n getWatchers() {\n return [\n \/\/ Check section limit.\n {watch: `course.sectionlist:updated`, handler: this._checkSectionlist},\n ];\n }\n\n _dispatchClick(event) {\n const target = event.target.closest(this.selectors.ACTIONLINK);\n if (!target) {\n return;\n }\n if (target.classList.contains(this.classes.DISABLED)) {\n event.preventDefault();\n return;\n }\n\n \/\/ Invoke proper method.\n const actionName = target.dataset.action;\n const methodName = this._actionMethodName(actionName);\n\n if (this[methodName] !== undefined) {\n this[methodName](target, event);\n return;\n }\n\n \/\/ Check direct mutations or mutations handlers.\n if (directMutations[actionName] !== undefined) {\n if (typeof directMutations[actionName] === 'function') {\n directMutations[actionName](target, event);\n return;\n }\n this._requestMutationAction(target, event, directMutations[actionName]);\n return;\n }\n }\n\n _actionMethodName(name) {\n const requestName = name.charAt(0).toUpperCase() + name.slice(1);\n return `_request${requestName}`;\n }\n\n \/**\n * Check the section list and disable some options if needed.\n *\n * @param {Object} detail the update details.\n * @param {Object} detail.state the state object.\n *\/\n _checkSectionlist({state}) {\n \/\/ Disable \"add section\" actions if the course max sections has been exceeded.\n this._setAddSectionLocked(state.course.sectionlist.length > state.course.maxsections);\n }\n\n \/**\n * Handle a move section request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n async _requestMoveSection(target, event) {\n \/\/ Check we have an id.\n const sectionId = target.dataset.id;\n if (!sectionId) {\n return;\n }\n const sectionInfo = this.reactive.get('section', sectionId);\n\n event.preventDefault();\n\n const pendingModalReady = new Pending(`courseformat\/actions:prepareMoveSectionModal`);\n\n \/\/ The section edit menu to refocus on end.\n const editTools = this._getClosestActionMenuToogler(target);\n\n \/\/ Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.course(this.reactive.state);\n\n \/\/ Add the target section id and title.\n data.sectionid = sectionInfo.id;\n data.sectiontitle = sectionInfo.title;\n\n \/\/ Build the modal parameters from the event data.\n const modalParams = {\n title: getString('movecoursesection', 'core'),\n body: Templates.render('core_courseformat\/local\/content\/movesection', data),\n };\n\n \/\/ Create the modal.\n const modal = await this._modalBodyRenderedPromise(modalParams);\n\n const modalBody = getList(modal.getBody())[0];\n\n \/\/ Disable current element and section zero.\n const currentElement = modalBody.querySelector(`${this.selectors.SECTIONLINK}[data-id='${sectionId}']`);\n this._disableLink(currentElement);\n const generalSection = modalBody.querySelector(`${this.selectors.SECTIONLINK}[data-number='0']`);\n this._disableLink(generalSection);\n\n \/\/ Setup keyboard navigation.\n new ContentTree(\n modalBody.querySelector(this.selectors.CONTENTTREE),\n {\n SECTION: this.selectors.SECTIONNODE,\n TOGGLER: this.selectors.MODALTOGGLER,\n COLLAPSE: this.selectors.MODALTOGGLER,\n },\n true\n );\n\n \/\/ Capture click.\n modalBody.addEventListener('click', (event) => {\n const target = event.target;\n if (!target.matches('a') || target.dataset.for != 'section' || target.dataset.id === undefined) {\n return;\n }\n if (target.getAttribute('aria-disabled')) {\n return;\n }\n event.preventDefault();\n this.reactive.dispatch('sectionMove', [sectionId], target.dataset.id);\n this._destroyModal(modal, editTools);\n });\n\n pendingModalReady.resolve();\n }\n\n \/**\n * Handle a move cm request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n async _requestMoveCm(target, event) {\n \/\/ Check we have an id.\n const cmId = target.dataset.id;\n if (!cmId) {\n return;\n }\n const cmInfo = this.reactive.get('cm', cmId);\n\n event.preventDefault();\n\n const pendingModalReady = new Pending(`courseformat\/actions:prepareMoveCmModal`);\n\n \/\/ The section edit menu to refocus on end.\n const editTools = this._getClosestActionMenuToogler(target);\n\n \/\/ Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.course(this.reactive.state);\n\n \/\/ Add the target cm info.\n data.cmid = cmInfo.id;\n data.cmname = cmInfo.name;\n\n \/\/ Build the modal parameters from the event data.\n const modalParams = {\n title: getString('movecoursemodule', 'core'),\n body: Templates.render('core_courseformat\/local\/content\/movecm', data),\n };\n\n \/\/ Create the modal.\n const modal = await this._modalBodyRenderedPromise(modalParams);\n\n const modalBody = getList(modal.getBody())[0];\n\n \/\/ Disable current element.\n let currentElement = modalBody.querySelector(`${this.selectors.CMLINK}[data-id='${cmId}']`);\n this._disableLink(currentElement);\n\n \/\/ Setup keyboard navigation.\n new ContentTree(\n modalBody.querySelector(this.selectors.CONTENTTREE),\n {\n SECTION: this.selectors.SECTIONNODE,\n TOGGLER: this.selectors.MODALTOGGLER,\n COLLAPSE: this.selectors.MODALTOGGLER,\n ENTER: this.selectors.SECTIONLINK,\n }\n );\n\n \/\/ Open the cm section node if possible (Bootstrap 4 uses jQuery to interact with collapsibles).\n \/\/ All jQuery int this code can be replaced when MDL-71979 is integrated.\n const sectionnode = currentElement.closest(this.selectors.SECTIONNODE);\n const toggler = jQuery(sectionnode).find(this.selectors.MODALTOGGLER);\n let collapsibleId = toggler.data('target') ?? toggler.attr('href');\n if (collapsibleId) {\n \/\/ We cannot be sure we have # in the id element name.\n collapsibleId = collapsibleId.replace('#', '');\n jQuery(`#${collapsibleId}`).collapse('toggle');\n }\n\n \/\/ Capture click.\n modalBody.addEventListener('click', (event) => {\n const target = event.target;\n if (!target.matches('a') || target.dataset.for === undefined || target.dataset.id === undefined) {\n return;\n }\n if (target.getAttribute('aria-disabled')) {\n return;\n }\n event.preventDefault();\n\n \/\/ Get draggable data from cm or section to dispatch.\n let targetSectionId;\n let targetCmId;\n if (target.dataset.for == 'cm') {\n const dropData = exporter.cmDraggableData(this.reactive.state, target.dataset.id);\n targetSectionId = dropData.sectionid;\n targetCmId = dropData.nextcmid;\n } else {\n const section = this.reactive.get('section', target.dataset.id);\n targetSectionId = target.dataset.id;\n targetCmId = section?.cmlist[0];\n }\n\n this.reactive.dispatch('cmMove', [cmId], targetSectionId, targetCmId);\n this._destroyModal(modal, editTools);\n });\n\n pendingModalReady.resolve();\n }\n\n \/**\n * Handle a create section request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n async _requestAddSection(target, event) {\n event.preventDefault();\n this.reactive.dispatch('addSection', target.dataset.id ?? 0);\n }\n\n \/**\n * Handle a delete section request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n async _requestDeleteSection(target, event) {\n \/\/ Check we have an id.\n const sectionId = target.dataset.id;\n\n if (!sectionId) {\n return;\n }\n const sectionInfo = this.reactive.get('section', sectionId);\n\n event.preventDefault();\n\n const cmList = sectionInfo.cmlist ?? [];\n if (cmList.length || sectionInfo.hassummary || sectionInfo.rawtitle) {\n \/\/ We need confirmation if the section has something.\n const modalParams = {\n title: getString('confirm', 'core'),\n body: getString('confirmdeletesection', 'moodle', sectionInfo.title),\n saveButtonText: getString('delete', 'core'),\n type: ModalFactory.types.SAVE_CANCEL,\n };\n\n const modal = await this._modalBodyRenderedPromise(modalParams);\n\n modal.getRoot().on(\n ModalEvents.save,\n e => {\n \/\/ Stop the default save button behaviour which is to close the modal.\n e.preventDefault();\n modal.destroy();\n this.reactive.dispatch('sectionDelete', [sectionId]);\n }\n );\n return;\n } else {\n \/\/ We don't need confirmation to delete empty sections.\n this.reactive.dispatch('sectionDelete', [sectionId]);\n }\n }\n\n \/**\n * Basic mutation action helper.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n * @param {string} mutationName the mutation name\n *\/\n async _requestMutationAction(target, event, mutationName) {\n if (!target.dataset.id) {\n return;\n }\n event.preventDefault();\n this.reactive.dispatch(mutationName, [target.dataset.id]);\n }\n\n \/**\n * Disable all add sections actions.\n *\n * @param {boolean} locked the new locked value.\n *\/\n _setAddSectionLocked(locked) {\n const targets = this.getElements(this.selectors.ADDSECTION);\n targets.forEach(element => {\n element.classList.toggle(this.classes.DISABLED, locked);\n element.classList.toggle(this.classes.ITALIC, locked);\n this.setElementLocked(element, locked);\n });\n }\n\n \/**\n * Replace an element with a copy with a different tag name.\n *\n * @param {Element} element the original element\n *\/\n _disableLink(element) {\n if (element) {\n element.style.pointerEvents = 'none';\n element.style.userSelect = 'none';\n element.classList.add(this.classes.DISABLED);\n element.classList.add(this.classes.ITALIC);\n element.setAttribute('aria-disabled', true);\n element.addEventListener('click', event => event.preventDefault());\n }\n }\n\n \/**\n * Render a modal and return a body ready promise.\n *\n * @param {object} modalParams the modal params\n * @return {Promise} the modal body ready promise\n *\/\n _modalBodyRenderedPromise(modalParams) {\n return new Promise((resolve, reject) => {\n ModalFactory.create(modalParams).then((modal) => {\n modal.setRemoveOnClose(true);\n \/\/ Handle body loading event.\n modal.getRoot().on(ModalEvents.bodyRendered, () => {\n resolve(modal);\n });\n \/\/ Configure some extra modal params.\n if (modalParams.saveButtonText !== undefined) {\n modal.setSaveButtonText(modalParams.saveButtonText);\n }\n modal.show();\n return;\n }).catch(() => {\n reject(`Cannot load modal content`);\n });\n });\n }\n\n \/**\n * Hide and later destroy a modal.\n *\n * Behat will fail if we remove the modal while some boostrap collapse is executing.\n *\n * @param {Modal} modal\n * @param {HTMLElement} element the dom element to focus on.\n *\/\n _destroyModal(modal, element) {\n modal.hide();\n const pendingDestroy = new Pending(`courseformat\/actions:destroyModal`);\n if (element) {\n element.focus();\n }\n setTimeout(() =>{\n modal.destroy();\n pendingDestroy.resolve();\n }, 500);\n }\n\n \/**\n * Get the closest actions menu toggler to an action element.\n *\n * @param {HTMLElement} element the action link element\n * @returns {HTMLElement|undefined}\n *\/\n _getClosestActionMenuToogler(element) {\n const actionMenu = element.closest(this.selectors.ACTIONMENU);\n if (!actionMenu) {\n return undefined;\n }\n return actionMenu.querySelector(this.selectors.ACTIONMENUTOGGLER);\n }\n}\n"],"names":["directMutations","sectionHide","sectionShow","cmHide","cmShow","cmStealth","cmMoveRight","cmMoveLeft","BaseComponent","create","name","selectors","ACTIONLINK","SECTIONLINK","CMLINK","SECTIONNODE","MODALTOGGLER","ADDSECTION","CONTENTTREE","ACTIONMENU","ACTIONMENUTOGGLER","classes","DISABLED","ITALIC","actions","action","mutationReference","Object","entries","Error","stateReady","state","addEventListener","this","element","_dispatchClick","_checkSectionlist","CourseEvents","sectionRefreshed","getWatchers","watch","handler","event","target","closest","classList","contains","preventDefault","actionName","dataset","methodName","_actionMethodName","undefined","_requestMutationAction","requestName","charAt","toUpperCase","slice","_setAddSectionLocked","course","sectionlist","length","maxsections","sectionId","id","sectionInfo","reactive","get","pendingModalReady","Pending","editTools","_getClosestActionMenuToogler","data","getExporter","sectionid","sectiontitle","title","modalParams","body","Templates","render","modal","_modalBodyRenderedPromise","modalBody","getBody","currentElement","querySelector","_disableLink","generalSection","ContentTree","SECTION","TOGGLER","COLLAPSE","matches","for","getAttribute","dispatch","_destroyModal","resolve","cmId","cmInfo","exporter","cmid","cmname","ENTER","sectionnode","toggler","find","collapsibleId","attr","replace","collapse","targetSectionId","targetCmId","dropData","cmDraggableData","nextcmid","section","cmlist","hassummary","rawtitle","saveButtonText","type","ModalFactory","types","SAVE_CANCEL","getRoot","on","ModalEvents","save","e","destroy","mutationName","locked","getElements","forEach","toggle","setElementLocked","style","pointerEvents","userSelect","add","setAttribute","Promise","reject","then","setRemoveOnClose","bodyRendered","setSaveButtonText","show","catch","hide","pendingDestroy","focus","setTimeout","actionMenu"],"mappings":"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\/C,cAAchB,MAAO\/C,SACjB+C,MAAMsE,aACAC,eAAiB,IAAInF,sDACvBnC,SACAA,QAAQuH,QAEZC,YAAW,KACPzE,MAAMkD,UACNqB,eAAetD,YAChB,KASP3B,6BAA6BrC,eACnByH,WAAazH,QAAQU,QAAQX,KAAKtB,UAAUQ,eAC7CwI,kBAGEA,WAAWrE,cAAcrD,KAAKtB,UAAUS"}