diff --git a/course/format/amd/build/local/courseeditor/exporter.min.js b/course/format/amd/build/local/courseeditor/exporter.min.js
index 988e42ef300..fde0509105b 100644
--- a/course/format/amd/build/local/courseeditor/exporter.min.js
+++ b/course/format/amd/build/local/courseeditor/exporter.min.js
@@ -1,2 +1,2 @@
-define ("core_courseformat/local/courseeditor/exporter",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;function b(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function c(a){for(var c=1,e;c.\n\n/**\n * Module to export parts of the state and transform them to be used in templates\n * and as draggable data.\n *\n * @module core_courseformat/local/courseeditor/exporter\n * @class core_courseformat/local/courseeditor/exporter\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default class {\n\n /**\n * Class constructor.\n *\n * @param {CourseEditor} reactive the course editor object\n */\n constructor(reactive) {\n this.reactive = reactive;\n\n // Completions states are defined in lib/completionlib.php. There are 4 different completion\n // state values, however, the course index uses the same state for complete and complete_pass.\n // This is the reason why completed appears twice in the array.\n this.COMPLETIONS = ['incomplete', 'complete', 'complete', 'fail'];\n }\n\n /**\n * Generate the course export data from the state.\n *\n * @param {Object} state the current state.\n * @returns {Object}\n */\n course(state) {\n // Collect section information from the state.\n const data = {\n sections: [],\n editmode: this.reactive.isEditing,\n highlighted: state.course.highlighted ?? '',\n };\n const sectionlist = state.course.sectionlist ?? [];\n sectionlist.forEach(sectionid => {\n const sectioninfo = state.section.get(sectionid) ?? {};\n const section = this.section(state, sectioninfo);\n data.sections.push(section);\n });\n data.hassections = (data.sections.length != 0);\n\n return data;\n }\n\n /**\n * Generate a section export data from the state.\n *\n * @param {Object} state the current state.\n * @param {Object} sectioninfo the section state data.\n * @returns {Object}\n */\n section(state, sectioninfo) {\n const section = {\n ...sectioninfo,\n cms: [],\n };\n const cmlist = sectioninfo.cmlist ?? [];\n cmlist.forEach(cmid => {\n const cminfo = state.cm.get(cmid);\n const cm = this.cm(state, cminfo);\n section.cms.push(cm);\n });\n section.hascms = (section.cms.length != 0);\n\n return section;\n }\n\n /**\n * Generate a cm export data from the state.\n *\n * @param {Object} state the current state.\n * @param {Object} cminfo the course module state data.\n * @returns {Object}\n */\n cm(state, cminfo) {\n const cm = {\n ...cminfo,\n isactive: false,\n };\n return cm;\n }\n\n /**\n * Generate a dragable cm data structure.\n *\n * This method is used by any draggable course module element to generate drop data\n * for its reactive/dragdrop instance.\n *\n * @param {*} state the state object\n * @param {*} cmid the cours emodule id\n * @returns {Object|null}\n */\n cmDraggableData(state, cmid) {\n const cminfo = state.cm.get(cmid);\n if (!cminfo) {\n return null;\n }\n\n // Drop an activity over the next activity is the same as doing anything.\n let nextcmid;\n const section = state.section.get(cminfo.sectionid);\n const currentindex = section?.cmlist.indexOf(cminfo.id);\n if (currentindex !== undefined) {\n nextcmid = section?.cmlist[currentindex + 1];\n }\n\n return {\n type: 'cm',\n id: cminfo.id,\n name: cminfo.name,\n sectionid: cminfo.sectionid,\n nextcmid,\n };\n }\n\n /**\n * Generate a dragable cm data structure.\n *\n * This method is used by any draggable section element to generate drop data\n * for its reactive/dragdrop instance.\n *\n * @param {*} state the state object\n * @param {*} sectionid the cours section id\n * @returns {Object|null}\n */\n sectionDraggableData(state, sectionid) {\n const sectioninfo = state.section.get(sectionid);\n if (!sectioninfo) {\n return null;\n }\n return {\n type: 'section',\n id: sectioninfo.id,\n name: sectioninfo.name,\n number: sectioninfo.number,\n };\n }\n\n /**\n * Generate a compoetion export data from the cm element.\n *\n * @param {Object} state the current state.\n * @param {Object} cminfo the course module state data.\n * @returns {Object}\n */\n cmCompletion(state, cminfo) {\n const data = {\n statename: '',\n state: 'NaN',\n };\n if (cminfo.completionstate !== undefined) {\n data.state = cminfo.completionstate;\n data.hasstate = true;\n const statename = this.COMPLETIONS[cminfo.completionstate] ?? 'NaN';\n data[`is${statename}`] = true;\n }\n return data;\n }\n}\n"],"file":"exporter.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../src/local/courseeditor/exporter.js"],"names":["reactive","COMPLETIONS","state","data","sections","editmode","isEditing","highlighted","course","sectionlist","forEach","sectionid","sectioninfo","section","get","push","hassections","length","cms","cmlist","cmid","cminfo","cm","hascms","isactive","nextcmid","currentindex","indexOf","id","type","name","number","statename","completionstate","hasstate"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module to export parts of the state and transform them to be used in templates\n * and as draggable data.\n *\n * @module core_courseformat/local/courseeditor/exporter\n * @class core_courseformat/local/courseeditor/exporter\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default class {\n\n /**\n * Class constructor.\n *\n * @param {CourseEditor} reactive the course editor object\n */\n constructor(reactive) {\n this.reactive = reactive;\n\n // Completions states are defined in lib/completionlib.php. There are 4 different completion\n // state values, however, the course index uses the same state for complete and complete_pass.\n // This is the reason why completed appears twice in the array.\n this.COMPLETIONS = ['incomplete', 'complete', 'complete', 'fail'];\n }\n\n /**\n * Generate the course export data from the state.\n *\n * @param {Object} state the current state.\n * @returns {Object}\n */\n course(state) {\n // Collect section information from the state.\n const data = {\n sections: [],\n editmode: this.reactive.isEditing,\n highlighted: state.course.highlighted ?? '',\n };\n const sectionlist = state.course.sectionlist ?? [];\n sectionlist.forEach(sectionid => {\n const sectioninfo = state.section.get(sectionid) ?? {};\n const section = this.section(state, sectioninfo);\n data.sections.push(section);\n });\n data.hassections = (data.sections.length != 0);\n\n return data;\n }\n\n /**\n * Generate a section export data from the state.\n *\n * @param {Object} state the current state.\n * @param {Object} sectioninfo the section state data.\n * @returns {Object}\n */\n section(state, sectioninfo) {\n const section = {\n ...sectioninfo,\n highlighted: state.course.highlighted ?? '',\n cms: [],\n };\n const cmlist = sectioninfo.cmlist ?? [];\n cmlist.forEach(cmid => {\n const cminfo = state.cm.get(cmid);\n const cm = this.cm(state, cminfo);\n section.cms.push(cm);\n });\n section.hascms = (section.cms.length != 0);\n\n return section;\n }\n\n /**\n * Generate a cm export data from the state.\n *\n * @param {Object} state the current state.\n * @param {Object} cminfo the course module state data.\n * @returns {Object}\n */\n cm(state, cminfo) {\n const cm = {\n ...cminfo,\n isactive: false,\n };\n return cm;\n }\n\n /**\n * Generate a dragable cm data structure.\n *\n * This method is used by any draggable course module element to generate drop data\n * for its reactive/dragdrop instance.\n *\n * @param {*} state the state object\n * @param {*} cmid the cours emodule id\n * @returns {Object|null}\n */\n cmDraggableData(state, cmid) {\n const cminfo = state.cm.get(cmid);\n if (!cminfo) {\n return null;\n }\n\n // Drop an activity over the next activity is the same as doing anything.\n let nextcmid;\n const section = state.section.get(cminfo.sectionid);\n const currentindex = section?.cmlist.indexOf(cminfo.id);\n if (currentindex !== undefined) {\n nextcmid = section?.cmlist[currentindex + 1];\n }\n\n return {\n type: 'cm',\n id: cminfo.id,\n name: cminfo.name,\n sectionid: cminfo.sectionid,\n nextcmid,\n };\n }\n\n /**\n * Generate a dragable cm data structure.\n *\n * This method is used by any draggable section element to generate drop data\n * for its reactive/dragdrop instance.\n *\n * @param {*} state the state object\n * @param {*} sectionid the cours section id\n * @returns {Object|null}\n */\n sectionDraggableData(state, sectionid) {\n const sectioninfo = state.section.get(sectionid);\n if (!sectioninfo) {\n return null;\n }\n return {\n type: 'section',\n id: sectioninfo.id,\n name: sectioninfo.name,\n number: sectioninfo.number,\n };\n }\n\n /**\n * Generate a compoetion export data from the cm element.\n *\n * @param {Object} state the current state.\n * @param {Object} cminfo the course module state data.\n * @returns {Object}\n */\n cmCompletion(state, cminfo) {\n const data = {\n statename: '',\n state: 'NaN',\n };\n if (cminfo.completionstate !== undefined) {\n data.state = cminfo.completionstate;\n data.hasstate = true;\n const statename = this.COMPLETIONS[cminfo.completionstate] ?? 'NaN';\n data[`is${statename}`] = true;\n }\n return data;\n }\n}\n"],"file":"exporter.min.js"}
\ No newline at end of file
diff --git a/course/format/amd/build/local/courseindex/cm.min.js b/course/format/amd/build/local/courseindex/cm.min.js
index fbfb28c7d1b..7f17990e6e9 100644
--- a/course/format/amd/build/local/courseindex/cm.min.js
+++ b/course/format/amd/build/local/courseindex/cm.min.js
@@ -1,2 +1,2 @@
-define ("core_courseformat/local/courseindex/cm",["exports","core_courseformat/local/courseeditor/dndcmitem","core/templates","core/prefetch"],function(a,b,c,d){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=e(b);c=e(c);d=e(d);function e(a){return a&&a.__esModule?a:{default:a}}function f(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){f=function(a){return typeof a}}else{f=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return f(a)}function g(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function h(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var i=a.apply(b,c);function f(a){g(i,d,e,f,h,"next",a)}function h(a){g(i,d,e,f,h,"throw",a)}f(void 0)})}}function i(a,b){if(!(a instanceof b)){throw new TypeError("Cannot call a class as a function")}}function j(a,b){for(var c=0,d;c.\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: state.cm.get(this.id),\n });\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n\n}\n"],"file":"cm.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../src/local/courseindex/cm.js"],"names":["Prefetch","prefetchTemplate","Component","name","selectors","CM_NAME","CM_COMPLETION","classes","CMHIDDEN","LOCKED","RESTRICTIONS","id","element","dataset","state","configDragDrop","_refreshCompletion","cm","get","watch","handler","remove","_refreshCm","classList","toggle","visible","getElement","innerHTML","DRAGGING","dragging","locked","hascmrectrictions","reactive","isEditing","istrackeduser","completionElement","value","completionstate","exporter","getExporter","data","cmCompletion","Templates","renderForPromise","html","js","replaceNode","target","document","getElementById","DndCmItem"],"mappings":"gPA0BA,OACA,OACA,O,8+DAIAA,UAASC,gBAAT,qD,GAEqBC,CAAAA,C,+HAKR,CAEL,KAAKC,IAAL,CAAY,gBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,OAAO,uBADM,CAEbC,aAAa,6BAFA,CAAjB,CAKA,KAAKC,OAAL,CAAe,CACXC,QAAQ,CAAE,QADC,CAEXC,MAAM,CAAE,gBAFG,CAGXC,YAAY,CAAE,cAHH,CAAf,CAMA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,8CAqBUG,C,CAAO,CACd,KAAKC,cAAL,CAAoB,KAAKJ,EAAzB,EAEA,KAAKK,kBAAL,CAAwB,CACpBF,KAAK,CAALA,CADoB,CAEpBF,OAAO,CAAEE,CAAK,CAACG,EAAN,CAASC,GAAT,CAAa,KAAKP,EAAlB,CAFW,CAAxB,CAIH,C,iDAOa,CACV,MAAO,CACH,CAACQ,KAAK,cAAQ,KAAKR,EAAb,aAAN,CAAkCS,OAAO,CAAE,KAAKC,MAAhD,CADG,CAEH,CAACF,KAAK,cAAQ,KAAKR,EAAb,aAAN,CAAkCS,OAAO,CAAE,KAAKE,UAAhD,CAFG,CAGH,CAACH,KAAK,cAAQ,KAAKR,EAAb,6BAAN,CAAkDS,OAAO,CAAE,KAAKJ,kBAAhE,CAHG,CAKV,C,gDAQqB,WAAVJ,CAAU,GAAVA,OAAU,CAElB,KAAKA,OAAL,CAAaW,SAAb,CAAuBC,MAAvB,CAA8B,KAAKjB,OAAL,CAAaC,QAA3C,CAAqD,CAACI,CAAO,CAACa,OAA9D,EACA,KAAKC,UAAL,CAAgB,KAAKtB,SAAL,CAAeC,OAA/B,EAAwCsB,SAAxC,CAAoDf,CAAO,CAACT,IAA5D,CACA,KAAKS,OAAL,CAAaW,SAAb,CAAuBC,MAAvB,CAA8B,KAAKjB,OAAL,CAAaqB,QAA3C,WAAqDhB,CAAO,CAACiB,QAA7D,oBACA,KAAKjB,OAAL,CAAaW,SAAb,CAAuBC,MAAvB,CAA8B,KAAKjB,OAAL,CAAaE,MAA3C,WAAmDG,CAAO,CAACkB,MAA3D,oBACA,KAAKlB,OAAL,CAAaW,SAAb,CAAuBC,MAAvB,CAA8B,KAAKjB,OAAL,CAAaG,YAA3C,WAAyDE,CAAO,CAACmB,iBAAjE,oBACA,KAAKD,MAAL,CAAclB,CAAO,CAACkB,MACzB,C,gMASyBhB,C,GAAAA,K,CAAOF,C,GAAAA,O,MAEzB,KAAKoB,QAAL,CAAcC,SAAd,EAA2B,CAACrB,CAAO,CAACsB,a,mDAIlCC,C,CAAoB,KAAKT,UAAL,CAAgB,KAAKtB,SAAL,CAAeE,aAA/B,C,MACtB6B,CAAiB,CAACtB,OAAlB,CAA0BuB,KAA1B,EAAmCxB,CAAO,CAACyB,e,mDAKzCC,C,CAAW,KAAKN,QAAL,CAAcO,WAAd,E,CACXC,C,CAAOF,CAAQ,CAACG,YAAT,CAAsB3B,CAAtB,CAA6BF,CAA7B,C,0BAGgB8B,WAAUC,gBAAV,oDAA+CH,CAA/C,C,kBAAlBI,C,GAAAA,I,CAAMC,C,GAAAA,E,CACbH,UAAUI,WAAV,CAAsBX,CAAtB,CAAyCS,CAAzC,CAA+CC,CAA/C,E,qOA1EIE,C,CAAQ3C,C,CAAW,CAC3B,MAAO,IAAIF,CAAAA,CAAJ,CAAc,CACjBU,OAAO,CAAEoC,QAAQ,CAACC,cAAT,CAAwBF,CAAxB,CADQ,CAEjB3C,SAAS,CAATA,CAFiB,CAAd,CAIV,C,cAnCkC8C,S","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index cm component.\n *\n * This component is used to control specific course modules interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/cm\n * @class core_courseformat/local/courseindex/cm\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DndCmItem from 'core_courseformat/local/courseeditor/dndcmitem';\nimport Templates from 'core/templates';\nimport Prefetch from 'core/prefetch';\n\n// Prefetch the completion icons template.\nconst completionTemplate = 'core_courseformat/local/courseindex/cmcompletion';\nPrefetch.prefetchTemplate(completionTemplate);\n\nexport default class Component extends DndCmItem {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_cm';\n // Default query selectors.\n this.selectors = {\n CM_NAME: `[data-for='cm_name']`,\n CM_COMPLETION: `[data-for='cm_completion']`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n CMHIDDEN: 'dimmed',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n };\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustache template.\n *\n * @param {element|string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the course state.\n */\n stateReady(state) {\n this.configDragDrop(this.id);\n // Refresh completion icon.\n this._refreshCompletion({\n state,\n element: state.cm.get(this.id),\n });\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `cm[${this.id}]:deleted`, handler: this.remove},\n {watch: `cm[${this.id}]:updated`, handler: this._refreshCm},\n {watch: `cm[${this.id}].completionstate:updated`, handler: this._refreshCompletion},\n ];\n }\n\n /**\n * Update a course index cm using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n _refreshCm({element}) {\n // Update classes.\n this.element.classList.toggle(this.classes.CMHIDDEN, !element.visible);\n this.getElement(this.selectors.CM_NAME).innerHTML = element.name;\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false);\n this.locked = element.locked;\n }\n\n /**\n * Update the activity completion icon.\n *\n * @param {Object} details the update details\n * @param {Object} details.state the state data\n * @param {Object} details.element the element data\n */\n async _refreshCompletion({state, element}) {\n // No completion icons are displayed in edit mode.\n if (this.reactive.isEditing || !element.istrackeduser) {\n return;\n }\n // Check if the completion value has changed.\n const completionElement = this.getElement(this.selectors.CM_COMPLETION);\n if (completionElement.dataset.value == element.completionstate) {\n return;\n }\n\n // Collect section information from the state.\n const exporter = this.reactive.getExporter();\n const data = exporter.cmCompletion(state, element);\n\n try {\n const {html, js} = await Templates.renderForPromise(completionTemplate, data);\n Templates.replaceNode(completionElement, html, js);\n } catch (error) {\n throw error;\n }\n }\n\n}\n"],"file":"cm.min.js"}
\ No newline at end of file
diff --git a/course/format/amd/build/local/courseindex/section.min.js b/course/format/amd/build/local/courseindex/section.min.js
index 1adbaf6b84e..00b3580a867 100644
--- a/course/format/amd/build/local/courseindex/section.min.js
+++ b/course/format/amd/build/local/courseindex/section.min.js
@@ -1,2 +1,2 @@
-define ("core_courseformat/local/courseindex/section",["exports","core_courseformat/local/courseindex/sectiontitle","core_courseformat/local/courseeditor/dndsection"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){"@babel/helpers - typeof";if("function"==typeof Symbol&&"symbol"==typeof Symbol.iterator){e=function(a){return typeof a}}else{e=function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a}}return e(a)}function f(a,b){var c=Object.keys(a);if(Object.getOwnPropertySymbols){var d=Object.getOwnPropertySymbols(a);if(b)d=d.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable});c.push.apply(c,d)}return c}function g(a){for(var b=1,c;b.\n\n/**\n * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n LOCKED: 'editinprogress',\n };\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: this.getElement(this.selectors.SECTION_ITEM),\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:deleted`, handler: this.remove},\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} param details the update details.\n * @param {Object} param.element\n */\n _refreshSection({element}) {\n // Update classes.\n const sectionitem = this.getElement(this.selectors.SECTION_ITEM);\n sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.locked = element.locked;\n // Update title.\n this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n}\n"],"file":"section.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../src/local/courseindex/section.js"],"names":["Component","name","selectors","SECTION_ITEM","SECTION_TITLE","CM_LAST","classes","SECTIONHIDDEN","SECTIONCURRENT","LOCKED","RESTRICTIONS","id","element","dataset","state","configState","reactive","isEditing","supportComponents","titleitem","SectionTitle","getElement","fullregion","configDragDrop","watch","handler","remove","_refreshSection","sectionitem","classList","toggle","visible","current","DRAGGING","dragging","locked","hasrestrictions","innerHTML","title","target","document","getElementById","DndSection"],"mappings":"sQA0BA,OACA,O,63EAEqBA,CAAAA,C,+HAKR,CAEL,KAAKC,IAAL,CAAY,qBAAZ,CAEA,KAAKC,SAAL,CAAiB,CACbC,YAAY,4BADC,CAEbC,aAAa,6BAFA,CAGbC,OAAO,+BAHM,CAAjB,CAMA,KAAKC,OAAL,CAAe,CACXC,aAAa,CAAE,QADJ,CAEXC,cAAc,CAAE,SAFL,CAGXC,MAAM,CAAE,gBAHG,CAIXC,YAAY,CAAE,cAJH,CAAf,CAQA,KAAKC,EAAL,CAAU,KAAKC,OAAL,CAAaC,OAAb,CAAqBF,EAClC,C,8CAqBUG,C,CAAO,CACd,KAAKC,WAAL,CAAiBD,CAAjB,EAEA,GAAI,KAAKE,QAAL,CAAcC,SAAd,EAA2B,KAAKD,QAAL,CAAcE,iBAA7C,CAAgE,CAE5D,GAAMC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,MACX,IADW,EAEdR,OAAO,CAAE,KAAKS,UAAL,CAAgB,KAAKnB,SAAL,CAAeC,YAA/B,CAFK,CAGdmB,UAAU,CAAE,KAAKV,OAHH,GAAlB,CAKA,KAAKW,cAAL,CAAoBJ,CAApB,CACH,CACJ,C,iDAOa,CACV,MAAO,CACH,CAACK,KAAK,mBAAa,KAAKb,EAAlB,aAAN,CAAuCc,OAAO,CAAE,KAAKC,MAArD,CADG,CAEH,CAACF,KAAK,mBAAa,KAAKb,EAAlB,aAAN,CAAuCc,OAAO,CAAE,KAAKE,eAArD,CAFG,CAIV,C,6CAOW,CACR,MAAO,MAAKN,UAAL,CAAgB,KAAKnB,SAAL,CAAeG,OAA/B,CACV,C,0DAQ0B,WAAVO,CAAU,GAAVA,OAAU,CAEjBgB,CAAW,CAAG,KAAKP,UAAL,CAAgB,KAAKnB,SAAL,CAAeC,YAA/B,CAFG,CAGvByB,CAAW,CAACC,SAAZ,CAAsBC,MAAtB,CAA6B,KAAKxB,OAAL,CAAaC,aAA1C,CAAyD,CAACK,CAAO,CAACmB,OAAlE,EACA,KAAKnB,OAAL,CAAaiB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKxB,OAAL,CAAaE,cAA3C,CAA2DI,CAAO,CAACoB,OAAnE,EACA,KAAKpB,OAAL,CAAaiB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKxB,OAAL,CAAa2B,QAA3C,WAAqDrB,CAAO,CAACsB,QAA7D,oBACA,KAAKtB,OAAL,CAAaiB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKxB,OAAL,CAAaG,MAA3C,WAAmDG,CAAO,CAACuB,MAA3D,oBACA,KAAKvB,OAAL,CAAaiB,SAAb,CAAuBC,MAAvB,CAA8B,KAAKxB,OAAL,CAAaI,YAA3C,WAAyDE,CAAO,CAACwB,eAAjE,oBACA,KAAKD,MAAL,CAAcvB,CAAO,CAACuB,MAAtB,CAEA,KAAKd,UAAL,CAAgB,KAAKnB,SAAL,CAAeE,aAA/B,EAA8CiC,SAA9C,CAA0DzB,CAAO,CAAC0B,KACrE,C,oCAhEWC,C,CAAQrC,C,CAAW,CAC3B,MAAO,IAAIF,CAAAA,CAAJ,CAAc,CACjBY,OAAO,CAAE4B,QAAQ,CAACC,cAAT,CAAwBF,CAAxB,CADQ,CAEjBrC,SAAS,CAATA,CAFiB,CAAd,CAIV,C,cAtCkCwC,S","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index section component.\n *\n * This component is used to control specific course section interactions like drag and drop.\n *\n * @module core_courseformat/local/courseindex/section\n * @class core_courseformat/local/courseindex/section\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport SectionTitle from 'core_courseformat/local/courseindex/sectiontitle';\nimport DndSection from 'core_courseformat/local/courseeditor/dndsection';\n\nexport default class Component extends DndSection {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'courseindex_section';\n // Default query selectors.\n this.selectors = {\n SECTION_ITEM: `[data-for='section_item']`,\n SECTION_TITLE: `[data-for='section_title']`,\n CM_LAST: `[data-for=\"cm\"]:last-child`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n SECTIONHIDDEN: 'dimmed',\n SECTIONCURRENT: 'current',\n LOCKED: 'editinprogress',\n RESTRICTIONS: 'rectrictions',\n };\n\n // We need our id to watch specific events.\n this.id = this.element.dataset.id;\n }\n\n /**\n * Static method to create a component instance form the mustahce template.\n *\n * @param {string} target the DOM main element or its ID\n * @param {object} selectors optional css selector overrides\n * @return {Component}\n */\n static init(target, selectors) {\n return new Component({\n element: document.getElementById(target),\n selectors,\n });\n }\n\n /**\n * Initial state ready method.\n *\n * @param {Object} state the initial state\n */\n stateReady(state) {\n this.configState(state);\n // Drag and drop is only available for components compatible course formats.\n if (this.reactive.isEditing && this.reactive.supportComponents) {\n // Init the inner dragable element passing the full section as affected region.\n const titleitem = new SectionTitle({\n ...this,\n element: this.getElement(this.selectors.SECTION_ITEM),\n fullregion: this.element,\n });\n this.configDragDrop(titleitem);\n }\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section[${this.id}]:deleted`, handler: this.remove},\n {watch: `section[${this.id}]:updated`, handler: this._refreshSection},\n ];\n }\n\n /**\n * Get the last CM element of that section.\n *\n * @returns {element|null}\n */\n getLastCm() {\n return this.getElement(this.selectors.CM_LAST);\n }\n\n /**\n * Update a course index section using the state information.\n *\n * @param {Object} param details the update details.\n * @param {Object} param.element\n */\n _refreshSection({element}) {\n // Update classes.\n const sectionitem = this.getElement(this.selectors.SECTION_ITEM);\n sectionitem.classList.toggle(this.classes.SECTIONHIDDEN, !element.visible);\n this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);\n this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);\n this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);\n this.element.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false);\n this.locked = element.locked;\n // Update title.\n this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;\n }\n}\n"],"file":"section.min.js"}
\ No newline at end of file
diff --git a/course/format/amd/src/local/courseeditor/exporter.js b/course/format/amd/src/local/courseeditor/exporter.js
index bf5b4943ff6..c68a6cd3737 100644
--- a/course/format/amd/src/local/courseeditor/exporter.js
+++ b/course/format/amd/src/local/courseeditor/exporter.js
@@ -72,6 +72,7 @@ export default class {
section(state, sectioninfo) {
const section = {
...sectioninfo,
+ highlighted: state.course.highlighted ?? '',
cms: [],
};
const cmlist = sectioninfo.cmlist ?? [];
diff --git a/course/format/amd/src/local/courseindex/cm.js b/course/format/amd/src/local/courseindex/cm.js
index 4146808ccb3..4b4e903965d 100644
--- a/course/format/amd/src/local/courseindex/cm.js
+++ b/course/format/amd/src/local/courseindex/cm.js
@@ -49,6 +49,7 @@ export default class Component extends DndCmItem {
this.classes = {
CMHIDDEN: 'dimmed',
LOCKED: 'editinprogress',
+ RESTRICTIONS: 'rectrictions',
};
// We need our id to watch specific events.
this.id = this.element.dataset.id;
@@ -107,6 +108,7 @@ export default class Component extends DndCmItem {
this.getElement(this.selectors.CM_NAME).innerHTML = element.name;
this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);
this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);
+ this.element.classList.toggle(this.classes.RESTRICTIONS, element.hascmrectrictions ?? false);
this.locked = element.locked;
}
diff --git a/course/format/amd/src/local/courseindex/section.js b/course/format/amd/src/local/courseindex/section.js
index cde594d60dd..6cf3092d66e 100644
--- a/course/format/amd/src/local/courseindex/section.js
+++ b/course/format/amd/src/local/courseindex/section.js
@@ -46,6 +46,7 @@ export default class Component extends DndSection {
SECTIONHIDDEN: 'dimmed',
SECTIONCURRENT: 'current',
LOCKED: 'editinprogress',
+ RESTRICTIONS: 'rectrictions',
};
// We need our id to watch specific events.
@@ -119,6 +120,7 @@ export default class Component extends DndSection {
this.element.classList.toggle(this.classes.SECTIONCURRENT, element.current);
this.element.classList.toggle(this.classes.DRAGGING, element.dragging ?? false);
this.element.classList.toggle(this.classes.LOCKED, element.locked ?? false);
+ this.element.classList.toggle(this.classes.RESTRICTIONS, element.hasrestrictions ?? false);
this.locked = element.locked;
// Update title.
this.getElement(this.selectors.SECTION_TITLE).innerHTML = element.title;
diff --git a/course/format/classes/output/local/state/cm.php b/course/format/classes/output/local/state/cm.php
index 9d4d71d92ce..a992d01c986 100644
--- a/course/format/classes/output/local/state/cm.php
+++ b/course/format/classes/output/local/state/cm.php
@@ -71,7 +71,7 @@ class cm implements renderable {
* @return stdClass data context for a mustache template
*/
public function export_for_template(\renderer_base $output): stdClass {
- global $USER;
+ global $USER, $CFG;
$format = $this->format;
$section = $this->section;
@@ -91,6 +91,15 @@ class cm implements renderable {
$info = new info_module($cm);
$data->accessvisible = ($data->visible && $info->is_available_for_all());
+ // Check if restriction access are visible to the user.
+ $canviewhidden = has_capability('moodle/course:viewhiddenactivities', $cm->context);
+ if (!empty($CFG->enableavailability) && $canviewhidden) {
+ // Some users can see restrictions even if it does not apply to them.
+ $data->hascmrectrictions = !empty($cm->availableinfo);
+ } else {
+ $data->hascmrectrictions = !$data->accessvisible || !$cm->uservisible;
+ }
+
// Add url if the activity is compatible.
$url = $cm->url;
if ($url) {
diff --git a/course/format/classes/output/local/state/section.php b/course/format/classes/output/local/state/section.php
index afabd2cc8f1..82438df970b 100644
--- a/course/format/classes/output/local/state/section.php
+++ b/course/format/classes/output/local/state/section.php
@@ -20,6 +20,7 @@ use core_courseformat\base as course_format;
use section_info;
use renderable;
use stdClass;
+use context_course;
/**
* Contains the ajax update section structure.
@@ -54,6 +55,7 @@ class section implements renderable {
* @return array data context for a mustache template
*/
public function export_for_template(\renderer_base $output): stdClass {
+ global $CFG;
$format = $this->format;
$course = $format->get_course();
@@ -88,6 +90,17 @@ class section implements renderable {
'contentexpanded' => $contentexpanded
];
+ // If the section availability restrictions must be displayed.
+ $canviewhidden = has_capability(
+ 'moodle/course:viewhiddenactivities',
+ context_course::instance($course->id)
+ );
+ if (!empty($CFG->enableavailability) && $canviewhidden) {
+ $data->hasrestrictions = !empty($section->availableinfo);
+ } else {
+ $data->hasrestrictions = false;
+ }
+
if (empty($modinfo->sections[$section->section])) {
return $data;
}
diff --git a/course/format/templates/local/courseindex/cm.mustache b/course/format/templates/local/courseindex/cm.mustache
index 4c2835068e7..bb4314dd2b7 100644
--- a/course/format/templates/local/courseindex/cm.mustache
+++ b/course/format/templates/local/courseindex/cm.mustache
@@ -28,11 +28,13 @@
"isactive": 1,
"uniqid": "0",
"isactive": 1,
- "accessvisible": 1
+ "accessvisible": 1,
+ "hascmrectrictions": 0
}
}}