From 8531f1c6e4511fcb5bf0a404652e826ac1a69819 Mon Sep 17 00:00:00 2001 From: Stefan Hanauska Date: Fri, 3 Oct 2025 08:54:31 +0200 Subject: [PATCH] MBS-10348: Fix learningmap showing in modal --- amd/build/initliveupdater.min.js | 2 +- amd/build/initliveupdater.min.js.map | 2 +- amd/build/linkmodal.min.js | 2 +- amd/build/linkmodal.min.js.map | 2 +- amd/build/renderer.min.js | 2 +- amd/build/renderer.min.js.map | 2 +- amd/src/initliveupdater.js | 5 ++- amd/src/linkmodal.js | 62 +++++++++++++++------------- amd/src/renderer.js | 16 +++++-- classes/external/get_cm.php | 16 +++++-- classes/external/get_learningmap.php | 13 ++++++ classes/helper.php | 9 ++++ lib.php | 1 + templates/rendercontainer.mustache | 9 ++-- view.php | 1 + 15 files changed, 95 insertions(+), 49 deletions(-) diff --git a/amd/build/initliveupdater.min.js b/amd/build/initliveupdater.min.js index 98333d3a..c627f2eb 100644 --- a/amd/build/initliveupdater.min.js +++ b/amd/build/initliveupdater.min.js @@ -6,6 +6,6 @@ define("mod_learningmap/initliveupdater",["exports","mod_learningmap/liveupdater * @copyright 2021-2024, ISB Bayern * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_liveupdater=_interopRequireDefault(_liveupdater),_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_pending=_interopRequireDefault(_pending);_exports.init=async cmId=>{const initliveupdaterPendingPromise=new _pending.default("mod_learningmap/initliveupdater");try{const data=await _ajax.default.call([{methodname:"mod_learningmap_get_dependingmodules",args:{cmId:cmId}}])[0];return initliveupdaterPendingPromise.resolve(),new _liveupdater.default({element:document.getElementById(_renderer.selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX+cmId),reactive:(0,_courseeditor.getCurrentCourseEditor)(),cmId:cmId,dependingModuleIds:data.dependingModuleIds})}catch(error){return _log.default.error(error),initliveupdaterPendingPromise.reject(),!1}}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_liveupdater=_interopRequireDefault(_liveupdater),_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_pending=_interopRequireDefault(_pending);_exports.init=async function(cmId){let inmodal=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const initliveupdaterPendingPromise=new _pending.default("mod_learningmap/initliveupdater");try{const data=await _ajax.default.call([{methodname:"mod_learningmap_get_dependingmodules",args:{cmId:cmId}}])[0];return initliveupdaterPendingPromise.resolve(),new _liveupdater.default({element:document.getElementById(_renderer.selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX+cmId+(inmodal?"-modal":"")),reactive:(0,_courseeditor.getCurrentCourseEditor)(),cmId:cmId,dependingModuleIds:data.dependingModuleIds})}catch(error){return _log.default.error(error),initliveupdaterPendingPromise.reject(),!1}}})); //# sourceMappingURL=initliveupdater.min.js.map \ No newline at end of file diff --git a/amd/build/initliveupdater.min.js.map b/amd/build/initliveupdater.min.js.map index 4c84100f..8a16ebf1 100644 --- a/amd/build/initliveupdater.min.js.map +++ b/amd/build/initliveupdater.min.js.map @@ -1 +1 @@ -{"version":3,"file":"initliveupdater.min.js","sources":["../src/initliveupdater.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 * Main module for the massaction block.\n *\n * @module mod_learningmap/initliveupdater\n * @copyright 2021-2024, ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport LiveUpdater from 'mod_learningmap/liveupdater';\nimport {selectors} from 'mod_learningmap/renderer';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport Ajax from 'core/ajax';\nimport Log from 'core/log';\nimport Pending from 'core/pending';\n\n/**\n * Renders the learningmap into the correct div.\n *\n * @param {number} cmId the course module id of the learningmap\n * @return {Component} the liveupdater component\n */\nexport const init = async(cmId) => {\n const initliveupdaterPendingPromise = new Pending('mod_learningmap/initliveupdater');\n try {\n const data = await Ajax.call(\n [\n {\n methodname: 'mod_learningmap_get_dependingmodules',\n args: {\n 'cmId': cmId\n }\n }\n ])[0];\n\n initliveupdaterPendingPromise.resolve();\n return new LiveUpdater({\n element: document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId),\n reactive: getCurrentCourseEditor(),\n cmId: cmId,\n dependingModuleIds: data.dependingModuleIds\n });\n } catch (error) {\n Log.error(error);\n initliveupdaterPendingPromise.reject();\n return false;\n }\n};\n"],"names":["async","initliveupdaterPendingPromise","Pending","data","Ajax","call","methodname","args","cmId","resolve","LiveUpdater","element","document","getElementById","selectors","LEARNINGMAP_RENDER_CONTAINER_PREFIX","reactive","dependingModuleIds","error","reject"],"mappings":";;;;;;;;kQAoCoBA,MAAAA,aACVC,8BAAgC,IAAIC,iBAAQ,6CAExCC,WAAaC,cAAKC,KACpB,CACI,CACIC,WAAY,uCACZC,KAAM,MACMC,SAGjB,UAEPP,8BAA8BQ,UACvB,IAAIC,qBAAY,CACnBC,QAASC,SAASC,eAAeC,oBAAUC,oCAAsCP,MACjFQ,UAAU,0CACVR,KAAMA,KACNS,mBAAoBd,KAAKc,qBAE/B,MAAOC,2BACDA,MAAMA,OACVjB,8BAA8BkB,UACvB"} \ No newline at end of file +{"version":3,"file":"initliveupdater.min.js","sources":["../src/initliveupdater.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 * Main module for the massaction block.\n *\n * @module mod_learningmap/initliveupdater\n * @copyright 2021-2024, ISB Bayern\n * @author Philipp Memmel\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport LiveUpdater from 'mod_learningmap/liveupdater';\nimport {selectors} from 'mod_learningmap/renderer';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport Ajax from 'core/ajax';\nimport Log from 'core/log';\nimport Pending from 'core/pending';\n\n/**\n * Renders the learningmap into the correct div.\n *\n * @param {number} cmId the course module id of the learningmap\n * @param {boolean} inmodal whether the learningmap is being rendered in a modal\n * @return {Component} the liveupdater component\n */\nexport const init = async(cmId, inmodal = false) => {\n const initliveupdaterPendingPromise = new Pending('mod_learningmap/initliveupdater');\n try {\n const data = await Ajax.call(\n [\n {\n methodname: 'mod_learningmap_get_dependingmodules',\n args: {\n 'cmId': cmId\n }\n }\n ])[0];\n\n initliveupdaterPendingPromise.resolve();\n return new LiveUpdater({\n element: document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId + (inmodal ? '-modal' : '')),\n reactive: getCurrentCourseEditor(),\n cmId: cmId,\n dependingModuleIds: data.dependingModuleIds\n });\n } catch (error) {\n Log.error(error);\n initliveupdaterPendingPromise.reject();\n return false;\n }\n};\n"],"names":["async","cmId","inmodal","initliveupdaterPendingPromise","Pending","data","Ajax","call","methodname","args","resolve","LiveUpdater","element","document","getElementById","selectors","LEARNINGMAP_RENDER_CONTAINER_PREFIX","reactive","dependingModuleIds","error","reject"],"mappings":";;;;;;;;kQAqCoBA,eAAMC,UAAMC,sEACtBC,8BAAgC,IAAIC,iBAAQ,6CAExCC,WAAaC,cAAKC,KACpB,CACI,CACIC,WAAY,uCACZC,KAAM,MACMR,SAGjB,UAEPE,8BAA8BO,UACvB,IAAIC,qBAAY,CACnBC,QAASC,SAASC,eAAeC,oBAAUC,oCAAsCf,MAAQC,QAAU,SAAW,KAC9Ge,UAAU,0CACVhB,KAAMA,KACNiB,mBAAoBb,KAAKa,qBAE/B,MAAOC,2BACDA,MAAMA,OACVhB,8BAA8BiB,UACvB"} \ No newline at end of file diff --git a/amd/build/linkmodal.min.js b/amd/build/linkmodal.min.js index b662f5aa..aca10384 100644 --- a/amd/build/linkmodal.min.js +++ b/amd/build/linkmodal.min.js @@ -5,6 +5,6 @@ define("mod_learningmap/linkmodal",["exports","core/modal","core/ajax","core_cou * @module mod_learningmap/linkmodal * @copyright 2025 ISB Bayern * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal=_interopRequireDefault(_modal),_ajax=_interopRequireDefault(_ajax),manualcompletion=function(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]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(manualcompletion),_events=_interopRequireDefault(_events),_jquery=_interopRequireDefault(_jquery);_exports.init=async learningmapcmid=>{document.getElementById("learningmap-render-container-"+learningmapcmid).addEventListener("click",(async event=>{const target=event.target.closest("a[data-cmid]");if(target&&!target.hasAttribute("xlink:href")){event.preventDefault();const cmid=target.getAttribute("data-cmid");if(cmid){const data=await _ajax.default.call([{methodname:"mod_learningmap_get_cm",args:{cmid:cmid}}])[0];let js=_jquery.default.parseHTML(data.js,null,!0).map((node=>node.innerHTML)).join("\n");const modal=await _modal.default.create({title:data.name,body:data.completion+data.html,show:!1,removeOnClose:!0,large:!0});modal.bodyJS=js,modal.show(),manualcompletion.init(),document.addEventListener(_events.default.manualCompletionToggled,(()=>{(0,_renderer.renderLearningmap)(learningmapcmid)}))}}}))}})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modal=_interopRequireDefault(_modal),_ajax=_interopRequireDefault(_ajax),manualcompletion=function(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]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(manualcompletion),_events=_interopRequireDefault(_events),_jquery=_interopRequireDefault(_jquery);_exports.init=async function(learningmapcmid){let inmodal=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const container=document.getElementById("learningmap-render-container-"+learningmapcmid+(inmodal?"-modal":""));container&&container.addEventListener("click",(async event=>{const target=event.target.closest("a[data-cmid]");if(target&&!target.hasAttribute("xlink:href")){event.preventDefault();const cmid=target.getAttribute("data-cmid");if(cmid){const data=await _ajax.default.call([{methodname:"mod_learningmap_get_cm",args:{cmid:cmid}}])[0];let js=_jquery.default.parseHTML(data.js,null,!0).map((node=>node.innerHTML)).join("\n");const modal=await _modal.default.create({title:data.name,body:data.completion+data.html,show:!1,removeOnClose:!0,large:!0});modal.bodyJS=js,modal.show(),manualcompletion.init(),document.addEventListener(_events.default.manualCompletionToggled,(()=>{(0,_renderer.renderLearningmap)(learningmapcmid)}))}}}))}})); //# sourceMappingURL=linkmodal.min.js.map \ No newline at end of file diff --git a/amd/build/linkmodal.min.js.map b/amd/build/linkmodal.min.js.map index 1b304973..b54758a1 100644 --- a/amd/build/linkmodal.min.js.map +++ b/amd/build/linkmodal.min.js.map @@ -1 +1 @@ -{"version":3,"file":"linkmodal.min.js","sources":["../src/linkmodal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport Modal from 'core/modal';\nimport Ajax from 'core/ajax';\nimport * as manualcompletion from 'core_course/manual_completion_toggle';\nimport {renderLearningmap} from 'mod_learningmap/renderer';\nimport CourseEvents from 'core_course/events';\nimport $ from 'jquery';\n\n/**\n * Helper for opening course modules in a modal that do not have a view page.\n *\n * @module mod_learningmap/linkmodal\n * @copyright 2025 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Initialize the link modal listener for a learning map.\n *\n * @param {number} learningmapcmid - The course module ID of the learning map.\n */\nexport const init = async(learningmapcmid) => {\n document.getElementById('learningmap-render-container-' + learningmapcmid).addEventListener('click', async(event) => {\n const target = event.target.closest('a[data-cmid]');\n if (target && !target.hasAttribute('xlink:href')) {\n event.preventDefault();\n const cmid = target.getAttribute('data-cmid');\n if (cmid) {\n const data = await Ajax.call([{\n methodname: 'mod_learningmap_get_cm',\n args: {\n cmid: cmid\n },\n }])[0];\n let js = $.parseHTML(data.js, null, true).map(node => node.innerHTML).join(\"\\n\");\n const modal = await Modal.create({\n title: data.name,\n body: data.completion + data.html,\n show: false,\n removeOnClose: true,\n large: true,\n });\n modal.bodyJS = js;\n modal.show();\n manualcompletion.init();\n document.addEventListener(CourseEvents.manualCompletionToggled, () => {\n renderLearningmap(learningmapcmid);\n });\n }\n }\n });\n};\n"],"names":["async","document","getElementById","learningmapcmid","addEventListener","target","event","closest","hasAttribute","preventDefault","cmid","getAttribute","data","Ajax","call","methodname","args","js","$","parseHTML","map","node","innerHTML","join","modal","Modal","create","title","name","body","completion","html","show","removeOnClose","large","bodyJS","manualcompletion","init","CourseEvents","manualCompletionToggled"],"mappings":";;;;;;;06BAmCoBA,MAAAA,kBAChBC,SAASC,eAAe,gCAAkCC,iBAAiBC,iBAAiB,SAASJ,MAAAA,cAC3FK,OAASC,MAAMD,OAAOE,QAAQ,mBAChCF,SAAWA,OAAOG,aAAa,cAAe,CAC9CF,MAAMG,uBACAC,KAAOL,OAAOM,aAAa,gBAC7BD,KAAM,OACAE,WAAaC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,yBACZC,KAAM,CACFN,KAAMA,SAEV,OACAO,GAAKC,gBAAEC,UAAUP,KAAKK,GAAI,MAAM,GAAMG,KAAIC,MAAQA,KAAKC,YAAWC,KAAK,YACrEC,YAAcC,eAAMC,OAAO,CAC7BC,MAAOf,KAAKgB,KACZC,KAAMjB,KAAKkB,WAAalB,KAAKmB,KAC7BC,MAAM,EACNC,eAAe,EACfC,OAAO,IAEXV,MAAMW,OAASlB,GACfO,MAAMQ,OACNI,iBAAiBC,OACjBpC,SAASG,iBAAiBkC,gBAAaC,yBAAyB,qCAC1CpC"} \ No newline at end of file +{"version":3,"file":"linkmodal.min.js","sources":["../src/linkmodal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\nimport Modal from 'core/modal';\nimport Ajax from 'core/ajax';\nimport * as manualcompletion from 'core_course/manual_completion_toggle';\nimport {renderLearningmap} from 'mod_learningmap/renderer';\nimport CourseEvents from 'core_course/events';\nimport $ from 'jquery';\n\n/**\n * Helper for opening course modules in a modal that do not have a view page.\n *\n * @module mod_learningmap/linkmodal\n * @copyright 2025 ISB Bayern\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Initialize the link modal listener for a learning map.\n *\n * @param {number} learningmapcmid - The course module ID of the learning map.\n * @param {boolean} inmodal - Whether the learning map is already in a modal.\n */\nexport const init = async(learningmapcmid, inmodal = false) => {\n const container = document.getElementById('learningmap-render-container-' + learningmapcmid + (inmodal ? '-modal' : ''));\n if (container) {\n container.addEventListener('click', async(event) => {\n const target = event.target.closest('a[data-cmid]');\n if (target && !target.hasAttribute('xlink:href')) {\n event.preventDefault();\n const cmid = target.getAttribute('data-cmid');\n if (cmid) {\n const data = await Ajax.call([{\n methodname: 'mod_learningmap_get_cm',\n args: {\n cmid: cmid\n },\n }])[0];\n let js = $.parseHTML(data.js, null, true).map(node => node.innerHTML).join(\"\\n\");\n const modal = await Modal.create({\n title: data.name,\n body: data.completion + data.html,\n show: false,\n removeOnClose: true,\n large: true,\n });\n modal.bodyJS = js;\n modal.show();\n manualcompletion.init();\n document.addEventListener(CourseEvents.manualCompletionToggled, () => {\n renderLearningmap(learningmapcmid);\n });\n }\n }\n });\n }\n};\n"],"names":["async","learningmapcmid","inmodal","container","document","getElementById","addEventListener","target","event","closest","hasAttribute","preventDefault","cmid","getAttribute","data","Ajax","call","methodname","args","js","$","parseHTML","map","node","innerHTML","join","modal","Modal","create","title","name","body","completion","html","show","removeOnClose","large","bodyJS","manualcompletion","init","CourseEvents","manualCompletionToggled"],"mappings":";;;;;;;06BAoCoBA,eAAMC,qBAAiBC,sEACjCC,UAAYC,SAASC,eAAe,gCAAkCJ,iBAAmBC,QAAU,SAAW,KAChHC,WACAA,UAAUG,iBAAiB,SAASN,MAAAA,cAC1BO,OAASC,MAAMD,OAAOE,QAAQ,mBAChCF,SAAWA,OAAOG,aAAa,cAAe,CAC9CF,MAAMG,uBACAC,KAAOL,OAAOM,aAAa,gBAC7BD,KAAM,OACAE,WAAaC,cAAKC,KAAK,CAAC,CAC1BC,WAAY,yBACZC,KAAM,CACFN,KAAMA,SAEV,OACAO,GAAKC,gBAAEC,UAAUP,KAAKK,GAAI,MAAM,GAAMG,KAAIC,MAAQA,KAAKC,YAAWC,KAAK,YACrEC,YAAcC,eAAMC,OAAO,CAC7BC,MAAOf,KAAKgB,KACZC,KAAMjB,KAAKkB,WAAalB,KAAKmB,KAC7BC,MAAM,EACNC,eAAe,EACfC,OAAO,IAEXV,MAAMW,OAASlB,GACfO,MAAMQ,OACNI,iBAAiBC,OACjBnC,SAASE,iBAAiBkC,gBAAaC,yBAAyB,qCAC1CxC"} \ No newline at end of file diff --git a/amd/build/renderer.min.js b/amd/build/renderer.min.js index c7357044..cec67608 100644 --- a/amd/build/renderer.min.js +++ b/amd/build/renderer.min.js @@ -6,6 +6,6 @@ define("mod_learningmap/renderer",["exports","core/ajax","core/log","core/pendin * @copyright 2021-2024, ISB Bayern * @author Philipp Memmel * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.selectors=_exports.renderLearningmap=_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_pending=_interopRequireDefault(_pending);const selectors={LEARNINGMAP_RENDER_CONTAINER_PREFIX:"learningmap-render-container-"};_exports.selectors=selectors;_exports.init=cmId=>{const rendererPendingPromise=new _pending.default("mod_learningmap/renderer-"+cmId);renderLearningmap(cmId),rendererPendingPromise.resolve()};const renderLearningmap=cmId=>{_ajax.default.call([{methodname:"mod_learningmap_get_learningmap",args:{cmId:cmId}}])[0].then((data=>(document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX+cmId).innerHTML=data.content,!0))).catch((error=>(_log.default.error(error),!1)))};_exports.renderLearningmap=renderLearningmap})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.selectors=_exports.renderLearningmap=_exports.init=void 0,_ajax=_interopRequireDefault(_ajax),_log=_interopRequireDefault(_log),_pending=_interopRequireDefault(_pending);const selectors={LEARNINGMAP_RENDER_CONTAINER_PREFIX:"learningmap-render-container-"};_exports.selectors=selectors;_exports.init=function(cmId){let inmodal=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const rendererPendingPromise=new _pending.default("mod_learningmap/renderer-"+cmId);renderLearningmap(cmId,inmodal),rendererPendingPromise.resolve()};const renderLearningmap=cmId=>{_ajax.default.call([{methodname:"mod_learningmap_get_learningmap",args:{cmId:cmId}}])[0].then((data=>{let targetDiv=document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX+cmId);return targetDiv&&(targetDiv.innerHTML=data.content),targetDiv=document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX+cmId+"-modal"),targetDiv&&(targetDiv.innerHTML=data.content,targetDiv.parentElement.previousElementSibling.outerHTML=data.completion),!0})).catch((error=>(_log.default.error(error),!1)))};_exports.renderLearningmap=renderLearningmap})); //# sourceMappingURL=renderer.min.js.map \ No newline at end of file diff --git a/amd/build/renderer.min.js.map b/amd/build/renderer.min.js.map index 476448e0..c05b43ac 100644 --- a/amd/build/renderer.min.js.map +++ b/amd/build/renderer.min.js.map @@ -1 +1 @@ -{"version":3,"file":"renderer.min.js","sources":["../src/renderer.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 * Renderer module for the learningmap.\n *\n * @module mod_learningmap/renderer\n * @copyright 2021-2024, ISB Bayern\n * @author Philipp Memmel\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';\nimport Pending from 'core/pending';\n\nexport const selectors = {\n LEARNINGMAP_RENDER_CONTAINER_PREFIX: 'learningmap-render-container-'\n};\n\n/**\n * Renders the learningmap into the correct div.\n *\n * @param {number} cmId the course module id of the learningmap\n */\nexport const init = (cmId) => {\n const rendererPendingPromise = new Pending('mod_learningmap/renderer-' + cmId);\n renderLearningmap(cmId);\n rendererPendingPromise.resolve();\n};\n\n/**\n * Render the learningmap with the given cmId into the corresponding div in the DOM.\n *\n * @param {number} cmId the course module id of the learningmap\n */\nexport const renderLearningmap = (cmId) => {\n const promises = Ajax.call(\n [\n {\n methodname: 'mod_learningmap_get_learningmap',\n args: {\n 'cmId': cmId\n }\n }\n ]);\n\n promises[0].then(data => {\n const targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId);\n targetDiv.innerHTML = data.content;\n return true;\n }).catch((error) => {\n Log.error(error);\n return false;\n });\n};\n"],"names":["selectors","LEARNINGMAP_RENDER_CONTAINER_PREFIX","cmId","rendererPendingPromise","Pending","renderLearningmap","resolve","Ajax","call","methodname","args","then","data","document","getElementById","innerHTML","content","catch","error"],"mappings":";;;;;;;;sPA2BaA,UAAY,CACrBC,oCAAqC,4EAQpBC,aACXC,uBAAyB,IAAIC,iBAAQ,4BAA8BF,MACzEG,kBAAkBH,MAClBC,uBAAuBG,iBAQdD,kBAAqBH,OACbK,cAAKC,KAClB,CACI,CACIC,WAAY,kCACZC,KAAM,MACMR,SAKf,GAAGS,MAAKC,OACKC,SAASC,eAAed,UAAUC,oCAAsCC,MAChFa,UAAYH,KAAKI,SACpB,KACRC,OAAOC,qBACFA,MAAMA,QACH"} \ No newline at end of file +{"version":3,"file":"renderer.min.js","sources":["../src/renderer.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 * Renderer module for the learningmap.\n *\n * @module mod_learningmap/renderer\n * @copyright 2021-2024, ISB Bayern\n * @author Philipp Memmel\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';\nimport Pending from 'core/pending';\n\nexport const selectors = {\n LEARNINGMAP_RENDER_CONTAINER_PREFIX: 'learningmap-render-container-'\n};\n\n/**\n * Renders the learningmap into the correct div.\n *\n * @param {number} cmId the course module id of the learningmap\n * @param {boolean} inmodal whether the learningmap is being rendered in a modal\n */\nexport const init = (cmId, inmodal = false) => {\n const rendererPendingPromise = new Pending('mod_learningmap/renderer-' + cmId);\n renderLearningmap(cmId, inmodal);\n rendererPendingPromise.resolve();\n};\n\n/**\n * Render the learningmap with the given cmId into the corresponding div in the DOM.\n *\n * @param {number} cmId the course module id of the learningmap\n */\nexport const renderLearningmap = (cmId) => {\n const promises = Ajax.call(\n [\n {\n methodname: 'mod_learningmap_get_learningmap',\n args: {\n 'cmId': cmId\n }\n }\n ]);\n\n promises[0].then(data => {\n let targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId);\n if (targetDiv) {\n targetDiv.innerHTML = data.content;\n }\n targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId + '-modal');\n if (targetDiv) {\n targetDiv.innerHTML = data.content;\n targetDiv.parentElement.previousElementSibling.outerHTML = data.completion;\n }\n return true;\n }).catch((error) => {\n Log.error(error);\n return false;\n });\n};\n"],"names":["selectors","LEARNINGMAP_RENDER_CONTAINER_PREFIX","cmId","inmodal","rendererPendingPromise","Pending","renderLearningmap","resolve","Ajax","call","methodname","args","then","data","targetDiv","document","getElementById","innerHTML","content","parentElement","previousElementSibling","outerHTML","completion","catch","error"],"mappings":";;;;;;;;sPA2BaA,UAAY,CACrBC,oCAAqC,4EASrB,SAACC,UAAMC,sEACjBC,uBAAyB,IAAIC,iBAAQ,4BAA8BH,MACzEI,kBAAkBJ,KAAMC,SACxBC,uBAAuBG,iBAQdD,kBAAqBJ,OACbM,cAAKC,KAClB,CACI,CACIC,WAAY,kCACZC,KAAM,MACMT,SAKf,GAAGU,MAAKC,WACTC,UAAYC,SAASC,eAAehB,UAAUC,oCAAsCC,aACpFY,YACAA,UAAUG,UAAYJ,KAAKK,SAE/BJ,UAAYC,SAASC,eAAehB,UAAUC,oCAAsCC,KAAO,UACvFY,YACAA,UAAUG,UAAYJ,KAAKK,QAC3BJ,UAAUK,cAAcC,uBAAuBC,UAAYR,KAAKS,aAE7D,KACRC,OAAOC,qBACFA,MAAMA,QACH"} \ No newline at end of file diff --git a/amd/src/initliveupdater.js b/amd/src/initliveupdater.js index 81d0d5e7..677d4079 100644 --- a/amd/src/initliveupdater.js +++ b/amd/src/initliveupdater.js @@ -32,9 +32,10 @@ import Pending from 'core/pending'; * Renders the learningmap into the correct div. * * @param {number} cmId the course module id of the learningmap + * @param {boolean} inmodal whether the learningmap is being rendered in a modal * @return {Component} the liveupdater component */ -export const init = async(cmId) => { +export const init = async(cmId, inmodal = false) => { const initliveupdaterPendingPromise = new Pending('mod_learningmap/initliveupdater'); try { const data = await Ajax.call( @@ -49,7 +50,7 @@ export const init = async(cmId) => { initliveupdaterPendingPromise.resolve(); return new LiveUpdater({ - element: document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId), + element: document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId + (inmodal ? '-modal' : '')), reactive: getCurrentCourseEditor(), cmId: cmId, dependingModuleIds: data.dependingModuleIds diff --git a/amd/src/linkmodal.js b/amd/src/linkmodal.js index 873b0a26..408fa97a 100644 --- a/amd/src/linkmodal.js +++ b/amd/src/linkmodal.js @@ -32,35 +32,39 @@ import $ from 'jquery'; * Initialize the link modal listener for a learning map. * * @param {number} learningmapcmid - The course module ID of the learning map. + * @param {boolean} inmodal - Whether the learning map is already in a modal. */ -export const init = async(learningmapcmid) => { - document.getElementById('learningmap-render-container-' + learningmapcmid).addEventListener('click', async(event) => { - const target = event.target.closest('a[data-cmid]'); - if (target && !target.hasAttribute('xlink:href')) { - event.preventDefault(); - const cmid = target.getAttribute('data-cmid'); - if (cmid) { - const data = await Ajax.call([{ - methodname: 'mod_learningmap_get_cm', - args: { - cmid: cmid - }, - }])[0]; - let js = $.parseHTML(data.js, null, true).map(node => node.innerHTML).join("\n"); - const modal = await Modal.create({ - title: data.name, - body: data.completion + data.html, - show: false, - removeOnClose: true, - large: true, - }); - modal.bodyJS = js; - modal.show(); - manualcompletion.init(); - document.addEventListener(CourseEvents.manualCompletionToggled, () => { - renderLearningmap(learningmapcmid); - }); +export const init = async(learningmapcmid, inmodal = false) => { + const container = document.getElementById('learningmap-render-container-' + learningmapcmid + (inmodal ? '-modal' : '')); + if (container) { + container.addEventListener('click', async(event) => { + const target = event.target.closest('a[data-cmid]'); + if (target && !target.hasAttribute('xlink:href')) { + event.preventDefault(); + const cmid = target.getAttribute('data-cmid'); + if (cmid) { + const data = await Ajax.call([{ + methodname: 'mod_learningmap_get_cm', + args: { + cmid: cmid + }, + }])[0]; + let js = $.parseHTML(data.js, null, true).map(node => node.innerHTML).join("\n"); + const modal = await Modal.create({ + title: data.name, + body: data.completion + data.html, + show: false, + removeOnClose: true, + large: true, + }); + modal.bodyJS = js; + modal.show(); + manualcompletion.init(); + document.addEventListener(CourseEvents.manualCompletionToggled, () => { + renderLearningmap(learningmapcmid); + }); + } } - } - }); + }); + } }; diff --git a/amd/src/renderer.js b/amd/src/renderer.js index 84a84d85..dc071757 100644 --- a/amd/src/renderer.js +++ b/amd/src/renderer.js @@ -33,10 +33,11 @@ export const selectors = { * Renders the learningmap into the correct div. * * @param {number} cmId the course module id of the learningmap + * @param {boolean} inmodal whether the learningmap is being rendered in a modal */ -export const init = (cmId) => { +export const init = (cmId, inmodal = false) => { const rendererPendingPromise = new Pending('mod_learningmap/renderer-' + cmId); - renderLearningmap(cmId); + renderLearningmap(cmId, inmodal); rendererPendingPromise.resolve(); }; @@ -57,8 +58,15 @@ export const renderLearningmap = (cmId) => { ]); promises[0].then(data => { - const targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId); - targetDiv.innerHTML = data.content; + let targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId); + if (targetDiv) { + targetDiv.innerHTML = data.content; + } + targetDiv = document.getElementById(selectors.LEARNINGMAP_RENDER_CONTAINER_PREFIX + cmId + '-modal'); + if (targetDiv) { + targetDiv.innerHTML = data.content; + targetDiv.parentElement.previousElementSibling.outerHTML = data.completion; + } return true; }).catch((error) => { Log.error(error); diff --git a/classes/external/get_cm.php b/classes/external/get_cm.php index 09ec0cb4..dc468db3 100644 --- a/classes/external/get_cm.php +++ b/classes/external/get_cm.php @@ -54,16 +54,15 @@ public static function execute(int $cmid): array { define('LEARNINGMAP_NO_BACKLINK', true); - $cm = get_coursemodule_from_id('', $cmid, 0, false, MUST_EXIST); + [$course, $cm] = get_course_and_cm_from_cmid($cmid); $context = \context_module::instance($cm->id); - $course = get_course($cm->course); self::validate_context($context); require_capability('mod/' . $cm->modname . ':view', $context); $modinfo = get_fast_modinfo($course); - if (!$cm->uservisible) { + if (!$cm->available || !$cm->is_stealth() && $cm->visible == 0) { require_capability('moodle/course:viewhiddenactivities', $context); } @@ -75,7 +74,16 @@ public static function execute(int $cmid): array { $completioninfo = new \completion_info($course); $completioninfo->set_module_viewed($cm); - $data = (array)$cm; + $data = [ + 'id' => $cm->id, + 'course' => $cm->course, + 'module' => $cm->module, + 'instance' => $cm->instance, + 'section' => $cm->sectionnum, + 'visible' => $cm->visible, + 'groupmode' => groups_get_activity_groupmode($cm, $course), + 'groupingid' => $cm->groupingid, + ]; // Remove description for labels, because it is already in html. if ($cm->modname === 'label') { diff --git a/classes/external/get_learningmap.php b/classes/external/get_learningmap.php index 0e8b06a5..615386e3 100644 --- a/classes/external/get_learningmap.php +++ b/classes/external/get_learningmap.php @@ -69,6 +69,7 @@ public static function execute_returns(): external_single_structure { new external_single_structure( [ 'content' => new external_value(PARAM_RAW, 'Rendered learningmap'), + 'completion' => new external_value(PARAM_RAW, 'Activity header HTML code'), ] ); } @@ -85,6 +86,7 @@ public static function execute_returns(): external_single_structure { * @throws moodle_exception */ public static function execute(int $cmid): array { + global $PAGE, $OUTPUT; $params = self::validate_parameters(self::execute_parameters(), ['cmId' => $cmid]); $cmid = $params['cmId']; [$course, $cminfo] = get_course_and_cm_from_cmid($cmid); @@ -93,8 +95,19 @@ public static function execute(int $cmid): array { require_capability('mod/learningmap:view', $context); $completion = new \completion_info($course); $completion->set_module_viewed($cminfo); + + $PAGE->set_context($context); + $PAGE->set_cm($cminfo); + $PAGE->set_pagelayout('embedded'); + + $completion = $OUTPUT->render_from_template( + 'core/activity_header', + $PAGE->activityheader->export_for_template($OUTPUT) + ); + return [ 'content' => learningmap_get_learningmap($cminfo), + 'completion' => $completion, ]; } } diff --git a/classes/helper.php b/classes/helper.php index 39be7cf4..e473b4c5 100644 --- a/classes/helper.php +++ b/classes/helper.php @@ -111,4 +111,13 @@ public static function is_ajax_request(): bool { !empty($_REQUEST['info']) && in_array($_REQUEST['info'], ['core_course_get_module', 'mod_learningmap_get_cm']); } + + /** + * Determines if the current request is for the get_cm web service function. + * + * @return bool True if the request is for the get_cm web service function, false otherwise. + */ + public static function is_get_cm_request(): bool { + return !empty($_REQUEST['info']) && $_REQUEST['info'] === 'mod_learningmap_get_cm'; + } } diff --git a/lib.php b/lib.php index c925ad9f..7fadb7fd 100644 --- a/lib.php +++ b/lib.php @@ -285,6 +285,7 @@ function learningmap_cm_info_view(cm_info $cm): void { 'hascontentbeforemap' => $hascontentbeforemap, 'mapcontent' => $mapcontent, 'usemodal' => !empty($learningmap->usemodal) || helper::is_learningmap_format($cm), + 'inmodal' => helper::is_get_cm_request(), ] ); diff --git a/templates/rendercontainer.mustache b/templates/rendercontainer.mustache index 928cd010..dd39d0ca 100644 --- a/templates/rendercontainer.mustache +++ b/templates/rendercontainer.mustache @@ -37,6 +37,7 @@ "hascontentbeforemap": true, "mapcontent": "...", "usemodal": true, + "inmodal": false, } }}
@@ -45,7 +46,7 @@ {{{contentbeforemap}}}
{{/hascontentbeforemap}} -
+
{{^mapcontent}}{{> mod_learningmap/loadingplaceholder}}{{/mapcontent}} {{{mapcontent}}}
@@ -53,17 +54,17 @@ {{#js}} {{^mapcontent}} require(['mod_learningmap/renderer'], function(renderer) { - renderer.init({{cmId}}); + renderer.init({{cmId}}, {{inmodal}}); }); {{/mapcontent}} {{#usemodal}} require(['mod_learningmap/linkmodal'], function(linkmodal) { - linkmodal.init({{cmId}}); + linkmodal.init({{cmId}}, {{inmodal}}); }); {{/usemodal}} {{#enableLiveUpdater}} require(['mod_learningmap/initliveupdater'], function(initliveupdater) { - initliveupdater.init({{cmId}}); + initliveupdater.init({{cmId}}, {{inmodal}}); }); {{/enableLiveUpdater}} {{/js}} diff --git a/view.php b/view.php index a6cfbe4b..4e0e5299 100644 --- a/view.php +++ b/view.php @@ -74,6 +74,7 @@ 'hascontentbeforemap' => false, 'mapcontent' => $mapcontent, 'usemodal' => !empty($map->usemodal) || helper::is_learningmap_format($cm), + 'inmodal' => false, ] );