{"version":3,"file":"actions.min.js","sources":["https:\/\/dl1.cuni.cz\/course\/format\/flexsections\/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\nimport {BaseComponent} from 'core\/reactive';\nimport {get_string as getString, get_strings as getStrings} from \"core\/str\";\nimport Notification from \"core\/notification\";\nimport ModalFactory from \"core\/modal_factory\";\nimport Templates from \"core\/templates\";\nimport Pending from \"core\/pending\";\n\n\/**\n * Actions\n *\n * @module format_flexsections\/local\/content\/actions\n * @copyright 2022 Marina Glancy\n * @license http:\/\/www.gnu.org\/copyleft\/gpl.html GNU GPL v3 or later\n *\/\nexport default class extends BaseComponent {\n \/\/ Example: course\/format\/amd\/src\/local\/content\/actions.js\n\n \/**\n * Constructor hook.\n *\/\n create() {\n \/\/ Optional component name for debugging.\n this.name = 'content_actions_flexsections';\n \/\/ Default query selectors.\n this.selectors = {\n ACTIONLINK: `[data-action-flexsections]`,\n SECTIONLINK: `[data-for='section']`,\n };\n \/\/ Component css classes.\n this.classes = {\n DISABLED: `disabled`,\n };\n }\n\n \/**\n * Initial state ready method.\n *\n * @param {Object} state the state data.\n *\n *\/\n stateReady(state) {\n super.stateReady(state);\n \/\/ Delegate dispatch clicks.\n this.addEventListener(\n this.element,\n 'click',\n this._dispatchClick\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 methodName = this._actionMethodName(target.getAttribute('data-action-flexsections'));\n\n if (this[methodName] !== undefined) {\n this[methodName](target, event);\n }\n }\n\n _actionMethodName(name) {\n const requestName = name.charAt(0).toUpperCase() + name.slice(1);\n return `_request${requestName}`;\n }\n\n \/**\n * Handle a section delete request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestDelete(target, event) {\n const sectionId = target.dataset.id;\n if (!sectionId) {\n return;\n }\n event.preventDefault();\n\n const sectionInfo = this.reactive.get('section', sectionId);\n\n const cmList = sectionInfo.cmlist ?? [];\n if (cmList.length || sectionInfo.hassummary || sectionInfo.rawtitle || sectionInfo.children.length) {\n getStrings([\n {key: 'confirm', component: 'moodle'},\n {key: 'confirmdelete', component: 'format_flexsections'},\n {key: 'yes', component: 'moodle'},\n {key: 'no', component: 'moodle'}\n ]).done((strings) => {\n Notification.confirm(\n strings[0], \/\/ Confirm.\n strings[1], \/\/ Are you sure you want to delete.\n strings[2], \/\/ Yes.\n strings[3], \/\/ No.\n () => {\n this.reactive.dispatch('sectionDelete', [sectionId]);\n }\n );\n }).fail(Notification.exception);\n } else {\n \/\/ We don't need confirmation to merge empty sections.\n this.reactive.dispatch('sectionDelete', [sectionId]);\n }\n }\n\n \/**\n * Handle a merge section request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestMergeup(target, event) {\n const sectionId = target.dataset.id;\n if (!sectionId) {\n return;\n }\n event.preventDefault();\n\n const sectionInfo = this.reactive.get('section', sectionId);\n\n const cmList = sectionInfo.cmlist ?? [];\n if (cmList.length || sectionInfo.hassummary || sectionInfo.rawtitle || sectionInfo.children.length) {\n getStrings([\n {key: 'confirm', component: 'moodle'},\n {key: 'confirmmerge', component: 'format_flexsections'},\n {key: 'yes', component: 'moodle'},\n {key: 'no', component: 'moodle'}\n ]).done((strings) => {\n Notification.confirm(\n strings[0], \/\/ Confirm.\n strings[1], \/\/ Are you sure you want to merge.\n strings[2], \/\/ Yes.\n strings[3], \/\/ No.\n () => {\n this.reactive.dispatch('sectionMergeUp', sectionId);\n }\n );\n }).fail(Notification.exception);\n } else {\n \/\/ We don't need confirmation to merge empty sections.\n this.reactive.dispatch('sectionMergeUp', sectionId);\n }\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 _requestMoveSection(target, event) {\n event.preventDefault();\n const sectionId = target.dataset.id;\n const sectionInfo = this.reactive.get('section', sectionId);\n const exporter = this.reactive.getExporter();\n const data = exporter.course(this.reactive.state);\n data.sectiontitle = sectionInfo.title;\n\n if (data.sections.length === 1 && `${data.sections[0].singlesection}` === '1') {\n \/\/ We are on a page of a collapsed section. Do not show \"move before\" and \"move after\" controls.\n data.singlesectionmode = 1;\n data.sections[0].contentcollapsed = false;\n \/\/ TODO allow to move from collapsed section up level.\n }\n const buildParents = (sections, parents) => {\n for (var i in sections) {\n sections[i].parents = parents;\n sections[i].aftersectionid = (i > 0) ? sections[i - 1].id : 0;\n buildParents(sections[i].children, parents + ',' + sections[i].id);\n sections[i].lastchildid = sections[i].children.length ?\n sections[i].children[sections[i].children.length - 1].id : 0;\n }\n };\n buildParents(data.sections, '');\n data.lastchildid = data.sections.length ? data.sections[data.sections.length - 1].id : 0;\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: getString('movecoursesection', 'core'),\n large: true,\n buttons: {cancel: getString('closebuttontitle', 'core')},\n removeOnClose: true,\n })\n .then(modal => {\n \/\/ eslint-disable-next-line promise\/no-nesting\n Templates.render('format_flexsections\/local\/content\/movesection', data).\n then((body) => {\n modal.setBody(body);\n this._setupMoveSection(modal, modal.getBody()[0], sectionId, data);\n return null;\n })\n .fail(() => null);\n modal.show();\n return modal;\n })\n .fail(() => null);\n }\n\n \/**\n * Handle a move activity request.\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestMoveCm(target, event) {\n event.preventDefault();\n const cmId = target.dataset.id;\n if (!cmId) {\n return;\n }\n const cmInfo = this.reactive.get('cm', cmId);\n\n const exporter = this.reactive.getExporter();\n const data = exporter.course(this.reactive.state);\n\n \/\/ TODO set before and after current as disabled.\n \/\/ TODO allow to move from collapsed section up level.\n\n data.cmid = cmInfo.id;\n data.cmname = cmInfo.name;\n\n ModalFactory.create({\n type: ModalFactory.types.CANCEL,\n title: getString('movecoursemodule', 'core'),\n large: true,\n buttons: {cancel: getString('closebuttontitle', 'core')},\n removeOnClose: true,\n })\n .then(modal => {\n \/\/ eslint-disable-next-line promise\/no-nesting\n Templates.render('format_flexsections\/local\/content\/movecm', data).\n then((body) => {\n modal.setBody(body);\n this._setupMoveCm(modal, modal.getBody()[0], cmId, data);\n return null;\n })\n .fail(() => null);\n modal.show();\n return modal;\n })\n .fail(() => null);\n }\n\n \/**\n * Set up a popup window for moving activity\n *\n * @param {Modal} modal\n * @param {Element} modalBody\n * @param {Number} cmId\n * @param {Object} data\n * @param {Element} element\n *\/\n _setupMoveCm(modal, modalBody, cmId, data, element = null) {\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 const targetSectionId = (target.dataset.for === 'section') ? target.dataset.id : 0;\n const targetCmId = (target.dataset.for === 'cm') ? target.dataset.id : 0;\n this.reactive.dispatch('cmMove', [cmId], targetSectionId, targetCmId);\n this._destroyModal(modal, element);\n });\n }\n\n \/**\n * Destroy modal popup\n *\n * @param {Modal} modal\n * @param {Element} element\n *\/\n _destroyModal(modal, element = null) {\n\n \/\/ Destroy\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 \/**\n * Set up a popup window for moving section\n *\n * @param {Modal} modal\n * @param {Element} modalBody\n * @param {Number} sectionId\n * @param {Object} data\n * @param {Element} element\n *\/\n _setupMoveSection(modal, modalBody, sectionId, data, element = null) {\n\n \/\/ Disable moving before or after itself or under one of its own children.\n const links = modalBody.querySelectorAll(`${this.selectors.SECTIONLINK}`);\n for (let i = 0; i < links.length; ++i) {\n const re = new RegExp(`,${sectionId},`, \"g\");\n if (links[i].getAttribute('data-before') === `${sectionId}` || links[i].getAttribute('data-after') === `${sectionId}` ||\n `${links[i].getAttribute('data-parents')},`.match(re)) {\n this._disableLink(links[i]);\n }\n \/\/ Disable moving to the depth that exceeds the maxsectiondepth setting.\n const depth = (`${links[i].getAttribute('data-parents')}`.match(\/,\/g) || []).length;\n if (data.maxsectiondepth && depth >= data.maxsectiondepth) {\n this._disableLink(links[i]);\n }\n }\n\n \/\/ TODO.\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\n const target = event.target;\n if (!target.matches('a') || target.dataset.for !== 'section' || target.dataset.after === undefined) {\n return;\n }\n if (target.getAttribute('aria-disabled')) {\n return;\n }\n event.preventDefault();\n const afterId = parseInt(target.dataset.after);\n const parentId = parseInt(target.dataset.parentid);\n this.reactive.dispatch('sectionMove', [sectionId], afterId ? afterId : -parentId);\n\n this._destroyModal(modal, element);\n });\n }\n\n \/**\n * Disable link\n *\n * @param {Element} element\n *\/\n _disableLink(element) {\n if (element) {\n element.style.pointerEvents = 'none';\n element.style.userSelect = 'none';\n element.classList.add('disabled');\n element.setAttribute('aria-disabled', true);\n element.addEventListener('click', event => event.preventDefault());\n }\n }\n\n \/**\n * Handle a request to add a subsection as the last child of the parent\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestAddSubSection(target, event) {\n event.preventDefault();\n this.reactive.dispatch('addSubSection', parseInt(target.dataset.parentid ?? 0));\n }\n\n \/**\n * Handle a request to add a subsection as the first child of the parent\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestInsertSubSection(target, event) {\n event.preventDefault();\n this.reactive.dispatch('insertSubSection', parseInt(target.dataset.parentid ?? 0));\n }\n\n \/**\n * Handle a request to switch the section mode (displayed on the same page vs as a link).\n *\n * @param {Element} target the dispatch action element\n * @param {Event} event the triggered event\n *\/\n _requestSectionSwitchCollapsed(target, event) {\n event.preventDefault();\n this.reactive.dispatch('sectionSwitchCollapsed', target.dataset.id ?? 0);\n }\n}\n"],"names":["BaseComponent","create","name","selectors","ACTIONLINK","SECTIONLINK","classes","DISABLED","stateReady","state","addEventListener","this","element","_dispatchClick","event","target","closest","classList","contains","preventDefault","methodName","_actionMethodName","getAttribute","undefined","requestName","charAt","toUpperCase","slice","_requestDelete","sectionId","dataset","id","sectionInfo","reactive","get","cmlist","length","hassummary","rawtitle","children","key","component","done","strings","confirm","dispatch","fail","Notification","exception","_requestMergeup","_requestMoveSection","data","getExporter","course","sectiontitle","title","sections","singlesection","singlesectionmode","contentcollapsed","buildParents","parents","i","aftersectionid","lastchildid","type","ModalFactory","types","CANCEL","large","buttons","cancel","removeOnClose","then","modal","render","body","setBody","_setupMoveSection","getBody","show","_requestMoveCm","cmId","cmInfo","cmid","cmname","_setupMoveCm","modalBody","matches","for","targetSectionId","targetCmId","_destroyModal","hide","pendingDestroy","Pending","focus","setTimeout","destroy","resolve","links","querySelectorAll","re","RegExp","match","_disableLink","depth","maxsectiondepth","after","afterId","parseInt","parentId","parentid","style","pointerEvents","userSelect","add","setAttribute","_requestAddSubSection","_requestInsertSubSection","_requestSectionSwitchCollapsed"],"mappings":";;;;;;;8SA6B6BA,wBAMzBC,cAESC,KAAO,oCAEPC,UAAY,CACbC,wCACAC,yCAGCC,QAAU,CACXC,qBAURC,WAAWC,aACDD,WAAWC,YAEZC,iBACDC,KAAKC,QACL,QACAD,KAAKE,gBAIbA,eAAeC,aACLC,OAASD,MAAMC,OAAOC,QAAQL,KAAKR,UAAUC,gBAC9CW,iBAGDA,OAAOE,UAAUC,SAASP,KAAKL,QAAQC,sBACvCO,MAAMK,uBAKJC,WAAaT,KAAKU,kBAAkBN,OAAOO,aAAa,kCAErCC,IAArBZ,KAAKS,kBACAA,YAAYL,OAAQD,OAIjCO,kBAAkBnB,YACRsB,YAActB,KAAKuB,OAAO,GAAGC,cAAgBxB,KAAKyB,MAAM,2BAC5CH,aAStBI,eAAeb,OAAQD,qCACbe,UAAYd,OAAOe,QAAQC,OAC5BF,iBAGLf,MAAMK,uBAEAa,YAAcrB,KAAKsB,SAASC,IAAI,UAAWL,wCAElCG,YAAYG,0DAAU,IAC1BC,QAAUJ,YAAYK,YAAcL,YAAYM,UAAYN,YAAYO,SAASH,4BAC7E,CACP,CAACI,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,gBAAiBC,UAAW,uBAClC,CAACD,IAAK,MAAOC,UAAW,UACxB,CAACD,IAAK,KAAMC,UAAW,YACxBC,MAAMC,gCACQC,QACTD,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,IACR,UACSV,SAASY,SAAS,gBAAiB,CAAChB,kBAGlDiB,KAAKC,sBAAaC,gBAGhBf,SAASY,SAAS,gBAAiB,CAAChB,YAUjDoB,gBAAgBlC,OAAQD,sCACde,UAAYd,OAAOe,QAAQC,OAC5BF,iBAGLf,MAAMK,uBAEAa,YAAcrB,KAAKsB,SAASC,IAAI,UAAWL,yCAElCG,YAAYG,4DAAU,IAC1BC,QAAUJ,YAAYK,YAAcL,YAAYM,UAAYN,YAAYO,SAASH,4BAC7E,CACP,CAACI,IAAK,UAAWC,UAAW,UAC5B,CAACD,IAAK,eAAgBC,UAAW,uBACjC,CAACD,IAAK,MAAOC,UAAW,UACxB,CAACD,IAAK,KAAMC,UAAW,YACxBC,MAAMC,gCACQC,QACTD,QAAQ,GACRA,QAAQ,GACRA,QAAQ,GACRA,QAAQ,IACR,UACSV,SAASY,SAAS,iBAAkBhB,iBAGlDiB,KAAKC,sBAAaC,gBAGhBf,SAASY,SAAS,iBAAkBhB,WAUjDqB,oBAAoBnC,OAAQD,OACxBA,MAAMK,uBACAU,UAAYd,OAAOe,QAAQC,GAC3BC,YAAcrB,KAAKsB,SAASC,IAAI,UAAWL,WAE3CsB,KADWxC,KAAKsB,SAASmB,cACTC,OAAO1C,KAAKsB,SAASxB,OAC3C0C,KAAKG,aAAetB,YAAYuB,MAEH,IAAzBJ,KAAKK,SAASpB,QAAwD,MAAxC,UAAGe,KAAKK,SAAS,GAAGC,iBAElDN,KAAKO,kBAAoB,EACzBP,KAAKK,SAAS,GAAGG,kBAAmB,SAGlCC,aAAe,CAACJ,SAAUK,eACvB,IAAIC,KAAKN,SACVA,SAASM,GAAGD,QAAUA,QACtBL,SAASM,GAAGC,eAAkBD,EAAI,EAAKN,SAASM,EAAI,GAAG\/B,GAAK,EAC5D6B,aAAaJ,SAASM,GAAGvB,SAAUsB,QAAU,IAAML,SAASM,GAAG\/B,IAC\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\/F,OAAOe,QAAQ8E,OAClCG,SAAWD,SAAS\/F,OAAOe,QAAQkF,eACpC\/E,SAASY,SAAS,cAAe,CAAChB,WAAYgF,UAAqBE,eAEnEnB,cAAclB,MAAO9D,YASlC6F,aAAa7F,SACLA,UACAA,QAAQqG,MAAMC,cAAgB,OAC9BtG,QAAQqG,MAAME,WAAa,OAC3BvG,QAAQK,UAAUmG,IAAI,YACtBxG,QAAQyG,aAAa,iBAAiB,GACtCzG,QAAQF,iBAAiB,SAASI,OAASA,MAAMK,oBAUzDmG,sBAAsBvG,OAAQD,iCAC1BA,MAAMK,sBACDc,SAASY,SAAS,gBAAiBiE,uCAAS\/F,OAAOe,QAAQkF,gEAAY,IAShFO,yBAAyBxG,OAAQD,kCAC7BA,MAAMK,sBACDc,SAASY,SAAS,mBAAoBiE,wCAAS\/F,OAAOe,QAAQkF,kEAAY,IASnFQ,+BAA+BzG,OAAQD,8BACnCA,MAAMK,sBACDc,SAASY,SAAS,oDAA0B9B,OAAOe,QAAQC,oDAAM"}