{"version":3,"file":"actions.min.js","sources":["https:\/\/moodle.tau.ac.il\/2023\/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};\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: `disabled`,\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 \/\/ 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\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 \/\/ 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\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 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.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","BaseComponent","create","name","selectors","ACTIONLINK","SECTIONLINK","CMLINK","SECTIONNODE","MODALTOGGLER","ADDSECTION","CONTENTTREE","ACTIONMENU","ACTIONMENUTOGGLER","classes","DISABLED","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","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","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","resolve","reject","then","setRemoveOnClose","bodyRendered","setSaveButtonText","show","catch","hide","pendingDestroy","Pending","focus","setTimeout","actionMenu"],"mappings":"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\/B,yBAM5CG,SAAS4B,SAAS,gBAAiB,CAAC\/B,yCAWpBpB,OAAQD,MAAOuF,cACnCtF,OAAOM,QAAQe,KAGpBtB,MAAMK,sBACDmB,SAAS4B,SAASmC,aAAc,CAACtF,OAAOM,QAAQe,MAQzDN,qBAAqBwE,QACDjG,KAAKkG,YAAYlG,KAAKrB,UAAUM,YACxCkH,SAAQlG,UACZA,QAAQW,UAAUwF,OAAOpG,KAAKX,QAAQC,SAAU2G,aAC3CI,iBAAiBpG,QAASgG,WASvC7C,aAAanD,SACLA,UACAA,QAAQqG,MAAMC,cAAgB,OAC9BtG,QAAQqG,MAAME,WAAa,OAC3BvG,QAAQW,UAAU6F,IAAIzG,KAAKX,QAAQC,UACnCW,QAAQyG,aAAa,iBAAiB,GACtCzG,QAAQF,iBAAiB,SAASU,OAASA,MAAMK,oBAUzDiC,0BAA0BL,oBACf,IAAIiE,SAAQ,CAACC,QAASC,iCACZpI,OAAOiE,aAAaoE,MAAMhE,QACnCA,MAAMiE,kBAAiB,GAEvBjE,MAAM4C,UAAUC,GAAGC,sBAAYoB,cAAc,KACzCJ,QAAQ9D,eAGuB3B,IAA\/BuB,YAAY2C,gBACZvC,MAAMmE,kBAAkBvE,YAAY2C,gBAExCvC,MAAMoE,UAEPC,OAAM,KACLN,0CAaZ\/C,cAAchB,MAAO7C,SACjB6C,MAAMsE,aACAC,eAAiB,IAAIC,sDACvBrH,SACAA,QAAQsH,QAEZC,YAAW,KACP1E,MAAMiD,UACNsB,eAAeT,YAChB,KASPxE,6BAA6BnC,eACnBwH,WAAaxH,QAAQU,QAAQX,KAAKrB,UAAUQ,eAC7CsI,kBAGEA,WAAWtE,cAAcnD,KAAKrB,UAAUS"}