diff --git a/.upgradenotes/MDL-80295-2025082810134999.yml b/.upgradenotes/MDL-80295-2025082810134999.yml new file mode 100644 index 00000000000..f1a95bb7fa0 --- /dev/null +++ b/.upgradenotes/MDL-80295-2025082810134999.yml @@ -0,0 +1,8 @@ +issueNumber: MDL-80295 +notes: + core_course: + - message: >- + The getModulesData and activityModules methods from + core_course/local/activitychooser/repository are deprecated. Use + getSectionModulesData and sectionActivityModules instead + type: deprecated diff --git a/public/course/amd/build/activitychooser.min.js b/public/course/amd/build/activitychooser.min.js index 57fcf71f448..ad11baff3e1 100644 --- a/public/course/amd/build/activitychooser.min.js +++ b/public/course/amd/build/activitychooser.min.js @@ -1,10 +1,10 @@ -define("core_course/activitychooser",["exports","core_course/local/activitychooser/dialogue","core_course/local/activitychooser/repository","core_course/local/activitychooser/selectors","core/custom_interaction_events","core/pending"],(function(_exports,ChooserDialogue,Repository,_selectors,_custom_interaction_events,_pending){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj} +define("core_course/activitychooser",["exports","core_course/local/activitychooser/dialogue","core/custom_interaction_events","core/log","core/pending","core_course/local/activitychooser/repository","core_course/local/activitychooser/selectors"],(function(_exports,ChooserDialogue,_custom_interaction_events,_log,_pending,Repository,_selectors){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj} /** * A type of dialogue used as for choosing modules in a course. * * @module core_course/activitychooser * @copyright 2020 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,ChooserDialogue=_interopRequireWildcard(ChooserDialogue),Repository=_interopRequireWildcard(Repository),_selectors=_interopRequireDefault(_selectors),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_pending=_interopRequireDefault(_pending);let initialized=!1;_exports.init=(courseId,chooserConfig)=>{const pendingPromise=new _pending.default;void 0!==chooserConfig.tabmode&&window.console.warn("The tabmode config option has been deprecated and will be ignored."),registerListenerEvents(courseId),pendingPromise.resolve()};const registerListenerEvents=courseId=>{if(initialized)return;initialized=!0;const eventsToHandle=["click",_custom_interaction_events.default.events.activate,_custom_interaction_events.default.events.keyboardActivate];_custom_interaction_events.default.define(document,eventsToHandle),eventsToHandle.forEach((eventToHandle=>{document.addEventListener(eventToHandle,(async event=>{if(!event.target.closest(_selectors.default.elements.sectionmodchooser))return;const position=function(target){var _caller$dataset$secti,_caller$dataset,_caller$dataset$befor,_caller$dataset2;let caller,sectionNum;const sectionDiv=target.closest(_selectors.default.elements.section),button=target.closest(_selectors.default.elements.sectionmodchooser);null!==sectionDiv&§ionDiv.hasAttribute("data-number")?(caller=sectionDiv,sectionNum=sectionDiv.getAttribute("data-number")):(caller=button,caller.hasAttribute("data-sectionid")&&(window.console.warn("The data-sectionid attribute has been deprecated. Please update your code to use data-sectionnum instead."),caller.setAttribute("data-sectionnum",caller.dataset.sectionid)),sectionNum=caller.dataset.sectionnum);return{sectionNum:sectionNum,sectionReturnNum:null!==(_caller$dataset$secti=null===(_caller$dataset=caller.dataset)||void 0===_caller$dataset?void 0:_caller$dataset.sectionreturnnum)&&void 0!==_caller$dataset$secti?_caller$dataset$secti:null,beforeMod:null!==(_caller$dataset$befor=null===(_caller$dataset2=caller.dataset)||void 0===_caller$dataset2?void 0:_caller$dataset2.beforemod)&&void 0!==_caller$dataset$befor?_caller$dataset$befor:null}}(event.target),footerDataPromise=Repository.getModalFooterData(courseId,position.sectionNum),modulesDataPromise=Repository.getModulesData(courseId,position.sectionNum,position.sectionReturnNum,position.beforeMod);ChooserDialogue.displayActivityChooserModal(footerDataPromise,modulesDataPromise)}))}))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,ChooserDialogue=_interopRequireWildcard(ChooserDialogue),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_log=_interopRequireDefault(_log),_pending=_interopRequireDefault(_pending),Repository=_interopRequireWildcard(Repository),_selectors=_interopRequireDefault(_selectors);let initialized=!1;_exports.init=(courseId,chooserConfig)=>{const pendingPromise=new _pending.default;void 0!==chooserConfig.tabmode&&window.console.warn("The tabmode config option has been deprecated and will be ignored."),registerListenerEvents(courseId),pendingPromise.resolve()};const registerListenerEvents=courseId=>{if(initialized)return;initialized=!0;const eventsToHandle=["click",_custom_interaction_events.default.events.activate,_custom_interaction_events.default.events.keyboardActivate];_custom_interaction_events.default.define(document,eventsToHandle),eventsToHandle.forEach((eventToHandle=>{document.addEventListener(eventToHandle,(async event=>{if(!event.target.closest(_selectors.default.elements.sectionmodchooser))return;const position=function(target){var _ref,_caller$dataset$secti,_caller$dataset,_caller$dataset2,_caller$dataset$secti2,_caller$dataset3,_caller$dataset$befor,_caller$dataset4;let caller,sectionNum=null,sectionId=null;const sectionDiv=target.closest(_selectors.default.elements.section),button=target.closest(_selectors.default.elements.sectionmodchooser);null!==sectionDiv&&(sectionDiv.hasAttribute("data-number")||sectionDiv.hasAttribute("data-id"))?(caller=sectionDiv,sectionNum=sectionDiv.getAttribute("data-number"),sectionId=sectionDiv.getAttribute("data-id")):(caller=button,caller.hasAttribute("data-sectionid")&&(window.console.warn("The data-sectionid attribute has been deprecated. Please update your code to use data-section-id passing the real section ID instead."),caller.setAttribute("data-sectionnum",caller.dataset.sectionid)),sectionNum=caller.dataset.sectionnum,sectionId=caller.getAttribute("data-section-id"));return{sectionNum:sectionNum,sectionId:sectionId,sectionReturnNum:null!==(_ref=null!==(_caller$dataset$secti=null===(_caller$dataset=caller.dataset)||void 0===_caller$dataset?void 0:_caller$dataset.sectionreturnnum)&&void 0!==_caller$dataset$secti?_caller$dataset$secti:null===(_caller$dataset2=caller.dataset)||void 0===_caller$dataset2?void 0:_caller$dataset2.sectionreturn)&&void 0!==_ref?_ref:null,sectionReturnId:null!==(_caller$dataset$secti2=null===(_caller$dataset3=caller.dataset)||void 0===_caller$dataset3?void 0:_caller$dataset3.sectionreturnid)&&void 0!==_caller$dataset$secti2?_caller$dataset$secti2:null,beforeMod:null!==(_caller$dataset$befor=null===(_caller$dataset4=caller.dataset)||void 0===_caller$dataset4?void 0:_caller$dataset4.beforemod)&&void 0!==_caller$dataset$befor?_caller$dataset$befor:null}}(event.target),footerDataPromise=Repository.getModalFooterData(courseId,position.sectionNum);let modulesDataPromise;position.sectionId&&""!==position.sectionId?modulesDataPromise=Repository.getSectionModulesData(courseId,position.sectionId,position.sectionReturnNum,position.beforeMod):(_log.default.debug("Having only the section number attribute in the activity chooser is deprecated. Please add the data-section-id attribute."),modulesDataPromise=Repository.getModulesData(courseId,position.sectionNum,position.sectionReturnNum,position.beforeMod)),ChooserDialogue.displayActivityChooserModal(footerDataPromise,modulesDataPromise)}))}))}})); //# sourceMappingURL=activitychooser.min.js.map \ No newline at end of file diff --git a/public/course/amd/build/activitychooser.min.js.map b/public/course/amd/build/activitychooser.min.js.map index 554c4ec8b02..05e92983486 100644 --- a/public/course/amd/build/activitychooser.min.js.map +++ b/public/course/amd/build/activitychooser.min.js.map @@ -1 +1 @@ -{"version":3,"file":"activitychooser.min.js","sources":["../src/activitychooser.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 * A type of dialogue used as for choosing modules in a course.\n *\n * @module core_course/activitychooser\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport CustomEvents from 'core/custom_interaction_events';\nimport Pending from 'core/pending';\n\nlet initialized = false;\n\n/**\n * Set up the activity chooser.\n *\n * @method init\n * @param {Number} courseId Course ID to use later on in fetchModules()\n * @param {Object} chooserConfig Any PHP config settings that we may need to reference\n */\nexport const init = (courseId, chooserConfig) => {\n const pendingPromise = new Pending();\n\n // TODO: Remove the chooserConfig in Moodle 6.0 (MDL-85655)\n if (chooserConfig.tabmode !== undefined) {\n window.console.warn('The tabmode config option has been deprecated and will be ignored.');\n }\n\n registerListenerEvents(courseId);\n\n pendingPromise.resolve();\n};\n\n/**\n * Once a selection has been made make the modal & module information and pass it along\n *\n * @method registerListenerEvents\n * @param {Number} courseId\n */\nconst registerListenerEvents = (courseId) => {\n if (initialized) {\n return;\n }\n initialized = true;\n\n const eventsToHandle = [\n 'click',\n CustomEvents.events.activate,\n CustomEvents.events.keyboardActivate\n ];\n\n CustomEvents.define(document, eventsToHandle);\n\n // Display module chooser event listeners.\n eventsToHandle.forEach((eventToHandle) => {\n document.addEventListener(eventToHandle, async(event) => {\n if (!event.target.closest(selectors.elements.sectionmodchooser)) {\n return;\n }\n const position = getCoursePositionFromTarget(event.target);\n\n const footerDataPromise = Repository.getModalFooterData(courseId, position.sectionNum);\n\n const modulesDataPromise = Repository.getModulesData(\n courseId,\n position.sectionNum,\n position.sectionReturnNum,\n position.beforeMod,\n );\n\n ChooserDialogue.displayActivityChooserModal(footerDataPromise, modulesDataPromise);\n });\n });\n};\n\n/**\n * Return the course position of a target add activity element.\n *\n * @param {HTMLElement} target The target element.\n * @return {Object} The course position of the target.\n * @property {Number} sectionNum The section number.\n * @property {Number|null} sectionReturnNum The section return number.\n * @property {Number|null} beforeMod The ID of the cm to add the modules before.\n */\nfunction getCoursePositionFromTarget(target) {\n let caller;\n let sectionNum;\n // We need to know who called this.\n // Standard courses use the ID in the main section info.\n const sectionDiv = target.closest(selectors.elements.section);\n // Front page courses need some special handling.\n const button = target.closest(selectors.elements.sectionmodchooser);\n\n // If we don't have a section number use the fallback ID.\n // We always want the sectionDiv caller first as it keeps track of section number's after DnD changes.\n // The button attribute is always just a fallback for us as the section div is not always available.\n // A YUI change could be done maybe to only update the button attribute but we are going for minimal change here.\n if (sectionDiv !== null && sectionDiv.hasAttribute('data-number')) {\n // We check for attributes just in case of outdated contrib course formats.\n caller = sectionDiv;\n sectionNum = sectionDiv.getAttribute('data-number');\n } else {\n caller = button;\n\n if (caller.hasAttribute('data-sectionid')) {\n window.console.warn(\n 'The data-sectionid attribute has been deprecated. ' +\n 'Please update your code to use data-sectionnum instead.'\n );\n caller.setAttribute('data-sectionnum', caller.dataset.sectionid);\n }\n sectionNum = caller.dataset.sectionnum;\n }\n return {\n sectionNum,\n sectionReturnNum: caller.dataset?.sectionreturnnum ?? null,\n beforeMod: caller.dataset?.beforemod ?? null,\n };\n}\n"],"names":["initialized","courseId","chooserConfig","pendingPromise","Pending","undefined","tabmode","window","console","warn","registerListenerEvents","resolve","eventsToHandle","CustomEvents","events","activate","keyboardActivate","define","document","forEach","eventToHandle","addEventListener","async","event","target","closest","selectors","elements","sectionmodchooser","position","caller","sectionNum","sectionDiv","section","button","hasAttribute","getAttribute","setAttribute","dataset","sectionid","sectionnum","sectionReturnNum","_caller$dataset","sectionreturnnum","beforeMod","_caller$dataset2","beforemod","getCoursePositionFromTarget","footerDataPromise","Repository","getModalFooterData","modulesDataPromise","getModulesData","ChooserDialogue","displayActivityChooserModal"],"mappings":";;;;;;;oWA6BIA,aAAc,gBASE,CAACC,SAAUC,uBACrBC,eAAiB,IAAIC,sBAGGC,IAA1BH,cAAcI,SACdC,OAAOC,QAAQC,KAAK,sEAGxBC,uBAAuBT,UAEvBE,eAAeQ,iBASbD,uBAA0BT,cACxBD,mBAGJA,aAAc,QAERY,eAAiB,CACnB,QACAC,mCAAaC,OAAOC,SACpBF,mCAAaC,OAAOE,qDAGXC,OAAOC,SAAUN,gBAG9BA,eAAeO,SAASC,gBACpBF,SAASG,iBAAiBD,eAAeE,MAAAA,YAChCC,MAAMC,OAAOC,QAAQC,mBAAUC,SAASC,gCAGvCC,kBAyBmBL,6FAC7BM,OACAC,iBAGEC,WAAaR,OAAOC,QAAQC,mBAAUC,SAASM,SAE/CC,OAASV,OAAOC,QAAQC,mBAAUC,SAASC,mBAM9B,OAAfI,YAAuBA,WAAWG,aAAa,gBAE/CL,OAASE,WACTD,WAAaC,WAAWI,aAAa,iBAErCN,OAASI,OAELJ,OAAOK,aAAa,oBACpB5B,OAAOC,QAAQC,KACX,6GAGJqB,OAAOO,aAAa,kBAAmBP,OAAOQ,QAAQC,YAE1DR,WAAaD,OAAOQ,QAAQE,kBAEzB,CACHT,WAAAA,WACAU,uEAAkBX,OAAOQ,0CAAPI,gBAAgBC,wEAAoB,KACtDC,iEAAWd,OAAOQ,2CAAPO,iBAAgBC,iEAAa,MAzDnBC,CAA4BxB,MAAMC,QAE7CwB,kBAAoBC,WAAWC,mBAAmBjD,SAAU4B,SAASE,YAErEoB,mBAAqBF,WAAWG,eAClCnD,SACA4B,SAASE,WACTF,SAASY,iBACTZ,SAASe,WAGbS,gBAAgBC,4BAA4BN,kBAAmBG"} \ No newline at end of file +{"version":3,"file":"activitychooser.min.js","sources":["../src/activitychooser.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 * A type of dialogue used as for choosing modules in a course.\n *\n * @module core_course/activitychooser\n * @copyright 2020 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';\nimport CustomEvents from 'core/custom_interaction_events';\nimport Log from 'core/log';\nimport Pending from 'core/pending';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport selectors from 'core_course/local/activitychooser/selectors';\n\nlet initialized = false;\n\n/**\n * Set up the activity chooser.\n *\n * @method init\n * @param {Number} courseId Course ID to use later on in fetchModules()\n * @param {Object} chooserConfig Any PHP config settings that we may need to reference\n */\nexport const init = (courseId, chooserConfig) => {\n const pendingPromise = new Pending();\n\n // TODO: Remove the chooserConfig in Moodle 6.0 (MDL-85655)\n if (chooserConfig.tabmode !== undefined) {\n window.console.warn('The tabmode config option has been deprecated and will be ignored.');\n }\n\n registerListenerEvents(courseId);\n\n pendingPromise.resolve();\n};\n\n/**\n * Once a selection has been made make the modal & module information and pass it along\n *\n * @method registerListenerEvents\n * @param {Number} courseId\n */\nconst registerListenerEvents = (courseId) => {\n if (initialized) {\n return;\n }\n initialized = true;\n\n const eventsToHandle = [\n 'click',\n CustomEvents.events.activate,\n CustomEvents.events.keyboardActivate\n ];\n\n CustomEvents.define(document, eventsToHandle);\n\n // Display module chooser event listeners.\n eventsToHandle.forEach((eventToHandle) => {\n document.addEventListener(eventToHandle, async(event) => {\n if (!event.target.closest(selectors.elements.sectionmodchooser)) {\n return;\n }\n const position = getCoursePositionFromTarget(event.target);\n\n const footerDataPromise = Repository.getModalFooterData(courseId, position.sectionNum);\n\n let modulesDataPromise;\n if (position.sectionId && position.sectionId !== '') {\n modulesDataPromise = Repository.getSectionModulesData(\n courseId,\n position.sectionId,\n position.sectionReturnNum,\n position.beforeMod,\n );\n } else {\n // Todo remove this else in Moodle 6.0 (MDL-86310)\n Log.debug(\n 'Having only the section number attribute in the activity chooser is deprecated. ' +\n 'Please add the data-section-id attribute.'\n );\n modulesDataPromise = Repository.getModulesData(\n courseId,\n position.sectionNum,\n position.sectionReturnNum,\n position.beforeMod,\n );\n }\n\n ChooserDialogue.displayActivityChooserModal(footerDataPromise, modulesDataPromise);\n });\n });\n};\n\n/**\n * Return the course position of a target add activity element.\n *\n * @param {HTMLElement} target The target element.\n * @return {Object} The course position of the target.\n * @property {Number} sectionNum The section number.\n * @property {Number|null} sectionId The section id.\n * @property {Number|null} sectionReturnNum The section return number.\n * @property {Number|null} sectionReturnId The section return id.\n * @property {Number|null} beforeMod The ID of the cm to add the modules before.\n */\nfunction getCoursePositionFromTarget(target) {\n let caller;\n let sectionNum = null;\n let sectionId = null;\n // We need to know who called this.\n // Standard courses use the ID in the main section info.\n const sectionDiv = target.closest(selectors.elements.section);\n // Front page courses need some special handling.\n const button = target.closest(selectors.elements.sectionmodchooser);\n\n // If we don't have a section number use the fallback ID.\n // We always want the sectionDiv caller first as it keeps track of section number's after DnD changes.\n // The button attribute is always just a fallback for us as the section div is not always available.\n // A YUI change could be done maybe to only update the button attribute but we are going for minimal change here.\n if (\n sectionDiv !== null\n && (sectionDiv.hasAttribute('data-number') || sectionDiv.hasAttribute('data-id'))\n ) {\n // We check for attributes just in case of outdated contrib course formats.\n caller = sectionDiv;\n sectionNum = sectionDiv.getAttribute('data-number');\n sectionId = sectionDiv.getAttribute('data-id');\n } else {\n caller = button;\n if (caller.hasAttribute('data-sectionid')) {\n window.console.warn(\n 'The data-sectionid attribute has been deprecated. ' +\n 'Please update your code to use data-section-id passing the real section ID instead.'\n );\n caller.setAttribute('data-sectionnum', caller.dataset.sectionid);\n }\n sectionNum = caller.dataset.sectionnum;\n sectionId = caller.getAttribute('data-section-id');\n }\n return {\n sectionNum,\n sectionId,\n // The old data attribute for the section return number was data-sectionreturn.\n sectionReturnNum: caller.dataset?.sectionreturnnum ?? caller.dataset?.sectionreturn ?? null,\n sectionReturnId: caller.dataset?.sectionreturnid ?? null,\n beforeMod: caller.dataset?.beforemod ?? null,\n };\n}\n"],"names":["initialized","courseId","chooserConfig","pendingPromise","Pending","undefined","tabmode","window","console","warn","registerListenerEvents","resolve","eventsToHandle","CustomEvents","events","activate","keyboardActivate","define","document","forEach","eventToHandle","addEventListener","async","event","target","closest","selectors","elements","sectionmodchooser","position","caller","sectionNum","sectionId","sectionDiv","section","button","hasAttribute","getAttribute","setAttribute","dataset","sectionid","sectionnum","sectionReturnNum","_caller$dataset","sectionreturnnum","_caller$dataset2","sectionreturn","sectionReturnId","_caller$dataset3","sectionreturnid","beforeMod","_caller$dataset4","beforemod","getCoursePositionFromTarget","footerDataPromise","Repository","getModalFooterData","modulesDataPromise","getSectionModulesData","debug","getModulesData","ChooserDialogue","displayActivityChooserModal"],"mappings":";;;;;;;sYA8BIA,aAAc,gBASE,CAACC,SAAUC,uBACrBC,eAAiB,IAAIC,sBAGGC,IAA1BH,cAAcI,SACdC,OAAOC,QAAQC,KAAK,sEAGxBC,uBAAuBT,UAEvBE,eAAeQ,iBASbD,uBAA0BT,cACxBD,mBAGJA,aAAc,QAERY,eAAiB,CACnB,QACAC,mCAAaC,OAAOC,SACpBF,mCAAaC,OAAOE,qDAGXC,OAAOC,SAAUN,gBAG9BA,eAAeO,SAASC,gBACpBF,SAASG,iBAAiBD,eAAeE,MAAAA,YAChCC,MAAMC,OAAOC,QAAQC,mBAAUC,SAASC,gCAGvCC,kBA0CmBL,2JAC7BM,OACAC,WAAa,KACbC,UAAY,WAGVC,WAAaT,OAAOC,QAAQC,mBAAUC,SAASO,SAE/CC,OAASX,OAAOC,QAAQC,mBAAUC,SAASC,mBAO9B,OAAfK,aACIA,WAAWG,aAAa,gBAAkBH,WAAWG,aAAa,aAGtEN,OAASG,WACTF,WAAaE,WAAWI,aAAa,eACrCL,UAAYC,WAAWI,aAAa,aAEpCP,OAASK,OACLL,OAAOM,aAAa,oBACpB7B,OAAOC,QAAQC,KACX,yIAGJqB,OAAOQ,aAAa,kBAAmBR,OAAOS,QAAQC,YAE1DT,WAAaD,OAAOS,QAAQE,WAC5BT,UAAYF,OAAOO,aAAa,0BAE7B,CACHN,WAAAA,WACAC,UAAAA,UAEAU,oFAAkBZ,OAAOS,0CAAPI,gBAAgBC,iGAAoBd,OAAOS,2CAAPM,iBAAgBC,mCAAiB,KACvFC,wEAAiBjB,OAAOS,2CAAPS,iBAAgBC,yEAAmB,KACpDC,iEAAWpB,OAAOS,2CAAPY,iBAAgBC,iEAAa,MAlFnBC,CAA4B9B,MAAMC,QAE7C8B,kBAAoBC,WAAWC,mBAAmBvD,SAAU4B,SAASE,gBAEvE0B,mBACA5B,SAASG,WAAoC,KAAvBH,SAASG,UAC/ByB,mBAAqBF,WAAWG,sBAC5BzD,SACA4B,SAASG,UACTH,SAASa,iBACTb,SAASqB,yBAITS,MACA,6HAGJF,mBAAqBF,WAAWK,eAC5B3D,SACA4B,SAASE,WACTF,SAASa,iBACTb,SAASqB,YAIjBW,gBAAgBC,4BAA4BR,kBAAmBG"} \ No newline at end of file diff --git a/public/course/amd/build/local/activitychooser/repository.min.js b/public/course/amd/build/local/activitychooser/repository.min.js index 8968a317d56..886b679a2c7 100644 --- a/public/course/amd/build/local/activitychooser/repository.min.js +++ b/public/course/amd/build/local/activitychooser/repository.min.js @@ -1,10 +1,10 @@ -define("core_course/local/activitychooser/repository",["exports","core/ajax"],(function(_exports,_ajax){var obj; +define("core_course/local/activitychooser/repository",["exports","core/ajax","core/log"],(function(_exports,_ajax,_log){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} /** * A javascript module to handle user AJAX actions. * * @module core_course/local/activitychooser/repository * @copyright 2019 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.fetchFooterData=_exports.favouriteModule=_exports.activityModules=void 0,_exports.getModalFooterData=async function(courseId,sectionNum){const cacheKey="".concat(courseId,"-").concat(sectionNum);if(sectionsFooterPromises.has(cacheKey))return sectionsFooterPromises.get(cacheKey);return sectionsFooterPromises.set(cacheKey,new Promise((resolve=>{resolve(fetchFooterData(courseId,sectionNum))}))),sectionsFooterPromises.get(cacheKey)},_exports.getModulesData=async function(courseId,sectionNum,sectionReturnNum,beforeMod){const cacheKey="".concat(courseId,"-").concat(sectionNum);sectionsModulesPromises.has(cacheKey)||sectionsModulesPromises.set(cacheKey,new Promise((resolve=>{resolve(activityModules(courseId,sectionNum))})));const moduleData=await sectionsModulesPromises.get(cacheKey);if(!moduleData)throw new Error("Cannot fetch module data");return function(webServiceData,sectionNum,sectionReturnNum,beforeMod){const newData=JSON.parse(JSON.stringify(webServiceData));return newData.content_items.forEach((module=>{module.link+="§ion="+sectionNum+"&beforemod="+(null!=beforeMod?beforeMod:0),sectionReturnNum&&(module.link+="&sr="+sectionReturnNum)})),newData.content_items}(moduleData,sectionNum,sectionReturnNum,beforeMod)},_exports.unfavouriteModule=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};const sectionsModulesPromises=new Map,sectionsFooterPromises=new Map,activityModules=(courseid,sectionnum)=>{const request={methodname:"core_course_get_course_content_items",args:{courseid:courseid,sectionnum:sectionnum}};return _ajax.default.call([request])[0]};_exports.activityModules=activityModules;_exports.favouriteModule=(modName,modID)=>{const request={methodname:"core_course_add_content_item_to_user_favourites",args:{componentname:modName,contentitemid:modID}};return _ajax.default.call([request])[0].then((()=>(sectionsModulesPromises.clear(),!0)))};_exports.unfavouriteModule=(modName,modID)=>{const request={methodname:"core_course_remove_content_item_from_user_favourites",args:{componentname:modName,contentitemid:modID}};return _ajax.default.call([request])[0].then((()=>(sectionsModulesPromises.clear(),!0)))};const fetchFooterData=(courseid,sectionid)=>{const request={methodname:"core_course_get_activity_chooser_footer",args:{courseid:courseid,sectionid:sectionid}};return _ajax.default.call([request])[0]};_exports.fetchFooterData=fetchFooterData})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.fetchFooterData=_exports.favouriteModule=_exports.activityModules=void 0,_exports.getModalFooterData=async function(courseId,sectionNum){const cacheKey="".concat(courseId,"-").concat(sectionNum);if(sectionsFooterPromises.has(cacheKey))return sectionsFooterPromises.get(cacheKey);return sectionsFooterPromises.set(cacheKey,new Promise((resolve=>{resolve(fetchFooterData(courseId,sectionNum))}))),sectionsFooterPromises.get(cacheKey)},_exports.getModulesData=async function(courseId,sectionNum,sectionReturnNum,beforeMod){_log.default.debug("The getModulesData function is deprecated. Use getSectionModulesData instead.");const cacheKey="".concat(courseId,"-").concat(sectionNum);sectionsModulesPromises.has(cacheKey)||sectionsModulesPromises.set(cacheKey,new Promise((resolve=>{resolve(activityModules(courseId,sectionNum))})));const moduleData=await sectionsModulesPromises.get(cacheKey);if(!moduleData)throw new Error("Cannot fetch module data");return sectionMapper(moduleData,null,sectionReturnNum,beforeMod,sectionNum)},_exports.getSectionModulesData=async function(courseId,sectionId,sectionReturnNum,beforeMod){const cacheKey="".concat(courseId,"-").concat(sectionId);sectionsModulesPromises.has(cacheKey)||sectionsModulesPromises.set(cacheKey,new Promise((resolve=>{resolve(sectionActivityModules(courseId,sectionId))})));const moduleData=await sectionsModulesPromises.get(cacheKey);if(!moduleData)throw new Error("Cannot fetch module data");return sectionMapper(moduleData,sectionId,sectionReturnNum,beforeMod)},_exports.unfavouriteModule=_exports.sectionActivityModules=void 0,_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log);const sectionsModulesPromises=new Map,sectionsFooterPromises=new Map,activityModules=(courseid,sectionnum)=>{_log.default.debug("The activityModules function is deprecated. Use sectionActivityModules instead.");const request={methodname:"core_course_get_course_content_items",args:{courseid:courseid,sectionnum:sectionnum}};return _ajax.default.call([request])[0]};_exports.activityModules=activityModules;const sectionActivityModules=(courseId,sectionId)=>{const request={methodname:"core_courseformat_get_section_content_items",args:{courseid:courseId,sectionid:sectionId}};return _ajax.default.call([request])[0]};_exports.sectionActivityModules=sectionActivityModules;_exports.favouriteModule=(modName,modID)=>{const request={methodname:"core_course_add_content_item_to_user_favourites",args:{componentname:modName,contentitemid:modID}};return _ajax.default.call([request])[0].then((()=>(sectionsModulesPromises.clear(),!0)))};_exports.unfavouriteModule=(modName,modID)=>{const request={methodname:"core_course_remove_content_item_from_user_favourites",args:{componentname:modName,contentitemid:modID}};return _ajax.default.call([request])[0].then((()=>(sectionsModulesPromises.clear(),!0)))};const fetchFooterData=(courseid,sectionid)=>{const request={methodname:"core_course_get_activity_chooser_footer",args:{courseid:courseid,sectionid:sectionid}};return _ajax.default.call([request])[0]};function sectionMapper(webServiceData,sectionId,sectionReturnNum,beforeMod){let legacySectionNum=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;const newData=JSON.parse(JSON.stringify(webServiceData));let urlParams="&beforemod="+(null!=beforeMod?beforeMod:0);return sectionId&&(urlParams+="§ionid=".concat(sectionId)),legacySectionNum&&(urlParams+="§ion=".concat(legacySectionNum)),sectionReturnNum&&(urlParams+="&sr=".concat(sectionReturnNum)),newData.content_items.forEach((module=>{module.link+=urlParams})),newData.content_items}_exports.fetchFooterData=fetchFooterData})); //# sourceMappingURL=repository.min.js.map \ No newline at end of file diff --git a/public/course/amd/build/local/activitychooser/repository.min.js.map b/public/course/amd/build/local/activitychooser/repository.min.js.map index 71353e1dafd..414cfea242b 100644 --- a/public/course/amd/build/local/activitychooser/repository.min.js.map +++ b/public/course/amd/build/local/activitychooser/repository.min.js.map @@ -1 +1 @@ -{"version":3,"file":"repository.min.js","sources":["../../../src/local/activitychooser/repository.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 * A javascript module to handle user AJAX actions.\n *\n * @module core_course/local/activitychooser/repository\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ajax from 'core/ajax';\n\n// A promises map for caching specific section modules data.\nconst sectionsModulesPromises = new Map();\n\n// A promises map for caching a specific section footer data.\nconst sectionsFooterPromises = new Map();\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method activityModules\n * @param {Number} courseid What course to fetch the modules for\n * @param {Number} sectionnum What course section to fetch the modules for\n * @return {object} jQuery promise\n */\nexport const activityModules = (courseid, sectionnum) => {\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\n sectionnum: sectionnum,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is a users' favourite.\n *\n * @method favouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const favouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_add_content_item_to_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n const promise = ajax.call([request])[0];\n // After the promise is resolved, we need to invalidate the cache for the section.\n return promise.then(() => {\n sectionsModulesPromises.clear();\n return true;\n });\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is no longer a users' favourite.\n *\n * @method unfavouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const unfavouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_remove_content_item_from_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n\n const promise = ajax.call([request])[0];\n // After the promise is resolved, we need to invalidate the cache for the section.\n return promise.then(() => {\n sectionsModulesPromises.clear();\n return true;\n });\n};\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method fetchFooterData\n * @param {Number} courseid What course to fetch the data for\n * @param {Number} sectionid What section to fetch the data for\n * @return {object} jQuery promise\n */\nexport const fetchFooterData = (courseid, sectionid) => {\n const request = {\n methodname: 'core_course_get_activity_chooser_footer',\n args: {\n courseid: courseid,\n sectionid: sectionid,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method fetchSectionModules\n *\n * @private\n * @param {Number} courseId Course ID.\n * @param {Number} sectionNum Section number.\n * @param {Number} sectionReturnNum Section return.\n * @param {Number} beforeMod Before module number to be used in the module.\n * @return {Object} Tab data.\n */\nexport async function getModulesData(courseId, sectionNum, sectionReturnNum, beforeMod) {\n const cacheKey = `${courseId}-${sectionNum}`;\n if (!sectionsModulesPromises.has(cacheKey)) {\n sectionsModulesPromises.set(\n cacheKey,\n new Promise((resolve) => {\n resolve(activityModules(courseId, sectionNum));\n })\n );\n }\n\n const moduleData = await sectionsModulesPromises.get(cacheKey);\n\n // Early return if there is no module data.\n if (!moduleData) {\n throw new Error('Cannot fetch module data');\n }\n\n // Apply the section num to all the module instance links.\n return sectionMapper(\n moduleData,\n sectionNum,\n sectionReturnNum,\n beforeMod\n );\n}\n\n/**\n * Given the web service data and an ID we want to make a deep copy\n * of the WS data then add on the section num to the addoption URL\n *\n * @method sectionMapper\n * @param {Object} webServiceData Our original data from the Web service call\n * @param {Number} sectionNum The number of the section we need to append to the links\n * @param {Number|null} sectionReturnNum The number of the section return we need to append to the links\n * @param {Number|null} beforeMod The ID of the cm we need to append to the links\n * @return {Array} [modules] with URL's built\n */\nfunction sectionMapper(webServiceData, sectionNum, sectionReturnNum, beforeMod) {\n // We need to take a fresh deep copy of the original data as an object is a reference type.\n const newData = JSON.parse(JSON.stringify(webServiceData));\n newData.content_items.forEach((module) => {\n module.link += '§ion=' + sectionNum + '&beforemod=' + (beforeMod ?? 0);\n if (sectionReturnNum) {\n module.link += '&sr=' + sectionReturnNum;\n }\n });\n return newData.content_items;\n}\n\n/**\n * Fetch the footer data for a specific section.\n *\n * @param {Number} courseId Course ID.\n * @param {Number} sectionNum Section number.\n * @return {Promise} Promise resolved with the footer data.\n */\nexport async function getModalFooterData(courseId, sectionNum) {\n const cacheKey = `${courseId}-${sectionNum}`;\n if (sectionsFooterPromises.has(cacheKey)) {\n return sectionsFooterPromises.get(cacheKey);\n }\n\n sectionsFooterPromises.set(\n cacheKey,\n new Promise((resolve) => {\n resolve(fetchFooterData(courseId, sectionNum));\n })\n );\n return sectionsFooterPromises.get(cacheKey);\n}\n"],"names":["courseId","sectionNum","cacheKey","sectionsFooterPromises","has","get","set","Promise","resolve","fetchFooterData","sectionReturnNum","beforeMod","sectionsModulesPromises","activityModules","moduleData","Error","webServiceData","newData","JSON","parse","stringify","content_items","forEach","module","link","sectionMapper","Map","courseid","sectionnum","request","methodname","args","ajax","call","modName","modID","componentname","contentitemid","then","clear","sectionid"],"mappings":";;;;;;;0LA4LyCA,SAAUC,kBACzCC,mBAAcF,qBAAYC,eAC5BE,uBAAuBC,IAAIF,iBACpBC,uBAAuBE,IAAIH,iBAGtCC,uBAAuBG,IACnBJ,SACA,IAAIK,SAASC,UACTA,QAAQC,gBAAgBT,SAAUC,iBAGnCE,uBAAuBE,IAAIH,kDArEDF,SAAUC,WAAYS,iBAAkBC,iBACnET,mBAAcF,qBAAYC,YAC3BW,wBAAwBR,IAAIF,WAC7BU,wBAAwBN,IACpBJ,SACA,IAAIK,SAASC,UACTA,QAAQK,gBAAgBb,SAAUC,uBAKxCa,iBAAmBF,wBAAwBP,IAAIH,cAGhDY,iBACK,IAAIC,MAAM,4CAuBDC,eAAgBf,WAAYS,iBAAkBC,iBAE3DM,QAAUC,KAAKC,MAAMD,KAAKE,UAAUJ,wBAC1CC,QAAQI,cAAcC,SAASC,SAC3BA,OAAOC,MAAQ,YAAcvB,WAAa,eAAiBU,MAAAA,UAAAA,UAAa,GACpED,mBACAa,OAAOC,MAAQ,OAASd,qBAGzBO,QAAQI,cA5BRI,CACHX,WACAb,WACAS,iBACAC,wGAjIFC,wBAA0B,IAAIc,IAG9BvB,uBAAyB,IAAIuB,IAUtBb,gBAAkB,CAACc,SAAUC,oBAChCC,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFJ,SAAUA,SACVC,WAAYA,oBAGbI,cAAKC,KAAK,CAACJ,UAAU,sEAYD,CAACK,QAASC,eAC/BN,QAAU,CACZC,WAAY,kDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAGPH,cAAKC,KAAK,CAACJ,UAAU,GAEtBS,MAAK,KAChB1B,wBAAwB2B,SACjB,iCAakB,CAACL,QAASC,eACjCN,QAAU,CACZC,WAAY,uDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAIPH,cAAKC,KAAK,CAACJ,UAAU,GAEtBS,MAAK,KAChB1B,wBAAwB2B,SACjB,YAYF9B,gBAAkB,CAACkB,SAAUa,mBAChCX,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFJ,SAAUA,SACVa,UAAWA,mBAGZR,cAAKC,KAAK,CAACJ,UAAU"} \ No newline at end of file +{"version":3,"file":"repository.min.js","sources":["../../../src/local/activitychooser/repository.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 * A javascript module to handle user AJAX actions.\n *\n * @module core_course/local/activitychooser/repository\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport ajax from 'core/ajax';\nimport Log from 'core/log';\n\n// A promises map for caching specific section modules data.\nconst sectionsModulesPromises = new Map();\n\n// A promises map for caching a specific section footer data.\nconst sectionsFooterPromises = new Map();\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method activityModules\n * @deprecated since Moodle 5.1\n * @todo Remove in Moodle 6.0 (MDL-86310)\n * @param {Number} courseid What course to fetch the modules for\n * @param {Number} sectionnum What course section to fetch the modules for\n * @return {object} jQuery promise\n */\nexport const activityModules = (courseid, sectionnum) => {\n Log.debug('The activityModules function is deprecated. Use sectionActivityModules instead.');\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\n sectionnum: sectionnum,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Fetch all the information on modules that can be added to a section.\n *\n * @method sectionActivityModules\n * @param {Number} courseId What course to fetch the modules for\n * @param {Number} sectionId What course section to fetch the modules for\n * @return {object} jQuery promise\n */\nexport const sectionActivityModules = (courseId, sectionId) => {\n const request = {\n methodname: 'core_courseformat_get_section_content_items',\n args: {\n courseid: courseId,\n sectionid: sectionId,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is a users' favourite.\n *\n * @method favouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const favouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_add_content_item_to_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n const promise = ajax.call([request])[0];\n // After the promise is resolved, we need to invalidate the cache for the section.\n return promise.then(() => {\n sectionsModulesPromises.clear();\n return true;\n });\n};\n\n/**\n * Given a module name, module ID & the current course we want to specify that the module\n * is no longer a users' favourite.\n *\n * @method unfavouriteModule\n * @param {String} modName Frankenstyle name of the component to add favourite\n * @param {int} modID ID of the module. Mainly for LTI cases where they have same / similar names\n * @return {object} jQuery promise\n */\nexport const unfavouriteModule = (modName, modID) => {\n const request = {\n methodname: 'core_course_remove_content_item_from_user_favourites',\n args: {\n componentname: modName,\n contentitemid: modID,\n },\n };\n\n const promise = ajax.call([request])[0];\n // After the promise is resolved, we need to invalidate the cache for the section.\n return promise.then(() => {\n sectionsModulesPromises.clear();\n return true;\n });\n};\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method fetchFooterData\n * @param {Number} courseid What course to fetch the data for\n * @param {Number} sectionid What section to fetch the data for\n * @return {object} jQuery promise\n */\nexport const fetchFooterData = (courseid, sectionid) => {\n const request = {\n methodname: 'core_course_get_activity_chooser_footer',\n args: {\n courseid: courseid,\n sectionid: sectionid,\n },\n };\n return ajax.call([request])[0];\n};\n\n/**\n * Legacy method to fetch all the information on modules using section number.\n *\n * @method fetchSectionModules\n *\n * @deprecated since Moodle 5.1\n * @todo Remove in Moodle 6.0 (MDL-86310)\n * @param {Number} courseId Course ID.\n * @param {Number} sectionNum Section number.\n * @param {Number} sectionReturnNum Section return.\n * @param {Number} beforeMod Before module number to be used in the module.\n * @return {Object} Tab data.\n */\nexport async function getModulesData(courseId, sectionNum, sectionReturnNum, beforeMod) {\n Log.debug('The getModulesData function is deprecated. Use getSectionModulesData instead.');\n const cacheKey = `${courseId}-${sectionNum}`;\n if (!sectionsModulesPromises.has(cacheKey)) {\n sectionsModulesPromises.set(\n cacheKey,\n new Promise((resolve) => {\n resolve(activityModules(courseId, sectionNum));\n })\n );\n }\n\n const moduleData = await sectionsModulesPromises.get(cacheKey);\n\n // Early return if there is no module data.\n if (!moduleData) {\n throw new Error('Cannot fetch module data');\n }\n\n // Apply the section num to all the module instance links.\n return sectionMapper(\n moduleData,\n null, // We do not have a section ID here.\n sectionReturnNum,\n beforeMod,\n sectionNum, // Legacy section number.\n );\n}\n\n/**\n * Fetch all the information on modules we'll need in the activity chooser.\n *\n * @method fetchSectionModules\n *\n * @param {Number} courseId Course ID.\n * @param {Number} sectionId Section ID.\n * @param {Number} sectionReturnNum Section return.\n * @param {Number} beforeMod Before module number to be used in the module.\n * @return {Object} Tab data.\n */\nexport async function getSectionModulesData(courseId, sectionId, sectionReturnNum, beforeMod) {\n const cacheKey = `${courseId}-${sectionId}`;\n if (!sectionsModulesPromises.has(cacheKey)) {\n sectionsModulesPromises.set(\n cacheKey,\n new Promise((resolve) => {\n resolve(sectionActivityModules(courseId, sectionId));\n })\n );\n }\n\n const moduleData = await sectionsModulesPromises.get(cacheKey);\n\n // Early return if there is no module data.\n if (!moduleData) {\n throw new Error('Cannot fetch module data');\n }\n\n // Apply the section num to all the module instance links.\n return sectionMapper(\n moduleData,\n sectionId,\n sectionReturnNum,\n beforeMod,\n );\n}\n\n/**\n * Given the web service data and an ID we want to make a deep copy\n * of the WS data then add on the section num to the addoption URL\n *\n * @method sectionMapper\n * @TODO remove legacySectionNum param in Moodle 6.0 (MDL-86310)\n * @param {Object} webServiceData Our original data from the Web service call\n * @param {Number} sectionId The number of the section we need to append to the links\n * @param {Number|null} sectionReturnNum The number of the section return we need to append to the links\n * @param {Number|null} beforeMod The ID of the cm we need to append to the links\n * @param {Number|null} legacySectionNum The legacy section number to append to the links\n * @return {Array} [modules] with URL's built\n */\nfunction sectionMapper(webServiceData, sectionId, sectionReturnNum, beforeMod, legacySectionNum = null) {\n // We need to take a fresh deep copy of the original data as an object is a reference type.\n const newData = JSON.parse(JSON.stringify(webServiceData));\n let urlParams = '&beforemod=' + (beforeMod ?? 0);\n if (sectionId) {\n urlParams += `§ionid=${sectionId}`;\n }\n // Todo: Remove legacySectionNum in Moodle 6.0 (MDL-86310).\n if (legacySectionNum) {\n urlParams += `§ion=${legacySectionNum}`;\n }\n if (sectionReturnNum) {\n urlParams += `&sr=${sectionReturnNum}`;\n }\n newData.content_items.forEach((module) => {\n module.link += urlParams;\n });\n return newData.content_items;\n}\n\n/**\n * Fetch the footer data for a specific section.\n *\n * @param {Number} courseId Course ID.\n * @param {Number} sectionNum Section number.\n * @return {Promise} Promise resolved with the footer data.\n */\nexport async function getModalFooterData(courseId, sectionNum) {\n const cacheKey = `${courseId}-${sectionNum}`;\n if (sectionsFooterPromises.has(cacheKey)) {\n return sectionsFooterPromises.get(cacheKey);\n }\n\n sectionsFooterPromises.set(\n cacheKey,\n new Promise((resolve) => {\n resolve(fetchFooterData(courseId, sectionNum));\n })\n );\n return sectionsFooterPromises.get(cacheKey);\n}\n"],"names":["courseId","sectionNum","cacheKey","sectionsFooterPromises","has","get","set","Promise","resolve","fetchFooterData","sectionReturnNum","beforeMod","debug","sectionsModulesPromises","activityModules","moduleData","Error","sectionMapper","sectionId","sectionActivityModules","Map","courseid","sectionnum","request","methodname","args","ajax","call","sectionid","modName","modID","componentname","contentitemid","then","clear","webServiceData","legacySectionNum","newData","JSON","parse","stringify","urlParams","content_items","forEach","module","link"],"mappings":";;;;;;;0LAsQyCA,SAAUC,kBACzCC,mBAAcF,qBAAYC,eAC5BE,uBAAuBC,IAAIF,iBACpBC,uBAAuBE,IAAIH,iBAGtCC,uBAAuBG,IACnBJ,SACA,IAAIK,SAASC,UACTA,QAAQC,gBAAgBT,SAAUC,iBAGnCE,uBAAuBE,IAAIH,kDAvHDF,SAAUC,WAAYS,iBAAkBC,wBACrEC,MAAM,uFACJV,mBAAcF,qBAAYC,YAC3BY,wBAAwBT,IAAIF,WAC7BW,wBAAwBP,IACpBJ,SACA,IAAIK,SAASC,UACTA,QAAQM,gBAAgBd,SAAUC,uBAKxCc,iBAAmBF,wBAAwBR,IAAIH,cAGhDa,iBACK,IAAIC,MAAM,mCAIbC,cACHF,WACA,KACAL,iBACAC,UACAV,2DAeoCD,SAAUkB,UAAWR,iBAAkBC,iBACzET,mBAAcF,qBAAYkB,WAC3BL,wBAAwBT,IAAIF,WAC7BW,wBAAwBP,IACpBJ,SACA,IAAIK,SAASC,UACTA,QAAQW,uBAAuBnB,SAAUkB,sBAK/CH,iBAAmBF,wBAAwBR,IAAIH,cAGhDa,iBACK,IAAIC,MAAM,mCAIbC,cACHF,WACAG,UACAR,iBACAC,0JAhMFE,wBAA0B,IAAIO,IAG9BjB,uBAAyB,IAAIiB,IAYtBN,gBAAkB,CAACO,SAAUC,2BAClCV,MAAM,yFACJW,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFJ,SAAUA,SACVC,WAAYA,oBAGbI,cAAKC,KAAK,CAACJ,UAAU,mDAWnBJ,uBAAyB,CAACnB,SAAUkB,mBACvCK,QAAU,CACZC,WAAY,8CACZC,KAAM,CACFJ,SAAUrB,SACV4B,UAAWV,mBAGZQ,cAAKC,KAAK,CAACJ,UAAU,oFAYD,CAACM,QAASC,eAC/BP,QAAU,CACZC,WAAY,kDACZC,KAAM,CACFM,cAAeF,QACfG,cAAeF,eAGPJ,cAAKC,KAAK,CAACJ,UAAU,GAEtBU,MAAK,KAChBpB,wBAAwBqB,SACjB,iCAakB,CAACL,QAASC,eACjCP,QAAU,CACZC,WAAY,uDACZC,KAAM,CACFM,cAAeF,QACfG,cAAeF,eAIPJ,cAAKC,KAAK,CAACJ,UAAU,GAEtBU,MAAK,KAChBpB,wBAAwBqB,SACjB,YAYFzB,gBAAkB,CAACY,SAAUO,mBAChCL,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFJ,SAAUA,SACVO,UAAWA,mBAGZF,cAAKC,KAAK,CAACJ,UAAU,aAgGvBN,cAAckB,eAAgBjB,UAAWR,iBAAkBC,eAAWyB,wEAAmB,WAExFC,QAAUC,KAAKC,MAAMD,KAAKE,UAAUL,qBACtCM,UAAY,eAAiB9B,MAAAA,UAAAA,UAAa,UAC1CO,YACAuB,gCAA2BvB,YAG3BkB,mBACAK,8BAAyBL,mBAEzB1B,mBACA+B,yBAAoB/B,mBAExB2B,QAAQK,cAAcC,SAASC,SAC3BA,OAAOC,MAAQJ,aAEZJ,QAAQK"} \ No newline at end of file diff --git a/public/course/amd/src/activitychooser.js b/public/course/amd/src/activitychooser.js index 515cd1d1efe..9c8365beff9 100644 --- a/public/course/amd/src/activitychooser.js +++ b/public/course/amd/src/activitychooser.js @@ -22,10 +22,11 @@ */ import * as ChooserDialogue from 'core_course/local/activitychooser/dialogue'; +import CustomEvents from 'core/custom_interaction_events'; +import Log from 'core/log'; +import Pending from 'core/pending'; import * as Repository from 'core_course/local/activitychooser/repository'; import selectors from 'core_course/local/activitychooser/selectors'; -import CustomEvents from 'core/custom_interaction_events'; -import Pending from 'core/pending'; let initialized = false; @@ -79,12 +80,27 @@ const registerListenerEvents = (courseId) => { const footerDataPromise = Repository.getModalFooterData(courseId, position.sectionNum); - const modulesDataPromise = Repository.getModulesData( - courseId, - position.sectionNum, - position.sectionReturnNum, - position.beforeMod, - ); + let modulesDataPromise; + if (position.sectionId && position.sectionId !== '') { + modulesDataPromise = Repository.getSectionModulesData( + courseId, + position.sectionId, + position.sectionReturnNum, + position.beforeMod, + ); + } else { + // Todo remove this else in Moodle 6.0 (MDL-86310) + Log.debug( + 'Having only the section number attribute in the activity chooser is deprecated. ' + + 'Please add the data-section-id attribute.' + ); + modulesDataPromise = Repository.getModulesData( + courseId, + position.sectionNum, + position.sectionReturnNum, + position.beforeMod, + ); + } ChooserDialogue.displayActivityChooserModal(footerDataPromise, modulesDataPromise); }); @@ -97,12 +113,15 @@ const registerListenerEvents = (courseId) => { * @param {HTMLElement} target The target element. * @return {Object} The course position of the target. * @property {Number} sectionNum The section number. + * @property {Number|null} sectionId The section id. * @property {Number|null} sectionReturnNum The section return number. + * @property {Number|null} sectionReturnId The section return id. * @property {Number|null} beforeMod The ID of the cm to add the modules before. */ function getCoursePositionFromTarget(target) { let caller; - let sectionNum; + let sectionNum = null; + let sectionId = null; // We need to know who called this. // Standard courses use the ID in the main section info. const sectionDiv = target.closest(selectors.elements.section); @@ -113,25 +132,32 @@ function getCoursePositionFromTarget(target) { // We always want the sectionDiv caller first as it keeps track of section number's after DnD changes. // The button attribute is always just a fallback for us as the section div is not always available. // A YUI change could be done maybe to only update the button attribute but we are going for minimal change here. - if (sectionDiv !== null && sectionDiv.hasAttribute('data-number')) { + if ( + sectionDiv !== null + && (sectionDiv.hasAttribute('data-number') || sectionDiv.hasAttribute('data-id')) + ) { // We check for attributes just in case of outdated contrib course formats. caller = sectionDiv; sectionNum = sectionDiv.getAttribute('data-number'); + sectionId = sectionDiv.getAttribute('data-id'); } else { caller = button; - if (caller.hasAttribute('data-sectionid')) { window.console.warn( 'The data-sectionid attribute has been deprecated. ' + - 'Please update your code to use data-sectionnum instead.' + 'Please update your code to use data-section-id passing the real section ID instead.' ); caller.setAttribute('data-sectionnum', caller.dataset.sectionid); } sectionNum = caller.dataset.sectionnum; + sectionId = caller.getAttribute('data-section-id'); } return { sectionNum, - sectionReturnNum: caller.dataset?.sectionreturnnum ?? null, + sectionId, + // The old data attribute for the section return number was data-sectionreturn. + sectionReturnNum: caller.dataset?.sectionreturnnum ?? caller.dataset?.sectionreturn ?? null, + sectionReturnId: caller.dataset?.sectionreturnid ?? null, beforeMod: caller.dataset?.beforemod ?? null, }; } diff --git a/public/course/amd/src/local/activitychooser/repository.js b/public/course/amd/src/local/activitychooser/repository.js index 29a3a5ddcec..00d249a5a30 100644 --- a/public/course/amd/src/local/activitychooser/repository.js +++ b/public/course/amd/src/local/activitychooser/repository.js @@ -21,6 +21,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import ajax from 'core/ajax'; +import Log from 'core/log'; // A promises map for caching specific section modules data. const sectionsModulesPromises = new Map(); @@ -32,11 +33,14 @@ const sectionsFooterPromises = new Map(); * Fetch all the information on modules we'll need in the activity chooser. * * @method activityModules + * @deprecated since Moodle 5.1 + * @todo Remove in Moodle 6.0 (MDL-86310) * @param {Number} courseid What course to fetch the modules for * @param {Number} sectionnum What course section to fetch the modules for * @return {object} jQuery promise */ export const activityModules = (courseid, sectionnum) => { + Log.debug('The activityModules function is deprecated. Use sectionActivityModules instead.'); const request = { methodname: 'core_course_get_course_content_items', args: { @@ -47,6 +51,25 @@ export const activityModules = (courseid, sectionnum) => { return ajax.call([request])[0]; }; +/** + * Fetch all the information on modules that can be added to a section. + * + * @method sectionActivityModules + * @param {Number} courseId What course to fetch the modules for + * @param {Number} sectionId What course section to fetch the modules for + * @return {object} jQuery promise + */ +export const sectionActivityModules = (courseId, sectionId) => { + const request = { + methodname: 'core_courseformat_get_section_content_items', + args: { + courseid: courseId, + sectionid: sectionId, + }, + }; + return ajax.call([request])[0]; +}; + /** * Given a module name, module ID & the current course we want to specify that the module * is a users' favourite. @@ -118,11 +141,12 @@ export const fetchFooterData = (courseid, sectionid) => { }; /** - * Fetch all the information on modules we'll need in the activity chooser. + * Legacy method to fetch all the information on modules using section number. * * @method fetchSectionModules * - * @private + * @deprecated since Moodle 5.1 + * @todo Remove in Moodle 6.0 (MDL-86310) * @param {Number} courseId Course ID. * @param {Number} sectionNum Section number. * @param {Number} sectionReturnNum Section return. @@ -130,6 +154,7 @@ export const fetchFooterData = (courseid, sectionid) => { * @return {Object} Tab data. */ export async function getModulesData(courseId, sectionNum, sectionReturnNum, beforeMod) { + Log.debug('The getModulesData function is deprecated. Use getSectionModulesData instead.'); const cacheKey = `${courseId}-${sectionNum}`; if (!sectionsModulesPromises.has(cacheKey)) { sectionsModulesPromises.set( @@ -150,9 +175,48 @@ export async function getModulesData(courseId, sectionNum, sectionReturnNum, bef // Apply the section num to all the module instance links. return sectionMapper( moduleData, - sectionNum, + null, // We do not have a section ID here. sectionReturnNum, - beforeMod + beforeMod, + sectionNum, // Legacy section number. + ); +} + +/** + * Fetch all the information on modules we'll need in the activity chooser. + * + * @method fetchSectionModules + * + * @param {Number} courseId Course ID. + * @param {Number} sectionId Section ID. + * @param {Number} sectionReturnNum Section return. + * @param {Number} beforeMod Before module number to be used in the module. + * @return {Object} Tab data. + */ +export async function getSectionModulesData(courseId, sectionId, sectionReturnNum, beforeMod) { + const cacheKey = `${courseId}-${sectionId}`; + if (!sectionsModulesPromises.has(cacheKey)) { + sectionsModulesPromises.set( + cacheKey, + new Promise((resolve) => { + resolve(sectionActivityModules(courseId, sectionId)); + }) + ); + } + + const moduleData = await sectionsModulesPromises.get(cacheKey); + + // Early return if there is no module data. + if (!moduleData) { + throw new Error('Cannot fetch module data'); + } + + // Apply the section num to all the module instance links. + return sectionMapper( + moduleData, + sectionId, + sectionReturnNum, + beforeMod, ); } @@ -161,20 +225,30 @@ export async function getModulesData(courseId, sectionNum, sectionReturnNum, bef * of the WS data then add on the section num to the addoption URL * * @method sectionMapper + * @TODO remove legacySectionNum param in Moodle 6.0 (MDL-86310) * @param {Object} webServiceData Our original data from the Web service call - * @param {Number} sectionNum The number of the section we need to append to the links + * @param {Number} sectionId The number of the section we need to append to the links * @param {Number|null} sectionReturnNum The number of the section return we need to append to the links * @param {Number|null} beforeMod The ID of the cm we need to append to the links + * @param {Number|null} legacySectionNum The legacy section number to append to the links * @return {Array} [modules] with URL's built */ -function sectionMapper(webServiceData, sectionNum, sectionReturnNum, beforeMod) { +function sectionMapper(webServiceData, sectionId, sectionReturnNum, beforeMod, legacySectionNum = null) { // We need to take a fresh deep copy of the original data as an object is a reference type. const newData = JSON.parse(JSON.stringify(webServiceData)); + let urlParams = '&beforemod=' + (beforeMod ?? 0); + if (sectionId) { + urlParams += `§ionid=${sectionId}`; + } + // Todo: Remove legacySectionNum in Moodle 6.0 (MDL-86310). + if (legacySectionNum) { + urlParams += `§ion=${legacySectionNum}`; + } + if (sectionReturnNum) { + urlParams += `&sr=${sectionReturnNum}`; + } newData.content_items.forEach((module) => { - module.link += '§ion=' + sectionNum + '&beforemod=' + (beforeMod ?? 0); - if (sectionReturnNum) { - module.link += '&sr=' + sectionReturnNum; - } + module.link += urlParams; }); return newData.content_items; }