From 04f8fdd02124e9bc07f3a88c9ca3f208d8a4b94c Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 27 Feb 2023 15:29:33 +0100 Subject: [PATCH 1/5] MDL-77164 various: fix javascript AMD module name --- admin/tool/lp/amd/build/competency_rule.min.js | 2 +- admin/tool/lp/amd/build/competency_rule.min.js.map | 2 +- admin/tool/lp/amd/build/competency_rule_points.min.js | 2 +- admin/tool/lp/amd/build/competency_rule_points.min.js.map | 2 +- admin/tool/lp/amd/build/competencydialogue.min.js | 2 +- admin/tool/lp/amd/build/competencydialogue.min.js.map | 2 +- admin/tool/lp/amd/build/competencytree.min.js | 2 +- admin/tool/lp/amd/build/competencytree.min.js.map | 2 +- admin/tool/lp/amd/build/course_competency_settings.min.js | 2 +- admin/tool/lp/amd/build/course_competency_settings.min.js.map | 2 +- admin/tool/lp/amd/src/competency_rule.js | 2 +- admin/tool/lp/amd/src/competency_rule_points.js | 2 +- admin/tool/lp/amd/src/competencydialogue.js | 2 +- admin/tool/lp/amd/src/competencytree.js | 2 +- admin/tool/lp/amd/src/course_competency_settings.js | 2 +- admin/tool/usertours/amd/build/repository.min.js.map | 2 +- admin/tool/usertours/amd/src/repository.js | 4 ++-- calendar/amd/build/calendar_view.min.js | 2 +- calendar/amd/build/calendar_view.min.js.map | 2 +- calendar/amd/build/modal_event_form.min.js | 2 +- calendar/amd/build/modal_event_form.min.js.map | 2 +- calendar/amd/build/selectors.min.js | 4 ++-- calendar/amd/build/selectors.min.js.map | 2 +- calendar/amd/src/calendar_view.js | 2 +- calendar/amd/src/modal_event_form.js | 2 +- calendar/amd/src/selectors.js | 4 ++-- course/amd/build/local/activitychooser/dialogue.min.js.map | 2 +- course/amd/build/local/activitychooser/repository.min.js | 3 ++- course/amd/build/local/activitychooser/repository.min.js.map | 2 +- course/amd/build/local/activitychooser/selectors.min.js | 2 +- course/amd/build/local/activitychooser/selectors.min.js.map | 2 +- course/amd/src/local/activitychooser/dialogue.js | 2 +- course/amd/src/local/activitychooser/repository.js | 3 ++- course/amd/src/local/activitychooser/selectors.js | 2 +- course/format/amd/build/local/courseeditor/contenttree.min.js | 4 ++-- .../amd/build/local/courseeditor/contenttree.min.js.map | 2 +- course/format/amd/src/local/courseeditor/contenttree.js | 4 ++-- course/format/topics/amd/build/section.min.js | 2 +- course/format/topics/amd/build/section.min.js.map | 2 +- course/format/topics/amd/src/section.js | 2 +- grade/report/singleview/amd/build/grade.min.js | 2 +- grade/report/singleview/amd/build/grade.min.js.map | 2 +- grade/report/singleview/amd/src/grade.js | 2 +- lib/amd/build/loadingicon.min.js | 3 +-- lib/amd/build/loadingicon.min.js.map | 2 +- lib/amd/build/local/aria/focuslock.min.js | 2 +- lib/amd/build/local/aria/focuslock.min.js.map | 2 +- lib/amd/build/local/modal/alert.min.js | 2 +- lib/amd/build/local/modal/alert.min.js.map | 2 +- lib/amd/build/local/reactive/debug.min.js | 2 +- lib/amd/build/local/reactive/debug.min.js.map | 2 +- lib/amd/build/local/reactive/reactive.min.js | 4 ++-- lib/amd/build/local/reactive/reactive.min.js.map | 2 +- lib/amd/build/local/reactive/statemanager.min.js | 4 ++-- lib/amd/build/local/reactive/statemanager.min.js.map | 2 +- lib/amd/build/paged_content_paging_bar.min.js | 2 +- lib/amd/build/paged_content_paging_bar.min.js.map | 2 +- lib/amd/build/userfeedback.min.js | 2 +- lib/amd/build/userfeedback.min.js.map | 2 +- lib/amd/src/loadingicon.js | 3 +-- lib/amd/src/local/aria/focuslock.js | 2 +- lib/amd/src/local/modal/alert.js | 2 +- lib/amd/src/local/reactive/debug.js | 2 +- lib/amd/src/local/reactive/reactive.js | 4 ++-- lib/amd/src/local/reactive/statemanager.js | 4 ++-- lib/amd/src/paged_content_paging_bar.js | 2 +- lib/amd/src/userfeedback.js | 2 +- lib/editor/tiny/amd/build/defaults.min.js | 2 +- lib/editor/tiny/amd/build/defaults.min.js.map | 2 +- lib/editor/tiny/amd/build/uploader.min.js.map | 2 +- lib/editor/tiny/amd/src/defaults.js | 2 +- lib/editor/tiny/amd/src/uploader.js | 2 +- lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js | 2 +- .../tiny/plugins/autosave/amd/build/autosaver.min.js.map | 2 +- lib/editor/tiny/plugins/autosave/amd/build/common.min.js.map | 2 +- lib/editor/tiny/plugins/autosave/amd/build/options.min.js | 2 +- lib/editor/tiny/plugins/autosave/amd/build/options.min.js.map | 2 +- lib/editor/tiny/plugins/autosave/amd/build/storage.min.js | 2 +- lib/editor/tiny/plugins/autosave/amd/build/storage.min.js.map | 2 +- lib/editor/tiny/plugins/autosave/amd/src/autosaver.js | 2 +- lib/editor/tiny/plugins/autosave/amd/src/common.js | 2 +- lib/editor/tiny/plugins/autosave/amd/src/options.js | 2 +- lib/editor/tiny/plugins/autosave/amd/src/storage.js | 2 +- lib/editor/tiny/plugins/h5p/amd/build/ui.min.js | 2 +- lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map | 2 +- lib/editor/tiny/plugins/h5p/amd/src/ui.js | 2 +- lib/editor/tiny/plugins/media/amd/build/embedmodal.min.js.map | 2 +- lib/editor/tiny/plugins/media/amd/src/embedmodal.js | 2 +- .../plugins/recordrtc/amd/build/audio_recorder.min.js.map | 2 +- .../tiny/plugins/recordrtc/amd/build/base_recorder.min.js.map | 2 +- .../tiny/plugins/recordrtc/amd/build/commands_audio.min.js | 2 +- .../plugins/recordrtc/amd/build/commands_audio.min.js.map | 2 +- .../tiny/plugins/recordrtc/amd/build/commands_video.min.js | 2 +- .../plugins/recordrtc/amd/build/commands_video.min.js.map | 2 +- .../plugins/recordrtc/amd/build/video_recorder.min.js.map | 2 +- lib/editor/tiny/plugins/recordrtc/amd/src/audio_recorder.js | 2 +- lib/editor/tiny/plugins/recordrtc/amd/src/base_recorder.js | 2 +- lib/editor/tiny/plugins/recordrtc/amd/src/commands_audio.js | 2 +- lib/editor/tiny/plugins/recordrtc/amd/src/commands_video.js | 2 +- lib/editor/tiny/plugins/recordrtc/amd/src/video_recorder.js | 2 +- lib/table/amd/build/local/dynamic/repository.min.js.map | 2 +- lib/table/amd/build/local/dynamic/selectors.min.js.map | 2 +- lib/table/amd/src/local/dynamic/repository.js | 2 +- lib/table/amd/src/local/dynamic/selectors.js | 2 +- mod/assign/amd/build/participant_selector.min.js | 2 +- mod/assign/amd/build/participant_selector.min.js.map | 2 +- mod/assign/amd/src/participant_selector.js | 2 +- mod/bigbluebuttonbn/amd/build/modform.min.js | 2 +- mod/bigbluebuttonbn/amd/build/modform.min.js.map | 2 +- mod/bigbluebuttonbn/amd/src/modform.js | 2 +- mod/data/amd/build/importpresets.min.js | 2 +- mod/data/amd/build/importpresets.min.js.map | 2 +- mod/data/amd/src/importpresets.js | 2 +- mod/forum/amd/build/discussion.min.js | 2 +- mod/forum/amd/build/discussion.min.js.map | 2 +- mod/forum/amd/build/discussion_nested_v2.min.js | 2 +- mod/forum/amd/build/discussion_nested_v2.min.js.map | 2 +- mod/forum/amd/src/discussion.js | 2 +- mod/forum/amd/src/discussion_nested_v2.js | 2 +- payment/gateway/paypal/amd/build/gateways_modal.min.js | 2 +- payment/gateway/paypal/amd/build/gateways_modal.min.js.map | 2 +- payment/gateway/paypal/amd/src/gateways_modal.js | 2 +- question/amd/build/selectors.min.js | 2 +- question/amd/build/selectors.min.js.map | 2 +- question/amd/src/selectors.js | 2 +- question/bank/previewquestion/amd/build/preview.min.js.map | 2 +- question/bank/previewquestion/amd/src/preview.js | 2 +- question/bank/tagquestion/amd/build/selectors.min.js | 2 +- question/bank/tagquestion/amd/build/selectors.min.js.map | 2 +- question/bank/tagquestion/amd/src/selectors.js | 2 +- report/participation/amd/build/participants.min.js | 2 +- report/participation/amd/build/participants.min.js.map | 2 +- report/participation/amd/src/participants.js | 2 +- 133 files changed, 144 insertions(+), 144 deletions(-) diff --git a/admin/tool/lp/amd/build/competency_rule.min.js b/admin/tool/lp/amd/build/competency_rule.min.js index 032876db145..72d554b96e3 100644 --- a/admin/tool/lp/amd/build/competency_rule.min.js +++ b/admin/tool/lp/amd/build/competency_rule.min.js @@ -1,7 +1,7 @@ /** * Competency rule base module. * - * @module tool_lp/competencyrule + * @module tool_lp/competency_rule * @copyright 2015 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/build/competency_rule.min.js.map b/admin/tool/lp/amd/build/competency_rule.min.js.map index a0fe9913190..863fade449a 100644 --- a/admin/tool/lp/amd/build/competency_rule.min.js.map +++ b/admin/tool/lp/amd/build/competency_rule.min.js.map @@ -1 +1 @@ -{"version":3,"file":"competency_rule.min.js","sources":["../src/competency_rule.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 * Competency rule base module.\n *\n * @module tool_lp/competencyrule\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * Competency rule abstract class.\n *\n * Any competency rule should extend this object. The event 'change' should be\n * triggered on the instance when the configuration has changed. This will allow\n * the components using the rule to gather the config, or check its validity.\n *\n * this._triggerChange();\n *\n * @param {Tree} tree The competency tree.\n */\n var Rule = function(tree) {\n this._eventNode = $('
');\n this._ready = $.Deferred();\n this._tree = tree;\n };\n\n /** @property {Object} The current competency. */\n Rule.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n Rule.prototype._eventNode = null;\n /** @property {Promise} Resolved when the object is ready. */\n Rule.prototype._ready = null;\n /** @property {Tree} The competency tree. */\n Rule.prototype._tree = null;\n\n /**\n * Whether or not the current competency can be configured using this rule.\n *\n * @return {Boolean}\n * @method canConfig\n */\n Rule.prototype.canConfig = function() {\n return this._tree.hasChildren(this._competency.id);\n };\n\n /**\n * The config established by this rule.\n *\n * To override in subclasses when relevant.\n *\n * @return {String|null}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return null;\n };\n\n // eslint-disable-line valid-jsdoc\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n // eslint-enable-line valid-jsdoc\n Rule.prototype.getType = function() {\n throw new Error('Not implemented');\n };\n\n /**\n * The init process.\n *\n * Do not override this, instead override _load.\n *\n * @return {Promise} Revoled when the plugin is initialised.\n * @method init\n */\n Rule.prototype.init = function() {\n return this._load();\n };\n\n /**\n * Callback to inject the template.\n *\n * @returns {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function() {\n return $.Deferred().reject().promise();\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * Plugins should override this.\n *\n * @return {Boolean}\n * @method _isValid\n */\n Rule.prototype.isValid = function() {\n return false;\n };\n\n /**\n * Load the class.\n *\n * @return {Promise}\n * @method _load\n * @protected\n */\n Rule.prototype._load = function() {\n return $.when();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Rule.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Sets the current competency.\n *\n * @param {Competency} competency\n * @method setTargetCompetency\n */\n Rule.prototype.setTargetCompetency = function(competency) {\n this._competency = competency;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n Rule.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n /**\n * Trigger the change event.\n *\n * @method _triggerChange\n * @protected\n */\n Rule.prototype._triggerChange = function() {\n this._trigger('change', this);\n };\n\n return /** @alias module:tool_lp/competency_rule */ Rule;\n\n});\n"],"names":["define","$","Rule","tree","_eventNode","_ready","Deferred","_tree","prototype","_competency","canConfig","this","hasChildren","id","getConfig","getType","Error","init","_load","injectTemplate","reject","promise","isValid","when","on","type","handler","setTargetCompetency","competency","_trigger","data","trigger","_triggerChange"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,WAAW,SAASC,OAapBC,KAAO,SAASC,WACXC,WAAaH,EAAE,cACfI,OAASJ,EAAEK,gBACXC,MAAQJ,aAIjBD,KAAKM,UAAUC,YAAc,KAE7BP,KAAKM,UAAUJ,WAAa,KAE5BF,KAAKM,UAAUH,OAAS,KAExBH,KAAKM,UAAUD,MAAQ,KAQvBL,KAAKM,UAAUE,UAAY,kBAChBC,KAAKJ,MAAMK,YAAYD,KAAKF,YAAYI,KAWnDX,KAAKM,UAAUM,UAAY,kBAChB,MAWXZ,KAAKM,UAAUO,QAAU,iBACf,IAAIC,MAAM,oBAWpBd,KAAKM,UAAUS,KAAO,kBACXN,KAAKO,SAShBhB,KAAKM,UAAUW,eAAiB,kBACrBlB,EAAEK,WAAWc,SAASC,WAWjCnB,KAAKM,UAAUc,QAAU,kBACd,GAUXpB,KAAKM,UAAUU,MAAQ,kBACZjB,EAAEsB,QAUbrB,KAAKM,UAAUgB,GAAK,SAASC,KAAMC,cAC1BtB,WAAWoB,GAAGC,KAAMC,UAS7BxB,KAAKM,UAAUmB,oBAAsB,SAASC,iBACrCnB,YAAcmB,YAWvB1B,KAAKM,UAAUqB,SAAW,SAASJ,KAAMK,WAChC1B,WAAW2B,QAAQN,KAAM,CAACK,QASnC5B,KAAKM,UAAUwB,eAAiB,gBACvBH,SAAS,SAAUlB,OAGwBT"} \ No newline at end of file +{"version":3,"file":"competency_rule.min.js","sources":["../src/competency_rule.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 * Competency rule base module.\n *\n * @module tool_lp/competency_rule\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery'], function($) {\n\n /**\n * Competency rule abstract class.\n *\n * Any competency rule should extend this object. The event 'change' should be\n * triggered on the instance when the configuration has changed. This will allow\n * the components using the rule to gather the config, or check its validity.\n *\n * this._triggerChange();\n *\n * @param {Tree} tree The competency tree.\n */\n var Rule = function(tree) {\n this._eventNode = $('
');\n this._ready = $.Deferred();\n this._tree = tree;\n };\n\n /** @property {Object} The current competency. */\n Rule.prototype._competency = null;\n /** @property {Node} The node we attach the events to. */\n Rule.prototype._eventNode = null;\n /** @property {Promise} Resolved when the object is ready. */\n Rule.prototype._ready = null;\n /** @property {Tree} The competency tree. */\n Rule.prototype._tree = null;\n\n /**\n * Whether or not the current competency can be configured using this rule.\n *\n * @return {Boolean}\n * @method canConfig\n */\n Rule.prototype.canConfig = function() {\n return this._tree.hasChildren(this._competency.id);\n };\n\n /**\n * The config established by this rule.\n *\n * To override in subclasses when relevant.\n *\n * @return {String|null}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return null;\n };\n\n // eslint-disable-line valid-jsdoc\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n // eslint-enable-line valid-jsdoc\n Rule.prototype.getType = function() {\n throw new Error('Not implemented');\n };\n\n /**\n * The init process.\n *\n * Do not override this, instead override _load.\n *\n * @return {Promise} Revoled when the plugin is initialised.\n * @method init\n */\n Rule.prototype.init = function() {\n return this._load();\n };\n\n /**\n * Callback to inject the template.\n *\n * @returns {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function() {\n return $.Deferred().reject().promise();\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * Plugins should override this.\n *\n * @return {Boolean}\n * @method _isValid\n */\n Rule.prototype.isValid = function() {\n return false;\n };\n\n /**\n * Load the class.\n *\n * @return {Promise}\n * @method _load\n * @protected\n */\n Rule.prototype._load = function() {\n return $.when();\n };\n\n /**\n * Register an event listener.\n *\n * @param {String} type The event type.\n * @param {Function} handler The event listener.\n * @method on\n */\n Rule.prototype.on = function(type, handler) {\n this._eventNode.on(type, handler);\n };\n\n /**\n * Sets the current competency.\n *\n * @param {Competency} competency\n * @method setTargetCompetency\n */\n Rule.prototype.setTargetCompetency = function(competency) {\n this._competency = competency;\n };\n\n /**\n * Trigger an event.\n *\n * @param {String} type The type of event.\n * @param {Object} data The data to pass to the listeners.\n * @method _trigger\n * @protected\n */\n Rule.prototype._trigger = function(type, data) {\n this._eventNode.trigger(type, [data]);\n };\n\n /**\n * Trigger the change event.\n *\n * @method _triggerChange\n * @protected\n */\n Rule.prototype._triggerChange = function() {\n this._trigger('change', this);\n };\n\n return /** @alias module:tool_lp/competency_rule */ Rule;\n\n});\n"],"names":["define","$","Rule","tree","_eventNode","_ready","Deferred","_tree","prototype","_competency","canConfig","this","hasChildren","id","getConfig","getType","Error","init","_load","injectTemplate","reject","promise","isValid","when","on","type","handler","setTargetCompetency","competency","_trigger","data","trigger","_triggerChange"],"mappings":";;;;;;;AAuBAA,iCAAO,CAAC,WAAW,SAASC,OAapBC,KAAO,SAASC,WACXC,WAAaH,EAAE,cACfI,OAASJ,EAAEK,gBACXC,MAAQJ,aAIjBD,KAAKM,UAAUC,YAAc,KAE7BP,KAAKM,UAAUJ,WAAa,KAE5BF,KAAKM,UAAUH,OAAS,KAExBH,KAAKM,UAAUD,MAAQ,KAQvBL,KAAKM,UAAUE,UAAY,kBAChBC,KAAKJ,MAAMK,YAAYD,KAAKF,YAAYI,KAWnDX,KAAKM,UAAUM,UAAY,kBAChB,MAWXZ,KAAKM,UAAUO,QAAU,iBACf,IAAIC,MAAM,oBAWpBd,KAAKM,UAAUS,KAAO,kBACXN,KAAKO,SAShBhB,KAAKM,UAAUW,eAAiB,kBACrBlB,EAAEK,WAAWc,SAASC,WAWjCnB,KAAKM,UAAUc,QAAU,kBACd,GAUXpB,KAAKM,UAAUU,MAAQ,kBACZjB,EAAEsB,QAUbrB,KAAKM,UAAUgB,GAAK,SAASC,KAAMC,cAC1BtB,WAAWoB,GAAGC,KAAMC,UAS7BxB,KAAKM,UAAUmB,oBAAsB,SAASC,iBACrCnB,YAAcmB,YAWvB1B,KAAKM,UAAUqB,SAAW,SAASJ,KAAMK,WAChC1B,WAAW2B,QAAQN,KAAM,CAACK,QASnC5B,KAAKM,UAAUwB,eAAiB,gBACvBH,SAAS,SAAUlB,OAGwBT"} \ No newline at end of file diff --git a/admin/tool/lp/amd/build/competency_rule_points.min.js b/admin/tool/lp/amd/build/competency_rule_points.min.js index fb104b99183..82c4aa4a0bf 100644 --- a/admin/tool/lp/amd/build/competency_rule_points.min.js +++ b/admin/tool/lp/amd/build/competency_rule_points.min.js @@ -1,7 +1,7 @@ /** * Competency rule points module. * - * @module tool_lp/competency_rule_all + * @module tool_lp/competency_rule_points * @copyright 2015 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/build/competency_rule_points.min.js.map b/admin/tool/lp/amd/build/competency_rule_points.min.js.map index d3583f13916..da569b12e26 100644 --- a/admin/tool/lp/amd/build/competency_rule_points.min.js.map +++ b/admin/tool/lp/amd/build/competency_rule_points.min.js.map @@ -1 +1 @@ -{"version":3,"file":"competency_rule_points.min.js","sources":["../src/competency_rule_points.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 * Competency rule points module.\n *\n * @module tool_lp/competency_rule_all\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'core/templates',\n 'tool_lp/competency_rule',\n ],\n function($, Str, Templates, RuleBase) {\n\n /**\n * Competency rule points class.\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /** @property {Node} Reference to the container in which the template was included. */\n Rule.prototype._container = null;\n /** @property {Boolean} Whether or not the template was included. */\n Rule.prototype._templateLoaded = false;\n\n /**\n * The config established by this rule.\n *\n * @return {String}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return JSON.stringify({\n base: {\n points: this._getRequiredPoints(),\n },\n competencies: this._getCompetenciesConfig()\n });\n };\n\n /**\n * Gathers the input provided by the user for competencies.\n *\n * @return {Array} Containing id, points and required.\n * @method _getCompetenciesConfig\n * @protected\n */\n Rule.prototype._getCompetenciesConfig = function() {\n var competencies = [];\n\n this._container.find('[data-competency]').each(function() {\n var node = $(this),\n id = node.data('competency'),\n points = parseInt(node.find('[name=\"points\"]').val(), 10),\n required = node.find('[name=\"required\"]').prop('checked');\n\n competencies.push({\n id: id,\n points: points,\n required: required ? 1 : 0\n });\n });\n\n return competencies;\n };\n\n /**\n * Fetches the required points set by the user.\n *\n * @return {Number}\n * @method _getRequiredPoints\n * @protected\n */\n Rule.prototype._getRequiredPoints = function() {\n return parseInt(this._container.find('[name=\"requiredpoints\"]').val() || 1, 10);\n };\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_points';\n };\n\n /**\n * Callback to inject the template.\n *\n * @param {Node} container Node to inject in.\n * @return {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function(container) {\n var self = this,\n children = this._tree.getChildren(this._competency.id),\n context,\n config = {\n base: {points: 2},\n competencies: []\n };\n\n this._templateLoaded = false;\n\n // Only pre-load the configuration when the competency is using this rule.\n if (self._competency.ruletype == self.getType()) {\n try {\n config = JSON.parse(self._competency.ruleconfig);\n } catch (e) {\n // eslint-disable-line no-empty\n }\n }\n\n context = {\n requiredpoints: (config && config.base) ? config.base.points : 2,\n competency: self._competency,\n children: []\n };\n\n $.each(children, function(index, child) {\n var competency = {\n id: child.id,\n shortname: child.shortname,\n required: false,\n points: 0\n };\n\n if (config) {\n $.each(config.competencies, function(index, comp) {\n if (comp.id == competency.id) {\n competency.required = comp.required ? true : false;\n competency.points = comp.points;\n }\n });\n }\n\n context.children.push(competency);\n });\n\n return Templates.render('tool_lp/competency_rule_points', context).then(function(html) {\n self._container = container;\n container.html(html);\n container.find('input').change(function() {\n self._triggerChange();\n });\n\n // We're done, let's trigger a change.\n self._templateLoaded = true;\n self._triggerChange();\n return;\n });\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n if (!this._templateLoaded) {\n return false;\n }\n\n var required = this._getRequiredPoints(),\n max = 0,\n valid = true;\n\n $.each(this._getCompetenciesConfig(), function(index, competency) {\n if (competency.points < 0) {\n valid = false;\n }\n max += competency.points;\n });\n\n valid = valid && max >= required;\n return valid;\n };\n\n return Rule;\n});\n"],"names":["define","$","Str","Templates","RuleBase","Rule","apply","this","arguments","prototype","Object","create","_container","_templateLoaded","getConfig","JSON","stringify","base","points","_getRequiredPoints","competencies","_getCompetenciesConfig","find","each","node","id","data","parseInt","val","required","prop","push","getType","injectTemplate","container","context","self","children","_tree","getChildren","_competency","config","ruletype","parse","ruleconfig","e","requiredpoints","competency","index","child","shortname","comp","render","then","html","change","_triggerChange","isValid","max","valid"],"mappings":";;;;;;;AAuBAA,wCAAO,CAAC,SACA,WACA,iBACA,4BAEA,SAASC,EAAGC,IAAKC,UAAWC,cAK5BC,KAAO,WACPD,SAASE,MAAMC,KAAMC,mBAEzBH,KAAKI,UAAYC,OAAOC,OAAOP,SAASK,YAGzBG,WAAa,KAE5BP,KAAKI,UAAUI,iBAAkB,EAQjCR,KAAKI,UAAUK,UAAY,kBAChBC,KAAKC,UAAU,CAClBC,KAAM,CACFC,OAAQX,KAAKY,sBAEjBC,aAAcb,KAAKc,4BAW3BhB,KAAKI,UAAUY,uBAAyB,eAChCD,aAAe,eAEdR,WAAWU,KAAK,qBAAqBC,MAAK,eACvCC,KAAOvB,EAAEM,MACTkB,GAAKD,KAAKE,KAAK,cACfR,OAASS,SAASH,KAAKF,KAAK,mBAAmBM,MAAO,IACtDC,SAAWL,KAAKF,KAAK,qBAAqBQ,KAAK,WAEnDV,aAAaW,KAAK,CACdN,GAAIA,GACJP,OAAQA,OACRW,SAAUA,SAAW,EAAI,OAI1BT,cAUXf,KAAKI,UAAUU,mBAAqB,kBACzBQ,SAASpB,KAAKK,WAAWU,KAAK,2BAA2BM,OAAS,EAAG,KAShFvB,KAAKI,UAAUuB,QAAU,iBACd,2CAUX3B,KAAKI,UAAUwB,eAAiB,SAASC,eAGjCC,QAFAC,KAAO7B,KACP8B,SAAW9B,KAAK+B,MAAMC,YAAYhC,KAAKiC,YAAYf,IAEnDgB,OAAS,CACLxB,KAAM,CAACC,OAAQ,GACfE,aAAc,YAGjBP,iBAAkB,EAGnBuB,KAAKI,YAAYE,UAAYN,KAAKJ,cAE9BS,OAAS1B,KAAK4B,MAAMP,KAAKI,YAAYI,YACvC,MAAOC,WAKbV,QAAU,CACNW,eAAiBL,QAAUA,OAAOxB,KAAQwB,OAAOxB,KAAKC,OAAS,EAC/D6B,WAAYX,KAAKI,YACjBH,SAAU,IAGdpC,EAAEsB,KAAKc,UAAU,SAASW,MAAOC,WACzBF,WAAa,CACbtB,GAAIwB,MAAMxB,GACVyB,UAAWD,MAAMC,UACjBrB,UAAU,EACVX,OAAQ,GAGRuB,QACAxC,EAAEsB,KAAKkB,OAAOrB,cAAc,SAAS4B,MAAOG,MACpCA,KAAK1B,IAAMsB,WAAWtB,KACtBsB,WAAWlB,WAAWsB,KAAKtB,SAC3BkB,WAAW7B,OAASiC,KAAKjC,WAKrCiB,QAAQE,SAASN,KAAKgB,eAGnB5C,UAAUiD,OAAO,iCAAkCjB,SAASkB,MAAK,SAASC,MAC7ElB,KAAKxB,WAAasB,UAClBA,UAAUoB,KAAKA,MACfpB,UAAUZ,KAAK,SAASiC,QAAO,WAC3BnB,KAAKoB,oBAITpB,KAAKvB,iBAAkB,EACvBuB,KAAKoB,qBAWbnD,KAAKI,UAAUgD,QAAU,eAChBlD,KAAKM,uBACC,MAGPgB,SAAWtB,KAAKY,qBAChBuC,IAAM,EACNC,OAAQ,SAEZ1D,EAAEsB,KAAKhB,KAAKc,0BAA0B,SAAS2B,MAAOD,YAC9CA,WAAW7B,OAAS,IACpByC,OAAQ,GAEZD,KAAOX,WAAW7B,UAGtByC,MAAQA,OAASD,KAAO7B,UAIrBxB"} \ No newline at end of file +{"version":3,"file":"competency_rule_points.min.js","sources":["../src/competency_rule_points.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 * Competency rule points module.\n *\n * @module tool_lp/competency_rule_points\n * @copyright 2015 Frédéric Massart - FMCorz.net\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery',\n 'core/str',\n 'core/templates',\n 'tool_lp/competency_rule',\n ],\n function($, Str, Templates, RuleBase) {\n\n /**\n * Competency rule points class.\n */\n var Rule = function() {\n RuleBase.apply(this, arguments);\n };\n Rule.prototype = Object.create(RuleBase.prototype);\n\n /** @property {Node} Reference to the container in which the template was included. */\n Rule.prototype._container = null;\n /** @property {Boolean} Whether or not the template was included. */\n Rule.prototype._templateLoaded = false;\n\n /**\n * The config established by this rule.\n *\n * @return {String}\n * @method getConfig\n */\n Rule.prototype.getConfig = function() {\n return JSON.stringify({\n base: {\n points: this._getRequiredPoints(),\n },\n competencies: this._getCompetenciesConfig()\n });\n };\n\n /**\n * Gathers the input provided by the user for competencies.\n *\n * @return {Array} Containing id, points and required.\n * @method _getCompetenciesConfig\n * @protected\n */\n Rule.prototype._getCompetenciesConfig = function() {\n var competencies = [];\n\n this._container.find('[data-competency]').each(function() {\n var node = $(this),\n id = node.data('competency'),\n points = parseInt(node.find('[name=\"points\"]').val(), 10),\n required = node.find('[name=\"required\"]').prop('checked');\n\n competencies.push({\n id: id,\n points: points,\n required: required ? 1 : 0\n });\n });\n\n return competencies;\n };\n\n /**\n * Fetches the required points set by the user.\n *\n * @return {Number}\n * @method _getRequiredPoints\n * @protected\n */\n Rule.prototype._getRequiredPoints = function() {\n return parseInt(this._container.find('[name=\"requiredpoints\"]').val() || 1, 10);\n };\n\n /**\n * Return the type of the module.\n *\n * @return {String}\n * @method getType\n */\n Rule.prototype.getType = function() {\n return 'core_competency\\\\competency_rule_points';\n };\n\n /**\n * Callback to inject the template.\n *\n * @param {Node} container Node to inject in.\n * @return {Promise} Resolved when done.\n * @method injectTemplate\n */\n Rule.prototype.injectTemplate = function(container) {\n var self = this,\n children = this._tree.getChildren(this._competency.id),\n context,\n config = {\n base: {points: 2},\n competencies: []\n };\n\n this._templateLoaded = false;\n\n // Only pre-load the configuration when the competency is using this rule.\n if (self._competency.ruletype == self.getType()) {\n try {\n config = JSON.parse(self._competency.ruleconfig);\n } catch (e) {\n // eslint-disable-line no-empty\n }\n }\n\n context = {\n requiredpoints: (config && config.base) ? config.base.points : 2,\n competency: self._competency,\n children: []\n };\n\n $.each(children, function(index, child) {\n var competency = {\n id: child.id,\n shortname: child.shortname,\n required: false,\n points: 0\n };\n\n if (config) {\n $.each(config.competencies, function(index, comp) {\n if (comp.id == competency.id) {\n competency.required = comp.required ? true : false;\n competency.points = comp.points;\n }\n });\n }\n\n context.children.push(competency);\n });\n\n return Templates.render('tool_lp/competency_rule_points', context).then(function(html) {\n self._container = container;\n container.html(html);\n container.find('input').change(function() {\n self._triggerChange();\n });\n\n // We're done, let's trigger a change.\n self._templateLoaded = true;\n self._triggerChange();\n return;\n });\n };\n\n /**\n * Whether or not the current config is valid.\n *\n * @return {Boolean}\n * @method isValid\n */\n Rule.prototype.isValid = function() {\n if (!this._templateLoaded) {\n return false;\n }\n\n var required = this._getRequiredPoints(),\n max = 0,\n valid = true;\n\n $.each(this._getCompetenciesConfig(), function(index, competency) {\n if (competency.points < 0) {\n valid = false;\n }\n max += competency.points;\n });\n\n valid = valid && max >= required;\n return valid;\n };\n\n return Rule;\n});\n"],"names":["define","$","Str","Templates","RuleBase","Rule","apply","this","arguments","prototype","Object","create","_container","_templateLoaded","getConfig","JSON","stringify","base","points","_getRequiredPoints","competencies","_getCompetenciesConfig","find","each","node","id","data","parseInt","val","required","prop","push","getType","injectTemplate","container","context","self","children","_tree","getChildren","_competency","config","ruletype","parse","ruleconfig","e","requiredpoints","competency","index","child","shortname","comp","render","then","html","change","_triggerChange","isValid","max","valid"],"mappings":";;;;;;;AAuBAA,wCAAO,CAAC,SACA,WACA,iBACA,4BAEA,SAASC,EAAGC,IAAKC,UAAWC,cAK5BC,KAAO,WACPD,SAASE,MAAMC,KAAMC,mBAEzBH,KAAKI,UAAYC,OAAOC,OAAOP,SAASK,YAGzBG,WAAa,KAE5BP,KAAKI,UAAUI,iBAAkB,EAQjCR,KAAKI,UAAUK,UAAY,kBAChBC,KAAKC,UAAU,CAClBC,KAAM,CACFC,OAAQX,KAAKY,sBAEjBC,aAAcb,KAAKc,4BAW3BhB,KAAKI,UAAUY,uBAAyB,eAChCD,aAAe,eAEdR,WAAWU,KAAK,qBAAqBC,MAAK,eACvCC,KAAOvB,EAAEM,MACTkB,GAAKD,KAAKE,KAAK,cACfR,OAASS,SAASH,KAAKF,KAAK,mBAAmBM,MAAO,IACtDC,SAAWL,KAAKF,KAAK,qBAAqBQ,KAAK,WAEnDV,aAAaW,KAAK,CACdN,GAAIA,GACJP,OAAQA,OACRW,SAAUA,SAAW,EAAI,OAI1BT,cAUXf,KAAKI,UAAUU,mBAAqB,kBACzBQ,SAASpB,KAAKK,WAAWU,KAAK,2BAA2BM,OAAS,EAAG,KAShFvB,KAAKI,UAAUuB,QAAU,iBACd,2CAUX3B,KAAKI,UAAUwB,eAAiB,SAASC,eAGjCC,QAFAC,KAAO7B,KACP8B,SAAW9B,KAAK+B,MAAMC,YAAYhC,KAAKiC,YAAYf,IAEnDgB,OAAS,CACLxB,KAAM,CAACC,OAAQ,GACfE,aAAc,YAGjBP,iBAAkB,EAGnBuB,KAAKI,YAAYE,UAAYN,KAAKJ,cAE9BS,OAAS1B,KAAK4B,MAAMP,KAAKI,YAAYI,YACvC,MAAOC,WAKbV,QAAU,CACNW,eAAiBL,QAAUA,OAAOxB,KAAQwB,OAAOxB,KAAKC,OAAS,EAC/D6B,WAAYX,KAAKI,YACjBH,SAAU,IAGdpC,EAAEsB,KAAKc,UAAU,SAASW,MAAOC,WACzBF,WAAa,CACbtB,GAAIwB,MAAMxB,GACVyB,UAAWD,MAAMC,UACjBrB,UAAU,EACVX,OAAQ,GAGRuB,QACAxC,EAAEsB,KAAKkB,OAAOrB,cAAc,SAAS4B,MAAOG,MACpCA,KAAK1B,IAAMsB,WAAWtB,KACtBsB,WAAWlB,WAAWsB,KAAKtB,SAC3BkB,WAAW7B,OAASiC,KAAKjC,WAKrCiB,QAAQE,SAASN,KAAKgB,eAGnB5C,UAAUiD,OAAO,iCAAkCjB,SAASkB,MAAK,SAASC,MAC7ElB,KAAKxB,WAAasB,UAClBA,UAAUoB,KAAKA,MACfpB,UAAUZ,KAAK,SAASiC,QAAO,WAC3BnB,KAAKoB,oBAITpB,KAAKvB,iBAAkB,EACvBuB,KAAKoB,qBAWbnD,KAAKI,UAAUgD,QAAU,eAChBlD,KAAKM,uBACC,MAGPgB,SAAWtB,KAAKY,qBAChBuC,IAAM,EACNC,OAAQ,SAEZ1D,EAAEsB,KAAKhB,KAAKc,0BAA0B,SAAS2B,MAAOD,YAC9CA,WAAW7B,OAAS,IACpByC,OAAQ,GAEZD,KAAOX,WAAW7B,UAGtByC,MAAQA,OAASD,KAAO7B,UAIrBxB"} \ No newline at end of file diff --git a/admin/tool/lp/amd/build/competencydialogue.min.js b/admin/tool/lp/amd/build/competencydialogue.min.js index c06ba3594da..240b33caf16 100644 --- a/admin/tool/lp/amd/build/competencydialogue.min.js +++ b/admin/tool/lp/amd/build/competencydialogue.min.js @@ -1,7 +1,7 @@ /** * Display Competency in dialogue box. * - * @module tool_lp/Competencydialogue + * @module tool_lp/competencydialogue * @copyright 2015 Issam Taboubi * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/build/competencydialogue.min.js.map b/admin/tool/lp/amd/build/competencydialogue.min.js.map index 3a66a43e0e3..463c8b11424 100644 --- a/admin/tool/lp/amd/build/competencydialogue.min.js.map +++ b/admin/tool/lp/amd/build/competencydialogue.min.js.map @@ -1 +1 @@ -{"version":3,"file":"competencydialogue.min.js","sources":["../src/competencydialogue.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 * Display Competency in dialogue box.\n *\n * @module tool_lp/Competencydialogue\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/dialogue'],\n function($, notification, ajax, templates, str, Dialogue) {\n\n /**\n * The main instance we'll be working with.\n *\n * @type {Competencydialogue}\n */\n var instance;\n\n /**\n * Constructor for CompetencyDialogue.\n */\n var Competencydialogue = function() {\n // Intentionally left empty.\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Number} competencyId The competency ID.\n * @method triggerCompetencyViewedEvent\n */\n Competencydialogue.prototype.triggerCompetencyViewedEvent = function(competencyId) {\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competencyId}\n }]);\n };\n\n /**\n * Display a dialogue box by competencyid.\n *\n * @param {Number} competencyid The competency ID.\n * @param {Object} options The options.\n * @method showDialogue\n */\n Competencydialogue.prototype.showDialogue = function(competencyid, options) {\n\n var datapromise = this.getCompetencyDataPromise(competencyid, options);\n var localthis = this;\n datapromise.done(function(data) {\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', data)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(competencyid);\n\n // Show the dialogue.\n new Dialogue(\n data.competency.shortname,\n html\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Display a dialogue box from data.\n *\n * @param {Object} dataSource data to be used to display dialogue box\n * @method showDialogueFromData\n */\n Competencydialogue.prototype.showDialogueFromData = function(dataSource) {\n\n var localthis = this;\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', dataSource)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(dataSource.id);\n\n // Show the dialogue.\n new Dialogue(\n dataSource.shortname,\n html,\n localthis.enhanceDialogue\n );\n }).fail(notification.exception);\n };\n\n /**\n * The action on the click event.\n *\n * @param {Event} e event click\n * @method clickEventHandler\n */\n Competencydialogue.prototype.clickEventHandler = function(e) {\n\n var compdialogue = e.data.compdialogue;\n var currentTarget = $(e.currentTarget);\n var competencyid = currentTarget.data('id');\n var includerelated = !(currentTarget.data('excluderelated'));\n var includecourses = currentTarget.data('includecourses');\n\n // Show the dialogue box.\n compdialogue.showDialogue(competencyid, {\n includerelated: includerelated,\n includecourses: includecourses\n });\n e.preventDefault();\n };\n\n /**\n * Get a promise on data competency.\n *\n * @param {Number} competencyid\n * @param {Object} options\n * @return {Promise} return promise on data request\n * @method getCompetencyDataPromise\n */\n Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid, options) {\n\n var requests = ajax.call([\n {methodname: 'tool_lp_data_for_competency_summary',\n args: {competencyid: competencyid,\n includerelated: options.includerelated || false,\n includecourses: options.includecourses || false\n }\n }\n ]);\n\n return requests[0].then(function(context) {\n return context;\n }).fail(notification.exception);\n };\n\n return /** @alias module:tool_lp/competencydialogue */ {\n\n /**\n * Initialise the competency dialogue module.\n *\n * Only the first call matters.\n */\n init: function() {\n if (typeof instance !== 'undefined') {\n return;\n }\n\n // Instantiate the one instance and delegate event on the body.\n instance = new Competencydialogue();\n $('body').delegate('[data-action=\"competency-dialogue\"]', 'click', {compdialogue: instance},\n instance.clickEventHandler.bind(instance));\n }\n };\n});\n"],"names":["define","$","notification","ajax","templates","str","Dialogue","instance","Competencydialogue","prototype","triggerCompetencyViewedEvent","competencyId","call","methodname","args","id","showDialogue","competencyid","options","datapromise","this","getCompetencyDataPromise","localthis","done","data","render","html","competency","shortname","fail","exception","showDialogueFromData","dataSource","enhanceDialogue","clickEventHandler","e","compdialogue","currentTarget","includerelated","includecourses","preventDefault","then","context","init","delegate","bind"],"mappings":";;;;;;;AAsBAA,oCAAO,CAAC,SACA,oBACA,YACA,iBACA,WACA,qBACD,SAASC,EAAGC,aAAcC,KAAMC,UAAWC,IAAKC,cAO/CC,SAKAC,mBAAqB,oBAUzBA,mBAAmBC,UAAUC,6BAA+B,SAASC,cACjER,KAAKS,KAAK,CAAC,CACHC,WAAY,oCACZC,KAAM,CAACC,GAAIJ,kBAWvBH,mBAAmBC,UAAUO,aAAe,SAASC,aAAcC,aAE3DC,YAAcC,KAAKC,yBAAyBJ,aAAcC,SAC1DI,UAAYF,KAChBD,YAAYI,MAAK,SAASC,MAEtBpB,UAAUqB,OAAO,6BAA8BD,MAC1CD,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BO,kBAGnCX,SACAkB,KAAKG,WAAWC,UAChBF,SAELG,KAAK3B,aAAa4B,cAC1BD,KAAK3B,aAAa4B,YASzBtB,mBAAmBC,UAAUsB,qBAAuB,SAASC,gBAErDV,UAAYF,KAEhBhB,UAAUqB,OAAO,6BAA8BO,YAC1CT,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BsB,WAAWjB,QAG9CT,SACA0B,WAAWJ,UACXF,KACAJ,UAAUW,oBAEfJ,KAAK3B,aAAa4B,YAS7BtB,mBAAmBC,UAAUyB,kBAAoB,SAASC,OAElDC,aAAeD,EAAEX,KAAKY,aACtBC,cAAgBpC,EAAEkC,EAAEE,eACpBpB,aAAeoB,cAAcb,KAAK,MAClCc,gBAAmBD,cAAcb,KAAK,kBACtCe,eAAiBF,cAAcb,KAAK,kBAGxCY,aAAapB,aAAaC,aAAc,CACpCqB,eAAgBA,eAChBC,eAAgBA,iBAEpBJ,EAAEK,kBAWNhC,mBAAmBC,UAAUY,yBAA2B,SAASJ,aAAcC,gBAE5Df,KAAKS,KAAK,CACrB,CAACC,WAAY,sCACXC,KAAM,CAACG,aAAcA,aACbqB,eAAgBpB,QAAQoB,iBAAkB,EAC1CC,eAAgBrB,QAAQqB,iBAAkB,MAKxC,GAAGE,MAAK,SAASC,gBACvBA,WACPb,KAAK3B,aAAa4B,YAG8B,CAOnDa,KAAM,gBACsB,IAAbpC,WAKXA,SAAW,IAAIC,mBACfP,EAAE,QAAQ2C,SAAS,sCAAuC,QAAS,CAACR,aAAc7B,UAC9EA,SAAS2B,kBAAkBW,KAAKtC"} \ No newline at end of file +{"version":3,"file":"competencydialogue.min.js","sources":["../src/competencydialogue.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 * Display Competency in dialogue box.\n *\n * @module tool_lp/competencydialogue\n * @copyright 2015 Issam Taboubi \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'core/ajax',\n 'core/templates',\n 'core/str',\n 'tool_lp/dialogue'],\n function($, notification, ajax, templates, str, Dialogue) {\n\n /**\n * The main instance we'll be working with.\n *\n * @type {Competencydialogue}\n */\n var instance;\n\n /**\n * Constructor for CompetencyDialogue.\n */\n var Competencydialogue = function() {\n // Intentionally left empty.\n };\n\n /**\n * Log the competency viewed event.\n *\n * @param {Number} competencyId The competency ID.\n * @method triggerCompetencyViewedEvent\n */\n Competencydialogue.prototype.triggerCompetencyViewedEvent = function(competencyId) {\n ajax.call([{\n methodname: 'core_competency_competency_viewed',\n args: {id: competencyId}\n }]);\n };\n\n /**\n * Display a dialogue box by competencyid.\n *\n * @param {Number} competencyid The competency ID.\n * @param {Object} options The options.\n * @method showDialogue\n */\n Competencydialogue.prototype.showDialogue = function(competencyid, options) {\n\n var datapromise = this.getCompetencyDataPromise(competencyid, options);\n var localthis = this;\n datapromise.done(function(data) {\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', data)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(competencyid);\n\n // Show the dialogue.\n new Dialogue(\n data.competency.shortname,\n html\n );\n }).fail(notification.exception);\n }).fail(notification.exception);\n };\n\n /**\n * Display a dialogue box from data.\n *\n * @param {Object} dataSource data to be used to display dialogue box\n * @method showDialogueFromData\n */\n Competencydialogue.prototype.showDialogueFromData = function(dataSource) {\n\n var localthis = this;\n // Inner Html in the dialogue content.\n templates.render('tool_lp/competency_summary', dataSource)\n .done(function(html) {\n // Log competency viewed event.\n localthis.triggerCompetencyViewedEvent(dataSource.id);\n\n // Show the dialogue.\n new Dialogue(\n dataSource.shortname,\n html,\n localthis.enhanceDialogue\n );\n }).fail(notification.exception);\n };\n\n /**\n * The action on the click event.\n *\n * @param {Event} e event click\n * @method clickEventHandler\n */\n Competencydialogue.prototype.clickEventHandler = function(e) {\n\n var compdialogue = e.data.compdialogue;\n var currentTarget = $(e.currentTarget);\n var competencyid = currentTarget.data('id');\n var includerelated = !(currentTarget.data('excluderelated'));\n var includecourses = currentTarget.data('includecourses');\n\n // Show the dialogue box.\n compdialogue.showDialogue(competencyid, {\n includerelated: includerelated,\n includecourses: includecourses\n });\n e.preventDefault();\n };\n\n /**\n * Get a promise on data competency.\n *\n * @param {Number} competencyid\n * @param {Object} options\n * @return {Promise} return promise on data request\n * @method getCompetencyDataPromise\n */\n Competencydialogue.prototype.getCompetencyDataPromise = function(competencyid, options) {\n\n var requests = ajax.call([\n {methodname: 'tool_lp_data_for_competency_summary',\n args: {competencyid: competencyid,\n includerelated: options.includerelated || false,\n includecourses: options.includecourses || false\n }\n }\n ]);\n\n return requests[0].then(function(context) {\n return context;\n }).fail(notification.exception);\n };\n\n return /** @alias module:tool_lp/competencydialogue */ {\n\n /**\n * Initialise the competency dialogue module.\n *\n * Only the first call matters.\n */\n init: function() {\n if (typeof instance !== 'undefined') {\n return;\n }\n\n // Instantiate the one instance and delegate event on the body.\n instance = new Competencydialogue();\n $('body').delegate('[data-action=\"competency-dialogue\"]', 'click', {compdialogue: instance},\n instance.clickEventHandler.bind(instance));\n }\n };\n});\n"],"names":["define","$","notification","ajax","templates","str","Dialogue","instance","Competencydialogue","prototype","triggerCompetencyViewedEvent","competencyId","call","methodname","args","id","showDialogue","competencyid","options","datapromise","this","getCompetencyDataPromise","localthis","done","data","render","html","competency","shortname","fail","exception","showDialogueFromData","dataSource","enhanceDialogue","clickEventHandler","e","compdialogue","currentTarget","includerelated","includecourses","preventDefault","then","context","init","delegate","bind"],"mappings":";;;;;;;AAsBAA,oCAAO,CAAC,SACA,oBACA,YACA,iBACA,WACA,qBACD,SAASC,EAAGC,aAAcC,KAAMC,UAAWC,IAAKC,cAO/CC,SAKAC,mBAAqB,oBAUzBA,mBAAmBC,UAAUC,6BAA+B,SAASC,cACjER,KAAKS,KAAK,CAAC,CACHC,WAAY,oCACZC,KAAM,CAACC,GAAIJ,kBAWvBH,mBAAmBC,UAAUO,aAAe,SAASC,aAAcC,aAE3DC,YAAcC,KAAKC,yBAAyBJ,aAAcC,SAC1DI,UAAYF,KAChBD,YAAYI,MAAK,SAASC,MAEtBpB,UAAUqB,OAAO,6BAA8BD,MAC1CD,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BO,kBAGnCX,SACAkB,KAAKG,WAAWC,UAChBF,SAELG,KAAK3B,aAAa4B,cAC1BD,KAAK3B,aAAa4B,YASzBtB,mBAAmBC,UAAUsB,qBAAuB,SAASC,gBAErDV,UAAYF,KAEhBhB,UAAUqB,OAAO,6BAA8BO,YAC1CT,MAAK,SAASG,MAEXJ,UAAUZ,6BAA6BsB,WAAWjB,QAG9CT,SACA0B,WAAWJ,UACXF,KACAJ,UAAUW,oBAEfJ,KAAK3B,aAAa4B,YAS7BtB,mBAAmBC,UAAUyB,kBAAoB,SAASC,OAElDC,aAAeD,EAAEX,KAAKY,aACtBC,cAAgBpC,EAAEkC,EAAEE,eACpBpB,aAAeoB,cAAcb,KAAK,MAClCc,gBAAmBD,cAAcb,KAAK,kBACtCe,eAAiBF,cAAcb,KAAK,kBAGxCY,aAAapB,aAAaC,aAAc,CACpCqB,eAAgBA,eAChBC,eAAgBA,iBAEpBJ,EAAEK,kBAWNhC,mBAAmBC,UAAUY,yBAA2B,SAASJ,aAAcC,gBAE5Df,KAAKS,KAAK,CACrB,CAACC,WAAY,sCACXC,KAAM,CAACG,aAAcA,aACbqB,eAAgBpB,QAAQoB,iBAAkB,EAC1CC,eAAgBrB,QAAQqB,iBAAkB,MAKxC,GAAGE,MAAK,SAASC,gBACvBA,WACPb,KAAK3B,aAAa4B,YAG8B,CAOnDa,KAAM,gBACsB,IAAbpC,WAKXA,SAAW,IAAIC,mBACfP,EAAE,QAAQ2C,SAAS,sCAAuC,QAAS,CAACR,aAAc7B,UAC9EA,SAAS2B,kBAAkBW,KAAKtC"} \ No newline at end of file diff --git a/admin/tool/lp/amd/build/competencytree.min.js b/admin/tool/lp/amd/build/competencytree.min.js index 6f3ab53f3da..35650118892 100644 --- a/admin/tool/lp/amd/build/competencytree.min.js +++ b/admin/tool/lp/amd/build/competencytree.min.js @@ -1,7 +1,7 @@ /** * Handle selection changes on the competency tree. * - * @module tool_lp/competencyselect + * @module tool_lp/competencytree * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/build/competencytree.min.js.map b/admin/tool/lp/amd/build/competencytree.min.js.map index 30b8cbf7e8e..fea1446eb29 100644 --- a/admin/tool/lp/amd/build/competencytree.min.js.map +++ b/admin/tool/lp/amd/build/competencytree.min.js.map @@ -1 +1 @@ -{"version":3,"file":"competencytree.min.js","sources":["../src/competencytree.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 * Handle selection changes on the competency tree.\n *\n * @module tool_lp/competencyselect\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'core/notification', 'core/templates', 'tool_lp/tree', 'tool_lp/competency_outcomes', 'jquery'],\n function(ajax, notification, templates, Ariatree, CompOutcomes, $) {\n\n // Private variables and functions.\n /** @var {Object[]} competencies - Cached list of competencies */\n var competencies = {};\n\n /** @var {Number} competencyFrameworkId - The current framework id */\n var competencyFrameworkId = 0;\n\n /** @var {String} competencyFrameworkShortName - The current framework short name */\n var competencyFrameworkShortName = '';\n\n /** @var {String} treeSelector - The selector for the root of the tree. */\n var treeSelector = '';\n\n /** @var {String} currentNodeId - The data-id of the current node in the tree. */\n var currentNodeId = '';\n\n /** @var {Boolean} competencyFramworkCanManage - Can manage the competencies framework */\n var competencyFramworkCanManage = false;\n\n /**\n * Build a tree from the flat list of competencies.\n * @param {Object} parent The parent competency.\n * @param {Array} all The list of all competencies.\n */\n var addChildren = function(parent, all) {\n var i = 0;\n var current = false;\n parent.haschildren = false;\n parent.children = [];\n for (i = 0; i < all.length; i++) {\n current = all[i];\n if (current.parentid == parent.id) {\n parent.haschildren = true;\n parent.children.push(current);\n addChildren(current, all);\n }\n }\n };\n\n /**\n * Load the list of competencies via ajax. Competencies are filtered by the searchtext.\n * @param {String} searchtext The text to filter on.\n * @return {promise}\n */\n var loadCompetencies = function(searchtext) {\n var deferred = $.Deferred();\n\n templates.render('tool_lp/loading', {}).done(function(loadinghtml, loadingjs) {\n templates.replaceNodeContents($(treeSelector), loadinghtml, loadingjs);\n\n var promises = ajax.call([{\n methodname: 'core_competency_search_competencies',\n args: {\n searchtext: searchtext,\n competencyframeworkid: competencyFrameworkId\n }\n }]);\n promises[0].done(function(result) {\n competencies = {};\n var i = 0;\n for (i = 0; i < result.length; i++) {\n competencies[result[i].id] = result[i];\n }\n\n var children = [];\n var competency = false;\n for (i = 0; i < result.length; i++) {\n competency = result[i];\n if (parseInt(competency.parentid, 10) === 0) {\n children.push(competency);\n addChildren(competency, result);\n }\n }\n var context = {\n shortname: competencyFrameworkShortName,\n canmanage: competencyFramworkCanManage,\n competencies: children\n };\n templates.render('tool_lp/competencies_tree_root', context).done(function(html, js) {\n templates.replaceNodeContents($(treeSelector), $(html).html(), js);\n var tree = new Ariatree(treeSelector, false);\n\n if (currentNodeId) {\n var node = $(treeSelector).find('[data-id=' + currentNodeId + ']');\n if (node.length) {\n tree.selectItem(node);\n tree.updateFocus(node);\n }\n }\n deferred.resolve(competencies);\n }).fail(deferred.reject);\n }).fail(deferred.reject);\n });\n\n return deferred.promise();\n };\n\n /**\n * Whenever the current item in the tree is changed - remember the \"id\".\n * @param {Event} evt\n * @param {Object} params The parameters for the event (This is the selected node).\n */\n var rememberCurrent = function(evt, params) {\n var node = params.selected;\n currentNodeId = node.attr('data-id');\n };\n\n return /** @alias module:tool_lp/competencytree */ {\n // Public variables and functions.\n /**\n * Initialise the tree.\n *\n * @param {Number} id The competency framework id.\n * @param {String} shortname The framework shortname\n * @param {String} search The current search string\n * @param {String} selector The selector for the tree div\n * @param {Boolean} canmanage Can manage the competencies\n * @param {Number} competencyid The id of the competency to show first\n */\n init: function(id, shortname, search, selector, canmanage, competencyid) {\n competencyFrameworkId = id;\n competencyFrameworkShortName = shortname;\n competencyFramworkCanManage = canmanage;\n treeSelector = selector;\n loadCompetencies(search).fail(notification.exception);\n if (competencyid > 0) {\n currentNodeId = competencyid;\n }\n\n this.on('selectionchanged', rememberCurrent);\n },\n\n /**\n * Add an event handler for custom events emitted by the tree.\n *\n * @param {String} eventname The name of the event - only \"selectionchanged\" for now\n * @param {Function} handler The handler for the event.\n */\n on: function(eventname, handler) {\n // We can't use the tree on function directly\n // because the tree gets rebuilt whenever the search string changes,\n // instead we attach the listner to the root node of the tree which never\n // gets destroyed (same as \"on()\" code in the tree.js).\n $(treeSelector).on(eventname, handler);\n },\n\n /**\n * Get the children of a competency.\n *\n * @param {Number} id The competency ID.\n * @return {Array}\n * @method getChildren\n */\n getChildren: function(id) {\n var children = [];\n $.each(competencies, function(index, competency) {\n if (competency.parentid == id) {\n children.push(competency);\n }\n });\n return children;\n },\n\n /**\n * Get the competency framework id this model was initiliased with.\n *\n * @return {Number}\n */\n getCompetencyFrameworkId: function() {\n return competencyFrameworkId;\n },\n\n /**\n * Get a competency by id\n *\n * @param {Number} id The competency id\n * @return {Object}\n */\n getCompetency: function(id) {\n return competencies[id];\n },\n\n /**\n * Get the competency level.\n *\n * @param {Number} id The competency ID.\n * @return {Number}\n */\n getCompetencyLevel: function(id) {\n var competency = this.getCompetency(id),\n level = competency.path.replace(/^\\/|\\/$/g, '').split('/').length;\n return level;\n },\n\n /**\n * Whether a competency has children.\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n * @method hasChildren\n */\n hasChildren: function(id) {\n return this.getChildren(id).length > 0;\n },\n\n /**\n * Does the competency have a rule?\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n */\n hasRule: function(id) {\n var comp = this.getCompetency(id);\n if (comp) {\n return comp.ruleoutcome != CompOutcomes.OUTCOME_NONE\n && comp.ruletype;\n }\n return false;\n },\n\n /**\n * Reload all the page competencies framework competencies.\n * @method reloadCompetencies\n * @return {Promise}\n */\n reloadCompetencies: function() {\n return loadCompetencies('').fail(notification.exception);\n },\n\n /**\n * Get all competencies for this framework.\n *\n * @return {Object[]}\n */\n listCompetencies: function() {\n return competencies;\n },\n\n };\n });\n"],"names":["define","ajax","notification","templates","Ariatree","CompOutcomes","$","competencies","competencyFrameworkId","competencyFrameworkShortName","treeSelector","currentNodeId","competencyFramworkCanManage","addChildren","parent","all","i","current","haschildren","children","length","parentid","id","push","loadCompetencies","searchtext","deferred","Deferred","render","done","loadinghtml","loadingjs","replaceNodeContents","call","methodname","args","competencyframeworkid","result","competency","parseInt","context","shortname","canmanage","html","js","tree","node","find","selectItem","updateFocus","resolve","fail","reject","promise","rememberCurrent","evt","params","selected","attr","init","search","selector","competencyid","exception","on","eventname","handler","getChildren","each","index","getCompetencyFrameworkId","getCompetency","getCompetencyLevel","this","path","replace","split","hasChildren","hasRule","comp","ruleoutcome","OUTCOME_NONE","ruletype","reloadCompetencies","listCompetencies"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"competencytree.min.js","sources":["../src/competencytree.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 * Handle selection changes on the competency tree.\n *\n * @module tool_lp/competencytree\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'core/notification', 'core/templates', 'tool_lp/tree', 'tool_lp/competency_outcomes', 'jquery'],\n function(ajax, notification, templates, Ariatree, CompOutcomes, $) {\n\n // Private variables and functions.\n /** @var {Object[]} competencies - Cached list of competencies */\n var competencies = {};\n\n /** @var {Number} competencyFrameworkId - The current framework id */\n var competencyFrameworkId = 0;\n\n /** @var {String} competencyFrameworkShortName - The current framework short name */\n var competencyFrameworkShortName = '';\n\n /** @var {String} treeSelector - The selector for the root of the tree. */\n var treeSelector = '';\n\n /** @var {String} currentNodeId - The data-id of the current node in the tree. */\n var currentNodeId = '';\n\n /** @var {Boolean} competencyFramworkCanManage - Can manage the competencies framework */\n var competencyFramworkCanManage = false;\n\n /**\n * Build a tree from the flat list of competencies.\n * @param {Object} parent The parent competency.\n * @param {Array} all The list of all competencies.\n */\n var addChildren = function(parent, all) {\n var i = 0;\n var current = false;\n parent.haschildren = false;\n parent.children = [];\n for (i = 0; i < all.length; i++) {\n current = all[i];\n if (current.parentid == parent.id) {\n parent.haschildren = true;\n parent.children.push(current);\n addChildren(current, all);\n }\n }\n };\n\n /**\n * Load the list of competencies via ajax. Competencies are filtered by the searchtext.\n * @param {String} searchtext The text to filter on.\n * @return {promise}\n */\n var loadCompetencies = function(searchtext) {\n var deferred = $.Deferred();\n\n templates.render('tool_lp/loading', {}).done(function(loadinghtml, loadingjs) {\n templates.replaceNodeContents($(treeSelector), loadinghtml, loadingjs);\n\n var promises = ajax.call([{\n methodname: 'core_competency_search_competencies',\n args: {\n searchtext: searchtext,\n competencyframeworkid: competencyFrameworkId\n }\n }]);\n promises[0].done(function(result) {\n competencies = {};\n var i = 0;\n for (i = 0; i < result.length; i++) {\n competencies[result[i].id] = result[i];\n }\n\n var children = [];\n var competency = false;\n for (i = 0; i < result.length; i++) {\n competency = result[i];\n if (parseInt(competency.parentid, 10) === 0) {\n children.push(competency);\n addChildren(competency, result);\n }\n }\n var context = {\n shortname: competencyFrameworkShortName,\n canmanage: competencyFramworkCanManage,\n competencies: children\n };\n templates.render('tool_lp/competencies_tree_root', context).done(function(html, js) {\n templates.replaceNodeContents($(treeSelector), $(html).html(), js);\n var tree = new Ariatree(treeSelector, false);\n\n if (currentNodeId) {\n var node = $(treeSelector).find('[data-id=' + currentNodeId + ']');\n if (node.length) {\n tree.selectItem(node);\n tree.updateFocus(node);\n }\n }\n deferred.resolve(competencies);\n }).fail(deferred.reject);\n }).fail(deferred.reject);\n });\n\n return deferred.promise();\n };\n\n /**\n * Whenever the current item in the tree is changed - remember the \"id\".\n * @param {Event} evt\n * @param {Object} params The parameters for the event (This is the selected node).\n */\n var rememberCurrent = function(evt, params) {\n var node = params.selected;\n currentNodeId = node.attr('data-id');\n };\n\n return /** @alias module:tool_lp/competencytree */ {\n // Public variables and functions.\n /**\n * Initialise the tree.\n *\n * @param {Number} id The competency framework id.\n * @param {String} shortname The framework shortname\n * @param {String} search The current search string\n * @param {String} selector The selector for the tree div\n * @param {Boolean} canmanage Can manage the competencies\n * @param {Number} competencyid The id of the competency to show first\n */\n init: function(id, shortname, search, selector, canmanage, competencyid) {\n competencyFrameworkId = id;\n competencyFrameworkShortName = shortname;\n competencyFramworkCanManage = canmanage;\n treeSelector = selector;\n loadCompetencies(search).fail(notification.exception);\n if (competencyid > 0) {\n currentNodeId = competencyid;\n }\n\n this.on('selectionchanged', rememberCurrent);\n },\n\n /**\n * Add an event handler for custom events emitted by the tree.\n *\n * @param {String} eventname The name of the event - only \"selectionchanged\" for now\n * @param {Function} handler The handler for the event.\n */\n on: function(eventname, handler) {\n // We can't use the tree on function directly\n // because the tree gets rebuilt whenever the search string changes,\n // instead we attach the listner to the root node of the tree which never\n // gets destroyed (same as \"on()\" code in the tree.js).\n $(treeSelector).on(eventname, handler);\n },\n\n /**\n * Get the children of a competency.\n *\n * @param {Number} id The competency ID.\n * @return {Array}\n * @method getChildren\n */\n getChildren: function(id) {\n var children = [];\n $.each(competencies, function(index, competency) {\n if (competency.parentid == id) {\n children.push(competency);\n }\n });\n return children;\n },\n\n /**\n * Get the competency framework id this model was initiliased with.\n *\n * @return {Number}\n */\n getCompetencyFrameworkId: function() {\n return competencyFrameworkId;\n },\n\n /**\n * Get a competency by id\n *\n * @param {Number} id The competency id\n * @return {Object}\n */\n getCompetency: function(id) {\n return competencies[id];\n },\n\n /**\n * Get the competency level.\n *\n * @param {Number} id The competency ID.\n * @return {Number}\n */\n getCompetencyLevel: function(id) {\n var competency = this.getCompetency(id),\n level = competency.path.replace(/^\\/|\\/$/g, '').split('/').length;\n return level;\n },\n\n /**\n * Whether a competency has children.\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n * @method hasChildren\n */\n hasChildren: function(id) {\n return this.getChildren(id).length > 0;\n },\n\n /**\n * Does the competency have a rule?\n *\n * @param {Number} id The competency ID.\n * @return {Boolean}\n */\n hasRule: function(id) {\n var comp = this.getCompetency(id);\n if (comp) {\n return comp.ruleoutcome != CompOutcomes.OUTCOME_NONE\n && comp.ruletype;\n }\n return false;\n },\n\n /**\n * Reload all the page competencies framework competencies.\n * @method reloadCompetencies\n * @return {Promise}\n */\n reloadCompetencies: function() {\n return loadCompetencies('').fail(notification.exception);\n },\n\n /**\n * Get all competencies for this framework.\n *\n * @return {Object[]}\n */\n listCompetencies: function() {\n return competencies;\n },\n\n };\n });\n"],"names":["define","ajax","notification","templates","Ariatree","CompOutcomes","$","competencies","competencyFrameworkId","competencyFrameworkShortName","treeSelector","currentNodeId","competencyFramworkCanManage","addChildren","parent","all","i","current","haschildren","children","length","parentid","id","push","loadCompetencies","searchtext","deferred","Deferred","render","done","loadinghtml","loadingjs","replaceNodeContents","call","methodname","args","competencyframeworkid","result","competency","parseInt","context","shortname","canmanage","html","js","tree","node","find","selectItem","updateFocus","resolve","fail","reject","promise","rememberCurrent","evt","params","selected","attr","init","search","selector","competencyid","exception","on","eventname","handler","getChildren","each","index","getCompetencyFrameworkId","getCompetency","getCompetencyLevel","this","path","replace","split","hasChildren","hasRule","comp","ruleoutcome","OUTCOME_NONE","ruletype","reloadCompetencies","listCompetencies"],"mappings":"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"} \ No newline at end of file diff --git a/admin/tool/lp/amd/build/course_competency_settings.min.js b/admin/tool/lp/amd/build/course_competency_settings.min.js index 71086022821..aa0f2e327d1 100644 --- a/admin/tool/lp/amd/build/course_competency_settings.min.js +++ b/admin/tool/lp/amd/build/course_competency_settings.min.js @@ -1,7 +1,7 @@ /** * Change the course competency settings in a popup. * - * @module tool_lp/configurecoursecompetencysettings + * @module tool_lp/course_competency_settings * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/build/course_competency_settings.min.js.map b/admin/tool/lp/amd/build/course_competency_settings.min.js.map index f473cf570da..b38316095fd 100644 --- a/admin/tool/lp/amd/build/course_competency_settings.min.js.map +++ b/admin/tool/lp/amd/build/course_competency_settings.min.js.map @@ -1 +1 @@ -{"version":3,"file":"course_competency_settings.min.js","sources":["../src/course_competency_settings.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 * Change the course competency settings in a popup.\n *\n * @module tool_lp/configurecoursecompetencysettings\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'tool_lp/dialogue',\n 'core/str',\n 'core/ajax',\n 'core/templates',\n 'core/pending'\n ],\n function($, notification, Dialogue, str, ajax, templates, Pending) {\n\n /**\n * Constructor\n *\n * @param {String} selector - selector for the links to open the dialogue.\n */\n var settingsMod = function(selector) {\n $(selector).on('click', this.configureSettings.bind(this));\n };\n\n /** @property {Dialogue} Reference to the dialogue that we opened. */\n settingsMod.prototype._dialogue = null;\n\n /**\n * Open the configure settings dialogue.\n *\n * @param {Event} e\n * @method configureSettings\n */\n settingsMod.prototype.configureSettings = function(e) {\n var pendingPromise = new Pending();\n var courseid = $(e.target).closest('a').data('courseid');\n var currentValue = $(e.target).closest('a').data('pushratingstouserplans');\n var context = {\n courseid: courseid,\n settings: {pushratingstouserplans: currentValue}\n };\n e.preventDefault();\n\n $.when(\n str.get_string('configurecoursecompetencysettings', 'tool_lp'),\n templates.render('tool_lp/course_competency_settings', context),\n )\n .then(function(title, templateResult) {\n this._dialogue = new Dialogue(\n title,\n templateResult[0],\n this.addListeners.bind(this)\n );\n\n return this._dialogue;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n /**\n * Add the save listener to the form.\n *\n * @method addSaveListener\n */\n settingsMod.prototype.addListeners = function() {\n var save = this._find('[data-action=\"save\"]');\n save.on('click', this.saveSettings.bind(this));\n var cancel = this._find('[data-action=\"cancel\"]');\n cancel.on('click', this.cancelChanges.bind(this));\n };\n\n /**\n * Cancel the changes.\n *\n * @param {Event} e\n * @method cancelChanges\n */\n settingsMod.prototype.cancelChanges = function(e) {\n e.preventDefault();\n this._dialogue.close();\n };\n\n /**\n * Cancel the changes.\n *\n * @param {String} selector\n * @return {JQuery}\n */\n settingsMod.prototype._find = function(selector) {\n return $('[data-region=\"coursecompetencysettings\"]').find(selector);\n };\n\n /**\n * Save the settings.\n *\n * @param {Event} e\n * @method saveSettings\n */\n settingsMod.prototype.saveSettings = function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n var newValue = this._find('input[name=\"pushratingstouserplans\"]:checked').val();\n var courseId = this._find('input[name=\"courseid\"]').val();\n var settings = {pushratingstouserplans: newValue};\n\n ajax.call([\n {methodname: 'core_competency_update_course_competency_settings',\n args: {courseid: courseId, settings: settings}}\n ])[0]\n .then(function() {\n return this.refreshCourseCompetenciesPage();\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n\n };\n\n /**\n * Refresh the course competencies page.\n *\n * @method saveSettings\n */\n settingsMod.prototype.refreshCourseCompetenciesPage = function() {\n var courseId = this._find('input[name=\"courseid\"]').val();\n var pendingPromise = new Pending();\n\n ajax.call([\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: courseId, moduleid: 0}}\n ])[0]\n .then(function(context) {\n return templates.render('tool_lp/course_competencies_page', context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"coursecompetenciespage\"]'), html, js);\n this._dialogue.close();\n\n return;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n return /** @alias module:tool_lp/configurecoursecompetencysettings */ settingsMod;\n});\n"],"names":["define","$","notification","Dialogue","str","ajax","templates","Pending","settingsMod","selector","on","this","configureSettings","bind","prototype","_dialogue","e","pendingPromise","context","courseid","target","closest","data","settings","pushratingstouserplans","preventDefault","when","get_string","render","then","title","templateResult","addListeners","resolve","catch","exception","_find","saveSettings","cancelChanges","close","find","newValue","val","courseId","call","methodname","args","refreshCourseCompetenciesPage","moduleid","html","js","replaceNode"],"mappings":";;;;;;;AAsBAA,4CAAO,CAAC,SACA,oBACA,mBACA,WACA,YACA,iBACA,iBAED,SAASC,EAAGC,aAAcC,SAAUC,IAAKC,KAAMC,UAAWC,aAOzDC,YAAc,SAASC,UACvBR,EAAEQ,UAAUC,GAAG,QAASC,KAAKC,kBAAkBC,KAAKF,eAIxDH,YAAYM,UAAUC,UAAY,KAQlCP,YAAYM,UAAUF,kBAAoB,SAASI,OAC3CC,eAAiB,IAAIV,QAGrBW,QAAU,CACVC,SAHWlB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,YAIzCC,SAAU,CAACC,uBAHIvB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,4BAKjDN,EAAES,iBAEFxB,EAAEyB,KACEtB,IAAIuB,WAAW,oCAAqC,WACpDrB,UAAUsB,OAAO,qCAAsCV,UAE1DW,KAAK,SAASC,MAAOC,4BACbhB,UAAY,IAAIZ,SACjB2B,MACAC,eAAe,GACfpB,KAAKqB,aAAanB,KAAKF,OAGpBA,KAAKI,WACdF,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAQxB3B,YAAYM,UAAUkB,aAAe,WACtBrB,KAAKyB,MAAM,wBACjB1B,GAAG,QAASC,KAAK0B,aAAaxB,KAAKF,OAC3BA,KAAKyB,MAAM,0BACjB1B,GAAG,QAASC,KAAK2B,cAAczB,KAAKF,QAS/CH,YAAYM,UAAUwB,cAAgB,SAAStB,GAC3CA,EAAES,sBACGV,UAAUwB,SASnB/B,YAAYM,UAAUsB,MAAQ,SAAS3B,iBAC5BR,EAAE,4CAA4CuC,KAAK/B,WAS9DD,YAAYM,UAAUuB,aAAe,SAASrB,OACtCC,eAAiB,IAAIV,QACzBS,EAAES,qBAEEgB,SAAW9B,KAAKyB,MAAM,gDAAgDM,MACtEC,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDnB,SAAW,CAACC,uBAAwBiB,UAExCpC,KAAKuC,KAAK,CACN,CAACC,WAAY,oDACXC,KAAM,CAAC3B,SAAUwB,SAAUpB,SAAUA,aACxC,GACFM,KAAK,kBACKlB,KAAKoC,iCACdlC,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YASxB3B,YAAYM,UAAUiC,8BAAgC,eAC9CJ,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDzB,eAAiB,IAAIV,QAEzBF,KAAKuC,KAAK,CACN,CAACC,WAAY,4CACXC,KAAM,CAAC3B,SAAUwB,SAAUK,SAAU,MACxC,GACFnB,MAAK,SAASX,gBACJZ,UAAUsB,OAAO,mCAAoCV,YAE/DW,KAAK,SAASoB,KAAMC,IACjB5C,UAAU6C,YAAYlD,EAAE,0CAA2CgD,KAAMC,SACpEnC,UAAUwB,SAGjB1B,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAG8C3B"} \ No newline at end of file +{"version":3,"file":"course_competency_settings.min.js","sources":["../src/course_competency_settings.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 * Change the course competency settings in a popup.\n *\n * @module tool_lp/course_competency_settings\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery',\n 'core/notification',\n 'tool_lp/dialogue',\n 'core/str',\n 'core/ajax',\n 'core/templates',\n 'core/pending'\n ],\n function($, notification, Dialogue, str, ajax, templates, Pending) {\n\n /**\n * Constructor\n *\n * @param {String} selector - selector for the links to open the dialogue.\n */\n var settingsMod = function(selector) {\n $(selector).on('click', this.configureSettings.bind(this));\n };\n\n /** @property {Dialogue} Reference to the dialogue that we opened. */\n settingsMod.prototype._dialogue = null;\n\n /**\n * Open the configure settings dialogue.\n *\n * @param {Event} e\n * @method configureSettings\n */\n settingsMod.prototype.configureSettings = function(e) {\n var pendingPromise = new Pending();\n var courseid = $(e.target).closest('a').data('courseid');\n var currentValue = $(e.target).closest('a').data('pushratingstouserplans');\n var context = {\n courseid: courseid,\n settings: {pushratingstouserplans: currentValue}\n };\n e.preventDefault();\n\n $.when(\n str.get_string('configurecoursecompetencysettings', 'tool_lp'),\n templates.render('tool_lp/course_competency_settings', context),\n )\n .then(function(title, templateResult) {\n this._dialogue = new Dialogue(\n title,\n templateResult[0],\n this.addListeners.bind(this)\n );\n\n return this._dialogue;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n /**\n * Add the save listener to the form.\n *\n * @method addSaveListener\n */\n settingsMod.prototype.addListeners = function() {\n var save = this._find('[data-action=\"save\"]');\n save.on('click', this.saveSettings.bind(this));\n var cancel = this._find('[data-action=\"cancel\"]');\n cancel.on('click', this.cancelChanges.bind(this));\n };\n\n /**\n * Cancel the changes.\n *\n * @param {Event} e\n * @method cancelChanges\n */\n settingsMod.prototype.cancelChanges = function(e) {\n e.preventDefault();\n this._dialogue.close();\n };\n\n /**\n * Cancel the changes.\n *\n * @param {String} selector\n * @return {JQuery}\n */\n settingsMod.prototype._find = function(selector) {\n return $('[data-region=\"coursecompetencysettings\"]').find(selector);\n };\n\n /**\n * Save the settings.\n *\n * @param {Event} e\n * @method saveSettings\n */\n settingsMod.prototype.saveSettings = function(e) {\n var pendingPromise = new Pending();\n e.preventDefault();\n\n var newValue = this._find('input[name=\"pushratingstouserplans\"]:checked').val();\n var courseId = this._find('input[name=\"courseid\"]').val();\n var settings = {pushratingstouserplans: newValue};\n\n ajax.call([\n {methodname: 'core_competency_update_course_competency_settings',\n args: {courseid: courseId, settings: settings}}\n ])[0]\n .then(function() {\n return this.refreshCourseCompetenciesPage();\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n\n };\n\n /**\n * Refresh the course competencies page.\n *\n * @method saveSettings\n */\n settingsMod.prototype.refreshCourseCompetenciesPage = function() {\n var courseId = this._find('input[name=\"courseid\"]').val();\n var pendingPromise = new Pending();\n\n ajax.call([\n {methodname: 'tool_lp_data_for_course_competencies_page',\n args: {courseid: courseId, moduleid: 0}}\n ])[0]\n .then(function(context) {\n return templates.render('tool_lp/course_competencies_page', context);\n })\n .then(function(html, js) {\n templates.replaceNode($('[data-region=\"coursecompetenciespage\"]'), html, js);\n this._dialogue.close();\n\n return;\n }.bind(this))\n .then(pendingPromise.resolve)\n .catch(notification.exception);\n };\n\n return /** @alias module:tool_lp/configurecoursecompetencysettings */ settingsMod;\n});\n"],"names":["define","$","notification","Dialogue","str","ajax","templates","Pending","settingsMod","selector","on","this","configureSettings","bind","prototype","_dialogue","e","pendingPromise","context","courseid","target","closest","data","settings","pushratingstouserplans","preventDefault","when","get_string","render","then","title","templateResult","addListeners","resolve","catch","exception","_find","saveSettings","cancelChanges","close","find","newValue","val","courseId","call","methodname","args","refreshCourseCompetenciesPage","moduleid","html","js","replaceNode"],"mappings":";;;;;;;AAsBAA,4CAAO,CAAC,SACA,oBACA,mBACA,WACA,YACA,iBACA,iBAED,SAASC,EAAGC,aAAcC,SAAUC,IAAKC,KAAMC,UAAWC,aAOzDC,YAAc,SAASC,UACvBR,EAAEQ,UAAUC,GAAG,QAASC,KAAKC,kBAAkBC,KAAKF,eAIxDH,YAAYM,UAAUC,UAAY,KAQlCP,YAAYM,UAAUF,kBAAoB,SAASI,OAC3CC,eAAiB,IAAIV,QAGrBW,QAAU,CACVC,SAHWlB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,YAIzCC,SAAU,CAACC,uBAHIvB,EAAEe,EAAEI,QAAQC,QAAQ,KAAKC,KAAK,4BAKjDN,EAAES,iBAEFxB,EAAEyB,KACEtB,IAAIuB,WAAW,oCAAqC,WACpDrB,UAAUsB,OAAO,qCAAsCV,UAE1DW,KAAK,SAASC,MAAOC,4BACbhB,UAAY,IAAIZ,SACjB2B,MACAC,eAAe,GACfpB,KAAKqB,aAAanB,KAAKF,OAGpBA,KAAKI,WACdF,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAQxB3B,YAAYM,UAAUkB,aAAe,WACtBrB,KAAKyB,MAAM,wBACjB1B,GAAG,QAASC,KAAK0B,aAAaxB,KAAKF,OAC3BA,KAAKyB,MAAM,0BACjB1B,GAAG,QAASC,KAAK2B,cAAczB,KAAKF,QAS/CH,YAAYM,UAAUwB,cAAgB,SAAStB,GAC3CA,EAAES,sBACGV,UAAUwB,SASnB/B,YAAYM,UAAUsB,MAAQ,SAAS3B,iBAC5BR,EAAE,4CAA4CuC,KAAK/B,WAS9DD,YAAYM,UAAUuB,aAAe,SAASrB,OACtCC,eAAiB,IAAIV,QACzBS,EAAES,qBAEEgB,SAAW9B,KAAKyB,MAAM,gDAAgDM,MACtEC,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDnB,SAAW,CAACC,uBAAwBiB,UAExCpC,KAAKuC,KAAK,CACN,CAACC,WAAY,oDACXC,KAAM,CAAC3B,SAAUwB,SAAUpB,SAAUA,aACxC,GACFM,KAAK,kBACKlB,KAAKoC,iCACdlC,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YASxB3B,YAAYM,UAAUiC,8BAAgC,eAC9CJ,SAAWhC,KAAKyB,MAAM,0BAA0BM,MAChDzB,eAAiB,IAAIV,QAEzBF,KAAKuC,KAAK,CACN,CAACC,WAAY,4CACXC,KAAM,CAAC3B,SAAUwB,SAAUK,SAAU,MACxC,GACFnB,MAAK,SAASX,gBACJZ,UAAUsB,OAAO,mCAAoCV,YAE/DW,KAAK,SAASoB,KAAMC,IACjB5C,UAAU6C,YAAYlD,EAAE,0CAA2CgD,KAAMC,SACpEnC,UAAUwB,SAGjB1B,KAAKF,OACNkB,KAAKZ,eAAegB,SACpBC,MAAMhC,aAAaiC,YAG8C3B"} \ No newline at end of file diff --git a/admin/tool/lp/amd/src/competency_rule.js b/admin/tool/lp/amd/src/competency_rule.js index ae648d8c9e6..0784351a1e8 100644 --- a/admin/tool/lp/amd/src/competency_rule.js +++ b/admin/tool/lp/amd/src/competency_rule.js @@ -16,7 +16,7 @@ /** * Competency rule base module. * - * @module tool_lp/competencyrule + * @module tool_lp/competency_rule * @copyright 2015 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/src/competency_rule_points.js b/admin/tool/lp/amd/src/competency_rule_points.js index c49cb390cd8..38456aee952 100644 --- a/admin/tool/lp/amd/src/competency_rule_points.js +++ b/admin/tool/lp/amd/src/competency_rule_points.js @@ -16,7 +16,7 @@ /** * Competency rule points module. * - * @module tool_lp/competency_rule_all + * @module tool_lp/competency_rule_points * @copyright 2015 Frédéric Massart - FMCorz.net * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/src/competencydialogue.js b/admin/tool/lp/amd/src/competencydialogue.js index 812e77a0eea..6cdd52f523c 100644 --- a/admin/tool/lp/amd/src/competencydialogue.js +++ b/admin/tool/lp/amd/src/competencydialogue.js @@ -16,7 +16,7 @@ /** * Display Competency in dialogue box. * - * @module tool_lp/Competencydialogue + * @module tool_lp/competencydialogue * @copyright 2015 Issam Taboubi * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/src/competencytree.js b/admin/tool/lp/amd/src/competencytree.js index 9718ae4451c..4d003a8a466 100644 --- a/admin/tool/lp/amd/src/competencytree.js +++ b/admin/tool/lp/amd/src/competencytree.js @@ -16,7 +16,7 @@ /** * Handle selection changes on the competency tree. * - * @module tool_lp/competencyselect + * @module tool_lp/competencytree * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/lp/amd/src/course_competency_settings.js b/admin/tool/lp/amd/src/course_competency_settings.js index 1d4668b46b4..d5532012354 100644 --- a/admin/tool/lp/amd/src/course_competency_settings.js +++ b/admin/tool/lp/amd/src/course_competency_settings.js @@ -16,7 +16,7 @@ /** * Change the course competency settings in a popup. * - * @module tool_lp/configurecoursecompetencysettings + * @module tool_lp/course_competency_settings * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/admin/tool/usertours/amd/build/repository.min.js.map b/admin/tool/usertours/amd/build/repository.min.js.map index 8afcf933c7f..0b5bae69bc2 100644 --- a/admin/tool/usertours/amd/build/repository.min.js.map +++ b/admin/tool/usertours/amd/build/repository.min.js.map @@ -1 +1 @@ -{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"sourcesContent":["/**\n * Step management code.\n *\n * @module tool_usertours/managesteps\n * @copyright 2016 Andrew Nicols \n */\nimport {call as fetchMany} from 'core/ajax';\nimport moodleConfig from 'core/config';\n\n/**\n * Reset the tour state of the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const resetTourState = tourid => fetchMany([{\n methodname: 'tool_usertours_reset_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified tour as complete.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markTourComplete = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_complete_tour',\n args: {\n stepid,\n stepindex: stepindex,\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Fetch the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const fetchTour = tourid => fetchMany([{\n methodname: 'tool_usertours_fetch_and_start_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified step as having been shown.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markStepShown = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_step_shown',\n args: {\n tourid,\n stepid,\n stepindex,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n"],"names":["tourid","methodname","args","context","moodleConfig","contextid","pageurl","window","location","href","stepid","stepindex"],"mappings":"8VAe8BA,SAAU,cAAU,CAAC,CAC/CC,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,6BAU4B,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACtEV,WAAY,+BACZC,KAAM,CACFQ,OAAAA,OACAC,UAAWA,UACXX,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,sBAQqBT,SAAU,cAAU,CAAC,CAC1CC,WAAY,sCACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,0BAUyB,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACnEV,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAU,OAAAA,OACAC,UAAAA,UACAR,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B"} \ No newline at end of file +{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"sourcesContent":["/**\n * Javascript module to handle tool_usertour AJAX requests.\n *\n * @module tool_usertours/repository\n * @copyright 2016 Andrew Nicols \n */\nimport {call as fetchMany} from 'core/ajax';\nimport moodleConfig from 'core/config';\n\n/**\n * Reset the tour state of the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const resetTourState = tourid => fetchMany([{\n methodname: 'tool_usertours_reset_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified tour as complete.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markTourComplete = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_complete_tour',\n args: {\n stepid,\n stepindex: stepindex,\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Fetch the specified tour.\n *\n * @param {number} tourid\n * @return {Promise}\n */\nexport const fetchTour = tourid => fetchMany([{\n methodname: 'tool_usertours_fetch_and_start_tour',\n args: {\n tourid,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n\n/**\n * Mark the specified step as having been shown.\n *\n * @param {number} stepid\n * @param {number} tourid\n * @param {number} stepindex\n * @return {Promise}\n */\nexport const markStepShown = (stepid, tourid, stepindex) => fetchMany([{\n methodname: 'tool_usertours_step_shown',\n args: {\n tourid,\n stepid,\n stepindex,\n context: moodleConfig.contextid,\n pageurl: window.location.href,\n }\n}])[0];\n"],"names":["tourid","methodname","args","context","moodleConfig","contextid","pageurl","window","location","href","stepid","stepindex"],"mappings":"8VAe8BA,SAAU,cAAU,CAAC,CAC/CC,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,6BAU4B,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACtEV,WAAY,+BACZC,KAAM,CACFQ,OAAAA,OACAC,UAAWA,UACXX,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,sBAQqBT,SAAU,cAAU,CAAC,CAC1CC,WAAY,sCACZC,KAAM,CACFF,OAAAA,OACAG,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B,0BAUyB,CAACC,OAAQV,OAAQW,aAAc,cAAU,CAAC,CACnEV,WAAY,4BACZC,KAAM,CACFF,OAAAA,OACAU,OAAAA,OACAC,UAAAA,UACAR,QAASC,gBAAaC,UACtBC,QAASC,OAAOC,SAASC,SAE7B"} \ No newline at end of file diff --git a/admin/tool/usertours/amd/src/repository.js b/admin/tool/usertours/amd/src/repository.js index ec6915cb534..1def70a14b2 100644 --- a/admin/tool/usertours/amd/src/repository.js +++ b/admin/tool/usertours/amd/src/repository.js @@ -1,7 +1,7 @@ /** - * Step management code. + * Javascript module to handle tool_usertour AJAX requests. * - * @module tool_usertours/managesteps + * @module tool_usertours/repository * @copyright 2016 Andrew Nicols */ import {call as fetchMany} from 'core/ajax'; diff --git a/calendar/amd/build/calendar_view.min.js b/calendar/amd/build/calendar_view.min.js index 915843d4e93..b554ce10cca 100644 --- a/calendar/amd/build/calendar_view.min.js +++ b/calendar/amd/build/calendar_view.min.js @@ -1,7 +1,7 @@ /** * This module is responsible for handle calendar day and upcoming view. * - * @module core_calendar/calendar + * @module core_calendar/calendar_view * @copyright 2017 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/amd/build/calendar_view.min.js.map b/calendar/amd/build/calendar_view.min.js.map index afacfe7aa48..967f0e2124f 100644 --- a/calendar/amd/build/calendar_view.min.js.map +++ b/calendar/amd/build/calendar_view.min.js.map @@ -1 +1 @@ -{"version":3,"file":"calendar_view.min.js","sources":["../src/calendar_view.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 * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/repository',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core/modal_events',\n 'core_calendar/crud'\n ],\n function(\n $,\n Str,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarRepository,\n ModalFactory,\n ModalEventForm,\n ModalEvents,\n CalendarCrud\n ) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=upcoming&course=' + courseId);\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type) {\n root = $(root);\n\n CalendarViewManager.init(root, type);\n registerEventListeners(root, type);\n }\n };\n });\n"],"names":["define","$","Str","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarRepository","ModalFactory","ModalEventForm","ModalEvents","CalendarCrud","init","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","courseId","this","val","then","find","updateUrl","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","registerEventListeners"],"mappings":";;;;;;;AAsBAA,qCAAO,CACC,SACA,WACA,oBACA,0BACA,uBACA,6BACA,2BACA,qBACA,iCACA,oBACA,uBAEJ,SACIC,EACAC,IACAC,aACAC,kBACAC,eACAC,oBACAC,mBACAC,aACAC,eACAC,YACAC,oBAgDO,CACHC,KAAM,SAASC,KAAMC,MACjBD,KAAOZ,EAAEY,MAETP,oBAAoBM,KAAKC,KAAMC,MAjDV,SAASD,KAAMC,UACpCC,KAAOd,EAAE,QAEbU,aAAaK,eAAeH,UAExBI,eAAiB,gBAAkBH,KAAKI,OAAO,GAAGC,cAAgBL,KAAKM,MAAM,GAEjFL,KAAKM,GAAGhB,eAAeiB,SAAS,WAC5BhB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAekB,SAAS,WAC5BjB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAemB,SAAS,WAC5BlB,oBAAoBW,gBAAgBJ,SAGxCA,KAAKQ,GAAG,SAAUjB,kBAAkBqB,gBAAgB,eAE5CC,SADgBzB,EAAE0B,MACOC,MAC7BtB,oBAAoBW,gBAAgBJ,KAAMa,SAAU,MAC/CG,MAAK,kBAEKhB,KAAKiB,KAAK1B,kBAAkBqB,gBAAgBG,IAAIF,aAE1DG,MAAK,WACFvB,oBAAoByB,UAAU,yBAA2BL,aAE5DM,KAAK7B,aAAa8B,cAG3BlB,KAAKM,GAAGhB,eAAe6B,eAAe,SAASC,EAAGC,UAC1CC,cAAgBxB,KAAKiB,KAAK1B,kBAAkBkC,UAAUF,KAAKtB,OAC5C,GAAfsB,KAAKG,OACLF,cAAcG,SAAS,UAEvBH,cAAcI,YAAY,UAE9BnC,oBAAoBoC,cAAc7B,aAGlC8B,iBAAmBhC,aAAaiC,uBAAuB/B,MAC3DF,aAAakC,sBAAsBhC,KAAM8B,kBAQrCG,CAAuBjC,KAAMC"} \ No newline at end of file +{"version":3,"file":"calendar_view.min.js","sources":["../src/calendar_view.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 * This module is responsible for handle calendar day and upcoming view.\n *\n * @module core_calendar/calendar_view\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/str',\n 'core/notification',\n 'core_calendar/selectors',\n 'core_calendar/events',\n 'core_calendar/view_manager',\n 'core_calendar/repository',\n 'core/modal_factory',\n 'core_calendar/modal_event_form',\n 'core/modal_events',\n 'core_calendar/crud'\n ],\n function(\n $,\n Str,\n Notification,\n CalendarSelectors,\n CalendarEvents,\n CalendarViewManager,\n CalendarRepository,\n ModalFactory,\n ModalEventForm,\n ModalEvents,\n CalendarCrud\n ) {\n\n var registerEventListeners = function(root, type) {\n var body = $('body');\n\n CalendarCrud.registerRemove(root);\n\n var reloadFunction = 'reloadCurrent' + type.charAt(0).toUpperCase() + type.slice(1);\n\n body.on(CalendarEvents.created, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.deleted, function() {\n CalendarViewManager[reloadFunction](root);\n });\n body.on(CalendarEvents.updated, function() {\n CalendarViewManager[reloadFunction](root);\n });\n\n root.on('change', CalendarSelectors.courseSelector, function() {\n var selectElement = $(this);\n var courseId = selectElement.val();\n CalendarViewManager[reloadFunction](root, courseId, null)\n .then(function() {\n // We need to get the selector again because the content has changed.\n return root.find(CalendarSelectors.courseSelector).val(courseId);\n })\n .then(function() {\n CalendarViewManager.updateUrl('?view=upcoming&course=' + courseId);\n })\n .fail(Notification.exception);\n });\n\n body.on(CalendarEvents.filterChanged, function(e, data) {\n var daysWithEvent = root.find(CalendarSelectors.eventType[data.type]);\n if (data.hidden == true) {\n daysWithEvent.addClass('hidden');\n } else {\n daysWithEvent.removeClass('hidden');\n }\n CalendarViewManager.foldDayEvents(root);\n });\n\n var eventFormPromise = CalendarCrud.registerEventFormModal(root);\n CalendarCrud.registerEditListeners(root, eventFormPromise);\n };\n\n return {\n init: function(root, type) {\n root = $(root);\n\n CalendarViewManager.init(root, type);\n registerEventListeners(root, type);\n }\n };\n });\n"],"names":["define","$","Str","Notification","CalendarSelectors","CalendarEvents","CalendarViewManager","CalendarRepository","ModalFactory","ModalEventForm","ModalEvents","CalendarCrud","init","root","type","body","registerRemove","reloadFunction","charAt","toUpperCase","slice","on","created","deleted","updated","courseSelector","courseId","this","val","then","find","updateUrl","fail","exception","filterChanged","e","data","daysWithEvent","eventType","hidden","addClass","removeClass","foldDayEvents","eventFormPromise","registerEventFormModal","registerEditListeners","registerEventListeners"],"mappings":";;;;;;;AAsBAA,qCAAO,CACC,SACA,WACA,oBACA,0BACA,uBACA,6BACA,2BACA,qBACA,iCACA,oBACA,uBAEJ,SACIC,EACAC,IACAC,aACAC,kBACAC,eACAC,oBACAC,mBACAC,aACAC,eACAC,YACAC,oBAgDO,CACHC,KAAM,SAASC,KAAMC,MACjBD,KAAOZ,EAAEY,MAETP,oBAAoBM,KAAKC,KAAMC,MAjDV,SAASD,KAAMC,UACpCC,KAAOd,EAAE,QAEbU,aAAaK,eAAeH,UAExBI,eAAiB,gBAAkBH,KAAKI,OAAO,GAAGC,cAAgBL,KAAKM,MAAM,GAEjFL,KAAKM,GAAGhB,eAAeiB,SAAS,WAC5BhB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAekB,SAAS,WAC5BjB,oBAAoBW,gBAAgBJ,SAExCE,KAAKM,GAAGhB,eAAemB,SAAS,WAC5BlB,oBAAoBW,gBAAgBJ,SAGxCA,KAAKQ,GAAG,SAAUjB,kBAAkBqB,gBAAgB,eAE5CC,SADgBzB,EAAE0B,MACOC,MAC7BtB,oBAAoBW,gBAAgBJ,KAAMa,SAAU,MAC/CG,MAAK,kBAEKhB,KAAKiB,KAAK1B,kBAAkBqB,gBAAgBG,IAAIF,aAE1DG,MAAK,WACFvB,oBAAoByB,UAAU,yBAA2BL,aAE5DM,KAAK7B,aAAa8B,cAG3BlB,KAAKM,GAAGhB,eAAe6B,eAAe,SAASC,EAAGC,UAC1CC,cAAgBxB,KAAKiB,KAAK1B,kBAAkBkC,UAAUF,KAAKtB,OAC5C,GAAfsB,KAAKG,OACLF,cAAcG,SAAS,UAEvBH,cAAcI,YAAY,UAE9BnC,oBAAoBoC,cAAc7B,aAGlC8B,iBAAmBhC,aAAaiC,uBAAuB/B,MAC3DF,aAAakC,sBAAsBhC,KAAM8B,kBAQrCG,CAAuBjC,KAAMC"} \ No newline at end of file diff --git a/calendar/amd/build/modal_event_form.min.js b/calendar/amd/build/modal_event_form.min.js index b9cf446f6b6..be14640dd4b 100644 --- a/calendar/amd/build/modal_event_form.min.js +++ b/calendar/amd/build/modal_event_form.min.js @@ -1,7 +1,7 @@ /** * Contain the logic for the quick add or update event modal. * - * @module core_calendar/modal_quick_add_event + * @module core_calendar/modal_event_form * @copyright 2017 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/amd/build/modal_event_form.min.js.map b/calendar/amd/build/modal_event_form.min.js.map index e0b9e917c2e..20ec5c3603a 100644 --- a/calendar/amd/build/modal_event_form.min.js.map +++ b/calendar/amd/build/modal_event_form.min.js.map @@ -1 +1 @@ -{"version":3,"file":"modal_event_form.min.js","sources":["../src/modal_event_form.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 * Contain the logic for the quick add or update event modal.\n *\n * @module core_calendar/modal_quick_add_event\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_form/events',\n 'core/str',\n 'core/notification',\n 'core/templates',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/fragment',\n 'core_calendar/events',\n 'core_calendar/repository'\n],\nfunction(\n $,\n FormEvents,\n Str,\n Notification,\n Templates,\n CustomEvents,\n Modal,\n ModalRegistry,\n Fragment,\n CalendarEvents,\n Repository\n) {\n var registered = false;\n var SELECTORS = {\n SAVE_BUTTON: '[data-action=\"save\"]',\n LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventForm = function(root) {\n Modal.call(this, root);\n this.eventId = null;\n this.startTime = null;\n this.courseId = null;\n this.categoryId = null;\n this.contextId = null;\n this.reloadingBody = false;\n this.reloadingTitle = false;\n this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n };\n\n ModalEventForm.TYPE = 'core_calendar-modal_event_form';\n ModalEventForm.prototype = Object.create(Modal.prototype);\n ModalEventForm.prototype.constructor = ModalEventForm;\n\n /**\n * Set the context id to the given value.\n *\n * @method setContextId\n * @param {Number} id The event id\n */\n ModalEventForm.prototype.setContextId = function(id) {\n this.contextId = id;\n };\n\n /**\n * Retrieve the current context id, if any.\n *\n * @method getContextId\n * @return {Number|null} The event id\n */\n ModalEventForm.prototype.getContextId = function() {\n return this.contextId;\n };\n\n /**\n * Set the course id to the given value.\n *\n * @method setCourseId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCourseId = function(id) {\n this.courseId = id;\n };\n\n /**\n * Retrieve the current course id, if any.\n *\n * @method getCourseId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCourseId = function() {\n return this.courseId;\n };\n\n /**\n * Set the category id to the given value.\n *\n * @method setCategoryId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCategoryId = function(id) {\n this.categoryId = id;\n };\n\n /**\n * Retrieve the current category id, if any.\n *\n * @method getCategoryId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCategoryId = function() {\n return this.categoryId;\n };\n\n /**\n * Check if the modal has an course id.\n *\n * @method hasCourseId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCourseId = function() {\n return this.courseId !== null;\n };\n\n /**\n * Check if the modal has an category id.\n *\n * @method hasCategoryId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCategoryId = function() {\n return this.categoryId !== null;\n };\n\n /**\n * Set the event id to the given value.\n *\n * @method setEventId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setEventId = function(id) {\n this.eventId = id;\n };\n\n /**\n * Retrieve the current event id, if any.\n *\n * @method getEventId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getEventId = function() {\n return this.eventId;\n };\n\n /**\n * Check if the modal has an event id.\n *\n * @method hasEventId\n * @return {bool}\n */\n ModalEventForm.prototype.hasEventId = function() {\n return this.eventId !== null;\n };\n\n /**\n * Set the start time to the given value.\n *\n * @method setStartTime\n * @param {int} time The start time\n */\n ModalEventForm.prototype.setStartTime = function(time) {\n this.startTime = time;\n };\n\n /**\n * Retrieve the current start time, if any.\n *\n * @method getStartTime\n * @return {int|null} The start time\n */\n ModalEventForm.prototype.getStartTime = function() {\n return this.startTime;\n };\n\n /**\n * Check if the modal has start time.\n *\n * @method hasStartTime\n * @return {bool}\n */\n ModalEventForm.prototype.hasStartTime = function() {\n return this.startTime !== null;\n };\n\n /**\n * Get the form element from the modal.\n *\n * @method getForm\n * @return {object}\n */\n ModalEventForm.prototype.getForm = function() {\n return this.getBody().find('form');\n };\n\n /**\n * Disable the buttons in the footer.\n *\n * @method disableButtons\n */\n ModalEventForm.prototype.disableButtons = function() {\n this.saveButton.prop('disabled', true);\n };\n\n /**\n * Enable the buttons in the footer.\n *\n * @method enableButtons\n */\n ModalEventForm.prototype.enableButtons = function() {\n this.saveButton.prop('disabled', false);\n };\n\n /**\n * Reload the title for the modal to the appropriate value\n * depending on whether we are creating a new event or\n * editing an existing event.\n *\n * @method reloadTitleContent\n * @return {object} A promise resolved with the new title text\n */\n ModalEventForm.prototype.reloadTitleContent = function() {\n if (this.reloadingTitle) {\n return this.titlePromise;\n }\n\n this.reloadingTitle = true;\n\n if (this.hasEventId()) {\n this.titlePromise = Str.get_string('editevent', 'calendar');\n } else {\n this.titlePromise = Str.get_string('newevent', 'calendar');\n }\n\n this.titlePromise.then(function(string) {\n this.setTitle(string);\n return string;\n }.bind(this))\n .always(function() {\n this.reloadingTitle = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.titlePromise;\n };\n\n /**\n * Send a request to the server to get the event_form in a fragment\n * and render the result in the body of the modal.\n *\n * If serialised form data is provided then it will be sent in the\n * request to the server to have the form rendered with the data. This\n * is used when the form had a server side error and we need the server\n * to re-render it for us to display the error to the user.\n *\n * @method reloadBodyContent\n * @param {string} formData The serialised form data\n * @return {object} A promise resolved with the fragment html and js from\n */\n ModalEventForm.prototype.reloadBodyContent = function(formData) {\n if (this.reloadingBody) {\n return this.bodyPromise;\n }\n\n this.reloadingBody = true;\n this.disableButtons();\n\n var args = {};\n\n if (this.hasEventId()) {\n args.eventid = this.getEventId();\n }\n\n if (this.hasStartTime()) {\n args.starttime = this.getStartTime();\n }\n\n if (this.hasCourseId()) {\n args.courseid = this.getCourseId();\n }\n\n if (this.hasCategoryId()) {\n args.categoryid = this.getCategoryId();\n }\n\n if (typeof formData !== 'undefined') {\n args.formdata = formData;\n }\n\n this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);\n\n this.setBody(this.bodyPromise);\n\n this.bodyPromise.then(function() {\n this.enableButtons();\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\n this.reloadingBody = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.bodyPromise;\n };\n\n /**\n * Reload both the title and body content.\n *\n * @method reloadAllContent\n * @return {object} promise\n */\n ModalEventForm.prototype.reloadAllContent = function() {\n return $.when(this.reloadTitleContent(), this.reloadBodyContent());\n };\n\n /**\n * Kick off a reload the modal content before showing it. This\n * is to allow us to re-use the same modal for creating and\n * editing different events within the page.\n *\n * We do the reload when showing the modal rather than hiding it\n * to save a request to the server if the user closes the modal\n * and never re-opens it.\n *\n * @method show\n */\n ModalEventForm.prototype.show = function() {\n this.reloadAllContent();\n Modal.prototype.show.call(this);\n };\n\n /**\n * Clear the event id from the modal when it's closed so\n * that it is loaded fresh next time it's displayed.\n *\n * The event id will be set by the calling code if it wants\n * to edit a specific event.\n *\n * @method hide\n */\n ModalEventForm.prototype.hide = function() {\n Modal.prototype.hide.call(this);\n this.setEventId(null);\n this.setStartTime(null);\n this.setCourseId(null);\n this.setCategoryId(null);\n };\n\n /**\n * Get the serialised form data.\n *\n * @method getFormData\n * @return {string} serialised form data\n */\n ModalEventForm.prototype.getFormData = function() {\n return this.getForm().serialize();\n };\n\n /**\n * Send the form data to the server to create or update\n * an event.\n *\n * If there is a server side validation error then we re-request the\n * rendered form (with the data) from the server in order to get the\n * server side errors to display.\n *\n * On success the modal is hidden and the page is reloaded so that the\n * new event will display.\n *\n * @method save\n * @return {object} A promise\n */\n ModalEventForm.prototype.save = function() {\n var invalid,\n loadingContainer = this.saveButton.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n invalid = this.getForm().find('[aria-invalid=\"true\"]');\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n return Promise.resolve();\n }\n\n loadingContainer.removeClass('hidden');\n this.disableButtons();\n\n var formData = this.getFormData();\n // Send the form data to the server for processing.\n return Repository.submitCreateUpdateForm(formData)\n .then(function(response) {\n if (response.validationerror) {\n // If there was a server side validation error then\n // we need to re-request the rendered form from the server\n // in order to display the error for the user.\n this.reloadBodyContent(formData);\n return;\n } else {\n // Check whether this was a new event or not.\n // The hide function unsets the form data so grab this before the hide.\n var isExisting = this.hasEventId();\n\n // No problemo! Our work here is done.\n this.hide();\n\n // Trigger the appropriate calendar event so that the view can be updated.\n if (isExisting) {\n $('body').trigger(CalendarEvents.updated, [response.event]);\n } else {\n $('body').trigger(CalendarEvents.created, [response.event]);\n }\n }\n\n return;\n }.bind(this))\n .always(function() {\n // Regardless of success or error we should always stop\n // the loading icon and re-enable the buttons.\n loadingContainer.addClass('hidden');\n this.enableButtons();\n\n return;\n }.bind(this))\n .fail(Notification.exception);\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n * @fires event:uploadStarted\n * @fires event:formSubmittedByJavascript\n */\n ModalEventForm.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // When the user clicks the save button we trigger the form submission. We need to\n // trigger an actual submission because there is some JS code in the form that is\n // listening for this event and doing some stuff (e.g. saving draft areas etc).\n this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {\n this.getForm().submit();\n data.originalEvent.preventDefault();\n e.stopPropagation();\n }.bind(this));\n\n // Catch the submit event before it is actually processed by the browser and\n // prevent the submission. We'll take it from here.\n this.getModal().on('submit', function(e) {\n FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);\n\n this.save();\n\n // Stop the form from actually submitting and prevent it's\n // propagation because we have already handled the event.\n e.preventDefault();\n e.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventForm.TYPE, ModalEventForm, 'calendar/modal_event_form');\n registered = true;\n }\n\n return ModalEventForm;\n});\n"],"names":["define","$","FormEvents","Str","Notification","Templates","CustomEvents","Modal","ModalRegistry","Fragment","CalendarEvents","Repository","registered","SELECTORS","ModalEventForm","root","call","this","eventId","startTime","courseId","categoryId","contextId","reloadingBody","reloadingTitle","saveButton","getFooter","find","TYPE","prototype","Object","create","constructor","setContextId","id","getContextId","setCourseId","getCourseId","setCategoryId","getCategoryId","hasCourseId","hasCategoryId","setEventId","getEventId","hasEventId","setStartTime","time","getStartTime","hasStartTime","getForm","getBody","disableButtons","prop","enableButtons","reloadTitleContent","titlePromise","get_string","then","string","setTitle","bind","always","fail","exception","reloadBodyContent","formData","bodyPromise","args","eventid","starttime","courseid","categoryid","formdata","loadFragment","setBody","reloadAllContent","when","show","hide","getFormData","serialize","save","invalid","loadingContainer","length","first","focus","Promise","resolve","removeClass","submitCreateUpdateForm","response","validationerror","isExisting","trigger","updated","event","created","addClass","registerEventListeners","getModal","on","events","activate","e","data","submit","originalEvent","preventDefault","stopPropagation","notifyFormSubmittedByJavascript","register"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"modal_event_form.min.js","sources":["../src/modal_event_form.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 * Contain the logic for the quick add or update event modal.\n *\n * @module core_calendar/modal_event_form\n * @copyright 2017 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core_form/events',\n 'core/str',\n 'core/notification',\n 'core/templates',\n 'core/custom_interaction_events',\n 'core/modal',\n 'core/modal_registry',\n 'core/fragment',\n 'core_calendar/events',\n 'core_calendar/repository'\n],\nfunction(\n $,\n FormEvents,\n Str,\n Notification,\n Templates,\n CustomEvents,\n Modal,\n ModalRegistry,\n Fragment,\n CalendarEvents,\n Repository\n) {\n var registered = false;\n var SELECTORS = {\n SAVE_BUTTON: '[data-action=\"save\"]',\n LOADING_ICON_CONTAINER: '[data-region=\"loading-icon-container\"]',\n };\n\n /**\n * Constructor for the Modal.\n *\n * @param {object} root The root jQuery element for the modal\n */\n var ModalEventForm = function(root) {\n Modal.call(this, root);\n this.eventId = null;\n this.startTime = null;\n this.courseId = null;\n this.categoryId = null;\n this.contextId = null;\n this.reloadingBody = false;\n this.reloadingTitle = false;\n this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);\n };\n\n ModalEventForm.TYPE = 'core_calendar-modal_event_form';\n ModalEventForm.prototype = Object.create(Modal.prototype);\n ModalEventForm.prototype.constructor = ModalEventForm;\n\n /**\n * Set the context id to the given value.\n *\n * @method setContextId\n * @param {Number} id The event id\n */\n ModalEventForm.prototype.setContextId = function(id) {\n this.contextId = id;\n };\n\n /**\n * Retrieve the current context id, if any.\n *\n * @method getContextId\n * @return {Number|null} The event id\n */\n ModalEventForm.prototype.getContextId = function() {\n return this.contextId;\n };\n\n /**\n * Set the course id to the given value.\n *\n * @method setCourseId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCourseId = function(id) {\n this.courseId = id;\n };\n\n /**\n * Retrieve the current course id, if any.\n *\n * @method getCourseId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCourseId = function() {\n return this.courseId;\n };\n\n /**\n * Set the category id to the given value.\n *\n * @method setCategoryId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setCategoryId = function(id) {\n this.categoryId = id;\n };\n\n /**\n * Retrieve the current category id, if any.\n *\n * @method getCategoryId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getCategoryId = function() {\n return this.categoryId;\n };\n\n /**\n * Check if the modal has an course id.\n *\n * @method hasCourseId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCourseId = function() {\n return this.courseId !== null;\n };\n\n /**\n * Check if the modal has an category id.\n *\n * @method hasCategoryId\n * @return {bool}\n */\n ModalEventForm.prototype.hasCategoryId = function() {\n return this.categoryId !== null;\n };\n\n /**\n * Set the event id to the given value.\n *\n * @method setEventId\n * @param {int} id The event id\n */\n ModalEventForm.prototype.setEventId = function(id) {\n this.eventId = id;\n };\n\n /**\n * Retrieve the current event id, if any.\n *\n * @method getEventId\n * @return {int|null} The event id\n */\n ModalEventForm.prototype.getEventId = function() {\n return this.eventId;\n };\n\n /**\n * Check if the modal has an event id.\n *\n * @method hasEventId\n * @return {bool}\n */\n ModalEventForm.prototype.hasEventId = function() {\n return this.eventId !== null;\n };\n\n /**\n * Set the start time to the given value.\n *\n * @method setStartTime\n * @param {int} time The start time\n */\n ModalEventForm.prototype.setStartTime = function(time) {\n this.startTime = time;\n };\n\n /**\n * Retrieve the current start time, if any.\n *\n * @method getStartTime\n * @return {int|null} The start time\n */\n ModalEventForm.prototype.getStartTime = function() {\n return this.startTime;\n };\n\n /**\n * Check if the modal has start time.\n *\n * @method hasStartTime\n * @return {bool}\n */\n ModalEventForm.prototype.hasStartTime = function() {\n return this.startTime !== null;\n };\n\n /**\n * Get the form element from the modal.\n *\n * @method getForm\n * @return {object}\n */\n ModalEventForm.prototype.getForm = function() {\n return this.getBody().find('form');\n };\n\n /**\n * Disable the buttons in the footer.\n *\n * @method disableButtons\n */\n ModalEventForm.prototype.disableButtons = function() {\n this.saveButton.prop('disabled', true);\n };\n\n /**\n * Enable the buttons in the footer.\n *\n * @method enableButtons\n */\n ModalEventForm.prototype.enableButtons = function() {\n this.saveButton.prop('disabled', false);\n };\n\n /**\n * Reload the title for the modal to the appropriate value\n * depending on whether we are creating a new event or\n * editing an existing event.\n *\n * @method reloadTitleContent\n * @return {object} A promise resolved with the new title text\n */\n ModalEventForm.prototype.reloadTitleContent = function() {\n if (this.reloadingTitle) {\n return this.titlePromise;\n }\n\n this.reloadingTitle = true;\n\n if (this.hasEventId()) {\n this.titlePromise = Str.get_string('editevent', 'calendar');\n } else {\n this.titlePromise = Str.get_string('newevent', 'calendar');\n }\n\n this.titlePromise.then(function(string) {\n this.setTitle(string);\n return string;\n }.bind(this))\n .always(function() {\n this.reloadingTitle = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.titlePromise;\n };\n\n /**\n * Send a request to the server to get the event_form in a fragment\n * and render the result in the body of the modal.\n *\n * If serialised form data is provided then it will be sent in the\n * request to the server to have the form rendered with the data. This\n * is used when the form had a server side error and we need the server\n * to re-render it for us to display the error to the user.\n *\n * @method reloadBodyContent\n * @param {string} formData The serialised form data\n * @return {object} A promise resolved with the fragment html and js from\n */\n ModalEventForm.prototype.reloadBodyContent = function(formData) {\n if (this.reloadingBody) {\n return this.bodyPromise;\n }\n\n this.reloadingBody = true;\n this.disableButtons();\n\n var args = {};\n\n if (this.hasEventId()) {\n args.eventid = this.getEventId();\n }\n\n if (this.hasStartTime()) {\n args.starttime = this.getStartTime();\n }\n\n if (this.hasCourseId()) {\n args.courseid = this.getCourseId();\n }\n\n if (this.hasCategoryId()) {\n args.categoryid = this.getCategoryId();\n }\n\n if (typeof formData !== 'undefined') {\n args.formdata = formData;\n }\n\n this.bodyPromise = Fragment.loadFragment('calendar', 'event_form', this.getContextId(), args);\n\n this.setBody(this.bodyPromise);\n\n this.bodyPromise.then(function() {\n this.enableButtons();\n return;\n }.bind(this))\n .fail(Notification.exception)\n .always(function() {\n this.reloadingBody = false;\n return;\n }.bind(this))\n .fail(Notification.exception);\n\n return this.bodyPromise;\n };\n\n /**\n * Reload both the title and body content.\n *\n * @method reloadAllContent\n * @return {object} promise\n */\n ModalEventForm.prototype.reloadAllContent = function() {\n return $.when(this.reloadTitleContent(), this.reloadBodyContent());\n };\n\n /**\n * Kick off a reload the modal content before showing it. This\n * is to allow us to re-use the same modal for creating and\n * editing different events within the page.\n *\n * We do the reload when showing the modal rather than hiding it\n * to save a request to the server if the user closes the modal\n * and never re-opens it.\n *\n * @method show\n */\n ModalEventForm.prototype.show = function() {\n this.reloadAllContent();\n Modal.prototype.show.call(this);\n };\n\n /**\n * Clear the event id from the modal when it's closed so\n * that it is loaded fresh next time it's displayed.\n *\n * The event id will be set by the calling code if it wants\n * to edit a specific event.\n *\n * @method hide\n */\n ModalEventForm.prototype.hide = function() {\n Modal.prototype.hide.call(this);\n this.setEventId(null);\n this.setStartTime(null);\n this.setCourseId(null);\n this.setCategoryId(null);\n };\n\n /**\n * Get the serialised form data.\n *\n * @method getFormData\n * @return {string} serialised form data\n */\n ModalEventForm.prototype.getFormData = function() {\n return this.getForm().serialize();\n };\n\n /**\n * Send the form data to the server to create or update\n * an event.\n *\n * If there is a server side validation error then we re-request the\n * rendered form (with the data) from the server in order to get the\n * server side errors to display.\n *\n * On success the modal is hidden and the page is reloaded so that the\n * new event will display.\n *\n * @method save\n * @return {object} A promise\n */\n ModalEventForm.prototype.save = function() {\n var invalid,\n loadingContainer = this.saveButton.find(SELECTORS.LOADING_ICON_CONTAINER);\n\n // Now the change events have run, see if there are any \"invalid\" form fields.\n invalid = this.getForm().find('[aria-invalid=\"true\"]');\n\n // If we found invalid fields, focus on the first one and do not submit via ajax.\n if (invalid.length) {\n invalid.first().focus();\n return Promise.resolve();\n }\n\n loadingContainer.removeClass('hidden');\n this.disableButtons();\n\n var formData = this.getFormData();\n // Send the form data to the server for processing.\n return Repository.submitCreateUpdateForm(formData)\n .then(function(response) {\n if (response.validationerror) {\n // If there was a server side validation error then\n // we need to re-request the rendered form from the server\n // in order to display the error for the user.\n this.reloadBodyContent(formData);\n return;\n } else {\n // Check whether this was a new event or not.\n // The hide function unsets the form data so grab this before the hide.\n var isExisting = this.hasEventId();\n\n // No problemo! Our work here is done.\n this.hide();\n\n // Trigger the appropriate calendar event so that the view can be updated.\n if (isExisting) {\n $('body').trigger(CalendarEvents.updated, [response.event]);\n } else {\n $('body').trigger(CalendarEvents.created, [response.event]);\n }\n }\n\n return;\n }.bind(this))\n .always(function() {\n // Regardless of success or error we should always stop\n // the loading icon and re-enable the buttons.\n loadingContainer.addClass('hidden');\n this.enableButtons();\n\n return;\n }.bind(this))\n .fail(Notification.exception);\n };\n\n /**\n * Set up all of the event handling for the modal.\n *\n * @method registerEventListeners\n * @fires event:uploadStarted\n * @fires event:formSubmittedByJavascript\n */\n ModalEventForm.prototype.registerEventListeners = function() {\n // Apply parent event listeners.\n Modal.prototype.registerEventListeners.call(this);\n\n // When the user clicks the save button we trigger the form submission. We need to\n // trigger an actual submission because there is some JS code in the form that is\n // listening for this event and doing some stuff (e.g. saving draft areas etc).\n this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {\n this.getForm().submit();\n data.originalEvent.preventDefault();\n e.stopPropagation();\n }.bind(this));\n\n // Catch the submit event before it is actually processed by the browser and\n // prevent the submission. We'll take it from here.\n this.getModal().on('submit', function(e) {\n FormEvents.notifyFormSubmittedByJavascript(this.getForm()[0]);\n\n this.save();\n\n // Stop the form from actually submitting and prevent it's\n // propagation because we have already handled the event.\n e.preventDefault();\n e.stopPropagation();\n }.bind(this));\n };\n\n // Automatically register with the modal registry the first time this module is imported so that you can create modals\n // of this type using the modal factory.\n if (!registered) {\n ModalRegistry.register(ModalEventForm.TYPE, ModalEventForm, 'calendar/modal_event_form');\n registered = true;\n }\n\n return ModalEventForm;\n});\n"],"names":["define","$","FormEvents","Str","Notification","Templates","CustomEvents","Modal","ModalRegistry","Fragment","CalendarEvents","Repository","registered","SELECTORS","ModalEventForm","root","call","this","eventId","startTime","courseId","categoryId","contextId","reloadingBody","reloadingTitle","saveButton","getFooter","find","TYPE","prototype","Object","create","constructor","setContextId","id","getContextId","setCourseId","getCourseId","setCategoryId","getCategoryId","hasCourseId","hasCategoryId","setEventId","getEventId","hasEventId","setStartTime","time","getStartTime","hasStartTime","getForm","getBody","disableButtons","prop","enableButtons","reloadTitleContent","titlePromise","get_string","then","string","setTitle","bind","always","fail","exception","reloadBodyContent","formData","bodyPromise","args","eventid","starttime","courseid","categoryid","formdata","loadFragment","setBody","reloadAllContent","when","show","hide","getFormData","serialize","save","invalid","loadingContainer","length","first","focus","Promise","resolve","removeClass","submitCreateUpdateForm","response","validationerror","isExisting","trigger","updated","event","created","addClass","registerEventListeners","getModal","on","events","activate","e","data","submit","originalEvent","preventDefault","stopPropagation","notifyFormSubmittedByJavascript","register"],"mappings":"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"} \ No newline at end of file diff --git a/calendar/amd/build/selectors.min.js b/calendar/amd/build/selectors.min.js index 70fa21dea38..d7a6dfa4ab0 100644 --- a/calendar/amd/build/selectors.min.js +++ b/calendar/amd/build/selectors.min.js @@ -1,7 +1,7 @@ /** - * This module is responsible for the calendar filter. + * CSS selectors for the calendar. * - * @module core_calendar/calendar_selectors + * @module core_calendar/selectors * @copyright 2017 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/amd/build/selectors.min.js.map b/calendar/amd/build/selectors.min.js.map index 6a3984a1cfc..91f8cd0a25f 100644 --- a/calendar/amd/build/selectors.min.js.map +++ b/calendar/amd/build/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * This module is responsible for the calendar filter.\n *\n * @module core_calendar/calendar_selectors\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,iCAEjBC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB"} \ No newline at end of file +{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * CSS selectors for the calendar.\n *\n * @module core_calendar/selectors\n * @copyright 2017 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n eventFilterItem: \"[data-action='filter-event-type']\",\n eventType: {\n site: \"[data-eventtype-site]\",\n category: \"[data-eventtype-category]\",\n course: \"[data-eventtype-course]\",\n group: \"[data-eventtype-group]\",\n user: \"[data-eventtype-user]\",\n other: \"[data-eventtype-other]\",\n },\n popoverType: {\n site: \"[data-popover-eventtype-site]\",\n category: \"[data-popover-eventtype-category]\",\n course: \"[data-popover-eventtype-course]\",\n group: \"[data-popover-eventtype-group]\",\n user: \"[data-popover-eventtype-user]\",\n other: \"[data-popover-eventtype-other]\",\n },\n calendarPeriods: {\n month: \"[data-period='month']\",\n },\n courseSelector: 'select[name=\"course\"]',\n viewSelector: 'div[data-region=\"view-selector\"]',\n actions: {\n create: '[data-action=\"new-event-button\"]',\n edit: '[data-action=\"edit\"]',\n remove: '[data-action=\"delete\"]',\n viewEvent: '[data-action=\"view-event\"]',\n deleteSubscription: '[data-action=\"delete-subscription\"]',\n },\n elements: {\n courseSelector: 'select[name=\"course\"]',\n dateContainer: '.clickable.hasevent',\n dateContent: '[data-region=\"day-content\"]',\n monthDetailed: '.calendarmonth.calendartable',\n },\n today: '.today',\n day: '[data-region=\"day\"]',\n calendarMain: '[data-region=\"calendar\"]',\n wrapper: '.calendarwrapper',\n eventItem: '[data-type=\"event\"]',\n links: {\n navLink: '.calendarwrapper .arrow_link',\n eventLink: \"[data-region='event-item']\",\n miniDayLink: \"[data-region='mini-day-link']\",\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n mainCalendar: '.maincalendar .heightcontainer',\n fullCalendarView: 'page-calendar-view',\n };\n});\n"],"names":["define","eventFilterItem","eventType","site","category","course","group","user","other","popoverType","calendarPeriods","month","courseSelector","viewSelector","actions","create","edit","remove","viewEvent","deleteSubscription","elements","dateContainer","dateContent","monthDetailed","today","day","calendarMain","wrapper","eventItem","links","navLink","eventLink","miniDayLink","containers","loadingIcon","mainCalendar","fullCalendarView"],"mappings":";;;;;;;AAsBAA,iCAAO,IAAI,iBACA,CACHC,gBAAiB,oCACjBC,UAAW,CACPC,KAAM,wBACNC,SAAU,4BACVC,OAAQ,0BACRC,MAAO,yBACPC,KAAM,wBACNC,MAAO,0BAEXC,YAAa,CACTN,KAAM,gCACNC,SAAU,oCACVC,OAAQ,kCACRC,MAAO,iCACPC,KAAM,gCACNC,MAAO,kCAEXE,gBAAiB,CACbC,MAAO,yBAEXC,eAAgB,wBAChBC,aAAc,mCACdC,QAAS,CACLC,OAAQ,mCACRC,KAAM,uBACNC,OAAQ,yBACRC,UAAW,6BACXC,mBAAoB,uCAExBC,SAAU,CACNR,eAAgB,wBAChBS,cAAe,sBACfC,YAAa,8BACbC,cAAe,gCAEnBC,MAAO,SACPC,IAAK,sBACLC,aAAc,2BACdC,QAAS,mBACTC,UAAW,sBACXC,MAAO,CACHC,QAAS,+BACTC,UAAW,6BACXC,YAAa,iCAEjBC,WAAY,CACRC,YAAa,0CAEjBC,aAAc,iCACdC,iBAAkB"} \ No newline at end of file diff --git a/calendar/amd/src/calendar_view.js b/calendar/amd/src/calendar_view.js index e6e132b14c6..e2b75ebd372 100644 --- a/calendar/amd/src/calendar_view.js +++ b/calendar/amd/src/calendar_view.js @@ -16,7 +16,7 @@ /** * This module is responsible for handle calendar day and upcoming view. * - * @module core_calendar/calendar + * @module core_calendar/calendar_view * @copyright 2017 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/amd/src/modal_event_form.js b/calendar/amd/src/modal_event_form.js index 83f25de527a..b7d94a49497 100644 --- a/calendar/amd/src/modal_event_form.js +++ b/calendar/amd/src/modal_event_form.js @@ -16,7 +16,7 @@ /** * Contain the logic for the quick add or update event modal. * - * @module core_calendar/modal_quick_add_event + * @module core_calendar/modal_event_form * @copyright 2017 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/calendar/amd/src/selectors.js b/calendar/amd/src/selectors.js index 4f764e614d5..2fa6ebf591d 100644 --- a/calendar/amd/src/selectors.js +++ b/calendar/amd/src/selectors.js @@ -14,9 +14,9 @@ // along with Moodle. If not, see . /** - * This module is responsible for the calendar filter. + * CSS selectors for the calendar. * - * @module core_calendar/calendar_selectors + * @module core_calendar/selectors * @copyright 2017 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/amd/build/local/activitychooser/dialogue.min.js.map b/course/amd/build/local/activitychooser/dialogue.min.js.map index b6559fd3649..311cbac7996 100644 --- a/course/amd/build/local/activitychooser/dialogue.min.js.map +++ b/course/amd/build/local/activitychooser/dialogue.min.js.map @@ -1 +1 @@ -{"version":3,"file":"dialogue.min.js","sources":["../../../src/local/activitychooser/dialogue.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 options.\n *\n * @module core_course/local/chooser/dialogue\n * @copyright 2019 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as ModalEvents from 'core/modal_events';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport * as Templates from 'core/templates';\nimport {end, arrowLeft, arrowRight, home, enter, space} from 'core/key_codes';\nimport {addIconToContainer} from 'core/loadingicon';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport Notification from 'core/notification';\nimport {debounce} from 'core/utils';\nconst getPlugin = pluginName => import(pluginName);\n\n/**\n * Given an event from the main module 'page' navigate to it's help section via a carousel.\n *\n * @method showModuleHelp\n * @param {jQuery} carousel Our initialized carousel to manipulate\n * @param {Object} moduleData Data of the module to carousel to\n * @param {jQuery} modal We need to figure out if the current modal has a footer.\n */\nconst showModuleHelp = (carousel, moduleData, modal = null) => {\n // If we have a real footer then we need to change temporarily.\n if (modal !== null && moduleData.showFooter === true) {\n modal.setFooter(Templates.render('core_course/local/activitychooser/footer_partial', moduleData));\n }\n const help = carousel.find(selectors.regions.help)[0];\n help.innerHTML = '';\n help.classList.add('m-auto');\n\n // Add a spinner.\n const spinnerPromise = addIconToContainer(help);\n\n // Used later...\n let transitionPromiseResolver = null;\n const transitionPromise = new Promise(resolve => {\n transitionPromiseResolver = resolve;\n });\n\n // Build up the html & js ready to place into the help section.\n const contentPromise = Templates.renderForPromise('core_course/local/activitychooser/help', moduleData);\n\n // Wait for the content to be ready, and for the transition to be complet.\n Promise.all([contentPromise, spinnerPromise, transitionPromise])\n .then(([{html, js}]) => Templates.replaceNodeContents(help, html, js))\n .then(() => {\n help.querySelector(selectors.regions.chooserSummary.header).focus();\n return help;\n })\n .catch(Notification.exception);\n\n // Move to the next slide, and resolve the transition promise when it's done.\n carousel.one('slid.bs.carousel', () => {\n transitionPromiseResolver();\n });\n // Trigger the transition between 'pages'.\n carousel.carousel('next');\n};\n\n/**\n * Given a user wants to change the favourite state of a module we either add or remove the status.\n * We also propergate this change across our map of modals.\n *\n * @method manageFavouriteState\n * @param {HTMLElement} modalBody The DOM node of the modal to manipulate\n * @param {HTMLElement} caller\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n */\nconst manageFavouriteState = async(modalBody, caller, partialFavourite) => {\n const isFavourite = caller.dataset.favourited;\n const id = caller.dataset.id;\n const name = caller.dataset.name;\n const internal = caller.dataset.internal;\n // Switch on fave or not.\n if (isFavourite === 'true') {\n await Repository.unfavouriteModule(name, id);\n\n partialFavourite(internal, false, modalBody);\n } else {\n await Repository.favouriteModule(name, id);\n\n partialFavourite(internal, true, modalBody);\n }\n\n};\n\n/**\n * Register chooser related event listeners.\n *\n * @method registerListenerEvents\n * @param {Promise} modal Our modal that we are working with\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n * @param {Object} footerData Our base footer object.\n */\nconst registerListenerEvents = (modal, mappedModules, partialFavourite, footerData) => {\n const bodyClickListener = async(e) => {\n if (e.target.closest(selectors.actions.optionActions.showSummary)) {\n const carousel = $(modal.getBody()[0].querySelector(selectors.regions.carousel));\n\n const module = e.target.closest(selectors.regions.chooserOption.container);\n const moduleName = module.dataset.modname;\n const moduleData = mappedModules.get(moduleName);\n // We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.\n moduleData.showFooter = modal.hasFooterContent();\n showModuleHelp(carousel, moduleData, modal);\n }\n\n if (e.target.closest(selectors.actions.optionActions.manageFavourite)) {\n const caller = e.target.closest(selectors.actions.optionActions.manageFavourite);\n await manageFavouriteState(modal.getBody()[0], caller, partialFavourite);\n const activeSectionId = modal.getBody()[0].querySelector(selectors.elements.activetab).getAttribute(\"href\");\n const sectionChooserOptions = modal.getBody()[0]\n .querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = sectionChooserOptions\n .querySelector(selectors.regions.chooserOption.container);\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(modal.getBody()[0], mappedModules, sectionChooserOptions, modal);\n }\n\n // From the help screen go back to the module overview.\n if (e.target.matches(selectors.actions.closeOption)) {\n const carousel = $(modal.getBody()[0].querySelector(selectors.regions.carousel));\n\n // Trigger the transition between 'pages'.\n carousel.carousel('prev');\n carousel.on('slid.bs.carousel', () => {\n const allModules = modal.getBody()[0].querySelector(selectors.regions.modules);\n const caller = allModules.querySelector(selectors.regions.getModuleSelector(e.target.dataset.modname));\n caller.focus();\n });\n }\n\n // The \"clear search\" button is triggered.\n if (e.target.closest(selectors.actions.clearSearch)) {\n // Clear the entered search query in the search bar and hide the search results container.\n const searchInput = modal.getBody()[0].querySelector(selectors.actions.search);\n searchInput.value = \"\";\n searchInput.focus();\n toggleSearchResultsView(modal, mappedModules, searchInput.value);\n }\n };\n\n // We essentially have two types of footer.\n // A fake one that is handled within the template for chooser_help and then all of the stuff for\n // modal.footer. We need to ensure we know exactly what type of footer we are using so we know what we\n // need to manage. The below code handles a real footer going to a mnet carousel item.\n const footerClickListener = async(e) => {\n if (footerData.footer === true) {\n const footerjs = await getPlugin(footerData.customfooterjs);\n await footerjs.footerClickListener(e, footerData, modal);\n }\n };\n\n modal.getBodyPromise()\n\n // The return value of getBodyPromise is a jquery object containing the body NodeElement.\n .then(body => body[0])\n\n // Set up the carousel.\n .then(body => {\n $(body.querySelector(selectors.regions.carousel))\n .carousel({\n interval: false,\n pause: true,\n keyboard: false\n });\n\n return body;\n })\n\n // Add the listener for clicks on the body.\n .then(body => {\n body.addEventListener('click', bodyClickListener);\n return body;\n })\n\n // Add a listener for an input change in the activity chooser's search bar.\n .then(body => {\n const searchInput = body.querySelector(selectors.actions.search);\n // The search input is triggered.\n searchInput.addEventListener('input', debounce(() => {\n // Display the search results.\n toggleSearchResultsView(modal, mappedModules, searchInput.value);\n }, 300));\n return body;\n })\n\n // Register event listeners related to the keyboard navigation controls.\n .then(body => {\n // Get the active chooser options section.\n const activeSectionId = body.querySelector(selectors.elements.activetab).getAttribute(\"href\");\n const sectionChooserOptions = body.querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = sectionChooserOptions.querySelector(selectors.regions.chooserOption.container);\n\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(body, mappedModules, sectionChooserOptions, modal);\n\n return body;\n })\n .catch();\n\n modal.getFooterPromise()\n\n // The return value of getBodyPromise is a jquery object containing the body NodeElement.\n .then(footer => footer[0])\n // Add the listener for clicks on the footer.\n .then(footer => {\n footer.addEventListener('click', footerClickListener);\n return footer;\n })\n .catch();\n};\n\n/**\n * Initialise the keyboard navigation controls for the chooser options.\n *\n * @method initChooserOptionsKeyboardNavigation\n * @param {HTMLElement} body Our modal that we are working with\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {HTMLElement} chooserOptionsContainer The section that contains the chooser items\n * @param {Object} modal Our created modal for the section\n */\nconst initChooserOptionsKeyboardNavigation = (body, mappedModules, chooserOptionsContainer, modal = null) => {\n const chooserOptions = chooserOptionsContainer.querySelectorAll(selectors.regions.chooserOption.container);\n\n Array.from(chooserOptions).forEach((element) => {\n return element.addEventListener('keydown', (e) => {\n\n // Check for enter/ space triggers for showing the help.\n if (e.keyCode === enter || e.keyCode === space) {\n if (e.target.matches(selectors.actions.optionActions.showSummary)) {\n e.preventDefault();\n const module = e.target.closest(selectors.regions.chooserOption.container);\n const moduleName = module.dataset.modname;\n const moduleData = mappedModules.get(moduleName);\n const carousel = $(body.querySelector(selectors.regions.carousel));\n carousel.carousel({\n interval: false,\n pause: true,\n keyboard: false\n });\n\n // We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.\n moduleData.showFooter = modal.hasFooterContent();\n showModuleHelp(carousel, moduleData, modal);\n }\n }\n\n // Next.\n if (e.keyCode === arrowRight) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const nextOption = currentOption.nextElementSibling;\n const firstOption = chooserOptionsContainer.firstElementChild;\n const toFocusOption = clickErrorHandler(nextOption, firstOption);\n focusChooserOption(toFocusOption, currentOption);\n }\n\n // Previous.\n if (e.keyCode === arrowLeft) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const previousOption = currentOption.previousElementSibling;\n const lastOption = chooserOptionsContainer.lastElementChild;\n const toFocusOption = clickErrorHandler(previousOption, lastOption);\n focusChooserOption(toFocusOption, currentOption);\n }\n\n if (e.keyCode === home) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const firstOption = chooserOptionsContainer.firstElementChild;\n focusChooserOption(firstOption, currentOption);\n }\n\n if (e.keyCode === end) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const lastOption = chooserOptionsContainer.lastElementChild;\n focusChooserOption(lastOption, currentOption);\n }\n });\n });\n};\n\n/**\n * Focus on a chooser option element and remove the previous chooser element from the focus order\n *\n * @method focusChooserOption\n * @param {HTMLElement} currentChooserOption The current chooser option element that we want to focus\n * @param {HTMLElement|null} previousChooserOption The previous focused option element\n */\nconst focusChooserOption = (currentChooserOption, previousChooserOption = null) => {\n if (previousChooserOption !== null) {\n toggleFocusableChooserOption(previousChooserOption, false);\n }\n\n toggleFocusableChooserOption(currentChooserOption, true);\n currentChooserOption.focus();\n};\n\n/**\n * Add or remove a chooser option from the focus order.\n *\n * @method toggleFocusableChooserOption\n * @param {HTMLElement} chooserOption The chooser option element which should be added or removed from the focus order\n * @param {Boolean} isFocusable Whether the chooser element is focusable or not\n */\nconst toggleFocusableChooserOption = (chooserOption, isFocusable) => {\n const chooserOptionLink = chooserOption.querySelector(selectors.actions.addChooser);\n const chooserOptionHelp = chooserOption.querySelector(selectors.actions.optionActions.showSummary);\n const chooserOptionFavourite = chooserOption.querySelector(selectors.actions.optionActions.manageFavourite);\n\n if (isFocusable) {\n // Set tabindex to 0 to add current chooser option element to the focus order.\n chooserOption.tabIndex = 0;\n chooserOptionLink.tabIndex = 0;\n chooserOptionHelp.tabIndex = 0;\n chooserOptionFavourite.tabIndex = 0;\n } else {\n // Set tabindex to -1 to remove the previous chooser option element from the focus order.\n chooserOption.tabIndex = -1;\n chooserOptionLink.tabIndex = -1;\n chooserOptionHelp.tabIndex = -1;\n chooserOptionFavourite.tabIndex = -1;\n }\n};\n\n/**\n * Small error handling function to make sure the navigated to object exists\n *\n * @method clickErrorHandler\n * @param {HTMLElement} item What we want to check exists\n * @param {HTMLElement} fallback If we dont match anything fallback the focus\n * @return {HTMLElement}\n */\nconst clickErrorHandler = (item, fallback) => {\n if (item !== null) {\n return item;\n } else {\n return fallback;\n }\n};\n\n/**\n * Render the search results in a defined container\n *\n * @method renderSearchResults\n * @param {HTMLElement} searchResultsContainer The container where the data should be rendered\n * @param {Object} searchResultsData Data containing the module items that satisfy the search criteria\n */\nconst renderSearchResults = async(searchResultsContainer, searchResultsData) => {\n const templateData = {\n 'searchresultsnumber': searchResultsData.length,\n 'searchresults': searchResultsData\n };\n // Build up the html & js ready to place into the help section.\n const {html, js} = await Templates.renderForPromise('core_course/local/activitychooser/search_results', templateData);\n await Templates.replaceNodeContents(searchResultsContainer, html, js);\n};\n\n/**\n * Toggle (display/hide) the search results depending on the value of the search query\n *\n * @method toggleSearchResultsView\n * @param {Object} modal Our created modal for the section\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {String} searchQuery The search query\n */\nconst toggleSearchResultsView = async(modal, mappedModules, searchQuery) => {\n const modalBody = modal.getBody()[0];\n const searchResultsContainer = modalBody.querySelector(selectors.regions.searchResults);\n const chooserContainer = modalBody.querySelector(selectors.regions.chooser);\n const clearSearchButton = modalBody.querySelector(selectors.actions.clearSearch);\n\n if (searchQuery.length > 0) { // Search query is present.\n const searchResultsData = searchModules(mappedModules, searchQuery);\n await renderSearchResults(searchResultsContainer, searchResultsData);\n const searchResultItemsContainer = searchResultsContainer.querySelector(selectors.regions.searchResultItems);\n const firstSearchResultItem = searchResultItemsContainer.querySelector(selectors.regions.chooserOption.container);\n if (firstSearchResultItem) {\n // Set the first result item to be focusable.\n toggleFocusableChooserOption(firstSearchResultItem, true);\n // Register keyboard events on the created search result items.\n initChooserOptionsKeyboardNavigation(modalBody, mappedModules, searchResultItemsContainer, modal);\n }\n // Display the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.remove('d-none');\n // Hide the default chooser options container.\n chooserContainer.setAttribute('hidden', 'hidden');\n // Display the search results container.\n searchResultsContainer.removeAttribute('hidden');\n } else { // Search query is not present.\n // Hide the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.add('d-none');\n // Hide the search results container.\n searchResultsContainer.setAttribute('hidden', 'hidden');\n // Display the default chooser options container.\n chooserContainer.removeAttribute('hidden');\n }\n};\n\n/**\n * Return the list of modules which have a name or description that matches the given search term.\n *\n * @method searchModules\n * @param {Array} modules List of available modules\n * @param {String} searchTerm The search term to match\n * @return {Array}\n */\nconst searchModules = (modules, searchTerm) => {\n if (searchTerm === '') {\n return modules;\n }\n searchTerm = searchTerm.toLowerCase();\n const searchResults = [];\n modules.forEach((activity) => {\n const activityName = activity.title.toLowerCase();\n const activityDesc = activity.help.toLowerCase();\n if (activityName.includes(searchTerm) || activityDesc.includes(searchTerm)) {\n searchResults.push(activity);\n }\n });\n\n return searchResults;\n};\n\n/**\n * Set up our tabindex information across the chooser.\n *\n * @method setupKeyboardAccessibility\n * @param {Promise} modal Our created modal for the section\n * @param {Map} mappedModules A map of all of the built module information\n */\nconst setupKeyboardAccessibility = (modal, mappedModules) => {\n modal.getModal()[0].tabIndex = -1;\n\n modal.getBodyPromise().then(body => {\n $(selectors.elements.tab).on('shown.bs.tab', (e) => {\n const activeSectionId = e.target.getAttribute(\"href\");\n const activeSectionChooserOptions = body[0]\n .querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = activeSectionChooserOptions\n .querySelector(selectors.regions.chooserOption.container);\n const prevActiveSectionId = e.relatedTarget.getAttribute(\"href\");\n const prevActiveSectionChooserOptions = body[0]\n .querySelector(selectors.regions.getSectionChooserOptions(prevActiveSectionId));\n\n // Disable the focus of every chooser option in the previous active section.\n disableFocusAllChooserOptions(prevActiveSectionChooserOptions);\n // Enable the focus of the first chooser option in the current active section.\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(body[0], mappedModules, activeSectionChooserOptions, modal);\n });\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Disable the focus of all chooser options in a specific container (section).\n *\n * @method disableFocusAllChooserOptions\n * @param {HTMLElement} sectionChooserOptions The section that contains the chooser items\n */\nconst disableFocusAllChooserOptions = (sectionChooserOptions) => {\n const allChooserOptions = sectionChooserOptions.querySelectorAll(selectors.regions.chooserOption.container);\n allChooserOptions.forEach((chooserOption) => {\n toggleFocusableChooserOption(chooserOption, false);\n });\n};\n\n/**\n * Display the module chooser.\n *\n * @method displayChooser\n * @param {Promise} modalPromise Our created modal for the section\n * @param {Array} sectionModules An array of all of the built module information\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n * @param {Object} footerData Our base footer object.\n */\nexport const displayChooser = (modalPromise, sectionModules, partialFavourite, footerData) => {\n // Make a map so we can quickly fetch a specific module's object for either rendering or searching.\n const mappedModules = new Map();\n sectionModules.forEach((module) => {\n mappedModules.set(module.componentname + '_' + module.link, module);\n });\n\n // Register event listeners.\n modalPromise.then(modal => {\n registerListenerEvents(modal, mappedModules, partialFavourite, footerData);\n\n // We want to focus on the first chooser option element as soon as the modal is opened.\n setupKeyboardAccessibility(modal, mappedModules);\n\n // We want to focus on the action select when the dialog is closed.\n modal.getRoot().on(ModalEvents.hidden, () => {\n modal.destroy();\n });\n\n return modal;\n }).catch();\n};\n"],"names":["showModuleHelp","carousel","moduleData","modal","showFooter","setFooter","Templates","render","help","find","selectors","regions","innerHTML","classList","add","spinnerPromise","transitionPromiseResolver","transitionPromise","Promise","resolve","contentPromise","renderForPromise","all","then","_ref","html","js","replaceNodeContents","querySelector","chooserSummary","header","focus","catch","Notification","exception","one","registerListenerEvents","mappedModules","partialFavourite","footerData","bodyClickListener","async","e","target","closest","actions","optionActions","showSummary","getBody","moduleName","chooserOption","container","dataset","modname","get","hasFooterContent","manageFavourite","caller","modalBody","isFavourite","favourited","id","name","internal","Repository","unfavouriteModule","favouriteModule","manageFavouriteState","activeSectionId","elements","activetab","getAttribute","sectionChooserOptions","getSectionChooserOptions","firstChooserOption","toggleFocusableChooserOption","initChooserOptionsKeyboardNavigation","matches","closeOption","on","modules","getModuleSelector","clearSearch","searchInput","search","value","toggleSearchResultsView","footerClickListener","footer","footerjs","pluginName","customfooterjs","getBodyPromise","body","interval","pause","keyboard","addEventListener","getFooterPromise","chooserOptionsContainer","chooserOptions","querySelectorAll","Array","from","forEach","element","keyCode","enter","space","preventDefault","arrowRight","currentOption","nextOption","nextElementSibling","firstOption","firstElementChild","toFocusOption","clickErrorHandler","focusChooserOption","arrowLeft","previousOption","previousElementSibling","lastOption","lastElementChild","home","end","currentChooserOption","previousChooserOption","isFocusable","chooserOptionLink","addChooser","chooserOptionHelp","chooserOptionFavourite","tabIndex","item","fallback","searchQuery","searchResultsContainer","searchResults","chooserContainer","chooser","clearSearchButton","length","searchResultsData","searchModules","templateData","renderSearchResults","searchResultItemsContainer","searchResultItems","firstSearchResultItem","remove","setAttribute","removeAttribute","searchTerm","toLowerCase","activity","activityName","title","activityDesc","includes","push","disableFocusAllChooserOptions","modalPromise","sectionModules","Map","module","set","componentname","link","getModal","tab","activeSectionChooserOptions","prevActiveSectionId","relatedTarget","prevActiveSectionChooserOptions","setupKeyboardAccessibility","getRoot","ModalEvents","hidden","destroy"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"dialogue.min.js","sources":["../../../src/local/activitychooser/dialogue.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 options.\n *\n * @module core_course/local/activitychooser/dialogue\n * @copyright 2019 Mihail Geshoski \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport $ from 'jquery';\nimport * as ModalEvents from 'core/modal_events';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport * as Templates from 'core/templates';\nimport {end, arrowLeft, arrowRight, home, enter, space} from 'core/key_codes';\nimport {addIconToContainer} from 'core/loadingicon';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport Notification from 'core/notification';\nimport {debounce} from 'core/utils';\nconst getPlugin = pluginName => import(pluginName);\n\n/**\n * Given an event from the main module 'page' navigate to it's help section via a carousel.\n *\n * @method showModuleHelp\n * @param {jQuery} carousel Our initialized carousel to manipulate\n * @param {Object} moduleData Data of the module to carousel to\n * @param {jQuery} modal We need to figure out if the current modal has a footer.\n */\nconst showModuleHelp = (carousel, moduleData, modal = null) => {\n // If we have a real footer then we need to change temporarily.\n if (modal !== null && moduleData.showFooter === true) {\n modal.setFooter(Templates.render('core_course/local/activitychooser/footer_partial', moduleData));\n }\n const help = carousel.find(selectors.regions.help)[0];\n help.innerHTML = '';\n help.classList.add('m-auto');\n\n // Add a spinner.\n const spinnerPromise = addIconToContainer(help);\n\n // Used later...\n let transitionPromiseResolver = null;\n const transitionPromise = new Promise(resolve => {\n transitionPromiseResolver = resolve;\n });\n\n // Build up the html & js ready to place into the help section.\n const contentPromise = Templates.renderForPromise('core_course/local/activitychooser/help', moduleData);\n\n // Wait for the content to be ready, and for the transition to be complet.\n Promise.all([contentPromise, spinnerPromise, transitionPromise])\n .then(([{html, js}]) => Templates.replaceNodeContents(help, html, js))\n .then(() => {\n help.querySelector(selectors.regions.chooserSummary.header).focus();\n return help;\n })\n .catch(Notification.exception);\n\n // Move to the next slide, and resolve the transition promise when it's done.\n carousel.one('slid.bs.carousel', () => {\n transitionPromiseResolver();\n });\n // Trigger the transition between 'pages'.\n carousel.carousel('next');\n};\n\n/**\n * Given a user wants to change the favourite state of a module we either add or remove the status.\n * We also propergate this change across our map of modals.\n *\n * @method manageFavouriteState\n * @param {HTMLElement} modalBody The DOM node of the modal to manipulate\n * @param {HTMLElement} caller\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n */\nconst manageFavouriteState = async(modalBody, caller, partialFavourite) => {\n const isFavourite = caller.dataset.favourited;\n const id = caller.dataset.id;\n const name = caller.dataset.name;\n const internal = caller.dataset.internal;\n // Switch on fave or not.\n if (isFavourite === 'true') {\n await Repository.unfavouriteModule(name, id);\n\n partialFavourite(internal, false, modalBody);\n } else {\n await Repository.favouriteModule(name, id);\n\n partialFavourite(internal, true, modalBody);\n }\n\n};\n\n/**\n * Register chooser related event listeners.\n *\n * @method registerListenerEvents\n * @param {Promise} modal Our modal that we are working with\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n * @param {Object} footerData Our base footer object.\n */\nconst registerListenerEvents = (modal, mappedModules, partialFavourite, footerData) => {\n const bodyClickListener = async(e) => {\n if (e.target.closest(selectors.actions.optionActions.showSummary)) {\n const carousel = $(modal.getBody()[0].querySelector(selectors.regions.carousel));\n\n const module = e.target.closest(selectors.regions.chooserOption.container);\n const moduleName = module.dataset.modname;\n const moduleData = mappedModules.get(moduleName);\n // We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.\n moduleData.showFooter = modal.hasFooterContent();\n showModuleHelp(carousel, moduleData, modal);\n }\n\n if (e.target.closest(selectors.actions.optionActions.manageFavourite)) {\n const caller = e.target.closest(selectors.actions.optionActions.manageFavourite);\n await manageFavouriteState(modal.getBody()[0], caller, partialFavourite);\n const activeSectionId = modal.getBody()[0].querySelector(selectors.elements.activetab).getAttribute(\"href\");\n const sectionChooserOptions = modal.getBody()[0]\n .querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = sectionChooserOptions\n .querySelector(selectors.regions.chooserOption.container);\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(modal.getBody()[0], mappedModules, sectionChooserOptions, modal);\n }\n\n // From the help screen go back to the module overview.\n if (e.target.matches(selectors.actions.closeOption)) {\n const carousel = $(modal.getBody()[0].querySelector(selectors.regions.carousel));\n\n // Trigger the transition between 'pages'.\n carousel.carousel('prev');\n carousel.on('slid.bs.carousel', () => {\n const allModules = modal.getBody()[0].querySelector(selectors.regions.modules);\n const caller = allModules.querySelector(selectors.regions.getModuleSelector(e.target.dataset.modname));\n caller.focus();\n });\n }\n\n // The \"clear search\" button is triggered.\n if (e.target.closest(selectors.actions.clearSearch)) {\n // Clear the entered search query in the search bar and hide the search results container.\n const searchInput = modal.getBody()[0].querySelector(selectors.actions.search);\n searchInput.value = \"\";\n searchInput.focus();\n toggleSearchResultsView(modal, mappedModules, searchInput.value);\n }\n };\n\n // We essentially have two types of footer.\n // A fake one that is handled within the template for chooser_help and then all of the stuff for\n // modal.footer. We need to ensure we know exactly what type of footer we are using so we know what we\n // need to manage. The below code handles a real footer going to a mnet carousel item.\n const footerClickListener = async(e) => {\n if (footerData.footer === true) {\n const footerjs = await getPlugin(footerData.customfooterjs);\n await footerjs.footerClickListener(e, footerData, modal);\n }\n };\n\n modal.getBodyPromise()\n\n // The return value of getBodyPromise is a jquery object containing the body NodeElement.\n .then(body => body[0])\n\n // Set up the carousel.\n .then(body => {\n $(body.querySelector(selectors.regions.carousel))\n .carousel({\n interval: false,\n pause: true,\n keyboard: false\n });\n\n return body;\n })\n\n // Add the listener for clicks on the body.\n .then(body => {\n body.addEventListener('click', bodyClickListener);\n return body;\n })\n\n // Add a listener for an input change in the activity chooser's search bar.\n .then(body => {\n const searchInput = body.querySelector(selectors.actions.search);\n // The search input is triggered.\n searchInput.addEventListener('input', debounce(() => {\n // Display the search results.\n toggleSearchResultsView(modal, mappedModules, searchInput.value);\n }, 300));\n return body;\n })\n\n // Register event listeners related to the keyboard navigation controls.\n .then(body => {\n // Get the active chooser options section.\n const activeSectionId = body.querySelector(selectors.elements.activetab).getAttribute(\"href\");\n const sectionChooserOptions = body.querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = sectionChooserOptions.querySelector(selectors.regions.chooserOption.container);\n\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(body, mappedModules, sectionChooserOptions, modal);\n\n return body;\n })\n .catch();\n\n modal.getFooterPromise()\n\n // The return value of getBodyPromise is a jquery object containing the body NodeElement.\n .then(footer => footer[0])\n // Add the listener for clicks on the footer.\n .then(footer => {\n footer.addEventListener('click', footerClickListener);\n return footer;\n })\n .catch();\n};\n\n/**\n * Initialise the keyboard navigation controls for the chooser options.\n *\n * @method initChooserOptionsKeyboardNavigation\n * @param {HTMLElement} body Our modal that we are working with\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {HTMLElement} chooserOptionsContainer The section that contains the chooser items\n * @param {Object} modal Our created modal for the section\n */\nconst initChooserOptionsKeyboardNavigation = (body, mappedModules, chooserOptionsContainer, modal = null) => {\n const chooserOptions = chooserOptionsContainer.querySelectorAll(selectors.regions.chooserOption.container);\n\n Array.from(chooserOptions).forEach((element) => {\n return element.addEventListener('keydown', (e) => {\n\n // Check for enter/ space triggers for showing the help.\n if (e.keyCode === enter || e.keyCode === space) {\n if (e.target.matches(selectors.actions.optionActions.showSummary)) {\n e.preventDefault();\n const module = e.target.closest(selectors.regions.chooserOption.container);\n const moduleName = module.dataset.modname;\n const moduleData = mappedModules.get(moduleName);\n const carousel = $(body.querySelector(selectors.regions.carousel));\n carousel.carousel({\n interval: false,\n pause: true,\n keyboard: false\n });\n\n // We need to know if the overall modal has a footer so we know when to show a real / vs fake footer.\n moduleData.showFooter = modal.hasFooterContent();\n showModuleHelp(carousel, moduleData, modal);\n }\n }\n\n // Next.\n if (e.keyCode === arrowRight) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const nextOption = currentOption.nextElementSibling;\n const firstOption = chooserOptionsContainer.firstElementChild;\n const toFocusOption = clickErrorHandler(nextOption, firstOption);\n focusChooserOption(toFocusOption, currentOption);\n }\n\n // Previous.\n if (e.keyCode === arrowLeft) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const previousOption = currentOption.previousElementSibling;\n const lastOption = chooserOptionsContainer.lastElementChild;\n const toFocusOption = clickErrorHandler(previousOption, lastOption);\n focusChooserOption(toFocusOption, currentOption);\n }\n\n if (e.keyCode === home) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const firstOption = chooserOptionsContainer.firstElementChild;\n focusChooserOption(firstOption, currentOption);\n }\n\n if (e.keyCode === end) {\n e.preventDefault();\n const currentOption = e.target.closest(selectors.regions.chooserOption.container);\n const lastOption = chooserOptionsContainer.lastElementChild;\n focusChooserOption(lastOption, currentOption);\n }\n });\n });\n};\n\n/**\n * Focus on a chooser option element and remove the previous chooser element from the focus order\n *\n * @method focusChooserOption\n * @param {HTMLElement} currentChooserOption The current chooser option element that we want to focus\n * @param {HTMLElement|null} previousChooserOption The previous focused option element\n */\nconst focusChooserOption = (currentChooserOption, previousChooserOption = null) => {\n if (previousChooserOption !== null) {\n toggleFocusableChooserOption(previousChooserOption, false);\n }\n\n toggleFocusableChooserOption(currentChooserOption, true);\n currentChooserOption.focus();\n};\n\n/**\n * Add or remove a chooser option from the focus order.\n *\n * @method toggleFocusableChooserOption\n * @param {HTMLElement} chooserOption The chooser option element which should be added or removed from the focus order\n * @param {Boolean} isFocusable Whether the chooser element is focusable or not\n */\nconst toggleFocusableChooserOption = (chooserOption, isFocusable) => {\n const chooserOptionLink = chooserOption.querySelector(selectors.actions.addChooser);\n const chooserOptionHelp = chooserOption.querySelector(selectors.actions.optionActions.showSummary);\n const chooserOptionFavourite = chooserOption.querySelector(selectors.actions.optionActions.manageFavourite);\n\n if (isFocusable) {\n // Set tabindex to 0 to add current chooser option element to the focus order.\n chooserOption.tabIndex = 0;\n chooserOptionLink.tabIndex = 0;\n chooserOptionHelp.tabIndex = 0;\n chooserOptionFavourite.tabIndex = 0;\n } else {\n // Set tabindex to -1 to remove the previous chooser option element from the focus order.\n chooserOption.tabIndex = -1;\n chooserOptionLink.tabIndex = -1;\n chooserOptionHelp.tabIndex = -1;\n chooserOptionFavourite.tabIndex = -1;\n }\n};\n\n/**\n * Small error handling function to make sure the navigated to object exists\n *\n * @method clickErrorHandler\n * @param {HTMLElement} item What we want to check exists\n * @param {HTMLElement} fallback If we dont match anything fallback the focus\n * @return {HTMLElement}\n */\nconst clickErrorHandler = (item, fallback) => {\n if (item !== null) {\n return item;\n } else {\n return fallback;\n }\n};\n\n/**\n * Render the search results in a defined container\n *\n * @method renderSearchResults\n * @param {HTMLElement} searchResultsContainer The container where the data should be rendered\n * @param {Object} searchResultsData Data containing the module items that satisfy the search criteria\n */\nconst renderSearchResults = async(searchResultsContainer, searchResultsData) => {\n const templateData = {\n 'searchresultsnumber': searchResultsData.length,\n 'searchresults': searchResultsData\n };\n // Build up the html & js ready to place into the help section.\n const {html, js} = await Templates.renderForPromise('core_course/local/activitychooser/search_results', templateData);\n await Templates.replaceNodeContents(searchResultsContainer, html, js);\n};\n\n/**\n * Toggle (display/hide) the search results depending on the value of the search query\n *\n * @method toggleSearchResultsView\n * @param {Object} modal Our created modal for the section\n * @param {Map} mappedModules A map of all of the modules we are working with with K: mod_name V: {Object}\n * @param {String} searchQuery The search query\n */\nconst toggleSearchResultsView = async(modal, mappedModules, searchQuery) => {\n const modalBody = modal.getBody()[0];\n const searchResultsContainer = modalBody.querySelector(selectors.regions.searchResults);\n const chooserContainer = modalBody.querySelector(selectors.regions.chooser);\n const clearSearchButton = modalBody.querySelector(selectors.actions.clearSearch);\n\n if (searchQuery.length > 0) { // Search query is present.\n const searchResultsData = searchModules(mappedModules, searchQuery);\n await renderSearchResults(searchResultsContainer, searchResultsData);\n const searchResultItemsContainer = searchResultsContainer.querySelector(selectors.regions.searchResultItems);\n const firstSearchResultItem = searchResultItemsContainer.querySelector(selectors.regions.chooserOption.container);\n if (firstSearchResultItem) {\n // Set the first result item to be focusable.\n toggleFocusableChooserOption(firstSearchResultItem, true);\n // Register keyboard events on the created search result items.\n initChooserOptionsKeyboardNavigation(modalBody, mappedModules, searchResultItemsContainer, modal);\n }\n // Display the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.remove('d-none');\n // Hide the default chooser options container.\n chooserContainer.setAttribute('hidden', 'hidden');\n // Display the search results container.\n searchResultsContainer.removeAttribute('hidden');\n } else { // Search query is not present.\n // Hide the \"clear\" search button in the activity chooser search bar.\n clearSearchButton.classList.add('d-none');\n // Hide the search results container.\n searchResultsContainer.setAttribute('hidden', 'hidden');\n // Display the default chooser options container.\n chooserContainer.removeAttribute('hidden');\n }\n};\n\n/**\n * Return the list of modules which have a name or description that matches the given search term.\n *\n * @method searchModules\n * @param {Array} modules List of available modules\n * @param {String} searchTerm The search term to match\n * @return {Array}\n */\nconst searchModules = (modules, searchTerm) => {\n if (searchTerm === '') {\n return modules;\n }\n searchTerm = searchTerm.toLowerCase();\n const searchResults = [];\n modules.forEach((activity) => {\n const activityName = activity.title.toLowerCase();\n const activityDesc = activity.help.toLowerCase();\n if (activityName.includes(searchTerm) || activityDesc.includes(searchTerm)) {\n searchResults.push(activity);\n }\n });\n\n return searchResults;\n};\n\n/**\n * Set up our tabindex information across the chooser.\n *\n * @method setupKeyboardAccessibility\n * @param {Promise} modal Our created modal for the section\n * @param {Map} mappedModules A map of all of the built module information\n */\nconst setupKeyboardAccessibility = (modal, mappedModules) => {\n modal.getModal()[0].tabIndex = -1;\n\n modal.getBodyPromise().then(body => {\n $(selectors.elements.tab).on('shown.bs.tab', (e) => {\n const activeSectionId = e.target.getAttribute(\"href\");\n const activeSectionChooserOptions = body[0]\n .querySelector(selectors.regions.getSectionChooserOptions(activeSectionId));\n const firstChooserOption = activeSectionChooserOptions\n .querySelector(selectors.regions.chooserOption.container);\n const prevActiveSectionId = e.relatedTarget.getAttribute(\"href\");\n const prevActiveSectionChooserOptions = body[0]\n .querySelector(selectors.regions.getSectionChooserOptions(prevActiveSectionId));\n\n // Disable the focus of every chooser option in the previous active section.\n disableFocusAllChooserOptions(prevActiveSectionChooserOptions);\n // Enable the focus of the first chooser option in the current active section.\n toggleFocusableChooserOption(firstChooserOption, true);\n initChooserOptionsKeyboardNavigation(body[0], mappedModules, activeSectionChooserOptions, modal);\n });\n return;\n }).catch(Notification.exception);\n};\n\n/**\n * Disable the focus of all chooser options in a specific container (section).\n *\n * @method disableFocusAllChooserOptions\n * @param {HTMLElement} sectionChooserOptions The section that contains the chooser items\n */\nconst disableFocusAllChooserOptions = (sectionChooserOptions) => {\n const allChooserOptions = sectionChooserOptions.querySelectorAll(selectors.regions.chooserOption.container);\n allChooserOptions.forEach((chooserOption) => {\n toggleFocusableChooserOption(chooserOption, false);\n });\n};\n\n/**\n * Display the module chooser.\n *\n * @method displayChooser\n * @param {Promise} modalPromise Our created modal for the section\n * @param {Array} sectionModules An array of all of the built module information\n * @param {Function} partialFavourite Partially applied function we need to manage favourite status\n * @param {Object} footerData Our base footer object.\n */\nexport const displayChooser = (modalPromise, sectionModules, partialFavourite, footerData) => {\n // Make a map so we can quickly fetch a specific module's object for either rendering or searching.\n const mappedModules = new Map();\n sectionModules.forEach((module) => {\n mappedModules.set(module.componentname + '_' + module.link, module);\n });\n\n // Register event listeners.\n modalPromise.then(modal => {\n registerListenerEvents(modal, mappedModules, partialFavourite, footerData);\n\n // We want to focus on the first chooser option element as soon as the modal is opened.\n setupKeyboardAccessibility(modal, mappedModules);\n\n // We want to focus on the action select when the dialog is closed.\n modal.getRoot().on(ModalEvents.hidden, () => {\n modal.destroy();\n });\n\n return modal;\n }).catch();\n};\n"],"names":["showModuleHelp","carousel","moduleData","modal","showFooter","setFooter","Templates","render","help","find","selectors","regions","innerHTML","classList","add","spinnerPromise","transitionPromiseResolver","transitionPromise","Promise","resolve","contentPromise","renderForPromise","all","then","_ref","html","js","replaceNodeContents","querySelector","chooserSummary","header","focus","catch","Notification","exception","one","registerListenerEvents","mappedModules","partialFavourite","footerData","bodyClickListener","async","e","target","closest","actions","optionActions","showSummary","getBody","moduleName","chooserOption","container","dataset","modname","get","hasFooterContent","manageFavourite","caller","modalBody","isFavourite","favourited","id","name","internal","Repository","unfavouriteModule","favouriteModule","manageFavouriteState","activeSectionId","elements","activetab","getAttribute","sectionChooserOptions","getSectionChooserOptions","firstChooserOption","toggleFocusableChooserOption","initChooserOptionsKeyboardNavigation","matches","closeOption","on","modules","getModuleSelector","clearSearch","searchInput","search","value","toggleSearchResultsView","footerClickListener","footer","footerjs","pluginName","customfooterjs","getBodyPromise","body","interval","pause","keyboard","addEventListener","getFooterPromise","chooserOptionsContainer","chooserOptions","querySelectorAll","Array","from","forEach","element","keyCode","enter","space","preventDefault","arrowRight","currentOption","nextOption","nextElementSibling","firstOption","firstElementChild","toFocusOption","clickErrorHandler","focusChooserOption","arrowLeft","previousOption","previousElementSibling","lastOption","lastElementChild","home","end","currentChooserOption","previousChooserOption","isFocusable","chooserOptionLink","addChooser","chooserOptionHelp","chooserOptionFavourite","tabIndex","item","fallback","searchQuery","searchResultsContainer","searchResults","chooserContainer","chooser","clearSearchButton","length","searchResultsData","searchModules","templateData","renderSearchResults","searchResultItemsContainer","searchResultItems","firstSearchResultItem","remove","setAttribute","removeAttribute","searchTerm","toLowerCase","activity","activityName","title","activityDesc","includes","push","disableFocusAllChooserOptions","modalPromise","sectionModules","Map","module","set","componentname","link","getModal","tab","activeSectionChooserOptions","prevActiveSectionId","relatedTarget","prevActiveSectionChooserOptions","setupKeyboardAccessibility","getRoot","ModalEvents","hidden","destroy"],"mappings":"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"} \ No newline at end of file diff --git a/course/amd/build/local/activitychooser/repository.min.js b/course/amd/build/local/activitychooser/repository.min.js index b2bc69e822d..3f0e7a585ea 100644 --- a/course/amd/build/local/activitychooser/repository.min.js +++ b/course/amd/build/local/activitychooser/repository.min.js @@ -1,7 +1,8 @@ define("core_course/local/activitychooser/repository",["exports","core/ajax"],(function(_exports,_ajax){var obj; /** + * A javascript module to handle user AJAX actions. * - * @module core_course/repository + * @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.unfavouriteModule=_exports.fetchFooterData=_exports.favouriteModule=_exports.activityModules=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.activityModules=courseid=>{const request={methodname:"core_course_get_course_content_items",args:{courseid:courseid}};return _ajax.default.call([request])[0]};_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]};_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]};_exports.fetchFooterData=(courseid,sectionid)=>{const request={methodname:"core_course_get_activity_chooser_footer",args:{courseid:courseid,sectionid:sectionid}};return _ajax.default.call([request])[0]}})); diff --git a/course/amd/build/local/activitychooser/repository.min.js.map b/course/amd/build/local/activitychooser/repository.min.js.map index b00bd661f92..e0ff7b00090 100644 --- a/course/amd/build/local/activitychooser/repository.min.js.map +++ b/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 *\n * @module core_course/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/**\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 * @return {object} jQuery promise\n */\nexport const activityModules = (courseid) => {\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\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 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 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 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 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"],"names":["courseid","request","methodname","args","ajax","call","modName","modID","componentname","contentitemid","sectionid"],"mappings":";;;;;;uPA8BgCA,iBACtBC,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFH,SAAUA,kBAGXI,cAAKC,KAAK,CAACJ,UAAU,6BAYD,CAACK,QAASC,eAC/BN,QAAU,CACZC,WAAY,kDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAGhBH,cAAKC,KAAK,CAACJ,UAAU,+BAYC,CAACK,QAASC,eACjCN,QAAU,CACZC,WAAY,uDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAGhBH,cAAKC,KAAK,CAACJ,UAAU,6BAWD,CAACD,SAAUU,mBAChCT,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFH,SAAUA,SACVU,UAAWA,mBAGZN,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';\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 * @return {object} jQuery promise\n */\nexport const activityModules = (courseid) => {\n const request = {\n methodname: 'core_course_get_course_content_items',\n args: {\n courseid: courseid,\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 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 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 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 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"],"names":["courseid","request","methodname","args","ajax","call","modName","modID","componentname","contentitemid","sectionid"],"mappings":";;;;;;;uPA+BgCA,iBACtBC,QAAU,CACZC,WAAY,uCACZC,KAAM,CACFH,SAAUA,kBAGXI,cAAKC,KAAK,CAACJ,UAAU,6BAYD,CAACK,QAASC,eAC/BN,QAAU,CACZC,WAAY,kDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAGhBH,cAAKC,KAAK,CAACJ,UAAU,+BAYC,CAACK,QAASC,eACjCN,QAAU,CACZC,WAAY,uDACZC,KAAM,CACFK,cAAeF,QACfG,cAAeF,eAGhBH,cAAKC,KAAK,CAACJ,UAAU,6BAWD,CAACD,SAAUU,mBAChCT,QAAU,CACZC,WAAY,0CACZC,KAAM,CACFH,SAAUA,SACVU,UAAWA,mBAGZN,cAAKC,KAAK,CAACJ,UAAU"} \ No newline at end of file diff --git a/course/amd/build/local/activitychooser/selectors.min.js b/course/amd/build/local/activitychooser/selectors.min.js index 632a5555397..816c5408f1a 100644 --- a/course/amd/build/local/activitychooser/selectors.min.js +++ b/course/amd/build/local/activitychooser/selectors.min.js @@ -2,7 +2,7 @@ define("core_course/local/activitychooser/selectors",["exports"],(function(_expo /** * Define all of the selectors we will be using on the grading interface. * - * @module core_course/local/chooser/selectors + * @module core_course/local/activitychooser/selectors * @copyright 2019 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/amd/build/local/activitychooser/selectors.min.js.map b/course/amd/build/local/activitychooser/selectors.min.js.map index 881518c03be..7f87df306d2 100644 --- a/course/amd/build/local/activitychooser/selectors.min.js.map +++ b/course/amd/build/local/activitychooser/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectors.min.js","sources":["../../../src/local/activitychooser/selectors.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 * Define all of the selectors we will be using on the grading interface.\n *\n * @module core_course/local/chooser/selectors\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n regions: {\n chooser: getDataSelector('region', 'chooser-container'),\n getSectionChooserOptions: containerid => `${containerid} ${getDataSelector('region', 'chooser-options-container')}`,\n chooserOption: {\n container: getDataSelector('region', 'chooser-option-container'),\n actions: getDataSelector('region', 'chooser-option-actions-container'),\n info: getDataSelector('region', 'chooser-option-info-container'),\n },\n chooserSummary: {\n container: getDataSelector('region', 'chooser-option-summary-container'),\n content: getDataSelector('region', 'chooser-option-summary-content-container'),\n header: getDataSelector('region', 'summary-header'),\n actions: getDataSelector('region', 'chooser-option-summary-actions-container'),\n },\n carousel: getDataSelector('region', 'carousel'),\n help: getDataSelector('region', 'help'),\n modules: getDataSelector('region', 'modules'),\n favouriteTabNav: getDataSelector('region', 'favourite-tab-nav'),\n defaultTabNav: getDataSelector('region', 'default-tab-nav'),\n activityTabNav: getDataSelector('region', 'activity-tab-nav'),\n favouriteTab: getDataSelector('region', 'favourites'),\n recommendedTab: getDataSelector('region', 'recommended'),\n defaultTab: getDataSelector('region', 'default'),\n activityTab: getDataSelector('region', 'activity'),\n resourceTab: getDataSelector('region', 'resources'),\n getModuleSelector: modname => `[role=\"menuitem\"][data-modname=\"${modname}\"]`,\n searchResults: getDataSelector('region', 'search-results-container'),\n searchResultItems: getDataSelector('region', 'search-result-items-container'),\n },\n actions: {\n optionActions: {\n showSummary: getDataSelector('action', 'show-option-summary'),\n manageFavourite: getDataSelector('action', 'manage-module-favourite'),\n },\n addChooser: getDataSelector('action', 'add-chooser-option'),\n closeOption: getDataSelector('action', 'close-chooser-option-summary'),\n hide: getDataSelector('action', 'hide'),\n search: getDataSelector('action', 'search'),\n clearSearch: getDataSelector('action', 'clearsearch'),\n },\n render: {\n favourites: getDataSelector('render', 'favourites-area'),\n },\n elements: {\n section: '.section',\n sectionmodchooser: 'button.section-modchooser-link',\n sitemenu: '.block_site_main_menu',\n sitetopic: 'div.sitetopic',\n tab: 'a[data-toggle=\"tab\"]',\n activetab: 'a[data-toggle=\"tab\"][aria-selected=\"true\"]',\n visibletabs: 'a[data-toggle=\"tab\"]:not(.d-none)'\n },\n};\n"],"names":["getDataSelector","name","value","regions","chooser","getSectionChooserOptions","containerid","chooserOption","container","actions","info","chooserSummary","content","header","carousel","help","modules","favouriteTabNav","defaultTabNav","activityTabNav","favouriteTab","recommendedTab","defaultTab","activityTab","resourceTab","getModuleSelector","modname","searchResults","searchResultItems","optionActions","showSummary","manageFavourite","addChooser","closeOption","hide","search","clearSearch","render","favourites","elements","section","sectionmodchooser","sitemenu","sitetopic","tab","activetab","visibletabs"],"mappings":";;;;;;;;MA8BMA,gBAAkB,CAACC,KAAMC,wBACXD,kBAASC,yBAGd,CACXC,QAAS,CACLC,QAASJ,gBAAgB,SAAU,qBACnCK,yBAA0BC,uBAAkBA,wBAAeN,gBAAgB,SAAU,8BACrFO,cAAe,CACXC,UAAWR,gBAAgB,SAAU,4BACrCS,QAAST,gBAAgB,SAAU,oCACnCU,KAAMV,gBAAgB,SAAU,kCAEpCW,eAAgB,CACZH,UAAWR,gBAAgB,SAAU,oCACrCY,QAASZ,gBAAgB,SAAU,4CACnCa,OAAQb,gBAAgB,SAAU,kBAClCS,QAAST,gBAAgB,SAAU,6CAEvCc,SAAUd,gBAAgB,SAAU,YACpCe,KAAMf,gBAAgB,SAAU,QAChCgB,QAAShB,gBAAgB,SAAU,WACnCiB,gBAAiBjB,gBAAgB,SAAU,qBAC3CkB,cAAelB,gBAAgB,SAAU,mBACzCmB,eAAgBnB,gBAAgB,SAAU,oBAC1CoB,aAAcpB,gBAAgB,SAAU,cACxCqB,eAAgBrB,gBAAgB,SAAU,eAC1CsB,WAAYtB,gBAAgB,SAAU,WACtCuB,YAAavB,gBAAgB,SAAU,YACvCwB,YAAaxB,gBAAgB,SAAU,aACvCyB,kBAAmBC,mDAA8CA,cACjEC,cAAe3B,gBAAgB,SAAU,4BACzC4B,kBAAmB5B,gBAAgB,SAAU,kCAEjDS,QAAS,CACLoB,cAAe,CACXC,YAAa9B,gBAAgB,SAAU,uBACvC+B,gBAAiB/B,gBAAgB,SAAU,4BAE/CgC,WAAYhC,gBAAgB,SAAU,sBACtCiC,YAAajC,gBAAgB,SAAU,gCACvCkC,KAAMlC,gBAAgB,SAAU,QAChCmC,OAAQnC,gBAAgB,SAAU,UAClCoC,YAAapC,gBAAgB,SAAU,gBAE3CqC,OAAQ,CACJC,WAAYtC,gBAAgB,SAAU,oBAE1CuC,SAAU,CACNC,QAAS,WACTC,kBAAmB,iCACnBC,SAAU,wBACVC,UAAW,gBACXC,IAAK,uBACLC,UAAW,6CACXC,YAAa"} \ No newline at end of file +{"version":3,"file":"selectors.min.js","sources":["../../../src/local/activitychooser/selectors.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 * Define all of the selectors we will be using on the grading interface.\n *\n * @module core_course/local/activitychooser/selectors\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n regions: {\n chooser: getDataSelector('region', 'chooser-container'),\n getSectionChooserOptions: containerid => `${containerid} ${getDataSelector('region', 'chooser-options-container')}`,\n chooserOption: {\n container: getDataSelector('region', 'chooser-option-container'),\n actions: getDataSelector('region', 'chooser-option-actions-container'),\n info: getDataSelector('region', 'chooser-option-info-container'),\n },\n chooserSummary: {\n container: getDataSelector('region', 'chooser-option-summary-container'),\n content: getDataSelector('region', 'chooser-option-summary-content-container'),\n header: getDataSelector('region', 'summary-header'),\n actions: getDataSelector('region', 'chooser-option-summary-actions-container'),\n },\n carousel: getDataSelector('region', 'carousel'),\n help: getDataSelector('region', 'help'),\n modules: getDataSelector('region', 'modules'),\n favouriteTabNav: getDataSelector('region', 'favourite-tab-nav'),\n defaultTabNav: getDataSelector('region', 'default-tab-nav'),\n activityTabNav: getDataSelector('region', 'activity-tab-nav'),\n favouriteTab: getDataSelector('region', 'favourites'),\n recommendedTab: getDataSelector('region', 'recommended'),\n defaultTab: getDataSelector('region', 'default'),\n activityTab: getDataSelector('region', 'activity'),\n resourceTab: getDataSelector('region', 'resources'),\n getModuleSelector: modname => `[role=\"menuitem\"][data-modname=\"${modname}\"]`,\n searchResults: getDataSelector('region', 'search-results-container'),\n searchResultItems: getDataSelector('region', 'search-result-items-container'),\n },\n actions: {\n optionActions: {\n showSummary: getDataSelector('action', 'show-option-summary'),\n manageFavourite: getDataSelector('action', 'manage-module-favourite'),\n },\n addChooser: getDataSelector('action', 'add-chooser-option'),\n closeOption: getDataSelector('action', 'close-chooser-option-summary'),\n hide: getDataSelector('action', 'hide'),\n search: getDataSelector('action', 'search'),\n clearSearch: getDataSelector('action', 'clearsearch'),\n },\n render: {\n favourites: getDataSelector('render', 'favourites-area'),\n },\n elements: {\n section: '.section',\n sectionmodchooser: 'button.section-modchooser-link',\n sitemenu: '.block_site_main_menu',\n sitetopic: 'div.sitetopic',\n tab: 'a[data-toggle=\"tab\"]',\n activetab: 'a[data-toggle=\"tab\"][aria-selected=\"true\"]',\n visibletabs: 'a[data-toggle=\"tab\"]:not(.d-none)'\n },\n};\n"],"names":["getDataSelector","name","value","regions","chooser","getSectionChooserOptions","containerid","chooserOption","container","actions","info","chooserSummary","content","header","carousel","help","modules","favouriteTabNav","defaultTabNav","activityTabNav","favouriteTab","recommendedTab","defaultTab","activityTab","resourceTab","getModuleSelector","modname","searchResults","searchResultItems","optionActions","showSummary","manageFavourite","addChooser","closeOption","hide","search","clearSearch","render","favourites","elements","section","sectionmodchooser","sitemenu","sitetopic","tab","activetab","visibletabs"],"mappings":";;;;;;;;MA8BMA,gBAAkB,CAACC,KAAMC,wBACXD,kBAASC,yBAGd,CACXC,QAAS,CACLC,QAASJ,gBAAgB,SAAU,qBACnCK,yBAA0BC,uBAAkBA,wBAAeN,gBAAgB,SAAU,8BACrFO,cAAe,CACXC,UAAWR,gBAAgB,SAAU,4BACrCS,QAAST,gBAAgB,SAAU,oCACnCU,KAAMV,gBAAgB,SAAU,kCAEpCW,eAAgB,CACZH,UAAWR,gBAAgB,SAAU,oCACrCY,QAASZ,gBAAgB,SAAU,4CACnCa,OAAQb,gBAAgB,SAAU,kBAClCS,QAAST,gBAAgB,SAAU,6CAEvCc,SAAUd,gBAAgB,SAAU,YACpCe,KAAMf,gBAAgB,SAAU,QAChCgB,QAAShB,gBAAgB,SAAU,WACnCiB,gBAAiBjB,gBAAgB,SAAU,qBAC3CkB,cAAelB,gBAAgB,SAAU,mBACzCmB,eAAgBnB,gBAAgB,SAAU,oBAC1CoB,aAAcpB,gBAAgB,SAAU,cACxCqB,eAAgBrB,gBAAgB,SAAU,eAC1CsB,WAAYtB,gBAAgB,SAAU,WACtCuB,YAAavB,gBAAgB,SAAU,YACvCwB,YAAaxB,gBAAgB,SAAU,aACvCyB,kBAAmBC,mDAA8CA,cACjEC,cAAe3B,gBAAgB,SAAU,4BACzC4B,kBAAmB5B,gBAAgB,SAAU,kCAEjDS,QAAS,CACLoB,cAAe,CACXC,YAAa9B,gBAAgB,SAAU,uBACvC+B,gBAAiB/B,gBAAgB,SAAU,4BAE/CgC,WAAYhC,gBAAgB,SAAU,sBACtCiC,YAAajC,gBAAgB,SAAU,gCACvCkC,KAAMlC,gBAAgB,SAAU,QAChCmC,OAAQnC,gBAAgB,SAAU,UAClCoC,YAAapC,gBAAgB,SAAU,gBAE3CqC,OAAQ,CACJC,WAAYtC,gBAAgB,SAAU,oBAE1CuC,SAAU,CACNC,QAAS,WACTC,kBAAmB,iCACnBC,SAAU,wBACVC,UAAW,gBACXC,IAAK,uBACLC,UAAW,6CACXC,YAAa"} \ No newline at end of file diff --git a/course/amd/src/local/activitychooser/dialogue.js b/course/amd/src/local/activitychooser/dialogue.js index 688c2a4922c..433469a1387 100644 --- a/course/amd/src/local/activitychooser/dialogue.js +++ b/course/amd/src/local/activitychooser/dialogue.js @@ -16,7 +16,7 @@ /** * A type of dialogue used as for choosing options. * - * @module core_course/local/chooser/dialogue + * @module core_course/local/activitychooser/dialogue * @copyright 2019 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/amd/src/local/activitychooser/repository.js b/course/amd/src/local/activitychooser/repository.js index 519357af63a..bc841cd19d2 100644 --- a/course/amd/src/local/activitychooser/repository.js +++ b/course/amd/src/local/activitychooser/repository.js @@ -14,8 +14,9 @@ // along with Moodle. If not, see . /** + * A javascript module to handle user AJAX actions. * - * @module core_course/repository + * @module core_course/local/activitychooser/repository * @copyright 2019 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/amd/src/local/activitychooser/selectors.js b/course/amd/src/local/activitychooser/selectors.js index ceedc44a9ac..d40410183c4 100644 --- a/course/amd/src/local/activitychooser/selectors.js +++ b/course/amd/src/local/activitychooser/selectors.js @@ -16,7 +16,7 @@ /** * Define all of the selectors we will be using on the grading interface. * - * @module core_course/local/chooser/selectors + * @module core_course/local/activitychooser/selectors * @copyright 2019 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/format/amd/build/local/courseeditor/contenttree.min.js b/course/format/amd/build/local/courseeditor/contenttree.min.js index dde6bbae941..9b937c49e49 100644 --- a/course/format/amd/build/local/courseeditor/contenttree.min.js +++ b/course/format/amd/build/local/courseeditor/contenttree.min.js @@ -6,8 +6,8 @@ define("core_courseformat/local/courseeditor/contenttree",["exports","jquery","c * all keybindings and logic is compatible. This class translate the primitive opetations * to a bootstrap collapsible structure. * - * @module core_courseformat/local/courseindex/keyboardnav - * @class core_courseformat/local/courseindex/keyboardnav + * @module core_courseformat/local/courseeditor/contenttree + * @class core_courseformat/local/courseeditor/contenttree * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_jquery=_interopRequireDefault(_jquery),_tree=_interopRequireDefault(_tree);class _default extends _tree.default{constructor(mainElement,selectors,preventcache){var _selectors$ENTER;super(mainElement),this.selectors={SECTION:selectors.SECTION,TOGGLER:selectors.TOGGLER,COLLAPSE:selectors.COLLAPSE,ENTER:null!==(_selectors$ENTER=selectors.ENTER)&&void 0!==_selectors$ENTER?_selectors$ENTER:selectors.TOGGLER},preventcache&&(this._getVisibleItems=this.getVisibleItems,this.getVisibleItems=()=>(this.refreshVisibleItemsCache(),this._getVisibleItems())),this.treeRoot.on("hidden.bs.collapse shown.bs.collapse",(()=>{this.refreshVisibleItemsCache()})),this.registerEnterCallback(this.enterCallback.bind(this))}getActiveItem(){const activeItem=this.treeRoot.data("activeItem");if(activeItem)return(0,_normalise.getList)(activeItem)[0]}enterCallback(jQueryItem){const item=(0,_normalise.getList)(jQueryItem)[0];if(this.isGroupItem(jQueryItem)){const enter=item.querySelector(this.selectors.ENTER);"#"!==enter.getAttribute("href")&&(window.location.href=enter.getAttribute("href")),enter.click()}else{const link=item.querySelector("a");"#"!==link.getAttribute("href")?window.location.href=link.getAttribute("href"):link.click()}}handleItemClick(event,jQueryItem){event.target.closest(this.selectors.COLLAPSE)?super.handleItemClick(event,jQueryItem):(jQueryItem.focus(),this.isGroupItem(jQueryItem)&&this.expandGroup(jQueryItem))}isGroupCollapsed(jQueryItem){return"false"===(0,_normalise.getList)(jQueryItem)[0].querySelector("[aria-expanded]").getAttribute("aria-expanded")}toggleGroup(item){var _toggler$data;const toggler=item.find(this.selectors.COLLAPSE);let collapsibleId=null!==(_toggler$data=toggler.data("target"))&&void 0!==_toggler$data?_toggler$data:toggler.attr("href");if(!collapsibleId)return;collapsibleId=collapsibleId.replace("#","");(0,_jquery.default)("#".concat(collapsibleId)).length&&(0,_jquery.default)("#".concat(collapsibleId)).collapse("toggle")}expandGroup(item){this.isGroupCollapsed(item)&&this.toggleGroup(item)}collapseGroup(item){this.isGroupCollapsed(item)||this.toggleGroup(item)}expandAllGroups(){(0,_normalise.getList)(this.treeRoot)[0].querySelectorAll(this.selectors.SECTION).forEach((item=>{this.expandGroup((0,_jquery.default)(item))}))}}return _exports.default=_default,_exports.default})); diff --git a/course/format/amd/build/local/courseeditor/contenttree.min.js.map b/course/format/amd/build/local/courseeditor/contenttree.min.js.map index d9d0ac85493..1196bd4aa47 100644 --- a/course/format/amd/build/local/courseeditor/contenttree.min.js.map +++ b/course/format/amd/build/local/courseeditor/contenttree.min.js.map @@ -1 +1 @@ -{"version":3,"file":"contenttree.min.js","sources":["../../../src/local/courseeditor/contenttree.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index keyboard navigation and aria-tree compatibility.\n *\n * Node tree and bootstrap collapsibles don't use the same HTML structure. However,\n * all keybindings and logic is compatible. This class translate the primitive opetations\n * to a bootstrap collapsible structure.\n *\n * @module core_courseformat/local/courseindex/keyboardnav\n * @class core_courseformat/local/courseindex/keyboardnav\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// The core/tree uses jQuery to expand all nodes.\nimport jQuery from 'jquery';\nimport Tree from 'core/tree';\nimport {getList} from 'core/normalise';\n\nexport default class extends Tree {\n\n /**\n * Setup the core/tree keyboard navigation.\n *\n * @param {Element|undefined} mainElement an alternative main element in case it is not from the parent component\n * @param {Object|undefined} selectors alternative selectors\n * @param {boolean} preventcache if the elements cache must be disabled.\n */\n constructor(mainElement, selectors, preventcache) {\n // Init this value with the parent DOM element.\n super(mainElement);\n\n // Get selectors from parent.\n this.selectors = {\n SECTION: selectors.SECTION,\n TOGGLER: selectors.TOGGLER,\n COLLAPSE: selectors.COLLAPSE,\n ENTER: selectors.ENTER ?? selectors.TOGGLER,\n };\n\n // The core/tree library saves the visible elements cache inside the main tree node.\n // However, in edit mode content can change suddenly so we need to refresh caches when needed.\n if (preventcache) {\n this._getVisibleItems = this.getVisibleItems;\n this.getVisibleItems = () => {\n this.refreshVisibleItemsCache();\n return this._getVisibleItems();\n };\n }\n // All jQuery events can be replaced when MDL-71979 is integrated.\n this.treeRoot.on('hidden.bs.collapse shown.bs.collapse', () => {\n this.refreshVisibleItemsCache();\n });\n // Register a custom callback for pressing enter key.\n this.registerEnterCallback(this.enterCallback.bind(this));\n }\n\n /**\n * Return the current active node.\n *\n * @return {Element|undefined} the active item if any\n */\n getActiveItem() {\n const activeItem = this.treeRoot.data('activeItem');\n if (activeItem) {\n return getList(activeItem)[0];\n }\n return undefined;\n }\n\n /**\n * Handle enter key on a collpasible node.\n *\n * @param {JQuery} jQueryItem the jQuery object\n */\n enterCallback(jQueryItem) {\n const item = getList(jQueryItem)[0];\n if (this.isGroupItem(jQueryItem)) {\n // Group elements is like clicking a topic but without loosing the focus.\n const enter = item.querySelector(this.selectors.ENTER);\n if (enter.getAttribute('href') !== '#') {\n window.location.href = enter.getAttribute('href');\n }\n enter.click();\n } else {\n // Activity links just follow the link href.\n const link = item.querySelector('a');\n if (link.getAttribute('href') !== '#') {\n window.location.href = link.getAttribute('href');\n } else {\n link.click();\n }\n return;\n }\n }\n\n /**\n * Handle an item click.\n *\n * @param {Event} event the click event\n * @param {jQuery} jQueryItem the item clicked\n */\n handleItemClick(event, jQueryItem) {\n const isChevron = event.target.closest(this.selectors.COLLAPSE);\n // Only chevron clicks toogle the sections always.\n if (isChevron) {\n super.handleItemClick(event, jQueryItem);\n return;\n }\n // This is a title or activity name click.\n jQueryItem.focus();\n if (this.isGroupItem(jQueryItem)) {\n this.expandGroup(jQueryItem);\n }\n }\n\n /**\n * Check if a gorup item is collapsed.\n *\n * @param {JQuery} jQueryItem the jQuery object\n * @returns {boolean} if the element is collapsed\n */\n isGroupCollapsed(jQueryItem) {\n const item = getList(jQueryItem)[0];\n const toggler = item.querySelector(`[aria-expanded]`);\n return toggler.getAttribute('aria-expanded') === 'false';\n }\n\n /**\n * Toggle a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n toggleGroup(item) {\n // All jQuery in this segment of code can be replaced when MDL-71979 is integrated.\n const toggler = item.find(this.selectors.COLLAPSE);\n let collapsibleId = toggler.data('target') ?? toggler.attr('href');\n if (!collapsibleId) {\n return;\n }\n collapsibleId = collapsibleId.replace('#', '');\n\n // Bootstrap 4 uses jQuery to interact with collapsibles.\n const collapsible = jQuery(`#${collapsibleId}`);\n if (collapsible.length) {\n jQuery(`#${collapsibleId}`).collapse('toggle');\n }\n }\n\n /**\n * Expand a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n expandGroup(item) {\n if (this.isGroupCollapsed(item)) {\n this.toggleGroup(item);\n }\n }\n\n /**\n * Collpase a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n collapseGroup(item) {\n if (!this.isGroupCollapsed(item)) {\n this.toggleGroup(item);\n }\n }\n\n /**\n * Expand all groups.\n */\n expandAllGroups() {\n const togglers = getList(this.treeRoot)[0].querySelectorAll(this.selectors.SECTION);\n togglers.forEach(item => {\n this.expandGroup(jQuery(item));\n });\n }\n}\n"],"names":["Tree","constructor","mainElement","selectors","preventcache","SECTION","TOGGLER","COLLAPSE","ENTER","_getVisibleItems","this","getVisibleItems","refreshVisibleItemsCache","treeRoot","on","registerEnterCallback","enterCallback","bind","getActiveItem","activeItem","data","jQueryItem","item","isGroupItem","enter","querySelector","getAttribute","window","location","href","click","link","handleItemClick","event","target","closest","focus","expandGroup","isGroupCollapsed","toggleGroup","toggler","find","collapsibleId","attr","replace","length","collapse","collapseGroup","expandAllGroups","querySelectorAll","forEach"],"mappings":";;;;;;;;;;;;wLAiC6BA,cASzBC,YAAYC,YAAaC,UAAWC,yCAE1BF,kBAGDC,UAAY,CACbE,QAASF,UAAUE,QACnBC,QAASH,UAAUG,QACnBC,SAAUJ,UAAUI,SACpBC,+BAAOL,UAAUK,mDAASL,UAAUG,SAKpCF,oBACKK,iBAAmBC,KAAKC,qBACxBA,gBAAkB,UACdC,2BACEF,KAAKD,0BAIfI,SAASC,GAAG,wCAAwC,UAChDF,mCAGJG,sBAAsBL,KAAKM,cAAcC,KAAKP,OAQvDQ,sBACUC,WAAaT,KAAKG,SAASO,KAAK,iBAClCD,kBACO,sBAAQA,YAAY,GAUnCH,cAAcK,kBACJC,MAAO,sBAAQD,YAAY,MAC7BX,KAAKa,YAAYF,YAAa,OAExBG,MAAQF,KAAKG,cAAcf,KAAKP,UAAUK,OACb,MAA/BgB,MAAME,aAAa,UACnBC,OAAOC,SAASC,KAAOL,MAAME,aAAa,SAE9CF,MAAMM,mBAGAC,KAAOT,KAAKG,cAAc,KACE,MAA9BM,KAAKL,aAAa,QAClBC,OAAOC,SAASC,KAAOE,KAAKL,aAAa,QAEzCK,KAAKD,SAYjBE,gBAAgBC,MAAOZ,YACDY,MAAMC,OAAOC,QAAQzB,KAAKP,UAAUI,gBAG5CyB,gBAAgBC,MAAOZ,aAIjCA,WAAWe,QACP1B,KAAKa,YAAYF,kBACZgB,YAAYhB,aAUzBiB,iBAAiBjB,kBAGoC,WAFpC,sBAAQA,YAAY,GACZI,iCACNC,aAAa,iBAQhCa,YAAYjB,8BAEFkB,QAAUlB,KAAKmB,KAAK/B,KAAKP,UAAUI,cACrCmC,oCAAgBF,QAAQpB,KAAK,iDAAaoB,QAAQG,KAAK,YACtDD,qBAGLA,cAAgBA,cAAcE,QAAQ,IAAK,KAGvB,8BAAWF,gBACfG,uCACDH,gBAAiBI,SAAS,UAS7CT,YAAYf,MACJZ,KAAK4B,iBAAiBhB,YACjBiB,YAAYjB,MASzByB,cAAczB,MACLZ,KAAK4B,iBAAiBhB,YAClBiB,YAAYjB,MAOzB0B,mBACqB,sBAAQtC,KAAKG,UAAU,GAAGoC,iBAAiBvC,KAAKP,UAAUE,SAClE6C,SAAQ5B,YACRe,aAAY,mBAAOf"} \ No newline at end of file +{"version":3,"file":"contenttree.min.js","sources":["../../../src/local/courseeditor/contenttree.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Course index keyboard navigation and aria-tree compatibility.\n *\n * Node tree and bootstrap collapsibles don't use the same HTML structure. However,\n * all keybindings and logic is compatible. This class translate the primitive opetations\n * to a bootstrap collapsible structure.\n *\n * @module core_courseformat/local/courseeditor/contenttree\n * @class core_courseformat/local/courseeditor/contenttree\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n// The core/tree uses jQuery to expand all nodes.\nimport jQuery from 'jquery';\nimport Tree from 'core/tree';\nimport {getList} from 'core/normalise';\n\nexport default class extends Tree {\n\n /**\n * Setup the core/tree keyboard navigation.\n *\n * @param {Element|undefined} mainElement an alternative main element in case it is not from the parent component\n * @param {Object|undefined} selectors alternative selectors\n * @param {boolean} preventcache if the elements cache must be disabled.\n */\n constructor(mainElement, selectors, preventcache) {\n // Init this value with the parent DOM element.\n super(mainElement);\n\n // Get selectors from parent.\n this.selectors = {\n SECTION: selectors.SECTION,\n TOGGLER: selectors.TOGGLER,\n COLLAPSE: selectors.COLLAPSE,\n ENTER: selectors.ENTER ?? selectors.TOGGLER,\n };\n\n // The core/tree library saves the visible elements cache inside the main tree node.\n // However, in edit mode content can change suddenly so we need to refresh caches when needed.\n if (preventcache) {\n this._getVisibleItems = this.getVisibleItems;\n this.getVisibleItems = () => {\n this.refreshVisibleItemsCache();\n return this._getVisibleItems();\n };\n }\n // All jQuery events can be replaced when MDL-71979 is integrated.\n this.treeRoot.on('hidden.bs.collapse shown.bs.collapse', () => {\n this.refreshVisibleItemsCache();\n });\n // Register a custom callback for pressing enter key.\n this.registerEnterCallback(this.enterCallback.bind(this));\n }\n\n /**\n * Return the current active node.\n *\n * @return {Element|undefined} the active item if any\n */\n getActiveItem() {\n const activeItem = this.treeRoot.data('activeItem');\n if (activeItem) {\n return getList(activeItem)[0];\n }\n return undefined;\n }\n\n /**\n * Handle enter key on a collpasible node.\n *\n * @param {JQuery} jQueryItem the jQuery object\n */\n enterCallback(jQueryItem) {\n const item = getList(jQueryItem)[0];\n if (this.isGroupItem(jQueryItem)) {\n // Group elements is like clicking a topic but without loosing the focus.\n const enter = item.querySelector(this.selectors.ENTER);\n if (enter.getAttribute('href') !== '#') {\n window.location.href = enter.getAttribute('href');\n }\n enter.click();\n } else {\n // Activity links just follow the link href.\n const link = item.querySelector('a');\n if (link.getAttribute('href') !== '#') {\n window.location.href = link.getAttribute('href');\n } else {\n link.click();\n }\n return;\n }\n }\n\n /**\n * Handle an item click.\n *\n * @param {Event} event the click event\n * @param {jQuery} jQueryItem the item clicked\n */\n handleItemClick(event, jQueryItem) {\n const isChevron = event.target.closest(this.selectors.COLLAPSE);\n // Only chevron clicks toogle the sections always.\n if (isChevron) {\n super.handleItemClick(event, jQueryItem);\n return;\n }\n // This is a title or activity name click.\n jQueryItem.focus();\n if (this.isGroupItem(jQueryItem)) {\n this.expandGroup(jQueryItem);\n }\n }\n\n /**\n * Check if a gorup item is collapsed.\n *\n * @param {JQuery} jQueryItem the jQuery object\n * @returns {boolean} if the element is collapsed\n */\n isGroupCollapsed(jQueryItem) {\n const item = getList(jQueryItem)[0];\n const toggler = item.querySelector(`[aria-expanded]`);\n return toggler.getAttribute('aria-expanded') === 'false';\n }\n\n /**\n * Toggle a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n toggleGroup(item) {\n // All jQuery in this segment of code can be replaced when MDL-71979 is integrated.\n const toggler = item.find(this.selectors.COLLAPSE);\n let collapsibleId = toggler.data('target') ?? toggler.attr('href');\n if (!collapsibleId) {\n return;\n }\n collapsibleId = collapsibleId.replace('#', '');\n\n // Bootstrap 4 uses jQuery to interact with collapsibles.\n const collapsible = jQuery(`#${collapsibleId}`);\n if (collapsible.length) {\n jQuery(`#${collapsibleId}`).collapse('toggle');\n }\n }\n\n /**\n * Expand a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n expandGroup(item) {\n if (this.isGroupCollapsed(item)) {\n this.toggleGroup(item);\n }\n }\n\n /**\n * Collpase a group item.\n *\n * @param {JQuery} item the jQuery object\n */\n collapseGroup(item) {\n if (!this.isGroupCollapsed(item)) {\n this.toggleGroup(item);\n }\n }\n\n /**\n * Expand all groups.\n */\n expandAllGroups() {\n const togglers = getList(this.treeRoot)[0].querySelectorAll(this.selectors.SECTION);\n togglers.forEach(item => {\n this.expandGroup(jQuery(item));\n });\n }\n}\n"],"names":["Tree","constructor","mainElement","selectors","preventcache","SECTION","TOGGLER","COLLAPSE","ENTER","_getVisibleItems","this","getVisibleItems","refreshVisibleItemsCache","treeRoot","on","registerEnterCallback","enterCallback","bind","getActiveItem","activeItem","data","jQueryItem","item","isGroupItem","enter","querySelector","getAttribute","window","location","href","click","link","handleItemClick","event","target","closest","focus","expandGroup","isGroupCollapsed","toggleGroup","toggler","find","collapsibleId","attr","replace","length","collapse","collapseGroup","expandAllGroups","querySelectorAll","forEach"],"mappings":";;;;;;;;;;;;wLAiC6BA,cASzBC,YAAYC,YAAaC,UAAWC,yCAE1BF,kBAGDC,UAAY,CACbE,QAASF,UAAUE,QACnBC,QAASH,UAAUG,QACnBC,SAAUJ,UAAUI,SACpBC,+BAAOL,UAAUK,mDAASL,UAAUG,SAKpCF,oBACKK,iBAAmBC,KAAKC,qBACxBA,gBAAkB,UACdC,2BACEF,KAAKD,0BAIfI,SAASC,GAAG,wCAAwC,UAChDF,mCAGJG,sBAAsBL,KAAKM,cAAcC,KAAKP,OAQvDQ,sBACUC,WAAaT,KAAKG,SAASO,KAAK,iBAClCD,kBACO,sBAAQA,YAAY,GAUnCH,cAAcK,kBACJC,MAAO,sBAAQD,YAAY,MAC7BX,KAAKa,YAAYF,YAAa,OAExBG,MAAQF,KAAKG,cAAcf,KAAKP,UAAUK,OACb,MAA/BgB,MAAME,aAAa,UACnBC,OAAOC,SAASC,KAAOL,MAAME,aAAa,SAE9CF,MAAMM,mBAGAC,KAAOT,KAAKG,cAAc,KACE,MAA9BM,KAAKL,aAAa,QAClBC,OAAOC,SAASC,KAAOE,KAAKL,aAAa,QAEzCK,KAAKD,SAYjBE,gBAAgBC,MAAOZ,YACDY,MAAMC,OAAOC,QAAQzB,KAAKP,UAAUI,gBAG5CyB,gBAAgBC,MAAOZ,aAIjCA,WAAWe,QACP1B,KAAKa,YAAYF,kBACZgB,YAAYhB,aAUzBiB,iBAAiBjB,kBAGoC,WAFpC,sBAAQA,YAAY,GACZI,iCACNC,aAAa,iBAQhCa,YAAYjB,8BAEFkB,QAAUlB,KAAKmB,KAAK/B,KAAKP,UAAUI,cACrCmC,oCAAgBF,QAAQpB,KAAK,iDAAaoB,QAAQG,KAAK,YACtDD,qBAGLA,cAAgBA,cAAcE,QAAQ,IAAK,KAGvB,8BAAWF,gBACfG,uCACDH,gBAAiBI,SAAS,UAS7CT,YAAYf,MACJZ,KAAK4B,iBAAiBhB,YACjBiB,YAAYjB,MASzByB,cAAczB,MACLZ,KAAK4B,iBAAiBhB,YAClBiB,YAAYjB,MAOzB0B,mBACqB,sBAAQtC,KAAKG,UAAU,GAAGoC,iBAAiBvC,KAAKP,UAAUE,SAClE6C,SAAQ5B,YACRe,aAAY,mBAAOf"} \ No newline at end of file diff --git a/course/format/amd/src/local/courseeditor/contenttree.js b/course/format/amd/src/local/courseeditor/contenttree.js index 4157783f4aa..2fc675e85ff 100644 --- a/course/format/amd/src/local/courseeditor/contenttree.js +++ b/course/format/amd/src/local/courseeditor/contenttree.js @@ -20,8 +20,8 @@ * all keybindings and logic is compatible. This class translate the primitive opetations * to a bootstrap collapsible structure. * - * @module core_courseformat/local/courseindex/keyboardnav - * @class core_courseformat/local/courseindex/keyboardnav + * @module core_courseformat/local/courseeditor/contenttree + * @class core_courseformat/local/courseeditor/contenttree * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/course/format/topics/amd/build/section.min.js b/course/format/topics/amd/build/section.min.js index b6f3c84a6ba..762120f2cbb 100644 --- a/course/format/topics/amd/build/section.min.js +++ b/course/format/topics/amd/build/section.min.js @@ -2,7 +2,7 @@ define("format_topics/section",["exports","core/reactive","core_courseformat/cou /** * Format topics section extra logic component. * - * @module format_topics/mutations + * @module format_topics/section * @copyright 2022 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=(obj=_templates)&&obj.__esModule?obj:{default:obj};class HighlightSection extends _reactive.BaseComponent{create(){this.name="format_topics_section",this.selectors={SECTION:"[data-for='section']",SETMARKER:'[data-action="sectionHighlight"]',REMOVEMARKER:'[data-action="sectionUnhighlight"]',ACTIONTEXT:".menu-action-text",ICON:".icon"},this.classes={HIDE:"d-none"},this.formatActions={HIGHLIGHT:"sectionHighlight",UNHIGHLIGHT:"sectionUnhighlight"}}getWatchers(){return[{watch:"section.current:updated",handler:this._refreshHighlight}]}async _refreshHighlight(_ref){var _affectedAction$datas,_affectedAction$datas2;let selector,newAction,{element:element}=_ref;element.current?(selector=this.selectors.SETMARKER,newAction=this.formatActions.UNHIGHLIGHT):(selector=this.selectors.REMOVEMARKER,newAction=this.formatActions.HIGHLIGHT);const affectedAction=this.getElement("".concat(this.selectors.SECTION," ").concat(selector),element.id);if(!affectedAction)return;affectedAction.dataset.action=newAction;const actionText=affectedAction.querySelector(this.selectors.ACTIONTEXT);if(null!==(_affectedAction$datas=affectedAction.dataset)&&void 0!==_affectedAction$datas&&_affectedAction$datas.swapname&&actionText){const oldText=null==actionText?void 0:actionText.innerText;actionText.innerText=affectedAction.dataset.swapname,affectedAction.dataset.swapname=oldText}const icon=affectedAction.querySelector(this.selectors.ICON);if(null!==(_affectedAction$datas2=affectedAction.dataset)&&void 0!==_affectedAction$datas2&&_affectedAction$datas2.swapicon&&icon){const newIcon=affectedAction.dataset.swapicon;if(newIcon){const pixHtml=await _templates.default.renderPix(newIcon,"core");_templates.default.replaceNode(icon,pixHtml,"")}}}}_exports.init=()=>{const courseEditor=(0,_courseeditor.getCurrentCourseEditor)();courseEditor.supportComponents&&courseEditor.isEditing&&new HighlightSection({element:document.getElementById("region-main"),reactive:courseEditor})}})); diff --git a/course/format/topics/amd/build/section.min.js.map b/course/format/topics/amd/build/section.min.js.map index d2444516253..9a9c3d87ffb 100644 --- a/course/format/topics/amd/build/section.min.js.map +++ b/course/format/topics/amd/build/section.min.js.map @@ -1 +1 @@ -{"version":3,"file":"section.min.js","sources":["../src/section.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 * Format topics section extra logic component.\n *\n * @module format_topics/mutations\n * @copyright 2022 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent} from 'core/reactive';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport Templates from 'core/templates';\n\nclass HighlightSection extends BaseComponent {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'format_topics_section';\n // Default query selectors.\n this.selectors = {\n SECTION: `[data-for='section']`,\n SETMARKER: `[data-action=\"sectionHighlight\"]`,\n REMOVEMARKER: `[data-action=\"sectionUnhighlight\"]`,\n ACTIONTEXT: `.menu-action-text`,\n ICON: `.icon`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n HIDE: 'd-none',\n };\n // The topics format section specific actions.\n this.formatActions = {\n HIGHLIGHT: 'sectionHighlight',\n UNHIGHLIGHT: 'sectionUnhighlight',\n };\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section.current:updated`, handler: this._refreshHighlight},\n ];\n }\n\n /**\n * Update a content section using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n async _refreshHighlight({element}) {\n let selector;\n let newAction;\n if (element.current) {\n selector = this.selectors.SETMARKER;\n newAction = this.formatActions.UNHIGHLIGHT;\n } else {\n selector = this.selectors.REMOVEMARKER;\n newAction = this.formatActions.HIGHLIGHT;\n }\n // Find the affected action.\n const affectedAction = this.getElement(`${this.selectors.SECTION} ${selector}`, element.id);\n if (!affectedAction) {\n return;\n }\n // Change action, text and icon.\n affectedAction.dataset.action = newAction;\n const actionText = affectedAction.querySelector(this.selectors.ACTIONTEXT);\n if (affectedAction.dataset?.swapname && actionText) {\n const oldText = actionText?.innerText;\n actionText.innerText = affectedAction.dataset.swapname;\n affectedAction.dataset.swapname = oldText;\n }\n const icon = affectedAction.querySelector(this.selectors.ICON);\n if (affectedAction.dataset?.swapicon && icon) {\n const newIcon = affectedAction.dataset.swapicon;\n if (newIcon) {\n const pixHtml = await Templates.renderPix(newIcon, 'core');\n Templates.replaceNode(icon, pixHtml, '');\n }\n }\n }\n}\n\nexport const init = () => {\n // Add component to the section.\n const courseEditor = getCurrentCourseEditor();\n if (courseEditor.supportComponents && courseEditor.isEditing) {\n new HighlightSection({\n element: document.getElementById('region-main'),\n reactive: courseEditor,\n });\n }\n};\n"],"names":["HighlightSection","BaseComponent","create","name","selectors","SECTION","SETMARKER","REMOVEMARKER","ACTIONTEXT","ICON","classes","HIDE","formatActions","HIGHLIGHT","UNHIGHLIGHT","getWatchers","watch","handler","this","_refreshHighlight","selector","newAction","element","current","affectedAction","getElement","id","dataset","action","actionText","querySelector","swapname","oldText","innerText","icon","swapicon","newIcon","pixHtml","Templates","renderPix","replaceNode","courseEditor","supportComponents","isEditing","document","getElementById","reactive"],"mappings":";;;;;;;sJA2BMA,yBAAyBC,wBAK3BC,cAESC,KAAO,6BAEPC,UAAY,CACbC,+BACAC,6CACAC,kDACAC,+BACAC,mBAGCC,QAAU,CACXC,KAAM,eAGLC,cAAgB,CACjBC,UAAW,mBACXC,YAAa,sBASrBC,oBACW,CACH,CAACC,gCAAkCC,QAASC,KAAKC,uGAWjDC,SACAC,WAFgBC,QAACA,cAGjBA,QAAQC,SACRH,SAAWF,KAAKd,UAAUE,UAC1Be,UAAYH,KAAKN,cAAcE,cAE/BM,SAAWF,KAAKd,UAAUG,aAC1Bc,UAAYH,KAAKN,cAAcC,iBAG7BW,eAAiBN,KAAKO,qBAAcP,KAAKd,UAAUC,oBAAWe,UAAYE,QAAQI,QACnFF,sBAILA,eAAeG,QAAQC,OAASP,gBAC1BQ,WAAaL,eAAeM,cAAcZ,KAAKd,UAAUI,6CAC3DgB,eAAeG,gEAASI,UAAYF,WAAY,OAC1CG,QAAUH,MAAAA,kBAAAA,WAAYI,UAC5BJ,WAAWI,UAAYT,eAAeG,QAAQI,SAC9CP,eAAeG,QAAQI,SAAWC,cAEhCE,KAAOV,eAAeM,cAAcZ,KAAKd,UAAUK,wCACrDe,eAAeG,kEAASQ,UAAYD,KAAM,OACpCE,QAAUZ,eAAeG,QAAQQ,YACnCC,QAAS,OACHC,cAAgBC,mBAAUC,UAAUH,QAAS,2BACzCI,YAAYN,KAAMG,QAAS,qBAMjC,WAEVI,cAAe,0CACjBA,aAAaC,mBAAqBD,aAAaE,eAC3C3C,iBAAiB,CACjBsB,QAASsB,SAASC,eAAe,eACjCC,SAAUL"} \ No newline at end of file +{"version":3,"file":"section.min.js","sources":["../src/section.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 * Format topics section extra logic component.\n *\n * @module format_topics/section\n * @copyright 2022 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {BaseComponent} from 'core/reactive';\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport Templates from 'core/templates';\n\nclass HighlightSection extends BaseComponent {\n\n /**\n * Constructor hook.\n */\n create() {\n // Optional component name for debugging.\n this.name = 'format_topics_section';\n // Default query selectors.\n this.selectors = {\n SECTION: `[data-for='section']`,\n SETMARKER: `[data-action=\"sectionHighlight\"]`,\n REMOVEMARKER: `[data-action=\"sectionUnhighlight\"]`,\n ACTIONTEXT: `.menu-action-text`,\n ICON: `.icon`,\n };\n // Default classes to toggle on refresh.\n this.classes = {\n HIDE: 'd-none',\n };\n // The topics format section specific actions.\n this.formatActions = {\n HIGHLIGHT: 'sectionHighlight',\n UNHIGHLIGHT: 'sectionUnhighlight',\n };\n }\n\n /**\n * Component watchers.\n *\n * @returns {Array} of watchers\n */\n getWatchers() {\n return [\n {watch: `section.current:updated`, handler: this._refreshHighlight},\n ];\n }\n\n /**\n * Update a content section using the state information.\n *\n * @param {object} param\n * @param {Object} param.element details the update details.\n */\n async _refreshHighlight({element}) {\n let selector;\n let newAction;\n if (element.current) {\n selector = this.selectors.SETMARKER;\n newAction = this.formatActions.UNHIGHLIGHT;\n } else {\n selector = this.selectors.REMOVEMARKER;\n newAction = this.formatActions.HIGHLIGHT;\n }\n // Find the affected action.\n const affectedAction = this.getElement(`${this.selectors.SECTION} ${selector}`, element.id);\n if (!affectedAction) {\n return;\n }\n // Change action, text and icon.\n affectedAction.dataset.action = newAction;\n const actionText = affectedAction.querySelector(this.selectors.ACTIONTEXT);\n if (affectedAction.dataset?.swapname && actionText) {\n const oldText = actionText?.innerText;\n actionText.innerText = affectedAction.dataset.swapname;\n affectedAction.dataset.swapname = oldText;\n }\n const icon = affectedAction.querySelector(this.selectors.ICON);\n if (affectedAction.dataset?.swapicon && icon) {\n const newIcon = affectedAction.dataset.swapicon;\n if (newIcon) {\n const pixHtml = await Templates.renderPix(newIcon, 'core');\n Templates.replaceNode(icon, pixHtml, '');\n }\n }\n }\n}\n\nexport const init = () => {\n // Add component to the section.\n const courseEditor = getCurrentCourseEditor();\n if (courseEditor.supportComponents && courseEditor.isEditing) {\n new HighlightSection({\n element: document.getElementById('region-main'),\n reactive: courseEditor,\n });\n }\n};\n"],"names":["HighlightSection","BaseComponent","create","name","selectors","SECTION","SETMARKER","REMOVEMARKER","ACTIONTEXT","ICON","classes","HIDE","formatActions","HIGHLIGHT","UNHIGHLIGHT","getWatchers","watch","handler","this","_refreshHighlight","selector","newAction","element","current","affectedAction","getElement","id","dataset","action","actionText","querySelector","swapname","oldText","innerText","icon","swapicon","newIcon","pixHtml","Templates","renderPix","replaceNode","courseEditor","supportComponents","isEditing","document","getElementById","reactive"],"mappings":";;;;;;;sJA2BMA,yBAAyBC,wBAK3BC,cAESC,KAAO,6BAEPC,UAAY,CACbC,+BACAC,6CACAC,kDACAC,+BACAC,mBAGCC,QAAU,CACXC,KAAM,eAGLC,cAAgB,CACjBC,UAAW,mBACXC,YAAa,sBASrBC,oBACW,CACH,CAACC,gCAAkCC,QAASC,KAAKC,uGAWjDC,SACAC,WAFgBC,QAACA,cAGjBA,QAAQC,SACRH,SAAWF,KAAKd,UAAUE,UAC1Be,UAAYH,KAAKN,cAAcE,cAE/BM,SAAWF,KAAKd,UAAUG,aAC1Bc,UAAYH,KAAKN,cAAcC,iBAG7BW,eAAiBN,KAAKO,qBAAcP,KAAKd,UAAUC,oBAAWe,UAAYE,QAAQI,QACnFF,sBAILA,eAAeG,QAAQC,OAASP,gBAC1BQ,WAAaL,eAAeM,cAAcZ,KAAKd,UAAUI,6CAC3DgB,eAAeG,gEAASI,UAAYF,WAAY,OAC1CG,QAAUH,MAAAA,kBAAAA,WAAYI,UAC5BJ,WAAWI,UAAYT,eAAeG,QAAQI,SAC9CP,eAAeG,QAAQI,SAAWC,cAEhCE,KAAOV,eAAeM,cAAcZ,KAAKd,UAAUK,wCACrDe,eAAeG,kEAASQ,UAAYD,KAAM,OACpCE,QAAUZ,eAAeG,QAAQQ,YACnCC,QAAS,OACHC,cAAgBC,mBAAUC,UAAUH,QAAS,2BACzCI,YAAYN,KAAMG,QAAS,qBAMjC,WAEVI,cAAe,0CACjBA,aAAaC,mBAAqBD,aAAaE,eAC3C3C,iBAAiB,CACjBsB,QAASsB,SAASC,eAAe,eACjCC,SAAUL"} \ No newline at end of file diff --git a/course/format/topics/amd/src/section.js b/course/format/topics/amd/src/section.js index 152cb9a5d48..8cf5b62437d 100644 --- a/course/format/topics/amd/src/section.js +++ b/course/format/topics/amd/src/section.js @@ -16,7 +16,7 @@ /** * Format topics section extra logic component. * - * @module format_topics/mutations + * @module format_topics/section * @copyright 2022 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/grade/report/singleview/amd/build/grade.min.js b/grade/report/singleview/amd/build/grade.min.js index ebb3377c95e..a4fcb2632ea 100644 --- a/grade/report/singleview/amd/build/grade.min.js +++ b/grade/report/singleview/amd/build/grade.min.js @@ -2,7 +2,7 @@ define("gradereport_singleview/grade",["exports","core/local/aria/focuslock","co /** * A small modal to search grade items within the gradebook. * - * @module gradereport_singleview + * @module gradereport_singleview/grade * @copyright 2022 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,FocusLockManager=_interopRequireWildcard(FocusLockManager),_pending=_interopRequireDefault(_pending),Templates=_interopRequireWildcard(Templates),_url=_interopRequireDefault(_url),Repository=_interopRequireWildcard(Repository),WidgetBase=_interopRequireWildcard(WidgetBase),_jquery=_interopRequireDefault(_jquery),Selectors=_interopRequireWildcard(Selectors);_exports.init=()=>{if(document.querySelector(Selectors.elements.getSearchWidgetSelector("grade"))){const pendingPromise=new _pending.default;registerListenerEvents(),pendingPromise.resolve()}};const registerListenerEvents=()=>{let{bodyPromiseResolver:bodyPromiseResolver,bodyPromise:bodyPromise}=WidgetBase.promisesAndResolvers();const dropdownMenuContainer=document.querySelector(Selectors.elements.getSearchWidgetDropdownSelector("grade")),menuContainer=document.querySelector(Selectors.elements.getSearchWidgetSelector("grade")),inputElement=menuContainer.querySelector('input[name="itemid"]');(0,_jquery.default)(menuContainer).on("show.bs.dropdown",(async e=>{const courseID=e.relatedTarget.dataset.courseid;await WidgetBase.showLoader(dropdownMenuContainer);const data=await Repository.gradeitemFetch(courseID).catch((async e=>{const errorTemplateData={errormessage:e.message};bodyPromiseResolver(await Templates.render("core_grades/searchwidget/error",errorTemplateData))}));data!==[]&&(await WidgetBase.init(dropdownMenuContainer,bodyPromise,data.gradeitems,searchGradeitems(),null,afterSelect),bodyPromiseResolver(Templates.render("gradereport_singleview/gradesearch_body",[])),FocusLockManager.trapFocus(dropdownMenuContainer))})),(0,_jquery.default)(menuContainer).on("hide.bs.dropdown",(()=>{FocusLockManager.untrapFocus()})),inputElement.addEventListener("change",(e=>{const courseId=menuContainer.querySelector(".dropdown-toggle").dataset.courseid,actionUrl=_url.default.relativeUrl("/grade/report/singleview/index.php",{id:courseId,item:"grade",itemid:e.target.value},!1);location.href=actionUrl,e.stopPropagation()}))},searchGradeitems=()=>()=>(modules,searchTerm)=>{if(""===searchTerm)return modules;searchTerm=searchTerm.toLowerCase();const searchResults=[];return modules.forEach((module=>{module.name.toLowerCase().includes(searchTerm)&&searchResults.push(module)})),searchResults},afterSelect=selected=>{const menuContainer=document.querySelector(Selectors.elements.getSearchWidgetSelector("grade")),inputElement=menuContainer.querySelector('input[name="itemid"]');(0,_jquery.default)(menuContainer).dropdown("hide"),inputElement.value!=selected&&(inputElement.value=selected,inputElement.dispatchEvent(new Event("change",{bubbles:!0})))}})); diff --git a/grade/report/singleview/amd/build/grade.min.js.map b/grade/report/singleview/amd/build/grade.min.js.map index 2ebb8bc3c39..a111e7feeaa 100644 --- a/grade/report/singleview/amd/build/grade.min.js.map +++ b/grade/report/singleview/amd/build/grade.min.js.map @@ -1 +1 @@ -{"version":3,"file":"grade.min.js","sources":["../src/grade.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 small modal to search grade items within the gradebook.\n *\n * @module gradereport_singleview\n * @copyright 2022 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as FocusLockManager from 'core/local/aria/focuslock';\nimport Pending from 'core/pending';\nimport * as Templates from 'core/templates';\nimport Url from 'core/url';\nimport * as Repository from 'core_grades/searchwidget/repository';\nimport * as WidgetBase from 'core_grades/searchwidget/basewidget';\nimport $ from 'jquery';\nimport * as Selectors from 'core_grades/searchwidget/selectors';\n\n/**\n * Our entry point into starting to build the search widget.\n * It'll eventually, based upon the listeners, open the search widget and allow filtering.\n *\n * @method init\n */\nexport const init = () => {\n if (document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'))) {\n const pendingPromise = new Pending();\n registerListenerEvents();\n pendingPromise.resolve();\n }\n};\n\n/**\n * Register grade item search widget related event listeners.\n *\n * @method registerListenerEvents\n */\nconst registerListenerEvents = () => {\n let {bodyPromiseResolver, bodyPromise} = WidgetBase.promisesAndResolvers();\n const dropdownMenuContainer = document.querySelector(Selectors.elements.getSearchWidgetDropdownSelector('grade'));\n const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'));\n const inputElement = menuContainer.querySelector('input[name=\"itemid\"]');\n\n // Handle the 'shown.bs.dropdown' event (Fired when the dropdown menu is fully displayed).\n $(menuContainer).on('show.bs.dropdown', async(e) => {\n const courseID = e.relatedTarget.dataset.courseid;\n // Display a loading icon in the dropdown menu container until the body promise is resolved.\n await WidgetBase.showLoader(dropdownMenuContainer);\n\n // If an error occurs while fetching the data, display the error within the modal.\n const data = await Repository.gradeitemFetch(courseID).catch(async(e) => {\n const errorTemplateData = {\n 'errormessage': e.message\n };\n bodyPromiseResolver(\n await Templates.render('core_grades/searchwidget/error', errorTemplateData)\n );\n });\n\n // Early return if there is no module data.\n if (data === []) {\n return;\n }\n\n await WidgetBase.init(\n dropdownMenuContainer,\n bodyPromise,\n data.gradeitems,\n searchGradeitems(),\n null,\n afterSelect\n );\n\n // Resolvers for passed functions in the modal creation.\n bodyPromiseResolver(Templates.render('gradereport_singleview/gradesearch_body', []));\n\n // Lock tab control. It has to be locked because the dropdown's role is dialog.\n FocusLockManager.trapFocus(dropdownMenuContainer);\n });\n\n // Handle the 'hide.bs.dropdown' event (Fired when the dropdown menu is being closed).\n $(menuContainer).on('hide.bs.dropdown', () => {\n FocusLockManager.untrapFocus();\n });\n\n inputElement.addEventListener('change', e => {\n const toggle = menuContainer.querySelector('.dropdown-toggle');\n const courseId = toggle.dataset.courseid;\n const actionUrl = Url.relativeUrl(\n '/grade/report/singleview/index.php',\n {\n id: courseId,\n item: 'grade',\n itemid: e.target.value\n },\n false\n );\n location.href = actionUrl;\n\n e.stopPropagation();\n });\n};\n\n/**\n * Define how we want to search and filter grade items when the user decides to input a search value.\n *\n * @method searchGradeitems\n * @returns {function(): function(*, *): (*)}\n */\nconst searchGradeitems = () => {\n return () => {\n return (modules, searchTerm) => {\n if (searchTerm === '') {\n return modules;\n }\n searchTerm = searchTerm.toLowerCase();\n const searchResults = [];\n modules.forEach((module) => {\n const moduleName = module.name.toLowerCase();\n if (moduleName.includes(searchTerm)) {\n searchResults.push(module);\n }\n });\n return searchResults;\n };\n };\n};\n\n/**\n * Define the action to be performed when an item is selected by the search widget.\n *\n * @param {String} selected The selected item's value.\n */\nconst afterSelect = (selected) => {\n const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'));\n const inputElement = menuContainer.querySelector('input[name=\"itemid\"]');\n\n $(menuContainer).dropdown('hide'); // Otherwise the dropdown stays open when user choose an option using keyboard.\n\n if (inputElement.value != selected) {\n inputElement.value = selected;\n inputElement.dispatchEvent(new Event('change', {bubbles: true}));\n }\n};\n"],"names":["document","querySelector","Selectors","elements","getSearchWidgetSelector","pendingPromise","Pending","registerListenerEvents","resolve","bodyPromiseResolver","bodyPromise","WidgetBase","promisesAndResolvers","dropdownMenuContainer","getSearchWidgetDropdownSelector","menuContainer","inputElement","on","async","courseID","e","relatedTarget","dataset","courseid","showLoader","data","Repository","gradeitemFetch","catch","errorTemplateData","message","Templates","render","init","gradeitems","searchGradeitems","afterSelect","FocusLockManager","trapFocus","untrapFocus","addEventListener","courseId","actionUrl","Url","relativeUrl","id","item","itemid","target","value","location","href","stopPropagation","modules","searchTerm","toLowerCase","searchResults","forEach","module","name","includes","push","selected","dropdown","dispatchEvent","Event","bubbles"],"mappings":";;;;;;;ucAsCoB,QACZA,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAAW,OACvEC,eAAiB,IAAIC,iBAC3BC,yBACAF,eAAeG,kBASjBD,uBAAyB,SACvBE,oBAACA,oBAADC,YAAsBA,aAAeC,WAAWC,6BAC9CC,sBAAwBb,SAASC,cAAcC,UAAUC,SAASW,gCAAgC,UAClGC,cAAgBf,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAClFY,aAAeD,cAAcd,cAAc,4CAG/Cc,eAAeE,GAAG,oBAAoBC,MAAAA,UAC9BC,SAAWC,EAAEC,cAAcC,QAAQC,eAEnCZ,WAAWa,WAAWX,6BAGtBY,WAAaC,WAAWC,eAAeR,UAAUS,OAAMV,MAAAA,UACnDW,kBAAoB,cACNT,EAAEU,SAEtBrB,0BACUsB,UAAUC,OAAO,iCAAkCH,uBAK7DJ,OAAS,WAIPd,WAAWsB,KACbpB,sBACAH,YACAe,KAAKS,WACLC,mBACA,KACAC,aAIJ3B,oBAAoBsB,UAAUC,OAAO,0CAA2C,KAGhFK,iBAAiBC,UAAUzB,+CAI7BE,eAAeE,GAAG,oBAAoB,KACpCoB,iBAAiBE,iBAGrBvB,aAAawB,iBAAiB,UAAUpB,UAE9BqB,SADS1B,cAAcd,cAAc,oBACnBqB,QAAQC,SAC1BmB,UAAYC,aAAIC,YAClB,qCACA,CACIC,GAAIJ,SACJK,KAAM,QACNC,OAAQ3B,EAAE4B,OAAOC,QAErB,GAEJC,SAASC,KAAOT,UAEhBtB,EAAEgC,sBAUJjB,iBAAmB,IACd,IACI,CAACkB,QAASC,iBACM,KAAfA,kBACOD,QAEXC,WAAaA,WAAWC,oBAClBC,cAAgB,UACtBH,QAAQI,SAASC,SACMA,OAAOC,KAAKJ,cAChBK,SAASN,aACpBE,cAAcK,KAAKH,WAGpBF,eAUbpB,YAAe0B,iBACX/C,cAAgBf,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAClFY,aAAeD,cAAcd,cAAc,4CAE/Cc,eAAegD,SAAS,QAEtB/C,aAAaiC,OAASa,WACtB9C,aAAaiC,MAAQa,SACrB9C,aAAagD,cAAc,IAAIC,MAAM,SAAU,CAACC,SAAS"} \ No newline at end of file +{"version":3,"file":"grade.min.js","sources":["../src/grade.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 small modal to search grade items within the gradebook.\n *\n * @module gradereport_singleview/grade\n * @copyright 2022 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as FocusLockManager from 'core/local/aria/focuslock';\nimport Pending from 'core/pending';\nimport * as Templates from 'core/templates';\nimport Url from 'core/url';\nimport * as Repository from 'core_grades/searchwidget/repository';\nimport * as WidgetBase from 'core_grades/searchwidget/basewidget';\nimport $ from 'jquery';\nimport * as Selectors from 'core_grades/searchwidget/selectors';\n\n/**\n * Our entry point into starting to build the search widget.\n * It'll eventually, based upon the listeners, open the search widget and allow filtering.\n *\n * @method init\n */\nexport const init = () => {\n if (document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'))) {\n const pendingPromise = new Pending();\n registerListenerEvents();\n pendingPromise.resolve();\n }\n};\n\n/**\n * Register grade item search widget related event listeners.\n *\n * @method registerListenerEvents\n */\nconst registerListenerEvents = () => {\n let {bodyPromiseResolver, bodyPromise} = WidgetBase.promisesAndResolvers();\n const dropdownMenuContainer = document.querySelector(Selectors.elements.getSearchWidgetDropdownSelector('grade'));\n const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'));\n const inputElement = menuContainer.querySelector('input[name=\"itemid\"]');\n\n // Handle the 'shown.bs.dropdown' event (Fired when the dropdown menu is fully displayed).\n $(menuContainer).on('show.bs.dropdown', async(e) => {\n const courseID = e.relatedTarget.dataset.courseid;\n // Display a loading icon in the dropdown menu container until the body promise is resolved.\n await WidgetBase.showLoader(dropdownMenuContainer);\n\n // If an error occurs while fetching the data, display the error within the modal.\n const data = await Repository.gradeitemFetch(courseID).catch(async(e) => {\n const errorTemplateData = {\n 'errormessage': e.message\n };\n bodyPromiseResolver(\n await Templates.render('core_grades/searchwidget/error', errorTemplateData)\n );\n });\n\n // Early return if there is no module data.\n if (data === []) {\n return;\n }\n\n await WidgetBase.init(\n dropdownMenuContainer,\n bodyPromise,\n data.gradeitems,\n searchGradeitems(),\n null,\n afterSelect\n );\n\n // Resolvers for passed functions in the modal creation.\n bodyPromiseResolver(Templates.render('gradereport_singleview/gradesearch_body', []));\n\n // Lock tab control. It has to be locked because the dropdown's role is dialog.\n FocusLockManager.trapFocus(dropdownMenuContainer);\n });\n\n // Handle the 'hide.bs.dropdown' event (Fired when the dropdown menu is being closed).\n $(menuContainer).on('hide.bs.dropdown', () => {\n FocusLockManager.untrapFocus();\n });\n\n inputElement.addEventListener('change', e => {\n const toggle = menuContainer.querySelector('.dropdown-toggle');\n const courseId = toggle.dataset.courseid;\n const actionUrl = Url.relativeUrl(\n '/grade/report/singleview/index.php',\n {\n id: courseId,\n item: 'grade',\n itemid: e.target.value\n },\n false\n );\n location.href = actionUrl;\n\n e.stopPropagation();\n });\n};\n\n/**\n * Define how we want to search and filter grade items when the user decides to input a search value.\n *\n * @method searchGradeitems\n * @returns {function(): function(*, *): (*)}\n */\nconst searchGradeitems = () => {\n return () => {\n return (modules, searchTerm) => {\n if (searchTerm === '') {\n return modules;\n }\n searchTerm = searchTerm.toLowerCase();\n const searchResults = [];\n modules.forEach((module) => {\n const moduleName = module.name.toLowerCase();\n if (moduleName.includes(searchTerm)) {\n searchResults.push(module);\n }\n });\n return searchResults;\n };\n };\n};\n\n/**\n * Define the action to be performed when an item is selected by the search widget.\n *\n * @param {String} selected The selected item's value.\n */\nconst afterSelect = (selected) => {\n const menuContainer = document.querySelector(Selectors.elements.getSearchWidgetSelector('grade'));\n const inputElement = menuContainer.querySelector('input[name=\"itemid\"]');\n\n $(menuContainer).dropdown('hide'); // Otherwise the dropdown stays open when user choose an option using keyboard.\n\n if (inputElement.value != selected) {\n inputElement.value = selected;\n inputElement.dispatchEvent(new Event('change', {bubbles: true}));\n }\n};\n"],"names":["document","querySelector","Selectors","elements","getSearchWidgetSelector","pendingPromise","Pending","registerListenerEvents","resolve","bodyPromiseResolver","bodyPromise","WidgetBase","promisesAndResolvers","dropdownMenuContainer","getSearchWidgetDropdownSelector","menuContainer","inputElement","on","async","courseID","e","relatedTarget","dataset","courseid","showLoader","data","Repository","gradeitemFetch","catch","errorTemplateData","message","Templates","render","init","gradeitems","searchGradeitems","afterSelect","FocusLockManager","trapFocus","untrapFocus","addEventListener","courseId","actionUrl","Url","relativeUrl","id","item","itemid","target","value","location","href","stopPropagation","modules","searchTerm","toLowerCase","searchResults","forEach","module","name","includes","push","selected","dropdown","dispatchEvent","Event","bubbles"],"mappings":";;;;;;;ucAsCoB,QACZA,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAAW,OACvEC,eAAiB,IAAIC,iBAC3BC,yBACAF,eAAeG,kBASjBD,uBAAyB,SACvBE,oBAACA,oBAADC,YAAsBA,aAAeC,WAAWC,6BAC9CC,sBAAwBb,SAASC,cAAcC,UAAUC,SAASW,gCAAgC,UAClGC,cAAgBf,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAClFY,aAAeD,cAAcd,cAAc,4CAG/Cc,eAAeE,GAAG,oBAAoBC,MAAAA,UAC9BC,SAAWC,EAAEC,cAAcC,QAAQC,eAEnCZ,WAAWa,WAAWX,6BAGtBY,WAAaC,WAAWC,eAAeR,UAAUS,OAAMV,MAAAA,UACnDW,kBAAoB,cACNT,EAAEU,SAEtBrB,0BACUsB,UAAUC,OAAO,iCAAkCH,uBAK7DJ,OAAS,WAIPd,WAAWsB,KACbpB,sBACAH,YACAe,KAAKS,WACLC,mBACA,KACAC,aAIJ3B,oBAAoBsB,UAAUC,OAAO,0CAA2C,KAGhFK,iBAAiBC,UAAUzB,+CAI7BE,eAAeE,GAAG,oBAAoB,KACpCoB,iBAAiBE,iBAGrBvB,aAAawB,iBAAiB,UAAUpB,UAE9BqB,SADS1B,cAAcd,cAAc,oBACnBqB,QAAQC,SAC1BmB,UAAYC,aAAIC,YAClB,qCACA,CACIC,GAAIJ,SACJK,KAAM,QACNC,OAAQ3B,EAAE4B,OAAOC,QAErB,GAEJC,SAASC,KAAOT,UAEhBtB,EAAEgC,sBAUJjB,iBAAmB,IACd,IACI,CAACkB,QAASC,iBACM,KAAfA,kBACOD,QAEXC,WAAaA,WAAWC,oBAClBC,cAAgB,UACtBH,QAAQI,SAASC,SACMA,OAAOC,KAAKJ,cAChBK,SAASN,aACpBE,cAAcK,KAAKH,WAGpBF,eAUbpB,YAAe0B,iBACX/C,cAAgBf,SAASC,cAAcC,UAAUC,SAASC,wBAAwB,UAClFY,aAAeD,cAAcd,cAAc,4CAE/Cc,eAAegD,SAAS,QAEtB/C,aAAaiC,OAASa,WACtB9C,aAAaiC,MAAQa,SACrB9C,aAAagD,cAAc,IAAIC,MAAM,SAAU,CAACC,SAAS"} \ No newline at end of file diff --git a/grade/report/singleview/amd/src/grade.js b/grade/report/singleview/amd/src/grade.js index c6834976df4..a0d076f433a 100644 --- a/grade/report/singleview/amd/src/grade.js +++ b/grade/report/singleview/amd/src/grade.js @@ -16,7 +16,7 @@ /** * A small modal to search grade items within the gradebook. * - * @module gradereport_singleview + * @module gradereport_singleview/grade * @copyright 2022 Mathew May * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/build/loadingicon.min.js b/lib/amd/build/loadingicon.min.js index 93bfd0c86ed..b27033a7727 100644 --- a/lib/amd/build/loadingicon.min.js +++ b/lib/amd/build/loadingicon.min.js @@ -1,8 +1,7 @@ /** * Contain the logic for the loading icon. * - * @module core/loading_icon - * @class loading_icon + * @module core/loadingicon * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/build/loadingicon.min.js.map b/lib/amd/build/loadingicon.min.js.map index 9cdf131721c..90f46ca5dad 100644 --- a/lib/amd/build/loadingicon.min.js.map +++ b/lib/amd/build/loadingicon.min.js.map @@ -1 +1 @@ -{"version":3,"file":"loadingicon.min.js","sources":["../src/loadingicon.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 * Contain the logic for the loading icon.\n *\n * @module core/loading_icon\n * @class loading_icon\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates'], function($, Templates) {\n var TEMPLATES = {\n LOADING: 'core/loading',\n };\n\n var getIcon = function() {\n return Templates.render(TEMPLATES.LOADING, {});\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainer\n * @param {jQuery} container The element to add the spinner to\n * @return {Promise} The Promise used to create the icon.\n */\n var addIconToContainer = function(container) {\n return getIcon()\n .then(function(html) {\n var loadingIcon = $(html).hide();\n $(container).append(loadingIcon);\n loadingIcon.fadeIn(150);\n\n return loadingIcon;\n });\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainerWithPromise\n * @param {jQuery} container The element to add the spinner to\n * @param {Promise} loadingIconPromise The jQuery Promise which determines the removal of the icon\n * @return {jQuery} The Promise used to create and then remove the icon.\n */\n var addIconToContainerRemoveOnCompletion = function(container, loadingIconPromise) {\n return getIcon()\n .then(function(html) {\n var loadingIcon = $(html).hide();\n $(container).append(loadingIcon);\n loadingIcon.fadeIn(150);\n\n return $.when(loadingIcon.promise(), loadingIconPromise);\n })\n .then(function(loadingIcon) {\n // Once the content has finished loading and\n // the loading icon has been shown then we can\n // fade the icon away to reveal the content.\n return loadingIcon.fadeOut(100).promise();\n })\n .then(function(loadingIcon) {\n loadingIcon.remove();\n\n return;\n });\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainerWithPromise\n * @param {jQuery} container The element to add the spinner to\n * @return {Promise} A jQuery Promise to resolve when ready\n */\n var addIconToContainerWithPromise = function(container) {\n var loadingIconPromise = $.Deferred();\n\n addIconToContainerRemoveOnCompletion(container, loadingIconPromise);\n\n return loadingIconPromise;\n };\n\n return {\n getIcon: getIcon,\n addIconToContainer: addIconToContainer,\n addIconToContainerWithPromise: addIconToContainerWithPromise,\n addIconToContainerRemoveOnCompletion: addIconToContainerRemoveOnCompletion,\n };\n\n});\n"],"names":["define","$","Templates","TEMPLATES","getIcon","render","addIconToContainerRemoveOnCompletion","container","loadingIconPromise","then","html","loadingIcon","hide","append","fadeIn","when","promise","fadeOut","remove","addIconToContainer","addIconToContainerWithPromise","Deferred"],"mappings":";;;;;;;;AAuBAA,0BAAO,CAAC,SAAU,mBAAmB,SAASC,EAAGC,eACzCC,kBACS,eAGTC,QAAU,kBACHF,UAAUG,OAAOF,kBAAmB,KAiC3CG,qCAAuC,SAASC,UAAWC,2BACpDJ,UACNK,MAAK,SAASC,UACPC,YAAcV,EAAES,MAAME,cAC1BX,EAAEM,WAAWM,OAAOF,aACpBA,YAAYG,OAAO,KAEZb,EAAEc,KAAKJ,YAAYK,UAAWR,uBAExCC,MAAK,SAASE,oBAIJA,YAAYM,QAAQ,KAAKD,aAEnCP,MAAK,SAASE,aACXA,YAAYO,mBAuBb,CACHd,QAASA,QACTe,mBA9DqB,SAASZ,kBACvBH,UACNK,MAAK,SAASC,UACPC,YAAcV,EAAES,MAAME,cAC1BX,EAAEM,WAAWM,OAAOF,aACpBA,YAAYG,OAAO,KAEZH,gBAwDXS,8BAXgC,SAASb,eACrCC,mBAAqBP,EAAEoB,kBAE3Bf,qCAAqCC,UAAWC,oBAEzCA,oBAOPF,qCAAsCA"} \ No newline at end of file +{"version":3,"file":"loadingicon.min.js","sources":["../src/loadingicon.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 * Contain the logic for the loading icon.\n *\n * @module core/loadingicon\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates'], function($, Templates) {\n var TEMPLATES = {\n LOADING: 'core/loading',\n };\n\n var getIcon = function() {\n return Templates.render(TEMPLATES.LOADING, {});\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainer\n * @param {jQuery} container The element to add the spinner to\n * @return {Promise} The Promise used to create the icon.\n */\n var addIconToContainer = function(container) {\n return getIcon()\n .then(function(html) {\n var loadingIcon = $(html).hide();\n $(container).append(loadingIcon);\n loadingIcon.fadeIn(150);\n\n return loadingIcon;\n });\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainerWithPromise\n * @param {jQuery} container The element to add the spinner to\n * @param {Promise} loadingIconPromise The jQuery Promise which determines the removal of the icon\n * @return {jQuery} The Promise used to create and then remove the icon.\n */\n var addIconToContainerRemoveOnCompletion = function(container, loadingIconPromise) {\n return getIcon()\n .then(function(html) {\n var loadingIcon = $(html).hide();\n $(container).append(loadingIcon);\n loadingIcon.fadeIn(150);\n\n return $.when(loadingIcon.promise(), loadingIconPromise);\n })\n .then(function(loadingIcon) {\n // Once the content has finished loading and\n // the loading icon has been shown then we can\n // fade the icon away to reveal the content.\n return loadingIcon.fadeOut(100).promise();\n })\n .then(function(loadingIcon) {\n loadingIcon.remove();\n\n return;\n });\n };\n\n /**\n * Add a loading icon to the end of the specified container and return an unresolved promise.\n *\n * Resolution of the returned promise causes the icon to be faded out and removed.\n *\n * @method addIconToContainerWithPromise\n * @param {jQuery} container The element to add the spinner to\n * @return {Promise} A jQuery Promise to resolve when ready\n */\n var addIconToContainerWithPromise = function(container) {\n var loadingIconPromise = $.Deferred();\n\n addIconToContainerRemoveOnCompletion(container, loadingIconPromise);\n\n return loadingIconPromise;\n };\n\n return {\n getIcon: getIcon,\n addIconToContainer: addIconToContainer,\n addIconToContainerWithPromise: addIconToContainerWithPromise,\n addIconToContainerRemoveOnCompletion: addIconToContainerRemoveOnCompletion,\n };\n\n});\n"],"names":["define","$","Templates","TEMPLATES","getIcon","render","addIconToContainerRemoveOnCompletion","container","loadingIconPromise","then","html","loadingIcon","hide","append","fadeIn","when","promise","fadeOut","remove","addIconToContainer","addIconToContainerWithPromise","Deferred"],"mappings":";;;;;;;AAsBAA,0BAAO,CAAC,SAAU,mBAAmB,SAASC,EAAGC,eACzCC,kBACS,eAGTC,QAAU,kBACHF,UAAUG,OAAOF,kBAAmB,KAiC3CG,qCAAuC,SAASC,UAAWC,2BACpDJ,UACNK,MAAK,SAASC,UACPC,YAAcV,EAAES,MAAME,cAC1BX,EAAEM,WAAWM,OAAOF,aACpBA,YAAYG,OAAO,KAEZb,EAAEc,KAAKJ,YAAYK,UAAWR,uBAExCC,MAAK,SAASE,oBAIJA,YAAYM,QAAQ,KAAKD,aAEnCP,MAAK,SAASE,aACXA,YAAYO,mBAuBb,CACHd,QAASA,QACTe,mBA9DqB,SAASZ,kBACvBH,UACNK,MAAK,SAASC,UACPC,YAAcV,EAAES,MAAME,cAC1BX,EAAEM,WAAWM,OAAOF,aACpBA,YAAYG,OAAO,KAEZH,gBAwDXS,8BAXgC,SAASb,eACrCC,mBAAqBP,EAAEoB,kBAE3Bf,qCAAqCC,UAAWC,oBAEzCA,oBAOPF,qCAAsCA"} \ No newline at end of file diff --git a/lib/amd/build/local/aria/focuslock.min.js b/lib/amd/build/local/aria/focuslock.min.js index ca77ebc08f5..42462334690 100644 --- a/lib/amd/build/local/aria/focuslock.min.js +++ b/lib/amd/build/local/aria/focuslock.min.js @@ -5,7 +5,7 @@ define("core/local/aria/focuslock",["exports","./selectors"],(function(_exports, * This is based on code and examples provided in the ARIA specification. * https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html * - * @module core/tablock + * @module core/local/aria/focuslock * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.untrapFocus=_exports.trapFocus=void 0,_selectors=(obj=_selectors)&&obj.__esModule?obj:{default:obj};const lockRegionStack=[],initialFocusElementStack=[],finalFocusElementStack=[];let lastFocus=null,ignoreFocusChanges=!1,isLocked=!1;const lockHandler=event=>{if(ignoreFocusChanges)return;let lockRegion=getCurrentLockRegion();for(;lockRegion&&!document.contains(lockRegion);)untrapFocus(),lockRegion=getCurrentLockRegion();lockRegion&&(lockRegion.contains(event.target)?lastFocus=event.target:(focusFirstDescendant(),lastFocus==document.activeElement&&focusLastDescendant(),lastFocus=document.activeElement))},focusFirstDescendant=()=>{const lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable));return focusableElements.unshift(lockRegion),focusableElements.some((focusableElement=>attemptFocus(focusableElement)))},focusLastDescendant=()=>{const lockRegion=getCurrentLockRegion(),focusableElements=Array.from(lockRegion.querySelectorAll(_selectors.default.elements.focusable)).reverse();return focusableElements.push(lockRegion),focusableElements.some((focusableElement=>attemptFocus(focusableElement)))},attemptFocus=focusTarget=>{if(!(focusTarget=>{if(focusTarget.tabIndex>0||0===focusTarget.tabIndex&&null!==focusTarget.getAttribute("tabIndex"))return!0;if(focusTarget.disabled)return!1;switch(focusTarget.nodeName){case"A":return!!focusTarget.href&&"ignore"!=focusTarget.rel;case"INPUT":return"hidden"!=focusTarget.type&&"file"!=focusTarget.type;case"BUTTON":case"SELECT":case"TEXTAREA":return!0;default:return!1}})(focusTarget))return!1;ignoreFocusChanges=!0;try{focusTarget.focus()}catch(e){}return ignoreFocusChanges=!1,document.activeElement===focusTarget},getCurrentLockRegion=()=>lockRegionStack[lockRegionStack.length-1];_exports.trapFocus=newLockRegion=>{if((newLockRegion=>{if(newLockRegion===getCurrentLockRegion())return;lockRegionStack.push(newLockRegion);const currentLockRegion=getCurrentLockRegion(),element=document.createElement("div");element.tabIndex=0,element.style.position="fixed",element.style.top=0,element.style.left=0;const initialNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(initialNode,currentLockRegion),initialFocusElementStack.push(initialNode);const finalNode=element.cloneNode();currentLockRegion.parentNode.insertBefore(finalNode,currentLockRegion.nextSibling),finalFocusElementStack.push(finalNode)})(newLockRegion),isLocked||document.addEventListener("focus",lockHandler,!0),!focusFirstDescendant()){const currentLockRegion=getCurrentLockRegion(),originalRegionTabIndex=currentLockRegion.tabIndex;currentLockRegion.tabIndex=0,attemptFocus(currentLockRegion),currentLockRegion.tabIndex=originalRegionTabIndex}lastFocus=document.activeElement,isLocked=!0};const untrapFocus=()=>{(()=>{lockRegionStack.pop();const finalNode=finalFocusElementStack.pop();finalNode&&finalNode.remove();const initialNode=initialFocusElementStack.pop();initialNode&&initialNode.remove()})(),lockRegionStack.length||(document.removeEventListener("focus",lockHandler,!0),lastFocus=null,ignoreFocusChanges=!1,isLocked=!1)};_exports.untrapFocus=untrapFocus})); diff --git a/lib/amd/build/local/aria/focuslock.min.js.map b/lib/amd/build/local/aria/focuslock.min.js.map index b3397770519..f43298a4bae 100644 --- a/lib/amd/build/local/aria/focuslock.min.js.map +++ b/lib/amd/build/local/aria/focuslock.min.js.map @@ -1 +1 @@ -{"version":3,"file":"focuslock.min.js","sources":["../../../src/local/aria/focuslock.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 * Tab locking system.\n *\n * This is based on code and examples provided in the ARIA specification.\n * https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html\n *\n * @module core/tablock\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Selectors from './selectors';\n\nconst lockRegionStack = [];\nconst initialFocusElementStack = [];\nconst finalFocusElementStack = [];\n\nlet lastFocus = null;\nlet ignoreFocusChanges = false;\nlet isLocked = false;\n\n/**\n * The lock handler.\n *\n * This is the item that does a majority of the work.\n * The overall logic from this comes from the examles in the WCAG guidelines.\n *\n * The general idea is that if the focus is not held within by an Element within the lock region, then we replace focus\n * on the first element in the lock region. If the first element is the element previously selected prior to the\n * user-initiated focus change, then instead jump to the last element in the lock region.\n *\n * This gives us a solution which supports focus locking of any kind, which loops in both directions, and which\n * prevents the lock from escaping the modal entirely.\n *\n * @method\n * @param {Event} event The event from the focus change\n */\nconst lockHandler = event => {\n if (ignoreFocusChanges) {\n // The focus change was made by an internal call to set focus.\n return;\n }\n\n // Find the current lock region.\n let lockRegion = getCurrentLockRegion();\n while (lockRegion) {\n if (document.contains(lockRegion)) {\n break;\n }\n\n // The lock region does not exist.\n // Perhaps it was removed without being untrapped.\n untrapFocus();\n lockRegion = getCurrentLockRegion();\n }\n if (!lockRegion) {\n return;\n }\n\n if (lockRegion.contains(event.target)) {\n lastFocus = event.target;\n } else {\n focusFirstDescendant();\n if (lastFocus == document.activeElement) {\n focusLastDescendant();\n }\n lastFocus = document.activeElement;\n }\n};\n\n/**\n * Focus the first descendant of the current lock region.\n *\n * @method\n * @returns {Bool} Whether a node was focused\n */\nconst focusFirstDescendant = () => {\n const lockRegion = getCurrentLockRegion();\n\n // Grab all elements in the lock region and attempt to focus each element until one is focused.\n // We can capture most of this in the query selector, but some cases may still reject focus.\n // For example, a disabled text area cannot be focused, and it becomes difficult to provide a decent query selector\n // to capture this.\n // The use of Array.some just ensures that we stop as soon as we have a successful focus.\n const focusableElements = Array.from(lockRegion.querySelectorAll(Selectors.elements.focusable));\n\n // The lock region itself may be focusable. This is particularly true on Moodle's older dialogues.\n // We must include it in the calculation of descendants to ensure that looping works correctly.\n focusableElements.unshift(lockRegion);\n return focusableElements.some(focusableElement => attemptFocus(focusableElement));\n};\n\n/**\n * Focus the last descendant of the current lock region.\n *\n * @method\n * @returns {Bool} Whether a node was focused\n */\nconst focusLastDescendant = () => {\n const lockRegion = getCurrentLockRegion();\n\n // Grab all elements in the lock region, reverse them, and attempt to focus each element until one is focused.\n // We can capture most of this in the query selector, but some cases may still reject focus.\n // For example, a disabled text area cannot be focused, and it becomes difficult to provide a decent query selector\n // to capture this.\n // The use of Array.some just ensures that we stop as soon as we have a successful focus.\n const focusableElements = Array.from(lockRegion.querySelectorAll(Selectors.elements.focusable)).reverse();\n\n // The lock region itself may be focusable. This is particularly true on Moodle's older dialogues.\n // We must include it in the calculation of descendants to ensure that looping works correctly.\n focusableElements.push(lockRegion);\n return focusableElements.some(focusableElement => attemptFocus(focusableElement));\n};\n\n/**\n * Check whether the supplied focusTarget is actually focusable.\n * There are cases where a normally focusable element can reject focus.\n *\n * Note: This example is a wholesale copy of the WCAG example.\n *\n * @method\n * @param {HTMLElement} focusTarget\n * @returns {Bool}\n */\nconst isFocusable = focusTarget => {\n if (focusTarget.tabIndex > 0 || (focusTarget.tabIndex === 0 && focusTarget.getAttribute('tabIndex') !== null)) {\n return true;\n }\n\n if (focusTarget.disabled) {\n return false;\n }\n\n switch (focusTarget.nodeName) {\n case 'A':\n return !!focusTarget.href && focusTarget.rel != 'ignore';\n case 'INPUT':\n return focusTarget.type != 'hidden' && focusTarget.type != 'file';\n case 'BUTTON':\n case 'SELECT':\n case 'TEXTAREA':\n return true;\n default:\n return false;\n }\n};\n\n/**\n * Attempt to focus the supplied focusTarget.\n *\n * Note: This example is a heavily inspired by the WCAG example.\n *\n * @method\n * @param {HTMLElement} focusTarget\n * @returns {Bool} Whether focus was successful o rnot.\n */\nconst attemptFocus = focusTarget => {\n if (!isFocusable(focusTarget)) {\n return false;\n }\n\n // The ignoreFocusChanges variable prevents the focus event handler from interfering and entering a fight with itself.\n ignoreFocusChanges = true;\n\n try {\n focusTarget.focus();\n } catch (e) {\n // Ignore failures. We will just try to focus the next element in the list.\n // eslint-disable-line\n }\n\n ignoreFocusChanges = false;\n\n // If focus was successful the activeElement will be the one we focused.\n return (document.activeElement === focusTarget);\n};\n\n/**\n * Get the current lock region from the top of the stack.\n *\n * @method\n * @returns {HTMLElement}\n */\nconst getCurrentLockRegion = () => {\n return lockRegionStack[lockRegionStack.length - 1];\n};\n\n/**\n * Add a new lock region to the stack.\n *\n * @method\n * @param {HTMLElement} newLockRegion\n */\nconst addLockRegionToStack = newLockRegion => {\n if (newLockRegion === getCurrentLockRegion()) {\n return;\n }\n\n lockRegionStack.push(newLockRegion);\n const currentLockRegion = getCurrentLockRegion();\n\n // Append an empty div which can be focused just outside of the item locked.\n // This locks tab focus to within the tab region, and does not allow it to extend back into the window by\n // guaranteeing the existence of a tabable item after the lock region which can be focused but which will be caught\n // by the handler.\n const element = document.createElement('div');\n element.tabIndex = 0;\n element.style.position = 'fixed';\n element.style.top = 0;\n element.style.left = 0;\n\n const initialNode = element.cloneNode();\n currentLockRegion.parentNode.insertBefore(initialNode, currentLockRegion);\n initialFocusElementStack.push(initialNode);\n\n const finalNode = element.cloneNode();\n currentLockRegion.parentNode.insertBefore(finalNode, currentLockRegion.nextSibling);\n finalFocusElementStack.push(finalNode);\n};\n\n/**\n * Remove the top lock region from the stack.\n *\n * @method\n */\nconst removeLastLockRegionFromStack = () => {\n // Take the top element off the stack, and replce the current lockRegion value.\n lockRegionStack.pop();\n\n const finalNode = finalFocusElementStack.pop();\n if (finalNode) {\n // The final focus element may have been removed if it was part of a parent item.\n finalNode.remove();\n }\n\n const initialNode = initialFocusElementStack.pop();\n if (initialNode) {\n // The initial focus element may have been removed if it was part of a parent item.\n initialNode.remove();\n }\n};\n\n/**\n * Whether any region is left in the stack.\n *\n * @return {Bool}\n */\nconst hasTrappedRegionsInStack = () => {\n return !!lockRegionStack.length;\n};\n\n/**\n * Start trapping the focus and lock it to the specified newLockRegion.\n *\n * @method\n * @param {HTMLElement} newLockRegion The container to lock focus to\n */\nexport const trapFocus = newLockRegion => {\n // Update the lock region stack.\n // This allows us to support nesting.\n addLockRegionToStack(newLockRegion);\n\n if (!isLocked) {\n // Add the focus handler.\n document.addEventListener('focus', lockHandler, true);\n }\n\n // Attempt to focus on the first item in the lock region.\n if (!focusFirstDescendant()) {\n const currentLockRegion = getCurrentLockRegion();\n\n // No focusable descendants found in the region yet.\n // This can happen when the region is locked before content is generated.\n // Focus on the region itself for now.\n const originalRegionTabIndex = currentLockRegion.tabIndex;\n currentLockRegion.tabIndex = 0;\n attemptFocus(currentLockRegion);\n currentLockRegion.tabIndex = originalRegionTabIndex;\n }\n\n // Keep track of the last item focused.\n lastFocus = document.activeElement;\n\n isLocked = true;\n};\n\n/**\n * Stop trapping the focus.\n *\n * @method\n */\nexport const untrapFocus = () => {\n // Remove the top region from the stack.\n removeLastLockRegionFromStack();\n\n if (hasTrappedRegionsInStack()) {\n // The focus manager still has items in the stack.\n return;\n }\n\n document.removeEventListener('focus', lockHandler, true);\n\n lastFocus = null;\n ignoreFocusChanges = false;\n isLocked = false;\n};\n"],"names":["lockRegionStack","initialFocusElementStack","finalFocusElementStack","lastFocus","ignoreFocusChanges","isLocked","lockHandler","event","lockRegion","getCurrentLockRegion","document","contains","untrapFocus","target","focusFirstDescendant","activeElement","focusLastDescendant","focusableElements","Array","from","querySelectorAll","Selectors","elements","focusable","unshift","some","focusableElement","attemptFocus","reverse","push","focusTarget","tabIndex","getAttribute","disabled","nodeName","href","rel","type","isFocusable","focus","e","length","newLockRegion","currentLockRegion","element","createElement","style","position","top","left","initialNode","cloneNode","parentNode","insertBefore","finalNode","nextSibling","addLockRegionToStack","addEventListener","originalRegionTabIndex","pop","remove","removeLastLockRegionFromStack","removeEventListener"],"mappings":";;;;;;;;;;gLA2BMA,gBAAkB,GAClBC,yBAA2B,GAC3BC,uBAAyB,OAE3BC,UAAY,KACZC,oBAAqB,EACrBC,UAAW,QAkBTC,YAAcC,WACZH,8BAMAI,WAAaC,4BACVD,aACCE,SAASC,SAASH,aAMtBI,cACAJ,WAAaC,uBAEZD,aAIDA,WAAWG,SAASJ,MAAMM,QAC1BV,UAAYI,MAAMM,QAElBC,uBACIX,WAAaO,SAASK,eACtBC,sBAEJb,UAAYO,SAASK,iBAUvBD,qBAAuB,WACnBN,WAAaC,uBAObQ,kBAAoBC,MAAMC,KAAKX,WAAWY,iBAAiBC,mBAAUC,SAASC,mBAIpFN,kBAAkBO,QAAQhB,YACnBS,kBAAkBQ,MAAKC,kBAAoBC,aAAaD,qBAS7DV,oBAAsB,WAClBR,WAAaC,uBAObQ,kBAAoBC,MAAMC,KAAKX,WAAWY,iBAAiBC,mBAAUC,SAASC,YAAYK,iBAIhGX,kBAAkBY,KAAKrB,YAChBS,kBAAkBQ,MAAKC,kBAAoBC,aAAaD,qBA6C7DC,aAAeG,kBAhCDA,CAAAA,iBACZA,YAAYC,SAAW,GAA+B,IAAzBD,YAAYC,UAA2D,OAAzCD,YAAYE,aAAa,mBAC7E,KAGPF,YAAYG,gBACL,SAGHH,YAAYI,cACX,YACQJ,YAAYK,MAA2B,UAAnBL,YAAYM,QACxC,cAC0B,UAApBN,YAAYO,MAAwC,QAApBP,YAAYO,SAClD,aACA,aACA,kBACM,iBAEA,IAcVC,CAAYR,oBACN,EAIX1B,oBAAqB,MAGjB0B,YAAYS,QACd,MAAOC,WAKTpC,oBAAqB,EAGbM,SAASK,gBAAkBe,aASjCrB,qBAAuB,IAClBT,gBAAgBA,gBAAgByC,OAAS,sBAyE3BC,mBAhEIA,CAAAA,mBACrBA,gBAAkBjC,8BAItBT,gBAAgB6B,KAAKa,qBACfC,kBAAoBlC,uBAMpBmC,QAAUlC,SAASmC,cAAc,OACvCD,QAAQb,SAAW,EACnBa,QAAQE,MAAMC,SAAW,QACzBH,QAAQE,MAAME,IAAM,EACpBJ,QAAQE,MAAMG,KAAO,QAEfC,YAAcN,QAAQO,YAC5BR,kBAAkBS,WAAWC,aAAaH,YAAaP,mBACvD1C,yBAAyB4B,KAAKqB,mBAExBI,UAAYV,QAAQO,YAC1BR,kBAAkBS,WAAWC,aAAaC,UAAWX,kBAAkBY,aACvErD,uBAAuB2B,KAAKyB,YA2C5BE,CAAqBd,eAEhBrC,UAEDK,SAAS+C,iBAAiB,QAASnD,aAAa,IAI/CQ,uBAAwB,OACnB6B,kBAAoBlC,uBAKpBiD,uBAAyBf,kBAAkBZ,SACjDY,kBAAkBZ,SAAW,EAC7BJ,aAAagB,mBACbA,kBAAkBZ,SAAW2B,uBAIjCvD,UAAYO,SAASK,cAErBV,UAAW,SAQFO,YAAc,KAlEW,MAElCZ,gBAAgB2D,YAEVL,UAAYpD,uBAAuByD,MACrCL,WAEAA,UAAUM,eAGRV,YAAcjD,yBAAyB0D,MACzCT,aAEAA,YAAYU,UAuDhBC,GA7CS7D,gBAAgByC,SAoDzB/B,SAASoD,oBAAoB,QAASxD,aAAa,GAEnDH,UAAY,KACZC,oBAAqB,EACrBC,UAAW"} \ No newline at end of file +{"version":3,"file":"focuslock.min.js","sources":["../../../src/local/aria/focuslock.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 * Tab locking system.\n *\n * This is based on code and examples provided in the ARIA specification.\n * https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html\n *\n * @module core/local/aria/focuslock\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Selectors from './selectors';\n\nconst lockRegionStack = [];\nconst initialFocusElementStack = [];\nconst finalFocusElementStack = [];\n\nlet lastFocus = null;\nlet ignoreFocusChanges = false;\nlet isLocked = false;\n\n/**\n * The lock handler.\n *\n * This is the item that does a majority of the work.\n * The overall logic from this comes from the examles in the WCAG guidelines.\n *\n * The general idea is that if the focus is not held within by an Element within the lock region, then we replace focus\n * on the first element in the lock region. If the first element is the element previously selected prior to the\n * user-initiated focus change, then instead jump to the last element in the lock region.\n *\n * This gives us a solution which supports focus locking of any kind, which loops in both directions, and which\n * prevents the lock from escaping the modal entirely.\n *\n * @method\n * @param {Event} event The event from the focus change\n */\nconst lockHandler = event => {\n if (ignoreFocusChanges) {\n // The focus change was made by an internal call to set focus.\n return;\n }\n\n // Find the current lock region.\n let lockRegion = getCurrentLockRegion();\n while (lockRegion) {\n if (document.contains(lockRegion)) {\n break;\n }\n\n // The lock region does not exist.\n // Perhaps it was removed without being untrapped.\n untrapFocus();\n lockRegion = getCurrentLockRegion();\n }\n if (!lockRegion) {\n return;\n }\n\n if (lockRegion.contains(event.target)) {\n lastFocus = event.target;\n } else {\n focusFirstDescendant();\n if (lastFocus == document.activeElement) {\n focusLastDescendant();\n }\n lastFocus = document.activeElement;\n }\n};\n\n/**\n * Focus the first descendant of the current lock region.\n *\n * @method\n * @returns {Bool} Whether a node was focused\n */\nconst focusFirstDescendant = () => {\n const lockRegion = getCurrentLockRegion();\n\n // Grab all elements in the lock region and attempt to focus each element until one is focused.\n // We can capture most of this in the query selector, but some cases may still reject focus.\n // For example, a disabled text area cannot be focused, and it becomes difficult to provide a decent query selector\n // to capture this.\n // The use of Array.some just ensures that we stop as soon as we have a successful focus.\n const focusableElements = Array.from(lockRegion.querySelectorAll(Selectors.elements.focusable));\n\n // The lock region itself may be focusable. This is particularly true on Moodle's older dialogues.\n // We must include it in the calculation of descendants to ensure that looping works correctly.\n focusableElements.unshift(lockRegion);\n return focusableElements.some(focusableElement => attemptFocus(focusableElement));\n};\n\n/**\n * Focus the last descendant of the current lock region.\n *\n * @method\n * @returns {Bool} Whether a node was focused\n */\nconst focusLastDescendant = () => {\n const lockRegion = getCurrentLockRegion();\n\n // Grab all elements in the lock region, reverse them, and attempt to focus each element until one is focused.\n // We can capture most of this in the query selector, but some cases may still reject focus.\n // For example, a disabled text area cannot be focused, and it becomes difficult to provide a decent query selector\n // to capture this.\n // The use of Array.some just ensures that we stop as soon as we have a successful focus.\n const focusableElements = Array.from(lockRegion.querySelectorAll(Selectors.elements.focusable)).reverse();\n\n // The lock region itself may be focusable. This is particularly true on Moodle's older dialogues.\n // We must include it in the calculation of descendants to ensure that looping works correctly.\n focusableElements.push(lockRegion);\n return focusableElements.some(focusableElement => attemptFocus(focusableElement));\n};\n\n/**\n * Check whether the supplied focusTarget is actually focusable.\n * There are cases where a normally focusable element can reject focus.\n *\n * Note: This example is a wholesale copy of the WCAG example.\n *\n * @method\n * @param {HTMLElement} focusTarget\n * @returns {Bool}\n */\nconst isFocusable = focusTarget => {\n if (focusTarget.tabIndex > 0 || (focusTarget.tabIndex === 0 && focusTarget.getAttribute('tabIndex') !== null)) {\n return true;\n }\n\n if (focusTarget.disabled) {\n return false;\n }\n\n switch (focusTarget.nodeName) {\n case 'A':\n return !!focusTarget.href && focusTarget.rel != 'ignore';\n case 'INPUT':\n return focusTarget.type != 'hidden' && focusTarget.type != 'file';\n case 'BUTTON':\n case 'SELECT':\n case 'TEXTAREA':\n return true;\n default:\n return false;\n }\n};\n\n/**\n * Attempt to focus the supplied focusTarget.\n *\n * Note: This example is a heavily inspired by the WCAG example.\n *\n * @method\n * @param {HTMLElement} focusTarget\n * @returns {Bool} Whether focus was successful o rnot.\n */\nconst attemptFocus = focusTarget => {\n if (!isFocusable(focusTarget)) {\n return false;\n }\n\n // The ignoreFocusChanges variable prevents the focus event handler from interfering and entering a fight with itself.\n ignoreFocusChanges = true;\n\n try {\n focusTarget.focus();\n } catch (e) {\n // Ignore failures. We will just try to focus the next element in the list.\n // eslint-disable-line\n }\n\n ignoreFocusChanges = false;\n\n // If focus was successful the activeElement will be the one we focused.\n return (document.activeElement === focusTarget);\n};\n\n/**\n * Get the current lock region from the top of the stack.\n *\n * @method\n * @returns {HTMLElement}\n */\nconst getCurrentLockRegion = () => {\n return lockRegionStack[lockRegionStack.length - 1];\n};\n\n/**\n * Add a new lock region to the stack.\n *\n * @method\n * @param {HTMLElement} newLockRegion\n */\nconst addLockRegionToStack = newLockRegion => {\n if (newLockRegion === getCurrentLockRegion()) {\n return;\n }\n\n lockRegionStack.push(newLockRegion);\n const currentLockRegion = getCurrentLockRegion();\n\n // Append an empty div which can be focused just outside of the item locked.\n // This locks tab focus to within the tab region, and does not allow it to extend back into the window by\n // guaranteeing the existence of a tabable item after the lock region which can be focused but which will be caught\n // by the handler.\n const element = document.createElement('div');\n element.tabIndex = 0;\n element.style.position = 'fixed';\n element.style.top = 0;\n element.style.left = 0;\n\n const initialNode = element.cloneNode();\n currentLockRegion.parentNode.insertBefore(initialNode, currentLockRegion);\n initialFocusElementStack.push(initialNode);\n\n const finalNode = element.cloneNode();\n currentLockRegion.parentNode.insertBefore(finalNode, currentLockRegion.nextSibling);\n finalFocusElementStack.push(finalNode);\n};\n\n/**\n * Remove the top lock region from the stack.\n *\n * @method\n */\nconst removeLastLockRegionFromStack = () => {\n // Take the top element off the stack, and replce the current lockRegion value.\n lockRegionStack.pop();\n\n const finalNode = finalFocusElementStack.pop();\n if (finalNode) {\n // The final focus element may have been removed if it was part of a parent item.\n finalNode.remove();\n }\n\n const initialNode = initialFocusElementStack.pop();\n if (initialNode) {\n // The initial focus element may have been removed if it was part of a parent item.\n initialNode.remove();\n }\n};\n\n/**\n * Whether any region is left in the stack.\n *\n * @return {Bool}\n */\nconst hasTrappedRegionsInStack = () => {\n return !!lockRegionStack.length;\n};\n\n/**\n * Start trapping the focus and lock it to the specified newLockRegion.\n *\n * @method\n * @param {HTMLElement} newLockRegion The container to lock focus to\n */\nexport const trapFocus = newLockRegion => {\n // Update the lock region stack.\n // This allows us to support nesting.\n addLockRegionToStack(newLockRegion);\n\n if (!isLocked) {\n // Add the focus handler.\n document.addEventListener('focus', lockHandler, true);\n }\n\n // Attempt to focus on the first item in the lock region.\n if (!focusFirstDescendant()) {\n const currentLockRegion = getCurrentLockRegion();\n\n // No focusable descendants found in the region yet.\n // This can happen when the region is locked before content is generated.\n // Focus on the region itself for now.\n const originalRegionTabIndex = currentLockRegion.tabIndex;\n currentLockRegion.tabIndex = 0;\n attemptFocus(currentLockRegion);\n currentLockRegion.tabIndex = originalRegionTabIndex;\n }\n\n // Keep track of the last item focused.\n lastFocus = document.activeElement;\n\n isLocked = true;\n};\n\n/**\n * Stop trapping the focus.\n *\n * @method\n */\nexport const untrapFocus = () => {\n // Remove the top region from the stack.\n removeLastLockRegionFromStack();\n\n if (hasTrappedRegionsInStack()) {\n // The focus manager still has items in the stack.\n return;\n }\n\n document.removeEventListener('focus', lockHandler, true);\n\n lastFocus = null;\n ignoreFocusChanges = false;\n isLocked = false;\n};\n"],"names":["lockRegionStack","initialFocusElementStack","finalFocusElementStack","lastFocus","ignoreFocusChanges","isLocked","lockHandler","event","lockRegion","getCurrentLockRegion","document","contains","untrapFocus","target","focusFirstDescendant","activeElement","focusLastDescendant","focusableElements","Array","from","querySelectorAll","Selectors","elements","focusable","unshift","some","focusableElement","attemptFocus","reverse","push","focusTarget","tabIndex","getAttribute","disabled","nodeName","href","rel","type","isFocusable","focus","e","length","newLockRegion","currentLockRegion","element","createElement","style","position","top","left","initialNode","cloneNode","parentNode","insertBefore","finalNode","nextSibling","addLockRegionToStack","addEventListener","originalRegionTabIndex","pop","remove","removeLastLockRegionFromStack","removeEventListener"],"mappings":";;;;;;;;;;gLA2BMA,gBAAkB,GAClBC,yBAA2B,GAC3BC,uBAAyB,OAE3BC,UAAY,KACZC,oBAAqB,EACrBC,UAAW,QAkBTC,YAAcC,WACZH,8BAMAI,WAAaC,4BACVD,aACCE,SAASC,SAASH,aAMtBI,cACAJ,WAAaC,uBAEZD,aAIDA,WAAWG,SAASJ,MAAMM,QAC1BV,UAAYI,MAAMM,QAElBC,uBACIX,WAAaO,SAASK,eACtBC,sBAEJb,UAAYO,SAASK,iBAUvBD,qBAAuB,WACnBN,WAAaC,uBAObQ,kBAAoBC,MAAMC,KAAKX,WAAWY,iBAAiBC,mBAAUC,SAASC,mBAIpFN,kBAAkBO,QAAQhB,YACnBS,kBAAkBQ,MAAKC,kBAAoBC,aAAaD,qBAS7DV,oBAAsB,WAClBR,WAAaC,uBAObQ,kBAAoBC,MAAMC,KAAKX,WAAWY,iBAAiBC,mBAAUC,SAASC,YAAYK,iBAIhGX,kBAAkBY,KAAKrB,YAChBS,kBAAkBQ,MAAKC,kBAAoBC,aAAaD,qBA6C7DC,aAAeG,kBAhCDA,CAAAA,iBACZA,YAAYC,SAAW,GAA+B,IAAzBD,YAAYC,UAA2D,OAAzCD,YAAYE,aAAa,mBAC7E,KAGPF,YAAYG,gBACL,SAGHH,YAAYI,cACX,YACQJ,YAAYK,MAA2B,UAAnBL,YAAYM,QACxC,cAC0B,UAApBN,YAAYO,MAAwC,QAApBP,YAAYO,SAClD,aACA,aACA,kBACM,iBAEA,IAcVC,CAAYR,oBACN,EAIX1B,oBAAqB,MAGjB0B,YAAYS,QACd,MAAOC,WAKTpC,oBAAqB,EAGbM,SAASK,gBAAkBe,aASjCrB,qBAAuB,IAClBT,gBAAgBA,gBAAgByC,OAAS,sBAyE3BC,mBAhEIA,CAAAA,mBACrBA,gBAAkBjC,8BAItBT,gBAAgB6B,KAAKa,qBACfC,kBAAoBlC,uBAMpBmC,QAAUlC,SAASmC,cAAc,OACvCD,QAAQb,SAAW,EACnBa,QAAQE,MAAMC,SAAW,QACzBH,QAAQE,MAAME,IAAM,EACpBJ,QAAQE,MAAMG,KAAO,QAEfC,YAAcN,QAAQO,YAC5BR,kBAAkBS,WAAWC,aAAaH,YAAaP,mBACvD1C,yBAAyB4B,KAAKqB,mBAExBI,UAAYV,QAAQO,YAC1BR,kBAAkBS,WAAWC,aAAaC,UAAWX,kBAAkBY,aACvErD,uBAAuB2B,KAAKyB,YA2C5BE,CAAqBd,eAEhBrC,UAEDK,SAAS+C,iBAAiB,QAASnD,aAAa,IAI/CQ,uBAAwB,OACnB6B,kBAAoBlC,uBAKpBiD,uBAAyBf,kBAAkBZ,SACjDY,kBAAkBZ,SAAW,EAC7BJ,aAAagB,mBACbA,kBAAkBZ,SAAW2B,uBAIjCvD,UAAYO,SAASK,cAErBV,UAAW,SAQFO,YAAc,KAlEW,MAElCZ,gBAAgB2D,YAEVL,UAAYpD,uBAAuByD,MACrCL,WAEAA,UAAUM,eAGRV,YAAcjD,yBAAyB0D,MACzCT,aAEAA,YAAYU,UAuDhBC,GA7CS7D,gBAAgByC,SAoDzB/B,SAASoD,oBAAoB,QAASxD,aAAa,GAEnDH,UAAY,KACZC,oBAAqB,EACrBC,UAAW"} \ No newline at end of file diff --git a/lib/amd/build/local/modal/alert.min.js b/lib/amd/build/local/modal/alert.min.js index 8b8fdfeff58..1876e740dd3 100644 --- a/lib/amd/build/local/modal/alert.min.js +++ b/lib/amd/build/local/modal/alert.min.js @@ -2,7 +2,7 @@ define("core/local/modal/alert",["exports","core/modal"],(function(_exports,_mod /** * Alert modal. * - * @module core/modal_alert + * @module core/local/modal/alert * @copyright 2020 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=(obj=_modal)&&obj.__esModule?obj:{default:obj};class _default extends _modal.default{registerEventListeners(){super.registerEventListeners(),this.registerCloseOnCancel()}}return _exports.default=_default,_exports.default})); diff --git a/lib/amd/build/local/modal/alert.min.js.map b/lib/amd/build/local/modal/alert.min.js.map index 0129aa1533c..1227a766902 100644 --- a/lib/amd/build/local/modal/alert.min.js.map +++ b/lib/amd/build/local/modal/alert.min.js.map @@ -1 +1 @@ -{"version":3,"file":"alert.min.js","sources":["../../../src/local/modal/alert.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 * Alert modal.\n *\n * @module core/modal_alert\n * @copyright 2020 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\n\n/**\n * The Alert Modal\n *\n * @class\n * @extends Modal\n */\nexport default class extends Modal {\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on cancel.\n this.registerCloseOnCancel();\n }\n}\n"],"names":["Modal","registerEventListeners","registerCloseOnCancel"],"mappings":";;;;;;;kKA+B6BA,eAIzBC,+BAEUA,8BAGDC"} \ No newline at end of file +{"version":3,"file":"alert.min.js","sources":["../../../src/local/modal/alert.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 * Alert modal.\n *\n * @module core/local/modal/alert\n * @copyright 2020 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\n\n/**\n * The Alert Modal\n *\n * @class\n * @extends Modal\n */\nexport default class extends Modal {\n /**\n * Register all event listeners.\n */\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on cancel.\n this.registerCloseOnCancel();\n }\n}\n"],"names":["Modal","registerEventListeners","registerCloseOnCancel"],"mappings":";;;;;;;kKA+B6BA,eAIzBC,+BAEUA,8BAGDC"} \ No newline at end of file diff --git a/lib/amd/build/local/reactive/debug.min.js b/lib/amd/build/local/reactive/debug.min.js index f91a22571db..3539ba5426a 100644 --- a/lib/amd/build/local/reactive/debug.min.js +++ b/lib/amd/build/local/reactive/debug.min.js @@ -2,7 +2,7 @@ define("core/local/reactive/debug",["exports","core/local/reactive/reactive","co /** * Reactive module debug tools. * - * @module core/reactive/local/reactive/debug + * @module core/local/reactive/debug * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.initDebug=void 0,_reactive=_interopRequireDefault(_reactive),_log=_interopRequireDefault(_log);const reactiveInstances={},reactiveDebuggers={}; diff --git a/lib/amd/build/local/reactive/debug.min.js.map b/lib/amd/build/local/reactive/debug.min.js.map index 7e9b68e277a..033b13f4336 100644 --- a/lib/amd/build/local/reactive/debug.min.js.map +++ b/lib/amd/build/local/reactive/debug.min.js.map @@ -1 +1 @@ -{"version":3,"file":"debug.min.js","sources":["../../../src/local/reactive/debug.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 * Reactive module debug tools.\n *\n * @module core/reactive/local/reactive/debug\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Reactive from 'core/local/reactive/reactive';\nimport log from 'core/log';\n\n// The list of reactives instances.\nconst reactiveInstances = {};\n\n// The reactive debugging objects.\nconst reactiveDebuggers = {};\n\n/**\n * Reactive module debug tools.\n *\n * If debug is enabled, this reactive module will spy all the reactive instances and keep a record\n * of the changes and components they have.\n *\n * It is important to note that the Debug class is also a Reactive module. The debug instance keeps\n * the reactive instances data as its own state. This way it is possible to implement development tools\n * that whatches this data.\n *\n * @class core/reactive/local/reactive/debug/Debug\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass Debug extends Reactive {\n\n /**\n * Set the initial state.\n *\n * @param {object} stateData the initial state data.\n */\n setInitialState(stateData) {\n super.setInitialState(stateData);\n log.debug(`Debug module \"M.reactive\" loaded.`);\n }\n\n /**\n * List the currents page reactives instances.\n */\n get list() {\n return JSON.parse(JSON.stringify(this.state.reactives));\n }\n\n /**\n * Register a new Reactive instance.\n *\n * This method is called every time a \"new Reactive\" is executed.\n *\n * @param {Reactive} instance the reactive instance\n */\n registerNewInstance(instance) {\n\n // Generate a valid variable name for that instance.\n let name = instance.name ?? `instance${this.state.reactives.length}`;\n name = name.replace(/\\W/g, '');\n\n log.debug(`Registering new reactive instance \"M.reactive.${name}\"`);\n\n reactiveInstances[name] = instance;\n reactiveDebuggers[name] = new DebugInstance(reactiveInstances[name]);\n // Register also in the state.\n this.dispatch('putInstance', name, instance);\n // Add debug watchers to instance.\n const refreshMethod = () => {\n this.dispatch('putInstance', name, instance);\n };\n instance.target.addEventListener('readmode:on', refreshMethod);\n instance.target.addEventListener('readmode:off', refreshMethod);\n instance.target.addEventListener('registerComponent:success', refreshMethod);\n instance.target.addEventListener('transaction:end', refreshMethod);\n // We store the last transaction into the state.\n const storeTransaction = ({detail}) => {\n const changes = detail?.changes;\n this.dispatch('lastTransaction', name, changes);\n };\n instance.target.addEventListener('transaction:start', storeTransaction);\n }\n\n /**\n * Returns a debugging object for a specific Reactive instance.\n *\n * A debugging object is a class that wraps a Reactive instance to quick access some of the\n * reactive methods using the browser JS console.\n *\n * @param {string} name the Reactive instance name\n * @returns {DebugInstance} a debug object wrapping the Reactive instance\n */\n debug(name) {\n return reactiveDebuggers[name];\n }\n}\n\n/**\n * The debug state mutations class.\n *\n * @class core/reactive/local/reactive/debug/Mutations\n */\nclass Mutations {\n\n /**\n * Insert or update a new instance into the debug state.\n *\n * @param {StateManager} stateManager the debug state manager\n * @param {string} name the instance name\n * @param {Reactive} instance the reactive instance\n */\n putInstance(stateManager, name, instance) {\n const state = stateManager.state;\n\n stateManager.setReadOnly(false);\n\n if (state.reactives.has(name)) {\n state.reactives.get(name).countcomponents = instance.components.length;\n state.reactives.get(name).readOnly = instance.stateManager.readonly;\n state.reactives.get(name).modified = new Date().getTime();\n } else {\n state.reactives.add({\n id: name,\n countcomponents: instance.components.length,\n readOnly: instance.stateManager.readonly,\n lastChanges: [],\n modified: new Date().getTime(),\n });\n }\n stateManager.setReadOnly(true);\n }\n\n /**\n * Update the lastChanges attribute with a list of changes\n *\n * @param {StateManager} stateManager the debug reactive state\n * @param {string} name tje instance name\n * @param {array} changes the list of changes\n */\n lastTransaction(stateManager, name, changes) {\n if (!changes || changes.length === 0) {\n return;\n }\n\n const state = stateManager.state;\n const lastChanges = ['transaction:start'];\n\n changes.forEach(change => {\n lastChanges.push(change.eventName);\n });\n\n lastChanges.push('transaction:end');\n\n stateManager.setReadOnly(false);\n\n state.reactives.get(name).lastChanges = lastChanges;\n\n stateManager.setReadOnly(true);\n }\n}\n\n/**\n * Class used to debug a specific instance and manipulate the state from the JS console.\n *\n * @class core/reactive/local/reactive/debug/DebugInstance\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass DebugInstance {\n\n /**\n * Constructor.\n *\n * @param {Reactive} instance the reactive instance\n */\n constructor(instance) {\n this.instance = instance;\n // Add some debug data directly into the instance. This way we avoid having attributes\n // that will confuse the console aoutocomplete.\n if (instance._reactiveDebugData === undefined) {\n instance._reactiveDebugData = {\n highlighted: false,\n };\n }\n }\n\n /**\n * Set the read only mode.\n *\n * Quick access to the instance setReadOnly method.\n *\n * @param {bool} value the new read only value\n */\n set readOnly(value) {\n this.instance.stateManager.setReadOnly(value);\n }\n\n /**\n * Get the read only value\n *\n * @returns {bool}\n */\n get readOnly() {\n return this.instance.stateManager.readonly;\n }\n\n /**\n * Return the current state object.\n *\n * @returns {object}\n */\n get state() {\n return this.instance.state;\n }\n\n /**\n * Tooggle the reactive HTML element highlight registered in this reactive instance.\n *\n * @param {bool} value the highlight value\n */\n set highlight(value) {\n this.instance._reactiveDebugData.highlighted = value;\n this.instance.components.forEach(({element}) => {\n const border = (value) ? `thick solid #0000FF` : '';\n element.style.border = border;\n });\n }\n\n /**\n * Get the current highligh value.\n *\n * @returns {bool}\n */\n get highlight() {\n return this.instance._reactiveDebugData.highlighted;\n }\n\n /**\n * List all the components registered in this instance.\n *\n * @returns {array}\n */\n get components() {\n return [...this.instance.components];\n }\n\n /**\n * List all the state changes evenet pending to dispatch.\n *\n * @returns {array}\n */\n get changes() {\n const result = [];\n this.instance.stateManager.eventsToPublish.forEach(\n (element) => {\n result.push(element.eventName);\n }\n );\n return result;\n }\n\n /**\n * Dispatch a change in the state.\n *\n * Usually reactive modules throw an error directly to the components when something\n * goes wrong. However, course editor can directly display a notification.\n *\n * @method dispatch\n * @param {*} args\n */\n async dispatch(...args) {\n this.instance.dispatch(...args);\n }\n\n /**\n * Return all the HTML elements registered in the instance components.\n *\n * @returns {array}\n */\n get elements() {\n const result = [];\n this.instance.components.forEach(({element}) => {\n result.push(element);\n });\n return result;\n }\n\n /**\n * Return a plain copy of the state data.\n *\n * @returns {object}\n */\n get stateData() {\n return JSON.parse(JSON.stringify(this.state));\n }\n\n /**\n * Process an update state array.\n *\n * @param {array} updates an array of update state messages\n */\n processUpdates(updates) {\n this.instance.stateManager.processUpdates(updates);\n }\n}\n\nconst stateChangedEventName = 'core_reactive_debug:stateChanged';\n\n/**\n * Internal state changed event.\n *\n * @method dispatchStateChangedEvent\n * @param {object} detail the full state\n * @param {object} target the custom event target (document if none provided)\n */\nfunction dispatchStateChangedEvent(detail, target) {\n if (target === undefined) {\n target = document;\n }\n target.dispatchEvent(\n new CustomEvent(\n stateChangedEventName,\n {\n bubbles: true,\n detail: detail,\n }\n )\n );\n}\n\n/**\n * The main init method to initialize the reactive debug.\n * @returns {object}\n */\nexport const initDebug = () => {\n const debug = new Debug({\n name: 'CoreReactiveDebug',\n eventName: stateChangedEventName,\n eventDispatch: dispatchStateChangedEvent,\n mutations: new Mutations(),\n state: {\n reactives: [],\n },\n });\n\n // The reactiveDebuggers will be used as a way of access the debug instances but also to register every new\n // instance. To ensure this will update the reactive debug state we add the registerNewInstance method to it.\n reactiveDebuggers.registerNewInstance = debug.registerNewInstance.bind(debug);\n\n return {\n debug,\n debuggers: reactiveDebuggers,\n };\n};\n"],"names":["reactiveInstances","reactiveDebuggers","Debug","Reactive","setInitialState","stateData","debug","list","JSON","parse","stringify","this","state","reactives","registerNewInstance","instance","name","length","replace","DebugInstance","dispatch","refreshMethod","target","addEventListener","_ref","detail","changes","Mutations","putInstance","stateManager","setReadOnly","has","get","countcomponents","components","readOnly","readonly","modified","Date","getTime","add","id","lastChanges","lastTransaction","forEach","change","push","eventName","constructor","undefined","_reactiveDebugData","highlighted","value","highlight","_ref2","element","border","style","result","eventsToPublish","elements","_ref3","processUpdates","updates","dispatchStateChangedEvent","document","dispatchEvent","CustomEvent","bubbles","eventDispatch","mutations","bind","debuggers"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"debug.min.js","sources":["../../../src/local/reactive/debug.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 * Reactive module debug tools.\n *\n * @module core/local/reactive/debug\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Reactive from 'core/local/reactive/reactive';\nimport log from 'core/log';\n\n// The list of reactives instances.\nconst reactiveInstances = {};\n\n// The reactive debugging objects.\nconst reactiveDebuggers = {};\n\n/**\n * Reactive module debug tools.\n *\n * If debug is enabled, this reactive module will spy all the reactive instances and keep a record\n * of the changes and components they have.\n *\n * It is important to note that the Debug class is also a Reactive module. The debug instance keeps\n * the reactive instances data as its own state. This way it is possible to implement development tools\n * that whatches this data.\n *\n * @class core/reactive/local/reactive/debug/Debug\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass Debug extends Reactive {\n\n /**\n * Set the initial state.\n *\n * @param {object} stateData the initial state data.\n */\n setInitialState(stateData) {\n super.setInitialState(stateData);\n log.debug(`Debug module \"M.reactive\" loaded.`);\n }\n\n /**\n * List the currents page reactives instances.\n */\n get list() {\n return JSON.parse(JSON.stringify(this.state.reactives));\n }\n\n /**\n * Register a new Reactive instance.\n *\n * This method is called every time a \"new Reactive\" is executed.\n *\n * @param {Reactive} instance the reactive instance\n */\n registerNewInstance(instance) {\n\n // Generate a valid variable name for that instance.\n let name = instance.name ?? `instance${this.state.reactives.length}`;\n name = name.replace(/\\W/g, '');\n\n log.debug(`Registering new reactive instance \"M.reactive.${name}\"`);\n\n reactiveInstances[name] = instance;\n reactiveDebuggers[name] = new DebugInstance(reactiveInstances[name]);\n // Register also in the state.\n this.dispatch('putInstance', name, instance);\n // Add debug watchers to instance.\n const refreshMethod = () => {\n this.dispatch('putInstance', name, instance);\n };\n instance.target.addEventListener('readmode:on', refreshMethod);\n instance.target.addEventListener('readmode:off', refreshMethod);\n instance.target.addEventListener('registerComponent:success', refreshMethod);\n instance.target.addEventListener('transaction:end', refreshMethod);\n // We store the last transaction into the state.\n const storeTransaction = ({detail}) => {\n const changes = detail?.changes;\n this.dispatch('lastTransaction', name, changes);\n };\n instance.target.addEventListener('transaction:start', storeTransaction);\n }\n\n /**\n * Returns a debugging object for a specific Reactive instance.\n *\n * A debugging object is a class that wraps a Reactive instance to quick access some of the\n * reactive methods using the browser JS console.\n *\n * @param {string} name the Reactive instance name\n * @returns {DebugInstance} a debug object wrapping the Reactive instance\n */\n debug(name) {\n return reactiveDebuggers[name];\n }\n}\n\n/**\n * The debug state mutations class.\n *\n * @class core/reactive/local/reactive/debug/Mutations\n */\nclass Mutations {\n\n /**\n * Insert or update a new instance into the debug state.\n *\n * @param {StateManager} stateManager the debug state manager\n * @param {string} name the instance name\n * @param {Reactive} instance the reactive instance\n */\n putInstance(stateManager, name, instance) {\n const state = stateManager.state;\n\n stateManager.setReadOnly(false);\n\n if (state.reactives.has(name)) {\n state.reactives.get(name).countcomponents = instance.components.length;\n state.reactives.get(name).readOnly = instance.stateManager.readonly;\n state.reactives.get(name).modified = new Date().getTime();\n } else {\n state.reactives.add({\n id: name,\n countcomponents: instance.components.length,\n readOnly: instance.stateManager.readonly,\n lastChanges: [],\n modified: new Date().getTime(),\n });\n }\n stateManager.setReadOnly(true);\n }\n\n /**\n * Update the lastChanges attribute with a list of changes\n *\n * @param {StateManager} stateManager the debug reactive state\n * @param {string} name tje instance name\n * @param {array} changes the list of changes\n */\n lastTransaction(stateManager, name, changes) {\n if (!changes || changes.length === 0) {\n return;\n }\n\n const state = stateManager.state;\n const lastChanges = ['transaction:start'];\n\n changes.forEach(change => {\n lastChanges.push(change.eventName);\n });\n\n lastChanges.push('transaction:end');\n\n stateManager.setReadOnly(false);\n\n state.reactives.get(name).lastChanges = lastChanges;\n\n stateManager.setReadOnly(true);\n }\n}\n\n/**\n * Class used to debug a specific instance and manipulate the state from the JS console.\n *\n * @class core/reactive/local/reactive/debug/DebugInstance\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass DebugInstance {\n\n /**\n * Constructor.\n *\n * @param {Reactive} instance the reactive instance\n */\n constructor(instance) {\n this.instance = instance;\n // Add some debug data directly into the instance. This way we avoid having attributes\n // that will confuse the console aoutocomplete.\n if (instance._reactiveDebugData === undefined) {\n instance._reactiveDebugData = {\n highlighted: false,\n };\n }\n }\n\n /**\n * Set the read only mode.\n *\n * Quick access to the instance setReadOnly method.\n *\n * @param {bool} value the new read only value\n */\n set readOnly(value) {\n this.instance.stateManager.setReadOnly(value);\n }\n\n /**\n * Get the read only value\n *\n * @returns {bool}\n */\n get readOnly() {\n return this.instance.stateManager.readonly;\n }\n\n /**\n * Return the current state object.\n *\n * @returns {object}\n */\n get state() {\n return this.instance.state;\n }\n\n /**\n * Tooggle the reactive HTML element highlight registered in this reactive instance.\n *\n * @param {bool} value the highlight value\n */\n set highlight(value) {\n this.instance._reactiveDebugData.highlighted = value;\n this.instance.components.forEach(({element}) => {\n const border = (value) ? `thick solid #0000FF` : '';\n element.style.border = border;\n });\n }\n\n /**\n * Get the current highligh value.\n *\n * @returns {bool}\n */\n get highlight() {\n return this.instance._reactiveDebugData.highlighted;\n }\n\n /**\n * List all the components registered in this instance.\n *\n * @returns {array}\n */\n get components() {\n return [...this.instance.components];\n }\n\n /**\n * List all the state changes evenet pending to dispatch.\n *\n * @returns {array}\n */\n get changes() {\n const result = [];\n this.instance.stateManager.eventsToPublish.forEach(\n (element) => {\n result.push(element.eventName);\n }\n );\n return result;\n }\n\n /**\n * Dispatch a change in the state.\n *\n * Usually reactive modules throw an error directly to the components when something\n * goes wrong. However, course editor can directly display a notification.\n *\n * @method dispatch\n * @param {*} args\n */\n async dispatch(...args) {\n this.instance.dispatch(...args);\n }\n\n /**\n * Return all the HTML elements registered in the instance components.\n *\n * @returns {array}\n */\n get elements() {\n const result = [];\n this.instance.components.forEach(({element}) => {\n result.push(element);\n });\n return result;\n }\n\n /**\n * Return a plain copy of the state data.\n *\n * @returns {object}\n */\n get stateData() {\n return JSON.parse(JSON.stringify(this.state));\n }\n\n /**\n * Process an update state array.\n *\n * @param {array} updates an array of update state messages\n */\n processUpdates(updates) {\n this.instance.stateManager.processUpdates(updates);\n }\n}\n\nconst stateChangedEventName = 'core_reactive_debug:stateChanged';\n\n/**\n * Internal state changed event.\n *\n * @method dispatchStateChangedEvent\n * @param {object} detail the full state\n * @param {object} target the custom event target (document if none provided)\n */\nfunction dispatchStateChangedEvent(detail, target) {\n if (target === undefined) {\n target = document;\n }\n target.dispatchEvent(\n new CustomEvent(\n stateChangedEventName,\n {\n bubbles: true,\n detail: detail,\n }\n )\n );\n}\n\n/**\n * The main init method to initialize the reactive debug.\n * @returns {object}\n */\nexport const initDebug = () => {\n const debug = new Debug({\n name: 'CoreReactiveDebug',\n eventName: stateChangedEventName,\n eventDispatch: dispatchStateChangedEvent,\n mutations: new Mutations(),\n state: {\n reactives: [],\n },\n });\n\n // The reactiveDebuggers will be used as a way of access the debug instances but also to register every new\n // instance. To ensure this will update the reactive debug state we add the registerNewInstance method to it.\n reactiveDebuggers.registerNewInstance = debug.registerNewInstance.bind(debug);\n\n return {\n debug,\n debuggers: reactiveDebuggers,\n };\n};\n"],"names":["reactiveInstances","reactiveDebuggers","Debug","Reactive","setInitialState","stateData","debug","list","JSON","parse","stringify","this","state","reactives","registerNewInstance","instance","name","length","replace","DebugInstance","dispatch","refreshMethod","target","addEventListener","_ref","detail","changes","Mutations","putInstance","stateManager","setReadOnly","has","get","countcomponents","components","readOnly","readonly","modified","Date","getTime","add","id","lastChanges","lastTransaction","forEach","change","push","eventName","constructor","undefined","_reactiveDebugData","highlighted","value","highlight","_ref2","element","border","style","result","eventsToPublish","elements","_ref3","processUpdates","updates","dispatchStateChangedEvent","document","dispatchEvent","CustomEvent","bubbles","eventDispatch","mutations","bind","debuggers"],"mappings":"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"} \ No newline at end of file diff --git a/lib/amd/build/local/reactive/reactive.min.js b/lib/amd/build/local/reactive/reactive.min.js index 9416ad78075..b1390690dbc 100644 --- a/lib/amd/build/local/reactive/reactive.min.js +++ b/lib/amd/build/local/reactive/reactive.min.js @@ -2,8 +2,8 @@ define("core/local/reactive/reactive",["exports","core/log","core/local/reactive /** * A generic single state reactive module. * - * @module core/reactive/local/reactive/reactive - * @class core/reactive/local/reactive/reactive + * @module core/local/reactive/reactive + * @class core/local/reactive/reactive * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_log=_interopRequireDefault(_log),_statemanager=_interopRequireDefault(_statemanager),_pending=_interopRequireDefault(_pending);let pendingCount=0;return _exports.default=class{constructor(description){var _description$target,_description$mutation;if(void 0===description.eventName||void 0===description.eventDispatch)throw new Error("Reactivity event required");void 0!==description.name&&(this.name=description.name),this.target=null!==(_description$target=description.target)&&void 0!==_description$target?_description$target:document.createTextNode(null),this.eventName=description.eventName,this.eventDispatch=description.eventDispatch,this.stateManager=new _statemanager.default(this.eventDispatch,this.target),this.watchers=new Map([]),this.components=new Set([]),this.mutations=null!==(_description$mutation=description.mutations)&&void 0!==_description$mutation?_description$mutation:{},this.target.addEventListener(this.eventName,this.callWatchersHandler.bind(this)),this.pendingState=new _pending.default("core/reactive:registerInstance".concat(pendingCount++)),void 0!==description.state&&this.setInitialState(description.state),void 0!==M.reactive&&M.reactive.registerNewInstance(this)}callWatchersHandler(event){this.target.dispatchEvent(new CustomEvent(event.detail.action,{bubbles:!1,detail:event.detail}))}setInitialState(stateData){this.pendingState.resolve(),this.stateManager.setInitialState(stateData)}addMutations(newFunctions){void 0!==newFunctions.init&&newFunctions.init(this.stateManager);for(const[mutation,mutationFunction]of Object.entries(newFunctions))this.mutations[mutation]=mutationFunction.bind(newFunctions)}setMutations(manager){this.mutations=manager,void 0!==manager.init&&manager.init(this.stateManager)}get state(){return this.stateManager.state}get(name,id){return this.stateManager.get(name,id)}getInitialStatePromise(){return this.stateManager.getInitialPromise()}registerComponent(component){var _component$name;const componentName=null!==(_component$name=component.name)&&void 0!==_component$name?_component$name:"Unkown component";let dispatchSuccess=()=>{},dispatchFail=dispatchSuccess;if(void 0!==component.dispatchRegistrationSuccess&&(dispatchSuccess=component.dispatchRegistrationSuccess.bind(component)),void 0!==component.dispatchRegistrationFail&&(dispatchFail=component.dispatchRegistrationFail.bind(component)),this.components.has(component))return dispatchSuccess(),component;const pendingPromise=new _pending.default("core/reactive:registerComponent".concat(pendingCount++));let listeners=[],handlers=[];return void 0!==component.getWatchers&&(handlers=component.getWatchers()),handlers.forEach((_ref=>{let{watch:watch,handler:handler}=_ref;if(void 0===watch)throw dispatchFail(),new Error("Missing watch attribute in ".concat(componentName," watcher"));if(void 0===handler)throw dispatchFail(),new Error("Missing handler for watcher ".concat(watch," in ").concat(componentName));const listener=event=>{const currentFocus=document.activeElement;handler.apply(component,[event.detail]),document.activeElement===document.body&&document.body.contains(currentFocus)&¤tFocus.focus()};listeners.push({target:this.target,watch:watch,listener:listener}),this.target.addEventListener(watch,listener)})),void 0!==component.stateReady&&this.getInitialStatePromise().then((state=>(component.stateReady(state),pendingPromise.resolve(),!0))).catch((reason=>{pendingPromise.resolve(),_log.default.error("Initial state in ".concat(componentName," rejected due to: ").concat(reason)),_log.default.error(reason)})),this.watchers.set(component,listeners),this.components.add(component),this.target.dispatchEvent(new CustomEvent("registerComponent:success",{bubbles:!1,detail:{component:component}})),dispatchSuccess(),component}unregisterComponent(component){if(!this.components.has(component))return component;this.components.delete(component);const listeners=this.watchers.get(component);return void 0===listeners||(listeners.forEach((_ref2=>{let{target:target,watch:watch,listener:listener}=_ref2;target.removeEventListener(watch,listener)})),this.watchers.delete(component)),component}async dispatch(actionName){if("string"!=typeof actionName)throw new Error("Dispatch action name must be a string");if("_"===actionName.charAt(0))throw new Error("Illegal Private ".concat(actionName," mutation method dispatch"));if(void 0===this.mutations[actionName])throw new Error("Unkown ".concat(actionName," mutation"));const pendingPromise=new _pending.default("core/reactive:".concat(actionName).concat(pendingCount++)),mutationFunction=this.mutations[actionName];try{for(var _len=arguments.length,params=new Array(_len>1?_len-1:0),_key=1;_key<_len;_key++)params[_key-1]=arguments[_key];await mutationFunction.apply(this.mutations,[this.stateManager,...params]),pendingPromise.resolve()}catch(error){throw this.stateManager.setReadOnly(!0),pendingPromise.resolve(),error}}},_exports.default})); diff --git a/lib/amd/build/local/reactive/reactive.min.js.map b/lib/amd/build/local/reactive/reactive.min.js.map index 30ea814588c..4f85aa63201 100644 --- a/lib/amd/build/local/reactive/reactive.min.js.map +++ b/lib/amd/build/local/reactive/reactive.min.js.map @@ -1 +1 @@ -{"version":3,"file":"reactive.min.js","sources":["../../../src/local/reactive/reactive.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 generic single state reactive module.\n *\n * @module core/reactive/local/reactive/reactive\n * @class core/reactive/local/reactive/reactive\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport log from 'core/log';\nimport StateManager from 'core/local/reactive/statemanager';\nimport Pending from 'core/pending';\n\n// Count the number of pending operations done to ensure we have a unique id for each one.\nlet pendingCount = 0;\n\n/**\n * Set up general reactive class to create a single state application with components.\n *\n * The reactive class is used for registering new UI components and manage the access to the state values\n * and mutations.\n *\n * When a new reactive instance is created, it will contain an empty state and and empty mutations\n * lists. When the state data is ready, the initial state can be loaded using the \"setInitialState\"\n * method. This will protect the state from writing and will trigger all the components \"stateReady\"\n * methods.\n *\n * State can only be altered by mutations. To replace all the mutations with a specific class,\n * use \"setMutations\" method. If you need to just add some new mutation methods, use \"addMutations\".\n *\n * To register new components into a reactive instance, use \"registerComponent\".\n *\n * Inside a component, use \"dispatch\" to invoke a mutation on the state (components can only access\n * the state in read only mode).\n */\nexport default class {\n\n /**\n * The component descriptor data structure.\n *\n * @typedef {object} description\n * @property {string} eventName the custom event name used for state changed events\n * @property {Function} eventDispatch the state update event dispatch function\n * @property {Element} [target] the target of the event dispatch. If not passed a fake element will be created\n * @property {Object} [mutations] an object with state mutations functions\n * @property {Object} [state] an object to initialize the state.\n */\n\n /**\n * Create a basic reactive manager.\n *\n * Note that if your state is not async loaded, you can pass directly on creation by using the\n * description.state attribute. However, this will initialize the state, this means\n * setInitialState will throw an exception because the state is already defined.\n *\n * @param {description} description reactive manager description.\n */\n constructor(description) {\n\n if (description.eventName === undefined || description.eventDispatch === undefined) {\n throw new Error(`Reactivity event required`);\n }\n\n if (description.name !== undefined) {\n this.name = description.name;\n }\n\n // Each reactive instance has its own element anchor to propagate state changes internally.\n // By default the module will create a fake DOM element to target custom events but\n // if all reactive components is constrait to a single element, this can be passed as\n // target in the description.\n this.target = description.target ?? document.createTextNode(null);\n\n this.eventName = description.eventName;\n this.eventDispatch = description.eventDispatch;\n\n // State manager is responsible for dispatch state change events when a mutation happens.\n this.stateManager = new StateManager(this.eventDispatch, this.target);\n\n // An internal registry of watchers and components.\n this.watchers = new Map([]);\n this.components = new Set([]);\n\n // Mutations can be overridden later using setMutations method.\n this.mutations = description.mutations ?? {};\n\n // Register the event to alert watchers when specific state change happens.\n this.target.addEventListener(this.eventName, this.callWatchersHandler.bind(this));\n\n // Add a pending operation waiting for the initial state.\n this.pendingState = new Pending(`core/reactive:registerInstance${pendingCount++}`);\n\n // Set initial state if we already have it.\n if (description.state !== undefined) {\n this.setInitialState(description.state);\n }\n\n // Check if we have a debug instance to register the instance.\n if (M.reactive !== undefined) {\n M.reactive.registerNewInstance(this);\n }\n }\n\n /**\n * State changed listener.\n *\n * This function take any state change and send it to the proper watchers.\n *\n * To prevent internal state changes from colliding with other reactive instances, only the\n * general \"state changed\" is triggered at document level. All the internal changes are\n * triggered at private target level without bubbling. This way any reactive instance can alert\n * only its own watchers.\n *\n * @param {CustomEvent} event\n */\n callWatchersHandler(event) {\n // Execute any registered component watchers.\n this.target.dispatchEvent(new CustomEvent(event.detail.action, {\n bubbles: false,\n detail: event.detail,\n }));\n }\n\n /**\n * Set the initial state.\n *\n * @param {object} stateData the initial state data.\n */\n setInitialState(stateData) {\n this.pendingState.resolve();\n this.stateManager.setInitialState(stateData);\n }\n\n /**\n * Add individual functions to the mutations.\n *\n * Note new mutations will be added to the existing ones. To replace the full mutation\n * object with a new one, use setMutations method.\n *\n * @method addMutations\n * @param {Object} newFunctions an object with new mutation functions.\n */\n addMutations(newFunctions) {\n // Mutations can provide an init method to do some setup in the statemanager.\n if (newFunctions.init !== undefined) {\n newFunctions.init(this.stateManager);\n }\n // Save all mutations.\n for (const [mutation, mutationFunction] of Object.entries(newFunctions)) {\n this.mutations[mutation] = mutationFunction.bind(newFunctions);\n }\n }\n\n /**\n * Replace the current mutations with a new object.\n *\n * This method is designed to override the full mutations class, for example by extending\n * the original one. To add some individual mutations, use addMutations instead.\n *\n * @param {object} manager the new mutations intance\n */\n setMutations(manager) {\n this.mutations = manager;\n // Mutations can provide an init method to do some setup in the statemanager.\n if (manager.init !== undefined) {\n manager.init(this.stateManager);\n }\n }\n\n /**\n * Return the current state.\n *\n * @return {object}\n */\n get state() {\n return this.stateManager.state;\n }\n\n /**\n * Get state data.\n *\n * Components access the state frequently. This convenience method is a shortcut to\n * this.reactive.state.stateManager.get() method.\n *\n * @param {String} name the state object name\n * @param {*} id an optional object id for state maps.\n * @return {Object|undefined} the state object found\n */\n get(name, id) {\n return this.stateManager.get(name, id);\n }\n\n /**\n * Return the initial state promise.\n *\n * Typically, components do not require to use this promise because registerComponent\n * will trigger their stateReady method automatically. But it could be useful for complex\n * components that require to combine state, template and string loadings.\n *\n * @method getState\n * @return {Promise}\n */\n getInitialStatePromise() {\n return this.stateManager.getInitialPromise();\n }\n\n /**\n * Register a new component.\n *\n * Component can provide some optional functions to the reactive module:\n * - getWatchers: returns an array of watchers\n * - stateReady: a method to call when the initial state is loaded\n *\n * It can also provide some optional attributes:\n * - name: the component name (default value: \"Unkown component\") to customize debug messages.\n *\n * The method will also use dispatchRegistrationSuccess and dispatchRegistrationFail. Those\n * are BaseComponent methods to inform parent components of the registration status.\n * Components should not override those methods.\n *\n * @method registerComponent\n * @param {object} component the new component\n * @param {string} [component.name] the component name to display in warnings and errors.\n * @param {Function} [component.dispatchRegistrationSuccess] method to notify registration success\n * @param {Function} [component.dispatchRegistrationFail] method to notify registration fail\n * @param {Function} [component.getWatchers] getter of the component watchers\n * @param {Function} [component.stateReady] method to call when the state is ready\n * @return {object} the registered component\n */\n registerComponent(component) {\n\n // Component name is an optional attribute to customize debug messages.\n const componentName = component.name ?? 'Unkown component';\n\n // Components can provide special methods to communicate registration to parent components.\n let dispatchSuccess = () => {\n return;\n };\n let dispatchFail = dispatchSuccess;\n if (component.dispatchRegistrationSuccess !== undefined) {\n dispatchSuccess = component.dispatchRegistrationSuccess.bind(component);\n }\n if (component.dispatchRegistrationFail !== undefined) {\n dispatchFail = component.dispatchRegistrationFail.bind(component);\n }\n\n // Components can be registered only one time.\n if (this.components.has(component)) {\n dispatchSuccess();\n return component;\n }\n\n // Components are fully registered only when the state ready promise is resolved.\n const pendingPromise = new Pending(`core/reactive:registerComponent${pendingCount++}`);\n\n // Keep track of the event listeners.\n let listeners = [];\n\n // Register watchers.\n let handlers = [];\n if (component.getWatchers !== undefined) {\n handlers = component.getWatchers();\n }\n handlers.forEach(({watch, handler}) => {\n\n if (watch === undefined) {\n dispatchFail();\n throw new Error(`Missing watch attribute in ${componentName} watcher`);\n }\n if (handler === undefined) {\n dispatchFail();\n throw new Error(`Missing handler for watcher ${watch} in ${componentName}`);\n }\n\n const listener = (event) => {\n // Prevent any watcher from losing the page focus.\n const currentFocus = document.activeElement;\n // Execute watcher.\n handler.apply(component, [event.detail]);\n // Restore focus in case it is lost.\n if (document.activeElement === document.body && document.body.contains(currentFocus)) {\n currentFocus.focus();\n }\n };\n\n // Save the listener information in case the component must be unregistered later.\n listeners.push({target: this.target, watch, listener});\n\n // The state manager triggers a general \"state changed\" event at a document level. However,\n // for the internal watchers, each component can listen to specific state changed custom events\n // in the target element. This way we can use the native event loop without colliding with other\n // reactive instances.\n this.target.addEventListener(watch, listener);\n });\n\n // Register state ready function. There's the possibility a component is registered after the initial state\n // is loaded. For those cases we have a state promise to handle this specific state change.\n if (component.stateReady !== undefined) {\n this.getInitialStatePromise()\n .then(state => {\n component.stateReady(state);\n pendingPromise.resolve();\n return true;\n })\n .catch(reason => {\n pendingPromise.resolve();\n log.error(`Initial state in ${componentName} rejected due to: ${reason}`);\n log.error(reason);\n });\n }\n\n // Save unregister data.\n this.watchers.set(component, listeners);\n this.components.add(component);\n\n // Dispatch an event to communicate the registration to the debug module.\n this.target.dispatchEvent(new CustomEvent('registerComponent:success', {\n bubbles: false,\n detail: {component},\n }));\n\n dispatchSuccess();\n return component;\n }\n\n /**\n * Unregister a component and its watchers.\n *\n * @param {object} component the object instance to unregister\n * @returns {object} the deleted component\n */\n unregisterComponent(component) {\n if (!this.components.has(component)) {\n return component;\n }\n\n this.components.delete(component);\n\n // Remove event listeners.\n const listeners = this.watchers.get(component);\n if (listeners === undefined) {\n return component;\n }\n\n listeners.forEach(({target, watch, listener}) => {\n target.removeEventListener(watch, listener);\n });\n\n this.watchers.delete(component);\n\n return component;\n }\n\n /**\n * Dispatch a change in the state.\n *\n * This method is the only way for components to alter the state. Watchers will receive a\n * read only state to prevent illegal changes. If some user action require a state change, the\n * component should dispatch a mutation to trigger all the necessary logic to alter the state.\n *\n * @method dispatch\n * @param {string} actionName the action name (usually the mutation name)\n * @param {mixed} params any number of params the mutation needs.\n */\n async dispatch(actionName, ...params) {\n if (typeof actionName !== 'string') {\n throw new Error(`Dispatch action name must be a string`);\n }\n // JS does not have private methods yet. However, we prevent any component from calling\n // a method starting with \"_\" because the most accepted convention for private methods.\n if (actionName.charAt(0) === '_') {\n throw new Error(`Illegal Private ${actionName} mutation method dispatch`);\n }\n if (this.mutations[actionName] === undefined) {\n throw new Error(`Unkown ${actionName} mutation`);\n }\n\n const pendingPromise = new Pending(`core/reactive:${actionName}${pendingCount++}`);\n\n const mutationFunction = this.mutations[actionName];\n try {\n await mutationFunction.apply(this.mutations, [this.stateManager, ...params]);\n pendingPromise.resolve();\n } catch (error) {\n // Ensure the state is locked.\n this.stateManager.setReadOnly(true);\n pendingPromise.resolve();\n throw error;\n }\n }\n}\n"],"names":["pendingCount","constructor","description","undefined","eventName","eventDispatch","Error","name","target","document","createTextNode","stateManager","StateManager","this","watchers","Map","components","Set","mutations","addEventListener","callWatchersHandler","bind","pendingState","Pending","state","setInitialState","M","reactive","registerNewInstance","event","dispatchEvent","CustomEvent","detail","action","bubbles","stateData","resolve","addMutations","newFunctions","init","mutation","mutationFunction","Object","entries","setMutations","manager","get","id","getInitialStatePromise","getInitialPromise","registerComponent","component","componentName","dispatchSuccess","dispatchFail","dispatchRegistrationSuccess","dispatchRegistrationFail","has","pendingPromise","listeners","handlers","getWatchers","forEach","_ref","watch","handler","listener","currentFocus","activeElement","apply","body","contains","focus","push","stateReady","then","catch","reason","error","set","add","unregisterComponent","delete","_ref2","removeEventListener","actionName","charAt","params","setReadOnly"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"reactive.min.js","sources":["../../../src/local/reactive/reactive.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 generic single state reactive module.\n *\n * @module core/local/reactive/reactive\n * @class core/local/reactive/reactive\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport log from 'core/log';\nimport StateManager from 'core/local/reactive/statemanager';\nimport Pending from 'core/pending';\n\n// Count the number of pending operations done to ensure we have a unique id for each one.\nlet pendingCount = 0;\n\n/**\n * Set up general reactive class to create a single state application with components.\n *\n * The reactive class is used for registering new UI components and manage the access to the state values\n * and mutations.\n *\n * When a new reactive instance is created, it will contain an empty state and and empty mutations\n * lists. When the state data is ready, the initial state can be loaded using the \"setInitialState\"\n * method. This will protect the state from writing and will trigger all the components \"stateReady\"\n * methods.\n *\n * State can only be altered by mutations. To replace all the mutations with a specific class,\n * use \"setMutations\" method. If you need to just add some new mutation methods, use \"addMutations\".\n *\n * To register new components into a reactive instance, use \"registerComponent\".\n *\n * Inside a component, use \"dispatch\" to invoke a mutation on the state (components can only access\n * the state in read only mode).\n */\nexport default class {\n\n /**\n * The component descriptor data structure.\n *\n * @typedef {object} description\n * @property {string} eventName the custom event name used for state changed events\n * @property {Function} eventDispatch the state update event dispatch function\n * @property {Element} [target] the target of the event dispatch. If not passed a fake element will be created\n * @property {Object} [mutations] an object with state mutations functions\n * @property {Object} [state] an object to initialize the state.\n */\n\n /**\n * Create a basic reactive manager.\n *\n * Note that if your state is not async loaded, you can pass directly on creation by using the\n * description.state attribute. However, this will initialize the state, this means\n * setInitialState will throw an exception because the state is already defined.\n *\n * @param {description} description reactive manager description.\n */\n constructor(description) {\n\n if (description.eventName === undefined || description.eventDispatch === undefined) {\n throw new Error(`Reactivity event required`);\n }\n\n if (description.name !== undefined) {\n this.name = description.name;\n }\n\n // Each reactive instance has its own element anchor to propagate state changes internally.\n // By default the module will create a fake DOM element to target custom events but\n // if all reactive components is constrait to a single element, this can be passed as\n // target in the description.\n this.target = description.target ?? document.createTextNode(null);\n\n this.eventName = description.eventName;\n this.eventDispatch = description.eventDispatch;\n\n // State manager is responsible for dispatch state change events when a mutation happens.\n this.stateManager = new StateManager(this.eventDispatch, this.target);\n\n // An internal registry of watchers and components.\n this.watchers = new Map([]);\n this.components = new Set([]);\n\n // Mutations can be overridden later using setMutations method.\n this.mutations = description.mutations ?? {};\n\n // Register the event to alert watchers when specific state change happens.\n this.target.addEventListener(this.eventName, this.callWatchersHandler.bind(this));\n\n // Add a pending operation waiting for the initial state.\n this.pendingState = new Pending(`core/reactive:registerInstance${pendingCount++}`);\n\n // Set initial state if we already have it.\n if (description.state !== undefined) {\n this.setInitialState(description.state);\n }\n\n // Check if we have a debug instance to register the instance.\n if (M.reactive !== undefined) {\n M.reactive.registerNewInstance(this);\n }\n }\n\n /**\n * State changed listener.\n *\n * This function take any state change and send it to the proper watchers.\n *\n * To prevent internal state changes from colliding with other reactive instances, only the\n * general \"state changed\" is triggered at document level. All the internal changes are\n * triggered at private target level without bubbling. This way any reactive instance can alert\n * only its own watchers.\n *\n * @param {CustomEvent} event\n */\n callWatchersHandler(event) {\n // Execute any registered component watchers.\n this.target.dispatchEvent(new CustomEvent(event.detail.action, {\n bubbles: false,\n detail: event.detail,\n }));\n }\n\n /**\n * Set the initial state.\n *\n * @param {object} stateData the initial state data.\n */\n setInitialState(stateData) {\n this.pendingState.resolve();\n this.stateManager.setInitialState(stateData);\n }\n\n /**\n * Add individual functions to the mutations.\n *\n * Note new mutations will be added to the existing ones. To replace the full mutation\n * object with a new one, use setMutations method.\n *\n * @method addMutations\n * @param {Object} newFunctions an object with new mutation functions.\n */\n addMutations(newFunctions) {\n // Mutations can provide an init method to do some setup in the statemanager.\n if (newFunctions.init !== undefined) {\n newFunctions.init(this.stateManager);\n }\n // Save all mutations.\n for (const [mutation, mutationFunction] of Object.entries(newFunctions)) {\n this.mutations[mutation] = mutationFunction.bind(newFunctions);\n }\n }\n\n /**\n * Replace the current mutations with a new object.\n *\n * This method is designed to override the full mutations class, for example by extending\n * the original one. To add some individual mutations, use addMutations instead.\n *\n * @param {object} manager the new mutations intance\n */\n setMutations(manager) {\n this.mutations = manager;\n // Mutations can provide an init method to do some setup in the statemanager.\n if (manager.init !== undefined) {\n manager.init(this.stateManager);\n }\n }\n\n /**\n * Return the current state.\n *\n * @return {object}\n */\n get state() {\n return this.stateManager.state;\n }\n\n /**\n * Get state data.\n *\n * Components access the state frequently. This convenience method is a shortcut to\n * this.reactive.state.stateManager.get() method.\n *\n * @param {String} name the state object name\n * @param {*} id an optional object id for state maps.\n * @return {Object|undefined} the state object found\n */\n get(name, id) {\n return this.stateManager.get(name, id);\n }\n\n /**\n * Return the initial state promise.\n *\n * Typically, components do not require to use this promise because registerComponent\n * will trigger their stateReady method automatically. But it could be useful for complex\n * components that require to combine state, template and string loadings.\n *\n * @method getState\n * @return {Promise}\n */\n getInitialStatePromise() {\n return this.stateManager.getInitialPromise();\n }\n\n /**\n * Register a new component.\n *\n * Component can provide some optional functions to the reactive module:\n * - getWatchers: returns an array of watchers\n * - stateReady: a method to call when the initial state is loaded\n *\n * It can also provide some optional attributes:\n * - name: the component name (default value: \"Unkown component\") to customize debug messages.\n *\n * The method will also use dispatchRegistrationSuccess and dispatchRegistrationFail. Those\n * are BaseComponent methods to inform parent components of the registration status.\n * Components should not override those methods.\n *\n * @method registerComponent\n * @param {object} component the new component\n * @param {string} [component.name] the component name to display in warnings and errors.\n * @param {Function} [component.dispatchRegistrationSuccess] method to notify registration success\n * @param {Function} [component.dispatchRegistrationFail] method to notify registration fail\n * @param {Function} [component.getWatchers] getter of the component watchers\n * @param {Function} [component.stateReady] method to call when the state is ready\n * @return {object} the registered component\n */\n registerComponent(component) {\n\n // Component name is an optional attribute to customize debug messages.\n const componentName = component.name ?? 'Unkown component';\n\n // Components can provide special methods to communicate registration to parent components.\n let dispatchSuccess = () => {\n return;\n };\n let dispatchFail = dispatchSuccess;\n if (component.dispatchRegistrationSuccess !== undefined) {\n dispatchSuccess = component.dispatchRegistrationSuccess.bind(component);\n }\n if (component.dispatchRegistrationFail !== undefined) {\n dispatchFail = component.dispatchRegistrationFail.bind(component);\n }\n\n // Components can be registered only one time.\n if (this.components.has(component)) {\n dispatchSuccess();\n return component;\n }\n\n // Components are fully registered only when the state ready promise is resolved.\n const pendingPromise = new Pending(`core/reactive:registerComponent${pendingCount++}`);\n\n // Keep track of the event listeners.\n let listeners = [];\n\n // Register watchers.\n let handlers = [];\n if (component.getWatchers !== undefined) {\n handlers = component.getWatchers();\n }\n handlers.forEach(({watch, handler}) => {\n\n if (watch === undefined) {\n dispatchFail();\n throw new Error(`Missing watch attribute in ${componentName} watcher`);\n }\n if (handler === undefined) {\n dispatchFail();\n throw new Error(`Missing handler for watcher ${watch} in ${componentName}`);\n }\n\n const listener = (event) => {\n // Prevent any watcher from losing the page focus.\n const currentFocus = document.activeElement;\n // Execute watcher.\n handler.apply(component, [event.detail]);\n // Restore focus in case it is lost.\n if (document.activeElement === document.body && document.body.contains(currentFocus)) {\n currentFocus.focus();\n }\n };\n\n // Save the listener information in case the component must be unregistered later.\n listeners.push({target: this.target, watch, listener});\n\n // The state manager triggers a general \"state changed\" event at a document level. However,\n // for the internal watchers, each component can listen to specific state changed custom events\n // in the target element. This way we can use the native event loop without colliding with other\n // reactive instances.\n this.target.addEventListener(watch, listener);\n });\n\n // Register state ready function. There's the possibility a component is registered after the initial state\n // is loaded. For those cases we have a state promise to handle this specific state change.\n if (component.stateReady !== undefined) {\n this.getInitialStatePromise()\n .then(state => {\n component.stateReady(state);\n pendingPromise.resolve();\n return true;\n })\n .catch(reason => {\n pendingPromise.resolve();\n log.error(`Initial state in ${componentName} rejected due to: ${reason}`);\n log.error(reason);\n });\n }\n\n // Save unregister data.\n this.watchers.set(component, listeners);\n this.components.add(component);\n\n // Dispatch an event to communicate the registration to the debug module.\n this.target.dispatchEvent(new CustomEvent('registerComponent:success', {\n bubbles: false,\n detail: {component},\n }));\n\n dispatchSuccess();\n return component;\n }\n\n /**\n * Unregister a component and its watchers.\n *\n * @param {object} component the object instance to unregister\n * @returns {object} the deleted component\n */\n unregisterComponent(component) {\n if (!this.components.has(component)) {\n return component;\n }\n\n this.components.delete(component);\n\n // Remove event listeners.\n const listeners = this.watchers.get(component);\n if (listeners === undefined) {\n return component;\n }\n\n listeners.forEach(({target, watch, listener}) => {\n target.removeEventListener(watch, listener);\n });\n\n this.watchers.delete(component);\n\n return component;\n }\n\n /**\n * Dispatch a change in the state.\n *\n * This method is the only way for components to alter the state. Watchers will receive a\n * read only state to prevent illegal changes. If some user action require a state change, the\n * component should dispatch a mutation to trigger all the necessary logic to alter the state.\n *\n * @method dispatch\n * @param {string} actionName the action name (usually the mutation name)\n * @param {mixed} params any number of params the mutation needs.\n */\n async dispatch(actionName, ...params) {\n if (typeof actionName !== 'string') {\n throw new Error(`Dispatch action name must be a string`);\n }\n // JS does not have private methods yet. However, we prevent any component from calling\n // a method starting with \"_\" because the most accepted convention for private methods.\n if (actionName.charAt(0) === '_') {\n throw new Error(`Illegal Private ${actionName} mutation method dispatch`);\n }\n if (this.mutations[actionName] === undefined) {\n throw new Error(`Unkown ${actionName} mutation`);\n }\n\n const pendingPromise = new Pending(`core/reactive:${actionName}${pendingCount++}`);\n\n const mutationFunction = this.mutations[actionName];\n try {\n await mutationFunction.apply(this.mutations, [this.stateManager, ...params]);\n pendingPromise.resolve();\n } catch (error) {\n // Ensure the state is locked.\n this.stateManager.setReadOnly(true);\n pendingPromise.resolve();\n throw error;\n }\n }\n}\n"],"names":["pendingCount","constructor","description","undefined","eventName","eventDispatch","Error","name","target","document","createTextNode","stateManager","StateManager","this","watchers","Map","components","Set","mutations","addEventListener","callWatchersHandler","bind","pendingState","Pending","state","setInitialState","M","reactive","registerNewInstance","event","dispatchEvent","CustomEvent","detail","action","bubbles","stateData","resolve","addMutations","newFunctions","init","mutation","mutationFunction","Object","entries","setMutations","manager","get","id","getInitialStatePromise","getInitialPromise","registerComponent","component","componentName","dispatchSuccess","dispatchFail","dispatchRegistrationSuccess","dispatchRegistrationFail","has","pendingPromise","listeners","handlers","getWatchers","forEach","_ref","watch","handler","listener","currentFocus","activeElement","apply","body","contains","focus","push","stateReady","then","catch","reason","error","set","add","unregisterComponent","delete","_ref2","removeEventListener","actionName","charAt","params","setReadOnly"],"mappings":"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"} \ No newline at end of file diff --git a/lib/amd/build/local/reactive/statemanager.min.js b/lib/amd/build/local/reactive/statemanager.min.js index ee802bcc1f9..015e34f9c35 100644 --- a/lib/amd/build/local/reactive/statemanager.min.js +++ b/lib/amd/build/local/reactive/statemanager.min.js @@ -10,8 +10,8 @@ define("core/local/reactive/statemanager",["exports"],(function(_exports){Object * - Proxy handler: a private class to keep track of the state object changes. * - StateMap class: a private class extending Map class that triggers event when a state list is modifed. * - * @module core/local/reactive/stateManager - * @class core/local/reactive/stateManager + * @module core/local/reactive/statemanager + * @class StateManager * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/build/local/reactive/statemanager.min.js.map b/lib/amd/build/local/reactive/statemanager.min.js.map index f8ed06c389a..9310b33768b 100644 --- a/lib/amd/build/local/reactive/statemanager.min.js.map +++ b/lib/amd/build/local/reactive/statemanager.min.js.map @@ -1 +1 @@ -{"version":3,"file":"statemanager.min.js","sources":["../../../src/local/reactive/statemanager.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 * Reactive simple state manager.\n *\n * The state manager contains the state data, trigger update events and\n * can lock and unlock the state data.\n *\n * This file contains the three main elements of the state manager:\n * - State manager: the public class to alter the state, dispatch events and process update messages.\n * - Proxy handler: a private class to keep track of the state object changes.\n * - StateMap class: a private class extending Map class that triggers event when a state list is modifed.\n *\n * @module core/local/reactive/stateManager\n * @class core/local/reactive/stateManager\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * State manager class.\n *\n * This class handle the reactive state and ensure only valid mutations can modify the state.\n * It also provide methods to apply batch state update messages (see processUpdates function doc\n * for more details on update messages).\n *\n * Implementing a deep state manager is complex and will require many frontend resources. To keep\n * the state fast and simple, the state can ONLY store two kind of data:\n * - Object with attributes\n * - Sets of objects with id attributes.\n *\n * This is an example of a valid state:\n *\n * {\n * course: {\n * name: 'course name',\n * shortname: 'courseshort',\n * sectionlist: [21, 34]\n * },\n * sections: [\n * {id: 21, name: 'Topic 1', visible: true},\n * {id: 34, name: 'Topic 2', visible: false,\n * ],\n * }\n *\n * The following cases are NOT allowed at a state ROOT level (throws an exception if they are assigned):\n * - Simple values (strings, boolean...).\n * - Arrays of simple values.\n * - Array of objects without ID attribute (all arrays will be converted to maps and requires an ID).\n *\n * Thanks to those limitations it can simplify the state update messages and the event names. If You\n * need to store simple data, just group them in an object.\n *\n * To grant any state change triggers the proper events, the class uses two private structures:\n * - proxy handler: any object stored in the state is proxied using this class.\n * - StateMap class: any object set in the state will be converted to StateMap using the\n * objects id attribute.\n */\nexport default class StateManager {\n\n /**\n * Create a basic reactive state store.\n *\n * The state manager is meant to work with native JS events. To ensure each reactive module can use\n * it in its own way, the parent element must provide a valid event dispatcher function and an optional\n * DOM element to anchor the event.\n *\n * @param {function} dispatchEvent the function to dispatch the custom event when the state changes.\n * @param {element} target the state changed custom event target (document if none provided)\n */\n constructor(dispatchEvent, target) {\n\n // The dispatch event function.\n /** @package */\n this.dispatchEvent = dispatchEvent;\n\n // The DOM container to trigger events.\n /** @package */\n this.target = target ?? document;\n\n // State can be altered freely until initial state is set.\n /** @package */\n this.readonly = false;\n\n // List of state changes pending to be published as events.\n /** @package */\n this.eventsToPublish = [];\n\n // The update state types functions.\n /** @package */\n this.updateTypes = {\n \"create\": this.defaultCreate.bind(this),\n \"update\": this.defaultUpdate.bind(this),\n \"delete\": this.defaultDelete.bind(this),\n \"put\": this.defaultPut.bind(this),\n \"override\": this.defaultOverride.bind(this),\n \"remove\": this.defaultRemove.bind(this),\n \"prepareFields\": this.defaultPrepareFields.bind(this),\n };\n\n // The state_loaded event is special because it only happens one but all components\n // may react to that state, even if they are registered after the setIinitialState.\n // For these reason we use a promise for that event.\n this.initialPromise = new Promise((resolve) => {\n const initialStateDone = (event) => {\n resolve(event.detail.state);\n };\n this.target.addEventListener('state:loaded', initialStateDone);\n });\n }\n\n /**\n * Loads the initial state.\n *\n * Note this method will trigger a state changed event with \"state:loaded\" actionname.\n *\n * The state mode will be set to read only when the initial state is loaded.\n *\n * @param {object} initialState\n */\n setInitialState(initialState) {\n\n if (this.state !== undefined) {\n throw Error('Initial state can only be initialized ones');\n }\n\n // Create the state object.\n const state = new Proxy({}, new Handler('state', this, true));\n for (const [prop, propValue] of Object.entries(initialState)) {\n state[prop] = propValue;\n }\n this.state = state;\n\n // When the state is loaded we can lock it to prevent illegal changes.\n this.readonly = true;\n\n this.dispatchEvent({\n action: 'state:loaded',\n state: this.state,\n }, this.target);\n }\n\n /**\n * Generate a promise that will be resolved when the initial state is loaded.\n *\n * In most cases the final state will be loaded using an ajax call. This is the reason\n * why states manager are created unlocked and won't be reactive until the initial state is set.\n *\n * @return {Promise} the resulting promise\n */\n getInitialPromise() {\n return this.initialPromise;\n }\n\n /**\n * Locks or unlocks the state to prevent illegal updates.\n *\n * Mutations use this method to modify the state. Once the state is updated, they must\n * block again the state.\n *\n * All changes done while the state is writable will be registered using registerStateAction.\n * When the state is set again to read only the method will trigger _publishEvents to communicate\n * changes to all watchers.\n *\n * @param {bool} readonly if the state is in read only mode enabled\n */\n setReadOnly(readonly) {\n\n this.readonly = readonly;\n\n let mode = 'off';\n\n // When the state is in readonly again is time to publish all pending events.\n if (this.readonly) {\n mode = 'on';\n this._publishEvents();\n }\n\n // Dispatch a read only event.\n this.dispatchEvent({\n action: `readmode:${mode}`,\n state: this.state,\n element: null,\n }, this.target);\n }\n\n /**\n * Add methods to process update state messages.\n *\n * The state manager provide a default update, create and delete methods. However,\n * some applications may require to override the default methods or even add new ones\n * like \"refresh\" or \"error\".\n *\n * @param {Object} newFunctions the new update types functions.\n */\n addUpdateTypes(newFunctions) {\n for (const [updateType, updateFunction] of Object.entries(newFunctions)) {\n if (typeof updateFunction === 'function') {\n this.updateTypes[updateType] = updateFunction.bind(newFunctions);\n }\n }\n }\n\n /**\n * Process a state updates array and do all the necessary changes.\n *\n * Note this method unlocks the state while it is executing and relocks it\n * when finishes.\n *\n * @param {array} updates\n * @param {Object} updateTypes optional functions to override the default update types.\n */\n processUpdates(updates, updateTypes) {\n if (!Array.isArray(updates)) {\n throw Error('State updates must be an array');\n }\n this.setReadOnly(false);\n updates.forEach((update) => {\n if (update.name === undefined) {\n throw Error('Missing state update name');\n }\n this.processUpdate(\n update.name,\n update.action,\n update.fields,\n updateTypes\n );\n });\n this.setReadOnly(true);\n }\n\n /**\n * Process a single state update.\n *\n * Note this method will not lock or unlock the state by itself.\n *\n * @param {string} updateName the state element to update\n * @param {string} action to action to perform\n * @param {object} fields the new data\n * @param {Object} updateTypes optional functions to override the default update types.\n */\n processUpdate(updateName, action, fields, updateTypes) {\n\n if (!fields) {\n throw Error('Missing state update fields');\n }\n\n if (updateTypes === undefined) {\n updateTypes = {};\n }\n\n action = action ?? 'update';\n\n const method = updateTypes[action] ?? this.updateTypes[action];\n\n if (method === undefined) {\n throw Error(`Unkown update action ${action}`);\n }\n\n // Some state data may require some cooking before sending to the\n // state. Reactive instances can overrdide the default fieldDefaults\n // method to add extra logic to all updates.\n const prepareFields = updateTypes.prepareFields ?? this.updateTypes.prepareFields;\n\n method(this, updateName, prepareFields(this, updateName, fields));\n }\n\n /**\n * Prepare fields for processing.\n *\n * This method is used to add default values or calculations from the frontend side.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n * @returns {Object} final fields data\n */\n defaultPrepareFields(stateManager, updateName, fields) {\n return fields;\n }\n\n\n /**\n * Process a create state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultCreate(stateManager, updateName, fields) {\n\n let state = stateManager.state;\n\n // Create can be applied only to lists, not to objects.\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n\n /**\n * Process a delete state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultDelete(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n throw Error(`Inexistent ${updateName} ${fields.id}`);\n }\n\n // Process deletion.\n let state = stateManager.state;\n\n if (state[updateName] instanceof StateMap) {\n state[updateName].delete(fields.id);\n return;\n }\n delete state[updateName];\n }\n\n /**\n * Process a remove state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultRemove(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n return;\n }\n\n // Process deletion.\n let state = stateManager.state;\n\n if (state[updateName] instanceof StateMap) {\n state[updateName].delete(fields.id);\n return;\n }\n delete state[updateName];\n }\n\n /**\n * Process a update state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultUpdate(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n throw Error(`Inexistent ${updateName} ${fields.id}`);\n }\n\n // Execute updates.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n }\n\n /**\n * Process a put state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultPut(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (current) {\n // Update attributes.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n } else {\n // Create new object.\n let state = stateManager.state;\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n }\n\n /**\n * Process an override state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultOverride(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (current) {\n // Remove any unnecessary fields.\n for (const [fieldName] of Object.entries(current)) {\n if (fields[fieldName] === undefined) {\n delete current[fieldName];\n }\n }\n // Update field.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n } else {\n // Create the element if not exists.\n let state = stateManager.state;\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n }\n\n /**\n * Get an element from the state or form an alternative state object.\n *\n * The altstate param is used by external update functions that gets the current\n * state as param.\n *\n * @param {String} name the state object name\n * @param {*} id and object id for state maps.\n * @return {Object|undefined} the state object found\n */\n get(name, id) {\n const state = this.state;\n\n let current = state[name];\n if (current instanceof StateMap) {\n if (id === undefined) {\n throw Error(`Missing id for ${name} state update`);\n }\n current = state[name].get(id);\n }\n\n return current;\n }\n\n /**\n * Register a state modification and generate the necessary events.\n *\n * This method is used mainly by proxy helpers to dispatch state change event.\n * However, mutations can use it to inform components about non reactive changes\n * in the state (only the two first levels of the state are reactive).\n *\n * Each action can produce several events:\n * - The specific attribute updated, created or deleter (example: \"cm.visible:updated\")\n * - The general state object updated, created or deleted (example: \"cm:updated\")\n * - If the element has an ID attribute, the specific event with id (example: \"cm[42].visible:updated\")\n * - If the element has an ID attribute, the general event with id (example: \"cm[42]:updated\")\n * - A generic state update event \"state:update\"\n *\n * @param {string} field the affected state field name\n * @param {string|null} prop the affecter field property (null if affect the full object)\n * @param {string} action the action done (created/updated/deleted)\n * @param {*} data the affected data\n */\n registerStateAction(field, prop, action, data) {\n\n let parentAction = 'updated';\n\n if (prop !== null) {\n this.eventsToPublish.push({\n eventName: `${field}.${prop}:${action}`,\n eventData: data,\n action,\n });\n } else {\n parentAction = action;\n }\n\n // Trigger extra events if the element has an ID attribute.\n if (data.id !== undefined) {\n if (prop !== null) {\n this.eventsToPublish.push({\n eventName: `${field}[${data.id}].${prop}:${action}`,\n eventData: data,\n action,\n });\n }\n this.eventsToPublish.push({\n eventName: `${field}[${data.id}]:${parentAction}`,\n eventData: data,\n action: parentAction,\n });\n }\n\n // Register the general change.\n this.eventsToPublish.push({\n eventName: `${field}:${parentAction}`,\n eventData: data,\n action: parentAction,\n });\n\n // Register state updated event.\n this.eventsToPublish.push({\n eventName: `state:updated`,\n eventData: data,\n action: 'updated',\n });\n }\n\n /**\n * Internal method to publish events.\n *\n * This is a private method, it will be invoked when the state is set back to read only mode.\n */\n _publishEvents() {\n const fieldChanges = this.eventsToPublish;\n this.eventsToPublish = [];\n\n // Dispatch a transaction start event.\n this.dispatchEvent({\n action: 'transaction:start',\n state: this.state,\n element: null,\n changes: fieldChanges,\n }, this.target);\n\n // State changes can be registered in any order. However it will avoid many\n // components errors if they are sorted to have creations-updates-deletes in case\n // some component needs to create or destroy DOM elements before updating them.\n fieldChanges.sort((a, b) => {\n const weights = {\n created: 0,\n updated: 1,\n deleted: 2,\n };\n const aweight = weights[a.action] ?? 0;\n const bweight = weights[b.action] ?? 0;\n // In case both have the same weight, the eventName length decide.\n if (aweight === bweight) {\n return a.eventName.length - b.eventName.length;\n }\n return aweight - bweight;\n });\n\n // List of the published events to prevent redundancies.\n let publishedEvents = new Set();\n\n fieldChanges.forEach((event) => {\n\n const eventkey = `${event.eventName}.${event.eventData.id ?? 0}`;\n\n if (!publishedEvents.has(eventkey)) {\n this.dispatchEvent({\n action: event.eventName,\n state: this.state,\n element: event.eventData\n }, this.target);\n\n publishedEvents.add(eventkey);\n }\n });\n\n // Dispatch a transaction end event.\n this.dispatchEvent({\n action: 'transaction:end',\n state: this.state,\n element: null,\n }, this.target);\n }\n}\n\n// Proxy helpers.\n\n/**\n * The proxy handler.\n *\n * This class will inform any value change directly to the state manager.\n *\n * The proxied variable will throw an error if it is altered when the state manager is\n * in read only mode.\n */\nclass Handler {\n\n /**\n * Class constructor.\n *\n * @param {string} name the variable name used for identify triggered actions\n * @param {StateManager} stateManager the state manager object\n * @param {boolean} proxyValues if new values must be proxied (used only at state root level)\n */\n constructor(name, stateManager, proxyValues) {\n this.name = name;\n this.stateManager = stateManager;\n this.proxyValues = proxyValues ?? false;\n }\n\n /**\n * Set trap to trigger events when the state changes.\n *\n * @param {object} obj the source object (not proxied)\n * @param {string} prop the attribute to set\n * @param {*} value the value to save\n * @param {*} receiver the proxied element to be attached to events\n * @returns {boolean} if the value is set\n */\n set(obj, prop, value, receiver) {\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${prop} value in ${this.name}.`);\n }\n\n // Check any data change.\n if (JSON.stringify(obj[prop]) === JSON.stringify(value)) {\n return true;\n }\n\n const action = (obj[prop] !== undefined) ? 'updated' : 'created';\n\n // Proxy value if necessary (used at state root level).\n if (this.proxyValues) {\n if (Array.isArray(value)) {\n obj[prop] = new StateMap(prop, this.stateManager).loadValues(value);\n } else {\n obj[prop] = new Proxy(value, new Handler(prop, this.stateManager));\n }\n } else {\n obj[prop] = value;\n }\n\n // If the state is not ready yet means the initial state is not yet loaded.\n if (this.stateManager.state === undefined) {\n return true;\n }\n\n this.stateManager.registerStateAction(this.name, prop, action, receiver);\n\n return true;\n }\n\n /**\n * Delete property trap to trigger state change events.\n *\n * @param {*} obj the affected object (not proxied)\n * @param {*} prop the prop to delete\n * @returns {boolean} if prop is deleted\n */\n deleteProperty(obj, prop) {\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to delete ${prop} in ${this.name}.`);\n }\n if (prop in obj) {\n\n delete obj[prop];\n\n this.stateManager.registerStateAction(this.name, prop, 'deleted', obj);\n }\n return true;\n }\n}\n\n/**\n * Class to add events dispatching to the JS Map class.\n *\n * When the state has a list of objects (with IDs) it will be converted into a StateMap.\n * StateMap is used almost in the same way as a regular JS map. Because all elements have an\n * id attribute, it has some specific methods:\n * - add: a convenient method to add an element without specifying the key (\"id\" attribute will be used as a key).\n * - loadValues: to add many elements at once wihout specifying keys (\"id\" attribute will be used).\n *\n * Apart, the main difference between regular Map and MapState is that this one will inform any change to the\n * state manager.\n */\nclass StateMap extends Map {\n\n /**\n * Create a reactive Map.\n *\n * @param {string} name the property name\n * @param {StateManager} stateManager the state manager\n * @param {iterable} iterable an iterable object to create the Map\n */\n constructor(name, stateManager, iterable) {\n // We don't have any \"this\" until be call super.\n super(iterable);\n this.name = name;\n this.stateManager = stateManager;\n }\n\n /**\n * Set an element into the map.\n *\n * Each value needs it's own id attribute. Objects without id will be rejected.\n * The function will throw an error if the value id and the key are not the same.\n *\n * @param {*} key the key to store\n * @param {*} value the value to store\n * @returns {Map} the resulting Map object\n */\n set(key, value) {\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${key} value in ${this.name}.`);\n }\n\n // Normalize keys as string to prevent json decoding errors.\n key = this.normalizeKey(key);\n\n this.checkValue(value);\n\n if (key === undefined || key === null) {\n throw Error('State lists keys cannot be null or undefined');\n }\n\n // ID is mandatory and should be the same as the key.\n if (this.normalizeKey(value.id) !== key) {\n throw new Error(`State error: ${this.name} list element ID (${value.id}) and key (${key}) mismatch`);\n }\n\n const action = (super.has(key)) ? 'updated' : 'created';\n\n // Save proxied data into the list.\n const result = super.set(key, new Proxy(value, new Handler(this.name, this.stateManager)));\n\n // If the state is not ready yet means the initial state is not yet loaded.\n if (this.stateManager.state === undefined) {\n return result;\n }\n\n this.stateManager.registerStateAction(this.name, null, action, super.get(key));\n\n return result;\n }\n\n /**\n * Check if a value is valid to be stored in a a State List.\n *\n * Only objects with id attribute can be stored in State lists.\n *\n * This method throws an error if the value is not valid.\n *\n * @param {object} value (with ID)\n */\n checkValue(value) {\n if (!typeof value === 'object' && value !== null) {\n throw Error('State lists can contain objects only');\n }\n\n if (value.id === undefined) {\n throw Error('State lists elements must contain at least an id attribute');\n }\n }\n\n /**\n * Return a normalized key value for state map.\n *\n * Regular maps uses strict key comparissons but state maps are indexed by ID.JSON conversions\n * and webservices sometimes do unexpected types conversions so we convert any integer key to string.\n *\n * @param {*} key the provided key\n * @returns {string}\n */\n normalizeKey(key) {\n return String(key).valueOf();\n }\n\n /**\n * Insert a new element int a list.\n *\n * Each value needs it's own id attribute. Objects withouts id will be rejected.\n *\n * @param {object} value the value to add (needs an id attribute)\n * @returns {Map} the resulting Map object\n */\n add(value) {\n this.checkValue(value);\n return this.set(value.id, value);\n }\n\n /**\n * Return a state map element.\n *\n * @param {*} key the element id\n * @return {Object}\n */\n get(key) {\n return super.get(this.normalizeKey(key));\n }\n\n /**\n * Check whether an element with the specified key exists or not.\n *\n * @param {*} key the key to find\n * @return {boolean}\n */\n has(key) {\n return super.has(this.normalizeKey(key));\n }\n\n /**\n * Delete an element from the map.\n *\n * @param {*} key\n * @returns {boolean}\n */\n delete(key) {\n // State maps uses only string keys to avoid strict comparisons.\n key = this.normalizeKey(key);\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${key} value in ${this.name}.`);\n }\n\n const previous = super.get(key);\n\n const result = super.delete(key);\n if (!result) {\n return result;\n }\n\n this.stateManager.registerStateAction(this.name, null, 'deleted', previous);\n\n return result;\n }\n\n /**\n * Return a suitable structure for JSON conversion.\n *\n * This function is needed because new values are compared in JSON. StateMap has Private\n * attributes which cannot be stringified (like this.stateManager which will produce an\n * infinite recursivity).\n *\n * @returns {array}\n */\n toJSON() {\n let result = [];\n this.forEach((value) => {\n result.push(value);\n });\n return result;\n }\n\n /**\n * Insert a full list of values using the id attributes as keys.\n *\n * This method is used mainly to initialize the list. Note each element is indexed by its \"id\" attribute.\n * This is a basic restriction of StateMap. All elements need an id attribute, otherwise it won't be saved.\n *\n * @param {iterable} values the values to load\n * @returns {StateMap} return the this value\n */\n loadValues(values) {\n values.forEach((data) => {\n this.checkValue(data);\n let key = data.id;\n let newvalue = new Proxy(data, new Handler(this.name, this.stateManager));\n this.set(key, newvalue);\n });\n return this;\n }\n}\n"],"names":["constructor","dispatchEvent","target","document","readonly","eventsToPublish","updateTypes","this","defaultCreate","bind","defaultUpdate","defaultDelete","defaultPut","defaultOverride","defaultRemove","defaultPrepareFields","initialPromise","Promise","resolve","addEventListener","event","detail","state","setInitialState","initialState","undefined","Error","Proxy","Handler","prop","propValue","Object","entries","action","getInitialPromise","setReadOnly","mode","_publishEvents","element","addUpdateTypes","newFunctions","updateType","updateFunction","processUpdates","updates","Array","isArray","forEach","update","name","processUpdate","fields","updateName","method","prepareFields","stateManager","StateMap","add","get","id","delete","current","fieldName","fieldValue","registerStateAction","field","data","parentAction","push","eventName","eventData","fieldChanges","changes","sort","a","b","weights","created","updated","deleted","aweight","bweight","length","publishedEvents","Set","eventkey","has","proxyValues","set","obj","value","receiver","JSON","stringify","loadValues","deleteProperty","Map","iterable","key","normalizeKey","checkValue","super","result","String","valueOf","previous","toJSON","values","newvalue"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"statemanager.min.js","sources":["../../../src/local/reactive/statemanager.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 * Reactive simple state manager.\n *\n * The state manager contains the state data, trigger update events and\n * can lock and unlock the state data.\n *\n * This file contains the three main elements of the state manager:\n * - State manager: the public class to alter the state, dispatch events and process update messages.\n * - Proxy handler: a private class to keep track of the state object changes.\n * - StateMap class: a private class extending Map class that triggers event when a state list is modifed.\n *\n * @module core/local/reactive/statemanager\n * @class StateManager\n * @copyright 2021 Ferran Recio \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * State manager class.\n *\n * This class handle the reactive state and ensure only valid mutations can modify the state.\n * It also provide methods to apply batch state update messages (see processUpdates function doc\n * for more details on update messages).\n *\n * Implementing a deep state manager is complex and will require many frontend resources. To keep\n * the state fast and simple, the state can ONLY store two kind of data:\n * - Object with attributes\n * - Sets of objects with id attributes.\n *\n * This is an example of a valid state:\n *\n * {\n * course: {\n * name: 'course name',\n * shortname: 'courseshort',\n * sectionlist: [21, 34]\n * },\n * sections: [\n * {id: 21, name: 'Topic 1', visible: true},\n * {id: 34, name: 'Topic 2', visible: false,\n * ],\n * }\n *\n * The following cases are NOT allowed at a state ROOT level (throws an exception if they are assigned):\n * - Simple values (strings, boolean...).\n * - Arrays of simple values.\n * - Array of objects without ID attribute (all arrays will be converted to maps and requires an ID).\n *\n * Thanks to those limitations it can simplify the state update messages and the event names. If You\n * need to store simple data, just group them in an object.\n *\n * To grant any state change triggers the proper events, the class uses two private structures:\n * - proxy handler: any object stored in the state is proxied using this class.\n * - StateMap class: any object set in the state will be converted to StateMap using the\n * objects id attribute.\n */\nexport default class StateManager {\n\n /**\n * Create a basic reactive state store.\n *\n * The state manager is meant to work with native JS events. To ensure each reactive module can use\n * it in its own way, the parent element must provide a valid event dispatcher function and an optional\n * DOM element to anchor the event.\n *\n * @param {function} dispatchEvent the function to dispatch the custom event when the state changes.\n * @param {element} target the state changed custom event target (document if none provided)\n */\n constructor(dispatchEvent, target) {\n\n // The dispatch event function.\n /** @package */\n this.dispatchEvent = dispatchEvent;\n\n // The DOM container to trigger events.\n /** @package */\n this.target = target ?? document;\n\n // State can be altered freely until initial state is set.\n /** @package */\n this.readonly = false;\n\n // List of state changes pending to be published as events.\n /** @package */\n this.eventsToPublish = [];\n\n // The update state types functions.\n /** @package */\n this.updateTypes = {\n \"create\": this.defaultCreate.bind(this),\n \"update\": this.defaultUpdate.bind(this),\n \"delete\": this.defaultDelete.bind(this),\n \"put\": this.defaultPut.bind(this),\n \"override\": this.defaultOverride.bind(this),\n \"remove\": this.defaultRemove.bind(this),\n \"prepareFields\": this.defaultPrepareFields.bind(this),\n };\n\n // The state_loaded event is special because it only happens one but all components\n // may react to that state, even if they are registered after the setIinitialState.\n // For these reason we use a promise for that event.\n this.initialPromise = new Promise((resolve) => {\n const initialStateDone = (event) => {\n resolve(event.detail.state);\n };\n this.target.addEventListener('state:loaded', initialStateDone);\n });\n }\n\n /**\n * Loads the initial state.\n *\n * Note this method will trigger a state changed event with \"state:loaded\" actionname.\n *\n * The state mode will be set to read only when the initial state is loaded.\n *\n * @param {object} initialState\n */\n setInitialState(initialState) {\n\n if (this.state !== undefined) {\n throw Error('Initial state can only be initialized ones');\n }\n\n // Create the state object.\n const state = new Proxy({}, new Handler('state', this, true));\n for (const [prop, propValue] of Object.entries(initialState)) {\n state[prop] = propValue;\n }\n this.state = state;\n\n // When the state is loaded we can lock it to prevent illegal changes.\n this.readonly = true;\n\n this.dispatchEvent({\n action: 'state:loaded',\n state: this.state,\n }, this.target);\n }\n\n /**\n * Generate a promise that will be resolved when the initial state is loaded.\n *\n * In most cases the final state will be loaded using an ajax call. This is the reason\n * why states manager are created unlocked and won't be reactive until the initial state is set.\n *\n * @return {Promise} the resulting promise\n */\n getInitialPromise() {\n return this.initialPromise;\n }\n\n /**\n * Locks or unlocks the state to prevent illegal updates.\n *\n * Mutations use this method to modify the state. Once the state is updated, they must\n * block again the state.\n *\n * All changes done while the state is writable will be registered using registerStateAction.\n * When the state is set again to read only the method will trigger _publishEvents to communicate\n * changes to all watchers.\n *\n * @param {bool} readonly if the state is in read only mode enabled\n */\n setReadOnly(readonly) {\n\n this.readonly = readonly;\n\n let mode = 'off';\n\n // When the state is in readonly again is time to publish all pending events.\n if (this.readonly) {\n mode = 'on';\n this._publishEvents();\n }\n\n // Dispatch a read only event.\n this.dispatchEvent({\n action: `readmode:${mode}`,\n state: this.state,\n element: null,\n }, this.target);\n }\n\n /**\n * Add methods to process update state messages.\n *\n * The state manager provide a default update, create and delete methods. However,\n * some applications may require to override the default methods or even add new ones\n * like \"refresh\" or \"error\".\n *\n * @param {Object} newFunctions the new update types functions.\n */\n addUpdateTypes(newFunctions) {\n for (const [updateType, updateFunction] of Object.entries(newFunctions)) {\n if (typeof updateFunction === 'function') {\n this.updateTypes[updateType] = updateFunction.bind(newFunctions);\n }\n }\n }\n\n /**\n * Process a state updates array and do all the necessary changes.\n *\n * Note this method unlocks the state while it is executing and relocks it\n * when finishes.\n *\n * @param {array} updates\n * @param {Object} updateTypes optional functions to override the default update types.\n */\n processUpdates(updates, updateTypes) {\n if (!Array.isArray(updates)) {\n throw Error('State updates must be an array');\n }\n this.setReadOnly(false);\n updates.forEach((update) => {\n if (update.name === undefined) {\n throw Error('Missing state update name');\n }\n this.processUpdate(\n update.name,\n update.action,\n update.fields,\n updateTypes\n );\n });\n this.setReadOnly(true);\n }\n\n /**\n * Process a single state update.\n *\n * Note this method will not lock or unlock the state by itself.\n *\n * @param {string} updateName the state element to update\n * @param {string} action to action to perform\n * @param {object} fields the new data\n * @param {Object} updateTypes optional functions to override the default update types.\n */\n processUpdate(updateName, action, fields, updateTypes) {\n\n if (!fields) {\n throw Error('Missing state update fields');\n }\n\n if (updateTypes === undefined) {\n updateTypes = {};\n }\n\n action = action ?? 'update';\n\n const method = updateTypes[action] ?? this.updateTypes[action];\n\n if (method === undefined) {\n throw Error(`Unkown update action ${action}`);\n }\n\n // Some state data may require some cooking before sending to the\n // state. Reactive instances can overrdide the default fieldDefaults\n // method to add extra logic to all updates.\n const prepareFields = updateTypes.prepareFields ?? this.updateTypes.prepareFields;\n\n method(this, updateName, prepareFields(this, updateName, fields));\n }\n\n /**\n * Prepare fields for processing.\n *\n * This method is used to add default values or calculations from the frontend side.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n * @returns {Object} final fields data\n */\n defaultPrepareFields(stateManager, updateName, fields) {\n return fields;\n }\n\n\n /**\n * Process a create state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultCreate(stateManager, updateName, fields) {\n\n let state = stateManager.state;\n\n // Create can be applied only to lists, not to objects.\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n\n /**\n * Process a delete state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultDelete(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n throw Error(`Inexistent ${updateName} ${fields.id}`);\n }\n\n // Process deletion.\n let state = stateManager.state;\n\n if (state[updateName] instanceof StateMap) {\n state[updateName].delete(fields.id);\n return;\n }\n delete state[updateName];\n }\n\n /**\n * Process a remove state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultRemove(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n return;\n }\n\n // Process deletion.\n let state = stateManager.state;\n\n if (state[updateName] instanceof StateMap) {\n state[updateName].delete(fields.id);\n return;\n }\n delete state[updateName];\n }\n\n /**\n * Process a update state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultUpdate(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (!current) {\n throw Error(`Inexistent ${updateName} ${fields.id}`);\n }\n\n // Execute updates.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n }\n\n /**\n * Process a put state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultPut(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (current) {\n // Update attributes.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n } else {\n // Create new object.\n let state = stateManager.state;\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n }\n\n /**\n * Process an override state message.\n *\n * @param {Object} stateManager the state manager\n * @param {String} updateName the state element to update\n * @param {Object} fields the new data\n */\n defaultOverride(stateManager, updateName, fields) {\n\n // Get the current value.\n let current = stateManager.get(updateName, fields.id);\n if (current) {\n // Remove any unnecessary fields.\n for (const [fieldName] of Object.entries(current)) {\n if (fields[fieldName] === undefined) {\n delete current[fieldName];\n }\n }\n // Update field.\n for (const [fieldName, fieldValue] of Object.entries(fields)) {\n current[fieldName] = fieldValue;\n }\n } else {\n // Create the element if not exists.\n let state = stateManager.state;\n if (state[updateName] instanceof StateMap) {\n state[updateName].add(fields);\n return;\n }\n state[updateName] = fields;\n }\n }\n\n /**\n * Get an element from the state or form an alternative state object.\n *\n * The altstate param is used by external update functions that gets the current\n * state as param.\n *\n * @param {String} name the state object name\n * @param {*} id and object id for state maps.\n * @return {Object|undefined} the state object found\n */\n get(name, id) {\n const state = this.state;\n\n let current = state[name];\n if (current instanceof StateMap) {\n if (id === undefined) {\n throw Error(`Missing id for ${name} state update`);\n }\n current = state[name].get(id);\n }\n\n return current;\n }\n\n /**\n * Register a state modification and generate the necessary events.\n *\n * This method is used mainly by proxy helpers to dispatch state change event.\n * However, mutations can use it to inform components about non reactive changes\n * in the state (only the two first levels of the state are reactive).\n *\n * Each action can produce several events:\n * - The specific attribute updated, created or deleter (example: \"cm.visible:updated\")\n * - The general state object updated, created or deleted (example: \"cm:updated\")\n * - If the element has an ID attribute, the specific event with id (example: \"cm[42].visible:updated\")\n * - If the element has an ID attribute, the general event with id (example: \"cm[42]:updated\")\n * - A generic state update event \"state:update\"\n *\n * @param {string} field the affected state field name\n * @param {string|null} prop the affecter field property (null if affect the full object)\n * @param {string} action the action done (created/updated/deleted)\n * @param {*} data the affected data\n */\n registerStateAction(field, prop, action, data) {\n\n let parentAction = 'updated';\n\n if (prop !== null) {\n this.eventsToPublish.push({\n eventName: `${field}.${prop}:${action}`,\n eventData: data,\n action,\n });\n } else {\n parentAction = action;\n }\n\n // Trigger extra events if the element has an ID attribute.\n if (data.id !== undefined) {\n if (prop !== null) {\n this.eventsToPublish.push({\n eventName: `${field}[${data.id}].${prop}:${action}`,\n eventData: data,\n action,\n });\n }\n this.eventsToPublish.push({\n eventName: `${field}[${data.id}]:${parentAction}`,\n eventData: data,\n action: parentAction,\n });\n }\n\n // Register the general change.\n this.eventsToPublish.push({\n eventName: `${field}:${parentAction}`,\n eventData: data,\n action: parentAction,\n });\n\n // Register state updated event.\n this.eventsToPublish.push({\n eventName: `state:updated`,\n eventData: data,\n action: 'updated',\n });\n }\n\n /**\n * Internal method to publish events.\n *\n * This is a private method, it will be invoked when the state is set back to read only mode.\n */\n _publishEvents() {\n const fieldChanges = this.eventsToPublish;\n this.eventsToPublish = [];\n\n // Dispatch a transaction start event.\n this.dispatchEvent({\n action: 'transaction:start',\n state: this.state,\n element: null,\n changes: fieldChanges,\n }, this.target);\n\n // State changes can be registered in any order. However it will avoid many\n // components errors if they are sorted to have creations-updates-deletes in case\n // some component needs to create or destroy DOM elements before updating them.\n fieldChanges.sort((a, b) => {\n const weights = {\n created: 0,\n updated: 1,\n deleted: 2,\n };\n const aweight = weights[a.action] ?? 0;\n const bweight = weights[b.action] ?? 0;\n // In case both have the same weight, the eventName length decide.\n if (aweight === bweight) {\n return a.eventName.length - b.eventName.length;\n }\n return aweight - bweight;\n });\n\n // List of the published events to prevent redundancies.\n let publishedEvents = new Set();\n\n fieldChanges.forEach((event) => {\n\n const eventkey = `${event.eventName}.${event.eventData.id ?? 0}`;\n\n if (!publishedEvents.has(eventkey)) {\n this.dispatchEvent({\n action: event.eventName,\n state: this.state,\n element: event.eventData\n }, this.target);\n\n publishedEvents.add(eventkey);\n }\n });\n\n // Dispatch a transaction end event.\n this.dispatchEvent({\n action: 'transaction:end',\n state: this.state,\n element: null,\n }, this.target);\n }\n}\n\n// Proxy helpers.\n\n/**\n * The proxy handler.\n *\n * This class will inform any value change directly to the state manager.\n *\n * The proxied variable will throw an error if it is altered when the state manager is\n * in read only mode.\n */\nclass Handler {\n\n /**\n * Class constructor.\n *\n * @param {string} name the variable name used for identify triggered actions\n * @param {StateManager} stateManager the state manager object\n * @param {boolean} proxyValues if new values must be proxied (used only at state root level)\n */\n constructor(name, stateManager, proxyValues) {\n this.name = name;\n this.stateManager = stateManager;\n this.proxyValues = proxyValues ?? false;\n }\n\n /**\n * Set trap to trigger events when the state changes.\n *\n * @param {object} obj the source object (not proxied)\n * @param {string} prop the attribute to set\n * @param {*} value the value to save\n * @param {*} receiver the proxied element to be attached to events\n * @returns {boolean} if the value is set\n */\n set(obj, prop, value, receiver) {\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${prop} value in ${this.name}.`);\n }\n\n // Check any data change.\n if (JSON.stringify(obj[prop]) === JSON.stringify(value)) {\n return true;\n }\n\n const action = (obj[prop] !== undefined) ? 'updated' : 'created';\n\n // Proxy value if necessary (used at state root level).\n if (this.proxyValues) {\n if (Array.isArray(value)) {\n obj[prop] = new StateMap(prop, this.stateManager).loadValues(value);\n } else {\n obj[prop] = new Proxy(value, new Handler(prop, this.stateManager));\n }\n } else {\n obj[prop] = value;\n }\n\n // If the state is not ready yet means the initial state is not yet loaded.\n if (this.stateManager.state === undefined) {\n return true;\n }\n\n this.stateManager.registerStateAction(this.name, prop, action, receiver);\n\n return true;\n }\n\n /**\n * Delete property trap to trigger state change events.\n *\n * @param {*} obj the affected object (not proxied)\n * @param {*} prop the prop to delete\n * @returns {boolean} if prop is deleted\n */\n deleteProperty(obj, prop) {\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to delete ${prop} in ${this.name}.`);\n }\n if (prop in obj) {\n\n delete obj[prop];\n\n this.stateManager.registerStateAction(this.name, prop, 'deleted', obj);\n }\n return true;\n }\n}\n\n/**\n * Class to add events dispatching to the JS Map class.\n *\n * When the state has a list of objects (with IDs) it will be converted into a StateMap.\n * StateMap is used almost in the same way as a regular JS map. Because all elements have an\n * id attribute, it has some specific methods:\n * - add: a convenient method to add an element without specifying the key (\"id\" attribute will be used as a key).\n * - loadValues: to add many elements at once wihout specifying keys (\"id\" attribute will be used).\n *\n * Apart, the main difference between regular Map and MapState is that this one will inform any change to the\n * state manager.\n */\nclass StateMap extends Map {\n\n /**\n * Create a reactive Map.\n *\n * @param {string} name the property name\n * @param {StateManager} stateManager the state manager\n * @param {iterable} iterable an iterable object to create the Map\n */\n constructor(name, stateManager, iterable) {\n // We don't have any \"this\" until be call super.\n super(iterable);\n this.name = name;\n this.stateManager = stateManager;\n }\n\n /**\n * Set an element into the map.\n *\n * Each value needs it's own id attribute. Objects without id will be rejected.\n * The function will throw an error if the value id and the key are not the same.\n *\n * @param {*} key the key to store\n * @param {*} value the value to store\n * @returns {Map} the resulting Map object\n */\n set(key, value) {\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${key} value in ${this.name}.`);\n }\n\n // Normalize keys as string to prevent json decoding errors.\n key = this.normalizeKey(key);\n\n this.checkValue(value);\n\n if (key === undefined || key === null) {\n throw Error('State lists keys cannot be null or undefined');\n }\n\n // ID is mandatory and should be the same as the key.\n if (this.normalizeKey(value.id) !== key) {\n throw new Error(`State error: ${this.name} list element ID (${value.id}) and key (${key}) mismatch`);\n }\n\n const action = (super.has(key)) ? 'updated' : 'created';\n\n // Save proxied data into the list.\n const result = super.set(key, new Proxy(value, new Handler(this.name, this.stateManager)));\n\n // If the state is not ready yet means the initial state is not yet loaded.\n if (this.stateManager.state === undefined) {\n return result;\n }\n\n this.stateManager.registerStateAction(this.name, null, action, super.get(key));\n\n return result;\n }\n\n /**\n * Check if a value is valid to be stored in a a State List.\n *\n * Only objects with id attribute can be stored in State lists.\n *\n * This method throws an error if the value is not valid.\n *\n * @param {object} value (with ID)\n */\n checkValue(value) {\n if (!typeof value === 'object' && value !== null) {\n throw Error('State lists can contain objects only');\n }\n\n if (value.id === undefined) {\n throw Error('State lists elements must contain at least an id attribute');\n }\n }\n\n /**\n * Return a normalized key value for state map.\n *\n * Regular maps uses strict key comparissons but state maps are indexed by ID.JSON conversions\n * and webservices sometimes do unexpected types conversions so we convert any integer key to string.\n *\n * @param {*} key the provided key\n * @returns {string}\n */\n normalizeKey(key) {\n return String(key).valueOf();\n }\n\n /**\n * Insert a new element int a list.\n *\n * Each value needs it's own id attribute. Objects withouts id will be rejected.\n *\n * @param {object} value the value to add (needs an id attribute)\n * @returns {Map} the resulting Map object\n */\n add(value) {\n this.checkValue(value);\n return this.set(value.id, value);\n }\n\n /**\n * Return a state map element.\n *\n * @param {*} key the element id\n * @return {Object}\n */\n get(key) {\n return super.get(this.normalizeKey(key));\n }\n\n /**\n * Check whether an element with the specified key exists or not.\n *\n * @param {*} key the key to find\n * @return {boolean}\n */\n has(key) {\n return super.has(this.normalizeKey(key));\n }\n\n /**\n * Delete an element from the map.\n *\n * @param {*} key\n * @returns {boolean}\n */\n delete(key) {\n // State maps uses only string keys to avoid strict comparisons.\n key = this.normalizeKey(key);\n\n // Only mutations should be able to set state values.\n if (this.stateManager.readonly) {\n throw new Error(`State locked. Use mutations to change ${key} value in ${this.name}.`);\n }\n\n const previous = super.get(key);\n\n const result = super.delete(key);\n if (!result) {\n return result;\n }\n\n this.stateManager.registerStateAction(this.name, null, 'deleted', previous);\n\n return result;\n }\n\n /**\n * Return a suitable structure for JSON conversion.\n *\n * This function is needed because new values are compared in JSON. StateMap has Private\n * attributes which cannot be stringified (like this.stateManager which will produce an\n * infinite recursivity).\n *\n * @returns {array}\n */\n toJSON() {\n let result = [];\n this.forEach((value) => {\n result.push(value);\n });\n return result;\n }\n\n /**\n * Insert a full list of values using the id attributes as keys.\n *\n * This method is used mainly to initialize the list. Note each element is indexed by its \"id\" attribute.\n * This is a basic restriction of StateMap. All elements need an id attribute, otherwise it won't be saved.\n *\n * @param {iterable} values the values to load\n * @returns {StateMap} return the this value\n */\n loadValues(values) {\n values.forEach((data) => {\n this.checkValue(data);\n let key = data.id;\n let newvalue = new Proxy(data, new Handler(this.name, this.stateManager));\n this.set(key, newvalue);\n });\n return this;\n }\n}\n"],"names":["constructor","dispatchEvent","target","document","readonly","eventsToPublish","updateTypes","this","defaultCreate","bind","defaultUpdate","defaultDelete","defaultPut","defaultOverride","defaultRemove","defaultPrepareFields","initialPromise","Promise","resolve","addEventListener","event","detail","state","setInitialState","initialState","undefined","Error","Proxy","Handler","prop","propValue","Object","entries","action","getInitialPromise","setReadOnly","mode","_publishEvents","element","addUpdateTypes","newFunctions","updateType","updateFunction","processUpdates","updates","Array","isArray","forEach","update","name","processUpdate","fields","updateName","method","prepareFields","stateManager","StateMap","add","get","id","delete","current","fieldName","fieldValue","registerStateAction","field","data","parentAction","push","eventName","eventData","fieldChanges","changes","sort","a","b","weights","created","updated","deleted","aweight","bweight","length","publishedEvents","Set","eventkey","has","proxyValues","set","obj","value","receiver","JSON","stringify","loadValues","deleteProperty","Map","iterable","key","normalizeKey","checkValue","super","result","String","valueOf","previous","toJSON","values","newvalue"],"mappings":";;;;;;;;;;;;;;;;;MAmFIA,YAAYC,cAAeC,aAIlBD,cAAgBA,mBAIhBC,OAASA,MAAAA,OAAAA,OAAUC,cAInBC,UAAW,OAIXC,gBAAkB,QAIlBC,YAAc,QACLC,KAAKC,cAAcC,KAAKF,aACxBA,KAAKG,cAAcD,KAAKF,aACxBA,KAAKI,cAAcF,KAAKF,UAC3BA,KAAKK,WAAWH,KAAKF,eAChBA,KAAKM,gBAAgBJ,KAAKF,aAC5BA,KAAKO,cAAcL,KAAKF,oBACjBA,KAAKQ,qBAAqBN,KAAKF,YAM/CS,eAAiB,IAAIC,SAASC,eAI1BhB,OAAOiB,iBAAiB,gBAHHC,QACtBF,QAAQE,MAAMC,OAAOC,aAejCC,gBAAgBC,sBAEOC,IAAflB,KAAKe,YACCI,MAAM,oDAIVJ,MAAQ,IAAIK,MAAM,GAAI,IAAIC,QAAQ,QAASrB,MAAM,QAClD,MAAOsB,KAAMC,aAAcC,OAAOC,QAAQR,cAC3CF,MAAMO,MAAQC,eAEbR,MAAQA,WAGRlB,UAAW,OAEXH,cAAc,CACfgC,OAAQ,eACRX,MAAOf,KAAKe,OACbf,KAAKL,QAWZgC,2BACW3B,KAAKS,eAehBmB,YAAY/B,eAEHA,SAAWA,aAEZgC,KAAO,MAGP7B,KAAKH,WACLgC,KAAO,UACFC,uBAIJpC,cAAc,CACfgC,0BAAoBG,MACpBd,MAAOf,KAAKe,MACZgB,QAAS,MACV/B,KAAKL,QAYZqC,eAAeC,kBACN,MAAOC,WAAYC,kBAAmBX,OAAOC,QAAQQ,cACxB,mBAAnBE,sBACFpC,YAAYmC,YAAcC,eAAejC,KAAK+B,eAc/DG,eAAeC,QAAStC,iBACfuC,MAAMC,QAAQF,eACTlB,MAAM,uCAEXS,aAAY,GACjBS,QAAQG,SAASC,iBACOvB,IAAhBuB,OAAOC,WACDvB,MAAM,kCAEXwB,cACDF,OAAOC,KACPD,OAAOf,OACPe,OAAOG,OACP7C,qBAGH6B,aAAY,GAarBe,cAAcE,WAAYnB,OAAQkB,OAAQ7C,uEAEjC6C,aACKzB,MAAM,oCAGID,IAAhBnB,cACAA,YAAc,UAKZ+C,mCAAS/C,YAFf2B,uBAASA,kCAAU,6DAEmB1B,KAAKD,YAAY2B,gBAExCR,IAAX4B,aACM3B,qCAA8BO,SAQxCoB,OAAO9C,KAAM6C,0CAFS9C,YAAYgD,qEAAiB/C,KAAKD,YAAYgD,eAE7B/C,KAAM6C,WAAYD,SAa7DpC,qBAAqBwC,aAAcH,WAAYD,eACpCA,OAWX3C,cAAc+C,aAAcH,WAAYD,YAEhC7B,MAAQiC,aAAajC,MAGrBA,MAAM8B,sBAAuBI,SAC7BlC,MAAM8B,YAAYK,IAAIN,QAG1B7B,MAAM8B,YAAcD,OAUxBxC,cAAc4C,aAAcH,WAAYD,YAGtBI,aAAaG,IAAIN,WAAYD,OAAOQ,UAExCjC,2BAAoB0B,uBAAcD,OAAOQ,SAI/CrC,MAAQiC,aAAajC,MAErBA,MAAM8B,sBAAuBI,SAC7BlC,MAAM8B,YAAYQ,OAAOT,OAAOQ,WAG7BrC,MAAM8B,YAUjBtC,cAAcyC,aAAcH,WAAYD,YAGtBI,aAAaG,IAAIN,WAAYD,OAAOQ,eAM9CrC,MAAQiC,aAAajC,MAErBA,MAAM8B,sBAAuBI,SAC7BlC,MAAM8B,YAAYQ,OAAOT,OAAOQ,WAG7BrC,MAAM8B,YAUjB1C,cAAc6C,aAAcH,WAAYD,YAGhCU,QAAUN,aAAaG,IAAIN,WAAYD,OAAOQ,QAC7CE,cACKnC,2BAAoB0B,uBAAcD,OAAOQ,SAI9C,MAAOG,UAAWC,cAAehC,OAAOC,QAAQmB,QACjDU,QAAQC,WAAaC,WAW7BnD,WAAW2C,aAAcH,WAAYD,YAG7BU,QAAUN,aAAaG,IAAIN,WAAYD,OAAOQ,OAC9CE,YAEK,MAAOC,UAAWC,cAAehC,OAAOC,QAAQmB,QACjDU,QAAQC,WAAaC,eAEtB,KAECzC,MAAQiC,aAAajC,SACrBA,MAAM8B,sBAAuBI,qBAC7BlC,MAAM8B,YAAYK,IAAIN,QAG1B7B,MAAM8B,YAAcD,QAW5BtC,gBAAgB0C,aAAcH,WAAYD,YAGlCU,QAAUN,aAAaG,IAAIN,WAAYD,OAAOQ,OAC9CE,QAAS,KAEJ,MAAOC,aAAc/B,OAAOC,QAAQ6B,cACXpC,IAAtB0B,OAAOW,mBACAD,QAAQC,eAIlB,MAAOA,UAAWC,cAAehC,OAAOC,QAAQmB,QACjDU,QAAQC,WAAaC,eAEtB,KAECzC,MAAQiC,aAAajC,SACrBA,MAAM8B,sBAAuBI,qBAC7BlC,MAAM8B,YAAYK,IAAIN,QAG1B7B,MAAM8B,YAAcD,QAc5BO,IAAIT,KAAMU,UACArC,MAAQf,KAAKe,UAEfuC,QAAUvC,MAAM2B,SAChBY,mBAAmBL,SAAU,SAClB/B,IAAPkC,SACMjC,+BAAwBuB,uBAElCY,QAAUvC,MAAM2B,MAAMS,IAAIC,WAGvBE,QAsBXG,oBAAoBC,MAAOpC,KAAMI,OAAQiC,UAEjCC,aAAe,UAEN,OAATtC,UACKxB,gBAAgB+D,KAAK,CACtBC,oBAAcJ,kBAASpC,iBAAQI,QAC/BqC,UAAWJ,KACXjC,OAAAA,SAGJkC,aAAelC,YAIHR,IAAZyC,KAAKP,KACQ,OAAT9B,WACKxB,gBAAgB+D,KAAK,CACtBC,oBAAcJ,kBAASC,KAAKP,gBAAO9B,iBAAQI,QAC3CqC,UAAWJ,KACXjC,OAAAA,cAGH5B,gBAAgB+D,KAAK,CACtBC,oBAAcJ,kBAASC,KAAKP,gBAAOQ,cACnCG,UAAWJ,KACXjC,OAAQkC,qBAKX9D,gBAAgB+D,KAAK,CACtBC,oBAAcJ,kBAASE,cACvBG,UAAWJ,KACXjC,OAAQkC,oBAIP9D,gBAAgB+D,KAAK,CACtBC,0BACAC,UAAWJ,KACXjC,OAAQ,YAShBI,uBACUkC,aAAehE,KAAKF,qBACrBA,gBAAkB,QAGlBJ,cAAc,CACfgC,OAAQ,oBACRX,MAAOf,KAAKe,MACZgB,QAAS,KACTkC,QAASD,cACVhE,KAAKL,QAKRqE,aAAaE,MAAK,CAACC,EAAGC,mDACZC,QAAU,CACZC,QAAS,EACTC,QAAS,EACTC,QAAS,GAEPC,kCAAUJ,QAAQF,EAAEzC,uDAAW,EAC/BgD,kCAAUL,QAAQD,EAAE1C,uDAAW,SAEjC+C,UAAYC,QACLP,EAAEL,UAAUa,OAASP,EAAEN,UAAUa,OAErCF,QAAUC,eAIjBE,gBAAkB,IAAIC,IAE1Bb,aAAaxB,SAAS3B,sCAEZiE,mBAAcjE,MAAMiD,kDAAajD,MAAMkD,UAAUX,sDAAM,GAExDwB,gBAAgBG,IAAID,iBAChBpF,cAAc,CACfgC,OAAQb,MAAMiD,UACd/C,MAAOf,KAAKe,MACZgB,QAASlB,MAAMkD,WAChB/D,KAAKL,QAERiF,gBAAgB1B,IAAI4B,mBAKvBpF,cAAc,CACfgC,OAAQ,kBACRX,MAAOf,KAAKe,MACZgB,QAAS,MACV/B,KAAKL,gBAcV0B,QASF5B,YAAYiD,KAAMM,aAAcgC,kBACvBtC,KAAOA,UACPM,aAAeA,kBACfgC,YAAcA,MAAAA,aAAAA,YAYvBC,IAAIC,IAAK5D,KAAM6D,MAAOC,aAGdpF,KAAKgD,aAAanD,eACZ,IAAIsB,sDAA+CG,0BAAiBtB,KAAK0C,cAI/E2C,KAAKC,UAAUJ,IAAI5D,SAAW+D,KAAKC,UAAUH,cACtC,QAGLzD,YAAwBR,IAAdgE,IAAI5D,MAAuB,UAAY,iBAGnDtB,KAAKgF,YACD1C,MAAMC,QAAQ4C,OACdD,IAAI5D,MAAQ,IAAI2B,SAAS3B,KAAMtB,KAAKgD,cAAcuC,WAAWJ,OAE7DD,IAAI5D,MAAQ,IAAIF,MAAM+D,MAAO,IAAI9D,QAAQC,KAAMtB,KAAKgD,eAGxDkC,IAAI5D,MAAQ6D,WAIgBjE,IAA5BlB,KAAKgD,aAAajC,YAIjBiC,aAAaS,oBAAoBzD,KAAK0C,KAAMpB,KAAMI,OAAQ0D,WAHpD,EAefI,eAAeN,IAAK5D,SAEZtB,KAAKgD,aAAanD,eACZ,IAAIsB,sDAA+CG,oBAAWtB,KAAK0C,kBAEzEpB,QAAQ4D,aAEDA,IAAI5D,WAEN0B,aAAaS,oBAAoBzD,KAAK0C,KAAMpB,KAAM,UAAW4D,OAE/D,SAgBTjC,iBAAiBwC,IASnBhG,YAAYiD,KAAMM,aAAc0C,gBAEtBA,eACDhD,KAAOA,UACPM,aAAeA,aAaxBiC,IAAIU,IAAKR,UAGDnF,KAAKgD,aAAanD,eACZ,IAAIsB,sDAA+CwE,yBAAgB3F,KAAK0C,cAIlFiD,IAAM3F,KAAK4F,aAAaD,UAEnBE,WAAWV,OAEZQ,MAAAA,UACMxE,MAAM,mDAIZnB,KAAK4F,aAAaT,MAAM/B,MAAQuC,UAC1B,IAAIxE,6BAAsBnB,KAAK0C,kCAAyByC,MAAM/B,yBAAgBuC,yBAGlFjE,OAAUoE,MAAMf,IAAIY,KAAQ,UAAY,UAGxCI,OAASD,MAAMb,IAAIU,IAAK,IAAIvE,MAAM+D,MAAO,IAAI9D,QAAQrB,KAAK0C,KAAM1C,KAAKgD,4BAG3C9B,IAA5BlB,KAAKgD,aAAajC,YAIjBiC,aAAaS,oBAAoBzD,KAAK0C,KAAM,KAAMhB,OAAQoE,MAAM3C,IAAIwC,MAH9DI,OAiBfF,WAAWV,eAKUjE,IAAbiE,MAAM/B,SACAjC,MAAM,8DAapByE,aAAaD,YACFK,OAAOL,KAAKM,UAWvB/C,IAAIiC,mBACKU,WAAWV,OACTnF,KAAKiF,IAAIE,MAAM/B,GAAI+B,OAS9BhC,IAAIwC,YACOG,MAAM3C,IAAInD,KAAK4F,aAAaD,MASvCZ,IAAIY,YACOG,MAAMf,IAAI/E,KAAK4F,aAAaD,MASvCtC,OAAOsC,QAEHA,IAAM3F,KAAK4F,aAAaD,KAGpB3F,KAAKgD,aAAanD,eACZ,IAAIsB,sDAA+CwE,yBAAgB3F,KAAK0C,iBAG5EwD,SAAWJ,MAAM3C,IAAIwC,KAErBI,OAASD,MAAMzC,OAAOsC,YACvBI,aAIA/C,aAAaS,oBAAoBzD,KAAK0C,KAAM,KAAM,UAAWwD,UAE3DH,QALIA,OAiBfI,aACQJ,OAAS,eACRvD,SAAS2C,QACVY,OAAOlC,KAAKsB,UAETY,OAYXR,WAAWa,eACPA,OAAO5D,SAASmB,YACPkC,WAAWlC,UACZgC,IAAMhC,KAAKP,GACXiD,SAAW,IAAIjF,MAAMuC,KAAM,IAAItC,QAAQrB,KAAK0C,KAAM1C,KAAKgD,oBACtDiC,IAAIU,IAAKU,aAEXrG"} \ No newline at end of file diff --git a/lib/amd/build/paged_content_paging_bar.min.js b/lib/amd/build/paged_content_paging_bar.min.js index 9a1cbf5a0c7..fb8a59c8cae 100644 --- a/lib/amd/build/paged_content_paging_bar.min.js +++ b/lib/amd/build/paged_content_paging_bar.min.js @@ -1,7 +1,7 @@ /** * Javascript to enhance the paged content paging bar. * - * @module core/paging_bar + * @module core/paged_content_paging_bar * @copyright 2018 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/build/paged_content_paging_bar.min.js.map b/lib/amd/build/paged_content_paging_bar.min.js.map index 89fdb47bb51..3969f19720e 100644 --- a/lib/amd/build/paged_content_paging_bar.min.js.map +++ b/lib/amd/build/paged_content_paging_bar.min.js.map @@ -1 +1 @@ -{"version":3,"file":"paged_content_paging_bar.min.js","sources":["../src/paged_content_paging_bar.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 * Javascript to enhance the paged content paging bar.\n *\n * @module core/paging_bar\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/custom_interaction_events',\n 'core/paged_content_events',\n 'core/str',\n 'core/pubsub',\n 'core/pending',\n],\nfunction(\n $,\n CustomEvents,\n PagedContentEvents,\n Str,\n PubSub,\n Pending\n) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"paging-bar\"]',\n PAGE: '[data-page]',\n PAGE_ITEM: '[data-region=\"page-item\"]',\n PAGE_LINK: '[data-region=\"page-link\"]',\n FIRST_BUTTON: '[data-control=\"first\"]',\n LAST_BUTTON: '[data-control=\"last\"]',\n NEXT_BUTTON: '[data-control=\"next\"]',\n PREVIOUS_BUTTON: '[data-control=\"previous\"]',\n DOTS_BUTTONS: '[data-dots]',\n BEGINNING_DOTS_BUTTON: '[data-dots=\"beginning\"]',\n ENDING_DOTS_BUTTON: '[data-dots=\"ending\"]',\n };\n\n /**\n * Get the page element by number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The page number.\n * @return {jQuery}\n */\n var getPageByNumber = function(root, pageNumber) {\n return root.find(SELECTORS.PAGE_ITEM + '[data-page-number=\"' + pageNumber + '\"]');\n };\n\n /**\n * Get the next button element.\n *\n * @param {object} root The root element.\n * @return {jQuery}\n */\n var getNextButton = function(root) {\n return root.find(SELECTORS.NEXT_BUTTON);\n };\n\n /**\n * Set the last page number after which no more pages\n * should be loaded.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setLastPageNumber = function(root, number) {\n root.attr('data-last-page-number', number);\n };\n\n /**\n * Get the last page number.\n *\n * @param {object} root The root element.\n * @return {Number}\n */\n var getLastPageNumber = function(root) {\n return parseInt(root.attr('data-last-page-number'), 10);\n };\n\n /**\n * Get the active page number.\n *\n * @param {object} root The root element.\n * @returns {Number} The page number\n */\n var getActivePageNumber = function(root) {\n return parseInt(root.attr('data-active-page-number'), 10);\n };\n\n /**\n * Set the active page number.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setActivePageNumber = function(root, number) {\n root.attr('data-active-page-number', number);\n };\n\n /**\n * Check if there is an active page number.\n *\n * @param {object} root The root element.\n * @returns {bool}\n */\n var hasActivePageNumber = function(root) {\n var number = getActivePageNumber(root);\n return !isNaN(number) && number != 0;\n };\n\n /**\n * Get the page number for a given page.\n *\n * @param {object} root The root element.\n * @param {object} page The page element.\n * @returns {Number} The page number\n */\n var getPageNumber = function(root, page) {\n if (page.attr('data-page') != undefined) {\n // If it's an actual page then we can just use the page number\n // attribute.\n return parseInt(page.attr('data-page-number'), 10);\n }\n\n var pageNumber = 1;\n var activePageNumber = null;\n\n switch (page.attr('data-control')) {\n case 'first':\n pageNumber = 1;\n break;\n\n case 'last':\n pageNumber = getLastPageNumber(root);\n break;\n\n case 'next':\n activePageNumber = getActivePageNumber(root);\n var lastPage = getLastPageNumber(root);\n if (!lastPage) {\n pageNumber = activePageNumber + 1;\n } else if (activePageNumber && activePageNumber < lastPage) {\n pageNumber = activePageNumber + 1;\n } else {\n pageNumber = lastPage;\n }\n break;\n\n case 'previous':\n activePageNumber = getActivePageNumber(root);\n if (activePageNumber && activePageNumber > 1) {\n pageNumber = activePageNumber - 1;\n } else {\n pageNumber = 1;\n }\n break;\n\n default:\n pageNumber = 1;\n break;\n }\n\n // Make sure we return an int not a string.\n return parseInt(pageNumber, 10);\n };\n\n /**\n * Get the limit of items for each page.\n *\n * @param {object} root The root element.\n * @returns {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-items-per-page'), 10);\n };\n\n /**\n * Set the limit of items for each page.\n *\n * @param {object} root The root element.\n * @param {Number} limit Items per page limit.\n */\n var setLimit = function(root, limit) {\n root.attr('data-items-per-page', limit);\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element.\n */\n var show = function(root) {\n root.removeClass('hidden');\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element.\n */\n var hide = function(root) {\n root.addClass('hidden');\n };\n\n /**\n * Disable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.addClass('disabled');\n nextButton.attr('aria-disabled', true);\n lastButton.addClass('disabled');\n lastButton.attr('aria-disabled', true);\n };\n\n /**\n * Enable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.removeClass('disabled');\n nextButton.removeAttr('aria-disabled');\n lastButton.removeClass('disabled');\n lastButton.removeAttr('aria-disabled');\n };\n\n /**\n * Disable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.addClass('disabled');\n previousButton.attr('aria-disabled', true);\n firstButton.addClass('disabled');\n firstButton.attr('aria-disabled', true);\n };\n\n /**\n * Adjusts the size of the paging bar and hides unnecessary pages.\n *\n * @param {object} root The root element.\n */\n var adjustPagingBarSize = function(root) {\n var activePageNumber = getActivePageNumber(root);\n var lastPageNumber = getLastPageNumber(root);\n\n var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);\n var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);\n var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);\n\n var pages = root.find(SELECTORS.PAGE);\n var barSize = parseInt(root.attr('data-bar-size'), 10);\n\n if (barSize && lastPageNumber > barSize) {\n\n var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);\n var maxpage = minpage + barSize - 1;\n\n if (maxpage >= lastPageNumber) {\n maxpage = lastPageNumber;\n minpage = maxpage - barSize + 1;\n }\n\n if (minpage > 1) {\n show(beginningDotsButton);\n minpage++;\n } else {\n hide(beginningDotsButton);\n }\n if (maxpage < lastPageNumber) {\n show(endingDotsButton);\n maxpage--;\n } else {\n hide(endingDotsButton);\n }\n dotsButtons.addClass('disabled');\n dotsButtons.attr('aria-disabled', true);\n\n hide(pages);\n\n pages.each(function(index, page) {\n page = $(page);\n if ((index + 1) >= minpage && (index + 1) <= maxpage) {\n show(page);\n }\n });\n\n } else {\n hide(dotsButtons);\n }\n };\n\n /**\n * Enable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.removeClass('disabled');\n previousButton.removeAttr('aria-disabled');\n firstButton.removeClass('disabled');\n firstButton.removeAttr('aria-disabled');\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on a page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getPageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on an active page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getActivePageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-active-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Set page numbers on each of the given items. Page numbers are set\n * from 1..n (where n is the number of items).\n *\n * Sets the active page number to be the last page found with\n * an \"active\" class (if any).\n *\n * Sets the last page number.\n *\n * @param {object} root The root element.\n * @param {jQuery} items A jQuery list of items.\n */\n var generatePageNumbers = function(root, items) {\n var lastPageNumber = 0;\n setActivePageNumber(root, 0);\n\n items.each(function(index, item) {\n var pageNumber = index + 1;\n item = $(item);\n item.attr('data-page-number', pageNumber);\n lastPageNumber++;\n\n if (item.hasClass('active')) {\n setActivePageNumber(root, pageNumber);\n }\n });\n\n setLastPageNumber(root, lastPageNumber);\n };\n\n /**\n * Set the aria-labels on each of the page items in the paging bar.\n * This includes the next, previous, first, and last items.\n *\n * @param {object} root The root element.\n */\n var generateAriaLabels = function(root) {\n var pageAriaLabelComponents = getPageAriaLabelComponents(root);\n var activePageAriaLabelComponents = getActivePageAriaLabelComponents(root);\n var activePageNumber = getActivePageNumber(root);\n var pageItems = root.find(SELECTORS.PAGE_ITEM);\n // We want to request all of the strings at once rather than\n // one at a time.\n var stringRequests = pageItems.toArray().map(function(index, page) {\n page = $(page);\n var pageNumber = getPageNumber(root, page);\n\n if (pageNumber === activePageNumber) {\n return {\n key: activePageAriaLabelComponents[0],\n component: activePageAriaLabelComponents[1],\n param: pageNumber\n };\n } else {\n return {\n key: pageAriaLabelComponents[0],\n component: pageAriaLabelComponents[1],\n param: pageNumber\n };\n }\n });\n\n Str.get_strings(stringRequests).then(function(strings) {\n pageItems.each(function(index, page) {\n page = $(page);\n var string = strings[index];\n page.attr('aria-label', string);\n page.find(SELECTORS.PAGE_LINK).attr('aria-label', string);\n });\n\n return strings;\n })\n .catch(function() {\n // No need to interrupt the page if we can't load the aria lang strings.\n return;\n });\n };\n\n /**\n * Make the paging bar item for the given page number visible and fire\n * the SHOW_PAGES paged content event to tell any listening content to\n * update.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number for the page to show.\n * @param {string} id A uniqie id for this instance.\n */\n var showPage = function(root, pageNumber, id) {\n var pendingPromise = new Pending('core/paged_content_paging_bar:showPage');\n var lastPageNumber = getLastPageNumber(root);\n var isSamePage = pageNumber == getActivePageNumber(root);\n var limit = getLimit(root);\n var offset = (pageNumber - 1) * limit;\n\n if (!isSamePage) {\n // We only need to toggle the active class if the user didn't click\n // on the already active page.\n root.find(SELECTORS.PAGE_ITEM).removeClass('active').removeAttr('aria-current');\n var page = getPageByNumber(root, pageNumber);\n page.addClass('active');\n page.attr('aria-current', true);\n setActivePageNumber(root, pageNumber);\n\n adjustPagingBarSize(root);\n }\n\n // Make sure the control buttons are disabled as the user navigates\n // to either end of the limits.\n if (lastPageNumber && pageNumber >= lastPageNumber) {\n disableNextControlButtons(root);\n } else {\n enableNextControlButtons(root);\n }\n\n if (pageNumber > 1) {\n enablePreviousControlButtons(root);\n } else {\n disablePreviousControlButtons(root);\n }\n\n generateAriaLabels(root);\n\n // This event requires a payload that contains a list of all pages that\n // were activated. In the case of the paging bar we only show one page at\n // a time.\n PubSub.publish(id + PagedContentEvents.SHOW_PAGES, [{\n pageNumber: pageNumber,\n limit: limit,\n offset: offset\n }]);\n\n pendingPromise.resolve();\n };\n\n /**\n * Add event listeners for interactions with the paging bar as well as listening\n * for custom paged content events.\n *\n * Each event will trigger different logic to update parts of the paging bar's\n * display.\n *\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var registerEventListeners = function(root, id) {\n var ignoreControlWhileLoading = root.attr('data-ignore-control-while-loading');\n var loading = false;\n\n if (ignoreControlWhileLoading == \"\") {\n // Default to ignoring control while loading if not specified.\n ignoreControlWhileLoading = true;\n }\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n\n if (ignoreControlWhileLoading && loading) {\n // Do nothing if configured to ignore control while loading.\n return;\n }\n\n var page = $(e.target).closest(SELECTORS.PAGE_ITEM);\n\n if (!page.hasClass('disabled')) {\n var pageNumber = getPageNumber(root, page);\n showPage(root, pageNumber, id);\n loading = true;\n }\n });\n\n // This event is fired when all of the items have been loaded. Typically used\n // in an \"infinite\" pages context when we don't know the exact number of pages\n // ahead of time.\n PubSub.subscribe(id + PagedContentEvents.ALL_ITEMS_LOADED, function(pageNumber) {\n loading = false;\n var currentLastPage = getLastPageNumber(root);\n\n if (!currentLastPage || pageNumber < currentLastPage) {\n // Somehow the value we've got saved is higher than the new\n // value we just received. Perhaps events came out of order.\n // In any case, save the lowest value.\n setLastPageNumber(root, pageNumber);\n }\n\n if (pageNumber === 1 && root.attr('data-hide-control-on-single-page')) {\n // If all items were loaded on the first page then we can hide\n // the paging bar because there are no other pages to load.\n hide(root);\n disableNextControlButtons(root);\n disablePreviousControlButtons(root);\n } else {\n show(root);\n disableNextControlButtons(root);\n }\n });\n\n // This event is fired after all of the requested pages have been rendered.\n PubSub.subscribe(id + PagedContentEvents.PAGES_SHOWN, function() {\n // All pages have been shown so turn off the loading flag.\n loading = false;\n });\n\n // This is triggered when the paging limit is modified.\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function(limit) {\n // Update the limit.\n setLimit(root, limit);\n setLastPageNumber(root, 0);\n setActivePageNumber(root, 0);\n show(root);\n // Reload the data from page 1 again.\n showPage(root, 1, id);\n });\n };\n\n /**\n * Initialise the paging bar.\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var init = function(root, id) {\n root = $(root);\n var pages = root.find(SELECTORS.PAGE);\n generatePageNumbers(root, pages);\n registerEventListeners(root, id);\n\n if (hasActivePageNumber(root)) {\n var activePageNumber = getActivePageNumber(root);\n // If the the paging bar was rendered with an active page selected\n // then make sure we fired off the event to tell the content page to\n // show.\n getPageByNumber(root, activePageNumber).click();\n if (activePageNumber == 1) {\n // If the first page is active then disable the previous buttons.\n disablePreviousControlButtons(root);\n }\n } else {\n // There was no active page number so load the first page using\n // the next button. This allows the infinite pagination to work.\n getNextButton(root).click();\n }\n\n adjustPagingBarSize(root);\n };\n\n return {\n init: init,\n disableNextControlButtons: disableNextControlButtons,\n enableNextControlButtons: enableNextControlButtons,\n disablePreviousControlButtons: disablePreviousControlButtons,\n enablePreviousControlButtons: enablePreviousControlButtons,\n showPage: showPage,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"names":["define","$","CustomEvents","PagedContentEvents","Str","PubSub","Pending","SELECTORS","getPageByNumber","root","pageNumber","find","setLastPageNumber","number","attr","getLastPageNumber","parseInt","getActivePageNumber","setActivePageNumber","getPageNumber","page","undefined","activePageNumber","lastPage","show","removeClass","hide","addClass","disableNextControlButtons","nextButton","lastButton","enableNextControlButtons","removeAttr","disablePreviousControlButtons","previousButton","firstButton","adjustPagingBarSize","lastPageNumber","dotsButtons","beginningDotsButton","endingDotsButton","pages","barSize","minpage","Math","max","round","maxpage","each","index","enablePreviousControlButtons","showPage","id","pendingPromise","isSamePage","limit","getLimit","offset","pageAriaLabelComponents","split","map","component","trim","getPageAriaLabelComponents","activePageAriaLabelComponents","getActivePageAriaLabelComponents","pageItems","stringRequests","toArray","key","param","get_strings","then","strings","string","catch","generateAriaLabels","publish","SHOW_PAGES","resolve","init","items","item","hasClass","generatePageNumbers","ignoreControlWhileLoading","loading","events","activate","on","e","data","originalEvent","preventDefault","stopPropagation","target","closest","subscribe","ALL_ITEMS_LOADED","currentLastPage","PAGES_SHOWN","SET_ITEMS_PER_PAGE_LIMIT","setLimit","registerEventListeners","isNaN","hasActivePageNumber","click","getNextButton","rootSelector"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"paged_content_paging_bar.min.js","sources":["../src/paged_content_paging_bar.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 * Javascript to enhance the paged content paging bar.\n *\n * @module core/paged_content_paging_bar\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/custom_interaction_events',\n 'core/paged_content_events',\n 'core/str',\n 'core/pubsub',\n 'core/pending',\n],\nfunction(\n $,\n CustomEvents,\n PagedContentEvents,\n Str,\n PubSub,\n Pending\n) {\n\n var SELECTORS = {\n ROOT: '[data-region=\"paging-bar\"]',\n PAGE: '[data-page]',\n PAGE_ITEM: '[data-region=\"page-item\"]',\n PAGE_LINK: '[data-region=\"page-link\"]',\n FIRST_BUTTON: '[data-control=\"first\"]',\n LAST_BUTTON: '[data-control=\"last\"]',\n NEXT_BUTTON: '[data-control=\"next\"]',\n PREVIOUS_BUTTON: '[data-control=\"previous\"]',\n DOTS_BUTTONS: '[data-dots]',\n BEGINNING_DOTS_BUTTON: '[data-dots=\"beginning\"]',\n ENDING_DOTS_BUTTON: '[data-dots=\"ending\"]',\n };\n\n /**\n * Get the page element by number.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The page number.\n * @return {jQuery}\n */\n var getPageByNumber = function(root, pageNumber) {\n return root.find(SELECTORS.PAGE_ITEM + '[data-page-number=\"' + pageNumber + '\"]');\n };\n\n /**\n * Get the next button element.\n *\n * @param {object} root The root element.\n * @return {jQuery}\n */\n var getNextButton = function(root) {\n return root.find(SELECTORS.NEXT_BUTTON);\n };\n\n /**\n * Set the last page number after which no more pages\n * should be loaded.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setLastPageNumber = function(root, number) {\n root.attr('data-last-page-number', number);\n };\n\n /**\n * Get the last page number.\n *\n * @param {object} root The root element.\n * @return {Number}\n */\n var getLastPageNumber = function(root) {\n return parseInt(root.attr('data-last-page-number'), 10);\n };\n\n /**\n * Get the active page number.\n *\n * @param {object} root The root element.\n * @returns {Number} The page number\n */\n var getActivePageNumber = function(root) {\n return parseInt(root.attr('data-active-page-number'), 10);\n };\n\n /**\n * Set the active page number.\n *\n * @param {object} root The root element.\n * @param {Number} number Page number.\n */\n var setActivePageNumber = function(root, number) {\n root.attr('data-active-page-number', number);\n };\n\n /**\n * Check if there is an active page number.\n *\n * @param {object} root The root element.\n * @returns {bool}\n */\n var hasActivePageNumber = function(root) {\n var number = getActivePageNumber(root);\n return !isNaN(number) && number != 0;\n };\n\n /**\n * Get the page number for a given page.\n *\n * @param {object} root The root element.\n * @param {object} page The page element.\n * @returns {Number} The page number\n */\n var getPageNumber = function(root, page) {\n if (page.attr('data-page') != undefined) {\n // If it's an actual page then we can just use the page number\n // attribute.\n return parseInt(page.attr('data-page-number'), 10);\n }\n\n var pageNumber = 1;\n var activePageNumber = null;\n\n switch (page.attr('data-control')) {\n case 'first':\n pageNumber = 1;\n break;\n\n case 'last':\n pageNumber = getLastPageNumber(root);\n break;\n\n case 'next':\n activePageNumber = getActivePageNumber(root);\n var lastPage = getLastPageNumber(root);\n if (!lastPage) {\n pageNumber = activePageNumber + 1;\n } else if (activePageNumber && activePageNumber < lastPage) {\n pageNumber = activePageNumber + 1;\n } else {\n pageNumber = lastPage;\n }\n break;\n\n case 'previous':\n activePageNumber = getActivePageNumber(root);\n if (activePageNumber && activePageNumber > 1) {\n pageNumber = activePageNumber - 1;\n } else {\n pageNumber = 1;\n }\n break;\n\n default:\n pageNumber = 1;\n break;\n }\n\n // Make sure we return an int not a string.\n return parseInt(pageNumber, 10);\n };\n\n /**\n * Get the limit of items for each page.\n *\n * @param {object} root The root element.\n * @returns {Number}\n */\n var getLimit = function(root) {\n return parseInt(root.attr('data-items-per-page'), 10);\n };\n\n /**\n * Set the limit of items for each page.\n *\n * @param {object} root The root element.\n * @param {Number} limit Items per page limit.\n */\n var setLimit = function(root, limit) {\n root.attr('data-items-per-page', limit);\n };\n\n /**\n * Show the paging bar.\n *\n * @param {object} root The root element.\n */\n var show = function(root) {\n root.removeClass('hidden');\n };\n\n /**\n * Hide the paging bar.\n *\n * @param {object} root The root element.\n */\n var hide = function(root) {\n root.addClass('hidden');\n };\n\n /**\n * Disable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.addClass('disabled');\n nextButton.attr('aria-disabled', true);\n lastButton.addClass('disabled');\n lastButton.attr('aria-disabled', true);\n };\n\n /**\n * Enable the next and last buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enableNextControlButtons = function(root) {\n var nextButton = root.find(SELECTORS.NEXT_BUTTON);\n var lastButton = root.find(SELECTORS.LAST_BUTTON);\n\n nextButton.removeClass('disabled');\n nextButton.removeAttr('aria-disabled');\n lastButton.removeClass('disabled');\n lastButton.removeAttr('aria-disabled');\n };\n\n /**\n * Disable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var disablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.addClass('disabled');\n previousButton.attr('aria-disabled', true);\n firstButton.addClass('disabled');\n firstButton.attr('aria-disabled', true);\n };\n\n /**\n * Adjusts the size of the paging bar and hides unnecessary pages.\n *\n * @param {object} root The root element.\n */\n var adjustPagingBarSize = function(root) {\n var activePageNumber = getActivePageNumber(root);\n var lastPageNumber = getLastPageNumber(root);\n\n var dotsButtons = root.find(SELECTORS.DOTS_BUTTONS);\n var beginningDotsButton = root.find(SELECTORS.BEGINNING_DOTS_BUTTON);\n var endingDotsButton = root.find(SELECTORS.ENDING_DOTS_BUTTON);\n\n var pages = root.find(SELECTORS.PAGE);\n var barSize = parseInt(root.attr('data-bar-size'), 10);\n\n if (barSize && lastPageNumber > barSize) {\n\n var minpage = Math.max(activePageNumber - Math.round(barSize / 2), 1);\n var maxpage = minpage + barSize - 1;\n\n if (maxpage >= lastPageNumber) {\n maxpage = lastPageNumber;\n minpage = maxpage - barSize + 1;\n }\n\n if (minpage > 1) {\n show(beginningDotsButton);\n minpage++;\n } else {\n hide(beginningDotsButton);\n }\n if (maxpage < lastPageNumber) {\n show(endingDotsButton);\n maxpage--;\n } else {\n hide(endingDotsButton);\n }\n dotsButtons.addClass('disabled');\n dotsButtons.attr('aria-disabled', true);\n\n hide(pages);\n\n pages.each(function(index, page) {\n page = $(page);\n if ((index + 1) >= minpage && (index + 1) <= maxpage) {\n show(page);\n }\n });\n\n } else {\n hide(dotsButtons);\n }\n };\n\n /**\n * Enable the previous and first buttons in the paging bar.\n *\n * @param {object} root The root element.\n */\n var enablePreviousControlButtons = function(root) {\n var previousButton = root.find(SELECTORS.PREVIOUS_BUTTON);\n var firstButton = root.find(SELECTORS.FIRST_BUTTON);\n\n previousButton.removeClass('disabled');\n previousButton.removeAttr('aria-disabled');\n firstButton.removeClass('disabled');\n firstButton.removeAttr('aria-disabled');\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on a page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getPageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Get the components for a get_string request for the aria-label\n * on an active page. The value is a comma separated string of key and\n * component.\n *\n * @param {object} root The root element.\n * @return {array} First element is the key, second is the component.\n */\n var getActivePageAriaLabelComponents = function(root) {\n var componentString = root.attr('data-aria-label-components-pagination-active-item');\n var components = componentString.split(',').map(function(component) {\n return component.trim();\n });\n return components;\n };\n\n /**\n * Set page numbers on each of the given items. Page numbers are set\n * from 1..n (where n is the number of items).\n *\n * Sets the active page number to be the last page found with\n * an \"active\" class (if any).\n *\n * Sets the last page number.\n *\n * @param {object} root The root element.\n * @param {jQuery} items A jQuery list of items.\n */\n var generatePageNumbers = function(root, items) {\n var lastPageNumber = 0;\n setActivePageNumber(root, 0);\n\n items.each(function(index, item) {\n var pageNumber = index + 1;\n item = $(item);\n item.attr('data-page-number', pageNumber);\n lastPageNumber++;\n\n if (item.hasClass('active')) {\n setActivePageNumber(root, pageNumber);\n }\n });\n\n setLastPageNumber(root, lastPageNumber);\n };\n\n /**\n * Set the aria-labels on each of the page items in the paging bar.\n * This includes the next, previous, first, and last items.\n *\n * @param {object} root The root element.\n */\n var generateAriaLabels = function(root) {\n var pageAriaLabelComponents = getPageAriaLabelComponents(root);\n var activePageAriaLabelComponents = getActivePageAriaLabelComponents(root);\n var activePageNumber = getActivePageNumber(root);\n var pageItems = root.find(SELECTORS.PAGE_ITEM);\n // We want to request all of the strings at once rather than\n // one at a time.\n var stringRequests = pageItems.toArray().map(function(index, page) {\n page = $(page);\n var pageNumber = getPageNumber(root, page);\n\n if (pageNumber === activePageNumber) {\n return {\n key: activePageAriaLabelComponents[0],\n component: activePageAriaLabelComponents[1],\n param: pageNumber\n };\n } else {\n return {\n key: pageAriaLabelComponents[0],\n component: pageAriaLabelComponents[1],\n param: pageNumber\n };\n }\n });\n\n Str.get_strings(stringRequests).then(function(strings) {\n pageItems.each(function(index, page) {\n page = $(page);\n var string = strings[index];\n page.attr('aria-label', string);\n page.find(SELECTORS.PAGE_LINK).attr('aria-label', string);\n });\n\n return strings;\n })\n .catch(function() {\n // No need to interrupt the page if we can't load the aria lang strings.\n return;\n });\n };\n\n /**\n * Make the paging bar item for the given page number visible and fire\n * the SHOW_PAGES paged content event to tell any listening content to\n * update.\n *\n * @param {object} root The root element.\n * @param {Number} pageNumber The number for the page to show.\n * @param {string} id A uniqie id for this instance.\n */\n var showPage = function(root, pageNumber, id) {\n var pendingPromise = new Pending('core/paged_content_paging_bar:showPage');\n var lastPageNumber = getLastPageNumber(root);\n var isSamePage = pageNumber == getActivePageNumber(root);\n var limit = getLimit(root);\n var offset = (pageNumber - 1) * limit;\n\n if (!isSamePage) {\n // We only need to toggle the active class if the user didn't click\n // on the already active page.\n root.find(SELECTORS.PAGE_ITEM).removeClass('active').removeAttr('aria-current');\n var page = getPageByNumber(root, pageNumber);\n page.addClass('active');\n page.attr('aria-current', true);\n setActivePageNumber(root, pageNumber);\n\n adjustPagingBarSize(root);\n }\n\n // Make sure the control buttons are disabled as the user navigates\n // to either end of the limits.\n if (lastPageNumber && pageNumber >= lastPageNumber) {\n disableNextControlButtons(root);\n } else {\n enableNextControlButtons(root);\n }\n\n if (pageNumber > 1) {\n enablePreviousControlButtons(root);\n } else {\n disablePreviousControlButtons(root);\n }\n\n generateAriaLabels(root);\n\n // This event requires a payload that contains a list of all pages that\n // were activated. In the case of the paging bar we only show one page at\n // a time.\n PubSub.publish(id + PagedContentEvents.SHOW_PAGES, [{\n pageNumber: pageNumber,\n limit: limit,\n offset: offset\n }]);\n\n pendingPromise.resolve();\n };\n\n /**\n * Add event listeners for interactions with the paging bar as well as listening\n * for custom paged content events.\n *\n * Each event will trigger different logic to update parts of the paging bar's\n * display.\n *\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var registerEventListeners = function(root, id) {\n var ignoreControlWhileLoading = root.attr('data-ignore-control-while-loading');\n var loading = false;\n\n if (ignoreControlWhileLoading == \"\") {\n // Default to ignoring control while loading if not specified.\n ignoreControlWhileLoading = true;\n }\n\n CustomEvents.define(root, [\n CustomEvents.events.activate\n ]);\n\n root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) {\n data.originalEvent.preventDefault();\n data.originalEvent.stopPropagation();\n\n if (ignoreControlWhileLoading && loading) {\n // Do nothing if configured to ignore control while loading.\n return;\n }\n\n var page = $(e.target).closest(SELECTORS.PAGE_ITEM);\n\n if (!page.hasClass('disabled')) {\n var pageNumber = getPageNumber(root, page);\n showPage(root, pageNumber, id);\n loading = true;\n }\n });\n\n // This event is fired when all of the items have been loaded. Typically used\n // in an \"infinite\" pages context when we don't know the exact number of pages\n // ahead of time.\n PubSub.subscribe(id + PagedContentEvents.ALL_ITEMS_LOADED, function(pageNumber) {\n loading = false;\n var currentLastPage = getLastPageNumber(root);\n\n if (!currentLastPage || pageNumber < currentLastPage) {\n // Somehow the value we've got saved is higher than the new\n // value we just received. Perhaps events came out of order.\n // In any case, save the lowest value.\n setLastPageNumber(root, pageNumber);\n }\n\n if (pageNumber === 1 && root.attr('data-hide-control-on-single-page')) {\n // If all items were loaded on the first page then we can hide\n // the paging bar because there are no other pages to load.\n hide(root);\n disableNextControlButtons(root);\n disablePreviousControlButtons(root);\n } else {\n show(root);\n disableNextControlButtons(root);\n }\n });\n\n // This event is fired after all of the requested pages have been rendered.\n PubSub.subscribe(id + PagedContentEvents.PAGES_SHOWN, function() {\n // All pages have been shown so turn off the loading flag.\n loading = false;\n });\n\n // This is triggered when the paging limit is modified.\n PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function(limit) {\n // Update the limit.\n setLimit(root, limit);\n setLastPageNumber(root, 0);\n setActivePageNumber(root, 0);\n show(root);\n // Reload the data from page 1 again.\n showPage(root, 1, id);\n });\n };\n\n /**\n * Initialise the paging bar.\n * @param {object} root The root element.\n * @param {string} id A uniqie id for this instance.\n */\n var init = function(root, id) {\n root = $(root);\n var pages = root.find(SELECTORS.PAGE);\n generatePageNumbers(root, pages);\n registerEventListeners(root, id);\n\n if (hasActivePageNumber(root)) {\n var activePageNumber = getActivePageNumber(root);\n // If the the paging bar was rendered with an active page selected\n // then make sure we fired off the event to tell the content page to\n // show.\n getPageByNumber(root, activePageNumber).click();\n if (activePageNumber == 1) {\n // If the first page is active then disable the previous buttons.\n disablePreviousControlButtons(root);\n }\n } else {\n // There was no active page number so load the first page using\n // the next button. This allows the infinite pagination to work.\n getNextButton(root).click();\n }\n\n adjustPagingBarSize(root);\n };\n\n return {\n init: init,\n disableNextControlButtons: disableNextControlButtons,\n enableNextControlButtons: enableNextControlButtons,\n disablePreviousControlButtons: disablePreviousControlButtons,\n enablePreviousControlButtons: enablePreviousControlButtons,\n showPage: showPage,\n rootSelector: SELECTORS.ROOT,\n };\n});\n"],"names":["define","$","CustomEvents","PagedContentEvents","Str","PubSub","Pending","SELECTORS","getPageByNumber","root","pageNumber","find","setLastPageNumber","number","attr","getLastPageNumber","parseInt","getActivePageNumber","setActivePageNumber","getPageNumber","page","undefined","activePageNumber","lastPage","show","removeClass","hide","addClass","disableNextControlButtons","nextButton","lastButton","enableNextControlButtons","removeAttr","disablePreviousControlButtons","previousButton","firstButton","adjustPagingBarSize","lastPageNumber","dotsButtons","beginningDotsButton","endingDotsButton","pages","barSize","minpage","Math","max","round","maxpage","each","index","enablePreviousControlButtons","showPage","id","pendingPromise","isSamePage","limit","getLimit","offset","pageAriaLabelComponents","split","map","component","trim","getPageAriaLabelComponents","activePageAriaLabelComponents","getActivePageAriaLabelComponents","pageItems","stringRequests","toArray","key","param","get_strings","then","strings","string","catch","generateAriaLabels","publish","SHOW_PAGES","resolve","init","items","item","hasClass","generatePageNumbers","ignoreControlWhileLoading","loading","events","activate","on","e","data","originalEvent","preventDefault","stopPropagation","target","closest","subscribe","ALL_ITEMS_LOADED","currentLastPage","PAGES_SHOWN","SET_ITEMS_PER_PAGE_LIMIT","setLimit","registerEventListeners","isNaN","hasActivePageNumber","click","getNextButton","rootSelector"],"mappings":"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"} \ No newline at end of file diff --git a/lib/amd/build/userfeedback.min.js b/lib/amd/build/userfeedback.min.js index 28eabb10954..8c45bf10739 100644 --- a/lib/amd/build/userfeedback.min.js +++ b/lib/amd/build/userfeedback.min.js @@ -2,7 +2,7 @@ define("core/userfeedback",["exports","core/ajax","core/notification"],(function /** * Handle clicking on action links of the feedback alert. * - * @module core/cta_feedback + * @module core/userfeedback * @copyright 2020 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.registerEventListeners=void 0,_ajax=_interopRequireDefault(_ajax),_notification=_interopRequireDefault(_notification);const Selectors={regions:{root:'[data-region="core/userfeedback"]'},actions:{}};Selectors.actions.give="".concat(Selectors.regions.root,' [data-action="give"]'),Selectors.actions.remind="".concat(Selectors.regions.root,' [data-action="remind"]');_exports.registerEventListeners=()=>{document.addEventListener("click",(e=>{const giveAction=e.target.closest(Selectors.actions.give);if(giveAction){if(e.preventDefault(),!window.open(giveAction.href))throw new Error("Unable to open popup");Promise.resolve(giveAction).then(hideRoot).then(recordAction).catch(_notification.default.exception)}const remindAction=e.target.closest(Selectors.actions.remind);remindAction&&(e.preventDefault(),Promise.resolve(remindAction).then(hideRoot).then(recordAction).catch(_notification.default.exception))}))};const recordAction=clickedItem=>clickedItem.dataset.record?_ajax.default.call([{methodname:"core_create_userfeedback_action_record",args:{action:clickedItem.dataset.action,contextid:M.cfg.contextid}}])[0]:Promise.resolve(),hideRoot=clickedItem=>(clickedItem.dataset.hide&&clickedItem.closest(Selectors.regions.root).remove(),clickedItem)})); diff --git a/lib/amd/build/userfeedback.min.js.map b/lib/amd/build/userfeedback.min.js.map index 0021e5260f4..ad4651842c8 100644 --- a/lib/amd/build/userfeedback.min.js.map +++ b/lib/amd/build/userfeedback.min.js.map @@ -1 +1 @@ -{"version":3,"file":"userfeedback.min.js","sources":["../src/userfeedback.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 * Handle clicking on action links of the feedback alert.\n *\n * @module core/cta_feedback\n * @copyright 2020 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\n\nconst Selectors = {\n regions: {\n root: '[data-region=\"core/userfeedback\"]',\n },\n actions: {},\n};\nSelectors.actions.give = `${Selectors.regions.root} [data-action=\"give\"]`;\nSelectors.actions.remind = `${Selectors.regions.root} [data-action=\"remind\"]`;\n\n/**\n * Attach the necessary event handlers to the action links\n */\nexport const registerEventListeners = () => {\n document.addEventListener('click', e => {\n const giveAction = e.target.closest(Selectors.actions.give);\n if (giveAction) {\n e.preventDefault();\n\n if (!window.open(giveAction.href)) {\n throw new Error('Unable to open popup');\n }\n\n Promise.resolve(giveAction)\n .then(hideRoot)\n .then(recordAction)\n .catch(Notification.exception);\n }\n\n const remindAction = e.target.closest(Selectors.actions.remind);\n if (remindAction) {\n e.preventDefault();\n\n Promise.resolve(remindAction)\n .then(hideRoot)\n .then(recordAction)\n .catch(Notification.exception);\n }\n });\n};\n\n/**\n * Record the action that the user took.\n *\n * @param {HTMLElement} clickedItem The action element that the user chose.\n * @returns {Promise}\n */\nconst recordAction = clickedItem => {\n if (clickedItem.dataset.record) {\n return Ajax.call([{\n methodname: 'core_create_userfeedback_action_record',\n args: {\n action: clickedItem.dataset.action,\n contextid: M.cfg.contextid,\n }\n }])[0];\n }\n\n return Promise.resolve();\n};\n\n/**\n * Hide the root node of the CTA notification.\n *\n * @param {HTMLElement} clickedItem The action element that the user chose.\n * @returns {HTMLElement}\n */\nconst hideRoot = clickedItem => {\n if (clickedItem.dataset.hide) {\n clickedItem.closest(Selectors.regions.root).remove();\n }\n\n return clickedItem;\n};\n"],"names":["Selectors","regions","root","actions","give","remind","document","addEventListener","e","giveAction","target","closest","preventDefault","window","open","href","Error","Promise","resolve","then","hideRoot","recordAction","catch","Notification","exception","remindAction","clickedItem","dataset","record","Ajax","call","methodname","args","action","contextid","M","cfg","hide","remove"],"mappings":";;;;;;;kMA0BMA,UAAY,CACdC,QAAS,CACLC,KAAM,qCAEVC,QAAS,IAEbH,UAAUG,QAAQC,eAAUJ,UAAUC,QAAQC,8BAC9CF,UAAUG,QAAQE,iBAAYL,UAAUC,QAAQC,gEAKV,KAClCI,SAASC,iBAAiB,SAASC,UACzBC,WAAaD,EAAEE,OAAOC,QAAQX,UAAUG,QAAQC,SAClDK,WAAY,IACZD,EAAEI,kBAEGC,OAAOC,KAAKL,WAAWM,YAClB,IAAIC,MAAM,wBAGpBC,QAAQC,QAAQT,YACXU,KAAKC,UACLD,KAAKE,cACLC,MAAMC,sBAAaC,iBAGtBC,aAAejB,EAAEE,OAAOC,QAAQX,UAAUG,QAAQE,QACpDoB,eACAjB,EAAEI,iBAEFK,QAAQC,QAAQO,cACXN,KAAKC,UACLD,KAAKE,cACLC,MAAMC,sBAAaC,sBAW9BH,aAAeK,aACbA,YAAYC,QAAQC,OACbC,cAAKC,KAAK,CAAC,CACdC,WAAY,yCACZC,KAAM,CACFC,OAAQP,YAAYC,QAAQM,OAC5BC,UAAWC,EAAEC,IAAIF,cAErB,GAGDjB,QAAQC,UASbE,SAAWM,cACTA,YAAYC,QAAQU,MACpBX,YAAYf,QAAQX,UAAUC,QAAQC,MAAMoC,SAGzCZ"} \ No newline at end of file +{"version":3,"file":"userfeedback.min.js","sources":["../src/userfeedback.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 * Handle clicking on action links of the feedback alert.\n *\n * @module core/userfeedback\n * @copyright 2020 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\nimport Notification from 'core/notification';\n\nconst Selectors = {\n regions: {\n root: '[data-region=\"core/userfeedback\"]',\n },\n actions: {},\n};\nSelectors.actions.give = `${Selectors.regions.root} [data-action=\"give\"]`;\nSelectors.actions.remind = `${Selectors.regions.root} [data-action=\"remind\"]`;\n\n/**\n * Attach the necessary event handlers to the action links\n */\nexport const registerEventListeners = () => {\n document.addEventListener('click', e => {\n const giveAction = e.target.closest(Selectors.actions.give);\n if (giveAction) {\n e.preventDefault();\n\n if (!window.open(giveAction.href)) {\n throw new Error('Unable to open popup');\n }\n\n Promise.resolve(giveAction)\n .then(hideRoot)\n .then(recordAction)\n .catch(Notification.exception);\n }\n\n const remindAction = e.target.closest(Selectors.actions.remind);\n if (remindAction) {\n e.preventDefault();\n\n Promise.resolve(remindAction)\n .then(hideRoot)\n .then(recordAction)\n .catch(Notification.exception);\n }\n });\n};\n\n/**\n * Record the action that the user took.\n *\n * @param {HTMLElement} clickedItem The action element that the user chose.\n * @returns {Promise}\n */\nconst recordAction = clickedItem => {\n if (clickedItem.dataset.record) {\n return Ajax.call([{\n methodname: 'core_create_userfeedback_action_record',\n args: {\n action: clickedItem.dataset.action,\n contextid: M.cfg.contextid,\n }\n }])[0];\n }\n\n return Promise.resolve();\n};\n\n/**\n * Hide the root node of the CTA notification.\n *\n * @param {HTMLElement} clickedItem The action element that the user chose.\n * @returns {HTMLElement}\n */\nconst hideRoot = clickedItem => {\n if (clickedItem.dataset.hide) {\n clickedItem.closest(Selectors.regions.root).remove();\n }\n\n return clickedItem;\n};\n"],"names":["Selectors","regions","root","actions","give","remind","document","addEventListener","e","giveAction","target","closest","preventDefault","window","open","href","Error","Promise","resolve","then","hideRoot","recordAction","catch","Notification","exception","remindAction","clickedItem","dataset","record","Ajax","call","methodname","args","action","contextid","M","cfg","hide","remove"],"mappings":";;;;;;;kMA0BMA,UAAY,CACdC,QAAS,CACLC,KAAM,qCAEVC,QAAS,IAEbH,UAAUG,QAAQC,eAAUJ,UAAUC,QAAQC,8BAC9CF,UAAUG,QAAQE,iBAAYL,UAAUC,QAAQC,gEAKV,KAClCI,SAASC,iBAAiB,SAASC,UACzBC,WAAaD,EAAEE,OAAOC,QAAQX,UAAUG,QAAQC,SAClDK,WAAY,IACZD,EAAEI,kBAEGC,OAAOC,KAAKL,WAAWM,YAClB,IAAIC,MAAM,wBAGpBC,QAAQC,QAAQT,YACXU,KAAKC,UACLD,KAAKE,cACLC,MAAMC,sBAAaC,iBAGtBC,aAAejB,EAAEE,OAAOC,QAAQX,UAAUG,QAAQE,QACpDoB,eACAjB,EAAEI,iBAEFK,QAAQC,QAAQO,cACXN,KAAKC,UACLD,KAAKE,cACLC,MAAMC,sBAAaC,sBAW9BH,aAAeK,aACbA,YAAYC,QAAQC,OACbC,cAAKC,KAAK,CAAC,CACdC,WAAY,yCACZC,KAAM,CACFC,OAAQP,YAAYC,QAAQM,OAC5BC,UAAWC,EAAEC,IAAIF,cAErB,GAGDjB,QAAQC,UASbE,SAAWM,cACTA,YAAYC,QAAQU,MACpBX,YAAYf,QAAQX,UAAUC,QAAQC,MAAMoC,SAGzCZ"} \ No newline at end of file diff --git a/lib/amd/src/loadingicon.js b/lib/amd/src/loadingicon.js index de24f96b0ea..3eaaa5ae733 100644 --- a/lib/amd/src/loadingicon.js +++ b/lib/amd/src/loadingicon.js @@ -16,8 +16,7 @@ /** * Contain the logic for the loading icon. * - * @module core/loading_icon - * @class loading_icon + * @module core/loadingicon * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/local/aria/focuslock.js b/lib/amd/src/local/aria/focuslock.js index eebcf303514..2e628c8e7c0 100644 --- a/lib/amd/src/local/aria/focuslock.js +++ b/lib/amd/src/local/aria/focuslock.js @@ -19,7 +19,7 @@ * This is based on code and examples provided in the ARIA specification. * https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html * - * @module core/tablock + * @module core/local/aria/focuslock * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/local/modal/alert.js b/lib/amd/src/local/modal/alert.js index 22d73fca051..6cf62f100f6 100644 --- a/lib/amd/src/local/modal/alert.js +++ b/lib/amd/src/local/modal/alert.js @@ -16,7 +16,7 @@ /** * Alert modal. * - * @module core/modal_alert + * @module core/local/modal/alert * @copyright 2020 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/local/reactive/debug.js b/lib/amd/src/local/reactive/debug.js index cdfba505eb4..93594357747 100644 --- a/lib/amd/src/local/reactive/debug.js +++ b/lib/amd/src/local/reactive/debug.js @@ -16,7 +16,7 @@ /** * Reactive module debug tools. * - * @module core/reactive/local/reactive/debug + * @module core/local/reactive/debug * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/local/reactive/reactive.js b/lib/amd/src/local/reactive/reactive.js index 250395c3631..e629264fd0b 100644 --- a/lib/amd/src/local/reactive/reactive.js +++ b/lib/amd/src/local/reactive/reactive.js @@ -16,8 +16,8 @@ /** * A generic single state reactive module. * - * @module core/reactive/local/reactive/reactive - * @class core/reactive/local/reactive/reactive + * @module core/local/reactive/reactive + * @class core/local/reactive/reactive * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/local/reactive/statemanager.js b/lib/amd/src/local/reactive/statemanager.js index 0b4c311582b..a8bcbae2962 100644 --- a/lib/amd/src/local/reactive/statemanager.js +++ b/lib/amd/src/local/reactive/statemanager.js @@ -24,8 +24,8 @@ * - Proxy handler: a private class to keep track of the state object changes. * - StateMap class: a private class extending Map class that triggers event when a state list is modifed. * - * @module core/local/reactive/stateManager - * @class core/local/reactive/stateManager + * @module core/local/reactive/statemanager + * @class StateManager * @copyright 2021 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/paged_content_paging_bar.js b/lib/amd/src/paged_content_paging_bar.js index 8deb94cd555..9bc656f62c9 100644 --- a/lib/amd/src/paged_content_paging_bar.js +++ b/lib/amd/src/paged_content_paging_bar.js @@ -16,7 +16,7 @@ /** * Javascript to enhance the paged content paging bar. * - * @module core/paging_bar + * @module core/paged_content_paging_bar * @copyright 2018 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/amd/src/userfeedback.js b/lib/amd/src/userfeedback.js index 28a77eddcb3..f898e327756 100644 --- a/lib/amd/src/userfeedback.js +++ b/lib/amd/src/userfeedback.js @@ -16,7 +16,7 @@ /** * Handle clicking on action links of the feedback alert. * - * @module core/cta_feedback + * @module core/userfeedback * @copyright 2020 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/amd/build/defaults.min.js b/lib/editor/tiny/amd/build/defaults.min.js index 720452b035f..06e471a0895 100644 --- a/lib/editor/tiny/amd/build/defaults.min.js +++ b/lib/editor/tiny/amd/build/defaults.min.js @@ -2,7 +2,7 @@ define("editor_tiny/defaults",["exports"],(function(_exports){Object.definePrope /** * TinyMCE Editor Upstream defaults. * - * @module editor_tiny/editor + * @module editor_tiny/defaults * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/amd/build/defaults.min.js.map b/lib/editor/tiny/amd/build/defaults.min.js.map index c65239b9af4..03d1a083987 100644 --- a/lib/editor/tiny/amd/build/defaults.min.js.map +++ b/lib/editor/tiny/amd/build/defaults.min.js.map @@ -1 +1 @@ -{"version":3,"file":"defaults.min.js","sources":["../src/defaults.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/* eslint-disable max-len, */\n\n/**\n * TinyMCE Editor Upstream defaults.\n *\n * @module editor_tiny/editor\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * The upstream defaults for the TinyMCE Menu.\n *\n * This value is defined in the TinyMCE documentation, but not exported anywhere useful.\n * https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu\n *\n * @returns {Object}\n */\nexport const getDefaultMenu = () => {\n return {\n file: {title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations'},\n edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'},\n view: {title: 'View', items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'},\n insert: {title: 'Insert', items: 'image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime'},\n format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'},\n tools: {title: 'Tools', items: 'spellchecker spellcheckerlanguage | a11ycheck code wordcount'},\n table: {title: 'Table', items: 'inserttable | cell row column | advtablesort | tableprops deletetable'},\n help: {title: 'Help', items: 'help'}\n };\n};\n\n/**\n * The default toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu\n *\n * @returns {Object}\n */\nexport const getDefaultToolbar = () => {\n return [\n {\n name: 'history',\n items: [\n 'undo',\n 'redo',\n ],\n },\n {\n name: 'formatting',\n items: [\n 'bold',\n 'italic',\n ],\n },\n {\n name: 'alignment',\n items: [\n 'alignleft',\n 'aligncenter',\n 'alignright',\n 'alignjustify',\n ],\n },\n {\n name: 'indentation',\n items: [\n 'outdent',\n 'indent',\n ],\n },\n {\n name: 'lists',\n items: [\n 'bullist',\n 'numlist',\n ],\n },\n {\n name: 'comments',\n items: ['addcomment'],\n },\n ];\n};\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsSelectionToolbar = () => 'bold italic | quicklink h2 h3 blockquote';\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsInsertToolbar = () => 'quickimage quicktable';\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsImageToolbar = () => 'alignleft aligncenter alignright';\n\n/**\n * Get the default configuration provided by TinyMCE.\n *\n * @returns {object}\n */\nexport const getDefaultConfiguration = () => ({\n // Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/toolbar-configuration-options/\n // TODO: Move this configuration to a passed-in option.\n // eslint-disable-next-line camelcase\n toolbar_mode: 'sliding',\n toolbar: getDefaultToolbar(),\n\n // Quickbars Selection Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar\n // eslint-disable-next-line camelcase\n quickbars_selection_toolbar: getDefaultQuickbarsSelectionToolbar(),\n\n // Quickbars Select Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar\n // eslint-disable-next-line camelcase\n quickbars_insert_toolbar: getDefaultQuickbarsInsertToolbar(),\n\n // Quickbars Image Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar\n // eslint-disable-next-line camelcase\n quickbars_image_toolbar: getDefaultQuickbarsImageToolbar(),\n\n\n // Menu configuration.\n // https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/\n // TODO: Move this configuration to a passed-in option.\n menu: getDefaultMenu(),\n\n // Mobile configuration.\n // At this time we will use the default TinyMCE mobile configuration.\n // https://www.tiny.cloud/docs/tinymce/6/tinymce-for-mobile/\n\n // Skins\n skin: 'oxide',\n});\n"],"names":["getDefaultMenu","file","title","items","edit","view","insert","format","tools","table","help","getDefaultToolbar","name","getDefaultQuickbarsSelectionToolbar","getDefaultQuickbarsInsertToolbar","getDefaultQuickbarsImageToolbar","toolbar_mode","toolbar","quickbars_selection_toolbar","quickbars_insert_toolbar","quickbars_image_toolbar","menu","skin"],"mappings":";;;;;;;;MAiCaA,eAAiB,KACnB,CACHC,KAAM,CAACC,MAAO,OAAQC,MAAO,8EAC7BC,KAAM,CAACF,MAAO,OAAQC,MAAO,oEAC7BE,KAAM,CAACH,MAAO,OAAQC,MAAO,gGAC7BG,OAAQ,CAACJ,MAAO,SAAUC,MAAO,gKACjCI,OAAQ,CAACL,MAAO,SAAUC,MAAO,6KACjCK,MAAO,CAACN,MAAO,QAASC,MAAO,gEAC/BM,MAAO,CAACP,MAAO,QAASC,MAAO,yEAC/BO,KAAM,CAACR,MAAO,OAAQC,MAAO,uDAaxBQ,kBAAoB,IACtB,CACH,CACIC,KAAM,UACNT,MAAO,CACH,OACA,SAGR,CACIS,KAAM,aACNT,MAAO,CACH,OACA,WAGR,CACIS,KAAM,YACNT,MAAO,CACH,YACA,cACA,aACA,iBAGR,CACIS,KAAM,cACNT,MAAO,CACH,UACA,WAGR,CACIS,KAAM,QACNT,MAAO,CACH,UACA,YAGR,CACIS,KAAM,WACNT,MAAO,CAAC,mEAcPU,oCAAsC,IAAM,kIAW5CC,iCAAmC,IAAM,yGAWzCC,gCAAkC,IAAM,6IAOd,MAKnCC,aAAc,UACdC,QAzFO,CACH,CACIL,KAAM,UACNT,MAAO,CACH,OACA,SAGR,CACIS,KAAM,aACNT,MAAO,CACH,OACA,WAGR,CACIS,KAAM,YACNT,MAAO,CACH,YACA,cACA,aACA,iBAGR,CACIS,KAAM,cACNT,MAAO,CACH,UACA,WAGR,CACIS,KAAM,QACNT,MAAO,CACH,UACA,YAGR,CACIS,KAAM,WACNT,MAAO,CAAC,gBAsDhBe,4BAxCqD,2CA6CrDC,yBAlCkD,wBAuClDC,wBA5BiD,mCAkCjDC,KApIO,CACHpB,KAAM,CAACC,MAAO,OAAQC,MAAO,8EAC7BC,KAAM,CAACF,MAAO,OAAQC,MAAO,oEAC7BE,KAAM,CAACH,MAAO,OAAQC,MAAO,gGAC7BG,OAAQ,CAACJ,MAAO,SAAUC,MAAO,gKACjCI,OAAQ,CAACL,MAAO,SAAUC,MAAO,6KACjCK,MAAO,CAACN,MAAO,QAASC,MAAO,gEAC/BM,MAAO,CAACP,MAAO,QAASC,MAAO,yEAC/BO,KAAM,CAACR,MAAO,OAAQC,MAAO,SAmIjCmB,KAAM"} \ No newline at end of file +{"version":3,"file":"defaults.min.js","sources":["../src/defaults.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/* eslint-disable max-len, */\n\n/**\n * TinyMCE Editor Upstream defaults.\n *\n * @module editor_tiny/defaults\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * The upstream defaults for the TinyMCE Menu.\n *\n * This value is defined in the TinyMCE documentation, but not exported anywhere useful.\n * https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu\n *\n * @returns {Object}\n */\nexport const getDefaultMenu = () => {\n return {\n file: {title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations'},\n edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace'},\n view: {title: 'View', items: 'code | visualaid visualchars visualblocks | spellchecker | preview fullscreen | showcomments'},\n insert: {title: 'Insert', items: 'image link media addcomment pageembed template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor tableofcontents | insertdatetime'},\n format: {title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | styles blocks fontfamily fontsize align lineheight | forecolor backcolor | language | removeformat'},\n tools: {title: 'Tools', items: 'spellchecker spellcheckerlanguage | a11ycheck code wordcount'},\n table: {title: 'Table', items: 'inserttable | cell row column | advtablesort | tableprops deletetable'},\n help: {title: 'Help', items: 'help'}\n };\n};\n\n/**\n * The default toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/#menu\n *\n * @returns {Object}\n */\nexport const getDefaultToolbar = () => {\n return [\n {\n name: 'history',\n items: [\n 'undo',\n 'redo',\n ],\n },\n {\n name: 'formatting',\n items: [\n 'bold',\n 'italic',\n ],\n },\n {\n name: 'alignment',\n items: [\n 'alignleft',\n 'aligncenter',\n 'alignright',\n 'alignjustify',\n ],\n },\n {\n name: 'indentation',\n items: [\n 'outdent',\n 'indent',\n ],\n },\n {\n name: 'lists',\n items: [\n 'bullist',\n 'numlist',\n ],\n },\n {\n name: 'comments',\n items: ['addcomment'],\n },\n ];\n};\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsSelectionToolbar = () => 'bold italic | quicklink h2 h3 blockquote';\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsInsertToolbar = () => 'quickimage quicktable';\n\n/**\n * The default quickbars_insert_toolbar configuration to use.\n *\n * This is based upon the default value used if no toolbar is specified.\n *\n * https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar\n *\n * @returns {string}\n */\nexport const getDefaultQuickbarsImageToolbar = () => 'alignleft aligncenter alignright';\n\n/**\n * Get the default configuration provided by TinyMCE.\n *\n * @returns {object}\n */\nexport const getDefaultConfiguration = () => ({\n // Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/toolbar-configuration-options/\n // TODO: Move this configuration to a passed-in option.\n // eslint-disable-next-line camelcase\n toolbar_mode: 'sliding',\n toolbar: getDefaultToolbar(),\n\n // Quickbars Selection Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_selection_toolbar\n // eslint-disable-next-line camelcase\n quickbars_selection_toolbar: getDefaultQuickbarsSelectionToolbar(),\n\n // Quickbars Select Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_insert_toolbar\n // eslint-disable-next-line camelcase\n quickbars_insert_toolbar: getDefaultQuickbarsInsertToolbar(),\n\n // Quickbars Image Toolbar configuration.\n // https://www.tiny.cloud/docs/tinymce/6/quickbars/#quickbars_image_toolbar\n // eslint-disable-next-line camelcase\n quickbars_image_toolbar: getDefaultQuickbarsImageToolbar(),\n\n\n // Menu configuration.\n // https://www.tiny.cloud/docs/tinymce/6/menus-configuration-options/\n // TODO: Move this configuration to a passed-in option.\n menu: getDefaultMenu(),\n\n // Mobile configuration.\n // At this time we will use the default TinyMCE mobile configuration.\n // https://www.tiny.cloud/docs/tinymce/6/tinymce-for-mobile/\n\n // Skins\n skin: 'oxide',\n});\n"],"names":["getDefaultMenu","file","title","items","edit","view","insert","format","tools","table","help","getDefaultToolbar","name","getDefaultQuickbarsSelectionToolbar","getDefaultQuickbarsInsertToolbar","getDefaultQuickbarsImageToolbar","toolbar_mode","toolbar","quickbars_selection_toolbar","quickbars_insert_toolbar","quickbars_image_toolbar","menu","skin"],"mappings":";;;;;;;;MAiCaA,eAAiB,KACnB,CACHC,KAAM,CAACC,MAAO,OAAQC,MAAO,8EAC7BC,KAAM,CAACF,MAAO,OAAQC,MAAO,oEAC7BE,KAAM,CAACH,MAAO,OAAQC,MAAO,gGAC7BG,OAAQ,CAACJ,MAAO,SAAUC,MAAO,gKACjCI,OAAQ,CAACL,MAAO,SAAUC,MAAO,6KACjCK,MAAO,CAACN,MAAO,QAASC,MAAO,gEAC/BM,MAAO,CAACP,MAAO,QAASC,MAAO,yEAC/BO,KAAM,CAACR,MAAO,OAAQC,MAAO,uDAaxBQ,kBAAoB,IACtB,CACH,CACIC,KAAM,UACNT,MAAO,CACH,OACA,SAGR,CACIS,KAAM,aACNT,MAAO,CACH,OACA,WAGR,CACIS,KAAM,YACNT,MAAO,CACH,YACA,cACA,aACA,iBAGR,CACIS,KAAM,cACNT,MAAO,CACH,UACA,WAGR,CACIS,KAAM,QACNT,MAAO,CACH,UACA,YAGR,CACIS,KAAM,WACNT,MAAO,CAAC,mEAcPU,oCAAsC,IAAM,kIAW5CC,iCAAmC,IAAM,yGAWzCC,gCAAkC,IAAM,6IAOd,MAKnCC,aAAc,UACdC,QAzFO,CACH,CACIL,KAAM,UACNT,MAAO,CACH,OACA,SAGR,CACIS,KAAM,aACNT,MAAO,CACH,OACA,WAGR,CACIS,KAAM,YACNT,MAAO,CACH,YACA,cACA,aACA,iBAGR,CACIS,KAAM,cACNT,MAAO,CACH,UACA,WAGR,CACIS,KAAM,QACNT,MAAO,CACH,UACA,YAGR,CACIS,KAAM,WACNT,MAAO,CAAC,gBAsDhBe,4BAxCqD,2CA6CrDC,yBAlCkD,wBAuClDC,wBA5BiD,mCAkCjDC,KApIO,CACHpB,KAAM,CAACC,MAAO,OAAQC,MAAO,8EAC7BC,KAAM,CAACF,MAAO,OAAQC,MAAO,oEAC7BE,KAAM,CAACH,MAAO,OAAQC,MAAO,gGAC7BG,OAAQ,CAACJ,MAAO,SAAUC,MAAO,gKACjCI,OAAQ,CAACL,MAAO,SAAUC,MAAO,6KACjCK,MAAO,CAACN,MAAO,QAASC,MAAO,gEAC/BM,MAAO,CAACP,MAAO,QAASC,MAAO,yEAC/BO,KAAM,CAACR,MAAO,OAAQC,MAAO,SAmIjCmB,KAAM"} \ No newline at end of file diff --git a/lib/editor/tiny/amd/build/uploader.min.js.map b/lib/editor/tiny/amd/build/uploader.min.js.map index d8de171c786..b32925ec1ec 100644 --- a/lib/editor/tiny/amd/build/uploader.min.js.map +++ b/lib/editor/tiny/amd/build/uploader.min.js.map @@ -1 +1 @@ -{"version":3,"file":"uploader.min.js","sources":["../src/uploader.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 * Tiny Media plugin for Moodle.\n *\n * @module editor_tiny/uploade\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {\n notifyUploadStarted,\n notifyUploadCompleted,\n} from 'core_form/events';\nimport {getFilePicker} from 'editor_tiny/options';\n\n// This image uploader is based on advice given at:\n// https://www.tiny.cloud/docs/tinymce/6/upload-images/\nexport default (editor, filePickerType, blob, fileName, progress) => new Promise((resolve, reject) => {\n notifyUploadStarted(editor.targetElm.id);\n\n const xhr = new XMLHttpRequest();\n\n // Add the progress handler.\n xhr.upload.addEventListener('progress', (e) => {\n progress(e.loaded / e.total * 100);\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status === 403) {\n reject({\n message: `HTTP error: ${xhr.status}`,\n remove: true,\n });\n return;\n }\n\n if (xhr.status < 200 || xhr.status >= 300) {\n reject(`HTTP Error: ${xhr.status}`);\n return;\n }\n\n const response = JSON.parse(xhr.responseText);\n\n if (!response) {\n reject(`Invalid JSON: ${xhr.responseText}`);\n return;\n }\n\n notifyUploadCompleted(editor.targetElm.id);\n\n let location;\n if (response.url) {\n location = response.url;\n } else if (response.event && response.event === 'fileexists' && response.newfile) {\n // A file with this name is already in use here - rename to avoid conflict.\n // Chances are, it's a different image (stored in a different folder on the user's computer).\n // If the user wants to reuse an existing image, they can copy/paste it within the editor.\n location = response.newfile.url;\n }\n\n if (location && typeof location === 'string') {\n resolve(location);\n return;\n }\n\n reject(`Unable to handle file result: ${xhr.responseText}`);\n });\n\n xhr.addEventListener('error', () => {\n reject({\n message: `Upload failed due to an XHR transport error. Code: ${xhr.status}`,\n remove: true,\n });\n });\n\n const formData = new FormData();\n const options = getFilePicker(editor, filePickerType);\n\n formData.append('repo_upload_file', blob, fileName);\n formData.append('itemid', options.itemid);\n Object.values(options.repositories).some((repository) => {\n if (repository.type === 'upload') {\n formData.append('repo_id', repository.id);\n return true;\n }\n return false;\n });\n\n formData.append('env', options.env);\n formData.append('sesskey', M.cfg.sesskey);\n formData.append('client_id', options.client_id);\n formData.append('savepath', options.savepath ?? '/');\n formData.append('ctx_id', options.context.id);\n\n xhr.open('POST', `${M.cfg.wwwroot}/repository/repository_ajax.php?action=upload`, true);\n xhr.send(formData);\n});\n"],"names":["editor","filePickerType","blob","fileName","progress","Promise","resolve","reject","targetElm","id","xhr","XMLHttpRequest","upload","addEventListener","e","loaded","total","status","message","remove","response","JSON","parse","responseText","location","url","event","newfile","formData","FormData","options","append","itemid","Object","values","repositories","some","repository","type","env","M","cfg","sesskey","client_id","savepath","context","open","wwwroot","send"],"mappings":"gOA8Be,CAACA,OAAQC,eAAgBC,KAAMC,SAAUC,WAAa,IAAIC,SAAQ,CAACC,QAASC,gEACnEP,OAAOQ,UAAUC,UAE/BC,IAAM,IAAIC,eAGhBD,IAAIE,OAAOC,iBAAiB,YAAaC,IACrCV,SAASU,EAAEC,OAASD,EAAEE,MAAQ,QAGlCN,IAAIG,iBAAiB,QAAQ,QACN,MAAfH,IAAIO,mBACJV,OAAO,CACHW,8BAAwBR,IAAIO,QAC5BE,QAAQ,OAKZT,IAAIO,OAAS,KAAOP,IAAIO,QAAU,gBAClCV,6BAAsBG,IAAIO,eAIxBG,SAAWC,KAAKC,MAAMZ,IAAIa,kBAE3BH,qBACDb,+BAAwBG,IAAIa,mBAM5BC,2CAFkBxB,OAAOQ,UAAUC,IAGnCW,SAASK,IACTD,SAAWJ,SAASK,IACbL,SAASM,OAA4B,eAAnBN,SAASM,OAA0BN,SAASO,UAIrEH,SAAWJ,SAASO,QAAQF,KAG5BD,UAAgC,iBAAbA,SACnBlB,QAAQkB,UAIZjB,+CAAwCG,IAAIa,kBAGhDb,IAAIG,iBAAiB,SAAS,KAC1BN,OAAO,CACHW,qEAA+DR,IAAIO,QACnEE,QAAQ,aAIVS,SAAW,IAAIC,SACfC,SAAU,0BAAc9B,OAAQC,gBAEtC2B,SAASG,OAAO,mBAAoB7B,KAAMC,UAC1CyB,SAASG,OAAO,SAAUD,QAAQE,QAClCC,OAAOC,OAAOJ,QAAQK,cAAcC,MAAMC,YACd,WAApBA,WAAWC,OACXV,SAASG,OAAO,UAAWM,WAAW5B,KAC/B,KAKfmB,SAASG,OAAO,MAAOD,QAAQS,KAC/BX,SAASG,OAAO,UAAWS,EAAEC,IAAIC,SACjCd,SAASG,OAAO,YAAaD,QAAQa,WACrCf,SAASG,OAAO,qCAAYD,QAAQc,wDAAY,KAChDhB,SAASG,OAAO,SAAUD,QAAQe,QAAQpC,IAE1CC,IAAIoC,KAAK,iBAAWN,EAAEC,IAAIM,0DAAwD,GAClFrC,IAAIsC,KAAKpB"} \ No newline at end of file +{"version":3,"file":"uploader.min.js","sources":["../src/uploader.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 * Tiny Media plugin for Moodle.\n *\n * @module editor_tiny/uploader\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {\n notifyUploadStarted,\n notifyUploadCompleted,\n} from 'core_form/events';\nimport {getFilePicker} from 'editor_tiny/options';\n\n// This image uploader is based on advice given at:\n// https://www.tiny.cloud/docs/tinymce/6/upload-images/\nexport default (editor, filePickerType, blob, fileName, progress) => new Promise((resolve, reject) => {\n notifyUploadStarted(editor.targetElm.id);\n\n const xhr = new XMLHttpRequest();\n\n // Add the progress handler.\n xhr.upload.addEventListener('progress', (e) => {\n progress(e.loaded / e.total * 100);\n });\n\n xhr.addEventListener('load', () => {\n if (xhr.status === 403) {\n reject({\n message: `HTTP error: ${xhr.status}`,\n remove: true,\n });\n return;\n }\n\n if (xhr.status < 200 || xhr.status >= 300) {\n reject(`HTTP Error: ${xhr.status}`);\n return;\n }\n\n const response = JSON.parse(xhr.responseText);\n\n if (!response) {\n reject(`Invalid JSON: ${xhr.responseText}`);\n return;\n }\n\n notifyUploadCompleted(editor.targetElm.id);\n\n let location;\n if (response.url) {\n location = response.url;\n } else if (response.event && response.event === 'fileexists' && response.newfile) {\n // A file with this name is already in use here - rename to avoid conflict.\n // Chances are, it's a different image (stored in a different folder on the user's computer).\n // If the user wants to reuse an existing image, they can copy/paste it within the editor.\n location = response.newfile.url;\n }\n\n if (location && typeof location === 'string') {\n resolve(location);\n return;\n }\n\n reject(`Unable to handle file result: ${xhr.responseText}`);\n });\n\n xhr.addEventListener('error', () => {\n reject({\n message: `Upload failed due to an XHR transport error. Code: ${xhr.status}`,\n remove: true,\n });\n });\n\n const formData = new FormData();\n const options = getFilePicker(editor, filePickerType);\n\n formData.append('repo_upload_file', blob, fileName);\n formData.append('itemid', options.itemid);\n Object.values(options.repositories).some((repository) => {\n if (repository.type === 'upload') {\n formData.append('repo_id', repository.id);\n return true;\n }\n return false;\n });\n\n formData.append('env', options.env);\n formData.append('sesskey', M.cfg.sesskey);\n formData.append('client_id', options.client_id);\n formData.append('savepath', options.savepath ?? '/');\n formData.append('ctx_id', options.context.id);\n\n xhr.open('POST', `${M.cfg.wwwroot}/repository/repository_ajax.php?action=upload`, true);\n xhr.send(formData);\n});\n"],"names":["editor","filePickerType","blob","fileName","progress","Promise","resolve","reject","targetElm","id","xhr","XMLHttpRequest","upload","addEventListener","e","loaded","total","status","message","remove","response","JSON","parse","responseText","location","url","event","newfile","formData","FormData","options","append","itemid","Object","values","repositories","some","repository","type","env","M","cfg","sesskey","client_id","savepath","context","open","wwwroot","send"],"mappings":"gOA8Be,CAACA,OAAQC,eAAgBC,KAAMC,SAAUC,WAAa,IAAIC,SAAQ,CAACC,QAASC,gEACnEP,OAAOQ,UAAUC,UAE/BC,IAAM,IAAIC,eAGhBD,IAAIE,OAAOC,iBAAiB,YAAaC,IACrCV,SAASU,EAAEC,OAASD,EAAEE,MAAQ,QAGlCN,IAAIG,iBAAiB,QAAQ,QACN,MAAfH,IAAIO,mBACJV,OAAO,CACHW,8BAAwBR,IAAIO,QAC5BE,QAAQ,OAKZT,IAAIO,OAAS,KAAOP,IAAIO,QAAU,gBAClCV,6BAAsBG,IAAIO,eAIxBG,SAAWC,KAAKC,MAAMZ,IAAIa,kBAE3BH,qBACDb,+BAAwBG,IAAIa,mBAM5BC,2CAFkBxB,OAAOQ,UAAUC,IAGnCW,SAASK,IACTD,SAAWJ,SAASK,IACbL,SAASM,OAA4B,eAAnBN,SAASM,OAA0BN,SAASO,UAIrEH,SAAWJ,SAASO,QAAQF,KAG5BD,UAAgC,iBAAbA,SACnBlB,QAAQkB,UAIZjB,+CAAwCG,IAAIa,kBAGhDb,IAAIG,iBAAiB,SAAS,KAC1BN,OAAO,CACHW,qEAA+DR,IAAIO,QACnEE,QAAQ,aAIVS,SAAW,IAAIC,SACfC,SAAU,0BAAc9B,OAAQC,gBAEtC2B,SAASG,OAAO,mBAAoB7B,KAAMC,UAC1CyB,SAASG,OAAO,SAAUD,QAAQE,QAClCC,OAAOC,OAAOJ,QAAQK,cAAcC,MAAMC,YACd,WAApBA,WAAWC,OACXV,SAASG,OAAO,UAAWM,WAAW5B,KAC/B,KAKfmB,SAASG,OAAO,MAAOD,QAAQS,KAC/BX,SAASG,OAAO,UAAWS,EAAEC,IAAIC,SACjCd,SAASG,OAAO,YAAaD,QAAQa,WACrCf,SAASG,OAAO,qCAAYD,QAAQc,wDAAY,KAChDhB,SAASG,OAAO,SAAUD,QAAQe,QAAQpC,IAE1CC,IAAIoC,KAAK,iBAAWN,EAAEC,IAAIM,0DAAwD,GAClFrC,IAAIsC,KAAKpB"} \ No newline at end of file diff --git a/lib/editor/tiny/amd/src/defaults.js b/lib/editor/tiny/amd/src/defaults.js index 54d767d64e1..fdeeb5da0ed 100644 --- a/lib/editor/tiny/amd/src/defaults.js +++ b/lib/editor/tiny/amd/src/defaults.js @@ -18,7 +18,7 @@ /** * TinyMCE Editor Upstream defaults. * - * @module editor_tiny/editor + * @module editor_tiny/defaults * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/amd/src/uploader.js b/lib/editor/tiny/amd/src/uploader.js index de1b8499fa4..b190377511d 100644 --- a/lib/editor/tiny/amd/src/uploader.js +++ b/lib/editor/tiny/amd/src/uploader.js @@ -16,7 +16,7 @@ /** * Tiny Media plugin for Moodle. * - * @module editor_tiny/uploade + * @module editor_tiny/uploader * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js index 2cdfc6ab0b3..f1261b0b977 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js +++ b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js @@ -2,7 +2,7 @@ define("tiny_autosave/autosaver",["exports","./options","./storage","core/log"," /** * Storage helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/autosaver * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=void 0,Options=_interopRequireWildcard(Options),Storage=_interopRequireWildcard(Storage),_log=(obj=_log)&&obj.__esModule?obj:{default:obj};_exports.register=editor=>{const undoHandler=()=>{editor.undoManager.hasUndo()?Storage.saveDraft(editor):_log.default.debug("Ignoring undo event as there is no undo history",(0,_common.getLogSource)(editor))},visibilityChangedHandler=()=>{"hidden"===document.visibilityState&&Options.isInitialised(editor)&&Storage.saveDraft(editor)};document.addEventListener("visibilitychange",visibilityChangedHandler),editor.on("submit",(()=>{document.removeEventListener("visibilitychange",visibilityChangedHandler),Storage.removeAutosaveSession(editor)})),editor.on("init",(()=>{editor.on("AddUndo",undoHandler),editor.dom.isEmpty(editor.getBody())?(_log.default.info("Attempting to restore draft",(0,_common.getLogSource)(editor)),Storage.restoreDraft(editor)):(_log.default.warn("Skipping draft restoration. The editor is not empty.",(0,_common.getLogSource)(editor)),Options.markInitialised(editor))}))}})); diff --git a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map index 9fb5152ac8c..ee05b2e52f6 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map +++ b/lib/editor/tiny/plugins/autosave/amd/build/autosaver.min.js.map @@ -1 +1 @@ -{"version":3,"file":"autosaver.min.js","sources":["../src/autosaver.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 * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Options from './options';\nimport * as Storage from './storage';\nimport Log from 'core/log';\nimport {getLogSource} from './common';\n\nexport const register = (editor) => {\n const undoHandler = () => {\n if (!editor.undoManager.hasUndo()) {\n Log.debug(`Ignoring undo event as there is no undo history`, getLogSource(editor));\n return;\n }\n Storage.saveDraft(editor);\n };\n\n const visibilityChangedHandler = () => {\n if (document.visibilityState === 'hidden') {\n if (Options.isInitialised(editor)) {\n Storage.saveDraft(editor);\n }\n }\n };\n\n // Attempt to store the draft one final time before the page unloads.\n // Note: This may need to be sent as a beacon instead.\n document.addEventListener('visibilitychange', visibilityChangedHandler);\n\n // When the page is submitted as a form, remove the draft.\n editor.on('submit', () => {\n document.removeEventListener('visibilitychange', visibilityChangedHandler);\n Storage.removeAutosaveSession(editor);\n });\n\n editor.on('init', () => {\n // Setup the Undo handler.\n editor.on('AddUndo', undoHandler);\n\n if (editor.dom.isEmpty(editor.getBody())) {\n Log.info(`Attempting to restore draft`, getLogSource(editor));\n Storage.restoreDraft(editor);\n } else {\n // There was nothing to restore, so we can mark the editor as initialised.\n Log.warn(`Skipping draft restoration. The editor is not empty.`, getLogSource(editor));\n Options.markInitialised(editor);\n }\n });\n};\n"],"names":["editor","undoHandler","undoManager","hasUndo","Storage","saveDraft","debug","visibilityChangedHandler","document","visibilityState","Options","isInitialised","addEventListener","on","removeEventListener","removeAutosaveSession","dom","isEmpty","getBody","info","restoreDraft","warn","markInitialised"],"mappings":";;;;;;;4OA4ByBA,eACfC,YAAc,KACXD,OAAOE,YAAYC,UAIxBC,QAAQC,UAAUL,qBAHVM,yDAAyD,wBAAaN,UAM5EO,yBAA2B,KACI,WAA7BC,SAASC,iBACLC,QAAQC,cAAcX,SACtBI,QAAQC,UAAUL,SAO9BQ,SAASI,iBAAiB,mBAAoBL,0BAG9CP,OAAOa,GAAG,UAAU,KAChBL,SAASM,oBAAoB,mBAAoBP,0BACjDH,QAAQW,sBAAsBf,WAGlCA,OAAOa,GAAG,QAAQ,KAEdb,OAAOa,GAAG,UAAWZ,aAEjBD,OAAOgB,IAAIC,QAAQjB,OAAOkB,yBACtBC,oCAAoC,wBAAanB,SACrDI,QAAQgB,aAAapB,uBAGjBqB,6DAA6D,wBAAarB,SAC9EU,QAAQY,gBAAgBtB"} \ No newline at end of file +{"version":3,"file":"autosaver.min.js","sources":["../src/autosaver.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 * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/autosaver\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Options from './options';\nimport * as Storage from './storage';\nimport Log from 'core/log';\nimport {getLogSource} from './common';\n\nexport const register = (editor) => {\n const undoHandler = () => {\n if (!editor.undoManager.hasUndo()) {\n Log.debug(`Ignoring undo event as there is no undo history`, getLogSource(editor));\n return;\n }\n Storage.saveDraft(editor);\n };\n\n const visibilityChangedHandler = () => {\n if (document.visibilityState === 'hidden') {\n if (Options.isInitialised(editor)) {\n Storage.saveDraft(editor);\n }\n }\n };\n\n // Attempt to store the draft one final time before the page unloads.\n // Note: This may need to be sent as a beacon instead.\n document.addEventListener('visibilitychange', visibilityChangedHandler);\n\n // When the page is submitted as a form, remove the draft.\n editor.on('submit', () => {\n document.removeEventListener('visibilitychange', visibilityChangedHandler);\n Storage.removeAutosaveSession(editor);\n });\n\n editor.on('init', () => {\n // Setup the Undo handler.\n editor.on('AddUndo', undoHandler);\n\n if (editor.dom.isEmpty(editor.getBody())) {\n Log.info(`Attempting to restore draft`, getLogSource(editor));\n Storage.restoreDraft(editor);\n } else {\n // There was nothing to restore, so we can mark the editor as initialised.\n Log.warn(`Skipping draft restoration. The editor is not empty.`, getLogSource(editor));\n Options.markInitialised(editor);\n }\n });\n};\n"],"names":["editor","undoHandler","undoManager","hasUndo","Storage","saveDraft","debug","visibilityChangedHandler","document","visibilityState","Options","isInitialised","addEventListener","on","removeEventListener","removeAutosaveSession","dom","isEmpty","getBody","info","restoreDraft","warn","markInitialised"],"mappings":";;;;;;;4OA4ByBA,eACfC,YAAc,KACXD,OAAOE,YAAYC,UAIxBC,QAAQC,UAAUL,qBAHVM,yDAAyD,wBAAaN,UAM5EO,yBAA2B,KACI,WAA7BC,SAASC,iBACLC,QAAQC,cAAcX,SACtBI,QAAQC,UAAUL,SAO9BQ,SAASI,iBAAiB,mBAAoBL,0BAG9CP,OAAOa,GAAG,UAAU,KAChBL,SAASM,oBAAoB,mBAAoBP,0BACjDH,QAAQW,sBAAsBf,WAGlCA,OAAOa,GAAG,QAAQ,KAEdb,OAAOa,GAAG,UAAWZ,aAEjBD,OAAOgB,IAAIC,QAAQjB,OAAOkB,yBACtBC,oCAAoC,wBAAanB,SACrDI,QAAQgB,aAAapB,uBAGjBqB,6DAA6D,wBAAarB,SAC9EU,QAAQY,gBAAgBtB"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/build/common.min.js.map b/lib/editor/tiny/plugins/autosave/amd/build/common.min.js.map index 4d851b9913f..1f8547ae23a 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/common.min.js.map +++ b/lib/editor/tiny/plugins/autosave/amd/build/common.min.js.map @@ -1 +1 @@ -{"version":3,"file":"common.min.js","sources":["../src/common.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 * Tiny Autosave plugin for Moodle.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n component: 'tiny_autosave',\n pluginName: 'tiny_autosave/plugin',\n getLogSource: (editor) => `tiny_autosave/${editor.id}`,\n};\n"],"names":["component","pluginName","getLogSource","editor","id"],"mappings":"sKAuBe,CACXA,UAAW,gBACXC,WAAY,uBACZC,aAAeC,gCAA4BA,OAAOC"} \ No newline at end of file +{"version":3,"file":"common.min.js","sources":["../src/common.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 * Tiny Autosave plugin for Moodle.\n *\n * @module tiny_autosave/common\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n component: 'tiny_autosave',\n pluginName: 'tiny_autosave/plugin',\n getLogSource: (editor) => `tiny_autosave/${editor.id}`,\n};\n"],"names":["component","pluginName","getLogSource","editor","id"],"mappings":"sKAuBe,CACXA,UAAW,gBACXC,WAAY,uBACZC,aAAeC,gCAA4BA,OAAOC"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/build/options.min.js b/lib/editor/tiny/plugins/autosave/amd/build/options.min.js index f549657bcda..ca69aa8fd3f 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/options.min.js +++ b/lib/editor/tiny/plugins/autosave/amd/build/options.min.js @@ -2,7 +2,7 @@ define("tiny_autosave/options",["exports","./common","editor_tiny/options","edit /** * Options helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/options * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/autosave/amd/build/options.min.js.map b/lib/editor/tiny/plugins/autosave/amd/build/options.min.js.map index b8059774741..fb34e08278c 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/options.min.js.map +++ b/lib/editor/tiny/plugins/autosave/amd/build/options.min.js.map @@ -1 +1 @@ -{"version":3,"file":"options.min.js","sources":["../src/options.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 * Options helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {pluginName} from './common';\nimport {\n getContextId,\n getDraftItemId,\n getPluginOptionName,\n} from 'editor_tiny/options';\nimport {ensureEditorIsValid} from 'editor_tiny/utils';\n\nconst initialisedOptionName = getPluginOptionName(pluginName, 'initialised');\nconst pageHashName = getPluginOptionName(pluginName, 'pagehash');\nconst pageInstanceName = getPluginOptionName(pluginName, 'pageinstance');\nconst backoffTime = getPluginOptionName(pluginName, 'backoffTime');\nconst autosaveHasReset = getPluginOptionName(pluginName, 'autosaveHasReset');\n\nexport const register = (editor) => {\n const registerOption = editor.options.register;\n registerOption(initialisedOptionName, {\n processor: 'boolean',\n \"default\": false,\n });\n\n registerOption(pageHashName, {\n processor: 'string',\n \"default\": '',\n });\n\n registerOption(pageInstanceName, {\n processor: 'string',\n \"default\": '',\n });\n registerOption(pageInstanceName, {\n processor: 'string',\n \"default\": '',\n });\n registerOption(backoffTime, {\n processor: 'number',\n \"default\": 500,\n });\n registerOption(autosaveHasReset, {\n processor: 'boolean',\n \"default\": false,\n });\n};\n\nexport const isInitialised = (editor) => {\n if (!ensureEditorIsValid(editor)) {\n return false;\n }\n\n return editor.options.get(initialisedOptionName);\n};\nexport const markInitialised = (editor) => editor.options.set(initialisedOptionName, true);\nexport const getPageHash = (editor) => editor.options.get(pageHashName);\nexport const getPageInstance = (editor) => editor.options.get(pageInstanceName);\nexport const getBackoffTime = (editor) => editor.options.get(backoffTime);\nexport const setAutosaveHasReset = (editor) => editor.options.set(autosaveHasReset, true);\nexport const hasAutosaveHasReset = (editor) => editor.options.get(autosaveHasReset);\n\nexport {\n getContextId,\n getDraftItemId,\n};\n"],"names":["initialisedOptionName","pluginName","pageHashName","pageInstanceName","backoffTime","autosaveHasReset","editor","registerOption","options","register","processor","get","set"],"mappings":";;;;;;;;MA+BMA,uBAAwB,gCAAoBC,mBAAY,eACxDC,cAAe,gCAAoBD,mBAAY,YAC/CE,kBAAmB,gCAAoBF,mBAAY,gBACnDG,aAAc,gCAAoBH,mBAAY,eAC9CI,kBAAmB,gCAAoBJ,mBAAY,sCAEhCK,eACfC,eAAiBD,OAAOE,QAAQC,SACtCF,eAAeP,sBAAuB,CAClCU,UAAW,mBACA,IAGfH,eAAeL,aAAc,CACzBQ,UAAW,iBACA,KAGfH,eAAeJ,iBAAkB,CAC7BO,UAAW,iBACA,KAEfH,eAAeJ,iBAAkB,CAC7BO,UAAW,iBACA,KAEfH,eAAeH,YAAa,CACxBM,UAAW,iBACA,MAEfH,eAAeF,iBAAkB,CAC7BK,UAAW,mBACA,4BAIWJ,WACrB,8BAAoBA,SAIlBA,OAAOE,QAAQG,IAAIX,gDAEEM,QAAWA,OAAOE,QAAQI,IAAIZ,uBAAuB,wBACzDM,QAAWA,OAAOE,QAAQG,IAAIT,uCAC1BI,QAAWA,OAAOE,QAAQG,IAAIR,0CAC/BG,QAAWA,OAAOE,QAAQG,IAAIP,0CACzBE,QAAWA,OAAOE,QAAQI,IAAIP,kBAAkB,gCAChDC,QAAWA,OAAOE,QAAQG,IAAIN"} \ No newline at end of file +{"version":3,"file":"options.min.js","sources":["../src/options.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 * Options helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/options\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {pluginName} from './common';\nimport {\n getContextId,\n getDraftItemId,\n getPluginOptionName,\n} from 'editor_tiny/options';\nimport {ensureEditorIsValid} from 'editor_tiny/utils';\n\nconst initialisedOptionName = getPluginOptionName(pluginName, 'initialised');\nconst pageHashName = getPluginOptionName(pluginName, 'pagehash');\nconst pageInstanceName = getPluginOptionName(pluginName, 'pageinstance');\nconst backoffTime = getPluginOptionName(pluginName, 'backoffTime');\nconst autosaveHasReset = getPluginOptionName(pluginName, 'autosaveHasReset');\n\nexport const register = (editor) => {\n const registerOption = editor.options.register;\n registerOption(initialisedOptionName, {\n processor: 'boolean',\n \"default\": false,\n });\n\n registerOption(pageHashName, {\n processor: 'string',\n \"default\": '',\n });\n\n registerOption(pageInstanceName, {\n processor: 'string',\n \"default\": '',\n });\n registerOption(pageInstanceName, {\n processor: 'string',\n \"default\": '',\n });\n registerOption(backoffTime, {\n processor: 'number',\n \"default\": 500,\n });\n registerOption(autosaveHasReset, {\n processor: 'boolean',\n \"default\": false,\n });\n};\n\nexport const isInitialised = (editor) => {\n if (!ensureEditorIsValid(editor)) {\n return false;\n }\n\n return editor.options.get(initialisedOptionName);\n};\nexport const markInitialised = (editor) => editor.options.set(initialisedOptionName, true);\nexport const getPageHash = (editor) => editor.options.get(pageHashName);\nexport const getPageInstance = (editor) => editor.options.get(pageInstanceName);\nexport const getBackoffTime = (editor) => editor.options.get(backoffTime);\nexport const setAutosaveHasReset = (editor) => editor.options.set(autosaveHasReset, true);\nexport const hasAutosaveHasReset = (editor) => editor.options.get(autosaveHasReset);\n\nexport {\n getContextId,\n getDraftItemId,\n};\n"],"names":["initialisedOptionName","pluginName","pageHashName","pageInstanceName","backoffTime","autosaveHasReset","editor","registerOption","options","register","processor","get","set"],"mappings":";;;;;;;;MA+BMA,uBAAwB,gCAAoBC,mBAAY,eACxDC,cAAe,gCAAoBD,mBAAY,YAC/CE,kBAAmB,gCAAoBF,mBAAY,gBACnDG,aAAc,gCAAoBH,mBAAY,eAC9CI,kBAAmB,gCAAoBJ,mBAAY,sCAEhCK,eACfC,eAAiBD,OAAOE,QAAQC,SACtCF,eAAeP,sBAAuB,CAClCU,UAAW,mBACA,IAGfH,eAAeL,aAAc,CACzBQ,UAAW,iBACA,KAGfH,eAAeJ,iBAAkB,CAC7BO,UAAW,iBACA,KAEfH,eAAeJ,iBAAkB,CAC7BO,UAAW,iBACA,KAEfH,eAAeH,YAAa,CACxBM,UAAW,iBACA,MAEfH,eAAeF,iBAAkB,CAC7BK,UAAW,mBACA,4BAIWJ,WACrB,8BAAoBA,SAIlBA,OAAOE,QAAQG,IAAIX,gDAEEM,QAAWA,OAAOE,QAAQI,IAAIZ,uBAAuB,wBACzDM,QAAWA,OAAOE,QAAQG,IAAIT,uCAC1BI,QAAWA,OAAOE,QAAQG,IAAIR,0CAC/BG,QAAWA,OAAOE,QAAQG,IAAIP,0CACzBE,QAAWA,OAAOE,QAAQI,IAAIP,kBAAkB,gCAChDC,QAAWA,OAAOE,QAAQG,IAAIN"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js b/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js index 24a92110b02..d56076cabe5 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js +++ b/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js @@ -2,7 +2,7 @@ define("tiny_autosave/storage",["exports","./repository","core/pending","./optio /** * Storage helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/storage * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */(Repository),_pending=_interopRequireDefault(_pending),_log=_interopRequireDefault(_log);const saveDebounceMap=new Map;_exports.restoreDraft=async editor=>{const pendingPromise=new _pending.default("tiny_autosave/restoreDraft");try{const session=await Repository.resumeAutosaveSession(editor);session&&session.drafttext&&editor.undoManager.ignore((()=>{editor.setContent(session.drafttext),editor.save()}))}catch(error){_log.default.warn("Failed to restore draft: ".concat(error),(0,_common.getLogSource)(editor))}(0,_options.markInitialised)(editor),pendingPromise.resolve()};_exports.saveDraft=editor=>{const timerId=saveDebounceMap.get(editor);timerId&&clearTimeout(timerId),saveDebounceMap.set(editor,setTimeout((()=>{_log.default.debug("Saving draft",(0,_common.getLogSource)(editor)),Repository.updateAutosaveSession(editor).catch((error=>window.console.warn(error)))}),(0,_options.getBackoffTime)(editor)))};_exports.removeAutosaveSession=editor=>{_log.default.debug("Removing Autosave session",(0,_common.getLogSource)(editor)),Repository.removeAutosaveSession(editor)}})); diff --git a/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js.map b/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js.map index 904b2254bea..7faae323db9 100644 --- a/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js.map +++ b/lib/editor/tiny/plugins/autosave/amd/build/storage.min.js.map @@ -1 +1 @@ -{"version":3,"file":"storage.min.js","sources":["../src/storage.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 * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Repository from \"./repository\";\nimport Pending from 'core/pending';\nimport {\n markInitialised,\n getBackoffTime,\n} from \"./options\";\nimport Log from 'core/log';\nimport {getLogSource} from './common';\n\n/** @property {Map} A map of debounced draft saves */\nconst saveDebounceMap = new Map();\n\n/**\n * Attempt to restore a draft into the editor\n *\n * @param {TinyMCE} editor The Editor to restore a draft for\n */\nexport const restoreDraft = async(editor) => {\n const pendingPromise = new Pending('tiny_autosave/restoreDraft');\n try {\n const session = await Repository.resumeAutosaveSession(editor);\n if (session && session.drafttext) {\n editor.undoManager.ignore(() => {\n editor.setContent(session.drafttext);\n editor.save();\n });\n }\n } catch (error) {\n // Ignore any errors as drafts are optional.\n Log.warn(`Failed to restore draft: ${error}`, getLogSource(editor));\n }\n markInitialised(editor);\n pendingPromise.resolve();\n};\n\n/**\n * Save the current content of the editor as a draft.\n *\n * @param {TinyMCE} editor\n */\nexport const saveDraft = (editor) => {\n const timerId = saveDebounceMap.get(editor);\n if (timerId) {\n clearTimeout(timerId);\n }\n saveDebounceMap.set(editor, setTimeout(() => {\n Log.debug(`Saving draft`, getLogSource(editor));\n Repository.updateAutosaveSession(editor)\n .catch((error) => window.console.warn(error));\n }, getBackoffTime(editor)));\n};\n\n/**\n * Delete the draft for the current editor.\n *\n * @param {TinyMCE} editor\n */\nexport const removeAutosaveSession = (editor) => {\n Log.debug(`Removing Autosave session`, getLogSource(editor));\n Repository.removeAutosaveSession(editor);\n};\n"],"names":["saveDebounceMap","Map","async","pendingPromise","Pending","session","Repository","resumeAutosaveSession","editor","drafttext","undoManager","ignore","setContent","save","error","warn","resolve","timerId","get","clearTimeout","set","setTimeout","debug","updateAutosaveSession","catch","window","console","removeAutosaveSession"],"mappings":";;;;;;;oGAiCMA,gBAAkB,IAAIC,0BAOAC,MAAAA,eAClBC,eAAiB,IAAIC,iBAAQ,wCAEzBC,cAAgBC,WAAWC,sBAAsBC,QACnDH,SAAWA,QAAQI,WACnBD,OAAOE,YAAYC,QAAO,KACtBH,OAAOI,WAAWP,QAAQI,WAC1BD,OAAOK,UAGjB,MAAOC,oBAEDC,wCAAiCD,QAAS,wBAAaN,sCAE/CA,QAChBL,eAAea,8BAQOR,eAChBS,QAAUjB,gBAAgBkB,IAAIV,QAChCS,SACAE,aAAaF,SAEjBjB,gBAAgBoB,IAAIZ,OAAQa,YAAW,kBAC/BC,sBAAsB,wBAAad,SACvCF,WAAWiB,sBAAsBf,QAChCgB,OAAOV,OAAUW,OAAOC,QAAQX,KAAKD,YACvC,2BAAeN,0CAQgBA,sBAC9Bc,mCAAmC,wBAAad,SACpDF,WAAWqB,sBAAsBnB"} \ No newline at end of file +{"version":3,"file":"storage.min.js","sources":["../src/storage.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 * Storage helper for the Moodle Tiny Autosave plugin.\n *\n * @module tiny_autosave/storage\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Repository from \"./repository\";\nimport Pending from 'core/pending';\nimport {\n markInitialised,\n getBackoffTime,\n} from \"./options\";\nimport Log from 'core/log';\nimport {getLogSource} from './common';\n\n/** @property {Map} A map of debounced draft saves */\nconst saveDebounceMap = new Map();\n\n/**\n * Attempt to restore a draft into the editor\n *\n * @param {TinyMCE} editor The Editor to restore a draft for\n */\nexport const restoreDraft = async(editor) => {\n const pendingPromise = new Pending('tiny_autosave/restoreDraft');\n try {\n const session = await Repository.resumeAutosaveSession(editor);\n if (session && session.drafttext) {\n editor.undoManager.ignore(() => {\n editor.setContent(session.drafttext);\n editor.save();\n });\n }\n } catch (error) {\n // Ignore any errors as drafts are optional.\n Log.warn(`Failed to restore draft: ${error}`, getLogSource(editor));\n }\n markInitialised(editor);\n pendingPromise.resolve();\n};\n\n/**\n * Save the current content of the editor as a draft.\n *\n * @param {TinyMCE} editor\n */\nexport const saveDraft = (editor) => {\n const timerId = saveDebounceMap.get(editor);\n if (timerId) {\n clearTimeout(timerId);\n }\n saveDebounceMap.set(editor, setTimeout(() => {\n Log.debug(`Saving draft`, getLogSource(editor));\n Repository.updateAutosaveSession(editor)\n .catch((error) => window.console.warn(error));\n }, getBackoffTime(editor)));\n};\n\n/**\n * Delete the draft for the current editor.\n *\n * @param {TinyMCE} editor\n */\nexport const removeAutosaveSession = (editor) => {\n Log.debug(`Removing Autosave session`, getLogSource(editor));\n Repository.removeAutosaveSession(editor);\n};\n"],"names":["saveDebounceMap","Map","async","pendingPromise","Pending","session","Repository","resumeAutosaveSession","editor","drafttext","undoManager","ignore","setContent","save","error","warn","resolve","timerId","get","clearTimeout","set","setTimeout","debug","updateAutosaveSession","catch","window","console","removeAutosaveSession"],"mappings":";;;;;;;oGAiCMA,gBAAkB,IAAIC,0BAOAC,MAAAA,eAClBC,eAAiB,IAAIC,iBAAQ,wCAEzBC,cAAgBC,WAAWC,sBAAsBC,QACnDH,SAAWA,QAAQI,WACnBD,OAAOE,YAAYC,QAAO,KACtBH,OAAOI,WAAWP,QAAQI,WAC1BD,OAAOK,UAGjB,MAAOC,oBAEDC,wCAAiCD,QAAS,wBAAaN,sCAE/CA,QAChBL,eAAea,8BAQOR,eAChBS,QAAUjB,gBAAgBkB,IAAIV,QAChCS,SACAE,aAAaF,SAEjBjB,gBAAgBoB,IAAIZ,OAAQa,YAAW,kBAC/BC,sBAAsB,wBAAad,SACvCF,WAAWiB,sBAAsBf,QAChCgB,OAAOV,OAAUW,OAAOC,QAAQX,KAAKD,YACvC,2BAAeN,0CAQgBA,sBAC9Bc,mCAAmC,wBAAad,SACpDF,WAAWqB,sBAAsBnB"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js b/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js index 194a27a2238..c6c3c48c05d 100644 --- a/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js +++ b/lib/editor/tiny/plugins/autosave/amd/src/autosaver.js @@ -16,7 +16,7 @@ /** * Storage helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/autosaver * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/autosave/amd/src/common.js b/lib/editor/tiny/plugins/autosave/amd/src/common.js index 0c90e4c7ef1..25085a58a56 100644 --- a/lib/editor/tiny/plugins/autosave/amd/src/common.js +++ b/lib/editor/tiny/plugins/autosave/amd/src/common.js @@ -16,7 +16,7 @@ /** * Tiny Autosave plugin for Moodle. * - * @module tiny_autosave/plugin + * @module tiny_autosave/common * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/autosave/amd/src/options.js b/lib/editor/tiny/plugins/autosave/amd/src/options.js index d964e663e97..a76ad0befb0 100644 --- a/lib/editor/tiny/plugins/autosave/amd/src/options.js +++ b/lib/editor/tiny/plugins/autosave/amd/src/options.js @@ -16,7 +16,7 @@ /** * Options helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/options * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/autosave/amd/src/storage.js b/lib/editor/tiny/plugins/autosave/amd/src/storage.js index 328b9f8d460..6069c727e0c 100644 --- a/lib/editor/tiny/plugins/autosave/amd/src/storage.js +++ b/lib/editor/tiny/plugins/autosave/amd/src/storage.js @@ -16,7 +16,7 @@ /** * Storage helper for the Moodle Tiny Autosave plugin. * - * @module tiny_autosave/plugin + * @module tiny_autosave/storage * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js index 9c5fc8242bd..7abf804a353 100644 --- a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js +++ b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js @@ -2,7 +2,7 @@ define("tiny_h5p/ui",["exports","editor_tiny/utils","./common","./options","core /** * Tiny H5P Content configuration. * - * @module tiny_h5p/commands + * @module tiny_h5p/ui * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_config=_interopRequireDefault(_config),_modal=_interopRequireDefault(_modal),_modal_events=_interopRequireDefault(_modal_events),_modal_factory=_interopRequireDefault(_modal_factory),_pending=_interopRequireDefault(_pending);let openingSelection=null;_exports.handleAction=editor=>{openingSelection=editor.selection.getBookmark(),displayDialogue(editor)};const getTemplateContext=(editor,data)=>{var _permissions$upload,_permissions$embed,_data$url;const permissions=(0,_options.getPermissions)(editor),canUpload=null!==(_permissions$upload=permissions.upload)&&void 0!==_permissions$upload&&_permissions$upload,canEmbed=null!==(_permissions$embed=permissions.embed)&&void 0!==_permissions$embed&&_permissions$embed,canUploadAndEmbed=canUpload&&canEmbed;return Object.assign({},{elementid:editor.id,canUpload:canUpload,canEmbed:canEmbed,canUploadAndEmbed:canUploadAndEmbed,showOptions:!1,fileURL:null!==(_data$url=null==data?void 0:data.url)&&void 0!==_data$url?_data$url:""},data)},isValidUrl=url=>!!new RegExp("^(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*").test(url),handleDialogueSubmission=async(editor,modal,data)=>{const pendingPromise=new _pending.default("tiny_h5p:handleDialogueSubmission"),form=(0,_normalise.getList)(modal.getRoot())[0].querySelector("form");if(!form)return modal.destroy(),displayDialogue(editor,Object.assign({},data)),void pendingPromise.resolve();const submittedUrl=form.querySelector('input[name="url"]').value,url=((form,submittedUrl,permissions)=>{if(!submittedUrl||!submittedUrl.startsWith(_config.default.wwwroot)&&!isValidUrl(submittedUrl))return null;const url=new URL(submittedUrl);return null!=permissions&&permissions.upload&&form.querySelector('[name="download"]').checked&&url.searchParams.append("export",1),null!=permissions&&permissions.embed&&form.querySelector('[name="embed"]').checked&&url.searchParams.append("embed",1),form.querySelector('[name="copyright"]').checked&&url.searchParams.append("copyright",1),url})(form,submittedUrl,(0,_options.getPermissions)(editor));if(!url)return modal.destroy(),displayDialogue(editor,Object.assign({},data,{url:submittedUrl,invalidUrl:!0})),void pendingPromise.resolve();const content=await(0,_templates.renderForPromise)("".concat(_common.component,"/content"),{url:url.toString()});editor.selection.moveToBookmark(openingSelection),editor.execCommand("mceInsertContent",!1,content.html),editor.selection.moveToBookmark(openingSelection),pendingPromise.resolve()},getCurrentH5PData=currentH5P=>{const data={};let url;try{url=new URL(currentH5P.textContent)}catch(error){return data}return url.searchParams.has("export")&&(data.download=!0,data.showOptions=!0,url.searchParams.delete("export")),url.searchParams.has("embed")&&(data.embed=!0,data.showOptions=!0,url.searchParams.delete("embed")),url.searchParams.has("copyright")&&(data.copyright=!0,data.showOptions=!0,url.searchParams.delete("copyright")),data.url=url.toString(),data},displayDialogue=async function(editor){let data=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const selection=editor.selection.getNode(),currentH5P=selection.closest(".h5p-placeholder");currentH5P&&Object.assign(data,getCurrentH5PData(currentH5P));const modal=await _modal_factory.default.create({type:_modal.default.TYPE,templateContext:getTemplateContext(editor,data),large:!0});modal.show();const $root=modal.getRoot(),root=$root[0];$root.on(_modal_events.default.save,((event,modal)=>{handleDialogueSubmission(editor,modal,data)})),root.addEventListener("click",(e=>{e.target.closest('[data-target="filepicker"]')&&(0,_utils.displayFilepicker)(editor,"h5p").then((params=>{if(""!==params.url){root.querySelector('form input[name="url"]').value=params.url}return params})).catch()}))}})); diff --git a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map index d38d37740fc..5107fbb676e 100644 --- a/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map +++ b/lib/editor/tiny/plugins/h5p/amd/build/ui.min.js.map @@ -1 +1 @@ -{"version":3,"file":"ui.min.js","sources":["../src/ui.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/commands\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {displayFilepicker} from 'editor_tiny/utils';\nimport {component} from './common';\nimport {getPermissions} from './options';\n\nimport Config from 'core/config';\nimport {getList} from 'core/normalise';\nimport {renderForPromise} from 'core/templates';\nimport Modal from 'tiny_h5p/modal';\nimport ModalEvents from 'core/modal_events';\nimport ModalFactory from 'core/modal_factory';\nimport Pending from 'core/pending';\n\nlet openingSelection = null;\n\nexport const handleAction = (editor) => {\n openingSelection = editor.selection.getBookmark();\n displayDialogue(editor);\n};\n\n/**\n * Get the template context for the dialogue.\n *\n * @param {Editor} editor\n * @param {object} data\n * @returns {object} data\n */\nconst getTemplateContext = (editor, data) => {\n const permissions = getPermissions(editor);\n\n const canUpload = permissions.upload ?? false;\n const canEmbed = permissions.embed ?? false;\n const canUploadAndEmbed = canUpload && canEmbed;\n\n return Object.assign({}, {\n elementid: editor.id,\n canUpload,\n canEmbed,\n canUploadAndEmbed,\n showOptions: false,\n fileURL: data?.url ?? '',\n }, data);\n};\n\n/**\n * Get the URL from the submitted form.\n *\n * @param {FormNode} form\n * @param {string} submittedUrl\n * @param {object} permissions\n * @returns {URL|null}\n */\nconst getUrlFromSubmission = (form, submittedUrl, permissions) => {\n if (!submittedUrl || (!submittedUrl.startsWith(Config.wwwroot) && !isValidUrl(submittedUrl))) {\n return null;\n }\n\n // Generate a URL Object for the submitted URL.\n const url = new URL(submittedUrl);\n\n if (permissions?.upload) {\n if (form.querySelector('[name=\"download\"]').checked) {\n url.searchParams.append('export', 1);\n }\n }\n\n if (permissions?.embed) {\n if (form.querySelector('[name=\"embed\"]').checked) {\n url.searchParams.append('embed', 1);\n }\n }\n if (form.querySelector('[name=\"copyright\"]').checked) {\n url.searchParams.append('copyright', 1);\n }\n\n return url;\n};\n\n/**\n * Verify if this could be a h5p URL.\n *\n * @param {string} url Url to verify\n * @return {boolean} whether this is a valid URL.\n */\nconst isValidUrl = (url) => {\n const pattern = new RegExp('^(https?:\\\\/\\\\/)?' + // Protocol.\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // Domain name.\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address.\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*'); // Port and path.\n return !!pattern.test(url);\n};\n\nconst handleDialogueSubmission = async(editor, modal, data) => {\n const pendingPromise = new Pending('tiny_h5p:handleDialogueSubmission');\n\n const form = getList(modal.getRoot())[0].querySelector('form');\n if (!form) {\n // The form couldn't be found, which is weird.\n // This should not happen.\n // Display the dialogue again.\n modal.destroy();\n displayDialogue(editor, Object.assign({}, data));\n pendingPromise.resolve();\n return;\n }\n\n // Get the URL from the submitted form.\n const submittedUrl = form.querySelector('input[name=\"url\"]').value;\n const url = getUrlFromSubmission(form, submittedUrl, getPermissions(editor));\n\n if (!url) {\n // The URL is invalid.\n // Fill it in and represent the dialogue with an error.\n modal.destroy();\n displayDialogue(editor, Object.assign({}, data, {\n url: submittedUrl,\n invalidUrl: true,\n }));\n pendingPromise.resolve();\n return;\n }\n\n const content = await renderForPromise(`${component}/content`, {\n url: url.toString(),\n });\n\n editor.selection.moveToBookmark(openingSelection);\n editor.execCommand('mceInsertContent', false, content.html);\n editor.selection.moveToBookmark(openingSelection);\n pendingPromise.resolve();\n};\n\nconst getCurrentH5PData = (currentH5P) => {\n const data = {};\n let url;\n try {\n url = new URL(currentH5P.textContent);\n } catch (error) {\n return data;\n }\n\n if (url.searchParams.has('export')) {\n data.download = true;\n data.showOptions = true;\n url.searchParams.delete('export');\n }\n\n if (url.searchParams.has('embed')) {\n data.embed = true;\n data.showOptions = true;\n url.searchParams.delete('embed');\n }\n\n if (url.searchParams.has('copyright')) {\n data.copyright = true;\n data.showOptions = true;\n url.searchParams.delete('copyright');\n }\n\n data.url = url.toString();\n\n return data;\n};\n\nconst displayDialogue = async(editor, data = {}) => {\n const selection = editor.selection.getNode();\n const currentH5P = selection.closest('.h5p-placeholder');\n if (currentH5P) {\n Object.assign(data, getCurrentH5PData(currentH5P));\n }\n\n const modal = await ModalFactory.create({\n type: Modal.TYPE,\n templateContext: getTemplateContext(editor, data),\n large: true,\n });\n modal.show();\n\n const $root = modal.getRoot();\n const root = $root[0];\n $root.on(ModalEvents.save, (event, modal) => {\n handleDialogueSubmission(editor, modal, data);\n });\n\n root.addEventListener('click', (e) => {\n const filepickerButton = e.target.closest('[data-target=\"filepicker\"]');\n if (filepickerButton) {\n displayFilepicker(editor, 'h5p').then((params) => {\n if (params.url !== '') {\n const input = root.querySelector('form input[name=\"url\"]');\n input.value = params.url;\n }\n return params;\n })\n .catch();\n }\n });\n};\n"],"names":["openingSelection","editor","selection","getBookmark","displayDialogue","getTemplateContext","data","permissions","canUpload","upload","canEmbed","embed","canUploadAndEmbed","Object","assign","elementid","id","showOptions","fileURL","url","isValidUrl","RegExp","test","handleDialogueSubmission","async","modal","pendingPromise","Pending","form","getRoot","querySelector","destroy","resolve","submittedUrl","value","startsWith","Config","wwwroot","URL","checked","searchParams","append","getUrlFromSubmission","invalidUrl","content","component","toString","moveToBookmark","execCommand","html","getCurrentH5PData","currentH5P","textContent","error","has","download","delete","copyright","getNode","closest","ModalFactory","create","type","Modal","TYPE","templateContext","large","show","$root","root","on","ModalEvents","save","event","addEventListener","e","target","then","params","catch"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"ui.min.js","sources":["../src/ui.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 * Tiny H5P Content configuration.\n *\n * @module tiny_h5p/ui\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {displayFilepicker} from 'editor_tiny/utils';\nimport {component} from './common';\nimport {getPermissions} from './options';\n\nimport Config from 'core/config';\nimport {getList} from 'core/normalise';\nimport {renderForPromise} from 'core/templates';\nimport Modal from 'tiny_h5p/modal';\nimport ModalEvents from 'core/modal_events';\nimport ModalFactory from 'core/modal_factory';\nimport Pending from 'core/pending';\n\nlet openingSelection = null;\n\nexport const handleAction = (editor) => {\n openingSelection = editor.selection.getBookmark();\n displayDialogue(editor);\n};\n\n/**\n * Get the template context for the dialogue.\n *\n * @param {Editor} editor\n * @param {object} data\n * @returns {object} data\n */\nconst getTemplateContext = (editor, data) => {\n const permissions = getPermissions(editor);\n\n const canUpload = permissions.upload ?? false;\n const canEmbed = permissions.embed ?? false;\n const canUploadAndEmbed = canUpload && canEmbed;\n\n return Object.assign({}, {\n elementid: editor.id,\n canUpload,\n canEmbed,\n canUploadAndEmbed,\n showOptions: false,\n fileURL: data?.url ?? '',\n }, data);\n};\n\n/**\n * Get the URL from the submitted form.\n *\n * @param {FormNode} form\n * @param {string} submittedUrl\n * @param {object} permissions\n * @returns {URL|null}\n */\nconst getUrlFromSubmission = (form, submittedUrl, permissions) => {\n if (!submittedUrl || (!submittedUrl.startsWith(Config.wwwroot) && !isValidUrl(submittedUrl))) {\n return null;\n }\n\n // Generate a URL Object for the submitted URL.\n const url = new URL(submittedUrl);\n\n if (permissions?.upload) {\n if (form.querySelector('[name=\"download\"]').checked) {\n url.searchParams.append('export', 1);\n }\n }\n\n if (permissions?.embed) {\n if (form.querySelector('[name=\"embed\"]').checked) {\n url.searchParams.append('embed', 1);\n }\n }\n if (form.querySelector('[name=\"copyright\"]').checked) {\n url.searchParams.append('copyright', 1);\n }\n\n return url;\n};\n\n/**\n * Verify if this could be a h5p URL.\n *\n * @param {string} url Url to verify\n * @return {boolean} whether this is a valid URL.\n */\nconst isValidUrl = (url) => {\n const pattern = new RegExp('^(https?:\\\\/\\\\/)?' + // Protocol.\n '((([a-z\\\\d]([a-z\\\\d-]*[a-z\\\\d])*)\\\\.)+[a-z]{2,}|' + // Domain name.\n '((\\\\d{1,3}\\\\.){3}\\\\d{1,3}))' + // OR ip (v4) address.\n '(\\\\:\\\\d+)?(\\\\/[-a-z\\\\d%_.~+]*)*'); // Port and path.\n return !!pattern.test(url);\n};\n\nconst handleDialogueSubmission = async(editor, modal, data) => {\n const pendingPromise = new Pending('tiny_h5p:handleDialogueSubmission');\n\n const form = getList(modal.getRoot())[0].querySelector('form');\n if (!form) {\n // The form couldn't be found, which is weird.\n // This should not happen.\n // Display the dialogue again.\n modal.destroy();\n displayDialogue(editor, Object.assign({}, data));\n pendingPromise.resolve();\n return;\n }\n\n // Get the URL from the submitted form.\n const submittedUrl = form.querySelector('input[name=\"url\"]').value;\n const url = getUrlFromSubmission(form, submittedUrl, getPermissions(editor));\n\n if (!url) {\n // The URL is invalid.\n // Fill it in and represent the dialogue with an error.\n modal.destroy();\n displayDialogue(editor, Object.assign({}, data, {\n url: submittedUrl,\n invalidUrl: true,\n }));\n pendingPromise.resolve();\n return;\n }\n\n const content = await renderForPromise(`${component}/content`, {\n url: url.toString(),\n });\n\n editor.selection.moveToBookmark(openingSelection);\n editor.execCommand('mceInsertContent', false, content.html);\n editor.selection.moveToBookmark(openingSelection);\n pendingPromise.resolve();\n};\n\nconst getCurrentH5PData = (currentH5P) => {\n const data = {};\n let url;\n try {\n url = new URL(currentH5P.textContent);\n } catch (error) {\n return data;\n }\n\n if (url.searchParams.has('export')) {\n data.download = true;\n data.showOptions = true;\n url.searchParams.delete('export');\n }\n\n if (url.searchParams.has('embed')) {\n data.embed = true;\n data.showOptions = true;\n url.searchParams.delete('embed');\n }\n\n if (url.searchParams.has('copyright')) {\n data.copyright = true;\n data.showOptions = true;\n url.searchParams.delete('copyright');\n }\n\n data.url = url.toString();\n\n return data;\n};\n\nconst displayDialogue = async(editor, data = {}) => {\n const selection = editor.selection.getNode();\n const currentH5P = selection.closest('.h5p-placeholder');\n if (currentH5P) {\n Object.assign(data, getCurrentH5PData(currentH5P));\n }\n\n const modal = await ModalFactory.create({\n type: Modal.TYPE,\n templateContext: getTemplateContext(editor, data),\n large: true,\n });\n modal.show();\n\n const $root = modal.getRoot();\n const root = $root[0];\n $root.on(ModalEvents.save, (event, modal) => {\n handleDialogueSubmission(editor, modal, data);\n });\n\n root.addEventListener('click', (e) => {\n const filepickerButton = e.target.closest('[data-target=\"filepicker\"]');\n if (filepickerButton) {\n displayFilepicker(editor, 'h5p').then((params) => {\n if (params.url !== '') {\n const input = root.querySelector('form input[name=\"url\"]');\n input.value = params.url;\n }\n return params;\n })\n .catch();\n }\n });\n};\n"],"names":["openingSelection","editor","selection","getBookmark","displayDialogue","getTemplateContext","data","permissions","canUpload","upload","canEmbed","embed","canUploadAndEmbed","Object","assign","elementid","id","showOptions","fileURL","url","isValidUrl","RegExp","test","handleDialogueSubmission","async","modal","pendingPromise","Pending","form","getRoot","querySelector","destroy","resolve","submittedUrl","value","startsWith","Config","wwwroot","URL","checked","searchParams","append","getUrlFromSubmission","invalidUrl","content","component","toString","moveToBookmark","execCommand","html","getCurrentH5PData","currentH5P","textContent","error","has","download","delete","copyright","getNode","closest","ModalFactory","create","type","Modal","TYPE","templateContext","large","show","$root","root","on","ModalEvents","save","event","addEventListener","e","target","then","params","catch"],"mappings":"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"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/h5p/amd/src/ui.js b/lib/editor/tiny/plugins/h5p/amd/src/ui.js index c34e7751167..2727af81236 100644 --- a/lib/editor/tiny/plugins/h5p/amd/src/ui.js +++ b/lib/editor/tiny/plugins/h5p/amd/src/ui.js @@ -16,7 +16,7 @@ /** * Tiny H5P Content configuration. * - * @module tiny_h5p/commands + * @module tiny_h5p/ui * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/media/amd/build/embedmodal.min.js.map b/lib/editor/tiny/plugins/media/amd/build/embedmodal.min.js.map index 6e4dba1909a..0c178b7a2ed 100644 --- a/lib/editor/tiny/plugins/media/amd/build/embedmodal.min.js.map +++ b/lib/editor/tiny/plugins/media/amd/build/embedmodal.min.js.map @@ -1 +1 @@ -{"version":3,"file":"embedmodal.min.js","sources":["../src/embedmodal.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 * Embedded Media Management Modal for Tiny.\n *\n * @module tiny_media/modal\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from './common';\n\nconst EmbedModal = class extends Modal {\n static TYPE = `${component}/modal`;\n\n static TEMPLATE = `${component}/embed_media_modal`;\n\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on save/cancel.\n this.registerCloseOnSave();\n this.registerCloseOnCancel();\n }\n};\n\nModalRegistry.register(EmbedModal.TYPE, EmbedModal, EmbedModal.TEMPLATE);\n\nexport default EmbedModal;\n"],"names":["EmbedModal","Modal","registerEventListeners","registerCloseOnSave","registerCloseOnCancel","component","register","TYPE","TEMPLATE"],"mappings":"ikBA2BMA,mCAAa,cAAcC,eAK7BC,+BAEUA,8BAGDC,2BACAC,2CAVQC,yEAEIA,yEAYXC,SAASN,WAAWO,KAAMP,WAAYA,WAAWQ,uBAEhDR"} \ No newline at end of file +{"version":3,"file":"embedmodal.min.js","sources":["../src/embedmodal.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 * Embedded Media Management Modal for Tiny.\n *\n * @module tiny_media/embedmodal\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from './common';\n\nconst EmbedModal = class extends Modal {\n static TYPE = `${component}/modal`;\n\n static TEMPLATE = `${component}/embed_media_modal`;\n\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on save/cancel.\n this.registerCloseOnSave();\n this.registerCloseOnCancel();\n }\n};\n\nModalRegistry.register(EmbedModal.TYPE, EmbedModal, EmbedModal.TEMPLATE);\n\nexport default EmbedModal;\n"],"names":["EmbedModal","Modal","registerEventListeners","registerCloseOnSave","registerCloseOnCancel","component","register","TYPE","TEMPLATE"],"mappings":"ikBA2BMA,mCAAa,cAAcC,eAK7BC,+BAEUA,8BAGDC,2BACAC,2CAVQC,yEAEIA,yEAYXC,SAASN,WAAWO,KAAMP,WAAYA,WAAWQ,uBAEhDR"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/media/amd/src/embedmodal.js b/lib/editor/tiny/plugins/media/amd/src/embedmodal.js index 431d4ad334d..eac32bd4bb2 100644 --- a/lib/editor/tiny/plugins/media/amd/src/embedmodal.js +++ b/lib/editor/tiny/plugins/media/amd/src/embedmodal.js @@ -16,7 +16,7 @@ /** * Embedded Media Management Modal for Tiny. * - * @module tiny_media/modal + * @module tiny_media/embedmodal * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/audio_recorder.min.js.map b/lib/editor/tiny/plugins/recordrtc/amd/build/audio_recorder.min.js.map index 3d5b29e413b..a3474ec0f1a 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/audio_recorder.min.js.map +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/audio_recorder.min.js.map @@ -1 +1 @@ -{"version":3,"file":"audio_recorder.min.js","sources":["../src/audio_recorder.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 * Tiny Record RTC - audio recorder configuration.\n *\n * @module tiny_recordrtc/audio\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BaseClass from './base_recorder';\nimport Modal from './modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from 'tiny_recordrtc/common';\n\nexport default class Audio extends BaseClass {\n configurePlayer() {\n return this.modalRoot.querySelector('audio');\n }\n\n getSupportedTypes() {\n return [\n 'audio/webm;codecs=opus',\n 'audio/ogg;codecs=opus',\n ];\n }\n\n getParsedRecordingOptions() {\n return {\n audioBitsPerSecond: parseInt(this.config.audiobitrate),\n };\n }\n\n getMediaConstraints() {\n return {\n audio: true,\n };\n }\n\n getRecordingType() {\n return 'audio';\n }\n\n getTimeLimit() {\n return this.config.audiotimelimit;\n }\n\n getEmbedTemplateName() {\n return 'tiny_recordrtc/embed_audio';\n }\n\n getFileName(prefix) {\n return `${prefix}-audio.ogg`;\n }\n\n static getModalClass() {\n const modalType = `${component}/audio_recorder`;\n const registration = ModalRegistry.get(modalType);\n if (registration) {\n return registration.module;\n }\n\n const AudioModal = class extends Modal {\n static TYPE = modalType;\n static TEMPLATE = `${component}/audio_recorder`;\n };\n\n ModalRegistry.register(AudioModal.TYPE, AudioModal, AudioModal.TEMPLATE);\n return AudioModal;\n }\n}\n"],"names":["Audio","BaseClass","configurePlayer","this","modalRoot","querySelector","getSupportedTypes","getParsedRecordingOptions","audioBitsPerSecond","parseInt","config","audiobitrate","getMediaConstraints","audio","getRecordingType","getTimeLimit","audiotimelimit","getEmbedTemplateName","getFileName","prefix","modalType","component","registration","ModalRegistry","get","module","AudioModal","Modal","register","TYPE","TEMPLATE"],"mappings":"+pBA4BqBA,cAAcC,uBAC/BC,yBACWC,KAAKC,UAAUC,cAAc,SAGxCC,0BACW,CACH,yBACA,yBAIRC,kCACW,CACHC,mBAAoBC,SAASN,KAAKO,OAAOC,eAIjDC,4BACW,CACHC,OAAO,GAIfC,yBACW,QAGXC,sBACWZ,KAAKO,OAAOM,eAGvBC,6BACW,6BAGXC,YAAYC,wBACEA,6DAIJC,oBAAeC,qCACfC,aAAeC,wBAAcC,IAAIJ,cACnCE,oBACOA,aAAaG,aAGlBC,mCAAa,cAAcC,wBACfP,uDACOC,6EAGXO,SAASF,WAAWG,KAAMH,WAAYA,WAAWI,UACxDJ"} \ No newline at end of file +{"version":3,"file":"audio_recorder.min.js","sources":["../src/audio_recorder.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 * Tiny Record RTC - audio recorder configuration.\n *\n * @module tiny_recordrtc/audio_recorder\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BaseClass from './base_recorder';\nimport Modal from './modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from 'tiny_recordrtc/common';\n\nexport default class Audio extends BaseClass {\n configurePlayer() {\n return this.modalRoot.querySelector('audio');\n }\n\n getSupportedTypes() {\n return [\n 'audio/webm;codecs=opus',\n 'audio/ogg;codecs=opus',\n ];\n }\n\n getParsedRecordingOptions() {\n return {\n audioBitsPerSecond: parseInt(this.config.audiobitrate),\n };\n }\n\n getMediaConstraints() {\n return {\n audio: true,\n };\n }\n\n getRecordingType() {\n return 'audio';\n }\n\n getTimeLimit() {\n return this.config.audiotimelimit;\n }\n\n getEmbedTemplateName() {\n return 'tiny_recordrtc/embed_audio';\n }\n\n getFileName(prefix) {\n return `${prefix}-audio.ogg`;\n }\n\n static getModalClass() {\n const modalType = `${component}/audio_recorder`;\n const registration = ModalRegistry.get(modalType);\n if (registration) {\n return registration.module;\n }\n\n const AudioModal = class extends Modal {\n static TYPE = modalType;\n static TEMPLATE = `${component}/audio_recorder`;\n };\n\n ModalRegistry.register(AudioModal.TYPE, AudioModal, AudioModal.TEMPLATE);\n return AudioModal;\n }\n}\n"],"names":["Audio","BaseClass","configurePlayer","this","modalRoot","querySelector","getSupportedTypes","getParsedRecordingOptions","audioBitsPerSecond","parseInt","config","audiobitrate","getMediaConstraints","audio","getRecordingType","getTimeLimit","audiotimelimit","getEmbedTemplateName","getFileName","prefix","modalType","component","registration","ModalRegistry","get","module","AudioModal","Modal","register","TYPE","TEMPLATE"],"mappings":"+pBA4BqBA,cAAcC,uBAC/BC,yBACWC,KAAKC,UAAUC,cAAc,SAGxCC,0BACW,CACH,yBACA,yBAIRC,kCACW,CACHC,mBAAoBC,SAASN,KAAKO,OAAOC,eAIjDC,4BACW,CACHC,OAAO,GAIfC,yBACW,QAGXC,sBACWZ,KAAKO,OAAOM,eAGvBC,6BACW,6BAGXC,YAAYC,wBACEA,6DAIJC,oBAAeC,qCACfC,aAAeC,wBAAcC,IAAIJ,cACnCE,oBACOA,aAAaG,aAGlBC,mCAAa,cAAcC,wBACfP,uDACOC,6EAGXO,SAASF,WAAWG,KAAMH,WAAYA,WAAWI,UACxDJ"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/base_recorder.min.js.map b/lib/editor/tiny/plugins/recordrtc/amd/build/base_recorder.min.js.map index 82dfe5618d5..7c5df51ffc0 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/base_recorder.min.js.map +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/base_recorder.min.js.map @@ -1 +1 @@ -{"version":3,"file":"base_recorder.min.js","sources":["../src/base_recorder.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/**\n * Tiny Record RTC type.\n *\n * @module tiny_recordrtc/recording/base\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString, get_strings as getStrings} from 'core/str';\nimport {component} from './common';\nimport Pending from 'core/pending';\nimport {getData} from './options';\nimport uploadFile from 'editor_tiny/uploader';\nimport {add as addToast} from 'core/toast';\nimport * as ModalEvents from 'core/modal_events';\nimport * as ModalFactory from 'core/modal_factory';\nimport * as Templates from 'core/templates';\nimport {saveCancelPromise} from 'core/notification';\nimport {prefetchStrings, prefetchTemplates} from 'core/prefetch';\n\n/**\n * The RecordRTC base class for audio, video, and any other future types\n */\nexport default class {\n\n stopRequested = false;\n\n /**\n * Constructor for the RecordRTC class\n *\n * @param {TinyMCE} editor The Editor to which the content will be inserted\n * @param {Modal} modal The Moodle Modal that contains the interface used for recording\n */\n constructor(editor, modal) {\n this.ready = false;\n\n if (!this.checkAndWarnAboutBrowserCompatibility()) {\n return;\n }\n\n this.editor = editor;\n this.config = getData(editor).params;\n this.modal = modal;\n this.modalRoot = modal.getRoot()[0];\n this.startStopButton = this.modalRoot.querySelector('button[data-action=\"startstop\"]');\n this.uploadButton = this.modalRoot.querySelector('button[data-action=\"upload\"]');\n\n // Disable the record button untilt he stream is acquired.\n this.setRecordButtonState(false);\n\n this.player = this.configurePlayer();\n this.registerEventListeners();\n this.ready = true;\n\n this.captureUserMedia();\n this.prefetchContent();\n }\n\n /**\n * Check whether the browser is compatible.\n *\n * @returns {boolean}\n */\n isReady() {\n return this.ready;\n }\n\n // Disable eslint's valid-jsdoc rule as the following methods are abstract and mnust be overridden by the child class.\n\n /* eslint-disable valid-jsdoc, no-unused-vars */\n\n /**\n * Get the Player element for this type.\n *\n * @returns {HTMLElement} The player element, typically an audio or video tag.\n */\n configurePlayer() {\n throw new Error(`configurePlayer() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get the list of supported mimetypes for this recorder.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/isTypeSupported}\n *\n * @returns {string[]} The list of supported mimetypes.\n */\n getSupportedTypes() {\n throw new Error(`getSupportedTypes() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get any recording options passed into the MediaRecorder.\n * Please note that the mimeType will be fetched from {@link getSupportedTypes()}.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder#options}\n * @returns {Object}\n */\n getRecordingOptions() {\n throw new Error(`getRecordingOptions() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get a filename for the generated file.\n *\n * Typically this function will take a prefix and add a type-specific suffix such as the extension to it.\n *\n * @param {string} prefix The prefix for the filename generated by the recorder.\n * @returns {string}\n */\n getFileName(prefix) {\n throw new Error(`getFileName() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get a list of constraints as required by the getUserMedia() function.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#constraints}\n *\n * @returns {Object}\n */\n getMediaConstraints() {\n throw new Error(`getMediaConstraints() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Whether to start playing the recording as it is captured.\n * @returns {boolean} Whether to start playing the recording as it is captured.\n */\n playOnCapture() {\n return false;\n }\n\n /**\n * Get the time limit for this recording type.\n *\n * @returns {number} The time limit in seconds.\n */\n getTimeLimit() {\n throw new Error(`getTimeLimit() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get the name of the template used when embedding the URL in the editor content.\n *\n * @returns {string}\n */\n getEmbedTemplateName() {\n throw new Error(`getEmbedTemplateName() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Fetch the Class of the Modal to be displayed.\n *\n * @returns {Modal}\n */\n static getModalClass() {\n throw new Error(`getModalClass() must be implemented in ${this.constructor.name}`);\n }\n\n /* eslint-enable valid-jsdoc, no-unused-vars */\n\n /**\n * Get the options for the MediaRecorder.\n *\n * @returns {object} The options for the MediaRecorder instance.\n */\n getParsedRecordingOptions() {\n const types = this.getSupportedTypes();\n const options = this.getParsedRecordingOptions();\n const compatTypes = types.filter((type) => window.MediaRecorder.isTypeSupported(type));\n\n if (compatTypes.length !== 0) {\n options.mimeType = compatTypes[0];\n }\n\n return options;\n }\n\n /**\n * Start capturing the User Media and handle success or failure of the capture.\n */\n async captureUserMedia() {\n try {\n const stream = await navigator.mediaDevices.getUserMedia(this.getMediaConstraints());\n this.handleCaptureSuccess(stream);\n } catch (error) {\n this.handleCaptureFailure(error);\n }\n }\n\n /**\n * Prefetch some of the content that will be used in the UI.\n *\n * Note: not all of the strings used are pre-fetched.\n * Some of the strings will be fetched because their template is used.\n */\n prefetchContent() {\n prefetchStrings(component, [\n 'uploading',\n 'recordagain_title',\n 'recordagain_desc',\n 'discard_title',\n 'discard_desc',\n 'confirm_yes',\n 'recordinguploaded',\n 'maxfilesizehit',\n 'maxfilesizehit_title',\n 'uploadfailed',\n ]);\n\n prefetchTemplates([\n this.getEmbedTemplateName(),\n 'tiny_recordrtc/timeremaining',\n ]);\n }\n\n /**\n * Display an error message to the user.\n *\n * @param {Promise} title The error title\n * @param {Promise} content The error message\n * @returns {Promise}\n */\n async displayAlert(title, content) {\n const pendingPromise = new Pending('core/confirm:alert');\n const ModalFactory = await import('core/modal_factory');\n const modal = await ModalFactory.create({\n type: ModalFactory.types.ALERT,\n title: title,\n body: content,\n removeOnClose: true,\n });\n\n modal.show();\n pendingPromise.resolve();\n\n return modal;\n }\n\n /**\n * Handle successful capture of the User Media.\n *\n * @param {MediaStream} stream The stream as captured by the User Media.\n */\n handleCaptureSuccess(stream) {\n // Set audio player source to microphone stream.\n this.player.srcObject = stream;\n\n if (this.playOnCapture()) {\n // Mute audio, distracting while recording.\n this.player.muted = true;\n\n this.player.play();\n }\n\n this.stream = stream;\n this.setupPlayerSource();\n this.setRecordButtonState(true);\n }\n\n /**\n * Setup the player to use the stream as a source.\n */\n setupPlayerSource() {\n if (!this.player.srcObject) {\n this.player.srcObject = this.stream;\n\n // Mute audio, distracting while recording.\n this.player.muted = true;\n\n this.player.play();\n }\n }\n\n /**\n * Enable the record button.\n *\n * @param {boolean|null} enabled Set the button state\n */\n setRecordButtonState(enabled) {\n this.startStopButton.disabled = !enabled;\n }\n\n /**\n * Configure button visibility for the record button.\n *\n * @param {boolean} visible Set the visibility of the button.\n */\n setRecordButtonVisibility(visible) {\n const container = this.getButtonContainer('start-stop');\n container.classList.toggle('hide', !visible);\n }\n\n /**\n * Enable the upload button.\n *\n * @param {boolean|null} enabled Set the button state\n */\n setUploadButtonState(enabled) {\n this.uploadButton.disabled = !enabled;\n }\n\n /**\n * Configure button visibility for the upload button.\n *\n * @param {boolean} visible Set the visibility of the button.\n */\n setUploadButtonVisibility(visible) {\n const container = this.getButtonContainer('upload');\n container.classList.toggle('hide', !visible);\n }\n /**\n * Handle failure to capture the User Media.\n *\n * @param {Error} error\n */\n handleCaptureFailure(error) {\n // Changes 'CertainError' -> 'gumcertain' to match language string names.\n var subject = `gum${error.name.replace('Error', '').toLowerCase()}`;\n this.displayAlert(\n getString(`${subject}_title`, component),\n getString(subject, component)\n );\n }\n\n /**\n * Close the modal and stop recording.\n */\n close() {\n // Closing the modal will destroy it and remove it from the DOM.\n // It will also stop the recording via the hidden Modal Event.\n this.modal.hide();\n }\n\n /**\n * Register event listeners for the modal.\n */\n registerEventListeners() {\n this.modalRoot.addEventListener('click', this.handleModalClick.bind(this));\n this.modal.getRoot().on(ModalEvents.outsideClick, this.outsideClickHandler.bind(this));\n this.modal.getRoot().on(ModalEvents.hidden, () => {\n this.cleanupStream();\n this.requestRecordingStop();\n });\n }\n\n /**\n * Prevent the Modal from closing when recording is on process.\n *\n * @param {MouseEvent} event The click event\n */\n async outsideClickHandler(event) {\n if (this.isRecording()) {\n // The user is recording.\n // Do not distract with a confirmation, just prevent closing.\n event.preventDefault();\n } else if (this.hasData()) {\n // If there is a blobsize then there is data that may be lost.\n // Ask the user to confirm they want to close the modal.\n // We prevent default here, and then close the modal if they confirm.\n event.preventDefault();\n\n try {\n await saveCancelPromise(\n await getString(\"discard_title\", component),\n await getString(\"discard_desc\", component),\n await getString(\"confirm_yes\", component),\n );\n this.modal.hide();\n } catch (error) {\n // Do nothing, the modal will not close.\n }\n }\n }\n\n /**\n * Handle a click within the Modal.\n *\n * @param {MouseEvent} event The click event\n */\n handleModalClick(event) {\n const button = event.target.closest('button');\n if (button && button.dataset.action) {\n const action = button.dataset.action;\n if (action === 'startstop') {\n this.handleRecordingStartStopRequested();\n }\n\n if (action === 'upload') {\n this.uploadRecording();\n }\n }\n }\n\n /**\n * Handle the click event for the recording start/stop button.\n */\n handleRecordingStartStopRequested() {\n if (this.mediaRecorder?.state === 'recording') {\n this.requestRecordingStop();\n } else {\n this.startRecording();\n }\n }\n\n /**\n * Handle the media stream after it has finished.\n */\n async onMediaStopped() {\n // Set source of audio player.\n this.blob = new Blob(this.data.chunks, {\n type: this.mediaRecorder.mimeType\n });\n this.player.srcObject = null;\n this.player.src = URL.createObjectURL(this.blob);\n\n // Change the label to \"Record again\".\n this.setRecordButtonTextFromString('recordagain');\n\n // Show audio player with controls enabled, and unmute.\n this.player.muted = false;\n this.player.controls = true;\n this.getButtonContainer('player')?.classList.toggle('hide', false);\n\n // Show upload button.\n this.setUploadButtonVisibility(true);\n this.setUploadButtonState(true);\n }\n\n /**\n * Upload the recording and insert it into the editor content.\n */\n async uploadRecording() {\n // Trigger error if no recording has been made.\n if (this.data.chunks.length === 0) {\n this.displayAlert('norecordingfound');\n return;\n }\n\n const fileName = this.getFileName((Math.random() * 1000).toString().replace('.', ''));\n\n // Upload recording to server.\n try {\n // Once uploading starts, do not allow any further changes to the recording.\n this.setRecordButtonVisibility(false);\n\n // Disable the upload button.\n this.setUploadButtonState(false);\n\n // Upload the recording.\n const fileURL = await uploadFile(this.editor, 'media', this.blob, fileName, (progress) => {\n this.setUploadButtonTextProgress(progress);\n });\n this.insertMedia(fileURL);\n this.close();\n addToast(await getString('recordinguploaded', component));\n } catch (error) {\n // Show a toast and unhide the button.\n this.setUploadButtonState(true);\n\n addToast(await getString('uploadfailed', component, {error}), {\n type: 'error',\n });\n\n }\n }\n\n /**\n * Helper to get the container that a button is in.\n *\n * @param {string} purpose The button purpose\n * @returns {HTMLElement}\n */\n getButtonContainer(purpose) {\n return this.modalRoot.querySelector(`[data-purpose=\"${purpose}-container\"]`);\n }\n\n /**\n * Check whether the browser is compatible with capturing media.\n *\n * @returns {boolean}\n */\n static isBrowserCompatible() {\n return this.checkSecure() && this.hasUserMedia();\n }\n\n static async display(editor) {\n const ModalClass = this.getModalClass();\n const modal = await ModalFactory.create({\n type: ModalClass.TYPE,\n templateContext: {},\n large: true,\n });\n\n // Set up the VideoRecorder.\n const recorder = new this(editor, modal);\n if (recorder.isReady()) {\n modal.show();\n }\n return modal;\n }\n\n /**\n * Check whether the browser is compatible with capturing media, and display a warning if not.\n *\n * @returns {boolean}\n */\n checkAndWarnAboutBrowserCompatibility() {\n if (!this.constructor.checkSecure()) {\n getStrings(['insecurealert_title', 'insecurealert'].map((key) => ({key, component})))\n .then(([title, message]) => addToast(message, {title, type: 'error'}))\n .catch();\n return false;\n }\n\n if (!this.constructor.hasUserMedia) {\n getStrings(['nowebrtc_title', 'nowebrtc'].map((key) => ({key, component})))\n .then(([title, message]) => addToast(message, {title, type: 'error'}))\n .catch();\n return false;\n }\n\n return true;\n }\n\n /**\n * Check whether the browser supports WebRTC.\n *\n * @returns {boolean}\n */\n static hasUserMedia() {\n return (navigator.mediaDevices && window.MediaRecorder);\n }\n\n /**\n * Check whether the hostname is either hosted over SSL, or from a valid localhost hostname.\n *\n * The UserMedia API can only be used in secure contexts as noted.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#privacy_and_security}\n *\n * @returns {boolean} Whether the plugin can be loaded.\n */\n static checkSecure() {\n // Note: We can now use window.isSecureContext.\n // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection\n // https://developer.mozilla.org/en-US/docs/Web/API/isSecureContext\n return window.isSecureContext;\n }\n\n /**\n * Update the content of the stop recording button timer.\n */\n async setStopRecordingButton() {\n const {html, js} = await Templates.renderForPromise('tiny_recordrtc/timeremaining', this.getTimeRemaining());\n Templates.replaceNodeContents(this.startStopButton, html, js);\n this.buttonTimer = setInterval(this.updateRecordButtonTime.bind(this), 500);\n }\n\n /**\n * Update the time on the stop recording button.\n */\n updateRecordButtonTime() {\n const {remaining, minutes, seconds} = this.getTimeRemaining();\n if (remaining < 0) {\n this.requestRecordingStop();\n } else {\n this.startStopButton.querySelector('[data-type=\"minutes\"]').textContent = minutes;\n this.startStopButton.querySelector('[data-type=\"seconds\"]').textContent = seconds;\n }\n }\n\n /**\n * Set the text of the record button using a language string.\n *\n * @param {string} string The string identifier\n */\n async setRecordButtonTextFromString(string) {\n this.startStopButton.textContent = await getString(string, component);\n }\n\n /**\n * Set the upload button text progress.\n *\n * @param {number} progress The progress\n */\n async setUploadButtonTextProgress(progress) {\n this.uploadButton.textContent = await getString('uploading', component, {\n progress: Math.round(progress * 100) / 100,\n });\n }\n\n async resetUploadButtonText() {\n this.uploadButton.textContent = await getString('upload', component);\n }\n\n /**\n * Clear the timer for the stop recording button.\n */\n clearButtonTimer() {\n if (this.buttonTimer) {\n clearInterval(this.buttonTimer);\n }\n this.buttonTimer = null;\n }\n\n /**\n * Get the time remaining for the recording.\n *\n * @returns {Object} The minutes and seconds remaining.\n */\n getTimeRemaining() {\n // All times are in milliseconds\n const now = new Date().getTime();\n const remaining = Math.floor(this.getTimeLimit() - ((now - this.startTime) / 1000));\n\n const formatter = new Intl.NumberFormat(navigator.language, {minimumIntegerDigits: 2});\n const seconds = formatter.format(remaining % 60);\n const minutes = formatter.format(Math.floor((remaining - seconds) / 60));\n return {\n remaining,\n minutes,\n seconds,\n };\n }\n\n /**\n * Get the maximum file size that can be uploaded.\n *\n * @returns {number} The max byte size\n */\n getMaxUploadSize() {\n return this.config.maxrecsize;\n }\n\n /**\n * Stop the recording.\n * Please note that this should only stop the recording.\n * Anything related to processing the recording should be handled by the\n * mediaRecorder's stopped event handler which is processed after it has stopped.\n */\n requestRecordingStop() {\n if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {\n this.stopRequested = true;\n } else {\n // There is no recording to stop, but the stream must still be cleaned up.\n this.cleanupStream();\n }\n }\n\n stopRecorder() {\n this.mediaRecorder.stop();\n\n // Unmute the player so that the audio is heard during playback.\n this.player.muted = false;\n }\n\n /**\n * Clean up the stream.\n *\n * This involves stopping any track which is still active.\n */\n cleanupStream() {\n if (this.stream) {\n this.stream.getTracks()\n .filter((track) => track.readyState !== 'ended')\n .forEach((track) => track.stop());\n }\n }\n\n /**\n * Handle the mediaRecorder `stop` event.\n */\n handleStopped() {\n // Handle the stream data.\n this.onMediaStopped();\n\n // Clear the button timer.\n this.clearButtonTimer();\n }\n\n /**\n * Handle the mediaRecorder `start` event.\n *\n * This event is called when the recording starts.\n */\n handleStarted() {\n this.startTime = new Date().getTime();\n this.setStopRecordingButton();\n }\n\n /**\n * Handle the mediaRecorder `dataavailable` event.\n *\n * @param {Event} event\n */\n handleDataAvailable(event) {\n if (this.isRecording()) {\n const newSize = this.data.blobSize + event.data.size;\n // Recording stops when either the maximum upload size is reached, or the time limit expires.\n // The time limit is checked in the `updateButtonTime` function.\n if (newSize >= this.getMaxUploadSize()) {\n this.stopRecorder();\n this.displayFileLimitHitMessage();\n } else {\n // Push recording slice to array.\n this.data.chunks.push(event.data);\n\n // Size of all recorded data so far.\n this.data.blobSize = newSize;\n\n if (this.stopRequested) {\n this.stopRecorder();\n }\n }\n }\n }\n\n async displayFileLimitHitMessage() {\n addToast(await getString('maxfilesizehit', component), {\n title: await getString('maxfilesizehit_title', component),\n type: 'error',\n });\n }\n\n /**\n * Check whether the recording is in progress.\n *\n * @returns {boolean}\n */\n isRecording() {\n return this.mediaRecorder?.state === 'recording';\n }\n\n /**\n * Whether any data has been recorded.\n *\n * @returns {boolean}\n */\n hasData() {\n return !!this.data?.blobSize;\n }\n\n /**\n * Start the recording\n */\n async startRecording() {\n if (this.mediaRecorder) {\n // Stop the existing recorder if it exists.\n if (this.isRecording()) {\n this.mediaRecorder.stop();\n }\n\n if (this.hasData()) {\n const resetRecording = await this.recordAgainConfirmation();\n if (!resetRecording) {\n // User cancelled at the confirmation to reset the data, so exit early.\n return;\n }\n this.setUploadButtonVisibility(false);\n }\n\n this.mediaRecorder = null;\n }\n\n // The options for the recording codecs and bitrates.\n this.mediaRecorder = new MediaRecorder(this.stream, this.getParsedRecordingOptions());\n\n this.mediaRecorder.addEventListener('dataavailable', this.handleDataAvailable.bind(this));\n this.mediaRecorder.addEventListener('stop', this.handleStopped.bind(this));\n this.mediaRecorder.addEventListener('start', this.handleStarted.bind(this));\n\n this.data = {\n chunks: [],\n blobSize: 0\n };\n this.setupPlayerSource();\n this.stopRequested = false;\n\n // Capture in 50ms chunks.\n this.mediaRecorder.start(50);\n }\n\n /**\n * Confirm whether the user wants to reset the existing recoring.\n *\n * @returns {Promise} Whether the user confirmed the reset.\n */\n async recordAgainConfirmation() {\n try {\n await saveCancelPromise(\n await getString(\"recordagain_title\", component),\n await getString(\"recordagain_desc\", component),\n await getString(\"confirm_yes\", component)\n );\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Insert the HTML to embed the recording into the editor content.\n *\n * @param {string} source The URL to view the media.\n */\n async insertMedia(source) {\n const {html} = await Templates.renderForPromise(\n this.getEmbedTemplateName(),\n this.getEmbedTemplateContext({\n source,\n })\n );\n this.editor.insertContent(html);\n }\n\n /**\n * Add or modify the template parameters for the specified type.\n *\n * @param {Object} templateContext The Tempalte context to use\n * @returns {Object} The finalised template context\n */\n getEmbedTemplateContext(templateContext) {\n return templateContext;\n }\n}\n"],"names":["constructor","editor","modal","ready","this","checkAndWarnAboutBrowserCompatibility","config","params","modalRoot","getRoot","startStopButton","querySelector","uploadButton","setRecordButtonState","player","configurePlayer","registerEventListeners","captureUserMedia","prefetchContent","isReady","Error","name","getSupportedTypes","getRecordingOptions","getFileName","prefix","getMediaConstraints","playOnCapture","getTimeLimit","getEmbedTemplateName","getParsedRecordingOptions","types","options","compatTypes","filter","type","window","MediaRecorder","isTypeSupported","length","mimeType","stream","navigator","mediaDevices","getUserMedia","handleCaptureSuccess","error","handleCaptureFailure","component","title","content","pendingPromise","Pending","ModalFactory","create","ALERT","body","removeOnClose","show","resolve","srcObject","muted","play","setupPlayerSource","enabled","disabled","setRecordButtonVisibility","visible","getButtonContainer","classList","toggle","setUploadButtonState","setUploadButtonVisibility","subject","replace","toLowerCase","displayAlert","close","hide","addEventListener","handleModalClick","bind","on","ModalEvents","outsideClick","outsideClickHandler","hidden","cleanupStream","requestRecordingStop","event","isRecording","preventDefault","hasData","button","target","closest","dataset","action","handleRecordingStartStopRequested","uploadRecording","mediaRecorder","state","startRecording","blob","Blob","data","chunks","src","URL","createObjectURL","setRecordButtonTextFromString","controls","fileName","Math","random","toString","fileURL","progress","setUploadButtonTextProgress","insertMedia","purpose","checkSecure","hasUserMedia","ModalClass","getModalClass","TYPE","templateContext","large","map","key","then","_ref2","message","catch","_ref","isSecureContext","html","js","Templates","renderForPromise","getTimeRemaining","replaceNodeContents","buttonTimer","setInterval","updateRecordButtonTime","remaining","minutes","seconds","textContent","string","round","clearButtonTimer","clearInterval","now","Date","getTime","floor","startTime","formatter","Intl","NumberFormat","language","minimumIntegerDigits","format","getMaxUploadSize","maxrecsize","stopRequested","stopRecorder","stop","getTracks","track","readyState","forEach","handleStopped","onMediaStopped","handleStarted","setStopRecordingButton","handleDataAvailable","newSize","blobSize","size","displayFileLimitHitMessage","push","_this$data","recordAgainConfirmation","start","source","getEmbedTemplateContext","insertContent"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"base_recorder.min.js","sources":["../src/base_recorder.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/**\n * Tiny Record RTC type.\n *\n * @module tiny_recordrtc/base_recorder\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString, get_strings as getStrings} from 'core/str';\nimport {component} from './common';\nimport Pending from 'core/pending';\nimport {getData} from './options';\nimport uploadFile from 'editor_tiny/uploader';\nimport {add as addToast} from 'core/toast';\nimport * as ModalEvents from 'core/modal_events';\nimport * as ModalFactory from 'core/modal_factory';\nimport * as Templates from 'core/templates';\nimport {saveCancelPromise} from 'core/notification';\nimport {prefetchStrings, prefetchTemplates} from 'core/prefetch';\n\n/**\n * The RecordRTC base class for audio, video, and any other future types\n */\nexport default class {\n\n stopRequested = false;\n\n /**\n * Constructor for the RecordRTC class\n *\n * @param {TinyMCE} editor The Editor to which the content will be inserted\n * @param {Modal} modal The Moodle Modal that contains the interface used for recording\n */\n constructor(editor, modal) {\n this.ready = false;\n\n if (!this.checkAndWarnAboutBrowserCompatibility()) {\n return;\n }\n\n this.editor = editor;\n this.config = getData(editor).params;\n this.modal = modal;\n this.modalRoot = modal.getRoot()[0];\n this.startStopButton = this.modalRoot.querySelector('button[data-action=\"startstop\"]');\n this.uploadButton = this.modalRoot.querySelector('button[data-action=\"upload\"]');\n\n // Disable the record button untilt he stream is acquired.\n this.setRecordButtonState(false);\n\n this.player = this.configurePlayer();\n this.registerEventListeners();\n this.ready = true;\n\n this.captureUserMedia();\n this.prefetchContent();\n }\n\n /**\n * Check whether the browser is compatible.\n *\n * @returns {boolean}\n */\n isReady() {\n return this.ready;\n }\n\n // Disable eslint's valid-jsdoc rule as the following methods are abstract and mnust be overridden by the child class.\n\n /* eslint-disable valid-jsdoc, no-unused-vars */\n\n /**\n * Get the Player element for this type.\n *\n * @returns {HTMLElement} The player element, typically an audio or video tag.\n */\n configurePlayer() {\n throw new Error(`configurePlayer() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get the list of supported mimetypes for this recorder.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/isTypeSupported}\n *\n * @returns {string[]} The list of supported mimetypes.\n */\n getSupportedTypes() {\n throw new Error(`getSupportedTypes() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get any recording options passed into the MediaRecorder.\n * Please note that the mimeType will be fetched from {@link getSupportedTypes()}.\n *\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder#options}\n * @returns {Object}\n */\n getRecordingOptions() {\n throw new Error(`getRecordingOptions() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get a filename for the generated file.\n *\n * Typically this function will take a prefix and add a type-specific suffix such as the extension to it.\n *\n * @param {string} prefix The prefix for the filename generated by the recorder.\n * @returns {string}\n */\n getFileName(prefix) {\n throw new Error(`getFileName() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get a list of constraints as required by the getUserMedia() function.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#constraints}\n *\n * @returns {Object}\n */\n getMediaConstraints() {\n throw new Error(`getMediaConstraints() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Whether to start playing the recording as it is captured.\n * @returns {boolean} Whether to start playing the recording as it is captured.\n */\n playOnCapture() {\n return false;\n }\n\n /**\n * Get the time limit for this recording type.\n *\n * @returns {number} The time limit in seconds.\n */\n getTimeLimit() {\n throw new Error(`getTimeLimit() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Get the name of the template used when embedding the URL in the editor content.\n *\n * @returns {string}\n */\n getEmbedTemplateName() {\n throw new Error(`getEmbedTemplateName() must be implemented in ${this.constructor.name}`);\n }\n\n /**\n * Fetch the Class of the Modal to be displayed.\n *\n * @returns {Modal}\n */\n static getModalClass() {\n throw new Error(`getModalClass() must be implemented in ${this.constructor.name}`);\n }\n\n /* eslint-enable valid-jsdoc, no-unused-vars */\n\n /**\n * Get the options for the MediaRecorder.\n *\n * @returns {object} The options for the MediaRecorder instance.\n */\n getParsedRecordingOptions() {\n const types = this.getSupportedTypes();\n const options = this.getParsedRecordingOptions();\n const compatTypes = types.filter((type) => window.MediaRecorder.isTypeSupported(type));\n\n if (compatTypes.length !== 0) {\n options.mimeType = compatTypes[0];\n }\n\n return options;\n }\n\n /**\n * Start capturing the User Media and handle success or failure of the capture.\n */\n async captureUserMedia() {\n try {\n const stream = await navigator.mediaDevices.getUserMedia(this.getMediaConstraints());\n this.handleCaptureSuccess(stream);\n } catch (error) {\n this.handleCaptureFailure(error);\n }\n }\n\n /**\n * Prefetch some of the content that will be used in the UI.\n *\n * Note: not all of the strings used are pre-fetched.\n * Some of the strings will be fetched because their template is used.\n */\n prefetchContent() {\n prefetchStrings(component, [\n 'uploading',\n 'recordagain_title',\n 'recordagain_desc',\n 'discard_title',\n 'discard_desc',\n 'confirm_yes',\n 'recordinguploaded',\n 'maxfilesizehit',\n 'maxfilesizehit_title',\n 'uploadfailed',\n ]);\n\n prefetchTemplates([\n this.getEmbedTemplateName(),\n 'tiny_recordrtc/timeremaining',\n ]);\n }\n\n /**\n * Display an error message to the user.\n *\n * @param {Promise} title The error title\n * @param {Promise} content The error message\n * @returns {Promise}\n */\n async displayAlert(title, content) {\n const pendingPromise = new Pending('core/confirm:alert');\n const ModalFactory = await import('core/modal_factory');\n const modal = await ModalFactory.create({\n type: ModalFactory.types.ALERT,\n title: title,\n body: content,\n removeOnClose: true,\n });\n\n modal.show();\n pendingPromise.resolve();\n\n return modal;\n }\n\n /**\n * Handle successful capture of the User Media.\n *\n * @param {MediaStream} stream The stream as captured by the User Media.\n */\n handleCaptureSuccess(stream) {\n // Set audio player source to microphone stream.\n this.player.srcObject = stream;\n\n if (this.playOnCapture()) {\n // Mute audio, distracting while recording.\n this.player.muted = true;\n\n this.player.play();\n }\n\n this.stream = stream;\n this.setupPlayerSource();\n this.setRecordButtonState(true);\n }\n\n /**\n * Setup the player to use the stream as a source.\n */\n setupPlayerSource() {\n if (!this.player.srcObject) {\n this.player.srcObject = this.stream;\n\n // Mute audio, distracting while recording.\n this.player.muted = true;\n\n this.player.play();\n }\n }\n\n /**\n * Enable the record button.\n *\n * @param {boolean|null} enabled Set the button state\n */\n setRecordButtonState(enabled) {\n this.startStopButton.disabled = !enabled;\n }\n\n /**\n * Configure button visibility for the record button.\n *\n * @param {boolean} visible Set the visibility of the button.\n */\n setRecordButtonVisibility(visible) {\n const container = this.getButtonContainer('start-stop');\n container.classList.toggle('hide', !visible);\n }\n\n /**\n * Enable the upload button.\n *\n * @param {boolean|null} enabled Set the button state\n */\n setUploadButtonState(enabled) {\n this.uploadButton.disabled = !enabled;\n }\n\n /**\n * Configure button visibility for the upload button.\n *\n * @param {boolean} visible Set the visibility of the button.\n */\n setUploadButtonVisibility(visible) {\n const container = this.getButtonContainer('upload');\n container.classList.toggle('hide', !visible);\n }\n /**\n * Handle failure to capture the User Media.\n *\n * @param {Error} error\n */\n handleCaptureFailure(error) {\n // Changes 'CertainError' -> 'gumcertain' to match language string names.\n var subject = `gum${error.name.replace('Error', '').toLowerCase()}`;\n this.displayAlert(\n getString(`${subject}_title`, component),\n getString(subject, component)\n );\n }\n\n /**\n * Close the modal and stop recording.\n */\n close() {\n // Closing the modal will destroy it and remove it from the DOM.\n // It will also stop the recording via the hidden Modal Event.\n this.modal.hide();\n }\n\n /**\n * Register event listeners for the modal.\n */\n registerEventListeners() {\n this.modalRoot.addEventListener('click', this.handleModalClick.bind(this));\n this.modal.getRoot().on(ModalEvents.outsideClick, this.outsideClickHandler.bind(this));\n this.modal.getRoot().on(ModalEvents.hidden, () => {\n this.cleanupStream();\n this.requestRecordingStop();\n });\n }\n\n /**\n * Prevent the Modal from closing when recording is on process.\n *\n * @param {MouseEvent} event The click event\n */\n async outsideClickHandler(event) {\n if (this.isRecording()) {\n // The user is recording.\n // Do not distract with a confirmation, just prevent closing.\n event.preventDefault();\n } else if (this.hasData()) {\n // If there is a blobsize then there is data that may be lost.\n // Ask the user to confirm they want to close the modal.\n // We prevent default here, and then close the modal if they confirm.\n event.preventDefault();\n\n try {\n await saveCancelPromise(\n await getString(\"discard_title\", component),\n await getString(\"discard_desc\", component),\n await getString(\"confirm_yes\", component),\n );\n this.modal.hide();\n } catch (error) {\n // Do nothing, the modal will not close.\n }\n }\n }\n\n /**\n * Handle a click within the Modal.\n *\n * @param {MouseEvent} event The click event\n */\n handleModalClick(event) {\n const button = event.target.closest('button');\n if (button && button.dataset.action) {\n const action = button.dataset.action;\n if (action === 'startstop') {\n this.handleRecordingStartStopRequested();\n }\n\n if (action === 'upload') {\n this.uploadRecording();\n }\n }\n }\n\n /**\n * Handle the click event for the recording start/stop button.\n */\n handleRecordingStartStopRequested() {\n if (this.mediaRecorder?.state === 'recording') {\n this.requestRecordingStop();\n } else {\n this.startRecording();\n }\n }\n\n /**\n * Handle the media stream after it has finished.\n */\n async onMediaStopped() {\n // Set source of audio player.\n this.blob = new Blob(this.data.chunks, {\n type: this.mediaRecorder.mimeType\n });\n this.player.srcObject = null;\n this.player.src = URL.createObjectURL(this.blob);\n\n // Change the label to \"Record again\".\n this.setRecordButtonTextFromString('recordagain');\n\n // Show audio player with controls enabled, and unmute.\n this.player.muted = false;\n this.player.controls = true;\n this.getButtonContainer('player')?.classList.toggle('hide', false);\n\n // Show upload button.\n this.setUploadButtonVisibility(true);\n this.setUploadButtonState(true);\n }\n\n /**\n * Upload the recording and insert it into the editor content.\n */\n async uploadRecording() {\n // Trigger error if no recording has been made.\n if (this.data.chunks.length === 0) {\n this.displayAlert('norecordingfound');\n return;\n }\n\n const fileName = this.getFileName((Math.random() * 1000).toString().replace('.', ''));\n\n // Upload recording to server.\n try {\n // Once uploading starts, do not allow any further changes to the recording.\n this.setRecordButtonVisibility(false);\n\n // Disable the upload button.\n this.setUploadButtonState(false);\n\n // Upload the recording.\n const fileURL = await uploadFile(this.editor, 'media', this.blob, fileName, (progress) => {\n this.setUploadButtonTextProgress(progress);\n });\n this.insertMedia(fileURL);\n this.close();\n addToast(await getString('recordinguploaded', component));\n } catch (error) {\n // Show a toast and unhide the button.\n this.setUploadButtonState(true);\n\n addToast(await getString('uploadfailed', component, {error}), {\n type: 'error',\n });\n\n }\n }\n\n /**\n * Helper to get the container that a button is in.\n *\n * @param {string} purpose The button purpose\n * @returns {HTMLElement}\n */\n getButtonContainer(purpose) {\n return this.modalRoot.querySelector(`[data-purpose=\"${purpose}-container\"]`);\n }\n\n /**\n * Check whether the browser is compatible with capturing media.\n *\n * @returns {boolean}\n */\n static isBrowserCompatible() {\n return this.checkSecure() && this.hasUserMedia();\n }\n\n static async display(editor) {\n const ModalClass = this.getModalClass();\n const modal = await ModalFactory.create({\n type: ModalClass.TYPE,\n templateContext: {},\n large: true,\n });\n\n // Set up the VideoRecorder.\n const recorder = new this(editor, modal);\n if (recorder.isReady()) {\n modal.show();\n }\n return modal;\n }\n\n /**\n * Check whether the browser is compatible with capturing media, and display a warning if not.\n *\n * @returns {boolean}\n */\n checkAndWarnAboutBrowserCompatibility() {\n if (!this.constructor.checkSecure()) {\n getStrings(['insecurealert_title', 'insecurealert'].map((key) => ({key, component})))\n .then(([title, message]) => addToast(message, {title, type: 'error'}))\n .catch();\n return false;\n }\n\n if (!this.constructor.hasUserMedia) {\n getStrings(['nowebrtc_title', 'nowebrtc'].map((key) => ({key, component})))\n .then(([title, message]) => addToast(message, {title, type: 'error'}))\n .catch();\n return false;\n }\n\n return true;\n }\n\n /**\n * Check whether the browser supports WebRTC.\n *\n * @returns {boolean}\n */\n static hasUserMedia() {\n return (navigator.mediaDevices && window.MediaRecorder);\n }\n\n /**\n * Check whether the hostname is either hosted over SSL, or from a valid localhost hostname.\n *\n * The UserMedia API can only be used in secure contexts as noted.\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#privacy_and_security}\n *\n * @returns {boolean} Whether the plugin can be loaded.\n */\n static checkSecure() {\n // Note: We can now use window.isSecureContext.\n // https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#feature_detection\n // https://developer.mozilla.org/en-US/docs/Web/API/isSecureContext\n return window.isSecureContext;\n }\n\n /**\n * Update the content of the stop recording button timer.\n */\n async setStopRecordingButton() {\n const {html, js} = await Templates.renderForPromise('tiny_recordrtc/timeremaining', this.getTimeRemaining());\n Templates.replaceNodeContents(this.startStopButton, html, js);\n this.buttonTimer = setInterval(this.updateRecordButtonTime.bind(this), 500);\n }\n\n /**\n * Update the time on the stop recording button.\n */\n updateRecordButtonTime() {\n const {remaining, minutes, seconds} = this.getTimeRemaining();\n if (remaining < 0) {\n this.requestRecordingStop();\n } else {\n this.startStopButton.querySelector('[data-type=\"minutes\"]').textContent = minutes;\n this.startStopButton.querySelector('[data-type=\"seconds\"]').textContent = seconds;\n }\n }\n\n /**\n * Set the text of the record button using a language string.\n *\n * @param {string} string The string identifier\n */\n async setRecordButtonTextFromString(string) {\n this.startStopButton.textContent = await getString(string, component);\n }\n\n /**\n * Set the upload button text progress.\n *\n * @param {number} progress The progress\n */\n async setUploadButtonTextProgress(progress) {\n this.uploadButton.textContent = await getString('uploading', component, {\n progress: Math.round(progress * 100) / 100,\n });\n }\n\n async resetUploadButtonText() {\n this.uploadButton.textContent = await getString('upload', component);\n }\n\n /**\n * Clear the timer for the stop recording button.\n */\n clearButtonTimer() {\n if (this.buttonTimer) {\n clearInterval(this.buttonTimer);\n }\n this.buttonTimer = null;\n }\n\n /**\n * Get the time remaining for the recording.\n *\n * @returns {Object} The minutes and seconds remaining.\n */\n getTimeRemaining() {\n // All times are in milliseconds\n const now = new Date().getTime();\n const remaining = Math.floor(this.getTimeLimit() - ((now - this.startTime) / 1000));\n\n const formatter = new Intl.NumberFormat(navigator.language, {minimumIntegerDigits: 2});\n const seconds = formatter.format(remaining % 60);\n const minutes = formatter.format(Math.floor((remaining - seconds) / 60));\n return {\n remaining,\n minutes,\n seconds,\n };\n }\n\n /**\n * Get the maximum file size that can be uploaded.\n *\n * @returns {number} The max byte size\n */\n getMaxUploadSize() {\n return this.config.maxrecsize;\n }\n\n /**\n * Stop the recording.\n * Please note that this should only stop the recording.\n * Anything related to processing the recording should be handled by the\n * mediaRecorder's stopped event handler which is processed after it has stopped.\n */\n requestRecordingStop() {\n if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {\n this.stopRequested = true;\n } else {\n // There is no recording to stop, but the stream must still be cleaned up.\n this.cleanupStream();\n }\n }\n\n stopRecorder() {\n this.mediaRecorder.stop();\n\n // Unmute the player so that the audio is heard during playback.\n this.player.muted = false;\n }\n\n /**\n * Clean up the stream.\n *\n * This involves stopping any track which is still active.\n */\n cleanupStream() {\n if (this.stream) {\n this.stream.getTracks()\n .filter((track) => track.readyState !== 'ended')\n .forEach((track) => track.stop());\n }\n }\n\n /**\n * Handle the mediaRecorder `stop` event.\n */\n handleStopped() {\n // Handle the stream data.\n this.onMediaStopped();\n\n // Clear the button timer.\n this.clearButtonTimer();\n }\n\n /**\n * Handle the mediaRecorder `start` event.\n *\n * This event is called when the recording starts.\n */\n handleStarted() {\n this.startTime = new Date().getTime();\n this.setStopRecordingButton();\n }\n\n /**\n * Handle the mediaRecorder `dataavailable` event.\n *\n * @param {Event} event\n */\n handleDataAvailable(event) {\n if (this.isRecording()) {\n const newSize = this.data.blobSize + event.data.size;\n // Recording stops when either the maximum upload size is reached, or the time limit expires.\n // The time limit is checked in the `updateButtonTime` function.\n if (newSize >= this.getMaxUploadSize()) {\n this.stopRecorder();\n this.displayFileLimitHitMessage();\n } else {\n // Push recording slice to array.\n this.data.chunks.push(event.data);\n\n // Size of all recorded data so far.\n this.data.blobSize = newSize;\n\n if (this.stopRequested) {\n this.stopRecorder();\n }\n }\n }\n }\n\n async displayFileLimitHitMessage() {\n addToast(await getString('maxfilesizehit', component), {\n title: await getString('maxfilesizehit_title', component),\n type: 'error',\n });\n }\n\n /**\n * Check whether the recording is in progress.\n *\n * @returns {boolean}\n */\n isRecording() {\n return this.mediaRecorder?.state === 'recording';\n }\n\n /**\n * Whether any data has been recorded.\n *\n * @returns {boolean}\n */\n hasData() {\n return !!this.data?.blobSize;\n }\n\n /**\n * Start the recording\n */\n async startRecording() {\n if (this.mediaRecorder) {\n // Stop the existing recorder if it exists.\n if (this.isRecording()) {\n this.mediaRecorder.stop();\n }\n\n if (this.hasData()) {\n const resetRecording = await this.recordAgainConfirmation();\n if (!resetRecording) {\n // User cancelled at the confirmation to reset the data, so exit early.\n return;\n }\n this.setUploadButtonVisibility(false);\n }\n\n this.mediaRecorder = null;\n }\n\n // The options for the recording codecs and bitrates.\n this.mediaRecorder = new MediaRecorder(this.stream, this.getParsedRecordingOptions());\n\n this.mediaRecorder.addEventListener('dataavailable', this.handleDataAvailable.bind(this));\n this.mediaRecorder.addEventListener('stop', this.handleStopped.bind(this));\n this.mediaRecorder.addEventListener('start', this.handleStarted.bind(this));\n\n this.data = {\n chunks: [],\n blobSize: 0\n };\n this.setupPlayerSource();\n this.stopRequested = false;\n\n // Capture in 50ms chunks.\n this.mediaRecorder.start(50);\n }\n\n /**\n * Confirm whether the user wants to reset the existing recoring.\n *\n * @returns {Promise} Whether the user confirmed the reset.\n */\n async recordAgainConfirmation() {\n try {\n await saveCancelPromise(\n await getString(\"recordagain_title\", component),\n await getString(\"recordagain_desc\", component),\n await getString(\"confirm_yes\", component)\n );\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Insert the HTML to embed the recording into the editor content.\n *\n * @param {string} source The URL to view the media.\n */\n async insertMedia(source) {\n const {html} = await Templates.renderForPromise(\n this.getEmbedTemplateName(),\n this.getEmbedTemplateContext({\n source,\n })\n );\n this.editor.insertContent(html);\n }\n\n /**\n * Add or modify the template parameters for the specified type.\n *\n * @param {Object} templateContext The Tempalte context to use\n * @returns {Object} The finalised template context\n */\n getEmbedTemplateContext(templateContext) {\n return templateContext;\n }\n}\n"],"names":["constructor","editor","modal","ready","this","checkAndWarnAboutBrowserCompatibility","config","params","modalRoot","getRoot","startStopButton","querySelector","uploadButton","setRecordButtonState","player","configurePlayer","registerEventListeners","captureUserMedia","prefetchContent","isReady","Error","name","getSupportedTypes","getRecordingOptions","getFileName","prefix","getMediaConstraints","playOnCapture","getTimeLimit","getEmbedTemplateName","getParsedRecordingOptions","types","options","compatTypes","filter","type","window","MediaRecorder","isTypeSupported","length","mimeType","stream","navigator","mediaDevices","getUserMedia","handleCaptureSuccess","error","handleCaptureFailure","component","title","content","pendingPromise","Pending","ModalFactory","create","ALERT","body","removeOnClose","show","resolve","srcObject","muted","play","setupPlayerSource","enabled","disabled","setRecordButtonVisibility","visible","getButtonContainer","classList","toggle","setUploadButtonState","setUploadButtonVisibility","subject","replace","toLowerCase","displayAlert","close","hide","addEventListener","handleModalClick","bind","on","ModalEvents","outsideClick","outsideClickHandler","hidden","cleanupStream","requestRecordingStop","event","isRecording","preventDefault","hasData","button","target","closest","dataset","action","handleRecordingStartStopRequested","uploadRecording","mediaRecorder","state","startRecording","blob","Blob","data","chunks","src","URL","createObjectURL","setRecordButtonTextFromString","controls","fileName","Math","random","toString","fileURL","progress","setUploadButtonTextProgress","insertMedia","purpose","checkSecure","hasUserMedia","ModalClass","getModalClass","TYPE","templateContext","large","map","key","then","_ref2","message","catch","_ref","isSecureContext","html","js","Templates","renderForPromise","getTimeRemaining","replaceNodeContents","buttonTimer","setInterval","updateRecordButtonTime","remaining","minutes","seconds","textContent","string","round","clearButtonTimer","clearInterval","now","Date","getTime","floor","startTime","formatter","Intl","NumberFormat","language","minimumIntegerDigits","format","getMaxUploadSize","maxrecsize","stopRequested","stopRecorder","stop","getTracks","track","readyState","forEach","handleStopped","onMediaStopped","handleStarted","setStopRecordingButton","handleDataAvailable","newSize","blobSize","size","displayFileLimitHitMessage","push","_this$data","recordAgainConfirmation","start","source","getEmbedTemplateContext","insertContent"],"mappings":"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"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js index 2e27d3e46c9..bc6773dec6f 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js @@ -2,7 +2,7 @@ define("tiny_recordrtc/commands_audio",["exports","core/str","editor_tiny/utils" /** * Tiny Record RTC - record audio command. * - * @module tiny_recordrtc/recordAudioCommands + * @module tiny_recordrtc/commands_audio * @copyright 2022, Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_audio_recorder=(obj=_audio_recorder)&&obj.__esModule?obj:{default:obj};return _exports.default=async()=>{if(!_audio_recorder.default.isBrowserCompatible())return()=>!1;const[audioButtonTitle,audio]=await Promise.all([(0,_str.get_string)("audiobuttontitle",_common.component),(0,_utils.getButtonImage)("audio",_common.component)]);return editor=>{if(!(0,_options.isAudioAllowed)(editor))return;editor.ui.registry.addIcon("audio",audio.html),editor.ui.registry.addButton(_common.audioButtonName,{icon:"audio",tooltip:audioButtonTitle,onAction:()=>_audio_recorder.default.display(editor)}),editor.ui.registry.addMenuItem(_common.audioButtonName,{icon:"audio",text:audioButtonTitle,onAction:()=>_audio_recorder.default.display(editor)})}},_exports.default})); diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js.map b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js.map index 2ef3c305245..7c23d1a7ba0 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js.map +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_audio.min.js.map @@ -1 +1 @@ -{"version":3,"file":"commands_audio.min.js","sources":["../src/commands_audio.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 * Tiny Record RTC - record audio command.\n *\n * @module tiny_recordrtc/recordAudioCommands\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {\n audioButtonName,\n component\n} from './common';\nimport Recorder from './audio_recorder';\nimport {isAudioAllowed} from './options';\n\nexport default async() => {\n if (!Recorder.isBrowserCompatible()) {\n // The browser doesn't support the plugin, so just don't show it.\n return () => false;\n }\n\n const [\n audioButtonTitle,\n audio,\n ] = await Promise.all([\n getString('audiobuttontitle', component),\n getButtonImage('audio', component),\n ]);\n\n return (editor) => {\n if (!isAudioAllowed(editor)) {\n return;\n }\n\n const icon = 'audio';\n editor.ui.registry.addIcon(icon, audio.html);\n\n editor.ui.registry.addButton(audioButtonName, {\n icon,\n tooltip: audioButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n\n editor.ui.registry.addMenuItem(audioButtonName, {\n icon,\n text: audioButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n };\n};\n"],"names":["async","Recorder","isBrowserCompatible","audioButtonTitle","audio","Promise","all","component","editor","ui","registry","addIcon","html","addButton","audioButtonName","icon","tooltip","onAction","display","addMenuItem","text"],"mappings":";;;;;;;qLAgCeA,cACNC,wBAASC,4BAEH,KAAM,QAIbC,iBACAC,aACMC,QAAQC,IAAI,EAClB,mBAAU,mBAAoBC,oBAC9B,yBAAe,QAASA,4BAGpBC,cACC,2BAAeA,eAKpBA,OAAOC,GAAGC,SAASC,QADN,QACoBP,MAAMQ,MAEvCJ,OAAOC,GAAGC,SAASG,UAAUC,wBAAiB,CAC1CC,KAJS,QAKTC,QAASb,iBACTc,SAAU,IAAMhB,wBAASiB,QAAQV,UAGrCA,OAAOC,GAAGC,SAASS,YAAYL,wBAAiB,CAC5CC,KAVS,QAWTK,KAAMjB,iBACNc,SAAU,IAAMhB,wBAASiB,QAAQV"} \ No newline at end of file +{"version":3,"file":"commands_audio.min.js","sources":["../src/commands_audio.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 * Tiny Record RTC - record audio command.\n *\n * @module tiny_recordrtc/commands_audio\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {\n audioButtonName,\n component\n} from './common';\nimport Recorder from './audio_recorder';\nimport {isAudioAllowed} from './options';\n\nexport default async() => {\n if (!Recorder.isBrowserCompatible()) {\n // The browser doesn't support the plugin, so just don't show it.\n return () => false;\n }\n\n const [\n audioButtonTitle,\n audio,\n ] = await Promise.all([\n getString('audiobuttontitle', component),\n getButtonImage('audio', component),\n ]);\n\n return (editor) => {\n if (!isAudioAllowed(editor)) {\n return;\n }\n\n const icon = 'audio';\n editor.ui.registry.addIcon(icon, audio.html);\n\n editor.ui.registry.addButton(audioButtonName, {\n icon,\n tooltip: audioButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n\n editor.ui.registry.addMenuItem(audioButtonName, {\n icon,\n text: audioButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n };\n};\n"],"names":["async","Recorder","isBrowserCompatible","audioButtonTitle","audio","Promise","all","component","editor","ui","registry","addIcon","html","addButton","audioButtonName","icon","tooltip","onAction","display","addMenuItem","text"],"mappings":";;;;;;;qLAgCeA,cACNC,wBAASC,4BAEH,KAAM,QAIbC,iBACAC,aACMC,QAAQC,IAAI,EAClB,mBAAU,mBAAoBC,oBAC9B,yBAAe,QAASA,4BAGpBC,cACC,2BAAeA,eAKpBA,OAAOC,GAAGC,SAASC,QADN,QACoBP,MAAMQ,MAEvCJ,OAAOC,GAAGC,SAASG,UAAUC,wBAAiB,CAC1CC,KAJS,QAKTC,QAASb,iBACTc,SAAU,IAAMhB,wBAASiB,QAAQV,UAGrCA,OAAOC,GAAGC,SAASS,YAAYL,wBAAiB,CAC5CC,KAVS,QAWTK,KAAMjB,iBACNc,SAAU,IAAMhB,wBAASiB,QAAQV"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js index bb20a74a4b1..84142088dcd 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js @@ -2,7 +2,7 @@ define("tiny_recordrtc/commands_video",["exports","core/str","editor_tiny/utils" /** * Tiny Record RTC - record video command. * - * @module tiny_recordrtc/recordVideoCommands + * @module tiny_recordrtc/commands_video * @copyright 2022, Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_video_recorder=(obj=_video_recorder)&&obj.__esModule?obj:{default:obj};return _exports.default=async()=>{if(!_video_recorder.default.isBrowserCompatible())return()=>!1;const[videoButtonTitle,buttonImage]=await Promise.all([(0,_str.get_string)("videobuttontitle",_common.component),(0,_utils.getButtonImage)("video",_common.component)]);return editor=>{if(!(0,_options.isVideoAllowed)(editor))return;editor.ui.registry.addIcon("video",buttonImage.html),editor.ui.registry.addButton(_common.videoButtonName,{icon:"video",tooltip:videoButtonTitle,onAction:()=>_video_recorder.default.display(editor)}),editor.ui.registry.addMenuItem(_common.videoButtonName,{icon:"video",text:videoButtonTitle,onAction:()=>_video_recorder.default.display(editor)})}},_exports.default})); diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js.map b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js.map index ffc1f6c218e..cdfd70dda16 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js.map +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/commands_video.min.js.map @@ -1 +1 @@ -{"version":3,"file":"commands_video.min.js","sources":["../src/commands_video.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 * Tiny Record RTC - record video command.\n *\n * @module tiny_recordrtc/recordVideoCommands\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {getButtonImage as getVideoIcon} from 'editor_tiny/utils';\nimport {\n videoButtonName,\n component\n} from './common';\nimport {isVideoAllowed} from './options';\nimport Recorder from './video_recorder';\n\nexport default async() => {\n if (!Recorder.isBrowserCompatible()) {\n // The browser doesn't support the plugin, so just don't show it.\n return () => false;\n }\n\n const [\n videoButtonTitle,\n buttonImage,\n ] = await Promise.all([\n getString('videobuttontitle', component),\n getVideoIcon('video', component),\n ]);\n\n return (editor) => {\n if (!isVideoAllowed(editor)) {\n return;\n }\n\n const icon = 'video';\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n editor.ui.registry.addButton(videoButtonName, {\n icon,\n tooltip: videoButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n\n editor.ui.registry.addMenuItem(videoButtonName, {\n icon,\n text: videoButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n };\n};\n"],"names":["async","Recorder","isBrowserCompatible","videoButtonTitle","buttonImage","Promise","all","component","editor","ui","registry","addIcon","html","addButton","videoButtonName","icon","tooltip","onAction","display","addMenuItem","text"],"mappings":";;;;;;;qLAgCeA,cACNC,wBAASC,4BAEH,KAAM,QAIbC,iBACAC,mBACMC,QAAQC,IAAI,EAClB,mBAAU,mBAAoBC,oBAC9B,yBAAa,QAASA,4BAGlBC,cACC,2BAAeA,eAKpBA,OAAOC,GAAGC,SAASC,QADN,QACoBP,YAAYQ,MAE7CJ,OAAOC,GAAGC,SAASG,UAAUC,wBAAiB,CAC1CC,KAJS,QAKTC,QAASb,iBACTc,SAAU,IAAMhB,wBAASiB,QAAQV,UAGrCA,OAAOC,GAAGC,SAASS,YAAYL,wBAAiB,CAC5CC,KAVS,QAWTK,KAAMjB,iBACNc,SAAU,IAAMhB,wBAASiB,QAAQV"} \ No newline at end of file +{"version":3,"file":"commands_video.min.js","sources":["../src/commands_video.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 * Tiny Record RTC - record video command.\n *\n * @module tiny_recordrtc/commands_video\n * @copyright 2022, Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport {getButtonImage as getVideoIcon} from 'editor_tiny/utils';\nimport {\n videoButtonName,\n component\n} from './common';\nimport {isVideoAllowed} from './options';\nimport Recorder from './video_recorder';\n\nexport default async() => {\n if (!Recorder.isBrowserCompatible()) {\n // The browser doesn't support the plugin, so just don't show it.\n return () => false;\n }\n\n const [\n videoButtonTitle,\n buttonImage,\n ] = await Promise.all([\n getString('videobuttontitle', component),\n getVideoIcon('video', component),\n ]);\n\n return (editor) => {\n if (!isVideoAllowed(editor)) {\n return;\n }\n\n const icon = 'video';\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n editor.ui.registry.addButton(videoButtonName, {\n icon,\n tooltip: videoButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n\n editor.ui.registry.addMenuItem(videoButtonName, {\n icon,\n text: videoButtonTitle,\n onAction: () => Recorder.display(editor),\n });\n };\n};\n"],"names":["async","Recorder","isBrowserCompatible","videoButtonTitle","buttonImage","Promise","all","component","editor","ui","registry","addIcon","html","addButton","videoButtonName","icon","tooltip","onAction","display","addMenuItem","text"],"mappings":";;;;;;;qLAgCeA,cACNC,wBAASC,4BAEH,KAAM,QAIbC,iBACAC,mBACMC,QAAQC,IAAI,EAClB,mBAAU,mBAAoBC,oBAC9B,yBAAa,QAASA,4BAGlBC,cACC,2BAAeA,eAKpBA,OAAOC,GAAGC,SAASC,QADN,QACoBP,YAAYQ,MAE7CJ,OAAOC,GAAGC,SAASG,UAAUC,wBAAiB,CAC1CC,KAJS,QAKTC,QAASb,iBACTc,SAAU,IAAMhB,wBAASiB,QAAQV,UAGrCA,OAAOC,GAAGC,SAASS,YAAYL,wBAAiB,CAC5CC,KAVS,QAWTK,KAAMjB,iBACNc,SAAU,IAAMhB,wBAASiB,QAAQV"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/recordrtc/amd/build/video_recorder.min.js.map b/lib/editor/tiny/plugins/recordrtc/amd/build/video_recorder.min.js.map index 1559867176e..1d9cc48d94b 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/build/video_recorder.min.js.map +++ b/lib/editor/tiny/plugins/recordrtc/amd/build/video_recorder.min.js.map @@ -1 +1 @@ -{"version":3,"file":"video_recorder.min.js","sources":["../src/video_recorder.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 * Tiny Record RTC - Video recorder configuration.\n *\n * @module tiny_recordrtc/video\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BaseClass from './base_recorder';\nimport Modal from 'tiny_recordrtc/modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from 'tiny_recordrtc/common';\n\nexport default class Video extends BaseClass {\n configurePlayer() {\n return this.modalRoot.querySelector('video');\n }\n\n getSupportedTypes() {\n return [\n 'video/webm;codecs=vp9,opus',\n 'video/webm;codecs=h264,opus',\n 'video/webm;codecs=vp8,opus',\n ];\n\n }\n\n getParsedRecordingOptions() {\n return {\n audioBitsPerSecond: parseInt(this.config.audiobitrate),\n videoBitsPerSecond: parseInt(this.config.videobitrate)\n };\n }\n\n getMediaConstraints() {\n return {\n audio: true,\n video: {\n width: {\n ideal: 640,\n },\n height: {\n ideal: 480,\n },\n },\n };\n }\n\n playOnCapture() {\n // Play the recording back on capture.\n return true;\n }\n\n getRecordingType() {\n return 'video';\n }\n\n getTimeLimit() {\n return this.config.videotimelimit;\n }\n\n getEmbedTemplateName() {\n return 'tiny_recordrtc/embed_video';\n }\n\n getFileName(prefix) {\n return `${prefix}-video.webm`;\n }\n\n static getModalClass() {\n const modalType = `${component}/video_recorder`;\n const registration = ModalRegistry.get(modalType);\n if (registration) {\n return registration.module;\n }\n\n const VideoModal = class extends Modal {\n static TYPE = modalType;\n static TEMPLATE = `${component}/video_recorder`;\n };\n\n ModalRegistry.register(VideoModal.TYPE, VideoModal, VideoModal.TEMPLATE);\n return VideoModal;\n }\n}\n"],"names":["Video","BaseClass","configurePlayer","this","modalRoot","querySelector","getSupportedTypes","getParsedRecordingOptions","audioBitsPerSecond","parseInt","config","audiobitrate","videoBitsPerSecond","videobitrate","getMediaConstraints","audio","video","width","ideal","height","playOnCapture","getRecordingType","getTimeLimit","videotimelimit","getEmbedTemplateName","getFileName","prefix","modalType","component","registration","ModalRegistry","get","module","VideoModal","Modal","register","TYPE","TEMPLATE"],"mappings":"4qBA4BqBA,cAAcC,uBAC/BC,yBACWC,KAAKC,UAAUC,cAAc,SAGxCC,0BACW,CACH,6BACA,8BACA,8BAKRC,kCACW,CACHC,mBAAoBC,SAASN,KAAKO,OAAOC,cACzCC,mBAAoBH,SAASN,KAAKO,OAAOG,eAIjDC,4BACW,CACHC,OAAO,EACPC,MAAO,CACHC,MAAO,CACHC,MAAO,KAEXC,OAAQ,CACJD,MAAO,OAMvBE,uBAEW,EAGXC,yBACW,QAGXC,sBACWnB,KAAKO,OAAOa,eAGvBC,6BACW,6BAGXC,YAAYC,wBACEA,8DAIJC,oBAAeC,qCACfC,aAAeC,wBAAcC,IAAIJ,cACnCE,oBACOA,aAAaG,aAGlBC,mCAAa,cAAcC,wBACfP,uDACOC,6EAGXO,SAASF,WAAWG,KAAMH,WAAYA,WAAWI,UACxDJ"} \ No newline at end of file +{"version":3,"file":"video_recorder.min.js","sources":["../src/video_recorder.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 * Tiny Record RTC - Video recorder configuration.\n *\n * @module tiny_recordrtc/video_recorder\n * @copyright 2022 Stevani Andolo \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BaseClass from './base_recorder';\nimport Modal from 'tiny_recordrtc/modal';\nimport ModalRegistry from 'core/modal_registry';\nimport {component} from 'tiny_recordrtc/common';\n\nexport default class Video extends BaseClass {\n configurePlayer() {\n return this.modalRoot.querySelector('video');\n }\n\n getSupportedTypes() {\n return [\n 'video/webm;codecs=vp9,opus',\n 'video/webm;codecs=h264,opus',\n 'video/webm;codecs=vp8,opus',\n ];\n\n }\n\n getParsedRecordingOptions() {\n return {\n audioBitsPerSecond: parseInt(this.config.audiobitrate),\n videoBitsPerSecond: parseInt(this.config.videobitrate)\n };\n }\n\n getMediaConstraints() {\n return {\n audio: true,\n video: {\n width: {\n ideal: 640,\n },\n height: {\n ideal: 480,\n },\n },\n };\n }\n\n playOnCapture() {\n // Play the recording back on capture.\n return true;\n }\n\n getRecordingType() {\n return 'video';\n }\n\n getTimeLimit() {\n return this.config.videotimelimit;\n }\n\n getEmbedTemplateName() {\n return 'tiny_recordrtc/embed_video';\n }\n\n getFileName(prefix) {\n return `${prefix}-video.webm`;\n }\n\n static getModalClass() {\n const modalType = `${component}/video_recorder`;\n const registration = ModalRegistry.get(modalType);\n if (registration) {\n return registration.module;\n }\n\n const VideoModal = class extends Modal {\n static TYPE = modalType;\n static TEMPLATE = `${component}/video_recorder`;\n };\n\n ModalRegistry.register(VideoModal.TYPE, VideoModal, VideoModal.TEMPLATE);\n return VideoModal;\n }\n}\n"],"names":["Video","BaseClass","configurePlayer","this","modalRoot","querySelector","getSupportedTypes","getParsedRecordingOptions","audioBitsPerSecond","parseInt","config","audiobitrate","videoBitsPerSecond","videobitrate","getMediaConstraints","audio","video","width","ideal","height","playOnCapture","getRecordingType","getTimeLimit","videotimelimit","getEmbedTemplateName","getFileName","prefix","modalType","component","registration","ModalRegistry","get","module","VideoModal","Modal","register","TYPE","TEMPLATE"],"mappings":"4qBA4BqBA,cAAcC,uBAC/BC,yBACWC,KAAKC,UAAUC,cAAc,SAGxCC,0BACW,CACH,6BACA,8BACA,8BAKRC,kCACW,CACHC,mBAAoBC,SAASN,KAAKO,OAAOC,cACzCC,mBAAoBH,SAASN,KAAKO,OAAOG,eAIjDC,4BACW,CACHC,OAAO,EACPC,MAAO,CACHC,MAAO,CACHC,MAAO,KAEXC,OAAQ,CACJD,MAAO,OAMvBE,uBAEW,EAGXC,yBACW,QAGXC,sBACWnB,KAAKO,OAAOa,eAGvBC,6BACW,6BAGXC,YAAYC,wBACEA,8DAIJC,oBAAeC,qCACfC,aAAeC,wBAAcC,IAAIJ,cACnCE,oBACOA,aAAaG,aAGlBC,mCAAa,cAAcC,wBACfP,uDACOC,6EAGXO,SAASF,WAAWG,KAAMH,WAAYA,WAAWI,UACxDJ"} \ No newline at end of file diff --git a/lib/editor/tiny/plugins/recordrtc/amd/src/audio_recorder.js b/lib/editor/tiny/plugins/recordrtc/amd/src/audio_recorder.js index 9e4723e3e56..346ec697e4e 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/src/audio_recorder.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/src/audio_recorder.js @@ -16,7 +16,7 @@ /** * Tiny Record RTC - audio recorder configuration. * - * @module tiny_recordrtc/audio + * @module tiny_recordrtc/audio_recorder * @copyright 2022 Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/recordrtc/amd/src/base_recorder.js b/lib/editor/tiny/plugins/recordrtc/amd/src/base_recorder.js index eee2ffe18eb..5ef7e522ceb 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/src/base_recorder.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/src/base_recorder.js @@ -17,7 +17,7 @@ /** * Tiny Record RTC type. * - * @module tiny_recordrtc/recording/base + * @module tiny_recordrtc/base_recorder * @copyright 2022 Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/recordrtc/amd/src/commands_audio.js b/lib/editor/tiny/plugins/recordrtc/amd/src/commands_audio.js index c1c9f05c01e..249f9fd922b 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/src/commands_audio.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/src/commands_audio.js @@ -16,7 +16,7 @@ /** * Tiny Record RTC - record audio command. * - * @module tiny_recordrtc/recordAudioCommands + * @module tiny_recordrtc/commands_audio * @copyright 2022, Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/recordrtc/amd/src/commands_video.js b/lib/editor/tiny/plugins/recordrtc/amd/src/commands_video.js index 7bdc602b1e5..a16a0a23a54 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/src/commands_video.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/src/commands_video.js @@ -16,7 +16,7 @@ /** * Tiny Record RTC - record video command. * - * @module tiny_recordrtc/recordVideoCommands + * @module tiny_recordrtc/commands_video * @copyright 2022, Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/editor/tiny/plugins/recordrtc/amd/src/video_recorder.js b/lib/editor/tiny/plugins/recordrtc/amd/src/video_recorder.js index 85eae290af8..28c3246747b 100644 --- a/lib/editor/tiny/plugins/recordrtc/amd/src/video_recorder.js +++ b/lib/editor/tiny/plugins/recordrtc/amd/src/video_recorder.js @@ -16,7 +16,7 @@ /** * Tiny Record RTC - Video recorder configuration. * - * @module tiny_recordrtc/video + * @module tiny_recordrtc/video_recorder * @copyright 2022 Stevani Andolo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/table/amd/build/local/dynamic/repository.min.js.map b/lib/table/amd/build/local/dynamic/repository.min.js.map index 4c6d62b2e5e..a71159f635a 100644 --- a/lib/table/amd/build/local/dynamic/repository.min.js.map +++ b/lib/table/amd/build/local/dynamic/repository.min.js.map @@ -1 +1 @@ -{"version":3,"file":"repository.min.js","sources":["../../../src/local/dynamic/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 calendar ajax actions.\n *\n * @module core_calendar/repository\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Fetch table view.\n *\n * @method fetch\n * @param {String} component The component\n * @param {String} handler The name of the handler\n * @param {String} uniqueid The unique id of the table\n * @param {Object} options The options to use when updating the table\n * @param {Array} options.sortData The list of columns to sort by\n * @param {Number} options.joinType The filterset join type\n * @param {Object} options.filters The filters to apply when searching\n * @param {String} options.firstinitial The first name initial to filter on\n * @param {String} options.lastinitial The last name initial to filter on\n * @param {String} options.pageNumber The page number\n * @param {Number} options.pageSize The page size\n * @param {Object} options.hiddenColumns The columns to hide\n * @param {Bool} resetPreferences\n * @return {Promise} Resolved with requested table view\n */\nexport const fetch = (component, handler, uniqueid, {\n sortData = [],\n joinType = null,\n filters = {},\n firstinitial = null,\n lastinitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = {}\n} = {}, resetPreferences = false) => fetchMany([{\n methodname: `core_table_get_dynamic_table_content`,\n args: {\n component,\n handler,\n uniqueid,\n sortdata: sortData,\n jointype: joinType,\n filters,\n firstinitial,\n lastinitial,\n pagenumber: pageNumber,\n pagesize: pageSize,\n hiddencolumns: hiddenColumns,\n resetpreferences: resetPreferences\n },\n}])[0];\n"],"names":["component","handler","uniqueid","sortData","joinType","filters","firstinitial","lastinitial","pageNumber","pageSize","hiddenColumns","resetPreferences","methodname","args","sortdata","jointype","pagenumber","pagesize","hiddencolumns","resetpreferences"],"mappings":"4LA2CqB,SAACA,UAAWC,QAASC,cAAUC,SAChDA,SAAW,GADqCC,SAEhDA,SAAW,KAFqCC,QAGhDA,QAAU,GAHsCC,aAIhDA,aAAe,KAJiCC,YAKhDA,YAAc,KALkCC,WAMhDA,WAAa,KANmCC,SAOhDA,SAAW,KAPqCC,cAQhDA,cAAgB,2DAChB,GAAIC,gFAA6B,cAAU,CAAC,CAC5CC,kDACAC,KAAM,CACFb,UAAAA,UACAC,QAAAA,QACAC,SAAAA,SACAY,SAAUX,SACVY,SAAUX,SACVC,QAAAA,QACAC,aAAAA,aACAC,YAAAA,YACAS,WAAYR,WACZS,SAAUR,SACVS,cAAeR,cACfS,iBAAkBR,qBAEtB"} \ No newline at end of file +{"version":3,"file":"repository.min.js","sources":["../../../src/local/dynamic/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 calendar ajax actions.\n *\n * @module core_table/local/dynamic/repository\n * @copyright 2017 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Fetch table view.\n *\n * @method fetch\n * @param {String} component The component\n * @param {String} handler The name of the handler\n * @param {String} uniqueid The unique id of the table\n * @param {Object} options The options to use when updating the table\n * @param {Array} options.sortData The list of columns to sort by\n * @param {Number} options.joinType The filterset join type\n * @param {Object} options.filters The filters to apply when searching\n * @param {String} options.firstinitial The first name initial to filter on\n * @param {String} options.lastinitial The last name initial to filter on\n * @param {String} options.pageNumber The page number\n * @param {Number} options.pageSize The page size\n * @param {Object} options.hiddenColumns The columns to hide\n * @param {Bool} resetPreferences\n * @return {Promise} Resolved with requested table view\n */\nexport const fetch = (component, handler, uniqueid, {\n sortData = [],\n joinType = null,\n filters = {},\n firstinitial = null,\n lastinitial = null,\n pageNumber = null,\n pageSize = null,\n hiddenColumns = {}\n} = {}, resetPreferences = false) => fetchMany([{\n methodname: `core_table_get_dynamic_table_content`,\n args: {\n component,\n handler,\n uniqueid,\n sortdata: sortData,\n jointype: joinType,\n filters,\n firstinitial,\n lastinitial,\n pagenumber: pageNumber,\n pagesize: pageSize,\n hiddencolumns: hiddenColumns,\n resetpreferences: resetPreferences\n },\n}])[0];\n"],"names":["component","handler","uniqueid","sortData","joinType","filters","firstinitial","lastinitial","pageNumber","pageSize","hiddenColumns","resetPreferences","methodname","args","sortdata","jointype","pagenumber","pagesize","hiddencolumns","resetpreferences"],"mappings":"4LA2CqB,SAACA,UAAWC,QAASC,cAAUC,SAChDA,SAAW,GADqCC,SAEhDA,SAAW,KAFqCC,QAGhDA,QAAU,GAHsCC,aAIhDA,aAAe,KAJiCC,YAKhDA,YAAc,KALkCC,WAMhDA,WAAa,KANmCC,SAOhDA,SAAW,KAPqCC,cAQhDA,cAAgB,2DAChB,GAAIC,gFAA6B,cAAU,CAAC,CAC5CC,kDACAC,KAAM,CACFb,UAAAA,UACAC,QAAAA,QACAC,SAAAA,SACAY,SAAUX,SACVY,SAAUX,SACVC,QAAAA,QACAC,aAAAA,aACAC,YAAAA,YACAS,WAAYR,WACZS,SAAUR,SACVS,cAAeR,cACfS,iBAAkBR,qBAEtB"} \ No newline at end of file diff --git a/lib/table/amd/build/local/dynamic/selectors.min.js.map b/lib/table/amd/build/local/dynamic/selectors.min.js.map index 5c48c1b9e20..de6e21d28c0 100644 --- a/lib/table/amd/build/local/dynamic/selectors.min.js.map +++ b/lib/table/amd/build/local/dynamic/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectors.min.js","sources":["../../../src/local/dynamic/selectors.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 * Dynamic table selectors.\n *\n * @module core_table/selectors\n * @copyright 2020 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n main: {\n region: '[data-region=\"core_table/dynamic\"]',\n fromRegionId: regionId => `[data-region=\"core_table/dynamic\"][data-table-uniqueid=\"${regionId}\"]`,\n },\n table: {\n links: {\n sortableColumn: 'a[data-sortable=\"1\"]',\n hide: 'a[data-action=\"hide\"]',\n show: 'a[data-action=\"show\"]',\n },\n },\n initialsBar: {\n links: {\n firstInitial: '.firstinitial [data-initial]',\n lastInitial: '.lastinitial [data-initial]',\n },\n },\n paginationBar: {\n links: {\n pageItem: '.pagination [data-page-number]'\n }\n },\n showCount: {\n links: {\n toggle: '[data-action=\"showcount\"]',\n },\n },\n};\n"],"names":["main","region","fromRegionId","regionId","table","links","sortableColumn","hide","show","initialsBar","firstInitial","lastInitial","paginationBar","pageItem","showCount","toggle"],"mappings":"oLAsBe,CACXA,KAAM,CACFC,OAAQ,qCACRC,aAAcC,4EAAuEA,gBAEzFC,MAAO,CACHC,MAAO,CACHC,eAAgB,uBAChBC,KAAM,wBACNC,KAAM,0BAGdC,YAAa,CACTJ,MAAO,CACHK,aAAc,+BACdC,YAAa,gCAGrBC,cAAe,CACXP,MAAO,CACHQ,SAAU,mCAGlBC,UAAW,CACPT,MAAO,CACHU,OAAQ"} \ No newline at end of file +{"version":3,"file":"selectors.min.js","sources":["../../../src/local/dynamic/selectors.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 * Dynamic table selectors.\n *\n * @module core_table/local/dynamic/selectors\n * @copyright 2020 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n main: {\n region: '[data-region=\"core_table/dynamic\"]',\n fromRegionId: regionId => `[data-region=\"core_table/dynamic\"][data-table-uniqueid=\"${regionId}\"]`,\n },\n table: {\n links: {\n sortableColumn: 'a[data-sortable=\"1\"]',\n hide: 'a[data-action=\"hide\"]',\n show: 'a[data-action=\"show\"]',\n },\n },\n initialsBar: {\n links: {\n firstInitial: '.firstinitial [data-initial]',\n lastInitial: '.lastinitial [data-initial]',\n },\n },\n paginationBar: {\n links: {\n pageItem: '.pagination [data-page-number]'\n }\n },\n showCount: {\n links: {\n toggle: '[data-action=\"showcount\"]',\n },\n },\n};\n"],"names":["main","region","fromRegionId","regionId","table","links","sortableColumn","hide","show","initialsBar","firstInitial","lastInitial","paginationBar","pageItem","showCount","toggle"],"mappings":"oLAsBe,CACXA,KAAM,CACFC,OAAQ,qCACRC,aAAcC,4EAAuEA,gBAEzFC,MAAO,CACHC,MAAO,CACHC,eAAgB,uBAChBC,KAAM,wBACNC,KAAM,0BAGdC,YAAa,CACTJ,MAAO,CACHK,aAAc,+BACdC,YAAa,gCAGrBC,cAAe,CACXP,MAAO,CACHQ,SAAU,mCAGlBC,UAAW,CACPT,MAAO,CACHU,OAAQ"} \ No newline at end of file diff --git a/lib/table/amd/src/local/dynamic/repository.js b/lib/table/amd/src/local/dynamic/repository.js index 371bc5418a0..9da65027e12 100644 --- a/lib/table/amd/src/local/dynamic/repository.js +++ b/lib/table/amd/src/local/dynamic/repository.js @@ -16,7 +16,7 @@ /** * A javascript module to handle calendar ajax actions. * - * @module core_calendar/repository + * @module core_table/local/dynamic/repository * @copyright 2017 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/lib/table/amd/src/local/dynamic/selectors.js b/lib/table/amd/src/local/dynamic/selectors.js index 11be2620621..81986529329 100644 --- a/lib/table/amd/src/local/dynamic/selectors.js +++ b/lib/table/amd/src/local/dynamic/selectors.js @@ -16,7 +16,7 @@ /** * Dynamic table selectors. * - * @module core_table/selectors + * @module core_table/local/dynamic/selectors * @copyright 2020 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/assign/amd/build/participant_selector.min.js b/mod/assign/amd/build/participant_selector.min.js index a5cc97fc808..5d5530765d1 100644 --- a/mod/assign/amd/build/participant_selector.min.js +++ b/mod/assign/amd/build/participant_selector.min.js @@ -1,7 +1,7 @@ /** * Custom auto-complete adapter to load users from the assignment list_participants webservice. * - * @module mod_assign/participants_selector + * @module mod_assign/participant_selector * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/assign/amd/build/participant_selector.min.js.map b/mod/assign/amd/build/participant_selector.min.js.map index 06f68f2f95a..aa62f33934f 100644 --- a/mod/assign/amd/build/participant_selector.min.js.map +++ b/mod/assign/amd/build/participant_selector.min.js.map @@ -1 +1 @@ -{"version":3,"file":"participant_selector.min.js","sources":["../src/participant_selector.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 * Custom auto-complete adapter to load users from the assignment list_participants webservice.\n *\n * @module mod_assign/participants_selector\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'jquery', 'core/templates'], function(ajax, $, templates) {\n\n\n return /** @alias module:mod_assign/participants_selector */ {\n\n // Public variables and functions.\n /**\n * Process the results returned from transport (convert to value + label)\n *\n * @method processResults\n * @param {String} selector\n * @param {Array} data\n * @return {Array}\n */\n processResults: function(selector, data) {\n return data;\n },\n\n /**\n * Fetch results based on the current query. This also renders each result from a template before returning them.\n *\n * @method transport\n * @param {String} selector Selector for the original select element\n * @param {String} query Current search string\n * @param {Function} success Success handler\n * @param {Function} failure Failure handler\n */\n transport: function(selector, query, success, failure) {\n var assignmentid = $(selector).attr('data-assignmentid');\n var groupid = $(selector).attr('data-groupid');\n var filters = $('[data-region=\"configure-filters\"] input[type=\"checkbox\"]');\n var filterstrings = [];\n\n filters.each(function(index, element) {\n filterstrings[$(element).attr('name')] = $(element).prop('checked');\n });\n\n ajax.call([{\n methodname: 'mod_assign_list_participants',\n args: {\n assignid: assignmentid,\n groupid: groupid,\n filter: query,\n limit: 30,\n includeenrolments: false,\n tablesort: true\n }\n }])[0].then(function(results) {\n var promises = [];\n var identityfields = $('[data-showuseridentity]').data('showuseridentity').split(',');\n\n // We got the results, now we loop over them and render each one from a template.\n $.each(results, function(index, user) {\n var ctx = user,\n identity = [],\n show = true;\n\n if (filterstrings.filter_submitted && !user.submitted) {\n show = false;\n }\n if (filterstrings.filter_notsubmitted && user.submitted) {\n show = false;\n }\n if (filterstrings.filter_requiregrading && !user.requiregrading) {\n show = false;\n }\n if (filterstrings.filter_grantedextension && !user.grantedextension) {\n show = false;\n }\n if (show) {\n $.each(identityfields, function(i, k) {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(templates.render('mod_assign/list_participant_user_summary', ctx).then(function(html) {\n return {value: user.id, label: html};\n }));\n }\n });\n // Do the dance for $.when()\n return $.when.apply($, promises);\n }).then(function() {\n var users = [];\n\n // Determine if we've been passed any arguments..\n if (arguments[0]) {\n // Undo the $.when() dance from arguments object into an array..\n users = Array.prototype.slice.call(arguments);\n }\n\n success(users);\n return;\n }).catch(failure);\n }\n };\n});\n"],"names":["define","ajax","$","templates","processResults","selector","data","transport","query","success","failure","assignmentid","attr","groupid","filters","filterstrings","each","index","element","prop","call","methodname","args","assignid","filter","limit","includeenrolments","tablesort","then","results","promises","identityfields","split","user","ctx","identity","show","filter_submitted","submitted","filter_notsubmitted","filter_requiregrading","requiregrading","filter_grantedextension","grantedextension","i","k","hasidentity","push","join","render","html","value","id","label","when","apply","users","arguments","Array","prototype","slice","catch"],"mappings":";;;;;;;AAsBAA,yCAAO,CAAC,YAAa,SAAU,mBAAmB,SAASC,KAAMC,EAAGC,iBAGH,CAWzDC,eAAgB,SAASC,SAAUC,aACxBA,MAYXC,UAAW,SAASF,SAAUG,MAAOC,QAASC,aACtCC,aAAeT,EAAEG,UAAUO,KAAK,qBAChCC,QAAUX,EAAEG,UAAUO,KAAK,gBAC3BE,QAAUZ,EAAE,4DACZa,cAAgB,GAEpBD,QAAQE,MAAK,SAASC,MAAOC,SACzBH,cAAcb,EAAEgB,SAASN,KAAK,SAAWV,EAAEgB,SAASC,KAAK,cAG7DlB,KAAKmB,KAAK,CAAC,CACPC,WAAY,+BACZC,KAAM,CACFC,SAAUZ,aACVE,QAASA,QACTW,OAAQhB,MACRiB,MAAO,GACPC,mBAAmB,EACnBC,WAAW,MAEf,GAAGC,MAAK,SAASC,aACbC,SAAW,GACXC,eAAiB7B,EAAE,2BAA2BI,KAAK,oBAAoB0B,MAAM,YAGjF9B,EAAEc,KAAKa,SAAS,SAASZ,MAAOgB,UACxBC,IAAMD,KACNE,SAAW,GACXC,MAAO,EAEPrB,cAAcsB,mBAAqBJ,KAAKK,YACxCF,MAAO,GAEPrB,cAAcwB,qBAAuBN,KAAKK,YAC1CF,MAAO,GAEPrB,cAAcyB,wBAA0BP,KAAKQ,iBAC7CL,MAAO,GAEPrB,cAAc2B,0BAA4BT,KAAKU,mBAC/CP,MAAO,GAEPA,OACAlC,EAAEc,KAAKe,gBAAgB,SAASa,EAAGC,QACR,IAAZZ,KAAKY,IAAkC,KAAZZ,KAAKY,KACvCX,IAAIY,aAAc,EAClBX,SAASY,KAAKd,KAAKY,QAG3BX,IAAIC,SAAWA,SAASa,KAAK,MAC7BlB,SAASiB,KAAK5C,UAAU8C,OAAO,2CAA4Cf,KAAKN,MAAK,SAASsB,YACnF,CAACC,MAAOlB,KAAKmB,GAAIC,MAAOH,cAKpChD,EAAEoD,KAAKC,MAAMrD,EAAG4B,aACxBF,MAAK,eACA4B,MAAQ,GAGRC,UAAU,KAEVD,MAAQE,MAAMC,UAAUC,MAAMxC,KAAKqC,YAGvChD,QAAQ+C,UAETK,MAAMnD"} \ No newline at end of file +{"version":3,"file":"participant_selector.min.js","sources":["../src/participant_selector.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 * Custom auto-complete adapter to load users from the assignment list_participants webservice.\n *\n * @module mod_assign/participant_selector\n * @copyright 2015 Damyon Wiese \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['core/ajax', 'jquery', 'core/templates'], function(ajax, $, templates) {\n\n\n return /** @alias module:mod_assign/participants_selector */ {\n\n // Public variables and functions.\n /**\n * Process the results returned from transport (convert to value + label)\n *\n * @method processResults\n * @param {String} selector\n * @param {Array} data\n * @return {Array}\n */\n processResults: function(selector, data) {\n return data;\n },\n\n /**\n * Fetch results based on the current query. This also renders each result from a template before returning them.\n *\n * @method transport\n * @param {String} selector Selector for the original select element\n * @param {String} query Current search string\n * @param {Function} success Success handler\n * @param {Function} failure Failure handler\n */\n transport: function(selector, query, success, failure) {\n var assignmentid = $(selector).attr('data-assignmentid');\n var groupid = $(selector).attr('data-groupid');\n var filters = $('[data-region=\"configure-filters\"] input[type=\"checkbox\"]');\n var filterstrings = [];\n\n filters.each(function(index, element) {\n filterstrings[$(element).attr('name')] = $(element).prop('checked');\n });\n\n ajax.call([{\n methodname: 'mod_assign_list_participants',\n args: {\n assignid: assignmentid,\n groupid: groupid,\n filter: query,\n limit: 30,\n includeenrolments: false,\n tablesort: true\n }\n }])[0].then(function(results) {\n var promises = [];\n var identityfields = $('[data-showuseridentity]').data('showuseridentity').split(',');\n\n // We got the results, now we loop over them and render each one from a template.\n $.each(results, function(index, user) {\n var ctx = user,\n identity = [],\n show = true;\n\n if (filterstrings.filter_submitted && !user.submitted) {\n show = false;\n }\n if (filterstrings.filter_notsubmitted && user.submitted) {\n show = false;\n }\n if (filterstrings.filter_requiregrading && !user.requiregrading) {\n show = false;\n }\n if (filterstrings.filter_grantedextension && !user.grantedextension) {\n show = false;\n }\n if (show) {\n $.each(identityfields, function(i, k) {\n if (typeof user[k] !== 'undefined' && user[k] !== '') {\n ctx.hasidentity = true;\n identity.push(user[k]);\n }\n });\n ctx.identity = identity.join(', ');\n promises.push(templates.render('mod_assign/list_participant_user_summary', ctx).then(function(html) {\n return {value: user.id, label: html};\n }));\n }\n });\n // Do the dance for $.when()\n return $.when.apply($, promises);\n }).then(function() {\n var users = [];\n\n // Determine if we've been passed any arguments..\n if (arguments[0]) {\n // Undo the $.when() dance from arguments object into an array..\n users = Array.prototype.slice.call(arguments);\n }\n\n success(users);\n return;\n }).catch(failure);\n }\n };\n});\n"],"names":["define","ajax","$","templates","processResults","selector","data","transport","query","success","failure","assignmentid","attr","groupid","filters","filterstrings","each","index","element","prop","call","methodname","args","assignid","filter","limit","includeenrolments","tablesort","then","results","promises","identityfields","split","user","ctx","identity","show","filter_submitted","submitted","filter_notsubmitted","filter_requiregrading","requiregrading","filter_grantedextension","grantedextension","i","k","hasidentity","push","join","render","html","value","id","label","when","apply","users","arguments","Array","prototype","slice","catch"],"mappings":";;;;;;;AAsBAA,yCAAO,CAAC,YAAa,SAAU,mBAAmB,SAASC,KAAMC,EAAGC,iBAGH,CAWzDC,eAAgB,SAASC,SAAUC,aACxBA,MAYXC,UAAW,SAASF,SAAUG,MAAOC,QAASC,aACtCC,aAAeT,EAAEG,UAAUO,KAAK,qBAChCC,QAAUX,EAAEG,UAAUO,KAAK,gBAC3BE,QAAUZ,EAAE,4DACZa,cAAgB,GAEpBD,QAAQE,MAAK,SAASC,MAAOC,SACzBH,cAAcb,EAAEgB,SAASN,KAAK,SAAWV,EAAEgB,SAASC,KAAK,cAG7DlB,KAAKmB,KAAK,CAAC,CACPC,WAAY,+BACZC,KAAM,CACFC,SAAUZ,aACVE,QAASA,QACTW,OAAQhB,MACRiB,MAAO,GACPC,mBAAmB,EACnBC,WAAW,MAEf,GAAGC,MAAK,SAASC,aACbC,SAAW,GACXC,eAAiB7B,EAAE,2BAA2BI,KAAK,oBAAoB0B,MAAM,YAGjF9B,EAAEc,KAAKa,SAAS,SAASZ,MAAOgB,UACxBC,IAAMD,KACNE,SAAW,GACXC,MAAO,EAEPrB,cAAcsB,mBAAqBJ,KAAKK,YACxCF,MAAO,GAEPrB,cAAcwB,qBAAuBN,KAAKK,YAC1CF,MAAO,GAEPrB,cAAcyB,wBAA0BP,KAAKQ,iBAC7CL,MAAO,GAEPrB,cAAc2B,0BAA4BT,KAAKU,mBAC/CP,MAAO,GAEPA,OACAlC,EAAEc,KAAKe,gBAAgB,SAASa,EAAGC,QACR,IAAZZ,KAAKY,IAAkC,KAAZZ,KAAKY,KACvCX,IAAIY,aAAc,EAClBX,SAASY,KAAKd,KAAKY,QAG3BX,IAAIC,SAAWA,SAASa,KAAK,MAC7BlB,SAASiB,KAAK5C,UAAU8C,OAAO,2CAA4Cf,KAAKN,MAAK,SAASsB,YACnF,CAACC,MAAOlB,KAAKmB,GAAIC,MAAOH,cAKpChD,EAAEoD,KAAKC,MAAMrD,EAAG4B,aACxBF,MAAK,eACA4B,MAAQ,GAGRC,UAAU,KAEVD,MAAQE,MAAMC,UAAUC,MAAMxC,KAAKqC,YAGvChD,QAAQ+C,UAETK,MAAMnD"} \ No newline at end of file diff --git a/mod/assign/amd/src/participant_selector.js b/mod/assign/amd/src/participant_selector.js index 001b71128d0..00026d2e8d7 100644 --- a/mod/assign/amd/src/participant_selector.js +++ b/mod/assign/amd/src/participant_selector.js @@ -16,7 +16,7 @@ /** * Custom auto-complete adapter to load users from the assignment list_participants webservice. * - * @module mod_assign/participants_selector + * @module mod_assign/participant_selector * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/bigbluebuttonbn/amd/build/modform.min.js b/mod/bigbluebuttonbn/amd/build/modform.min.js index 27700a54412..d90336f5202 100644 --- a/mod/bigbluebuttonbn/amd/build/modform.min.js +++ b/mod/bigbluebuttonbn/amd/build/modform.min.js @@ -2,7 +2,7 @@ define("mod_bigbluebuttonbn/modform",["exports","core/str","core/notification"," /** * JS for the mod_form page on mod_bigbluebuttonbn plugin. * - * @module mod_bigbluebuttonbn/mod_form + * @module mod_bigbluebuttonbn/modform * @copyright 2021 Blindside Networks Inc * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const ELEMENT_SELECTOR_instanceTypeSelection=()=>document.querySelector("select#id_type"),ELEMENT_SELECTOR_instanceTypeProfiles=()=>document.querySelector("[data-profile-types]"),ELEMENT_SELECTOR_participantData=()=>document.querySelector("[data-participant-data]"),ELEMENT_SELECTOR_participantList=()=>document.getElementsByName("participants")[0],ELEMENT_SELECTOR_participantTable=()=>document.getElementById("participant_list_table"),ELEMENT_SELECTOR_participantSelectionType=()=>document.getElementsByName("bigbluebuttonbn_participant_selection_type")[0],ELEMENT_SELECTOR_participantSelection=()=>document.getElementsByName("bigbluebuttonbn_participant_selection")[0],ELEMENT_SELECTOR_participantAddButton=()=>document.getElementsByName("bigbluebuttonbn_participant_selection_add")[0];_exports.init=info=>{const selectedType=ELEMENT_SELECTOR_instanceTypeSelection(),instanceTypeProfiles=JSON.parse(ELEMENT_SELECTOR_instanceTypeProfiles().dataset.profileTypes);let profileType=info.instanceTypeDefault;null!==selectedType&&-1!==selectedType.selectedIndex&&(profileType=selectedType.options[selectedType.selectedIndex].value);const isFeatureEnabled=(profileType,feature)=>-1!==instanceTypeProfiles[profileType].features.indexOf(feature);applyInstanceTypeProfile(profileType,isFeatureEnabled),selectedType.addEventListener("change",(e=>{applyInstanceTypeProfile(e.target.value,isFeatureEnabled)})),ELEMENT_SELECTOR_participantSelectionType().addEventListener("change",(e=>{const currentTypeSelect=e.target;updateSelectionFromType(currentTypeSelect)})),ELEMENT_SELECTOR_participantAddButton().addEventListener("click",(e=>{e.stopPropagation(),e.preventDefault(),participantAddFromCurrentSelection()})),participantListInit()};const applyInstanceTypeProfile=(profileType,isFeatureEnabled)=>{let showAll=isFeatureEnabled(profileType,"all");const showFieldset=(id,show)=>{const node=document.querySelector("#"+id);node&&(node.style.display=show?"block":"none")},showInput=(id,show)=>{const node=document.querySelector("#"+id);if(node){var ancestor=node.closest("div").closest("div");ancestor.style.display=show?"block":"none"}},showFormGroup=(id,show)=>{const node=document.querySelector("#fgroup_id_"+id);node&&(show?node.classList.remove("hidden"):node.classList.add("hidden"))};showFieldset("id_room",showAll||isFeatureEnabled(profileType,"showroom")),showInput("id_record",showAll||isFeatureEnabled(profileType,"showroom")),showFieldset("id_recordings",showAll||isFeatureEnabled(profileType,"showrecordings")),showInput("id_recordings_imported",showAll||isFeatureEnabled(profileType,"showrecordings")),showFieldset("id_lock",showAll||isFeatureEnabled(profileType,"lock")),showFieldset("id_guestaccess",showAll||isFeatureEnabled(profileType,"showroom")),showFieldset("id_preuploadpresentation",showAll||isFeatureEnabled(profileType,"preuploadpresentation")),showFieldset("id_permissions",showAll||isFeatureEnabled(profileType,"permissions")),showFieldset("id_schedule",showAll||isFeatureEnabled(profileType,"schedule")),showFieldset("id_modstandardelshdr",showAll||isFeatureEnabled(profileType,"modstandardelshdr")),showFieldset("id_availabilityconditionsheader",showAll||isFeatureEnabled(profileType,"availabilityconditionsheader")),showFieldset("id_tagshdr",showAll||isFeatureEnabled(profileType,"tagshdr")),showFieldset("id_competenciessection",showAll||isFeatureEnabled(profileType,"competenciessection")),showFormGroup("completionattendancegroup",showAll||isFeatureEnabled(profileType,"completionattendance")),showFormGroup("completionengagementgroup",showAll||isFeatureEnabled(profileType,"completionengagement"))},participantListInit=()=>{const participantData=JSON.parse(ELEMENT_SELECTOR_participantData().dataset.participantData);getParticipantList().forEach((participant=>{const selectionTypeValue=participant.selectiontype,selectionValue=participant.selectionid,selectionRole=participant.role;"all"!==participant.selectiontype&&void 0===participantData[participant.selectiontype].children[participant.selectionid]||participantAddToForm(selectionTypeValue,selectionValue,selectionRole,!0).then()}))},participantAddToForm=async(selectionTypeValue,selectionValue,selectedRole,canRemove)=>{const participantData=JSON.parse(ELEMENT_SELECTOR_participantData().dataset.participantData);let roles={viewer:{id:"viewer",label:await(0,_str.get_string)("mod_form_field_participant_bbb_role_viewer","mod_bigbluebuttonbn")},moderator:{id:"moderator",label:await(0,_str.get_string)("mod_form_field_participant_bbb_role_moderator","mod_bigbluebuttonbn")}};roles[selectedRole].isselected=!0;try{const listTable=document.querySelector("#participant_list_table tbody"),templateContext={selectiontypevalue:selectionTypeValue,selectionvalue:selectionValue,participanttype:participantData[selectionTypeValue].name,participantvalue:"all"!==selectionTypeValue?participantData[selectionTypeValue].children[selectionValue].name:null,roles:Object.values(roles),canRemove:canRemove},{html:html,js:js}=await _templates.default.renderForPromise("mod_bigbluebuttonbn/participant_form_add",templateContext),newNode=_templates.default.appendNodeContents(listTable,html,js)[0];newNode.querySelector(".participant-select").addEventListener("change",(()=>{participantListRoleUpdate(selectionTypeValue,selectionValue)}));const removeNode=newNode.querySelector(".remove-button");removeNode&&removeNode.addEventListener("click",(()=>{participantRemove(selectionTypeValue,selectionValue)}))}catch(e){_notification.default.exception(e)}},participantListUpdate=list=>{ELEMENT_SELECTOR_participantList().value=JSON.stringify(list)},getParticipantList=()=>{const participantListValue=ELEMENT_SELECTOR_participantList().value;return participantListValue?JSON.parse(participantListValue):[]},participantRemove=(selectionTypeValue,selectionValue)=>{const pList=getParticipantList(),id="participant_list_tr_"+selectionTypeValue+"-"+selectionValue,participantListTable=ELEMENT_SELECTOR_participantTable(),selectionid=""===selectionValue?null:selectionValue;for(let i=0;i{const participantListRoleSelection=document.querySelector("#participant_list_tr_".concat(type,"-").concat(id," .participant-select")),pList=getParticipantList();for(var i=0;i{let selectionType=ELEMENT_SELECTOR_participantSelectionType(),selection=ELEMENT_SELECTOR_participantSelection();const pList=getParticipantList();for(var i=0;i{const createNewOption=(selectItem,label,value)=>{const option=document.createElement("option");option.text=label,option.value=value,selectItem.add(option)},participantData=JSON.parse(ELEMENT_SELECTOR_participantData().dataset.participantData),participantSelect=ELEMENT_SELECTOR_participantSelection();for(;participantSelect.firstChild;)participantSelect.removeChild(participantSelect.firstChild);if(-1!==currentTypeSelect.selectedIndex){Object.values(participantData[currentTypeSelect.value].children).forEach((option=>{createNewOption(participantSelect,option.name,option.id)})),"all"===currentTypeSelect.value?(createNewOption(participantSelect,"---------------","all"),participantSelect.disabled=!0):participantSelect.disabled=!1}}})); diff --git a/mod/bigbluebuttonbn/amd/build/modform.min.js.map b/mod/bigbluebuttonbn/amd/build/modform.min.js.map index cdd5f83f49c..a233b57173b 100644 --- a/mod/bigbluebuttonbn/amd/build/modform.min.js.map +++ b/mod/bigbluebuttonbn/amd/build/modform.min.js.map @@ -1 +1 @@ -{"version":3,"file":"modform.min.js","sources":["../src/modform.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 * JS for the mod_form page on mod_bigbluebuttonbn plugin.\n *\n * @module mod_bigbluebuttonbn/mod_form\n * @copyright 2021 Blindside Networks Inc\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Templates from \"core/templates\";\n\n/**\n * Get all selectors in one place.\n *\n */\nconst ELEMENT_SELECTOR = {\n instanceTypeSelection: () => document.querySelector('select#id_type'),\n instanceTypeProfiles: () => document.querySelector('[data-profile-types]'),\n participantData: () => document.querySelector('[data-participant-data]'),\n participantList: () => document.getElementsByName('participants')[0],\n participantTable: () => document.getElementById('participant_list_table'),\n participantSelectionType: () => document.getElementsByName('bigbluebuttonbn_participant_selection_type')[0],\n participantSelection: () => document.getElementsByName('bigbluebuttonbn_participant_selection')[0],\n participantAddButton: () => document.getElementsByName('bigbluebuttonbn_participant_selection_add')[0],\n};\n/**\n * Initialise the moodle form code.\n *\n * This will help hide or show items depending on the selection of the instance type.\n *\n * @method init\n * @param {object} info\n */\nexport const init = (info) => {\n const selectedType = ELEMENT_SELECTOR.instanceTypeSelection();\n const instanceTypeProfiles = JSON.parse(ELEMENT_SELECTOR.instanceTypeProfiles().dataset.profileTypes);\n\n let profileType = info.instanceTypeDefault;\n if (selectedType !== null && selectedType.selectedIndex !== -1) {\n profileType = selectedType.options[selectedType.selectedIndex].value;\n }\n\n const isFeatureEnabled = (profileType, feature) => {\n const features = instanceTypeProfiles[profileType].features;\n return (features.indexOf(feature) !== -1);\n };\n applyInstanceTypeProfile(profileType, isFeatureEnabled);\n\n // Change form visible fields depending on the selection.\n selectedType.addEventListener('change', (e) => {\n applyInstanceTypeProfile(e.target.value, isFeatureEnabled);\n });\n\n ELEMENT_SELECTOR.participantSelectionType().addEventListener('change', (e) => {\n const currentTypeSelect = e.target;\n updateSelectionFromType(currentTypeSelect);\n });\n\n ELEMENT_SELECTOR.participantAddButton().addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n participantAddFromCurrentSelection();\n });\n\n participantListInit();\n};\n\n/**\n * Show or hide form element depending on the selected profile\n *\n * @param {string} profileType\n * @param {function} isFeatureEnabled\n */\nconst applyInstanceTypeProfile = (profileType, isFeatureEnabled) => {\n let showAll = isFeatureEnabled(profileType, 'all');\n const showFieldset = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#' + id);\n if (!node) {\n return;\n }\n if (show) {\n node.style.display = 'block';\n return;\n }\n node.style.display = 'none';\n };\n const showInput = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#' + id);\n if (!node) {\n return;\n }\n var ancestor = node.closest('div').closest('div');\n if (show) {\n ancestor.style.display = 'block';\n return;\n }\n ancestor.style.display = 'none';\n };\n const showFormGroup = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#fgroup_id_' + id);\n if (!node) {\n return;\n }\n if (show) {\n node.classList.remove('hidden');\n return;\n }\n node.classList.add('hidden');\n };\n // Show room settings validation.\n showFieldset('id_room', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n showInput('id_record', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n // Show recordings settings validation.\n showFieldset('id_recordings', showAll ||\n isFeatureEnabled(profileType, 'showrecordings'));\n // Show recordings imported settings validation.\n showInput('id_recordings_imported', showAll ||\n isFeatureEnabled(profileType, 'showrecordings'));\n // Show lock settings validation.\n showFieldset('id_lock', showAll ||\n isFeatureEnabled(profileType, 'lock'));\n // Show guest settings validation.\n showFieldset('id_guestaccess', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n // Preuploadpresentation feature validation.\n showFieldset('id_preuploadpresentation', showAll ||\n isFeatureEnabled(profileType, 'preuploadpresentation'));\n // Participants feature validation.\n showFieldset('id_permissions', showAll ||\n isFeatureEnabled(profileType, 'permissions'));\n // Schedule feature validation.\n showFieldset('id_schedule', showAll ||\n isFeatureEnabled(profileType, 'schedule'));\n // Common module settings validation.\n showFieldset('id_modstandardelshdr', showAll ||\n isFeatureEnabled(profileType, 'modstandardelshdr'));\n // Restrict access validation.\n showFieldset('id_availabilityconditionsheader', showAll ||\n isFeatureEnabled(profileType, 'availabilityconditionsheader'));\n // Tags validation.\n showFieldset('id_tagshdr', showAll || isFeatureEnabled(profileType, 'tagshdr'));\n // Competencies validation.\n showFieldset('id_competenciessection', showAll ||\n isFeatureEnabled(profileType, 'competenciessection'));\n // Completion validation.\n showFormGroup('completionattendancegroup', showAll ||\n isFeatureEnabled(profileType, 'completionattendance'));\n // Completion validation.\n showFormGroup('completionengagementgroup', showAll ||\n isFeatureEnabled(profileType, 'completionengagement'));\n};\n\n/**\n * Init the participant list\n */\nconst participantListInit = () => {\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n const participantList = getParticipantList();\n participantList.forEach(participant => {\n const selectionTypeValue = participant.selectiontype;\n const selectionValue = participant.selectionid;\n const selectionRole = participant.role;\n if (participant.selectiontype === 'all' ||\n typeof participantData[participant.selectiontype].children[participant.selectionid] !== 'undefined') {\n // Add it to the form, but don't add the delete button if it is the first item.\n participantAddToForm(selectionTypeValue, selectionValue, selectionRole, true).then();\n }\n });\n};\n\n/**\n * Add rows to the participant list depending on the current selection.\n *\n * @param {string} selectionTypeValue\n * @param {string} selectionValue\n * @param {string} selectedRole\n * @param {boolean} canRemove\n * @returns {Promise}\n */\nconst participantAddToForm = async(selectionTypeValue, selectionValue, selectedRole, canRemove) => {\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n const sviewer = await getString('mod_form_field_participant_bbb_role_viewer', 'mod_bigbluebuttonbn');\n const smoderator = await getString('mod_form_field_participant_bbb_role_moderator', 'mod_bigbluebuttonbn');\n let roles = {\n viewer: {'id': 'viewer', label: sviewer},\n moderator: {'id': 'moderator', label: smoderator}\n };\n roles[selectedRole].isselected = true;\n try {\n const listTable = document.querySelector('#participant_list_table tbody');\n const templateContext = {\n 'selectiontypevalue': selectionTypeValue,\n 'selectionvalue': selectionValue,\n 'participanttype': participantData[selectionTypeValue].name,\n 'participantvalue':\n (selectionTypeValue !== 'all') ?\n participantData[selectionTypeValue].children[selectionValue].name : null,\n 'roles': Object.values(roles),\n 'canRemove': canRemove\n };\n const {html, js} = await Templates.renderForPromise('mod_bigbluebuttonbn/participant_form_add', templateContext);\n const newNode = Templates.appendNodeContents(listTable, html, js)[0];\n newNode.querySelector('.participant-select').addEventListener('change', () => {\n participantListRoleUpdate(selectionTypeValue, selectionValue);\n });\n // Now add the callbacks: participantListRoleUpdate() and participantRemove().\n const removeNode = newNode.querySelector('.remove-button');\n if (removeNode) {\n removeNode\n .addEventListener('click', () => {\n participantRemove(selectionTypeValue, selectionValue);\n });\n }\n\n } catch (e) {\n Notification.exception(e);\n }\n};\n/*\n\n */\n\n/**\n * Update the related form element with the list value.\n *\n * @param {object} list\n */\nconst participantListUpdate = (list) => {\n const participantList = ELEMENT_SELECTOR.participantList();\n participantList.value = JSON.stringify(list);\n};\n\n/**\n *\n * @returns {any}\n */\nconst getParticipantList = () => {\n const participantListValue = ELEMENT_SELECTOR.participantList().value;\n if (participantListValue) {\n return JSON.parse(participantListValue);\n }\n return [];\n};\n\n/**\n * Remove participant both in the table/form and in the form element.\n *\n * @param {string} selectionTypeValue\n * @param {string} selectionValue\n */\nconst participantRemove = (selectionTypeValue, selectionValue) => {\n const pList = getParticipantList();\n const id = 'participant_list_tr_' + selectionTypeValue + '-' + selectionValue;\n const participantListTable = ELEMENT_SELECTOR.participantTable();\n const selectionid = (selectionValue === '' ? null : selectionValue);\n for (let i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === selectionTypeValue &&\n pList[i].selectionid === selectionid) {\n pList.splice(i, 1);\n }\n }\n // Remove from the form.\n for (let i = 0; i < participantListTable.rows.length; i++) {\n if (participantListTable.rows[i].id === id) {\n participantListTable.deleteRow(i);\n }\n }\n // Update value in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Role update\n *\n * @param {string} type\n * @param {string} id\n */\nconst participantListRoleUpdate = (type, id) => {\n // Update in memory.\n const participantListRoleSelection = document.querySelector(`#participant_list_tr_${type}-${id} .participant-select`);\n const pList = getParticipantList();\n\n for (var i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === type && pList[i].selectionid === id) {\n pList[i].role = participantListRoleSelection.value;\n }\n }\n // Update in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Add participant from the currently selected options\n */\nconst participantAddFromCurrentSelection = () => {\n let selectionType = ELEMENT_SELECTOR.participantSelectionType();\n let selection = ELEMENT_SELECTOR.participantSelection();\n const pList = getParticipantList();\n // Lookup to see if it has been added already.\n for (var i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === selectionType.value &&\n pList[i].selectionid === selection.value) {\n return;\n }\n }\n pList.push({\n \"selectiontype\": selectionType.value,\n \"selectionid\": selection.value,\n \"role\": \"viewer\"\n });\n // Add it to the form.\n participantAddToForm(selectionType.value, selection.value, 'viewer', true).then();\n // Update in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Update selectable options when changing types\n *\n * @param {HTMLNode} currentTypeSelect\n */\nconst updateSelectionFromType = (currentTypeSelect) => {\n const createNewOption = (selectItem, label, value) => {\n const option = document.createElement('option');\n option.text = label;\n option.value = value;\n\n selectItem.add(option);\n };\n\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n // Clear all selection items.\n const participantSelect = ELEMENT_SELECTOR.participantSelection();\n while (participantSelect.firstChild) {\n participantSelect.removeChild(participantSelect.firstChild);\n }\n // Add options depending on the selection.\n if (currentTypeSelect.selectedIndex !== -1) {\n const options = Object.values(participantData[currentTypeSelect.value].children);\n options.forEach(option => {\n createNewOption(participantSelect, option.name, option.id);\n });\n\n if (currentTypeSelect.value === 'all') {\n createNewOption(participantSelect, '---------------', 'all');\n participantSelect.disabled = true;\n } else {\n participantSelect.disabled = false;\n }\n }\n};\n"],"names":["ELEMENT_SELECTOR","document","querySelector","getElementsByName","getElementById","info","selectedType","instanceTypeProfiles","JSON","parse","dataset","profileTypes","profileType","instanceTypeDefault","selectedIndex","options","value","isFeatureEnabled","feature","features","indexOf","applyInstanceTypeProfile","addEventListener","e","target","currentTypeSelect","updateSelectionFromType","stopPropagation","preventDefault","participantAddFromCurrentSelection","participantListInit","showAll","showFieldset","id","show","node","style","display","showInput","ancestor","closest","showFormGroup","classList","remove","add","participantData","getParticipantList","forEach","participant","selectionTypeValue","selectiontype","selectionValue","selectionid","selectionRole","role","children","participantAddToForm","then","async","selectedRole","canRemove","roles","viewer","label","moderator","isselected","listTable","templateContext","name","Object","values","html","js","Templates","renderForPromise","newNode","appendNodeContents","participantListRoleUpdate","removeNode","participantRemove","exception","participantListUpdate","list","stringify","participantListValue","pList","participantListTable","i","length","splice","rows","deleteRow","type","participantListRoleSelection","selectionType","selection","push","createNewOption","selectItem","option","createElement","text","participantSelect","firstChild","removeChild","disabled"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"modform.min.js","sources":["../src/modform.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 * JS for the mod_form page on mod_bigbluebuttonbn plugin.\n *\n * @module mod_bigbluebuttonbn/modform\n * @copyright 2021 Blindside Networks Inc\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {get_string as getString} from 'core/str';\nimport Notification from 'core/notification';\nimport Templates from \"core/templates\";\n\n/**\n * Get all selectors in one place.\n *\n */\nconst ELEMENT_SELECTOR = {\n instanceTypeSelection: () => document.querySelector('select#id_type'),\n instanceTypeProfiles: () => document.querySelector('[data-profile-types]'),\n participantData: () => document.querySelector('[data-participant-data]'),\n participantList: () => document.getElementsByName('participants')[0],\n participantTable: () => document.getElementById('participant_list_table'),\n participantSelectionType: () => document.getElementsByName('bigbluebuttonbn_participant_selection_type')[0],\n participantSelection: () => document.getElementsByName('bigbluebuttonbn_participant_selection')[0],\n participantAddButton: () => document.getElementsByName('bigbluebuttonbn_participant_selection_add')[0],\n};\n/**\n * Initialise the moodle form code.\n *\n * This will help hide or show items depending on the selection of the instance type.\n *\n * @method init\n * @param {object} info\n */\nexport const init = (info) => {\n const selectedType = ELEMENT_SELECTOR.instanceTypeSelection();\n const instanceTypeProfiles = JSON.parse(ELEMENT_SELECTOR.instanceTypeProfiles().dataset.profileTypes);\n\n let profileType = info.instanceTypeDefault;\n if (selectedType !== null && selectedType.selectedIndex !== -1) {\n profileType = selectedType.options[selectedType.selectedIndex].value;\n }\n\n const isFeatureEnabled = (profileType, feature) => {\n const features = instanceTypeProfiles[profileType].features;\n return (features.indexOf(feature) !== -1);\n };\n applyInstanceTypeProfile(profileType, isFeatureEnabled);\n\n // Change form visible fields depending on the selection.\n selectedType.addEventListener('change', (e) => {\n applyInstanceTypeProfile(e.target.value, isFeatureEnabled);\n });\n\n ELEMENT_SELECTOR.participantSelectionType().addEventListener('change', (e) => {\n const currentTypeSelect = e.target;\n updateSelectionFromType(currentTypeSelect);\n });\n\n ELEMENT_SELECTOR.participantAddButton().addEventListener('click', (e) => {\n e.stopPropagation();\n e.preventDefault();\n participantAddFromCurrentSelection();\n });\n\n participantListInit();\n};\n\n/**\n * Show or hide form element depending on the selected profile\n *\n * @param {string} profileType\n * @param {function} isFeatureEnabled\n */\nconst applyInstanceTypeProfile = (profileType, isFeatureEnabled) => {\n let showAll = isFeatureEnabled(profileType, 'all');\n const showFieldset = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#' + id);\n if (!node) {\n return;\n }\n if (show) {\n node.style.display = 'block';\n return;\n }\n node.style.display = 'none';\n };\n const showInput = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#' + id);\n if (!node) {\n return;\n }\n var ancestor = node.closest('div').closest('div');\n if (show) {\n ancestor.style.display = 'block';\n return;\n }\n ancestor.style.display = 'none';\n };\n const showFormGroup = (id, show) => {\n // Show room settings validation.\n const node = document.querySelector('#fgroup_id_' + id);\n if (!node) {\n return;\n }\n if (show) {\n node.classList.remove('hidden');\n return;\n }\n node.classList.add('hidden');\n };\n // Show room settings validation.\n showFieldset('id_room', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n showInput('id_record', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n // Show recordings settings validation.\n showFieldset('id_recordings', showAll ||\n isFeatureEnabled(profileType, 'showrecordings'));\n // Show recordings imported settings validation.\n showInput('id_recordings_imported', showAll ||\n isFeatureEnabled(profileType, 'showrecordings'));\n // Show lock settings validation.\n showFieldset('id_lock', showAll ||\n isFeatureEnabled(profileType, 'lock'));\n // Show guest settings validation.\n showFieldset('id_guestaccess', showAll ||\n isFeatureEnabled(profileType, 'showroom'));\n // Preuploadpresentation feature validation.\n showFieldset('id_preuploadpresentation', showAll ||\n isFeatureEnabled(profileType, 'preuploadpresentation'));\n // Participants feature validation.\n showFieldset('id_permissions', showAll ||\n isFeatureEnabled(profileType, 'permissions'));\n // Schedule feature validation.\n showFieldset('id_schedule', showAll ||\n isFeatureEnabled(profileType, 'schedule'));\n // Common module settings validation.\n showFieldset('id_modstandardelshdr', showAll ||\n isFeatureEnabled(profileType, 'modstandardelshdr'));\n // Restrict access validation.\n showFieldset('id_availabilityconditionsheader', showAll ||\n isFeatureEnabled(profileType, 'availabilityconditionsheader'));\n // Tags validation.\n showFieldset('id_tagshdr', showAll || isFeatureEnabled(profileType, 'tagshdr'));\n // Competencies validation.\n showFieldset('id_competenciessection', showAll ||\n isFeatureEnabled(profileType, 'competenciessection'));\n // Completion validation.\n showFormGroup('completionattendancegroup', showAll ||\n isFeatureEnabled(profileType, 'completionattendance'));\n // Completion validation.\n showFormGroup('completionengagementgroup', showAll ||\n isFeatureEnabled(profileType, 'completionengagement'));\n};\n\n/**\n * Init the participant list\n */\nconst participantListInit = () => {\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n const participantList = getParticipantList();\n participantList.forEach(participant => {\n const selectionTypeValue = participant.selectiontype;\n const selectionValue = participant.selectionid;\n const selectionRole = participant.role;\n if (participant.selectiontype === 'all' ||\n typeof participantData[participant.selectiontype].children[participant.selectionid] !== 'undefined') {\n // Add it to the form, but don't add the delete button if it is the first item.\n participantAddToForm(selectionTypeValue, selectionValue, selectionRole, true).then();\n }\n });\n};\n\n/**\n * Add rows to the participant list depending on the current selection.\n *\n * @param {string} selectionTypeValue\n * @param {string} selectionValue\n * @param {string} selectedRole\n * @param {boolean} canRemove\n * @returns {Promise}\n */\nconst participantAddToForm = async(selectionTypeValue, selectionValue, selectedRole, canRemove) => {\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n const sviewer = await getString('mod_form_field_participant_bbb_role_viewer', 'mod_bigbluebuttonbn');\n const smoderator = await getString('mod_form_field_participant_bbb_role_moderator', 'mod_bigbluebuttonbn');\n let roles = {\n viewer: {'id': 'viewer', label: sviewer},\n moderator: {'id': 'moderator', label: smoderator}\n };\n roles[selectedRole].isselected = true;\n try {\n const listTable = document.querySelector('#participant_list_table tbody');\n const templateContext = {\n 'selectiontypevalue': selectionTypeValue,\n 'selectionvalue': selectionValue,\n 'participanttype': participantData[selectionTypeValue].name,\n 'participantvalue':\n (selectionTypeValue !== 'all') ?\n participantData[selectionTypeValue].children[selectionValue].name : null,\n 'roles': Object.values(roles),\n 'canRemove': canRemove\n };\n const {html, js} = await Templates.renderForPromise('mod_bigbluebuttonbn/participant_form_add', templateContext);\n const newNode = Templates.appendNodeContents(listTable, html, js)[0];\n newNode.querySelector('.participant-select').addEventListener('change', () => {\n participantListRoleUpdate(selectionTypeValue, selectionValue);\n });\n // Now add the callbacks: participantListRoleUpdate() and participantRemove().\n const removeNode = newNode.querySelector('.remove-button');\n if (removeNode) {\n removeNode\n .addEventListener('click', () => {\n participantRemove(selectionTypeValue, selectionValue);\n });\n }\n\n } catch (e) {\n Notification.exception(e);\n }\n};\n/*\n\n */\n\n/**\n * Update the related form element with the list value.\n *\n * @param {object} list\n */\nconst participantListUpdate = (list) => {\n const participantList = ELEMENT_SELECTOR.participantList();\n participantList.value = JSON.stringify(list);\n};\n\n/**\n *\n * @returns {any}\n */\nconst getParticipantList = () => {\n const participantListValue = ELEMENT_SELECTOR.participantList().value;\n if (participantListValue) {\n return JSON.parse(participantListValue);\n }\n return [];\n};\n\n/**\n * Remove participant both in the table/form and in the form element.\n *\n * @param {string} selectionTypeValue\n * @param {string} selectionValue\n */\nconst participantRemove = (selectionTypeValue, selectionValue) => {\n const pList = getParticipantList();\n const id = 'participant_list_tr_' + selectionTypeValue + '-' + selectionValue;\n const participantListTable = ELEMENT_SELECTOR.participantTable();\n const selectionid = (selectionValue === '' ? null : selectionValue);\n for (let i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === selectionTypeValue &&\n pList[i].selectionid === selectionid) {\n pList.splice(i, 1);\n }\n }\n // Remove from the form.\n for (let i = 0; i < participantListTable.rows.length; i++) {\n if (participantListTable.rows[i].id === id) {\n participantListTable.deleteRow(i);\n }\n }\n // Update value in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Role update\n *\n * @param {string} type\n * @param {string} id\n */\nconst participantListRoleUpdate = (type, id) => {\n // Update in memory.\n const participantListRoleSelection = document.querySelector(`#participant_list_tr_${type}-${id} .participant-select`);\n const pList = getParticipantList();\n\n for (var i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === type && pList[i].selectionid === id) {\n pList[i].role = participantListRoleSelection.value;\n }\n }\n // Update in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Add participant from the currently selected options\n */\nconst participantAddFromCurrentSelection = () => {\n let selectionType = ELEMENT_SELECTOR.participantSelectionType();\n let selection = ELEMENT_SELECTOR.participantSelection();\n const pList = getParticipantList();\n // Lookup to see if it has been added already.\n for (var i = 0; i < pList.length; i++) {\n if (pList[i].selectiontype === selectionType.value &&\n pList[i].selectionid === selection.value) {\n return;\n }\n }\n pList.push({\n \"selectiontype\": selectionType.value,\n \"selectionid\": selection.value,\n \"role\": \"viewer\"\n });\n // Add it to the form.\n participantAddToForm(selectionType.value, selection.value, 'viewer', true).then();\n // Update in the form.\n participantListUpdate(pList);\n};\n\n/**\n * Update selectable options when changing types\n *\n * @param {HTMLNode} currentTypeSelect\n */\nconst updateSelectionFromType = (currentTypeSelect) => {\n const createNewOption = (selectItem, label, value) => {\n const option = document.createElement('option');\n option.text = label;\n option.value = value;\n\n selectItem.add(option);\n };\n\n const participantData = JSON.parse(ELEMENT_SELECTOR.participantData().dataset.participantData);\n // Clear all selection items.\n const participantSelect = ELEMENT_SELECTOR.participantSelection();\n while (participantSelect.firstChild) {\n participantSelect.removeChild(participantSelect.firstChild);\n }\n // Add options depending on the selection.\n if (currentTypeSelect.selectedIndex !== -1) {\n const options = Object.values(participantData[currentTypeSelect.value].children);\n options.forEach(option => {\n createNewOption(participantSelect, option.name, option.id);\n });\n\n if (currentTypeSelect.value === 'all') {\n createNewOption(participantSelect, '---------------', 'all');\n participantSelect.disabled = true;\n } else {\n participantSelect.disabled = false;\n }\n }\n};\n"],"names":["ELEMENT_SELECTOR","document","querySelector","getElementsByName","getElementById","info","selectedType","instanceTypeProfiles","JSON","parse","dataset","profileTypes","profileType","instanceTypeDefault","selectedIndex","options","value","isFeatureEnabled","feature","features","indexOf","applyInstanceTypeProfile","addEventListener","e","target","currentTypeSelect","updateSelectionFromType","stopPropagation","preventDefault","participantAddFromCurrentSelection","participantListInit","showAll","showFieldset","id","show","node","style","display","showInput","ancestor","closest","showFormGroup","classList","remove","add","participantData","getParticipantList","forEach","participant","selectionTypeValue","selectiontype","selectionValue","selectionid","selectionRole","role","children","participantAddToForm","then","async","selectedRole","canRemove","roles","viewer","label","moderator","isselected","listTable","templateContext","name","Object","values","html","js","Templates","renderForPromise","newNode","appendNodeContents","participantListRoleUpdate","removeNode","participantRemove","exception","participantListUpdate","list","stringify","participantListValue","pList","participantListTable","i","length","splice","rows","deleteRow","type","participantListRoleSelection","selectionType","selection","push","createNewOption","selectItem","option","createElement","text","participantSelect","firstChild","removeChild","disabled"],"mappings":"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"} \ No newline at end of file diff --git a/mod/bigbluebuttonbn/amd/src/modform.js b/mod/bigbluebuttonbn/amd/src/modform.js index b669f8b97a0..c1a6c9f23cd 100644 --- a/mod/bigbluebuttonbn/amd/src/modform.js +++ b/mod/bigbluebuttonbn/amd/src/modform.js @@ -16,7 +16,7 @@ /** * JS for the mod_form page on mod_bigbluebuttonbn plugin. * - * @module mod_bigbluebuttonbn/mod_form + * @module mod_bigbluebuttonbn/modform * @copyright 2021 Blindside Networks Inc * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/data/amd/build/importpresets.min.js b/mod/data/amd/build/importpresets.min.js index 9933ac2d3e0..52ec0f77bc7 100644 --- a/mod/data/amd/build/importpresets.min.js +++ b/mod/data/amd/build/importpresets.min.js @@ -2,7 +2,7 @@ define("mod_data/importpresets",["exports","core_form/modalform","core/notificat /** * Javascript module for importing presets. * - * @module mod_data/importpreset + * @module mod_data/importpresets * @copyright 2022 Laurent David * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_modalform=_interopRequireDefault(_modalform),_notification=_interopRequireDefault(_notification);const selectors_importPresetButton='[data-action="importpresets"]';_exports.init=()=>{document.addEventListener("click",(event=>{const importPresetButton=event.target.closest(selectors_importPresetButton);if(!importPresetButton)return;event.preventDefault();const modalForm=new _modalform.default({modalConfig:{title:(0,_str.get_string)("importpreset","mod_data")},formClass:"mod_data\\form\\import_presets",args:{cmid:importPresetButton.dataset.dataid},saveButtonText:(0,_str.get_string)("importandapply","mod_data")});modalForm.addEventListener(modalForm.events.FORM_SUBMITTED,(event=>{event.detail.result?window.location.assign(event.detail.url):_notification.default.addNotification({type:"error",message:event.detail.errors.join("
")})})),modalForm.show()}))}})); diff --git a/mod/data/amd/build/importpresets.min.js.map b/mod/data/amd/build/importpresets.min.js.map index 80143082774..01c94d2db23 100644 --- a/mod/data/amd/build/importpresets.min.js.map +++ b/mod/data/amd/build/importpresets.min.js.map @@ -1 +1 @@ -{"version":3,"file":"importpresets.min.js","sources":["../src/importpresets.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 * Javascript module for importing presets.\n *\n * @module mod_data/importpreset\n * @copyright 2022 Laurent David \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\nconst selectors = {\n importPresetButton: '[data-action=\"importpresets\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n document.addEventListener('click', (event) => {\n const importPresetButton = event.target.closest(selectors.importPresetButton);\n\n if (!importPresetButton) {\n return;\n }\n\n event.preventDefault();\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('importpreset', 'mod_data'),\n },\n formClass: 'mod_data\\\\form\\\\import_presets',\n args: {cmid: importPresetButton.dataset.dataid},\n saveButtonText: getString('importandapply', 'mod_data'),\n });\n\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n window.location.assign(event.detail.url);\n } else {\n Notification.addNotification({\n type: 'error',\n message: event.detail.errors.join('
')\n });\n }\n });\n modalForm.show();\n });\n};\n"],"names":["selectors","document","addEventListener","event","importPresetButton","target","closest","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","args","cmid","dataset","dataid","saveButtonText","events","FORM_SUBMITTED","detail","result","window","location","assign","url","addNotification","type","message","errors","join","show"],"mappings":";;;;;;;0LA2BMA,6BACkB,8CAMJ,KAChBC,SAASC,iBAAiB,SAAUC,cAC1BC,mBAAqBD,MAAME,OAAOC,QAAQN,kCAE3CI,0BAILD,MAAMI,uBACAC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,OAAO,mBAAU,eAAgB,aAErCC,UAAW,iCACXC,KAAM,CAACC,KAAMV,mBAAmBW,QAAQC,QACxCC,gBAAgB,mBAAU,iBAAkB,cAGhDT,UAAUN,iBAAiBM,UAAUU,OAAOC,gBAAgBhB,QACpDA,MAAMiB,OAAOC,OACbC,OAAOC,SAASC,OAAOrB,MAAMiB,OAAOK,2BAEvBC,gBAAgB,CACzBC,KAAM,QACNC,QAASzB,MAAMiB,OAAOS,OAAOC,KAAK,aAI9CtB,UAAUuB"} \ No newline at end of file +{"version":3,"file":"importpresets.min.js","sources":["../src/importpresets.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 * Javascript module for importing presets.\n *\n * @module mod_data/importpresets\n * @copyright 2022 Laurent David \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\n\nconst selectors = {\n importPresetButton: '[data-action=\"importpresets\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n document.addEventListener('click', (event) => {\n const importPresetButton = event.target.closest(selectors.importPresetButton);\n\n if (!importPresetButton) {\n return;\n }\n\n event.preventDefault();\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('importpreset', 'mod_data'),\n },\n formClass: 'mod_data\\\\form\\\\import_presets',\n args: {cmid: importPresetButton.dataset.dataid},\n saveButtonText: getString('importandapply', 'mod_data'),\n });\n\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n window.location.assign(event.detail.url);\n } else {\n Notification.addNotification({\n type: 'error',\n message: event.detail.errors.join('
')\n });\n }\n });\n modalForm.show();\n });\n};\n"],"names":["selectors","document","addEventListener","event","importPresetButton","target","closest","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","args","cmid","dataset","dataid","saveButtonText","events","FORM_SUBMITTED","detail","result","window","location","assign","url","addNotification","type","message","errors","join","show"],"mappings":";;;;;;;0LA2BMA,6BACkB,8CAMJ,KAChBC,SAASC,iBAAiB,SAAUC,cAC1BC,mBAAqBD,MAAME,OAAOC,QAAQN,kCAE3CI,0BAILD,MAAMI,uBACAC,UAAY,IAAIC,mBAAU,CAC5BC,YAAa,CACTC,OAAO,mBAAU,eAAgB,aAErCC,UAAW,iCACXC,KAAM,CAACC,KAAMV,mBAAmBW,QAAQC,QACxCC,gBAAgB,mBAAU,iBAAkB,cAGhDT,UAAUN,iBAAiBM,UAAUU,OAAOC,gBAAgBhB,QACpDA,MAAMiB,OAAOC,OACbC,OAAOC,SAASC,OAAOrB,MAAMiB,OAAOK,2BAEvBC,gBAAgB,CACzBC,KAAM,QACNC,QAASzB,MAAMiB,OAAOS,OAAOC,KAAK,aAI9CtB,UAAUuB"} \ No newline at end of file diff --git a/mod/data/amd/src/importpresets.js b/mod/data/amd/src/importpresets.js index 2c57a259e19..6d5716128bb 100644 --- a/mod/data/amd/src/importpresets.js +++ b/mod/data/amd/src/importpresets.js @@ -16,7 +16,7 @@ /** * Javascript module for importing presets. * - * @module mod_data/importpreset + * @module mod_data/importpresets * @copyright 2022 Laurent David * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/forum/amd/build/discussion.min.js b/mod/forum/amd/build/discussion.min.js index 1d372cc6168..473c25e0e60 100644 --- a/mod/forum/amd/build/discussion.min.js +++ b/mod/forum/amd/build/discussion.min.js @@ -1,7 +1,7 @@ /** * Module for viewing a discussion. * - * @module mod_forum/discussion_list + * @module mod_forum/discussion * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/forum/amd/build/discussion.min.js.map b/mod/forum/amd/build/discussion.min.js.map index 704eb56d576..7268d817776 100644 --- a/mod/forum/amd/build/discussion.min.js.map +++ b/mod/forum/amd/build/discussion.min.js.map @@ -1 +1 @@ -{"version":3,"file":"discussion.min.js","sources":["../src/discussion.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 * Module for viewing a discussion.\n *\n * @module mod_forum/discussion_list\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'mod_forum/selectors',\n 'core/pubsub',\n 'mod_forum/forum_events',\n 'core/str',\n 'core/notification',\n],\nfunction(\n $,\n CustomEvents,\n Selectors,\n PubSub,\n ForumEvents,\n String,\n Notification\n) {\n\n /**\n * Set the focus on the previous post in the list. Previous post is calculated\n * based on position in list as viewed top to bottom.\n *\n * @param {Object} currentPost The post that currently has focus\n */\n var focusPreviousPost = function(currentPost) {\n // See if there is a previous sibling post.\n var prevPost = currentPost.prev(Selectors.post.post);\n\n if (prevPost.length) {\n // The previous post might have replies that appear visually between\n // it and the current post (see nested view) so if that's the case\n // then the last reply will be the previous post in the list.\n var replyPost = prevPost.find(Selectors.post.post).last();\n\n if (replyPost.length) {\n // Focus the last reply.\n replyPost.focus();\n } else {\n // No replies so we can focus straight on the sibling.\n prevPost.focus();\n }\n } else {\n // If there are no siblings then jump up the tree to the parent\n // post and focus the first parent post we find.\n currentPost.parents(Selectors.post.post).first().focus();\n }\n };\n\n /**\n * Set the focus on the next post in the list. Previous post is calculated\n * based on position in list as viewed top to bottom.\n *\n * @param {Object} currentPost The post that currently has focus\n */\n var focusNextPost = function(currentPost) {\n // The next post in the visual list would be the first reply to this one\n // so let's see if we have one.\n var replyPost = currentPost.find(Selectors.post.post).first();\n\n if (replyPost.length) {\n // Got a reply.\n replyPost.focus();\n } else {\n // If we don't have a reply then the next post in the visual list would\n // be a sibling post (replying to the same parent).\n var siblingPost = currentPost.next(Selectors.post.post);\n\n if (siblingPost.length) {\n siblingPost.focus();\n } else {\n // No siblings either. That means we're the lowest level reply in a thread\n // so we need to walk back up the tree of posts and find an ancestor post that\n // has a sibling post we can focus.\n var parentPosts = currentPost.parents(Selectors.post.post).toArray();\n\n for (var i = 0; i < parentPosts.length; i++) {\n var ancestorSiblingPost = $(parentPosts[i]).next(Selectors.post.post);\n\n if (ancestorSiblingPost.length) {\n ancestorSiblingPost.focus();\n break;\n }\n }\n }\n }\n };\n\n /**\n * Check if the element is inside the in page reply section.\n *\n * @param {Object} element The element to check\n * @return {Boolean}\n */\n var isElementInInPageReplySection = function(element) {\n var inPageReply = $(element).closest(Selectors.post.inpageReplyContent);\n return inPageReply.length ? true : false;\n };\n\n /**\n * Initialise the keyboard accessibility controls for the discussion.\n *\n * @param {Object} root The discussion root element\n */\n var initAccessibilityKeyboardNav = function(root) {\n var posts = root.find(Selectors.post.post);\n\n // Take each post action out of the tab index.\n posts.each(function(index, post) {\n var actions = $(post).find(Selectors.post.action);\n var firstAction = actions.first();\n actions.attr('tabindex', '-1');\n firstAction.attr('tabindex', 0);\n });\n\n CustomEvents.define(root, [\n CustomEvents.events.up,\n CustomEvents.events.down,\n CustomEvents.events.next,\n CustomEvents.events.previous,\n CustomEvents.events.home,\n CustomEvents.events.end,\n ]);\n\n root.on(CustomEvents.events.up, function(e, data) {\n var activeElement = document.activeElement;\n\n if (isElementInInPageReplySection(activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n\n var focusPost = $(activeElement).closest(Selectors.post.post);\n\n if (focusPost.length) {\n focusPreviousPost(focusPost);\n } else {\n root.find(Selectors.post.post).first().focus();\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.down, function(e, data) {\n var activeElement = document.activeElement;\n\n if (isElementInInPageReplySection(activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n\n var focusPost = $(activeElement).closest(Selectors.post.post);\n\n if (focusPost.length) {\n focusNextPost(focusPost);\n } else {\n root.find(Selectors.post.post).first().focus();\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.home, function(e, data) {\n if (isElementInInPageReplySection(document.activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n root.find(Selectors.post.post).first().focus();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.end, function(e, data) {\n if (isElementInInPageReplySection(document.activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n root.find(Selectors.post.post).last().focus();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.next, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var nextAction = currentAction.next(Selectors.post.action);\n\n actions.attr('tabindex', '-1');\n\n if (!nextAction.length) {\n nextAction = actions.first();\n }\n\n nextAction.attr('tabindex', 0);\n nextAction.focus();\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.previous, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var nextAction = currentAction.prev(Selectors.post.action);\n\n actions.attr('tabindex', '-1');\n\n if (!nextAction.length) {\n nextAction = actions.last();\n }\n\n nextAction.attr('tabindex', 0);\n nextAction.focus();\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.home, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var firstAction = actions.first();\n\n actions.attr('tabindex', '-1');\n firstAction.attr('tabindex', 0);\n firstAction.focus();\n\n e.stopPropagation();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.end, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var lastAction = actions.last();\n\n actions.attr('tabindex', '-1');\n lastAction.attr('tabindex', 0);\n lastAction.focus();\n\n e.stopPropagation();\n data.originalEvent.preventDefault();\n });\n\n PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) {\n var subscribed = data.subscriptionState;\n var updateMessage = subscribed ? 'discussionsubscribed' : 'discussionunsubscribed';\n String.get_string(updateMessage, \"forum\")\n .then(function(s) {\n return Notification.addNotification({\n message: s,\n type: \"info\"\n });\n })\n .catch(Notification.exception);\n });\n };\n\n return {\n init: function(root) {\n initAccessibilityKeyboardNav(root);\n }\n };\n});\n"],"names":["define","$","CustomEvents","Selectors","PubSub","ForumEvents","String","Notification","isElementInInPageReplySection","element","closest","post","inpageReplyContent","length","initAccessibilityKeyboardNav","root","find","each","index","actions","action","firstAction","first","attr","events","up","down","next","previous","home","end","on","e","data","activeElement","document","focusPost","currentPost","prevPost","prev","replyPost","last","focus","parents","focusPreviousPost","originalEvent","preventDefault","siblingPost","parentPosts","toArray","i","ancestorSiblingPost","focusNextPost","currentAction","target","actionsContainer","nextAction","stopPropagation","lastAction","subscribe","SUBSCRIPTION_TOGGLED","updateMessage","subscriptionState","get_string","then","s","addNotification","message","type","catch","exception","init"],"mappings":";;;;;;;AAsBAA,8BACA,CACI,SACA,iCACA,sBACA,cACA,yBACA,WACA,sBAEJ,SACIC,EACAC,aACAC,UACAC,OACAC,YACAC,OACAC,kBA8EIC,8BAAgC,SAASC,iBACvBR,EAAEQ,SAASC,QAAQP,UAAUQ,KAAKC,oBACjCC,QAQnBC,6BAA+B,SAASC,MAC5BA,KAAKC,KAAKb,UAAUQ,KAAKA,MAG/BM,MAAK,SAASC,MAAOP,UACnBQ,QAAUlB,EAAEU,MAAMK,KAAKb,UAAUQ,KAAKS,QACtCC,YAAcF,QAAQG,QAC1BH,QAAQI,KAAK,WAAY,MACzBF,YAAYE,KAAK,WAAY,MAGjCrB,aAAaF,OAAOe,KAAM,CACtBb,aAAasB,OAAOC,GACpBvB,aAAasB,OAAOE,KACpBxB,aAAasB,OAAOG,KACpBzB,aAAasB,OAAOI,SACpB1B,aAAasB,OAAOK,KACpB3B,aAAasB,OAAOM,MAGxBf,KAAKgB,GAAG7B,aAAasB,OAAOC,IAAI,SAASO,EAAGC,UACpCC,cAAgBC,SAASD,kBAEzB1B,8BAA8B0B,oBAM9BE,UAAYnC,EAAEiC,eAAexB,QAAQP,UAAUQ,KAAKA,MAEpDyB,UAAUvB,OA9GE,SAASwB,iBAEzBC,SAAWD,YAAYE,KAAKpC,UAAUQ,KAAKA,SAE3C2B,SAASzB,OAAQ,KAIb2B,UAAYF,SAAStB,KAAKb,UAAUQ,KAAKA,MAAM8B,OAE/CD,UAAU3B,OAEV2B,UAAUE,QAGVJ,SAASI,aAKbL,YAAYM,QAAQxC,UAAUQ,KAAKA,MAAMW,QAAQoB,QA2F7CE,CAAkBR,WAElBrB,KAAKC,KAAKb,UAAUQ,KAAKA,MAAMW,QAAQoB,QAG3CT,KAAKY,cAAcC,qBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOE,MAAM,SAASM,EAAGC,UACtCC,cAAgBC,SAASD,kBAEzB1B,8BAA8B0B,oBAM9BE,UAAYnC,EAAEiC,eAAexB,QAAQP,UAAUQ,KAAKA,MAEpDyB,UAAUvB,OApGF,SAASwB,iBAGrBG,UAAYH,YAAYrB,KAAKb,UAAUQ,KAAKA,MAAMW,WAElDkB,UAAU3B,OAEV2B,UAAUE,YACP,KAGCK,YAAcV,YAAYV,KAAKxB,UAAUQ,KAAKA,SAE9CoC,YAAYlC,OACZkC,YAAYL,qBAKRM,YAAcX,YAAYM,QAAQxC,UAAUQ,KAAKA,MAAMsC,UAElDC,EAAI,EAAGA,EAAIF,YAAYnC,OAAQqC,IAAK,KACrCC,oBAAsBlD,EAAE+C,YAAYE,IAAIvB,KAAKxB,UAAUQ,KAAKA,SAE5DwC,oBAAoBtC,OAAQ,CAC5BsC,oBAAoBT,iBA4E5BU,CAAchB,WAEdrB,KAAKC,KAAKb,UAAUQ,KAAKA,MAAMW,QAAQoB,QAG3CT,KAAKY,cAAcC,qBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOK,MAAM,SAASG,EAAGC,MACtCzB,8BAA8B2B,SAASD,iBAK3CnB,KAAKC,KAAKb,UAAUQ,KAAKA,MAAMW,QAAQoB,QACvCT,KAAKY,cAAcC,qBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOM,KAAK,SAASE,EAAGC,MACrCzB,8BAA8B2B,SAASD,iBAK3CnB,KAAKC,KAAKb,UAAUQ,KAAKA,MAAM8B,OAAOC,QACtCT,KAAKY,cAAcC,qBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOG,KAAMxB,UAAUQ,KAAKS,QAAQ,SAASY,EAAGC,UAC7DoB,cAAgBpD,EAAE+B,EAAEsB,QAEpBnC,QADYkC,cAAc3C,QAAQP,UAAUQ,KAAK4C,kBAC7BvC,KAAKb,UAAUQ,KAAKS,QACxCoC,WAAaH,cAAc1B,KAAKxB,UAAUQ,KAAKS,QAEnDD,QAAQI,KAAK,WAAY,MAEpBiC,WAAW3C,SACZ2C,WAAarC,QAAQG,SAGzBkC,WAAWjC,KAAK,WAAY,GAC5BiC,WAAWd,QAEXT,KAAKY,cAAcC,oBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOI,SAAUzB,UAAUQ,KAAKS,QAAQ,SAASY,EAAGC,UACjEoB,cAAgBpD,EAAE+B,EAAEsB,QAEpBnC,QADYkC,cAAc3C,QAAQP,UAAUQ,KAAK4C,kBAC7BvC,KAAKb,UAAUQ,KAAKS,QACxCoC,WAAaH,cAAcd,KAAKpC,UAAUQ,KAAKS,QAEnDD,QAAQI,KAAK,WAAY,MAEpBiC,WAAW3C,SACZ2C,WAAarC,QAAQsB,QAGzBe,WAAWjC,KAAK,WAAY,GAC5BiC,WAAWd,QAEXT,KAAKY,cAAcC,oBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOK,KAAM1B,UAAUQ,KAAKS,QAAQ,SAASY,EAAGC,UAG7Dd,QAFgBlB,EAAE+B,EAAEsB,QACM5C,QAAQP,UAAUQ,KAAK4C,kBAC7BvC,KAAKb,UAAUQ,KAAKS,QACxCC,YAAcF,QAAQG,QAE1BH,QAAQI,KAAK,WAAY,MACzBF,YAAYE,KAAK,WAAY,GAC7BF,YAAYqB,QAEZV,EAAEyB,kBACFxB,KAAKY,cAAcC,oBAGvB/B,KAAKgB,GAAG7B,aAAasB,OAAOM,IAAK3B,UAAUQ,KAAKS,QAAQ,SAASY,EAAGC,UAG5Dd,QAFgBlB,EAAE+B,EAAEsB,QACM5C,QAAQP,UAAUQ,KAAK4C,kBAC7BvC,KAAKb,UAAUQ,KAAKS,QACxCsC,WAAavC,QAAQsB,OAEzBtB,QAAQI,KAAK,WAAY,MACzBmC,WAAWnC,KAAK,WAAY,GAC5BmC,WAAWhB,QAEXV,EAAEyB,kBACFxB,KAAKY,cAAcC,oBAGvB1C,OAAOuD,UAAUtD,YAAYuD,sBAAsB,SAAS3B,UAEpD4B,cADa5B,KAAK6B,kBACW,uBAAyB,yBAC1DxD,OAAOyD,WAAWF,cAAe,SAC5BG,MAAK,SAASC,UACJ1D,aAAa2D,gBAAgB,CAChCC,QAASF,EACTG,KAAM,YAGbC,MAAM9D,aAAa+D,qBAIzB,CACHC,KAAM,SAASxD,MACXD,6BAA6BC"} \ No newline at end of file +{"version":3,"file":"discussion.min.js","sources":["../src/discussion.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 * Module for viewing a discussion.\n *\n * @module mod_forum/discussion\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'mod_forum/selectors',\n 'core/pubsub',\n 'mod_forum/forum_events',\n 'core/str',\n 'core/notification',\n],\nfunction(\n $,\n CustomEvents,\n Selectors,\n PubSub,\n ForumEvents,\n String,\n Notification\n) {\n\n /**\n * Set the focus on the previous post in the list. Previous post is calculated\n * based on position in list as viewed top to bottom.\n *\n * @param {Object} currentPost The post that currently has focus\n */\n var focusPreviousPost = function(currentPost) {\n // See if there is a previous sibling post.\n var prevPost = currentPost.prev(Selectors.post.post);\n\n if (prevPost.length) {\n // The previous post might have replies that appear visually between\n // it and the current post (see nested view) so if that's the case\n // then the last reply will be the previous post in the list.\n var replyPost = prevPost.find(Selectors.post.post).last();\n\n if (replyPost.length) {\n // Focus the last reply.\n replyPost.focus();\n } else {\n // No replies so we can focus straight on the sibling.\n prevPost.focus();\n }\n } else {\n // If there are no siblings then jump up the tree to the parent\n // post and focus the first parent post we find.\n currentPost.parents(Selectors.post.post).first().focus();\n }\n };\n\n /**\n * Set the focus on the next post in the list. Previous post is calculated\n * based on position in list as viewed top to bottom.\n *\n * @param {Object} currentPost The post that currently has focus\n */\n var focusNextPost = function(currentPost) {\n // The next post in the visual list would be the first reply to this one\n // so let's see if we have one.\n var replyPost = currentPost.find(Selectors.post.post).first();\n\n if (replyPost.length) {\n // Got a reply.\n replyPost.focus();\n } else {\n // If we don't have a reply then the next post in the visual list would\n // be a sibling post (replying to the same parent).\n var siblingPost = currentPost.next(Selectors.post.post);\n\n if (siblingPost.length) {\n siblingPost.focus();\n } else {\n // No siblings either. That means we're the lowest level reply in a thread\n // so we need to walk back up the tree of posts and find an ancestor post that\n // has a sibling post we can focus.\n var parentPosts = currentPost.parents(Selectors.post.post).toArray();\n\n for (var i = 0; i < parentPosts.length; i++) {\n var ancestorSiblingPost = $(parentPosts[i]).next(Selectors.post.post);\n\n if (ancestorSiblingPost.length) {\n ancestorSiblingPost.focus();\n break;\n }\n }\n }\n }\n };\n\n /**\n * Check if the element is inside the in page reply section.\n *\n * @param {Object} element The element to check\n * @return {Boolean}\n */\n var isElementInInPageReplySection = function(element) {\n var inPageReply = $(element).closest(Selectors.post.inpageReplyContent);\n return inPageReply.length ? true : false;\n };\n\n /**\n * Initialise the keyboard accessibility controls for the discussion.\n *\n * @param {Object} root The discussion root element\n */\n var initAccessibilityKeyboardNav = function(root) {\n var posts = root.find(Selectors.post.post);\n\n // Take each post action out of the tab index.\n posts.each(function(index, post) {\n var actions = $(post).find(Selectors.post.action);\n var firstAction = actions.first();\n actions.attr('tabindex', '-1');\n firstAction.attr('tabindex', 0);\n });\n\n CustomEvents.define(root, [\n CustomEvents.events.up,\n CustomEvents.events.down,\n CustomEvents.events.next,\n CustomEvents.events.previous,\n CustomEvents.events.home,\n CustomEvents.events.end,\n ]);\n\n root.on(CustomEvents.events.up, function(e, data) {\n var activeElement = document.activeElement;\n\n if (isElementInInPageReplySection(activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n\n var focusPost = $(activeElement).closest(Selectors.post.post);\n\n if (focusPost.length) {\n focusPreviousPost(focusPost);\n } else {\n root.find(Selectors.post.post).first().focus();\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.down, function(e, data) {\n var activeElement = document.activeElement;\n\n if (isElementInInPageReplySection(activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n\n var focusPost = $(activeElement).closest(Selectors.post.post);\n\n if (focusPost.length) {\n focusNextPost(focusPost);\n } else {\n root.find(Selectors.post.post).first().focus();\n }\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.home, function(e, data) {\n if (isElementInInPageReplySection(document.activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n root.find(Selectors.post.post).first().focus();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.end, function(e, data) {\n if (isElementInInPageReplySection(document.activeElement)) {\n // Focus is currently inside the in page reply section so don't move focus\n // to another post.\n return;\n }\n root.find(Selectors.post.post).last().focus();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.next, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var nextAction = currentAction.next(Selectors.post.action);\n\n actions.attr('tabindex', '-1');\n\n if (!nextAction.length) {\n nextAction = actions.first();\n }\n\n nextAction.attr('tabindex', 0);\n nextAction.focus();\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.previous, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var nextAction = currentAction.prev(Selectors.post.action);\n\n actions.attr('tabindex', '-1');\n\n if (!nextAction.length) {\n nextAction = actions.last();\n }\n\n nextAction.attr('tabindex', 0);\n nextAction.focus();\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.home, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var firstAction = actions.first();\n\n actions.attr('tabindex', '-1');\n firstAction.attr('tabindex', 0);\n firstAction.focus();\n\n e.stopPropagation();\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.end, Selectors.post.action, function(e, data) {\n var currentAction = $(e.target);\n var container = currentAction.closest(Selectors.post.actionsContainer);\n var actions = container.find(Selectors.post.action);\n var lastAction = actions.last();\n\n actions.attr('tabindex', '-1');\n lastAction.attr('tabindex', 0);\n lastAction.focus();\n\n e.stopPropagation();\n data.originalEvent.preventDefault();\n });\n\n PubSub.subscribe(ForumEvents.SUBSCRIPTION_TOGGLED, function(data) {\n var subscribed = data.subscriptionState;\n var updateMessage = subscribed ? 'discussionsubscribed' : 'discussionunsubscribed';\n String.get_string(updateMessage, \"forum\")\n .then(function(s) {\n return Notification.addNotification({\n message: s,\n type: \"info\"\n });\n })\n .catch(Notification.exception);\n });\n };\n\n return {\n init: function(root) {\n initAccessibilityKeyboardNav(root);\n }\n };\n});\n"],"names":["define","$","CustomEvents","Selectors","PubSub","ForumEvents","String","Notification","isElementInInPageReplySection","element","closest","post","inpageReplyContent","length","initAccessibilityKeyboardNav","root","find","each","index","actions","action","firstAction","first","attr","events","up","down","next","previous","home","end","on","e","data","activeElement","document","focusPost","currentPost","prevPost","prev","replyPost","last","focus","parents","focusPreviousPost","originalEvent","preventDefault","siblingPost","parentPosts","toArray","i","ancestorSiblingPost","focusNextPost","currentAction","target","actionsContainer","nextAction","stopPropagation","lastAction","subscribe","SUBSCRIPTION_TOGGLED","updateMessage","subscriptionState","get_string","then","s","addNotification","message","type","catch","exception","init"],"mappings":"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"} \ No newline at end of file diff --git a/mod/forum/amd/build/discussion_nested_v2.min.js b/mod/forum/amd/build/discussion_nested_v2.min.js index 399da95c84a..83094998365 100644 --- a/mod/forum/amd/build/discussion_nested_v2.min.js +++ b/mod/forum/amd/build/discussion_nested_v2.min.js @@ -2,7 +2,7 @@ define("mod_forum/discussion_nested_v2",["exports","jquery","core/auto_rows","co /** * Module for viewing a discussion in nested v2 view. * - * @module mod_Forum/discussion_nested_v2 + * @module mod_forum/discussion_nested_v2 * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_auto_rows=_interopRequireDefault(_auto_rows),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),FormChangeChecker=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}(FormChangeChecker),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates),_discussion=_interopRequireDefault(_discussion),_inpage_reply=_interopRequireDefault(_inpage_reply),_lock_toggle=_interopRequireDefault(_lock_toggle),_favourite_toggle=_interopRequireDefault(_favourite_toggle),_pin_toggle=_interopRequireDefault(_pin_toggle),_selectors=_interopRequireDefault(_selectors),_subscription_toggle=_interopRequireDefault(_subscription_toggle);const getPostContainer=element=>element.closest(_selectors.default.post.post),getPostContainerById=(element,id)=>element.find("".concat(_selectors.default.post.post,"[data-post-id=").concat(id,"]")),getPostContentContainer=postContainer=>postContainer.children().not(_selectors.default.post.repliesContainer).find(_selectors.default.post.forumCoreContent),getInPageReplyContainer=postContainer=>postContainer.children().filter(_selectors.default.post.inpageReplyContainer),getInPageReplyForm=postContainer=>getInPageReplyContainer(postContainer).find(_selectors.default.post.inpageReplyContent),getInPageReplyCreateButton=postContainer=>getPostContentContainer(postContainer).find(_selectors.default.post.inpageReplyCreateButton),getRepliesVisibilityToggleContainer=postContainer=>postContainer.children(_selectors.default.post.repliesVisibilityToggleContainer),getRepliesContainer=postContainer=>postContainer.children(_selectors.default.post.repliesContainer),hasReplies=postContainer=>getRepliesContainer(postContainer).children().length>0,getShowRepliesButton=replyVisibilityToggleContainer=>replyVisibilityToggleContainer.find(_selectors.default.post.showReplies),getHideRepliesButton=replyVisibilityToggleContainer=>replyVisibilityToggleContainer.find(_selectors.default.post.hideReplies),repliesVisible=postContainer=>getRepliesContainer(postContainer).is(":visible"),showReplies=function(postContainer){let postIdToSee=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const repliesContainer=getRepliesContainer(postContainer),replyVisibilityToggleContainer=getRepliesVisibilityToggleContainer(postContainer),showButton=getShowRepliesButton(replyVisibilityToggleContainer),hideButton=getHideRepliesButton(replyVisibilityToggleContainer);showButton.addClass("hidden"),hideButton.removeClass("hidden"),repliesContainer.slideDown({duration:150,queue:!1,complete:()=>{if(postIdToSee){const postContainerToSee=getPostContainerById(repliesContainer,postIdToSee);postContainerToSee.length&&postContainerToSee[0].scrollIntoView()}}}).css("display","none").fadeIn(150)},hideReplies=postContainer=>{const repliesContainer=getRepliesContainer(postContainer),replyVisibilityToggleContainer=getRepliesVisibilityToggleContainer(postContainer),showButton=getShowRepliesButton(replyVisibilityToggleContainer),hideButton=getHideRepliesButton(replyVisibilityToggleContainer);showButton.removeClass("hidden"),hideButton.addClass("hidden"),repliesContainer.slideUp({duration:150,queue:!1}).fadeOut(150)};let showInPageReplyForm=null;const hideInPageReplyForm=function(postContainer){let postIdToSee=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;const inPageReplyForm=getInPageReplyForm(postContainer),inPageReplyCreateButton=getInPageReplyCreateButton(postContainer),repliesVisibilityToggleContainer=getRepliesVisibilityToggleContainer(postContainer);repliesVisibilityToggleContainer.length&&hasReplies(postContainer)&&(repliesVisibilityToggleContainer.fadeOut(150),repliesVisible(postContainer)||showReplies(postContainer,postIdToSee)),inPageReplyForm.slideUp({duration:150,queue:!1,complete:()=>{inPageReplyCreateButton.fadeIn(150)}}).fadeOut(200)},hasInPageReplyForm=inPageReplyContainer=>inPageReplyContainer.find(_selectors.default.post.inpageReplyContent).length>0,renderInPageReplyTemplate=(additionalTemplateContext,button,postContainer)=>{const postContentContainer=getPostContentContainer(postContainer),currentSubject=postContentContainer.find(_selectors.default.post.forumSubject).text(),currentAuthorName=postContentContainer.find(_selectors.default.post.authorName).text(),context={postid:postContainer.data("post-id"),reply_url:button.attr("data-href"),sesskey:M.cfg.sesskey,parentsubject:currentSubject,parentauthorname:currentAuthorName,canreplyprivately:button.data("can-reply-privately"),postformat:_inpage_reply.default.CONTENT_FORMATS.MOODLE,...additionalTemplateContext};return _templates.default.render("mod_forum/inpage_reply_v2",context)},registerEventListeners=root=>{_custom_interaction_events.default.define(root,[_custom_interaction_events.default.events.activate]),_auto_rows.default.init(root),root.on(_custom_interaction_events.default.events.activate,_selectors.default.post.inpageReplyCreateButton,((e,data)=>{data.originalEvent.preventDefault();const postContainer=getPostContainer((0,_jquery.default)(e.currentTarget));showInPageReplyForm(postContainer)})),root.on(_custom_interaction_events.default.events.activate,_selectors.default.post.inpageReplyCancelButton,((e,data)=>{data.originalEvent.preventDefault();const postContainer=getPostContainer((0,_jquery.default)(e.currentTarget));hideInPageReplyForm(postContainer)})),root.on(_custom_interaction_events.default.events.activate,_selectors.default.post.showReplies,((e,data)=>{data.originalEvent.preventDefault();const postContainer=getPostContainer((0,_jquery.default)(e.target));showReplies(postContainer)})),root.on(_custom_interaction_events.default.events.activate,_selectors.default.post.hideReplies,((e,data)=>{data.originalEvent.preventDefault();const postContainer=getPostContainer((0,_jquery.default)(e.target));hideReplies(postContainer)})),root.on(_inpage_reply.default.EVENTS.POST_CREATED,_selectors.default.post.inpageSubmitBtn,((e,newPostId)=>{const currentTarget=(0,_jquery.default)(e.currentTarget),postContainer=getPostContainer(currentTarget),postContainers=currentTarget.parents(_selectors.default.post.post);hideInPageReplyForm(postContainer,newPostId),postContainers.each(((index,container)=>{(postContainer=>{getRepliesVisibilityToggleContainer(postContainer).find(_selectors.default.post.replyCount).each(((index,element)=>{const currentCount=parseInt(element.innerText,10);element.innerText=currentCount+1}))})((0,_jquery.default)(container))}))}))};_exports.init=(root,context)=>{var additionalTemplateContext;additionalTemplateContext=context,showInPageReplyForm=async postContainer=>{const inPageReplyContainer=getInPageReplyContainer(postContainer),repliesVisibilityToggleContainer=getRepliesVisibilityToggleContainer(postContainer),inPageReplyCreateButton=getInPageReplyCreateButton(postContainer);if(!hasInPageReplyForm(inPageReplyContainer)){try{const html=await renderInPageReplyTemplate(additionalTemplateContext,inPageReplyCreateButton,postContainer);_templates.default.appendNodeContents(inPageReplyContainer,html,"")}catch(e){_notification.default.exception(e)}FormChangeChecker.watchForm(postContainer[0].querySelector("form"))}inPageReplyCreateButton.fadeOut(150,(()=>{const inPageReplyForm=getInPageReplyForm(postContainer);inPageReplyForm.slideDown({duration:150,queue:!1,complete:()=>{inPageReplyForm.find("textarea").focus()}}).css("display","none").fadeIn(150),repliesVisibilityToggleContainer.length&&hasReplies(postContainer)&&(repliesVisibilityToggleContainer.fadeIn(150),hideReplies(postContainer))}))},registerEventListeners(root),_discussion.default.init(root),_inpage_reply.default.init(root);const discussionToolsContainer=root.find(_selectors.default.discussion.tools);_lock_toggle.default.init(discussionToolsContainer,!1),_favourite_toggle.default.init(discussionToolsContainer,!1,((toggleElement,response)=>{const newTargetState=response.userstate.favourited?0:1;return toggleElement.data("targetstate",newTargetState)})),_pin_toggle.default.init(discussionToolsContainer,!1,((toggleElement,response)=>{const newTargetState=response.pinned?0:1;return toggleElement.data("targetstate",newTargetState)})),_subscription_toggle.default.init(discussionToolsContainer,!1,((toggleElement,response)=>{const newTargetState=response.userstate.subscribed?0:1;toggleElement.data("targetstate",newTargetState)}))}})); diff --git a/mod/forum/amd/build/discussion_nested_v2.min.js.map b/mod/forum/amd/build/discussion_nested_v2.min.js.map index 2e1e85508d3..5245f2f1d76 100644 --- a/mod/forum/amd/build/discussion_nested_v2.min.js.map +++ b/mod/forum/amd/build/discussion_nested_v2.min.js.map @@ -1 +1 @@ -{"version":3,"file":"discussion_nested_v2.min.js","sources":["../src/discussion_nested_v2.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 * Module for viewing a discussion in nested v2 view.\n *\n * @module mod_Forum/discussion_nested_v2\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport AutoRows from 'core/auto_rows';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as FormChangeChecker from 'core_form/changechecker';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport Discussion from 'mod_forum/discussion';\nimport InPageReply from 'mod_forum/inpage_reply';\nimport LockToggle from 'mod_forum/lock_toggle';\nimport FavouriteToggle from 'mod_forum/favourite_toggle';\nimport Pin from 'mod_forum/pin_toggle';\nimport Selectors from 'mod_forum/selectors';\nimport Subscribe from 'mod_forum/subscription_toggle';\n\nconst ANIMATION_DURATION = 150;\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getPostContainer = (element) => {\n return element.closest(Selectors.post.post);\n};\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @param {Number} id Id of the post to find.\n * @return {Object} jQuery element\n */\nconst getPostContainerById = (element, id) => {\n return element.find(`${Selectors.post.post}[data-post-id=${id}]`);\n};\n\n/**\n * Get the parent post container elements from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getParentPostContainers = (element) => {\n return element.parents(Selectors.post.post);\n};\n\n/**\n * Get the post content container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getPostContentContainer = (postContainer) => {\n return postContainer.children().not(Selectors.post.repliesContainer).find(Selectors.post.forumCoreContent);\n};\n\n/**\n * Get the in page reply container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyContainer = (postContainer) => {\n return postContainer.children().filter(Selectors.post.inpageReplyContainer);\n};\n\n/**\n * Get the in page reply form element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyForm = (postContainer) => {\n return getInPageReplyContainer(postContainer).find(Selectors.post.inpageReplyContent);\n};\n\n/**\n * Get the in page reply create (reply) button element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyCreateButton = (postContainer) => {\n return getPostContentContainer(postContainer).find(Selectors.post.inpageReplyCreateButton);\n};\n\n/**\n * Get the replies visibility toggle container (show/hide replies button container) element\n * from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesVisibilityToggleContainer = (postContainer) => {\n return postContainer.children(Selectors.post.repliesVisibilityToggleContainer);\n};\n\n/**\n * Get the replies container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesContainer = (postContainer) => {\n return postContainer.children(Selectors.post.repliesContainer);\n};\n\n/**\n * Check if the post has any replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst hasReplies = (postContainer) => {\n return getRepliesContainer(postContainer).children().length > 0;\n};\n\n/**\n * Get the show replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getShowRepliesButton = (replyVisibilityToggleContainer) => {\n return replyVisibilityToggleContainer.find(Selectors.post.showReplies);\n};\n\n/**\n * Get the hide replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getHideRepliesButton = (replyVisibilityToggleContainer) => {\n return replyVisibilityToggleContainer.find(Selectors.post.hideReplies);\n};\n\n/**\n * Check if the replies are visible.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst repliesVisible = (postContainer) => {\n const repliesContainer = getRepliesContainer(postContainer);\n return repliesContainer.is(':visible');\n};\n\n/**\n * Show the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst showReplies = (postContainer, postIdToSee = null) => {\n const repliesContainer = getRepliesContainer(postContainer);\n const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n showButton.addClass('hidden');\n hideButton.removeClass('hidden');\n\n repliesContainer.slideDown({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n if (postIdToSee) {\n const postContainerToSee = getPostContainerById(repliesContainer, postIdToSee);\n if (postContainerToSee.length) {\n postContainerToSee[0].scrollIntoView();\n }\n }\n }\n }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n};\n\n/**\n * Hide the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst hideReplies = (postContainer) => {\n const repliesContainer = getRepliesContainer(postContainer);\n const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n showButton.removeClass('hidden');\n hideButton.addClass('hidden');\n\n repliesContainer.slideUp({\n duration: ANIMATION_DURATION,\n queue: false\n }).fadeOut(ANIMATION_DURATION);\n};\n\n/** Variable to hold the showInPageReplyForm function after it's built. */\nlet showInPageReplyForm = null;\n\n/**\n * Build the showInPageReplyForm function with the given additional template context.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template.\n * @return {Function}\n */\nconst buildShowInPageReplyFormFunction = (additionalTemplateContext) => {\n /**\n * Show the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\n return async(postContainer) => {\n\n const inPageReplyContainer = getInPageReplyContainer(postContainer);\n const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n\n if (!hasInPageReplyForm(inPageReplyContainer)) {\n try {\n const html = await renderInPageReplyTemplate(additionalTemplateContext, inPageReplyCreateButton, postContainer);\n Templates.appendNodeContents(inPageReplyContainer, html, '');\n } catch (e) {\n Notification.exception(e);\n }\n\n FormChangeChecker.watchForm(postContainer[0].querySelector('form'));\n }\n\n inPageReplyCreateButton.fadeOut(ANIMATION_DURATION, () => {\n const inPageReplyForm = getInPageReplyForm(postContainer);\n inPageReplyForm.slideDown({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n inPageReplyForm.find('textarea').focus();\n }\n }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n\n if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n repliesVisibilityToggleContainer.fadeIn(ANIMATION_DURATION);\n hideReplies(postContainer);\n }\n });\n };\n};\n\n/**\n * Hide the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst hideInPageReplyForm = (postContainer, postIdToSee = null) => {\n const inPageReplyForm = getInPageReplyForm(postContainer);\n const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n\n if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n repliesVisibilityToggleContainer.fadeOut(ANIMATION_DURATION);\n if (!repliesVisible(postContainer)) {\n showReplies(postContainer, postIdToSee);\n }\n }\n\n inPageReplyForm.slideUp({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n inPageReplyCreateButton.fadeIn(ANIMATION_DURATION);\n }\n }).fadeOut(200);\n};\n\n/**\n * Check if the in page reply container contains the in page reply form.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @return {Bool}\n */\nconst hasInPageReplyForm = (inPageReplyContainer) => {\n return inPageReplyContainer.find(Selectors.post.inpageReplyContent).length > 0;\n};\n\n/**\n * Render the template to generate the in page reply form HTML.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template\n * @param {Object} button jQuery element for the reply button that was clicked\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery promise\n */\nconst renderInPageReplyTemplate = (additionalTemplateContext, button, postContainer) => {\n const postContentContainer = getPostContentContainer(postContainer);\n const currentSubject = postContentContainer.find(Selectors.post.forumSubject).text();\n const currentAuthorName = postContentContainer.find(Selectors.post.authorName).text();\n const context = {\n postid: postContainer.data('post-id'),\n \"reply_url\": button.attr('data-href'),\n sesskey: M.cfg.sesskey,\n parentsubject: currentSubject,\n parentauthorname: currentAuthorName,\n canreplyprivately: button.data('can-reply-privately'),\n postformat: InPageReply.CONTENT_FORMATS.MOODLE,\n ...additionalTemplateContext\n };\n\n return Templates.render('mod_forum/inpage_reply_v2', context);\n};\n\n/**\n * Increment the total reply count in the show/hide replies buttons for the post.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst incrementTotalReplyCount = (postContainer) => {\n getRepliesVisibilityToggleContainer(postContainer).find(Selectors.post.replyCount).each((index, element) => {\n const currentCount = parseInt(element.innerText, 10);\n element.innerText = currentCount + 1;\n });\n};\n\n/**\n * Create all of the event listeners for the discussion.\n *\n * @param {Object} root jQuery element for the discussion container\n */\nconst registerEventListeners = (root) => {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Auto expanding text area for in page reply.\n AutoRows.init(root);\n\n // Reply button is clicked.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCreateButton, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.currentTarget));\n showInPageReplyForm(postContainer);\n });\n\n // Cancel in page reply button.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCancelButton, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.currentTarget));\n hideInPageReplyForm(postContainer);\n });\n\n // Show replies button clicked.\n root.on(CustomEvents.events.activate, Selectors.post.showReplies, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.target));\n showReplies(postContainer);\n });\n\n // Hide replies button clicked.\n root.on(CustomEvents.events.activate, Selectors.post.hideReplies, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.target));\n hideReplies(postContainer);\n });\n\n // Post created with in page reply.\n root.on(InPageReply.EVENTS.POST_CREATED, Selectors.post.inpageSubmitBtn, (e, newPostId) => {\n const currentTarget = $(e.currentTarget);\n const postContainer = getPostContainer(currentTarget);\n const postContainers = getParentPostContainers(currentTarget);\n hideInPageReplyForm(postContainer, newPostId);\n\n postContainers.each((index, container) => {\n incrementTotalReplyCount($(container));\n });\n });\n};\n\n/**\n * Initialise the javascript for the discussion in nested v2 display mode.\n *\n * @param {Object} root jQuery element for the discussion container\n * @param {Object} context Additional render context for the in page reply template\n */\nexport const init = (root, context) => {\n // Build the showInPageReplyForm function with the additional render context.\n showInPageReplyForm = buildShowInPageReplyFormFunction(context);\n // Add discussion event listeners.\n registerEventListeners(root);\n // Initialise default discussion javascript (keyboard nav etc).\n Discussion.init(root);\n // Add in page reply javascript.\n InPageReply.init(root);\n\n // Initialise the settings menu javascript.\n const discussionToolsContainer = root.find(Selectors.discussion.tools);\n LockToggle.init(discussionToolsContainer, false);\n FavouriteToggle.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.userstate.favourited ? 0 : 1;\n return toggleElement.data('targetstate', newTargetState);\n });\n Pin.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.pinned ? 0 : 1;\n return toggleElement.data('targetstate', newTargetState);\n });\n Subscribe.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.userstate.subscribed ? 0 : 1;\n toggleElement.data('targetstate', newTargetState);\n });\n};\n"],"names":["getPostContainer","element","closest","Selectors","post","getPostContainerById","id","find","getPostContentContainer","postContainer","children","not","repliesContainer","forumCoreContent","getInPageReplyContainer","filter","inpageReplyContainer","getInPageReplyForm","inpageReplyContent","getInPageReplyCreateButton","inpageReplyCreateButton","getRepliesVisibilityToggleContainer","repliesVisibilityToggleContainer","getRepliesContainer","hasReplies","length","getShowRepliesButton","replyVisibilityToggleContainer","showReplies","getHideRepliesButton","hideReplies","repliesVisible","is","postIdToSee","showButton","hideButton","addClass","removeClass","slideDown","duration","queue","complete","postContainerToSee","scrollIntoView","css","fadeIn","slideUp","fadeOut","showInPageReplyForm","hideInPageReplyForm","inPageReplyForm","inPageReplyCreateButton","hasInPageReplyForm","inPageReplyContainer","renderInPageReplyTemplate","additionalTemplateContext","button","postContentContainer","currentSubject","forumSubject","text","currentAuthorName","authorName","context","postid","data","attr","sesskey","M","cfg","parentsubject","parentauthorname","canreplyprivately","postformat","InPageReply","CONTENT_FORMATS","MOODLE","Templates","render","registerEventListeners","root","define","CustomEvents","events","activate","init","on","e","originalEvent","preventDefault","currentTarget","inpageReplyCancelButton","target","EVENTS","POST_CREATED","inpageSubmitBtn","newPostId","postContainers","parents","each","index","container","replyCount","currentCount","parseInt","innerText","incrementTotalReplyCount","async","html","appendNodeContents","exception","FormChangeChecker","watchForm","querySelector","focus","discussionToolsContainer","discussion","tools","toggleElement","response","newTargetState","userstate","favourited","pinned","subscribed"],"mappings":";;;;;;;k4CA4CMA,iBAAoBC,SACfA,QAAQC,QAAQC,mBAAUC,KAAKA,MAUpCC,qBAAuB,CAACJ,QAASK,KAC5BL,QAAQM,eAAQJ,mBAAUC,KAAKA,8BAAqBE,SAmBzDE,wBAA2BC,eACtBA,cAAcC,WAAWC,IAAIR,mBAAUC,KAAKQ,kBAAkBL,KAAKJ,mBAAUC,KAAKS,kBASvFC,wBAA2BL,eACtBA,cAAcC,WAAWK,OAAOZ,mBAAUC,KAAKY,sBASpDC,mBAAsBR,eACjBK,wBAAwBL,eAAeF,KAAKJ,mBAAUC,KAAKc,oBAShEC,2BAA8BV,eACzBD,wBAAwBC,eAAeF,KAAKJ,mBAAUC,KAAKgB,yBAUhEC,oCAAuCZ,eAClCA,cAAcC,SAASP,mBAAUC,KAAKkB,kCAS3CC,oBAAuBd,eAClBA,cAAcC,SAASP,mBAAUC,KAAKQ,kBAS3CY,WAAcf,eACTc,oBAAoBd,eAAeC,WAAWe,OAAS,EAS5DC,qBAAwBC,gCACnBA,+BAA+BpB,KAAKJ,mBAAUC,KAAKwB,aASxDC,qBAAwBF,gCACnBA,+BAA+BpB,KAAKJ,mBAAUC,KAAK0B,aASxDC,eAAkBtB,eACKc,oBAAoBd,eACrBuB,GAAG,YASzBJ,YAAc,SAACnB,mBAAewB,mEAAc,WACxCrB,iBAAmBW,oBAAoBd,eACvCkB,+BAAiCN,oCAAoCZ,eACrEyB,WAAaR,qBAAqBC,gCAClCQ,WAAaN,qBAAqBF,gCAExCO,WAAWE,SAAS,UACpBD,WAAWE,YAAY,UAEvBzB,iBAAiB0B,UAAU,CACvBC,SAvJmB,IAwJnBC,OAAO,EACPC,SAAU,QACFR,YAAa,OACPS,mBAAqBrC,qBAAqBO,iBAAkBqB,aAC9DS,mBAAmBjB,QACnBiB,mBAAmB,GAAGC,qBAInCC,IAAI,UAAW,QAAQC,OAjKH,MAyKrBf,YAAerB,sBACXG,iBAAmBW,oBAAoBd,eACvCkB,+BAAiCN,oCAAoCZ,eACrEyB,WAAaR,qBAAqBC,gCAClCQ,WAAaN,qBAAqBF,gCAExCO,WAAWG,YAAY,UACvBF,WAAWC,SAAS,UAEpBxB,iBAAiBkC,QAAQ,CACrBP,SAnLmB,IAoLnBC,OAAO,IACRO,QArLoB,UAyLvBC,oBAAsB,WAyDpBC,oBAAsB,SAACxC,mBAAewB,mEAAc,WAChDiB,gBAAkBjC,mBAAmBR,eACrC0C,wBAA0BhC,2BAA2BV,eACrDa,iCAAmCD,oCAAoCZ,eAEzEa,iCAAiCG,QAAUD,WAAWf,iBACtDa,iCAAiCyB,QAxPd,KAyPdhB,eAAetB,gBAChBmB,YAAYnB,cAAewB,cAInCiB,gBAAgBJ,QAAQ,CACpBP,SA/PmB,IAgQnBC,OAAO,EACPC,SAAU,KACNU,wBAAwBN,OAlQT,QAoQpBE,QAAQ,MASTK,mBAAsBC,sBACjBA,qBAAqB9C,KAAKJ,mBAAUC,KAAKc,oBAAoBO,OAAS,EAW3E6B,0BAA4B,CAACC,0BAA2BC,OAAQ/C,uBAC5DgD,qBAAuBjD,wBAAwBC,eAC/CiD,eAAiBD,qBAAqBlD,KAAKJ,mBAAUC,KAAKuD,cAAcC,OACxEC,kBAAoBJ,qBAAqBlD,KAAKJ,mBAAUC,KAAK0D,YAAYF,OACzEG,QAAU,CACZC,OAAQvD,cAAcwD,KAAK,qBACdT,OAAOU,KAAK,aACzBC,QAASC,EAAEC,IAAIF,QACfG,cAAeZ,eACfa,iBAAkBV,kBAClBW,kBAAmBhB,OAAOS,KAAK,uBAC/BQ,WAAYC,sBAAYC,gBAAgBC,UACrCrB,kCAGAsB,mBAAUC,OAAO,4BAA6Bf,UAoBnDgB,uBAA0BC,0CACfC,OAAOD,KAAM,CAACE,mCAAaC,OAAOC,8BAEtCC,KAAKL,MAGdA,KAAKM,GAAGJ,mCAAaC,OAAOC,SAAUjF,mBAAUC,KAAKgB,yBAAyB,CAACmE,EAAGtB,QAC9EA,KAAKuB,cAAcC,uBACbhF,cAAgBT,kBAAiB,mBAAEuF,EAAEG,gBAC3C1C,oBAAoBvC,kBAIxBuE,KAAKM,GAAGJ,mCAAaC,OAAOC,SAAUjF,mBAAUC,KAAKuF,yBAAyB,CAACJ,EAAGtB,QAC9EA,KAAKuB,cAAcC,uBACbhF,cAAgBT,kBAAiB,mBAAEuF,EAAEG,gBAC3CzC,oBAAoBxC,kBAIxBuE,KAAKM,GAAGJ,mCAAaC,OAAOC,SAAUjF,mBAAUC,KAAKwB,aAAa,CAAC2D,EAAGtB,QAClEA,KAAKuB,cAAcC,uBACbhF,cAAgBT,kBAAiB,mBAAEuF,EAAEK,SAC3ChE,YAAYnB,kBAIhBuE,KAAKM,GAAGJ,mCAAaC,OAAOC,SAAUjF,mBAAUC,KAAK0B,aAAa,CAACyD,EAAGtB,QAClEA,KAAKuB,cAAcC,uBACbhF,cAAgBT,kBAAiB,mBAAEuF,EAAEK,SAC3C9D,YAAYrB,kBAIhBuE,KAAKM,GAAGZ,sBAAYmB,OAAOC,aAAc3F,mBAAUC,KAAK2F,iBAAiB,CAACR,EAAGS,mBACnEN,eAAgB,mBAAEH,EAAEG,eACpBjF,cAAgBT,iBAAiB0F,eACjCO,eAAyCP,cAnUpCQ,QAAQ/F,mBAAUC,KAAKA,MAoUlC6C,oBAAoBxC,cAAeuF,WAEnCC,eAAeE,MAAK,CAACC,MAAOC,aApDF5F,CAAAA,gBAC9BY,oCAAoCZ,eAAeF,KAAKJ,mBAAUC,KAAKkG,YAAYH,MAAK,CAACC,MAAOnG,iBACtFsG,aAAeC,SAASvG,QAAQwG,UAAW,IACjDxG,QAAQwG,UAAYF,aAAe,MAkD/BG,EAAyB,mBAAEL,iCAWnB,CAACrB,KAAMjB,WA/KeR,IAAAA,0BAAAA,0BAiLiBQ,QAAvDf,oBA1KO2D,MAAAA,sBAEGtD,qBAAuBvC,wBAAwBL,eAC/Ca,iCAAmCD,oCAAoCZ,eACvE0C,wBAA0BhC,2BAA2BV,mBAEtD2C,mBAAmBC,sBAAuB,WAEjCuD,WAAatD,0BAA0BC,0BAA2BJ,wBAAyB1C,kCACvFoG,mBAAmBxD,qBAAsBuD,KAAM,IAC3D,MAAOrB,yBACQuB,UAAUvB,GAG3BwB,kBAAkBC,UAAUvG,cAAc,GAAGwG,cAAc,SAG/D9D,wBAAwBJ,QAzNL,KAyNiC,WAC1CG,gBAAkBjC,mBAAmBR,eAC3CyC,gBAAgBZ,UAAU,CACtBC,SA5NW,IA6NXC,OAAO,EACPC,SAAU,KACNS,gBAAgB3C,KAAK,YAAY2G,WAEtCtE,IAAI,UAAW,QAAQC,OAjOX,KAmOXvB,iCAAiCG,QAAUD,WAAWf,iBACtDa,iCAAiCuB,OApOtB,KAqOXf,YAAYrB,oBA+IxBsE,uBAAuBC,0BAEZK,KAAKL,4BAEJK,KAAKL,YAGXmC,yBAA2BnC,KAAKzE,KAAKJ,mBAAUiH,WAAWC,4BACrDhC,KAAK8B,0BAA0B,6BAC1B9B,KAAK8B,0BAA0B,GAAO,CAACG,cAAeC,kBAC5DC,eAAiBD,SAASE,UAAUC,WAAa,EAAI,SACpDJ,cAAcrD,KAAK,cAAeuD,uCAEzCnC,KAAK8B,0BAA0B,GAAO,CAACG,cAAeC,kBAChDC,eAAiBD,SAASI,OAAS,EAAI,SACtCL,cAAcrD,KAAK,cAAeuD,gDAEnCnC,KAAK8B,0BAA0B,GAAO,CAACG,cAAeC,kBACtDC,eAAiBD,SAASE,UAAUG,WAAa,EAAI,EAC3DN,cAAcrD,KAAK,cAAeuD"} \ No newline at end of file +{"version":3,"file":"discussion_nested_v2.min.js","sources":["../src/discussion_nested_v2.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 * Module for viewing a discussion in nested v2 view.\n *\n * @module mod_forum/discussion_nested_v2\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport AutoRows from 'core/auto_rows';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as FormChangeChecker from 'core_form/changechecker';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport Discussion from 'mod_forum/discussion';\nimport InPageReply from 'mod_forum/inpage_reply';\nimport LockToggle from 'mod_forum/lock_toggle';\nimport FavouriteToggle from 'mod_forum/favourite_toggle';\nimport Pin from 'mod_forum/pin_toggle';\nimport Selectors from 'mod_forum/selectors';\nimport Subscribe from 'mod_forum/subscription_toggle';\n\nconst ANIMATION_DURATION = 150;\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getPostContainer = (element) => {\n return element.closest(Selectors.post.post);\n};\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @param {Number} id Id of the post to find.\n * @return {Object} jQuery element\n */\nconst getPostContainerById = (element, id) => {\n return element.find(`${Selectors.post.post}[data-post-id=${id}]`);\n};\n\n/**\n * Get the parent post container elements from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getParentPostContainers = (element) => {\n return element.parents(Selectors.post.post);\n};\n\n/**\n * Get the post content container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getPostContentContainer = (postContainer) => {\n return postContainer.children().not(Selectors.post.repliesContainer).find(Selectors.post.forumCoreContent);\n};\n\n/**\n * Get the in page reply container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyContainer = (postContainer) => {\n return postContainer.children().filter(Selectors.post.inpageReplyContainer);\n};\n\n/**\n * Get the in page reply form element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyForm = (postContainer) => {\n return getInPageReplyContainer(postContainer).find(Selectors.post.inpageReplyContent);\n};\n\n/**\n * Get the in page reply create (reply) button element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyCreateButton = (postContainer) => {\n return getPostContentContainer(postContainer).find(Selectors.post.inpageReplyCreateButton);\n};\n\n/**\n * Get the replies visibility toggle container (show/hide replies button container) element\n * from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesVisibilityToggleContainer = (postContainer) => {\n return postContainer.children(Selectors.post.repliesVisibilityToggleContainer);\n};\n\n/**\n * Get the replies container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getRepliesContainer = (postContainer) => {\n return postContainer.children(Selectors.post.repliesContainer);\n};\n\n/**\n * Check if the post has any replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst hasReplies = (postContainer) => {\n return getRepliesContainer(postContainer).children().length > 0;\n};\n\n/**\n * Get the show replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getShowRepliesButton = (replyVisibilityToggleContainer) => {\n return replyVisibilityToggleContainer.find(Selectors.post.showReplies);\n};\n\n/**\n * Get the hide replies button element from the replies visibility toggle container element.\n *\n * @param {Object} replyVisibilityToggleContainer jQuery element for the toggle container\n * @return {Object} jQuery element\n */\nconst getHideRepliesButton = (replyVisibilityToggleContainer) => {\n return replyVisibilityToggleContainer.find(Selectors.post.hideReplies);\n};\n\n/**\n * Check if the replies are visible.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Bool}\n */\nconst repliesVisible = (postContainer) => {\n const repliesContainer = getRepliesContainer(postContainer);\n return repliesContainer.is(':visible');\n};\n\n/**\n * Show the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst showReplies = (postContainer, postIdToSee = null) => {\n const repliesContainer = getRepliesContainer(postContainer);\n const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n showButton.addClass('hidden');\n hideButton.removeClass('hidden');\n\n repliesContainer.slideDown({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n if (postIdToSee) {\n const postContainerToSee = getPostContainerById(repliesContainer, postIdToSee);\n if (postContainerToSee.length) {\n postContainerToSee[0].scrollIntoView();\n }\n }\n }\n }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n};\n\n/**\n * Hide the post replies.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst hideReplies = (postContainer) => {\n const repliesContainer = getRepliesContainer(postContainer);\n const replyVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const showButton = getShowRepliesButton(replyVisibilityToggleContainer);\n const hideButton = getHideRepliesButton(replyVisibilityToggleContainer);\n\n showButton.removeClass('hidden');\n hideButton.addClass('hidden');\n\n repliesContainer.slideUp({\n duration: ANIMATION_DURATION,\n queue: false\n }).fadeOut(ANIMATION_DURATION);\n};\n\n/** Variable to hold the showInPageReplyForm function after it's built. */\nlet showInPageReplyForm = null;\n\n/**\n * Build the showInPageReplyForm function with the given additional template context.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template.\n * @return {Function}\n */\nconst buildShowInPageReplyFormFunction = (additionalTemplateContext) => {\n /**\n * Show the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\n return async(postContainer) => {\n\n const inPageReplyContainer = getInPageReplyContainer(postContainer);\n const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n\n if (!hasInPageReplyForm(inPageReplyContainer)) {\n try {\n const html = await renderInPageReplyTemplate(additionalTemplateContext, inPageReplyCreateButton, postContainer);\n Templates.appendNodeContents(inPageReplyContainer, html, '');\n } catch (e) {\n Notification.exception(e);\n }\n\n FormChangeChecker.watchForm(postContainer[0].querySelector('form'));\n }\n\n inPageReplyCreateButton.fadeOut(ANIMATION_DURATION, () => {\n const inPageReplyForm = getInPageReplyForm(postContainer);\n inPageReplyForm.slideDown({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n inPageReplyForm.find('textarea').focus();\n }\n }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n\n if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n repliesVisibilityToggleContainer.fadeIn(ANIMATION_DURATION);\n hideReplies(postContainer);\n }\n });\n };\n};\n\n/**\n * Hide the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @param {Number|null} postIdToSee Id of the post to scroll into view (if any)\n */\nconst hideInPageReplyForm = (postContainer, postIdToSee = null) => {\n const inPageReplyForm = getInPageReplyForm(postContainer);\n const inPageReplyCreateButton = getInPageReplyCreateButton(postContainer);\n const repliesVisibilityToggleContainer = getRepliesVisibilityToggleContainer(postContainer);\n\n if (repliesVisibilityToggleContainer.length && hasReplies(postContainer)) {\n repliesVisibilityToggleContainer.fadeOut(ANIMATION_DURATION);\n if (!repliesVisible(postContainer)) {\n showReplies(postContainer, postIdToSee);\n }\n }\n\n inPageReplyForm.slideUp({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: () => {\n inPageReplyCreateButton.fadeIn(ANIMATION_DURATION);\n }\n }).fadeOut(200);\n};\n\n/**\n * Check if the in page reply container contains the in page reply form.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @return {Bool}\n */\nconst hasInPageReplyForm = (inPageReplyContainer) => {\n return inPageReplyContainer.find(Selectors.post.inpageReplyContent).length > 0;\n};\n\n/**\n * Render the template to generate the in page reply form HTML.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template\n * @param {Object} button jQuery element for the reply button that was clicked\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery promise\n */\nconst renderInPageReplyTemplate = (additionalTemplateContext, button, postContainer) => {\n const postContentContainer = getPostContentContainer(postContainer);\n const currentSubject = postContentContainer.find(Selectors.post.forumSubject).text();\n const currentAuthorName = postContentContainer.find(Selectors.post.authorName).text();\n const context = {\n postid: postContainer.data('post-id'),\n \"reply_url\": button.attr('data-href'),\n sesskey: M.cfg.sesskey,\n parentsubject: currentSubject,\n parentauthorname: currentAuthorName,\n canreplyprivately: button.data('can-reply-privately'),\n postformat: InPageReply.CONTENT_FORMATS.MOODLE,\n ...additionalTemplateContext\n };\n\n return Templates.render('mod_forum/inpage_reply_v2', context);\n};\n\n/**\n * Increment the total reply count in the show/hide replies buttons for the post.\n *\n * @param {Object} postContainer jQuery element for the post container\n */\nconst incrementTotalReplyCount = (postContainer) => {\n getRepliesVisibilityToggleContainer(postContainer).find(Selectors.post.replyCount).each((index, element) => {\n const currentCount = parseInt(element.innerText, 10);\n element.innerText = currentCount + 1;\n });\n};\n\n/**\n * Create all of the event listeners for the discussion.\n *\n * @param {Object} root jQuery element for the discussion container\n */\nconst registerEventListeners = (root) => {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Auto expanding text area for in page reply.\n AutoRows.init(root);\n\n // Reply button is clicked.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCreateButton, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.currentTarget));\n showInPageReplyForm(postContainer);\n });\n\n // Cancel in page reply button.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCancelButton, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.currentTarget));\n hideInPageReplyForm(postContainer);\n });\n\n // Show replies button clicked.\n root.on(CustomEvents.events.activate, Selectors.post.showReplies, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.target));\n showReplies(postContainer);\n });\n\n // Hide replies button clicked.\n root.on(CustomEvents.events.activate, Selectors.post.hideReplies, (e, data) => {\n data.originalEvent.preventDefault();\n const postContainer = getPostContainer($(e.target));\n hideReplies(postContainer);\n });\n\n // Post created with in page reply.\n root.on(InPageReply.EVENTS.POST_CREATED, Selectors.post.inpageSubmitBtn, (e, newPostId) => {\n const currentTarget = $(e.currentTarget);\n const postContainer = getPostContainer(currentTarget);\n const postContainers = getParentPostContainers(currentTarget);\n hideInPageReplyForm(postContainer, newPostId);\n\n postContainers.each((index, container) => {\n incrementTotalReplyCount($(container));\n });\n });\n};\n\n/**\n * Initialise the javascript for the discussion in nested v2 display mode.\n *\n * @param {Object} root jQuery element for the discussion container\n * @param {Object} context Additional render context for the in page reply template\n */\nexport const init = (root, context) => {\n // Build the showInPageReplyForm function with the additional render context.\n showInPageReplyForm = buildShowInPageReplyFormFunction(context);\n // Add discussion event listeners.\n registerEventListeners(root);\n // Initialise default discussion javascript (keyboard nav etc).\n Discussion.init(root);\n // Add in page reply javascript.\n InPageReply.init(root);\n\n // Initialise the settings menu javascript.\n const discussionToolsContainer = root.find(Selectors.discussion.tools);\n LockToggle.init(discussionToolsContainer, false);\n FavouriteToggle.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.userstate.favourited ? 0 : 1;\n return toggleElement.data('targetstate', newTargetState);\n });\n Pin.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.pinned ? 0 : 1;\n return toggleElement.data('targetstate', newTargetState);\n });\n Subscribe.init(discussionToolsContainer, false, (toggleElement, response) => {\n const newTargetState = response.userstate.subscribed ? 0 : 1;\n toggleElement.data('targetstate', newTargetState);\n });\n};\n"],"names":["getPostContainer","element","closest","Selectors","post","getPostContainerById","id","find","getPostContentContainer","postContainer","children","not","repliesContainer","forumCoreContent","getInPageReplyContainer","filter","inpageReplyContainer","getInPageReplyForm","inpageReplyContent","getInPageReplyCreateButton","inpageReplyCreateButton","getRepliesVisibilityToggleContainer","repliesVisibilityToggleContainer","getRepliesContainer","hasReplies","length","getShowRepliesButton","replyVisibilityToggleContainer","showReplies","getHideRepliesButton","hideReplies","repliesVisible","is","postIdToSee","showButton","hideButton","addClass","removeClass","slideDown","duration","queue","complete","postContainerToSee","scrollIntoView","css","fadeIn","slideUp","fadeOut","showInPageReplyForm","hideInPageReplyForm","inPageReplyForm","inPageReplyCreateButton","hasInPageReplyForm","inPageReplyContainer","renderInPageReplyTemplate","additionalTemplateContext","button","postContentContainer","currentSubject","forumSubject","text","currentAuthorName","authorName","context","postid","data","attr","sesskey","M","cfg","parentsubject","parentauthorname","canreplyprivately","postformat","InPageReply","CONTENT_FORMATS","MOODLE","Templates","render","registerEventListeners","root","define","CustomEvents","events","activate","init","on","e","originalEvent","preventDefault","currentTarget","inpageReplyCancelButton","target","EVENTS","POST_CREATED","inpageSubmitBtn","newPostId","postContainers","parents","each","index","container","replyCount","currentCount","parseInt","innerText","incrementTotalReplyCount","async","html","appendNodeContents","exception","FormChangeChecker","watchForm","querySelector","focus","discussionToolsContainer","discussion","tools","toggleElement","response","newTargetState","userstate","favourited","pinned","subscribed"],"mappings":"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"} \ No newline at end of file diff --git a/mod/forum/amd/src/discussion.js b/mod/forum/amd/src/discussion.js index b016950f35b..730c951ed3d 100644 --- a/mod/forum/amd/src/discussion.js +++ b/mod/forum/amd/src/discussion.js @@ -16,7 +16,7 @@ /** * Module for viewing a discussion. * - * @module mod_forum/discussion_list + * @module mod_forum/discussion * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/mod/forum/amd/src/discussion_nested_v2.js b/mod/forum/amd/src/discussion_nested_v2.js index 0fd42d01a1c..7b33e322e8e 100644 --- a/mod/forum/amd/src/discussion_nested_v2.js +++ b/mod/forum/amd/src/discussion_nested_v2.js @@ -16,7 +16,7 @@ /** * Module for viewing a discussion in nested v2 view. * - * @module mod_Forum/discussion_nested_v2 + * @module mod_forum/discussion_nested_v2 * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/payment/gateway/paypal/amd/build/gateways_modal.min.js b/payment/gateway/paypal/amd/build/gateways_modal.min.js index 0a75d539df6..e096c8c6b22 100644 --- a/payment/gateway/paypal/amd/build/gateways_modal.min.js +++ b/payment/gateway/paypal/amd/build/gateways_modal.min.js @@ -2,7 +2,7 @@ define("paygw_paypal/gateways_modal",["exports","./repository","core/templates", /** * This module is responsible for PayPal content in the gateways modal. * - * @module paygw_paypal/gateway_modal + * @module paygw_paypal/gateways_modal * @copyright 2020 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */(Repository),_templates=_interopRequireDefault(_templates),_truncate=_interopRequireDefault(_truncate),_modal_factory=_interopRequireDefault(_modal_factory),_modal_events=_interopRequireDefault(_modal_events);const showModalWithPlaceholder=async()=>{const modal=await _modal_factory.default.create({body:await _templates.default.render("paygw_paypal/paypal_button_placeholder",{})});return modal.show(),modal};_exports.process=(component,paymentArea,itemId,description)=>Promise.all([showModalWithPlaceholder(),Repository.getConfigForJs(component,paymentArea,itemId)]).then((_ref=>{let[modal,paypalConfig]=_ref;return modal.getRoot().on(_modal_events.default.hidden,(()=>{modal.destroy()})),Promise.all([modal,paypalConfig,switchSdk(paypalConfig.clientid,paypalConfig.currency)])})).then((_ref2=>{let[modal,paypalConfig]=_ref2;return modal.setBody(""),new Promise((resolve=>{window.paypal.Buttons({createOrder:function(data,actions){return actions.order.create({purchase_units:[{amount:{currency_code:paypalConfig.currency_code,value:paypalConfig.cost},description:_truncate.default.truncate(description,{length:127,stripTags:!0})}],application_context:{shipping_preference:"NO_SHIPPING",brand_name:_truncate.default.truncate(paypalConfig.brandname,{length:127,stripTags:!0})}})},onApprove:function(data){modal.getRoot().on(_modal_events.default.outsideClick,(e=>{e.preventDefault()})),modal.setBody((0,_str.get_string)("authorising","paygw_paypal")),Repository.markTransactionComplete(component,paymentArea,itemId,data.orderID).then((res=>(modal.hide(),res))).then(resolve)}}).render(modal.getBody()[0])}))})).then((res=>res.success?Promise.resolve(res.message):Promise.reject(res.message)));const switchSdk=(clientId,currency)=>{const sdkUrl="https://www.paypal.com/sdk/js?client-id=".concat(clientId,"¤cy=").concat(currency);if(switchSdk.currentlyloaded===sdkUrl)return Promise.resolve();if(switchSdk.currentlyloaded){const suspectedScript=document.querySelector('script[src="'.concat(switchSdk.currentlyloaded,'"]'));suspectedScript&&suspectedScript.parentNode.removeChild(suspectedScript)}const script=document.createElement("script");return new Promise((resolve=>{script.readyState?script.onreadystatechange=function(){"complete"!=this.readyState&&"loaded"!=this.readyState||(this.onreadystatechange=null,resolve())}:script.onload=function(){resolve()},script.setAttribute("src",sdkUrl),document.head.appendChild(script),switchSdk.currentlyloaded=sdkUrl}))};switchSdk.currentlyloaded=""})); diff --git a/payment/gateway/paypal/amd/build/gateways_modal.min.js.map b/payment/gateway/paypal/amd/build/gateways_modal.min.js.map index 99a5914daf5..ffdb674eb0c 100644 --- a/payment/gateway/paypal/amd/build/gateways_modal.min.js.map +++ b/payment/gateway/paypal/amd/build/gateways_modal.min.js.map @@ -1 +1 @@ -{"version":3,"file":"gateways_modal.min.js","sources":["../src/gateways_modal.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 * This module is responsible for PayPal content in the gateways modal.\n *\n * @module paygw_paypal/gateway_modal\n * @copyright 2020 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Repository from './repository';\nimport Templates from 'core/templates';\nimport Truncate from 'core/truncate';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Creates and shows a modal that contains a placeholder.\n *\n * @returns {Promise}\n */\nconst showModalWithPlaceholder = async() => {\n const modal = await ModalFactory.create({\n body: await Templates.render('paygw_paypal/paypal_button_placeholder', {})\n });\n modal.show();\n return modal;\n};\n\n/**\n * Process the payment.\n *\n * @param {string} component Name of the component that the itemId belongs to\n * @param {string} paymentArea The area of the component that the itemId belongs to\n * @param {number} itemId An internal identifier that is used by the component\n * @param {string} description Description of the payment\n * @returns {Promise}\n */\nexport const process = (component, paymentArea, itemId, description) => {\n return Promise.all([\n showModalWithPlaceholder(),\n Repository.getConfigForJs(component, paymentArea, itemId),\n ])\n .then(([modal, paypalConfig]) => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return Promise.all([\n modal,\n paypalConfig,\n switchSdk(paypalConfig.clientid, paypalConfig.currency),\n ]);\n })\n .then(([modal, paypalConfig]) => {\n // We have to clear the body. The render method in paypal.Buttons will render everything.\n modal.setBody('');\n\n return new Promise(resolve => {\n window.paypal.Buttons({\n // Set up the transaction.\n createOrder: function(data, actions) {\n return actions.order.create({\n purchase_units: [{ // eslint-disable-line\n amount: {\n currency_code: paypalConfig.currency_code, // eslint-disable-line\n value: paypalConfig.cost,\n },\n description: Truncate.truncate(description, {length: 127, stripTags: true}),\n }],\n application_context: { // eslint-disable-line\n shipping_preference: 'NO_SHIPPING', // eslint-disable-line\n brand_name: Truncate.truncate(paypalConfig.brandname, {length: 127, stripTags: true}), // eslint-disable-line\n },\n });\n },\n // Finalise the transaction.\n onApprove: function(data) {\n modal.getRoot().on(ModalEvents.outsideClick, (e) => {\n // Prevent closing the modal when clicking outside of it.\n e.preventDefault();\n });\n\n modal.setBody(getString('authorising', 'paygw_paypal'));\n\n Repository.markTransactionComplete(component, paymentArea, itemId, data.orderID)\n .then(res => {\n modal.hide();\n return res;\n })\n .then(resolve);\n }\n }).render(modal.getBody()[0]);\n });\n })\n .then(res => {\n if (res.success) {\n return Promise.resolve(res.message);\n }\n\n return Promise.reject(res.message);\n });\n};\n\n/**\n * Unloads the previously loaded PayPal JavaScript SDK, and loads a new one.\n *\n * @param {string} clientId PayPal client ID\n * @param {string} currency The currency\n * @returns {Promise}\n */\nconst switchSdk = (clientId, currency) => {\n const sdkUrl = `https://www.paypal.com/sdk/js?client-id=${clientId}¤cy=${currency}`;\n\n // Check to see if this file has already been loaded. If so just go straight to the func.\n if (switchSdk.currentlyloaded === sdkUrl) {\n return Promise.resolve();\n }\n\n // PayPal can only work with one currency at the same time. We have to unload the previously loaded script\n // if it was loaded for a different currency. Weird way indeed, but the only way.\n // See: https://github.com/paypal/paypal-checkout-components/issues/1180\n if (switchSdk.currentlyloaded) {\n const suspectedScript = document.querySelector(`script[src=\"${switchSdk.currentlyloaded}\"]`);\n if (suspectedScript) {\n suspectedScript.parentNode.removeChild(suspectedScript);\n }\n }\n\n const script = document.createElement('script');\n\n return new Promise(resolve => {\n if (script.readyState) {\n script.onreadystatechange = function() {\n if (this.readyState == 'complete' || this.readyState == 'loaded') {\n this.onreadystatechange = null;\n resolve();\n }\n };\n } else {\n script.onload = function() {\n resolve();\n };\n }\n\n script.setAttribute('src', sdkUrl);\n document.head.appendChild(script);\n\n switchSdk.currentlyloaded = sdkUrl;\n });\n};\n\n/**\n * Holds the full url of loaded PayPal JavaScript SDK.\n *\n * @static\n * @type {string}\n */\nswitchSdk.currentlyloaded = '';\n"],"names":["showModalWithPlaceholder","async","modal","ModalFactory","create","body","Templates","render","show","component","paymentArea","itemId","description","Promise","all","Repository","getConfigForJs","then","_ref","paypalConfig","getRoot","on","ModalEvents","hidden","destroy","switchSdk","clientid","currency","_ref2","setBody","resolve","window","paypal","Buttons","createOrder","data","actions","order","purchase_units","amount","currency_code","value","cost","Truncate","truncate","length","stripTags","application_context","shipping_preference","brand_name","brandname","onApprove","outsideClick","e","preventDefault","markTransactionComplete","orderID","res","hide","getBody","success","message","reject","clientId","sdkUrl","currentlyloaded","suspectedScript","document","querySelector","parentNode","removeChild","script","createElement","readyState","onreadystatechange","this","onload","setAttribute","head","appendChild"],"mappings":";;;;;;;4NAmCMA,yBAA2BC,gBACvBC,YAAcC,uBAAaC,OAAO,CACpCC,WAAYC,mBAAUC,OAAO,yCAA0C,aAE3EL,MAAMM,OACCN,wBAYY,CAACO,UAAWC,YAAaC,OAAQC,cAC7CC,QAAQC,IAAI,CACfd,2BACAe,WAAWC,eAAeP,UAAWC,YAAaC,UAErDM,MAAKC,WAAEhB,MAAOiB,0BACXjB,MAAMkB,UAAUC,GAAGC,sBAAYC,QAAQ,KAEnCrB,MAAMsB,aAGHX,QAAQC,IAAI,CACfZ,MACAiB,aACAM,UAAUN,aAAaO,SAAUP,aAAaQ,eAGrDV,MAAKW,YAAE1B,MAAOiB,2BAEXjB,MAAM2B,QAAQ,IAEP,IAAIhB,SAAQiB,UACfC,OAAOC,OAAOC,QAAQ,CAElBC,YAAa,SAASC,KAAMC,gBACjBA,QAAQC,MAAMjC,OAAO,CACxBkC,eAAgB,CAAC,CACbC,OAAQ,CACJC,cAAerB,aAAaqB,cAC5BC,MAAOtB,aAAauB,MAExB9B,YAAa+B,kBAASC,SAAShC,YAAa,CAACiC,OAAQ,IAAKC,WAAW,MAEzEC,oBAAqB,CACjBC,oBAAqB,cACrBC,WAAYN,kBAASC,SAASzB,aAAa+B,UAAW,CAACL,OAAQ,IAAKC,WAAW,QAK3FK,UAAW,SAAShB,MAChBjC,MAAMkB,UAAUC,GAAGC,sBAAY8B,cAAeC,IAE1CA,EAAEC,oBAGNpD,MAAM2B,SAAQ,mBAAU,cAAe,iBAEvCd,WAAWwC,wBAAwB9C,UAAWC,YAAaC,OAAQwB,KAAKqB,SACvEvC,MAAKwC,MACFvD,MAAMwD,OACCD,OAEVxC,KAAKa,YAEXvB,OAAOL,MAAMyD,UAAU,UAGjC1C,MAAKwC,KACEA,IAAIG,QACG/C,QAAQiB,QAAQ2B,IAAII,SAGxBhD,QAAQiD,OAAOL,IAAII,iBAW5BpC,UAAY,CAACsC,SAAUpC,kBACnBqC,yDAAoDD,8BAAqBpC,aAG3EF,UAAUwC,kBAAoBD,cACvBnD,QAAQiB,aAMfL,UAAUwC,gBAAiB,OACrBC,gBAAkBC,SAASC,oCAA6B3C,UAAUwC,uBACpEC,iBACAA,gBAAgBG,WAAWC,YAAYJ,uBAIzCK,OAASJ,SAASK,cAAc,iBAE/B,IAAI3D,SAAQiB,UACXyC,OAAOE,WACPF,OAAOG,mBAAqB,WACD,YAAnBC,KAAKF,YAA+C,UAAnBE,KAAKF,kBACjCC,mBAAqB,KAC1B5C,YAIRyC,OAAOK,OAAS,WACZ9C,WAIRyC,OAAOM,aAAa,MAAOb,QAC3BG,SAASW,KAAKC,YAAYR,QAE1B9C,UAAUwC,gBAAkBD,WAUpCvC,UAAUwC,gBAAkB"} \ No newline at end of file +{"version":3,"file":"gateways_modal.min.js","sources":["../src/gateways_modal.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 * This module is responsible for PayPal content in the gateways modal.\n *\n * @module paygw_paypal/gateways_modal\n * @copyright 2020 Shamim Rezaie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as Repository from './repository';\nimport Templates from 'core/templates';\nimport Truncate from 'core/truncate';\nimport ModalFactory from 'core/modal_factory';\nimport ModalEvents from 'core/modal_events';\nimport {get_string as getString} from 'core/str';\n\n/**\n * Creates and shows a modal that contains a placeholder.\n *\n * @returns {Promise}\n */\nconst showModalWithPlaceholder = async() => {\n const modal = await ModalFactory.create({\n body: await Templates.render('paygw_paypal/paypal_button_placeholder', {})\n });\n modal.show();\n return modal;\n};\n\n/**\n * Process the payment.\n *\n * @param {string} component Name of the component that the itemId belongs to\n * @param {string} paymentArea The area of the component that the itemId belongs to\n * @param {number} itemId An internal identifier that is used by the component\n * @param {string} description Description of the payment\n * @returns {Promise}\n */\nexport const process = (component, paymentArea, itemId, description) => {\n return Promise.all([\n showModalWithPlaceholder(),\n Repository.getConfigForJs(component, paymentArea, itemId),\n ])\n .then(([modal, paypalConfig]) => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Destroy when hidden.\n modal.destroy();\n });\n\n return Promise.all([\n modal,\n paypalConfig,\n switchSdk(paypalConfig.clientid, paypalConfig.currency),\n ]);\n })\n .then(([modal, paypalConfig]) => {\n // We have to clear the body. The render method in paypal.Buttons will render everything.\n modal.setBody('');\n\n return new Promise(resolve => {\n window.paypal.Buttons({\n // Set up the transaction.\n createOrder: function(data, actions) {\n return actions.order.create({\n purchase_units: [{ // eslint-disable-line\n amount: {\n currency_code: paypalConfig.currency_code, // eslint-disable-line\n value: paypalConfig.cost,\n },\n description: Truncate.truncate(description, {length: 127, stripTags: true}),\n }],\n application_context: { // eslint-disable-line\n shipping_preference: 'NO_SHIPPING', // eslint-disable-line\n brand_name: Truncate.truncate(paypalConfig.brandname, {length: 127, stripTags: true}), // eslint-disable-line\n },\n });\n },\n // Finalise the transaction.\n onApprove: function(data) {\n modal.getRoot().on(ModalEvents.outsideClick, (e) => {\n // Prevent closing the modal when clicking outside of it.\n e.preventDefault();\n });\n\n modal.setBody(getString('authorising', 'paygw_paypal'));\n\n Repository.markTransactionComplete(component, paymentArea, itemId, data.orderID)\n .then(res => {\n modal.hide();\n return res;\n })\n .then(resolve);\n }\n }).render(modal.getBody()[0]);\n });\n })\n .then(res => {\n if (res.success) {\n return Promise.resolve(res.message);\n }\n\n return Promise.reject(res.message);\n });\n};\n\n/**\n * Unloads the previously loaded PayPal JavaScript SDK, and loads a new one.\n *\n * @param {string} clientId PayPal client ID\n * @param {string} currency The currency\n * @returns {Promise}\n */\nconst switchSdk = (clientId, currency) => {\n const sdkUrl = `https://www.paypal.com/sdk/js?client-id=${clientId}¤cy=${currency}`;\n\n // Check to see if this file has already been loaded. If so just go straight to the func.\n if (switchSdk.currentlyloaded === sdkUrl) {\n return Promise.resolve();\n }\n\n // PayPal can only work with one currency at the same time. We have to unload the previously loaded script\n // if it was loaded for a different currency. Weird way indeed, but the only way.\n // See: https://github.com/paypal/paypal-checkout-components/issues/1180\n if (switchSdk.currentlyloaded) {\n const suspectedScript = document.querySelector(`script[src=\"${switchSdk.currentlyloaded}\"]`);\n if (suspectedScript) {\n suspectedScript.parentNode.removeChild(suspectedScript);\n }\n }\n\n const script = document.createElement('script');\n\n return new Promise(resolve => {\n if (script.readyState) {\n script.onreadystatechange = function() {\n if (this.readyState == 'complete' || this.readyState == 'loaded') {\n this.onreadystatechange = null;\n resolve();\n }\n };\n } else {\n script.onload = function() {\n resolve();\n };\n }\n\n script.setAttribute('src', sdkUrl);\n document.head.appendChild(script);\n\n switchSdk.currentlyloaded = sdkUrl;\n });\n};\n\n/**\n * Holds the full url of loaded PayPal JavaScript SDK.\n *\n * @static\n * @type {string}\n */\nswitchSdk.currentlyloaded = '';\n"],"names":["showModalWithPlaceholder","async","modal","ModalFactory","create","body","Templates","render","show","component","paymentArea","itemId","description","Promise","all","Repository","getConfigForJs","then","_ref","paypalConfig","getRoot","on","ModalEvents","hidden","destroy","switchSdk","clientid","currency","_ref2","setBody","resolve","window","paypal","Buttons","createOrder","data","actions","order","purchase_units","amount","currency_code","value","cost","Truncate","truncate","length","stripTags","application_context","shipping_preference","brand_name","brandname","onApprove","outsideClick","e","preventDefault","markTransactionComplete","orderID","res","hide","getBody","success","message","reject","clientId","sdkUrl","currentlyloaded","suspectedScript","document","querySelector","parentNode","removeChild","script","createElement","readyState","onreadystatechange","this","onload","setAttribute","head","appendChild"],"mappings":";;;;;;;4NAmCMA,yBAA2BC,gBACvBC,YAAcC,uBAAaC,OAAO,CACpCC,WAAYC,mBAAUC,OAAO,yCAA0C,aAE3EL,MAAMM,OACCN,wBAYY,CAACO,UAAWC,YAAaC,OAAQC,cAC7CC,QAAQC,IAAI,CACfd,2BACAe,WAAWC,eAAeP,UAAWC,YAAaC,UAErDM,MAAKC,WAAEhB,MAAOiB,0BACXjB,MAAMkB,UAAUC,GAAGC,sBAAYC,QAAQ,KAEnCrB,MAAMsB,aAGHX,QAAQC,IAAI,CACfZ,MACAiB,aACAM,UAAUN,aAAaO,SAAUP,aAAaQ,eAGrDV,MAAKW,YAAE1B,MAAOiB,2BAEXjB,MAAM2B,QAAQ,IAEP,IAAIhB,SAAQiB,UACfC,OAAOC,OAAOC,QAAQ,CAElBC,YAAa,SAASC,KAAMC,gBACjBA,QAAQC,MAAMjC,OAAO,CACxBkC,eAAgB,CAAC,CACbC,OAAQ,CACJC,cAAerB,aAAaqB,cAC5BC,MAAOtB,aAAauB,MAExB9B,YAAa+B,kBAASC,SAAShC,YAAa,CAACiC,OAAQ,IAAKC,WAAW,MAEzEC,oBAAqB,CACjBC,oBAAqB,cACrBC,WAAYN,kBAASC,SAASzB,aAAa+B,UAAW,CAACL,OAAQ,IAAKC,WAAW,QAK3FK,UAAW,SAAShB,MAChBjC,MAAMkB,UAAUC,GAAGC,sBAAY8B,cAAeC,IAE1CA,EAAEC,oBAGNpD,MAAM2B,SAAQ,mBAAU,cAAe,iBAEvCd,WAAWwC,wBAAwB9C,UAAWC,YAAaC,OAAQwB,KAAKqB,SACvEvC,MAAKwC,MACFvD,MAAMwD,OACCD,OAEVxC,KAAKa,YAEXvB,OAAOL,MAAMyD,UAAU,UAGjC1C,MAAKwC,KACEA,IAAIG,QACG/C,QAAQiB,QAAQ2B,IAAII,SAGxBhD,QAAQiD,OAAOL,IAAII,iBAW5BpC,UAAY,CAACsC,SAAUpC,kBACnBqC,yDAAoDD,8BAAqBpC,aAG3EF,UAAUwC,kBAAoBD,cACvBnD,QAAQiB,aAMfL,UAAUwC,gBAAiB,OACrBC,gBAAkBC,SAASC,oCAA6B3C,UAAUwC,uBACpEC,iBACAA,gBAAgBG,WAAWC,YAAYJ,uBAIzCK,OAASJ,SAASK,cAAc,iBAE/B,IAAI3D,SAAQiB,UACXyC,OAAOE,WACPF,OAAOG,mBAAqB,WACD,YAAnBC,KAAKF,YAA+C,UAAnBE,KAAKF,kBACjCC,mBAAqB,KAC1B5C,YAIRyC,OAAOK,OAAS,WACZ9C,WAIRyC,OAAOM,aAAa,MAAOb,QAC3BG,SAASW,KAAKC,YAAYR,QAE1B9C,UAAUwC,gBAAkBD,WAUpCvC,UAAUwC,gBAAkB"} \ No newline at end of file diff --git a/payment/gateway/paypal/amd/src/gateways_modal.js b/payment/gateway/paypal/amd/src/gateways_modal.js index 04f8a96ec82..7ca5f45ebf1 100644 --- a/payment/gateway/paypal/amd/src/gateways_modal.js +++ b/payment/gateway/paypal/amd/src/gateways_modal.js @@ -16,7 +16,7 @@ /** * This module is responsible for PayPal content in the gateways modal. * - * @module paygw_paypal/gateway_modal + * @module paygw_paypal/gateways_modal * @copyright 2020 Shamim Rezaie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/amd/build/selectors.min.js b/question/amd/build/selectors.min.js index 130221855c6..750edd806d5 100644 --- a/question/amd/build/selectors.min.js +++ b/question/amd/build/selectors.min.js @@ -3,7 +3,7 @@ * * @deprecated since Moodle 4.0 * @todo Final deprecation on Moodle 4.4 MDL-72438 - * @module core_question/question_selectors + * @module core_question/selectors * @copyright 2018 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/amd/build/selectors.min.js.map b/question/amd/build/selectors.min.js.map index 5642a694e64..cd9f6f8acc6 100644 --- a/question/amd/build/selectors.min.js.map +++ b/question/amd/build/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * The purpose of this module is to centralize selectors related to question.\n *\n * @deprecated since Moodle 4.0\n * @todo Final deprecation on Moodle 4.4 MDL-72438\n * @module core_question/question_selectors\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n window.console.warn('warn: The core_question/selectors has been deprecated. Please use qbank_tagquestion/selectors instead.');\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"names":["define","window","console","warn","actions","save","edittags","containers","loadingIcon"],"mappings":";;;;;;;;;AAwBAA,iCAAO,IAAI,kBACPC,OAAOC,QAAQC,KAAK,0GACb,CACHC,QAAS,CACLC,KAAM,uBACNC,SAAU,4BAEdC,WAAY,CACRC,YAAa"} \ No newline at end of file +{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * The purpose of this module is to centralize selectors related to question.\n *\n * @deprecated since Moodle 4.0\n * @todo Final deprecation on Moodle 4.4 MDL-72438\n * @module core_question/selectors\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n window.console.warn('warn: The core_question/selectors has been deprecated. Please use qbank_tagquestion/selectors instead.');\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"names":["define","window","console","warn","actions","save","edittags","containers","loadingIcon"],"mappings":";;;;;;;;;AAwBAA,iCAAO,IAAI,kBACPC,OAAOC,QAAQC,KAAK,0GACb,CACHC,QAAS,CACLC,KAAM,uBACNC,SAAU,4BAEdC,WAAY,CACRC,YAAa"} \ No newline at end of file diff --git a/question/amd/src/selectors.js b/question/amd/src/selectors.js index 6a3fb874894..2375e62cd9c 100644 --- a/question/amd/src/selectors.js +++ b/question/amd/src/selectors.js @@ -18,7 +18,7 @@ * * @deprecated since Moodle 4.0 * @todo Final deprecation on Moodle 4.4 MDL-72438 - * @module core_question/question_selectors + * @module core_question/selectors * @copyright 2018 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/bank/previewquestion/amd/build/preview.min.js.map b/question/bank/previewquestion/amd/build/preview.min.js.map index 40c460b3e0e..fc7748cb96f 100644 --- a/question/bank/previewquestion/amd/build/preview.min.js.map +++ b/question/bank/previewquestion/amd/build/preview.min.js.map @@ -1 +1 @@ -{"version":3,"file":"preview.min.js","sources":["../src/preview.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 * Javascript for preview.\n *\n * @module qbank_preview/preview\n * @copyright 2021 Catalyst IT Australia Pty Ltd\n * @author Safat Shahin \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {initForm as initQuestionEngineForm} from 'core_question/question_engine';\n\n/**\n * Set up the actions.\n *\n * @method init\n * @param {bool} redirect Redirect.\n * @param {string} url url to redirect.\n */\nexport const init = (redirect, url) => {\n if (!redirect) {\n const closeButton = document.getElementById('close-previewquestion-page');\n closeButton.addEventListener('click', (e) => {\n e.preventDefault();\n if (window.opener === null) {\n location.href = url;\n } else {\n window.close();\n }\n });\n }\n // Set up the form to be displayed.\n initQuestionEngineForm('#responseform');\n};\n"],"names":["redirect","url","document","getElementById","addEventListener","e","preventDefault","window","opener","location","href","close"],"mappings":"mNAiCoB,CAACA,SAAUC,WACtBD,SAAU,CACSE,SAASC,eAAe,8BAChCC,iBAAiB,SAAUC,IACnCA,EAAEC,iBACoB,OAAlBC,OAAOC,OACPC,SAASC,KAAOT,IAEhBM,OAAOI,yCAKI"} \ No newline at end of file +{"version":3,"file":"preview.min.js","sources":["../src/preview.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 * Javascript for preview.\n *\n * @module qbank_previewquestion/preview\n * @copyright 2021 Catalyst IT Australia Pty Ltd\n * @author Safat Shahin \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {initForm as initQuestionEngineForm} from 'core_question/question_engine';\n\n/**\n * Set up the actions.\n *\n * @method init\n * @param {bool} redirect Redirect.\n * @param {string} url url to redirect.\n */\nexport const init = (redirect, url) => {\n if (!redirect) {\n const closeButton = document.getElementById('close-previewquestion-page');\n closeButton.addEventListener('click', (e) => {\n e.preventDefault();\n if (window.opener === null) {\n location.href = url;\n } else {\n window.close();\n }\n });\n }\n // Set up the form to be displayed.\n initQuestionEngineForm('#responseform');\n};\n"],"names":["redirect","url","document","getElementById","addEventListener","e","preventDefault","window","opener","location","href","close"],"mappings":"mNAiCoB,CAACA,SAAUC,WACtBD,SAAU,CACSE,SAASC,eAAe,8BAChCC,iBAAiB,SAAUC,IACnCA,EAAEC,iBACoB,OAAlBC,OAAOC,OACPC,SAASC,KAAOT,IAEhBM,OAAOI,yCAKI"} \ No newline at end of file diff --git a/question/bank/previewquestion/amd/src/preview.js b/question/bank/previewquestion/amd/src/preview.js index d1ef49c4cdd..7df269edf02 100644 --- a/question/bank/previewquestion/amd/src/preview.js +++ b/question/bank/previewquestion/amd/src/preview.js @@ -16,7 +16,7 @@ /** * Javascript for preview. * - * @module qbank_preview/preview + * @module qbank_previewquestion/preview * @copyright 2021 Catalyst IT Australia Pty Ltd * @author Safat Shahin * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/question/bank/tagquestion/amd/build/selectors.min.js b/question/bank/tagquestion/amd/build/selectors.min.js index 9bce5874ae8..2a873113801 100644 --- a/question/bank/tagquestion/amd/build/selectors.min.js +++ b/question/bank/tagquestion/amd/build/selectors.min.js @@ -1,7 +1,7 @@ /** * The purpose of this module is to centralize selectors related to question. * - * @module qbank_tagquestion/question_selectors + * @module qbank_tagquestion/selectors * @copyright 2018 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/bank/tagquestion/amd/build/selectors.min.js.map b/question/bank/tagquestion/amd/build/selectors.min.js.map index 44becf2231b..aec8b07cd7d 100644 --- a/question/bank/tagquestion/amd/build/selectors.min.js.map +++ b/question/bank/tagquestion/amd/build/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * The purpose of this module is to centralize selectors related to question.\n *\n * @module qbank_tagquestion/question_selectors\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"names":["define","actions","save","edittags","containers","loadingIcon"],"mappings":";;;;;;;AAsBAA,qCAAO,IAAI,iBACA,CACHC,QAAS,CACLC,KAAM,uBACNC,SAAU,4BAEdC,WAAY,CACRC,YAAa"} \ No newline at end of file +{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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 * The purpose of this module is to centralize selectors related to question.\n *\n * @module qbank_tagquestion/selectors\n * @copyright 2018 Simey Lameze \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n actions: {\n save: '[data-action=\"save\"]',\n edittags: '[data-action=\"edittags\"]',\n },\n containers: {\n loadingIcon: '[data-region=\"overlay-icon-container\"]',\n },\n };\n});\n"],"names":["define","actions","save","edittags","containers","loadingIcon"],"mappings":";;;;;;;AAsBAA,qCAAO,IAAI,iBACA,CACHC,QAAS,CACLC,KAAM,uBACNC,SAAU,4BAEdC,WAAY,CACRC,YAAa"} \ No newline at end of file diff --git a/question/bank/tagquestion/amd/src/selectors.js b/question/bank/tagquestion/amd/src/selectors.js index 7dd055a6dc9..5854ec59624 100644 --- a/question/bank/tagquestion/amd/src/selectors.js +++ b/question/bank/tagquestion/amd/src/selectors.js @@ -16,7 +16,7 @@ /** * The purpose of this module is to centralize selectors related to question. * - * @module qbank_tagquestion/question_selectors + * @module qbank_tagquestion/selectors * @copyright 2018 Simey Lameze * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/report/participation/amd/build/participants.min.js b/report/participation/amd/build/participants.min.js index 39e3fec7389..4fe85ae8c82 100644 --- a/report/participation/amd/build/participants.min.js +++ b/report/participation/amd/build/participants.min.js @@ -3,7 +3,7 @@ define("report_participation/participants",["exports","jquery","core/custom_inte * Some UI stuff for participants page. * This is also used by the report/participants/index.php because it has the same functionality. * - * @module core_user/participants + * @module report_participation/participants * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_jquery=_interopRequireDefault(_jquery),_custom_interaction_events=_interopRequireDefault(_custom_interaction_events),_modal_events=_interopRequireDefault(_modal_events),_notification=_interopRequireDefault(_notification);const Selectors_bulkActionSelect="#formactionid",Selectors_bulkUserSelectedCheckBoxes="input[data-togglegroup^='participants-table'][data-toggle='slave']:checked",Selectors_participantsForm="#participantsform";_exports.init=()=>{const root=document.querySelector(Selectors_participantsForm),resetBulkAction=bulkActionSelect=>{bulkActionSelect.value=""};_custom_interaction_events.default.define(Selectors_bulkActionSelect,[_custom_interaction_events.default.events.accessibleChange]),(0,_jquery.default)(Selectors_bulkActionSelect).on(_custom_interaction_events.default.events.accessibleChange,(e=>{const action=e.target.value,checkboxes=root.querySelectorAll(Selectors_bulkUserSelectedCheckBoxes);if(-1!==action.indexOf("#")){e.preventDefault();const ids=[];checkboxes.forEach((checkbox=>{ids.push(checkbox.getAttribute("name").replace("user",""))})),"#messageselect"===action&&(0,_bulkactions.showSendMessage)(ids).then((modal=>(modal.getRoot().on(_modal_events.default.hidden,(()=>{const bulkActionSelector=root.querySelector(Selectors_bulkActionSelect);resetBulkAction(bulkActionSelector),bulkActionSelector.focus()})),modal))).catch(_notification.default.exception)}else""!==action&&checkboxes.length&&e.target.form().submit();resetBulkAction(e.target)}))}})); diff --git a/report/participation/amd/build/participants.min.js.map b/report/participation/amd/build/participants.min.js.map index 87f1ad92c82..5c3f51be0c0 100644 --- a/report/participation/amd/build/participants.min.js.map +++ b/report/participation/amd/build/participants.min.js.map @@ -1 +1 @@ -{"version":3,"file":"participants.min.js","sources":["../src/participants.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 * Some UI stuff for participants page.\n * This is also used by the report/participants/index.php because it has the same functionality.\n *\n * @module core_user/participants\n * @copyright 2017 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport jQuery from 'jquery';\nimport CustomEvents from 'core/custom_interaction_events';\nimport ModalEvents from 'core/modal_events';\nimport Notification from 'core/notification';\nimport {showSendMessage} from 'core_user/local/participants/bulkactions';\n\nconst Selectors = {\n bulkActionSelect: \"#formactionid\",\n bulkUserSelectedCheckBoxes: \"input[data-togglegroup^='participants-table'][data-toggle='slave']:checked\",\n participantsForm: '#participantsform',\n};\n\nexport const init = () => {\n const root = document.querySelector(Selectors.participantsForm);\n\n /**\n * Private method.\n *\n * @method registerEventListeners\n * @private\n */\n const registerEventListeners = () => {\n CustomEvents.define(Selectors.bulkActionSelect, [CustomEvents.events.accessibleChange]);\n jQuery(Selectors.bulkActionSelect).on(CustomEvents.events.accessibleChange, e => {\n const action = e.target.value;\n const checkboxes = root.querySelectorAll(Selectors.bulkUserSelectedCheckBoxes);\n\n if (action.indexOf('#') !== -1) {\n e.preventDefault();\n\n const ids = [];\n checkboxes.forEach(checkbox => {\n ids.push(checkbox.getAttribute('name').replace('user', ''));\n });\n\n if (action === '#messageselect') {\n showSendMessage(ids)\n .then(modal => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Focus on the action select when the dialog is closed.\n const bulkActionSelector = root.querySelector(Selectors.bulkActionSelect);\n resetBulkAction(bulkActionSelector);\n bulkActionSelector.focus();\n });\n\n return modal;\n })\n .catch(Notification.exception);\n }\n } else if (action !== '' && checkboxes.length) {\n e.target.form().submit();\n }\n\n resetBulkAction(e.target);\n });\n };\n\n const resetBulkAction = bulkActionSelect => {\n bulkActionSelect.value = '';\n };\n\n registerEventListeners();\n};\n"],"names":["Selectors","root","document","querySelector","resetBulkAction","bulkActionSelect","value","define","CustomEvents","events","accessibleChange","on","e","action","target","checkboxes","querySelectorAll","indexOf","preventDefault","ids","forEach","checkbox","push","getAttribute","replace","then","modal","getRoot","ModalEvents","hidden","bulkActionSelector","focus","catch","Notification","exception","length","form","submit"],"mappings":";;;;;;;;sTA8BMA,2BACgB,gBADhBA,qCAE0B,6EAF1BA,2BAGgB,kCAGF,WACVC,KAAOC,SAASC,cAAcH,4BA4C9BI,gBAAkBC,mBACpBA,iBAAiBC,MAAQ,uCApCZC,OAAOP,2BAA4B,CAACQ,mCAAaC,OAAOC,uCAC9DV,4BAA4BW,GAAGH,mCAAaC,OAAOC,kBAAkBE,UAClEC,OAASD,EAAEE,OAAOR,MAClBS,WAAad,KAAKe,iBAAiBhB,0CAEZ,IAAzBa,OAAOI,QAAQ,KAAa,CAC5BL,EAAEM,uBAEIC,IAAM,GACZJ,WAAWK,SAAQC,WACfF,IAAIG,KAAKD,SAASE,aAAa,QAAQC,QAAQ,OAAQ,QAG5C,mBAAXX,yCACgBM,KACfM,MAAKC,QACFA,MAAMC,UAAUhB,GAAGiB,sBAAYC,QAAQ,WAE7BC,mBAAqB7B,KAAKE,cAAcH,4BAC9CI,gBAAgB0B,oBAChBA,mBAAmBC,WAGhBL,SAEVM,MAAMC,sBAAaC,eAEN,KAAXrB,QAAiBE,WAAWoB,QACnCvB,EAAEE,OAAOsB,OAAOC,SAGpBjC,gBAAgBQ,EAAEE"} \ No newline at end of file +{"version":3,"file":"participants.min.js","sources":["../src/participants.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 * Some UI stuff for participants page.\n * This is also used by the report/participants/index.php because it has the same functionality.\n *\n * @module report_participation/participants\n * @copyright 2017 Damyon Wiese\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport jQuery from 'jquery';\nimport CustomEvents from 'core/custom_interaction_events';\nimport ModalEvents from 'core/modal_events';\nimport Notification from 'core/notification';\nimport {showSendMessage} from 'core_user/local/participants/bulkactions';\n\nconst Selectors = {\n bulkActionSelect: \"#formactionid\",\n bulkUserSelectedCheckBoxes: \"input[data-togglegroup^='participants-table'][data-toggle='slave']:checked\",\n participantsForm: '#participantsform',\n};\n\nexport const init = () => {\n const root = document.querySelector(Selectors.participantsForm);\n\n /**\n * Private method.\n *\n * @method registerEventListeners\n * @private\n */\n const registerEventListeners = () => {\n CustomEvents.define(Selectors.bulkActionSelect, [CustomEvents.events.accessibleChange]);\n jQuery(Selectors.bulkActionSelect).on(CustomEvents.events.accessibleChange, e => {\n const action = e.target.value;\n const checkboxes = root.querySelectorAll(Selectors.bulkUserSelectedCheckBoxes);\n\n if (action.indexOf('#') !== -1) {\n e.preventDefault();\n\n const ids = [];\n checkboxes.forEach(checkbox => {\n ids.push(checkbox.getAttribute('name').replace('user', ''));\n });\n\n if (action === '#messageselect') {\n showSendMessage(ids)\n .then(modal => {\n modal.getRoot().on(ModalEvents.hidden, () => {\n // Focus on the action select when the dialog is closed.\n const bulkActionSelector = root.querySelector(Selectors.bulkActionSelect);\n resetBulkAction(bulkActionSelector);\n bulkActionSelector.focus();\n });\n\n return modal;\n })\n .catch(Notification.exception);\n }\n } else if (action !== '' && checkboxes.length) {\n e.target.form().submit();\n }\n\n resetBulkAction(e.target);\n });\n };\n\n const resetBulkAction = bulkActionSelect => {\n bulkActionSelect.value = '';\n };\n\n registerEventListeners();\n};\n"],"names":["Selectors","root","document","querySelector","resetBulkAction","bulkActionSelect","value","define","CustomEvents","events","accessibleChange","on","e","action","target","checkboxes","querySelectorAll","indexOf","preventDefault","ids","forEach","checkbox","push","getAttribute","replace","then","modal","getRoot","ModalEvents","hidden","bulkActionSelector","focus","catch","Notification","exception","length","form","submit"],"mappings":";;;;;;;;sTA8BMA,2BACgB,gBADhBA,qCAE0B,6EAF1BA,2BAGgB,kCAGF,WACVC,KAAOC,SAASC,cAAcH,4BA4C9BI,gBAAkBC,mBACpBA,iBAAiBC,MAAQ,uCApCZC,OAAOP,2BAA4B,CAACQ,mCAAaC,OAAOC,uCAC9DV,4BAA4BW,GAAGH,mCAAaC,OAAOC,kBAAkBE,UAClEC,OAASD,EAAEE,OAAOR,MAClBS,WAAad,KAAKe,iBAAiBhB,0CAEZ,IAAzBa,OAAOI,QAAQ,KAAa,CAC5BL,EAAEM,uBAEIC,IAAM,GACZJ,WAAWK,SAAQC,WACfF,IAAIG,KAAKD,SAASE,aAAa,QAAQC,QAAQ,OAAQ,QAG5C,mBAAXX,yCACgBM,KACfM,MAAKC,QACFA,MAAMC,UAAUhB,GAAGiB,sBAAYC,QAAQ,WAE7BC,mBAAqB7B,KAAKE,cAAcH,4BAC9CI,gBAAgB0B,oBAChBA,mBAAmBC,WAGhBL,SAEVM,MAAMC,sBAAaC,eAEN,KAAXrB,QAAiBE,WAAWoB,QACnCvB,EAAEE,OAAOsB,OAAOC,SAGpBjC,gBAAgBQ,EAAEE"} \ No newline at end of file diff --git a/report/participation/amd/src/participants.js b/report/participation/amd/src/participants.js index 5d0cb8cac37..0029abf116e 100644 --- a/report/participation/amd/src/participants.js +++ b/report/participation/amd/src/participants.js @@ -17,7 +17,7 @@ * Some UI stuff for participants page. * This is also used by the report/participants/index.php because it has the same functionality. * - * @module core_user/participants + * @module report_participation/participants * @copyright 2017 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 9ffbcce0accea6060c697596adc4c697c7246324 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 27 Feb 2023 17:51:46 +0100 Subject: [PATCH 2/5] MDL-77164 various: fix mustache template name --- admin/templates/setting_encryptedpassword.mustache | 2 +- admin/tool/brickfield/templates/chartsingle.mustache | 2 +- admin/tool/brickfield/templates/tabtree.mustache | 2 +- .../tool/dataprivacy/templates/context_tree_branches.mustache | 2 +- admin/tool/dataprivacy/templates/context_tree_node.mustache | 2 +- admin/tool/lp/templates/user_competency_summary.mustache | 2 +- admin/tool/lp/templates/user_summary.mustache | 2 +- .../local/ltiadvantage/account_binding_complete.mustache | 2 +- auth/lti/templates/local/ltiadvantage/login.mustache | 2 +- badges/templates/issued_badge.mustache | 2 +- .../timeline/templates/placeholder-event-list-item.mustache | 2 +- calendar/templates/add_event_button.mustache | 2 +- calendar/templates/calendar_mini.mustache | 2 +- calendar/templates/calendar_month.mustache | 2 +- calendar/templates/calendar_threemonth.mustache | 2 +- calendar/templates/calendar_upcoming.mustache | 2 +- calendar/templates/calendar_upcoming_mini.mustache | 2 +- calendar/templates/day_navigation.mustache | 2 +- calendar/templates/event_filter.mustache | 2 +- calendar/templates/event_filter_key.mustache | 2 +- calendar/templates/event_icon.mustache | 2 +- calendar/templates/event_subscription.mustache | 2 +- calendar/templates/header.mustache | 2 +- calendar/templates/modal_event_form.mustache | 2 +- calendar/templates/month_detailed.mustache | 2 +- calendar/templates/month_mini.mustache | 2 +- calendar/templates/month_navigation.mustache | 2 +- calendar/templates/threemonth_month.mustache | 2 +- calendar/templates/upcoming_detailed.mustache | 2 +- calendar/templates/upcoming_mini.mustache | 2 +- contentbank/templates/viewcontent.mustache | 2 +- .../format/templates/local/content/bulkedittoggler.mustache | 2 +- course/format/templates/local/content/bulkedittools.mustache | 2 +- .../format/templates/local/content/frontpagesection.mustache | 2 +- course/format/templates/local/content/movecm.mustache | 2 +- course/format/templates/local/content/movesection.mustache | 2 +- .../format/templates/local/content/sectionnavigation.mustache | 2 +- .../format/templates/local/content/sectionselector.mustache | 2 +- course/templates/coursecard.mustache | 2 +- course/templates/coursecards.mustache | 2 +- course/templates/local/activitychooser/favourites.mustache | 2 +- course/templates/local/activitychooser/help.mustache | 2 +- course/templates/local/activitychooser/item.mustache | 2 +- course/templates/local/activitychooser/search.mustache | 2 +- .../templates/local/activitychooser/search_results.mustache | 2 +- customfield/templates/field_data.mustache | 2 +- .../lti/templates/local/ltiadvantage/content_select.mustache | 2 +- enrol/lti/templates/local/ltiadvantage/deployments.mustache | 2 +- .../local/ltiadvantage/registered_platforms.mustache | 2 +- .../form/guide/templates/grades/grader/gradingpanel.mustache | 2 +- grade/report/singleview/templates/bulkinsert.mustache | 2 +- grade/report/singleview/templates/gradesearch_body.mustache | 2 +- grade/report/singleview/templates/page_toggler.mustache | 2 +- grade/report/singleview/templates/report_navigation.mustache | 2 +- grade/report/singleview/templates/zero_state_grade.mustache | 2 +- grade/report/singleview/templates/zero_state_user.mustache | 2 +- .../templates/grades/grader/gradingpanel/point_blank.mustache | 2 +- grade/templates/grades/grader/input.mustache | 2 +- grade/templates/grades/grader/scale.mustache | 2 +- grade/templates/grades/grader/text.mustache | 2 +- .../accessibilitychecker/templates/warning_content.mustache | 2 +- lib/editor/tiny/templates/toolbar_button.mustache | 2 +- lib/form/templates/element-radio-inline.mustache | 2 +- lib/form/templates/element-radio.mustache | 2 +- lib/templates/auth_digital_minor_page.mustache | 2 +- lib/templates/auth_verify_age_location_page.mustache | 2 +- lib/templates/check/result.mustache | 2 +- lib/templates/check/result/error.mustache | 2 +- lib/templates/editswitch.mustache | 2 +- lib/templates/emoji/emoji_row.mustache | 4 ++-- lib/templates/emoji/header_row.mustache | 4 ++-- lib/templates/user_action_menu_submenu_items.mustache | 2 +- message/output/email/templates/email_digest_html.mustache | 2 +- message/output/email/templates/email_digest_text.mustache | 2 +- message/output/popup/templates/message_content_item.mustache | 2 +- .../output/popup/templates/notification_content_item.mustache | 2 +- message/output/popup/templates/notification_popover.mustache | 2 +- ...e_drawer_view_contacts_body_section_requests_list.mustache | 2 +- .../templates/message_drawer_view_conversation_body.mustache | 2 +- ...age_drawer_view_conversation_body_day_placeholder.mustache | 2 +- ...drawer_view_conversation_footer_unable_to_message.mustache | 2 +- ...wer_view_conversation_header_content_type_private.mustache | 2 +- ...versation_header_content_type_private_no_controls.mustache | 2 +- ...awer_view_conversation_header_content_type_public.mustache | 2 +- .../templates/message_drawer_view_overview_footer.mustache | 2 +- ...ssage_drawer_view_overview_section_group_messages.mustache | 2 +- message/templates/message_jumpto.mustache | 2 +- message/templates/remove_contact_button.mustache | 2 +- mod/bigbluebuttonbn/templates/element_text_with_copy.mustache | 2 +- .../templates/mobile_view_page_ionic3.mustache | 2 +- .../templates/mobile_view_page_latest.mustache | 2 +- mod/bigbluebuttonbn/templates/recordings_table.mustache | 2 +- mod/data/templates/fields_mapping_body.mustache | 2 +- mod/data/templates/fields_mapping_footer.mustache | 2 +- mod/data/templates/view_noentries.mustache | 2 +- .../report/summary/templates/filter_dates_popover.mustache | 2 +- mod/forum/templates/discussion_favourite_toggle.mustache | 2 +- mod/forum/templates/discussion_pin_toggle.mustache | 2 +- .../templates/forum_discussion_favourite_toggle.mustache | 2 +- .../templates/forum_discussion_nested_v2_post_reply.mustache | 2 +- mod/forum/templates/forum_post_email_htmlemail_body.mustache | 2 +- mod/forum/templates/frontpage_news_discussion_list.mustache | 2 +- .../templates/grades/grader/discussion/post_modal.mustache | 2 +- mod/forum/templates/grades/grader/discussion/posts.mustache | 2 +- mod/forum/templates/grades/view_grade_button.mustache | 2 +- mod/forum/templates/local/grades/grader.mustache | 2 +- mod/forum/templates/local/grades/view_grade.mustache | 2 +- mod/scorm/templates/user_report_actionbar.mustache | 3 ++- payment/templates/fee_breakdown.mustache | 2 +- question/bank/viewcreator/templates/version_info.mustache | 2 +- report/insights/templates/bulk_actions.mustache | 2 +- theme/boost/templates/core/sticky_footer.mustache | 2 +- theme/boost/templates/embedded.mustache | 2 +- theme/classic/templates/core/full_header.mustache | 2 +- 114 files changed, 117 insertions(+), 116 deletions(-) diff --git a/admin/templates/setting_encryptedpassword.mustache b/admin/templates/setting_encryptedpassword.mustache index e2a98cf7db0..f5b05d64185 100644 --- a/admin/templates/setting_encryptedpassword.mustache +++ b/admin/templates/setting_encryptedpassword.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_admin/admin_setting_encryptedpassword + @template core_admin/setting_encryptedpassword Admin encrypted password template. diff --git a/admin/tool/brickfield/templates/chartsingle.mustache b/admin/tool/brickfield/templates/chartsingle.mustache index aa1152864ef..f80f8254f7e 100644 --- a/admin/tool/brickfield/templates/chartsingle.mustache +++ b/admin/tool/brickfield/templates/chartsingle.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tool_brickfield/checktypes + @template tool_brickfield/chartsingle This template renders the charts for the different check groups diff --git a/admin/tool/brickfield/templates/tabtree.mustache b/admin/tool/brickfield/templates/tabtree.mustache index f6b075c0896..f4c7b528325 100644 --- a/admin/tool/brickfield/templates/tabtree.mustache +++ b/admin/tool/brickfield/templates/tabtree.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tabtree + @template tool_brickfield/tabtree Tab tree. diff --git a/admin/tool/dataprivacy/templates/context_tree_branches.mustache b/admin/tool/dataprivacy/templates/context_tree_branches.mustache index f30c470bd67..1539067f7db 100644 --- a/admin/tool/dataprivacy/templates/context_tree_branches.mustache +++ b/admin/tool/dataprivacy/templates/context_tree_branches.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tool_dataprivacy/context_tree + @template tool_dataprivacy/context_tree_branches Context tree. diff --git a/admin/tool/dataprivacy/templates/context_tree_node.mustache b/admin/tool/dataprivacy/templates/context_tree_node.mustache index 7a02e06e9d6..0598c6d2f2f 100644 --- a/admin/tool/dataprivacy/templates/context_tree_node.mustache +++ b/admin/tool/dataprivacy/templates/context_tree_node.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tool_dataprivacy/context_tree_branch + @template tool_dataprivacy/context_tree_node A tree branch. diff --git a/admin/tool/lp/templates/user_competency_summary.mustache b/admin/tool/lp/templates/user_competency_summary.mustache index 9011c8a0658..33799670c0b 100644 --- a/admin/tool/lp/templates/user_competency_summary.mustache +++ b/admin/tool/lp/templates/user_competency_summary.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tool_lp/user_competency_page + @template tool_lp/user_competency_summary Moodle template for the the summary of a user competency diff --git a/admin/tool/lp/templates/user_summary.mustache b/admin/tool/lp/templates/user_summary.mustache index 4aa459978d3..dbcf6397eb9 100644 --- a/admin/tool/lp/templates/user_summary.mustache +++ b/admin/tool/lp/templates/user_summary.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tool_lp/user-summary + @template tool_lp/user_summary Moodle template for the list of valid options in an autocomplate form element. diff --git a/auth/lti/templates/local/ltiadvantage/account_binding_complete.mustache b/auth/lti/templates/local/ltiadvantage/account_binding_complete.mustache index 2595f712189..aee5add5150 100644 --- a/auth/lti/templates/local/ltiadvantage/account_binding_complete.mustache +++ b/auth/lti/templates/local/ltiadvantage/account_binding_complete.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template auth_lti/account_binding_complete + @template auth_lti/local/ltiadvantage/account_binding_complete Template which displays the confirmation after the user has either signed in and has their account linked, or has had an account automatically provisioned and linked. diff --git a/auth/lti/templates/local/ltiadvantage/login.mustache b/auth/lti/templates/local/ltiadvantage/login.mustache index 1bdd6eabcce..f7e1d305d52 100644 --- a/auth/lti/templates/local/ltiadvantage/login.mustache +++ b/auth/lti/templates/local/ltiadvantage/login.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template auth_lti/login + @template auth_lti/local/ltiadvantage/login Template which displays a choice screen for instructors on first launch, allowing them to select whether to use an existing account in the tool, or to auto provision a new one. diff --git a/badges/templates/issued_badge.mustache b/badges/templates/issued_badge.mustache index 57077ab49c2..b4b870c377b 100644 --- a/badges/templates/issued_badge.mustache +++ b/badges/templates/issued_badge.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_badges/issued_badges + @template core_badges/issued_badge Display an issued badge. diff --git a/blocks/timeline/templates/placeholder-event-list-item.mustache b/blocks/timeline/templates/placeholder-event-list-item.mustache index e71aa23c591..2c02d5000a3 100644 --- a/blocks/timeline/templates/placeholder-event-list-item.mustache +++ b/blocks/timeline/templates/placeholder-event-list-item.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template block_timeline/event-list-item + @template block_timeline/placeholder-event-list-item This template renders an event list item loading placeholder for the timeline block. diff --git a/calendar/templates/add_event_button.mustache b/calendar/templates/add_event_button.mustache index 9c2221236c1..115e58ce5db 100644 --- a/calendar/templates/add_event_button.mustache +++ b/calendar/templates/add_event_button.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/add_event_button + @template core_calendar/add_event_button Button to launch the "Add new event" dialogue. diff --git a/calendar/templates/calendar_mini.mustache b/calendar/templates/calendar_mini.mustache index 1ddd0546080..ed7bf5ac38f 100644 --- a/calendar/templates/calendar_mini.mustache +++ b/calendar/templates/calendar_mini.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/calendar_mini + @template core_calendar/calendar_mini Calendar month view for blocks. diff --git a/calendar/templates/calendar_month.mustache b/calendar/templates/calendar_month.mustache index da4800f081a..28517c1e758 100644 --- a/calendar/templates/calendar_month.mustache +++ b/calendar/templates/calendar_month.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/calendar_month + @template core_calendar/calendar_month Calendar month view for blcoks. diff --git a/calendar/templates/calendar_threemonth.mustache b/calendar/templates/calendar_threemonth.mustache index 0da8c3a2180..5fc66f7eb47 100644 --- a/calendar/templates/calendar_threemonth.mustache +++ b/calendar/templates/calendar_threemonth.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/calendar_threemonth + @template core_calendar/calendar_threemonth @deprecated since 4.0 MDL-72810. @todo MDL-73117 This will be deleted in Moodle 4.4. diff --git a/calendar/templates/calendar_upcoming.mustache b/calendar/templates/calendar_upcoming.mustache index 0d56246b007..1edcb7c49a8 100644 --- a/calendar/templates/calendar_upcoming.mustache +++ b/calendar/templates/calendar_upcoming.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/calendar_upcoming + @template core_calendar/calendar_upcoming Calendar upcoming view. diff --git a/calendar/templates/calendar_upcoming_mini.mustache b/calendar/templates/calendar_upcoming_mini.mustache index c2317bd955f..a5ec861b865 100644 --- a/calendar/templates/calendar_upcoming_mini.mustache +++ b/calendar/templates/calendar_upcoming_mini.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_calendar/calendar_upcoming_block + @template core_calendar/calendar_upcoming_mini Calendar upcoming view. diff --git a/calendar/templates/day_navigation.mustache b/calendar/templates/day_navigation.mustache index d2c7ecad8fc..d8099eb6d0f 100644 --- a/calendar/templates/day_navigation.mustache +++ b/calendar/templates/day_navigation.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/day_navigation + @template core_calendar/day_navigation Calendar day navigation. diff --git a/calendar/templates/event_filter.mustache b/calendar/templates/event_filter.mustache index a15f2ffc119..79e42de5516 100644 --- a/calendar/templates/event_filter.mustache +++ b/calendar/templates/event_filter.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/event_filter + @template core_calendar/event_filter Filter to select which event types displayed on this page. diff --git a/calendar/templates/event_filter_key.mustache b/calendar/templates/event_filter_key.mustache index 41a5592dd5a..10ab0d4b013 100644 --- a/calendar/templates/event_filter_key.mustache +++ b/calendar/templates/event_filter_key.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/event_filter_key + @template core_calendar/event_filter_key Key item for the event filter. diff --git a/calendar/templates/event_icon.mustache b/calendar/templates/event_icon.mustache index ab58936a82e..c43b7c4ecbf 100644 --- a/calendar/templates/event_icon.mustache +++ b/calendar/templates/event_icon.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/event_icon + @template core_calendar/event_icon Event icon display. diff --git a/calendar/templates/event_subscription.mustache b/calendar/templates/event_subscription.mustache index ccfd7beb2dc..c192084be0f 100644 --- a/calendar/templates/event_subscription.mustache +++ b/calendar/templates/event_subscription.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/event_subscription + @template core_calendar/event_subscription Calendar event subscription. diff --git a/calendar/templates/header.mustache b/calendar/templates/header.mustache index 166f008e9cf..ae856708d75 100644 --- a/calendar/templates/header.mustache +++ b/calendar/templates/header.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/header + @template core_calendar/header Calendar header. diff --git a/calendar/templates/modal_event_form.mustache b/calendar/templates/modal_event_form.mustache index 99a2f59cd1f..35a01d33fa6 100644 --- a/calendar/templates/modal_event_form.mustache +++ b/calendar/templates/modal_event_form.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/modal_event_form + @template core_calendar/modal_event_form Moodle modal template with save and cancel buttons. diff --git a/calendar/templates/month_detailed.mustache b/calendar/templates/month_detailed.mustache index 4671f521f08..8236b5530f1 100644 --- a/calendar/templates/month_detailed.mustache +++ b/calendar/templates/month_detailed.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/month_detailed + @template core_calendar/month_detailed Calendar month view. diff --git a/calendar/templates/month_mini.mustache b/calendar/templates/month_mini.mustache index 7918d98416e..54909c2f99c 100644 --- a/calendar/templates/month_mini.mustache +++ b/calendar/templates/month_mini.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/month_mini + @template core_calendar/month_mini Calendar month view for blocks. diff --git a/calendar/templates/month_navigation.mustache b/calendar/templates/month_navigation.mustache index 89dcfcf13bc..3039bbb61ce 100644 --- a/calendar/templates/month_navigation.mustache +++ b/calendar/templates/month_navigation.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/month_navigation + @template core_calendar/month_navigation Calendar month navigation. diff --git a/calendar/templates/threemonth_month.mustache b/calendar/templates/threemonth_month.mustache index f842a830b79..bac1b5b68ee 100644 --- a/calendar/templates/threemonth_month.mustache +++ b/calendar/templates/threemonth_month.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/threemonth_month + @template core_calendar/threemonth_month @deprecated since 4.0 MDL-72810. @todo MDL-73117 This will be deleted in Moodle 4.4. diff --git a/calendar/templates/upcoming_detailed.mustache b/calendar/templates/upcoming_detailed.mustache index d57344f14a2..a65914c2dd3 100644 --- a/calendar/templates/upcoming_detailed.mustache +++ b/calendar/templates/upcoming_detailed.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/upcoming_detailed + @template core_calendar/upcoming_detailed Calendar upcoming detailed. diff --git a/calendar/templates/upcoming_mini.mustache b/calendar/templates/upcoming_mini.mustache index 91a7e5e3d29..79c1217d80c 100644 --- a/calendar/templates/upcoming_mini.mustache +++ b/calendar/templates/upcoming_mini.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template calendar/upcoming_mini + @template core_calendar/upcoming_mini Calendar upcoming view for blocks. diff --git a/contentbank/templates/viewcontent.mustache b/contentbank/templates/viewcontent.mustache index 2a8a8b0c873..991e4e81a11 100644 --- a/contentbank/templates/viewcontent.mustache +++ b/contentbank/templates/viewcontent.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_contentbank/view_content + @template core_contentbank/viewcontent View content page. diff --git a/course/format/templates/local/content/bulkedittoggler.mustache b/course/format/templates/local/content/bulkedittoggler.mustache index 8cde7db232c..1cd70e1e3a4 100644 --- a/course/format/templates/local/content/bulkedittoggler.mustache +++ b/course/format/templates/local/content/bulkedittoggler.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/content/bulkedittoggler + @template core_courseformat/local/content/bulkedittoggler Displays the bulk actions button in the page header. diff --git a/course/format/templates/local/content/bulkedittools.mustache b/course/format/templates/local/content/bulkedittools.mustache index a668f841049..a29f6dc4797 100644 --- a/course/format/templates/local/content/bulkedittools.mustache +++ b/course/format/templates/local/content/bulkedittools.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/content/bulkedittoggler + @template core_courseformat/local/content/bulkedittools Displays the bulk actions button in the page header. diff --git a/course/format/templates/local/content/frontpagesection.mustache b/course/format/templates/local/content/frontpagesection.mustache index 0e6c9f76edf..90624a33c2a 100644 --- a/course/format/templates/local/content/frontpagesection.mustache +++ b/course/format/templates/local/content/frontpagesection.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/local/course_format/frontpagesection + @template core_courseformat/local/content/frontpagesection Displays the frontpage section 1 (site home). diff --git a/course/format/templates/local/content/movecm.mustache b/course/format/templates/local/content/movecm.mustache index 0d31441a1fc..44ab8851558 100644 --- a/course/format/templates/local/content/movecm.mustache +++ b/course/format/templates/local/content/movecm.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/local/movemodal/movecm + @template core_courseformat/local/content/movecm Displays the course index. diff --git a/course/format/templates/local/content/movesection.mustache b/course/format/templates/local/content/movesection.mustache index 4fd981dc1ca..ff09d36b3b1 100644 --- a/course/format/templates/local/content/movesection.mustache +++ b/course/format/templates/local/content/movesection.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/local/movemodal/movesection + @template core_courseformat/local/content/movesection Displays the course index. diff --git a/course/format/templates/local/content/sectionnavigation.mustache b/course/format/templates/local/content/sectionnavigation.mustache index e584562e44e..22e5ea47e42 100644 --- a/course/format/templates/local/content/sectionnavigation.mustache +++ b/course/format/templates/local/content/sectionnavigation.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/local/course_format/sectionnavigation + @template core_courseformat/local/content/sectionnavigation Displays the course section navigation. diff --git a/course/format/templates/local/content/sectionselector.mustache b/course/format/templates/local/content/sectionselector.mustache index 86731992102..7874ea5b3b7 100644 --- a/course/format/templates/local/content/sectionselector.mustache +++ b/course/format/templates/local/content/sectionselector.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_courseformat/local/course_format/sectionselector + @template core_courseformat/local/content/sectionselector Displays the course section navigation. diff --git a/course/templates/coursecard.mustache b/course/templates/coursecard.mustache index d5ea8dc2f67..d8970d2f733 100644 --- a/course/templates/coursecard.mustache +++ b/course/templates/coursecard.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template course_course/coursecard + @template core_course/coursecard This template renders the a card for the course cards. diff --git a/course/templates/coursecards.mustache b/course/templates/coursecards.mustache index f7ba6ed1850..21a8610b7db 100644 --- a/course/templates/coursecards.mustache +++ b/course/templates/coursecards.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template block_myoverview/view-cards + @template core_course/coursecards This template renders the cards view for the myoverview block. diff --git a/course/templates/local/activitychooser/favourites.mustache b/course/templates/local/activitychooser/favourites.mustache index 2130e7086a5..15ceba69bea 100644 --- a/course/templates/local/activitychooser/favourites.mustache +++ b/course/templates/local/activitychooser/favourites.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_course/chooser_favourites + @template core_course/local/activitychooser/favourites Chooser favourite template partial. diff --git a/course/templates/local/activitychooser/help.mustache b/course/templates/local/activitychooser/help.mustache index 471dffc380f..b0ffac3aefa 100644 --- a/course/templates/local/activitychooser/help.mustache +++ b/course/templates/local/activitychooser/help.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_course/chooser_help + @template core_course/local/activitychooser/help Chooser help / more information template. diff --git a/course/templates/local/activitychooser/item.mustache b/course/templates/local/activitychooser/item.mustache index 347949858df..47f9776b145 100644 --- a/course/templates/local/activitychooser/item.mustache +++ b/course/templates/local/activitychooser/item.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_course/chooser_item + @template core_course/local/activitychooser/item Chooser item template. diff --git a/course/templates/local/activitychooser/search.mustache b/course/templates/local/activitychooser/search.mustache index 70dfac6b560..b7285fd50a5 100644 --- a/course/templates/local/activitychooser/search.mustache +++ b/course/templates/local/activitychooser/search.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_course/chooser_search + @template core_course/local/activitychooser/search Chooser search template. diff --git a/course/templates/local/activitychooser/search_results.mustache b/course/templates/local/activitychooser/search_results.mustache index a7124f16b5d..4439143c075 100644 --- a/course/templates/local/activitychooser/search_results.mustache +++ b/course/templates/local/activitychooser/search_results.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_course/chooser_search_results + @template core_course/local/activitychooser/search_results Chooser search results template. diff --git a/customfield/templates/field_data.mustache b/customfield/templates/field_data.mustache index 94d323a940c..9c3b93278a4 100644 --- a/customfield/templates/field_data.mustache +++ b/customfield/templates/field_data.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_customfield/display_field + @template core_customfield/field_data Example context (json): { diff --git a/enrol/lti/templates/local/ltiadvantage/content_select.mustache b/enrol/lti/templates/local/ltiadvantage/content_select.mustache index 04f13f31e6c..33a06edb585 100644 --- a/enrol/lti/templates/local/ltiadvantage/content_select.mustache +++ b/enrol/lti/templates/local/ltiadvantage/content_select.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template enrol_lti/content_select + @template enrol_lti/local/ltiadvantage/content_select Template which displays a list of published courses and activities. diff --git a/enrol/lti/templates/local/ltiadvantage/deployments.mustache b/enrol/lti/templates/local/ltiadvantage/deployments.mustache index 45718a8c79b..10d6f098781 100644 --- a/enrol/lti/templates/local/ltiadvantage/deployments.mustache +++ b/enrol/lti/templates/local/ltiadvantage/deployments.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template enrol_lti/loca/ltiadvantage/deployments + @template enrol_lti/local/ltiadvantage/deployments Template which displays a table view of all deployments attached to a registration, with options to delete and add. diff --git a/enrol/lti/templates/local/ltiadvantage/registered_platforms.mustache b/enrol/lti/templates/local/ltiadvantage/registered_platforms.mustache index f2e908d73ec..63a7ee5c97e 100644 --- a/enrol/lti/templates/local/ltiadvantage/registered_platforms.mustache +++ b/enrol/lti/templates/local/ltiadvantage/registered_platforms.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template enrol_lti/registered_platforms + @template enrol_lti/local/ltiadvantage/registered_platforms Template which displays a table view of all registered apps with options to add, delete and manage deployments. diff --git a/grade/grading/form/guide/templates/grades/grader/gradingpanel.mustache b/grade/grading/form/guide/templates/grades/grader/gradingpanel.mustache index 965c805ac5c..e364b774834 100644 --- a/grade/grading/form/guide/templates/grades/grader/gradingpanel.mustache +++ b/grade/grading/form/guide/templates/grades/grader/gradingpanel.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template gradingform_rubric/grades/grader/gradingpanel + @template gradingform_guide/grades/grader/gradingpanel Classes required for JS: * none diff --git a/grade/report/singleview/templates/bulkinsert.mustache b/grade/report/singleview/templates/bulkinsert.mustache index c6ddedeaf0b..0ef12da75e2 100644 --- a/grade/report/singleview/templates/bulkinsert.mustache +++ b/grade/report/singleview/templates/bulkinsert.mustache @@ -12,7 +12,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/send_bulk_message + @template gradereport_singleview/bulkinsert Template for the bulk insert grades modal. Example context (json): diff --git a/grade/report/singleview/templates/gradesearch_body.mustache b/grade/report/singleview/templates/gradesearch_body.mustache index e232ca90dd4..3a4ed2a237f 100644 --- a/grade/report/singleview/templates/gradesearch_body.mustache +++ b/grade/report/singleview/templates/gradesearch_body.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_grades/report/singleview/gradesearch_body + @template gradereport_singleview/gradesearch_body The body of the grade item widget. diff --git a/grade/report/singleview/templates/page_toggler.mustache b/grade/report/singleview/templates/page_toggler.mustache index 25f01e5c195..e16db15eb49 100644 --- a/grade/report/singleview/templates/page_toggler.mustache +++ b/grade/report/singleview/templates/page_toggler.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_grades/report/singleview/page_toggler + @template gradereport_singleview/page_toggler The small selector at the top right of the page to switch between zero states. diff --git a/grade/report/singleview/templates/report_navigation.mustache b/grade/report/singleview/templates/report_navigation.mustache index 19bbf2bd541..5973f09e640 100644 --- a/grade/report/singleview/templates/report_navigation.mustache +++ b/grade/report/singleview/templates/report_navigation.mustache @@ -12,7 +12,7 @@ along with Moodle. If not, see . }} {{! - @template gradereport_user/user_navigation + @template gradereport_singleview/report_navigation The previous/next user navigation for the user report view. Context variables required for this template: * previoususer - (optional) The object containing information about the previous user. diff --git a/grade/report/singleview/templates/zero_state_grade.mustache b/grade/report/singleview/templates/zero_state_grade.mustache index 3cf1aadba3e..8041c60b2a0 100644 --- a/grade/report/singleview/templates/zero_state_grade.mustache +++ b/grade/report/singleview/templates/zero_state_grade.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_grades/report/singleview/zero_state_grade + @template gradereport_singleview/zero_state_grade The zero state of the user report that contains the image and trigger for the search widget. diff --git a/grade/report/singleview/templates/zero_state_user.mustache b/grade/report/singleview/templates/zero_state_user.mustache index 8af52294598..280ee8b5ca3 100644 --- a/grade/report/singleview/templates/zero_state_user.mustache +++ b/grade/report/singleview/templates/zero_state_user.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_grades/report/singleview/zero_state_user + @template gradereport_singleview/zero_state_user The zero state of the user report that contains the image and trigger for the search widget. diff --git a/grade/templates/grades/grader/gradingpanel/point_blank.mustache b/grade/templates/grades/grader/gradingpanel/point_blank.mustache index eec2296ba12..ad2608283e6 100644 --- a/grade/templates/grades/grader/gradingpanel/point_blank.mustache +++ b/grade/templates/grades/grader/gradingpanel/point_blank.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_grades/grades/grader/gradingpanel/point_black + @template core_grades/grades/grader/gradingpanel/point_blank Point-based grading template for use in the grading panel. diff --git a/grade/templates/grades/grader/input.mustache b/grade/templates/grades/grader/input.mustache index 7316678e9c2..a090319c179 100644 --- a/grade/templates/grades/grader/input.mustache +++ b/grade/templates/grades/grader/input.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template gradereport_grader/input + @template core_grades/grades/grader/input Input template for grader report cell. diff --git a/grade/templates/grades/grader/scale.mustache b/grade/templates/grades/grader/scale.mustache index d0c26a76292..f60efbead79 100644 --- a/grade/templates/grades/grader/scale.mustache +++ b/grade/templates/grades/grader/scale.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template gradereport_grader/scale + @template core_grades/grades/grader/scale Scale template for grader report cell. diff --git a/grade/templates/grades/grader/text.mustache b/grade/templates/grades/grader/text.mustache index 9f1b2a84f8c..b31ee5c0d3d 100644 --- a/grade/templates/grades/grader/text.mustache +++ b/grade/templates/grades/grader/text.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template gradereport_grader/text + @template core_grades/grades/grader/text Text template for grader report cell. diff --git a/lib/editor/tiny/plugins/accessibilitychecker/templates/warning_content.mustache b/lib/editor/tiny/plugins/accessibilitychecker/templates/warning_content.mustache index 8f62f93946c..7b094747c5b 100644 --- a/lib/editor/tiny/plugins/accessibilitychecker/templates/warning_content.mustache +++ b/lib/editor/tiny/plugins/accessibilitychecker/templates/warning_content.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template tiny_accessibilitychecker/warning_contenet + @template tiny_accessibilitychecker/warning_content Display a content warning message diff --git a/lib/editor/tiny/templates/toolbar_button.mustache b/lib/editor/tiny/templates/toolbar_button.mustache index a44aeeddb31..3f846759b26 100644 --- a/lib/editor/tiny/templates/toolbar_button.mustache +++ b/lib/editor/tiny/templates/toolbar_button.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template edtior_tiny/toolbar_button + @template editor_tiny/toolbar_button Template to genearte a button for the Tiny Editor toolbar. diff --git a/lib/form/templates/element-radio-inline.mustache b/lib/form/templates/element-radio-inline.mustache index 7f99a2ec840..8dddaeccad7 100644 --- a/lib/form/templates/element-radio-inline.mustache +++ b/lib/form/templates/element-radio-inline.mustache @@ -1,5 +1,5 @@ {{! -@template theme_boost/core_form/element-radio-online +@template core_form/element-radio-inline Example context (json): { diff --git a/lib/form/templates/element-radio.mustache b/lib/form/templates/element-radio.mustache index 76fb692b590..6d5d7552ede 100644 --- a/lib/form/templates/element-radio.mustache +++ b/lib/form/templates/element-radio.mustache @@ -1,5 +1,5 @@ {{! - @template theme_boost/core_form/element-radio + @template core_form/element-radio Example context (json): { diff --git a/lib/templates/auth_digital_minor_page.mustache b/lib/templates/auth_digital_minor_page.mustache index 44c018393c9..282405819ee 100644 --- a/lib/templates/auth_digital_minor_page.mustache +++ b/lib/templates/auth_digital_minor_page.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_auth/output/digital_minor_page + @template core/auth_digital_minor_page Example context (json): { diff --git a/lib/templates/auth_verify_age_location_page.mustache b/lib/templates/auth_verify_age_location_page.mustache index 6e73f9cfcbb..843301d4071 100644 --- a/lib/templates/auth_verify_age_location_page.mustache +++ b/lib/templates/auth_verify_age_location_page.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_auth/output/verify_age_location_page + @template core/auth_verify_age_location_page Example context (json): { diff --git a/lib/templates/check/result.mustache b/lib/templates/check/result.mustache index e1fb69501e0..8f0b582389b 100644 --- a/lib/templates/check/result.mustache +++ b/lib/templates/check/result.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core/result + @template core/check/result Moodle Check API result template. diff --git a/lib/templates/check/result/error.mustache b/lib/templates/check/result/error.mustache index c4c2e5a965f..29dcbc09068 100644 --- a/lib/templates/check/result/error.mustache +++ b/lib/templates/check/result/error.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core/check/result/critical + @template core/check/result/error Moodle Check API result template. diff --git a/lib/templates/editswitch.mustache b/lib/templates/editswitch.mustache index a9b3b676e3c..e20f2d9411c 100644 --- a/lib/templates/editswitch.mustache +++ b/lib/templates/editswitch.mustache @@ -16,7 +16,7 @@ }} {{! - @template theme_boost/editswitch + @template core/editswitch This template renders the top navbar. diff --git a/lib/templates/emoji/emoji_row.mustache b/lib/templates/emoji/emoji_row.mustache index 83f1d445970..bbbbb41c2cc 100644 --- a/lib/templates/emoji/emoji_row.mustache +++ b/lib/templates/emoji/emoji_row.mustache @@ -15,9 +15,9 @@ along with Moodle. If not, see . }} {{! - @template core/emoji/picker + @template core/emoji/emoji_row - This template will render the emoji picker. + This template will render the row in the emoji picker table. Classes required for JS: * none diff --git a/lib/templates/emoji/header_row.mustache b/lib/templates/emoji/header_row.mustache index 3b7dafad05a..e3bee334bc3 100644 --- a/lib/templates/emoji/header_row.mustache +++ b/lib/templates/emoji/header_row.mustache @@ -15,9 +15,9 @@ along with Moodle. If not, see . }} {{! - @template core/emoji/picker + @template core/emoji/header_row - This template will render the emoji picker. + Header row element for the category name in the emoji picker. Classes required for JS: * none diff --git a/lib/templates/user_action_menu_submenu_items.mustache b/lib/templates/user_action_menu_submenu_items.mustache index 35a25e3eeea..60f16303cc9 100644 --- a/lib/templates/user_action_menu_submenu_items.mustache +++ b/lib/templates/user_action_menu_submenu_items.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core/user_action_menu_submenus + @template core/user_action_menu_submenu_items Template for the submenus in the user action menu. diff --git a/message/output/email/templates/email_digest_html.mustache b/message/output/email/templates/email_digest_html.mustache index d3e5a58f14f..cb09333f529 100644 --- a/message/output/email/templates/email_digest_html.mustache +++ b/message/output/email/templates/email_digest_html.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template email_message/email_digest_html + @template message_email/email_digest_html Template which defines a forum post for sending in a single-post HTML email. diff --git a/message/output/email/templates/email_digest_text.mustache b/message/output/email/templates/email_digest_text.mustache index e09ca39e534..5ec03fe9c62 100644 --- a/message/output/email/templates/email_digest_text.mustache +++ b/message/output/email/templates/email_digest_text.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template email_message/email_digest_text + @template message_email/email_digest_text Template which defines a forum post for sending in a single-post HTML email. diff --git a/message/output/popup/templates/message_content_item.mustache b/message/output/popup/templates/message_content_item.mustache index f24a8aeb424..33663352ff6 100644 --- a/message/output/popup/templates/message_content_item.mustache +++ b/message/output/popup/templates/message_content_item.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template message_output_popup/message_content_item + @template message_popup/message_content_item This template will render the message content item for the navigation bar message menu. diff --git a/message/output/popup/templates/notification_content_item.mustache b/message/output/popup/templates/notification_content_item.mustache index 16bde2187c4..6da6648a1d9 100644 --- a/message/output/popup/templates/notification_content_item.mustache +++ b/message/output/popup/templates/notification_content_item.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template message_output_popup/notification_content_item + @template message_popup/notification_content_item This template will render the notification content item for the navigation bar notification menu. diff --git a/message/output/popup/templates/notification_popover.mustache b/message/output/popup/templates/notification_popover.mustache index 680eb589ef0..09058f216e1 100644 --- a/message/output/popup/templates/notification_popover.mustache +++ b/message/output/popup/templates/notification_popover.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template message_output_popup/notification_popover + @template message_popup/notification_popover This template will render the notification popover for the navigation bar. diff --git a/message/templates/message_drawer_view_contacts_body_section_requests_list.mustache b/message/templates/message_drawer_view_contacts_body_section_requests_list.mustache index 4ca2482cb3b..52061c5afc6 100644 --- a/message/templates/message_drawer_view_contacts_body_section_requests_list.mustache +++ b/message/templates/message_drawer_view_contacts_body_section_requests_list.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_contacts_list + @template core_message/message_drawer_view_contacts_body_section_requests_list This template will render a list of contacts for the message drawer. diff --git a/message/templates/message_drawer_view_conversation_body.mustache b/message/templates/message_drawer_view_conversation_body.mustache index 93636fb8266..00154cd0b28 100644 --- a/message/templates/message_drawer_view_conversation_body.mustache +++ b/message/templates/message_drawer_view_conversation_body.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_conversation_body + @template core_message/message_drawer_view_conversation_body This template will render the body container for the conversation page in the message drawer. diff --git a/message/templates/message_drawer_view_conversation_body_day_placeholder.mustache b/message/templates/message_drawer_view_conversation_body_day_placeholder.mustache index 032cc3ad64b..ca5e019c3f3 100644 --- a/message/templates/message_drawer_view_conversation_body_day_placeholder.mustache +++ b/message/templates/message_drawer_view_conversation_body_day_placeholder.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_covnersation_body_day_placeholder + @template core_message/message_drawer_view_conversation_body_day_placeholder This template will render the loading placeholder elements for a day of messages in the conversation page of the message drawer. diff --git a/message/templates/message_drawer_view_conversation_footer_unable_to_message.mustache b/message/templates/message_drawer_view_conversation_footer_unable_to_message.mustache index 8a203a22554..be2a91b1766 100644 --- a/message/templates/message_drawer_view_conversation_footer_unable_to_message.mustache +++ b/message/templates/message_drawer_view_conversation_footer_unable_to_message.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_conversation_unable_to_message + @template core_message/message_drawer_view_conversation_footer_unable_to_message This template will render the footer content when the user is unable to message in a conversation in the message drawer. diff --git a/message/templates/message_drawer_view_conversation_header_content_type_private.mustache b/message/templates/message_drawer_view_conversation_header_content_type_private.mustache index 2ea58936dc1..712b10bdd6f 100644 --- a/message/templates/message_drawer_view_conversation_header_content_type_private.mustache +++ b/message/templates/message_drawer_view_conversation_header_content_type_private.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_conversation_heeader_content + @template core_message/message_drawer_view_conversation_header_content_type_private This template will render the header content of the conversation page in the message message drawer. diff --git a/message/templates/message_drawer_view_conversation_header_content_type_private_no_controls.mustache b/message/templates/message_drawer_view_conversation_header_content_type_private_no_controls.mustache index 799ba62eb24..adf4c4adc1d 100644 --- a/message/templates/message_drawer_view_conversation_header_content_type_private_no_controls.mustache +++ b/message/templates/message_drawer_view_conversation_header_content_type_private_no_controls.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_conversation_heeader_content_type_private_no_controls + @template core_message/message_drawer_view_conversation_header_content_type_private_no_controls This template will render the header content of the conversation page without controls in the message message drawer. diff --git a/message/templates/message_drawer_view_conversation_header_content_type_public.mustache b/message/templates/message_drawer_view_conversation_header_content_type_public.mustache index f1bae5f9ba2..88b24812cd8 100644 --- a/message/templates/message_drawer_view_conversation_header_content_type_public.mustache +++ b/message/templates/message_drawer_view_conversation_header_content_type_public.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_conversation_heeader_content + @template core_message/message_drawer_view_conversation_header_content_type_public This template will render the header content of the conversation page in the message message drawer. diff --git a/message/templates/message_drawer_view_overview_footer.mustache b/message/templates/message_drawer_view_overview_footer.mustache index 6772e643b9c..dfcff6e2641 100644 --- a/message/templates/message_drawer_view_overview_footer.mustache +++ b/message/templates/message_drawer_view_overview_footer.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_overview_message_page_link + @template core_message/message_drawer_view_overview_footer This template will render the body of the overview section of the message drawer. diff --git a/message/templates/message_drawer_view_overview_section_group_messages.mustache b/message/templates/message_drawer_view_overview_section_group_messages.mustache index 48c169cf455..3b664c09c32 100644 --- a/message/templates/message_drawer_view_overview_section_group_messages.mustache +++ b/message/templates/message_drawer_view_overview_section_group_messages.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_drawer_view_overview_section_group_mesages + @template core_message/message_drawer_view_overview_section_group_messages This template will render the group messages section of the overview page in the message drawer. diff --git a/message/templates/message_jumpto.mustache b/message/templates/message_jumpto.mustache index a1e53a4308b..328c5fea55a 100644 --- a/message/templates/message_jumpto.mustache +++ b/message/templates/message_jumpto.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/message_jump_botton + @template core_message/message_jumpto This template will render the jump button used for keyboard navigation. diff --git a/message/templates/remove_contact_button.mustache b/message/templates/remove_contact_button.mustache index 70b9fda103b..4373be4beb0 100644 --- a/message/templates/remove_contact_button.mustache +++ b/message/templates/remove_contact_button.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_message/add_contact_button + @template core_message/remove_contact_button Template for the contents of the add contact button on the user's profile page. diff --git a/mod/bigbluebuttonbn/templates/element_text_with_copy.mustache b/mod/bigbluebuttonbn/templates/element_text_with_copy.mustache index 2913954ae7d..d2b0acc91d4 100644 --- a/mod/bigbluebuttonbn/templates/element_text_with_copy.mustache +++ b/mod/bigbluebuttonbn/templates/element_text_with_copy.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_bigbluebuttonbn/text_with-copy + @template mod_bigbluebuttonbn/element_text_with_copy This template renders a text input form element with a copy link next to it. diff --git a/mod/bigbluebuttonbn/templates/mobile_view_page_ionic3.mustache b/mod/bigbluebuttonbn/templates/mobile_view_page_ionic3.mustache index 578c9ba4f30..e2a20f447b1 100644 --- a/mod/bigbluebuttonbn/templates/mobile_view_page_ionic3.mustache +++ b/mod/bigbluebuttonbn/templates/mobile_view_page_ionic3.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_bigbluebuttonbn/mobile_view_page + @template mod_bigbluebuttonbn/mobile_view_page_ionic3 This template renders the mobile page. diff --git a/mod/bigbluebuttonbn/templates/mobile_view_page_latest.mustache b/mod/bigbluebuttonbn/templates/mobile_view_page_latest.mustache index adffe0d859d..3a3515376c5 100644 --- a/mod/bigbluebuttonbn/templates/mobile_view_page_latest.mustache +++ b/mod/bigbluebuttonbn/templates/mobile_view_page_latest.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_bigbluebuttonbn/mobile_view_page + @template mod_bigbluebuttonbn/mobile_view_page_latest This template renders the mobile page. diff --git a/mod/bigbluebuttonbn/templates/recordings_table.mustache b/mod/bigbluebuttonbn/templates/recordings_table.mustache index b1fdbb069ad..4b6aa2d76b6 100644 --- a/mod/bigbluebuttonbn/templates/recordings_table.mustache +++ b/mod/bigbluebuttonbn/templates/recordings_table.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_bigbluebuttonbn/recording_table + @template mod_bigbluebuttonbn/recordings_table This template renders the mobile page. diff --git a/mod/data/templates/fields_mapping_body.mustache b/mod/data/templates/fields_mapping_body.mustache index 4feb12e33cb..c716f5e0d43 100644 --- a/mod/data/templates/fields_mapping_body.mustache +++ b/mod/data/templates/fields_mapping_body.mustache @@ -12,7 +12,7 @@ along with Moodle. If not, see . }} {{! - @template mod_data/field_mapping_modal + @template mod_data/fields_mapping_body Display a modal to decide on field mapping diff --git a/mod/data/templates/fields_mapping_footer.mustache b/mod/data/templates/fields_mapping_footer.mustache index 9db4b5c029a..31df84ac338 100644 --- a/mod/data/templates/fields_mapping_footer.mustache +++ b/mod/data/templates/fields_mapping_footer.mustache @@ -12,7 +12,7 @@ along with Moodle. If not, see . }} {{! - @template mod_data/field_mapping_modal + @template mod_data/fields_mapping_footer Display a modal to decide on field mapping diff --git a/mod/data/templates/view_noentries.mustache b/mod/data/templates/view_noentries.mustache index c8eade57387..ae3a196f707 100644 --- a/mod/data/templates/view_noentries.mustache +++ b/mod/data/templates/view_noentries.mustache @@ -12,7 +12,7 @@ along with Moodle. If not, see . }} {{! - @template mod_data/view_no_fields_nomanagers + @template mod_data/view_noentries Form containing all database presets displayed within a table. diff --git a/mod/forum/report/summary/templates/filter_dates_popover.mustache b/mod/forum/report/summary/templates/filter_dates_popover.mustache index e1d6329126c..469e0e8493e 100644 --- a/mod/forum/report/summary/templates/filter_dates_popover.mustache +++ b/mod/forum/report/summary/templates/filter_dates_popover.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template forumreport_summary/filter_dates + @template forumreport_summary/filter_dates_popover Summary report dates filter. diff --git a/mod/forum/templates/discussion_favourite_toggle.mustache b/mod/forum/templates/discussion_favourite_toggle.mustache index 246ab35d148..828c442ee70 100644 --- a/mod/forum/templates/discussion_favourite_toggle.mustache +++ b/mod/forum/templates/discussion_favourite_toggle.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/discussion_subscription_toggle + @template mod_forum/discussion_favourite_toggle Template to display the discussion subscription toggle. diff --git a/mod/forum/templates/discussion_pin_toggle.mustache b/mod/forum/templates/discussion_pin_toggle.mustache index de2f5b655bf..f3fa3788e4c 100644 --- a/mod/forum/templates/discussion_pin_toggle.mustache +++ b/mod/forum/templates/discussion_pin_toggle.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/discussion_subscription_toggle + @template mod_forum/discussion_pin_toggle Template to display the discussion subscription toggle. diff --git a/mod/forum/templates/forum_discussion_favourite_toggle.mustache b/mod/forum/templates/forum_discussion_favourite_toggle.mustache index 79fef67ccb6..6d31a6bcf8f 100644 --- a/mod/forum/templates/forum_discussion_favourite_toggle.mustache +++ b/mod/forum/templates/forum_discussion_favourite_toggle.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/forum_discussion_nested_post + @template mod_forum/forum_discussion_favourite_toggle Template which defines a forum post for sending in a single-post HTML email. diff --git a/mod/forum/templates/forum_discussion_nested_v2_post_reply.mustache b/mod/forum/templates/forum_discussion_nested_v2_post_reply.mustache index b21ef816b29..5c8e8fc16c0 100644 --- a/mod/forum/templates/forum_discussion_nested_v2_post_reply.mustache +++ b/mod/forum/templates/forum_discussion_nested_v2_post_reply.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/forum_discussion_post + @template mod_forum/forum_discussion_nested_v2_post_reply Template to render a single post from a discussion. diff --git a/mod/forum/templates/forum_post_email_htmlemail_body.mustache b/mod/forum/templates/forum_post_email_htmlemail_body.mustache index 4b58ba2943b..e8ee3ab6f83 100644 --- a/mod/forum/templates/forum_post_email_htmlemail_body.mustache +++ b/mod/forum/templates/forum_post_email_htmlemail_body.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/forum_post_emaildigestfull_htmlemail_body + @template mod_forum/forum_post_email_htmlemail_body Template which defines the body component of a forum post for sending in a single-post HTML email. diff --git a/mod/forum/templates/frontpage_news_discussion_list.mustache b/mod/forum/templates/frontpage_news_discussion_list.mustache index ed1d27b1748..cbfa575bf0e 100644 --- a/mod/forum/templates/frontpage_news_discussion_list.mustache +++ b/mod/forum/templates/frontpage_news_discussion_list.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/social_discussion_list + @template mod_forum/frontpage_news_discussion_list Template which defines a forum post for sending in a single-post HTML email. diff --git a/mod/forum/templates/grades/grader/discussion/post_modal.mustache b/mod/forum/templates/grades/grader/discussion/post_modal.mustache index f48858b8fe3..1f36ef380f3 100644 --- a/mod/forum/templates/grades/grader/discussion/post_modal.mustache +++ b/mod/forum/templates/grades/grader/discussion/post_modal.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/forum_discussion_post_modal + @template mod_forum/grades/grader/discussion/post_modal Template to render a single post from a discussion. diff --git a/mod/forum/templates/grades/grader/discussion/posts.mustache b/mod/forum/templates/grades/grader/discussion/posts.mustache index 8f902bc6dbc..d62bff737ed 100644 --- a/mod/forum/templates/grades/grader/discussion/posts.mustache +++ b/mod/forum/templates/grades/grader/discussion/posts.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/forum_grader_discussion_posts + @template mod_forum/grades/grader/discussion/posts Template to render a list of posts for a discussion. diff --git a/mod/forum/templates/grades/view_grade_button.mustache b/mod/forum/templates/grades/view_grade_button.mustache index 5a65a34f34f..d706126e7ca 100644 --- a/mod/forum/templates/grades/view_grade_button.mustache +++ b/mod/forum/templates/grades/view_grade_button.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/grades/grade_button + @template mod_forum/grades/view_grade_button Template which defines a forum post for sending in a single-post HTML email. diff --git a/mod/forum/templates/local/grades/grader.mustache b/mod/forum/templates/local/grades/grader.mustache index 5c526304bad..72f4085c7b8 100644 --- a/mod/forum/templates/local/grades/grader.mustache +++ b/mod/forum/templates/local/grades/grader.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/local/grades/local/grader + @template mod_forum/local/grades/grader Classes required for JS: * TODO diff --git a/mod/forum/templates/local/grades/view_grade.mustache b/mod/forum/templates/local/grades/view_grade.mustache index b5db349afe4..6dd4aa2dc5d 100644 --- a/mod/forum/templates/local/grades/view_grade.mustache +++ b/mod/forum/templates/local/grades/view_grade.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template mod_forum/local/grades/local/view_grade + @template mod_forum/local/grades/view_grade Classes required for JS: * none diff --git a/mod/scorm/templates/user_report_actionbar.mustache b/mod/scorm/templates/user_report_actionbar.mustache index 932c1a3cbf5..1aaf9b13ee9 100644 --- a/mod/scorm/templates/user_report_actionbar.mustache +++ b/mod/scorm/templates/user_report_actionbar.mustache @@ -12,7 +12,8 @@ along with Moodle. If not, see . }} {{! - @template mod_scorm/report_actionbar + @template mod_scorm/user_report_actionbar + Actions bar for the user reports page UI. Classes required for JS: * none diff --git a/payment/templates/fee_breakdown.mustache b/payment/templates/fee_breakdown.mustache index 1483461515f..a9b5cf32ea7 100644 --- a/payment/templates/fee_breakdown.mustache +++ b/payment/templates/fee_breakdown.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template core_payment/fee_breakdown_placeholder + @template core_payment/fee_breakdown Classes required for JS: * none diff --git a/question/bank/viewcreator/templates/version_info.mustache b/question/bank/viewcreator/templates/version_info.mustache index b7e6e64779f..3898c4feb6f 100644 --- a/question/bank/viewcreator/templates/version_info.mustache +++ b/question/bank/viewcreator/templates/version_info.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template qbank_editquestion/version_info + @template qbank_viewcreator/version_info Example context (json): { diff --git a/report/insights/templates/bulk_actions.mustache b/report/insights/templates/bulk_actions.mustache index 3248dc0caaf..7efc3251bca 100644 --- a/report/insights/templates/bulk_actions.mustache +++ b/report/insights/templates/bulk_actions.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template report_insights/insight_details + @template report_insights/bulk_actions Actions panel at the bottom of the assignment grading UI. diff --git a/theme/boost/templates/core/sticky_footer.mustache b/theme/boost/templates/core/sticky_footer.mustache index b35c8395387..9508a1d9dc7 100644 --- a/theme/boost/templates/core/sticky_footer.mustache +++ b/theme/boost/templates/core/sticky_footer.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template theme_boost/core/sticky_footer + @template core/sticky_footer Displays a page sticky footer element. diff --git a/theme/boost/templates/embedded.mustache b/theme/boost/templates/embedded.mustache index ab390c5a0a0..fe8dff905a7 100644 --- a/theme/boost/templates/embedded.mustache +++ b/theme/boost/templates/embedded.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template theme_boost/maintenance + @template theme_boost/embedded Boost maintenance layout template. diff --git a/theme/classic/templates/core/full_header.mustache b/theme/classic/templates/core/full_header.mustache index 3928046ef52..461486e4972 100644 --- a/theme/classic/templates/core/full_header.mustache +++ b/theme/classic/templates/core/full_header.mustache @@ -15,7 +15,7 @@ along with Moodle. If not, see . }} {{! - @template theme_classic/header + @template core/full_header This template renders the header. From fcf887919b457b097284ccefea2d15885f1df71d Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Wed, 8 Feb 2023 11:04:52 +0000 Subject: [PATCH 3/5] MDL-77164 lib/pear: correct phpdocs --- lib/pear/HTML/Common.php | 2 +- lib/pear/HTML/QuickForm/select.php | 2 +- lib/pear/readme_moodle.txt | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pear/HTML/Common.php b/lib/pear/HTML/Common.php index 3797cc3b736..33023e044a7 100644 --- a/lib/pear/HTML/Common.php +++ b/lib/pear/HTML/Common.php @@ -274,7 +274,7 @@ class HTML_Common { * @param string $attr Attribute name * @since 1.5 * @access public - * @return void + * @return mixed * @throws */ function getAttribute($attr) diff --git a/lib/pear/HTML/QuickForm/select.php b/lib/pear/HTML/QuickForm/select.php index eda84388c4c..d06b40181e3 100644 --- a/lib/pear/HTML/QuickForm/select.php +++ b/lib/pear/HTML/QuickForm/select.php @@ -46,7 +46,7 @@ class HTML_QuickForm_select extends HTML_QuickForm_element { /** * Default values of the SELECT * - * @var string + * @var array * @since 1.0 * @access private */ diff --git a/lib/pear/readme_moodle.txt b/lib/pear/readme_moodle.txt index b3a0e70d4b7..556c32f803b 100644 --- a/lib/pear/readme_moodle.txt +++ b/lib/pear/readme_moodle.txt @@ -34,6 +34,7 @@ MDL-71126 - Quiz: Manual grading page size preference can get stuck at 0 - New positiveint regex rule to check if the value is a positive integer MDL-76102 / MDL-77081 PHP 8.1 passing null to a non-nullable argument of a built-in function is deprecated +MDL-77164 - PHPdocs corrections Pear ==== From 4d765cd6993d9b029a3fbb2d13d2772e918c17a0 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 28 Feb 2023 13:42:50 +0000 Subject: [PATCH 4/5] MDL-77164 privacy: typehint test content writer --- admin/roles/tests/privacy/provider_test.php | 4 ++++ admin/tool/mobile/tests/privacy/provider_test.php | 1 + auth/mnet/tests/privacy/provider_test.php | 1 + blocks/html/tests/privacy/provider_test.php | 2 ++ calendar/tests/privacy/provider_test.php | 1 + enrol/cohort/tests/privacy/provider_test.php | 1 + enrol/meta/tests/privacy/provider_test.php | 1 + .../form/guide/tests/privacy/provider_test.php | 1 + grade/grading/tests/privacy/provider_test.php | 1 + .../report/grader/tests/privacy/provider_test.php | 2 ++ grade/report/user/tests/privacy/provider_test.php | 1 + group/tests/privacy/provider_test.php | 3 +++ lib/editor/atto/tests/privacy/provider_test.php | 3 +++ lib/editor/tests/privacy/provider_test.php | 14 ++++++++++---- lib/userkey/tests/privacy/provider_test.php | 9 +++++++++ mod/assign/tests/privacy/provider_test.php | 2 ++ .../accessrule/seb/tests/privacy/provider_test.php | 1 + mod/quiz/tests/privacy/provider_test.php | 2 ++ .../report/basic/tests/privacy/provider_test.php | 1 + .../interactions/tests/privacy/provider_test.php | 1 + .../objectives/tests/privacy/provider_test.php | 1 + notes/tests/privacy/provider_test.php | 1 + question/tests/privacy/provider_test.php | 3 +++ question/tests/privacy_helper.php | 1 + rating/tests/privacy/provider_test.php | 5 +++++ rss/tests/privacy/provider_test.php | 1 + tag/tests/privacy/provider_test.php | 2 ++ 27 files changed, 62 insertions(+), 4 deletions(-) diff --git a/admin/roles/tests/privacy/provider_test.php b/admin/roles/tests/privacy/provider_test.php index 2504be7f822..4846ac74b5e 100644 --- a/admin/roles/tests/privacy/provider_test.php +++ b/admin/roles/tests/privacy/provider_test.php @@ -53,6 +53,7 @@ class provider_test extends provider_testcase { $showadvanced = 1; set_user_preference('definerole_showadvanced', $showadvanced); provider::export_user_preferences($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context(\context_system::instance()); $prefs = $writer->get_user_preferences('core_role'); $this->assertEquals(transform::yesno($showadvanced), transform::yesno($prefs->definerole_showadvanced->value)); @@ -184,6 +185,7 @@ class provider_test extends provider_testcase { // Retrieve role capabilities and role assignments. provider::export_user_data($approvedcontextlist); foreach ($contextlist as $context) { + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); if ($context->contextlevel == CONTEXT_MODULE) { @@ -413,6 +415,7 @@ class provider_test extends provider_testcase { ]; // Test User is assigned role teacher to cohort. provider::export_user_role_to_cohort($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($contextuserassignover); $this->assertTrue($writer->has_any_data()); $exported = (array)$writer->get_related_data($subcontextteacher, 'cohortroles'); @@ -430,6 +433,7 @@ class provider_test extends provider_testcase { api::create_cohort_role_assignment($params); api::sync_all_cohort_roles(); provider::export_user_role_to_cohort($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($contextuser); $this->assertTrue($writer->has_any_data()); $exported = (array)$writer->get_related_data($subcontextteacher, 'cohortroles'); diff --git a/admin/tool/mobile/tests/privacy/provider_test.php b/admin/tool/mobile/tests/privacy/provider_test.php index 6d2fd7d324d..92add10ad65 100644 --- a/admin/tool/mobile/tests/privacy/provider_test.php +++ b/admin/tool/mobile/tests/privacy/provider_test.php @@ -111,6 +111,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $key = $DB->get_record('user_private_key', ['value' => $keyvalue]); // Validate exported data. $this->setUser($user); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); $this->export_context_data_for_user($user->id, $context, 'tool_mobile'); diff --git a/auth/mnet/tests/privacy/provider_test.php b/auth/mnet/tests/privacy/provider_test.php index 01fac8140b2..a41ac4de0f8 100644 --- a/auth/mnet/tests/privacy/provider_test.php +++ b/auth/mnet/tests/privacy/provider_test.php @@ -106,6 +106,7 @@ class provider_test extends provider_testcase { $usercontext = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($usercontext); $this->assertFalse($writer->has_any_data()); $approvedlist = new approved_contextlist($user, 'auth_mnet', [$usercontext->id]); diff --git a/blocks/html/tests/privacy/provider_test.php b/blocks/html/tests/privacy/provider_test.php index 1348d130a1a..e776d0ae662 100644 --- a/blocks/html/tests/privacy/provider_test.php +++ b/blocks/html/tests/privacy/provider_test.php @@ -185,6 +185,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export the data. $this->export_context_data_for_user($user->id, $context, 'block_html'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = \core_privacy\local\request\writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -233,6 +234,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export the data. $this->export_context_data_for_user($user->id, $context, 'block_html'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = \core_privacy\local\request\writer::with_context($context); $this->assertFalse($writer->has_any_data()); } diff --git a/calendar/tests/privacy/provider_test.php b/calendar/tests/privacy/provider_test.php index 8645f0d5966..0d4b57a908a 100644 --- a/calendar/tests/privacy/provider_test.php +++ b/calendar/tests/privacy/provider_test.php @@ -180,6 +180,7 @@ class provider_test extends provider_testcase { provider::export_user_data($approvedcontextlist); foreach ($contextlist as $context) { + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); diff --git a/enrol/cohort/tests/privacy/provider_test.php b/enrol/cohort/tests/privacy/provider_test.php index a31f2a24984..d6296134042 100644 --- a/enrol/cohort/tests/privacy/provider_test.php +++ b/enrol/cohort/tests/privacy/provider_test.php @@ -114,6 +114,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $approvedcontextlist = new approved_contextlist($user1, 'enrol_cohort', $contextlist->get_contextids()); provider::export_user_data($approvedcontextlist); foreach ($contextlist as $context) { + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $data = $writer->get_data([ get_string('pluginname', 'enrol_cohort'), diff --git a/enrol/meta/tests/privacy/provider_test.php b/enrol/meta/tests/privacy/provider_test.php index 1a278df8a38..c7c954a8a15 100644 --- a/enrol/meta/tests/privacy/provider_test.php +++ b/enrol/meta/tests/privacy/provider_test.php @@ -103,6 +103,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $approvedcontextlist = new approved_contextlist($user1, 'enrol_meta', $contextlist->get_contextids()); provider::export_user_data($approvedcontextlist); foreach ($contextlist as $context) { + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $data = $writer->get_data([ get_string('pluginname', 'enrol_meta'), diff --git a/grade/grading/form/guide/tests/privacy/provider_test.php b/grade/grading/form/guide/tests/privacy/provider_test.php index 7348ba18adb..c114b8537a5 100644 --- a/grade/grading/form/guide/tests/privacy/provider_test.php +++ b/grade/grading/form/guide/tests/privacy/provider_test.php @@ -67,6 +67,7 @@ class provider_test extends provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('gradingform_guide'); diff --git a/grade/grading/tests/privacy/provider_test.php b/grade/grading/tests/privacy/provider_test.php index 40823d75980..c24065fce62 100644 --- a/grade/grading/tests/privacy/provider_test.php +++ b/grade/grading/tests/privacy/provider_test.php @@ -110,6 +110,7 @@ class provider_test extends provider_testcase { $this->setUser($user); $context = \context_system::instance(); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); $this->export_context_data_for_user($user->id, $context, 'core_grading'); diff --git a/grade/report/grader/tests/privacy/provider_test.php b/grade/report/grader/tests/privacy/provider_test.php index ca68563f1d6..1557d1c8e79 100644 --- a/grade/report/grader/tests/privacy/provider_test.php +++ b/grade/report/grader/tests/privacy/provider_test.php @@ -77,6 +77,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data for our test user. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('gradereport_grader'); @@ -99,6 +100,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('gradereport_grader'); diff --git a/grade/report/user/tests/privacy/provider_test.php b/grade/report/user/tests/privacy/provider_test.php index e8f45ed9f92..58ac0271b85 100644 --- a/grade/report/user/tests/privacy/provider_test.php +++ b/grade/report/user/tests/privacy/provider_test.php @@ -67,6 +67,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('gradereport_user'); diff --git a/group/tests/privacy/provider_test.php b/group/tests/privacy/provider_test.php index af30c2ec835..3345b1a8f41 100644 --- a/group/tests/privacy/provider_test.php +++ b/group/tests/privacy/provider_test.php @@ -90,6 +90,7 @@ class provider_test extends provider_testcase { // Retrieve groups for user1. $this->setUser($user1); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); provider::export_groups($context, ''); @@ -134,6 +135,7 @@ class provider_test extends provider_testcase { // Retrieve groups for user1. $this->setUser($user1); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); provider::export_groups($context, 'enrol_self'); @@ -792,6 +794,7 @@ class provider_test extends provider_testcase { // Export all of the data for the context. $this->export_context_data_for_user($user1->id, $context, 'core_group'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); diff --git a/lib/editor/atto/tests/privacy/provider_test.php b/lib/editor/atto/tests/privacy/provider_test.php index 258d0385f3f..1920417e1a1 100644 --- a/lib/editor/atto/tests/privacy/provider_test.php +++ b/lib/editor/atto/tests/privacy/provider_test.php @@ -118,6 +118,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export the data for the system context. // There should be two. $this->export_context_data_for_user($user->id, $systemcontext, 'editor_atto'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = \core_privacy\local\request\writer::with_context($systemcontext); $this->assertTrue($writer->has_any_data()); @@ -535,6 +536,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Should have the data. $this->export_context_data_for_user($user->id, $usercontext, 'editor_atto'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = \core_privacy\local\request\writer::with_context($usercontext); $this->assertTrue($writer->has_any_data()); @@ -587,6 +589,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Should have the data. $this->export_context_data_for_user($user->id, $otherusercontext, 'editor_atto'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = \core_privacy\local\request\writer::with_context($otherusercontext); $this->assertTrue($writer->has_any_data()); diff --git a/lib/editor/tests/privacy/provider_test.php b/lib/editor/tests/privacy/provider_test.php index 79fb31da8b9..6bacfa61ab3 100644 --- a/lib/editor/tests/privacy/provider_test.php +++ b/lib/editor/tests/privacy/provider_test.php @@ -47,7 +47,9 @@ class provider_test extends \core_privacy\tests\provider_testcase { $this->setAdminUser(); provider::export_user_preferences($USER->id); - $this->assertFalse(writer::with_context(\context_system::instance())->has_any_data()); + /** @var \core_privacy\tests\request\content_writer $writer */ + $writer = writer::with_context(\context_system::instance()); + $this->assertFalse($writer->has_any_data()); } /** @@ -67,7 +69,9 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export test users preferences. provider::export_user_preferences($user->id); - $this->assertFalse(writer::with_context(\context_system::instance())->has_any_data()); + /** @var \core_privacy\tests\request\content_writer $writer */ + $writer = writer::with_context(\context_system::instance()); + $this->assertFalse($writer->has_any_data()); } /** @@ -87,9 +91,11 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export test users preferences. provider::export_user_preferences($user->id); - $this->assertTrue(writer::with_context(\context_system::instance())->has_any_data()); + /** @var \core_privacy\tests\request\content_writer $writer */ + $writer = writer::with_context(\context_system::instance()); + $this->assertTrue($writer->has_any_data()); - $prefs = writer::with_context(\context_system::instance())->get_user_preferences('core_editor'); + $prefs = $writer->get_user_preferences('core_editor'); $this->assertNotEmpty($prefs->htmleditor); $this->assertNotEmpty($prefs->htmleditor->value); $this->assertNotEmpty($prefs->htmleditor->description); diff --git a/lib/userkey/tests/privacy/provider_test.php b/lib/userkey/tests/privacy/provider_test.php index 8eeeaf526b0..bbca41ea486 100644 --- a/lib/userkey/tests/privacy/provider_test.php +++ b/lib/userkey/tests/privacy/provider_test.php @@ -70,6 +70,7 @@ class provider_test extends provider_testcase { provider::export_userkeys($context, $subcontext, 'core_tests'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -107,6 +108,7 @@ class provider_test extends provider_testcase { // Export all keys in core_tests. provider::export_userkeys($context, $subcontext, 'core_tests'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -143,6 +145,7 @@ class provider_test extends provider_testcase { provider::export_userkeys($context, $subcontext, 'core_tests'); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -179,11 +182,13 @@ class provider_test extends provider_testcase { // Export all keys in core_tests against instance 43 - no keys. provider::export_userkeys($context, $subcontext, 'core_tests', 43); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); // Export all keys in core_tests against instance 42. provider::export_userkeys($context, $subcontext, 'core_tests', 42); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $exported = $writer->get_related_data($subcontext, 'userkeys'); @@ -224,11 +229,13 @@ class provider_test extends provider_testcase { // Export all keys in core_tests against instance 43 - no keys. provider::export_userkeys($context, $subcontext, 'core_tests', 43); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); // Export all keys in core_tests against instance 42. provider::export_userkeys($context, $subcontext, 'core_tests', 42); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $exported = $writer->get_related_data($subcontext, 'userkeys'); @@ -278,11 +285,13 @@ class provider_test extends provider_testcase { // Export all keys in core_tests against instance 43 - no keys. provider::export_userkeys($context, $subcontext, 'core_tests', 43); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); // Export all keys in core_tests against instance 42. provider::export_userkeys($context, $subcontext, 'core_tests', 42); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $exported = $writer->get_related_data($subcontext, 'userkeys'); diff --git a/mod/assign/tests/privacy/provider_test.php b/mod/assign/tests/privacy/provider_test.php index a3efabce75c..d773bdfff12 100644 --- a/mod/assign/tests/privacy/provider_test.php +++ b/mod/assign/tests/privacy/provider_test.php @@ -299,6 +299,7 @@ class provider_test extends provider_testcase { // Give the submission a grade. $assign->save_grade($user->id, $data); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); @@ -411,6 +412,7 @@ class provider_test extends provider_testcase { $flagdata->extensionduedate = $duedate; $assign->update_user_flags($flagdata); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); diff --git a/mod/quiz/accessrule/seb/tests/privacy/provider_test.php b/mod/quiz/accessrule/seb/tests/privacy/provider_test.php index 3ece5a279a0..836326f5e3c 100644 --- a/mod/quiz/accessrule/seb/tests/privacy/provider_test.php +++ b/mod/quiz/accessrule/seb/tests/privacy/provider_test.php @@ -119,6 +119,7 @@ class provider_test extends provider_testcase { ); writer::reset(); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); provider::export_user_data($approvedcontextlist); diff --git a/mod/quiz/tests/privacy/provider_test.php b/mod/quiz/tests/privacy/provider_test.php index ffba8269df1..559ea67d732 100644 --- a/mod/quiz/tests/privacy/provider_test.php +++ b/mod/quiz/tests/privacy/provider_test.php @@ -170,6 +170,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { provider::export_user_data($approvedcontextlist); // Ensure that the quiz data was exported correctly. + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -366,6 +367,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { provider::export_user_data($approvedcontextlist); // Ensure that nothing was exported. + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data_in_any_context()); diff --git a/mod/scorm/report/basic/tests/privacy/provider_test.php b/mod/scorm/report/basic/tests/privacy/provider_test.php index da05406c1e7..8d781849570 100644 --- a/mod/scorm/report/basic/tests/privacy/provider_test.php +++ b/mod/scorm/report/basic/tests/privacy/provider_test.php @@ -68,6 +68,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('scormreport_basic'); diff --git a/mod/scorm/report/interactions/tests/privacy/provider_test.php b/mod/scorm/report/interactions/tests/privacy/provider_test.php index 6add72fe501..c87dbcb45f4 100644 --- a/mod/scorm/report/interactions/tests/privacy/provider_test.php +++ b/mod/scorm/report/interactions/tests/privacy/provider_test.php @@ -71,6 +71,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('scormreport_interactions'); diff --git a/mod/scorm/report/objectives/tests/privacy/provider_test.php b/mod/scorm/report/objectives/tests/privacy/provider_test.php index 25d4d35e48b..5f9c4ed9c0e 100644 --- a/mod/scorm/report/objectives/tests/privacy/provider_test.php +++ b/mod/scorm/report/objectives/tests/privacy/provider_test.php @@ -68,6 +68,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Validate exported data. provider::export_user_preferences($user->id); $context = \context_user::instance($user->id); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $prefs = $writer->get_user_preferences('scormreport_objectives'); diff --git a/notes/tests/privacy/provider_test.php b/notes/tests/privacy/provider_test.php index e6832d18c84..e56079bc4f3 100644 --- a/notes/tests/privacy/provider_test.php +++ b/notes/tests/privacy/provider_test.php @@ -229,6 +229,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { foreach ($contextlist as $context) { $this->assertEquals(CONTEXT_COURSE, $context->contextlevel); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); } diff --git a/question/tests/privacy/provider_test.php b/question/tests/privacy/provider_test.php index 0e6a3c883a0..78dd9360b61 100644 --- a/question/tests/privacy/provider_test.php +++ b/question/tests/privacy/provider_test.php @@ -96,6 +96,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $options = new \question_display_options(); provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, false); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data_in_any_context()); @@ -137,6 +138,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { // Export all questions for this attempt. $options = new \question_display_options(); provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data_in_any_context()); @@ -161,6 +163,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $options->marks = \question_display_options::HIDDEN; provider::export_question_usage($testuser->id, $context, [], $quba->get_id(), $options, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data_in_any_context()); diff --git a/question/tests/privacy_helper.php b/question/tests/privacy_helper.php index 65f3a46bfb4..521448549e4 100644 --- a/question/tests/privacy_helper.php +++ b/question/tests/privacy_helper.php @@ -93,6 +93,7 @@ trait core_question_privacy_helper { [get_string('questions', 'core_question')] ); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); foreach ($quba->get_slots() as $slotno) { diff --git a/rating/tests/privacy/provider_test.php b/rating/tests/privacy/provider_test.php index c20540ed4e0..d605c74f54d 100644 --- a/rating/tests/privacy/provider_test.php +++ b/rating/tests/privacy/provider_test.php @@ -283,6 +283,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $subcontext = []; provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course1->id, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $rating = $writer->get_related_data($subcontext, 'rating'); @@ -293,6 +294,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $subcontext = ['foo']; provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course2->id, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $result = $writer->get_related_data($subcontext, 'rating'); @@ -304,6 +306,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $subcontext = ['foo']; provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course3->id, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $result = $writer->get_related_data($subcontext, 'rating'); @@ -315,6 +318,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $subcontext = ['foo', 'files']; provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'files', $course3->id, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $result = $writer->get_related_data($subcontext, 'rating'); @@ -327,6 +331,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { $subcontext = ['user']; provider::export_area_ratings($u3->id, $context, $subcontext, 'user', 'user', $u3->id, false); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); $result = $writer->get_related_data($subcontext, 'rating'); diff --git a/rss/tests/privacy/provider_test.php b/rss/tests/privacy/provider_test.php index 406db4ba938..c44f4125940 100644 --- a/rss/tests/privacy/provider_test.php +++ b/rss/tests/privacy/provider_test.php @@ -72,6 +72,7 @@ class provider_test extends provider_testcase { // Validate exported data. $this->setUser($user); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertFalse($writer->has_any_data()); $this->export_context_data_for_user($user->id, $context, 'core_rss'); diff --git a/tag/tests/privacy/provider_test.php b/tag/tests/privacy/provider_test.php index 03e1cbe9437..2f41e4e2489 100644 --- a/tag/tests/privacy/provider_test.php +++ b/tag/tests/privacy/provider_test.php @@ -77,6 +77,7 @@ class provider_test extends provider_testcase { // Retrieve tags only for this user. provider::export_item_tags($user->id, $context, $subcontext, 'core_course', 'course', $course->id, true); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $this->assertTrue($writer->has_any_data()); @@ -261,6 +262,7 @@ class provider_test extends provider_testcase { }, \core_tag_tag::get_by_name_bulk(\core_tag_collection::get_default(), ['Birdwatching', 'Computers']))); provider::export_user_data(new \core_privacy\local\request\approved_contextlist($user1, 'core_tag', [$context->id])); + /** @var \core_privacy\tests\request\content_writer $writer */ $writer = writer::with_context($context); $data = $writer->get_data(['Tags', $tagids[0]]); From 8fc1486d36ad7ed5f44deddd80bd6b19a8410e06 Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Tue, 28 Feb 2023 13:13:42 +0000 Subject: [PATCH 5/5] MDL-77164 various: fix incorrect phpdocs --- .../local/setting/adminpresets_setting.php | 4 +-- admin/presets/classes/manager.php | 3 ++- admin/presets/classes/privacy/provider.php | 2 +- admin/roles/classes/allow_view_page.php | 5 ++-- .../classes/local/action/base.php | 2 +- admin/tool/analytics/classes/external.php | 2 +- .../classes/output/restorable_models.php | 2 +- .../brickfield/classes/brickfieldconnect.php | 1 - admin/tool/brickfield/classes/manager.php | 2 +- .../dataprivacy/classes/metadata_registry.php | 4 ++- .../tool/log/classes/plugininfo/logstore.php | 1 + admin/tool/lp/classes/external.php | 3 ++- .../output/manage_competencies_page.php | 4 +-- .../output/user_competency_summary.php | 2 +- .../user_competency_summary_in_plan.php | 8 +++--- admin/tool/usertours/classes/helper.php | 26 +++++++++---------- admin/tool/usertours/classes/step.php | 12 ++++----- admin/tool/usertours/classes/tour.php | 4 +-- auth/db/auth.php | 2 +- backup/moodle2/restore_plugin.class.php | 2 +- backup/moodle2/restore_stepslib.php | 4 +-- backup/moodle2/restore_subplugin.class.php | 5 ++++ backup/util/dbops/restore_dbops.class.php | 2 +- .../util/plan/backup_structure_step.class.php | 17 ++++++++---- backup/util/plan/base_step.class.php | 6 +++-- backup/util/plan/base_task.class.php | 7 ++++- .../structure/backup_nested_element.class.php | 13 +++++++++- backup/util/ui/import_extensions.php | 2 +- badges/classes/backpack_api.php | 3 ++- badges/classes/badge.php | 2 +- .../comments/tests/privacy/provider_test.php | 9 ++++--- blocks/html/classes/privacy/provider.php | 2 +- blocks/html/lib.php | 2 +- blocks/myprofile/classes/output/myprofile.php | 2 +- blocks/online_users/tests/generator_test.php | 2 +- .../classes/output/main.php | 2 +- blocks/rss_client/classes/output/feed.php | 4 +-- blocks/rss_client/classes/output/item.php | 2 +- blocks/rss_client/classes/output/renderer.php | 14 +++++----- .../rss_client/classes/privacy/provider.php | 2 +- .../tag_flickr/classes/privacy/provider.php | 2 +- blocks/tag_youtube/block_tag_youtube.php | 2 +- blocks/tests/privacy/provider_test.php | 8 +++--- blocks/timeline/classes/output/main.php | 2 +- cache/classes/helper.php | 5 ++-- cache/classes/loaders.php | 2 +- .../external/calendar_event_exporter.php | 8 +++--- .../local/event/data_access/event_vault.php | 2 +- .../local/event/proxies/cm_info_proxy.php | 2 +- .../local/event/proxies/proxy_interface.php | 2 +- .../raw_event_retrieval_strategy.php | 2 +- calendar/classes/privacy/provider.php | 6 ++--- calendar/lib.php | 4 +-- competency/classes/api.php | 10 +++---- competency/classes/competency.php | 6 ++--- competency/classes/competency_framework.php | 2 +- competency/classes/user_competency.php | 2 +- .../criteria/completion_criteria_date.php | 2 +- .../criteria/completion_criteria_role.php | 2 +- ...tion_events_by_timeline_classification.php | 2 +- course/classes/output/content_export_link.php | 2 +- course/classes/output/course_module_name.php | 2 +- course/classes/privacy/provider.php | 2 +- course/classes/search/course.php | 2 +- course/externallib.php | 6 ++--- course/format/classes/base.php | 2 +- .../local/content/section/controlmenu.php | 2 +- .../classes/output/local/state/section.php | 2 +- course/togglecompletion.php | 1 + enrol/classes/privacy/provider.php | 2 +- enrol/cohort/classes/privacy/provider.php | 2 +- enrol/externallib.php | 2 +- enrol/fee/classes/privacy/provider.php | 2 +- enrol/flatfile/tests/flatfile_test.php | 12 ++++----- enrol/ldap/classes/task/sync_enrolments.php | 2 +- enrol/ldap/tests/ldap_test.php | 2 +- enrol/locallib.php | 2 +- enrol/lti/tests/privacy/provider_test.php | 3 ++- enrol/meta/classes/privacy/provider.php | 2 +- enrol/paypal/classes/util.php | 2 +- enrol/paypal/tests/paypal_test.php | 4 +-- enrol/paypal/tests/privacy/provider_test.php | 1 + enrol/tests/course_enrolment_manager_test.php | 4 +-- enrol/tests/externallib_test.php | 6 ++--- files/tests/conversion_test.php | 2 +- filter/glossary/tests/filter_test.php | 8 +++--- .../guide/tests/privacy/provider_test.php | 6 ++--- grade/lib.php | 2 +- .../singleview/classes/local/screen/grade.php | 2 +- group/lib.php | 6 +++-- h5p/classes/helper.php | 10 +++---- lib/accesslib.php | 8 +++--- lib/adminlib.php | 3 ++- lib/authlib.php | 2 +- lib/badgeslib.php | 6 ++--- lib/behat/classes/behat_core_generator.php | 10 ++++--- lib/behat/classes/behat_session_trait.php | 4 +-- lib/blocklib.php | 4 ++- lib/classes/antivirus/scanner.php | 2 +- lib/classes/check/access/defaultuserrole.php | 2 +- lib/classes/check/access/frontpagerole.php | 2 +- lib/classes/check/access/guestrole.php | 2 +- lib/classes/check/access/riskadmin.php | 2 +- lib/classes/check/access/riskbackup.php | 2 +- lib/classes/check/access/riskxss.php | 2 +- lib/classes/check/check.php | 4 +-- lib/classes/check/environment/antivirus.php | 2 +- lib/classes/check/environment/environment.php | 2 +- lib/classes/check/environment/publicpaths.php | 2 +- .../check/environment/upgradecheck.php | 2 +- lib/classes/check/http/cookiesecure.php | 2 +- lib/classes/check/performance/backups.php | 2 +- lib/classes/check/performance/cachejs.php | 2 +- lib/classes/check/performance/dbschema.php | 2 +- lib/classes/check/performance/debugging.php | 2 +- .../check/performance/designermode.php | 2 +- lib/classes/check/performance/stats.php | 2 +- lib/classes/check/result.php | 4 +-- lib/classes/check/security/crawlers.php | 2 +- .../security/emailchangeconfirmation.php | 2 +- lib/classes/check/security/embed.php | 2 +- lib/classes/check/security/openprofiles.php | 2 +- lib/classes/check/security/passwordpolicy.php | 2 +- lib/classes/check/security/webcron.php | 2 +- lib/classes/check/table.php | 2 +- .../export/exporters/course_exporter.php | 4 +-- lib/classes/event/tag_added.php | 2 +- lib/classes/event/tag_removed.php | 2 +- lib/classes/external/exporter.php | 2 +- lib/classes/hub/registration.php | 8 +++--- lib/classes/lock/mysql_lock_factory.php | 2 +- lib/classes/log/sql_reader.php | 2 +- lib/classes/navigation/output/primary.php | 2 +- lib/classes/navigation/views/view.php | 4 +-- lib/classes/notification.php | 2 +- lib/classes/output/inplace_editable.php | 4 +-- lib/classes/output/language_menu.php | 4 +-- lib/classes/output/notification.php | 4 +-- lib/classes/output/sticky_footer.php | 2 +- lib/classes/output/url_rewriter.php | 4 +-- lib/classes/persistent.php | 2 +- lib/classes/plugin_manager.php | 2 +- lib/classes/plugininfo/antivirus.php | 1 + lib/classes/plugininfo/auth.php | 1 + lib/classes/plugininfo/availability.php | 1 + lib/classes/plugininfo/block.php | 1 + lib/classes/plugininfo/calendartype.php | 1 + lib/classes/plugininfo/contenttype.php | 3 ++- lib/classes/plugininfo/customfield.php | 1 + lib/classes/plugininfo/dataformat.php | 1 + lib/classes/plugininfo/editor.php | 1 + lib/classes/plugininfo/enrol.php | 1 + lib/classes/plugininfo/fileconverter.php | 1 + lib/classes/plugininfo/filter.php | 1 + lib/classes/plugininfo/format.php | 1 + lib/classes/plugininfo/media.php | 2 ++ lib/classes/plugininfo/message.php | 1 + lib/classes/plugininfo/mlbackend.php | 1 + lib/classes/plugininfo/mod.php | 1 + lib/classes/plugininfo/orphaned.php | 2 +- lib/classes/plugininfo/paygw.php | 1 + lib/classes/plugininfo/qbank.php | 1 + lib/classes/plugininfo/qtype.php | 1 + lib/classes/plugininfo/webservice.php | 1 + lib/classes/privacy/provider.php | 2 +- lib/classes/session/manager.php | 2 +- lib/classes/string_manager_standard.php | 2 +- lib/classes/task/manager.php | 2 +- .../send_failed_login_notifications_task.php | 1 + lib/classes/task/task_base.php | 2 +- lib/classes/update/api.php | 4 +-- lib/ddl/mysql_sql_generator.php | 2 ++ lib/ddl/sql_generator.php | 6 ++--- lib/dml/moodle_database.php | 15 ++++++----- lib/dml/mysqli_native_moodle_database.php | 5 ++-- lib/dml/oci_native_moodle_database.php | 7 ++--- lib/dml/pdo_moodle_database.php | 2 +- lib/dml/pgsql_native_moodle_database.php | 9 ++++--- lib/dml/pgsql_native_moodle_recordset.php | 3 ++- lib/dml/sqlsrv_native_moodle_database.php | 5 ++-- .../fixtures/read_slave_moodle_database.php | 2 +- ...read_slave_moodle_database_mock_mysqli.php | 2 +- .../tests/fixtures/test_moodle_database.php | 4 ++- lib/dml/tests/fixtures/test_sql_generator.php | 3 +++ lib/dml/tests/recordset_walk_test.php | 2 ++ lib/dmllib.php | 2 +- lib/editor/atto/classes/plugininfo/atto.php | 1 + lib/editor/atto/classes/privacy/provider.php | 2 +- lib/editor/tiny/classes/plugininfo/tiny.php | 1 + .../autosave/classes/privacy/provider.php | 2 +- lib/enrollib.php | 4 +-- lib/excellib.class.php | 2 +- lib/external/classes/util.php | 6 ++--- lib/external/tests/privacy/provider_test.php | 4 +-- lib/filebrowser/file_info.php | 2 +- lib/filebrowser/tests/file_browser_test.php | 3 ++- lib/filelib.php | 4 +-- lib/filestorage/file_storage.php | 2 +- lib/filestorage/tests/file_storage_test.php | 3 +++ .../tests/file_system_filedir_test.php | 4 +-- lib/filestorage/tests/file_system_test.php | 2 +- lib/filestorage/tests/zip_packer_test.php | 2 +- lib/form/classes/filetypes_util.php | 2 +- lib/form/modgrade.php | 2 +- lib/form/passwordunmask.php | 2 +- lib/form/selectgroups.php | 2 +- lib/form/tests/dateselector_test.php | 4 +-- lib/form/tests/datetimeselector_test.php | 4 +-- lib/formslib.php | 14 +++++----- lib/gdlib.php | 6 ++--- lib/grade/grade_category.php | 2 +- lib/grade/grade_object.php | 2 +- lib/grade/tests/grade_category_test.php | 6 ++--- lib/grade/tests/grade_item_test.php | 2 +- lib/gradelib.php | 5 ++-- lib/moodlelib.php | 8 +++--- lib/navigationlib.php | 12 ++++----- lib/outputcomponents.php | 2 +- lib/outputrenderers.php | 14 +++++----- lib/pagelib.php | 4 +-- lib/pear/HTML/QuickForm.php | 2 +- lib/phpunit/classes/util.php | 4 +-- lib/portfolio/exporter.php | 2 +- lib/portfolio/formats.php | 2 +- lib/portfolio/plugin.php | 4 +-- lib/questionlib.php | 4 +-- lib/tablelib.php | 22 ++++++++-------- lib/testing/generator/block_generator.php | 2 +- lib/testing/generator/data_generator.php | 8 +++--- lib/testing/generator/module_generator.php | 2 +- lib/testing/lib.php | 2 +- lib/tests/accesslib_has_capability_test.php | 4 +-- .../core_renderer_template_exploit_test.php | 2 +- .../contentbank_content_created_test.php | 1 + .../contentbank_content_deleted_test.php | 1 + .../contentbank_content_updated_test.php | 1 + .../event/contentbank_content_viewed_test.php | 1 + lib/tests/event/context_locked_test.php | 1 + .../fixtures/testable_plugin_manager.php | 2 +- .../h5p_clean_orphaned_records_task_test.php | 1 + lib/tests/moodlelib_test.php | 2 +- .../filtersettingsperformancetester.php | 1 + lib/tests/questionlib_test.php | 19 +++++++++++++- lib/tests/task/logging_test.php | 2 +- lib/tests/update_api_test.php | 1 + lib/weblib.php | 9 +++---- lib/xapi/classes/local/statement.php | 4 +-- .../classes/local/statement/item_group.php | 4 +-- .../local/statement/item_attachment_test.php | 2 +- .../local/statement/item_result_test.php | 2 +- lib/xmldb/xmldb_field.php | 6 ++--- lib/xmldb/xmldb_object.php | 12 ++++----- lib/xmldb/xmldb_structure.php | 2 +- mod/assign/classes/output/grading_app.php | 2 +- mod/assign/classes/output/renderer.php | 4 +-- .../privacy/assign_plugin_request_data.php | 8 +++--- mod/assign/classes/privacy/provider.php | 2 +- .../comments/tests/privacy/provider_test.php | 4 +-- .../feedback/editpdf/classes/annotation.php | 2 +- .../editpdf/classes/combined_document.php | 6 ++--- .../editpdf/classes/comments_quick_list.php | 2 +- .../editpdf/classes/document_services.php | 6 ++--- .../feedback/editpdf/classes/page_editor.php | 2 +- mod/assign/feedback/editpdf/classes/pdf.php | 2 +- .../feedback/editpdf/tests/feedback_test.php | 4 +-- .../editpdf/tests/privacy/provider_test.php | 6 ++--- .../file/tests/privacy/provider_test.php | 4 +-- mod/assign/lib.php | 2 +- mod/assign/locallib.php | 4 +-- .../classes/event/assessable_uploaded.php | 2 +- mod/bigbluebuttonbn/classes/recording.php | 2 +- mod/bigbluebuttonbn/classes/settings.php | 2 +- mod/bigbluebuttonbn/lib.php | 6 ++--- mod/book/lib.php | 2 +- mod/chat/lib.php | 2 +- mod/choice/lib.php | 2 +- mod/data/lib.php | 2 +- mod/feedback/item/multichoicerated/lib.php | 5 ++++ mod/feedback/lib.php | 6 ++--- mod/feedback/tests/generator/lib.php | 18 ++++++------- mod/forum/classes/output/forum_post.php | 2 +- mod/forum/lib.php | 4 +-- mod/glossary/lib.php | 6 ++--- mod/h5pactivity/lib.php | 2 +- mod/imscp/lib.php | 2 +- mod/lesson/lib.php | 4 +-- mod/lesson/tests/generator/lib.php | 2 +- .../local/ltiservice/resource_base.php | 2 +- mod/page/lib.php | 2 +- mod/quiz/lib.php | 4 +-- mod/quiz/report/statistics/report.php | 3 ++- mod/resource/lib.php | 2 +- mod/scorm/lib.php | 11 ++++---- mod/survey/lib.php | 4 +-- mod/url/classes/search/activity.php | 4 +-- mod/url/locallib.php | 2 +- mod/wiki/locallib.php | 3 ++- mod/workshop/classes/privacy/provider.php | 2 +- privacy/classes/local/metadata/collection.php | 4 +-- privacy/classes/local/request/writer.php | 2 +- .../classes/tests/request/content_writer.php | 12 ++++----- .../classes/customfield/question_handler.php | 2 +- .../engine/variants/least_used_strategy.php | 4 +-- rating/classes/phpunit/privacy_helper.php | 2 +- rating/lib.php | 2 +- repository/lib.php | 10 +++---- repository/recent/tests/lib_test.php | 8 +++--- repository/tests/privacy/provider_test.php | 1 - search/classes/base_activity.php | 2 +- search/engine/simpledb/tests/engine_test.php | 5 +--- search/engine/solr/tests/engine_test.php | 3 --- search/tests/base_activity_test.php | 8 +++--- search/tests/base_block_test.php | 2 +- search/tests/top_result_test.php | 2 ++ tag/classes/tests/privacy_helper.php | 2 +- tag/tests/taglib_test.php | 4 +-- user/classes/output/myprofile/manager.php | 2 +- user/editlib.php | 2 +- user/externallib.php | 2 +- user/lib.php | 6 ++--- user/profile/field/social/define.class.php | 4 +-- .../tests/group_non_members_selector_test.php | 2 -- user/tests/privacy/provider_test.php | 4 +-- webservice/rest/tests/server_test.php | 2 +- webservice/soap/locallib.php | 1 + webservice/tests/helpers.php | 2 +- webservice/tests/lib_test.php | 6 ++--- 327 files changed, 644 insertions(+), 533 deletions(-) diff --git a/admin/presets/classes/local/setting/adminpresets_setting.php b/admin/presets/classes/local/setting/adminpresets_setting.php index 92103872603..413a2b160e2 100644 --- a/admin/presets/classes/local/setting/adminpresets_setting.php +++ b/admin/presets/classes/local/setting/adminpresets_setting.php @@ -170,7 +170,7 @@ class adminpresets_setting { /** * Saves the setting attributes values * - * @return array Array of inserted ids (in config_log) + * @return array|false Array of inserted ids (in config_log) or false if nothing was inserted */ public function save_attributes_values() { // Plugin name or null. @@ -209,8 +209,6 @@ class adminpresets_setting { * @param bool $name Setting name to store. * @param mixed $value Setting value to store. * @return int|false config_log inserted id or false whenever the new value is the same as old value. - * @throws dml_exception - * @throws moodle_exception */ public function save_value($name = false, $value = null) { // Object values if no arguments. diff --git a/admin/presets/classes/manager.php b/admin/presets/classes/manager.php index fc059ddb43f..95321541c9f 100644 --- a/admin/presets/classes/manager.php +++ b/admin/presets/classes/manager.php @@ -183,7 +183,8 @@ class manager { * @param boolean $sitedbvalues Indicates if $dbsettings comes from the site db or not * @param array $settings Array format $array['plugin']['settingname'] = settings_types child class * @param array|false $children Array of admin_category children or false - * @return array Array format $array['plugin']['settingname'] = settings_types child class + * @return \core_adminpresets\local\setting\adminpresets_setting[][] Array format + * $array['plugin']['settingname'] = adminpresets_setting child class */ public function get_settings(array $dbsettings, bool $sitedbvalues = false, array $settings = [], $children = false): array { global $DB; diff --git a/admin/presets/classes/privacy/provider.php b/admin/presets/classes/privacy/provider.php index c552b0b45f7..81b955d972f 100644 --- a/admin/presets/classes/privacy/provider.php +++ b/admin/presets/classes/privacy/provider.php @@ -99,7 +99,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { // None of the the data from these tables should be deleted. diff --git a/admin/roles/classes/allow_view_page.php b/admin/roles/classes/allow_view_page.php index d3313220d0c..9b6a5bf6ca6 100644 --- a/admin/roles/classes/allow_view_page.php +++ b/admin/roles/classes/allow_view_page.php @@ -54,10 +54,9 @@ class core_role_allow_view_page extends core_role_allow_role_page { /** * Get tool tip for cell. - * @param string $fromrole - * @param string $targetrole + * @param stdClass $fromrole + * @param stdClass $targetrole * @return string - * @throws \coding_exception */ protected function get_cell_tooltip($fromrole, $targetrole) { $a = new stdClass; diff --git a/admin/tool/admin_presets/classes/local/action/base.php b/admin/tool/admin_presets/classes/local/action/base.php index fc1e6ffab32..86ddd71aa85 100644 --- a/admin/tool/admin_presets/classes/local/action/base.php +++ b/admin/tool/admin_presets/classes/local/action/base.php @@ -56,7 +56,7 @@ class base { /** @var int The output content to display in the page. **/ protected $outputs; - /** @var int The moodle form to display in the page. **/ + /** @var \moodleform The moodle form to display in the page. **/ protected $moodleform; /** @var manager The manager helper class instance. **/ diff --git a/admin/tool/analytics/classes/external.php b/admin/tool/analytics/classes/external.php index 8ea300f473c..2771cae297b 100644 --- a/admin/tool/analytics/classes/external.php +++ b/admin/tool/analytics/classes/external.php @@ -96,7 +96,7 @@ class external extends external_api { * potential_contexts return * * @since Moodle 3.8 - * @return external_description + * @return \core_external\external_description */ public static function potential_contexts_returns() { return new external_multiple_structure( diff --git a/admin/tool/analytics/classes/output/restorable_models.php b/admin/tool/analytics/classes/output/restorable_models.php index a4e345673c6..f8dca62f6a1 100644 --- a/admin/tool/analytics/classes/output/restorable_models.php +++ b/admin/tool/analytics/classes/output/restorable_models.php @@ -51,7 +51,7 @@ class restorable_models implements \renderable, \templatable { /** * Export the list of models to be rendered. * - * @param renderer_base $output + * @param \renderer_base $output * @return string */ public function export_for_template(\renderer_base $output) { diff --git a/admin/tool/brickfield/classes/brickfieldconnect.php b/admin/tool/brickfield/classes/brickfieldconnect.php index ee1857eb375..0b1657109a9 100644 --- a/admin/tool/brickfield/classes/brickfieldconnect.php +++ b/admin/tool/brickfield/classes/brickfieldconnect.php @@ -244,7 +244,6 @@ class brickfieldconnect extends curl { /** * Get the check registration API URI. * @return string - * @throws dml_exception */ protected function get_baseapiuri(): string { $baseapiuri = get_config(manager::PLUGINNAME, 'baseapiuri'); diff --git a/admin/tool/brickfield/classes/manager.php b/admin/tool/brickfield/classes/manager.php index 97fff856690..0c67267a169 100644 --- a/admin/tool/brickfield/classes/manager.php +++ b/admin/tool/brickfield/classes/manager.php @@ -788,7 +788,7 @@ class manager { * Get course module summary information for a course. * * @param int $courseid - * @return stdClass[] + * @return \stdClass[] */ public static function get_cm_summary_for_course(int $courseid): array { global $DB; diff --git a/admin/tool/dataprivacy/classes/metadata_registry.php b/admin/tool/dataprivacy/classes/metadata_registry.php index 65264807acb..e54e97ad2f9 100644 --- a/admin/tool/dataprivacy/classes/metadata_registry.php +++ b/admin/tool/dataprivacy/classes/metadata_registry.php @@ -23,6 +23,8 @@ */ namespace tool_dataprivacy; +use core_privacy\local\metadata\types\type; + defined('MOODLE_INTERNAL') || die(); /** @@ -114,7 +116,7 @@ class metadata_registry { /** * Formats the metadata for use with a template. * - * @param array $collection The collection associated with the component that we want to expand and format. + * @param type[] $collection The collection associated with the component that we want to expand and format. * @param string $component The component that we are dealing in * @param array $internaldata The array to add the formatted metadata to. * @return array The internal data array with the formatted metadata. diff --git a/admin/tool/log/classes/plugininfo/logstore.php b/admin/tool/log/classes/plugininfo/logstore.php index 28ae96e6061..b87741320d7 100644 --- a/admin/tool/log/classes/plugininfo/logstore.php +++ b/admin/tool/log/classes/plugininfo/logstore.php @@ -80,6 +80,7 @@ class logstore extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $section = $this->get_settings_section_name(); diff --git a/admin/tool/lp/classes/external.php b/admin/tool/lp/classes/external.php index d59b54fa28e..4d7990ca50c 100644 --- a/admin/tool/lp/classes/external.php +++ b/admin/tool/lp/classes/external.php @@ -42,6 +42,7 @@ use core_competency\external\user_competency_plan_exporter; use core_course\external\course_module_summary_exporter; use core_course\external\course_summary_exporter; use core_external\external_api; +use core_external\external_description; use core_external\external_function_parameters; use core_external\external_multiple_structure; use core_external\external_single_structure; @@ -109,7 +110,7 @@ class external extends external_api { /** * Loads the data required to render the competency_frameworks_manage_page template. * - * @param context $pagecontext The page context + * @param \context $pagecontext The page context * @return \stdClass */ public static function data_for_competency_frameworks_manage_page($pagecontext) { diff --git a/admin/tool/lp/classes/output/manage_competencies_page.php b/admin/tool/lp/classes/output/manage_competencies_page.php index 5541900be6f..6d954c3fc37 100644 --- a/admin/tool/lp/classes/output/manage_competencies_page.php +++ b/admin/tool/lp/classes/output/manage_competencies_page.php @@ -59,7 +59,7 @@ class manage_competencies_page implements renderable, templatable { /** @var moodle_url $pluginurlbase Base url to use constructing links. */ protected $pluginbaseurl = null; - /** @var context $pagecontext The page context. */ + /** @var \context $pagecontext The page context. */ protected $pagecontext = null; /** @var \core_competency\competency $competency The competency to show when the page loads. */ @@ -73,7 +73,7 @@ class manage_competencies_page implements renderable, templatable { * * @param \core_competency\competency_framework $framework Competency framework. * @param string $search Search string. - * @param context $pagecontext The page context. + * @param \context $pagecontext The page context. * @param \core_competency\competency $competency The core competency to show when the page loads. */ public function __construct($framework, $search, $pagecontext, $competency) { diff --git a/admin/tool/lp/classes/output/user_competency_summary.php b/admin/tool/lp/classes/output/user_competency_summary.php index 53680069c2f..ff42ab50597 100644 --- a/admin/tool/lp/classes/output/user_competency_summary.php +++ b/admin/tool/lp/classes/output/user_competency_summary.php @@ -61,7 +61,7 @@ class user_competency_summary implements renderable, templatable { * Export the data. * * @param renderer_base $output - * @return stdClass + * @return \stdClass */ public function export_for_template(renderer_base $output) { if (!isset($related['user'])) { diff --git a/admin/tool/lp/classes/output/user_competency_summary_in_plan.php b/admin/tool/lp/classes/output/user_competency_summary_in_plan.php index f2cd81b12d7..81f4c09fc71 100644 --- a/admin/tool/lp/classes/output/user_competency_summary_in_plan.php +++ b/admin/tool/lp/classes/output/user_competency_summary_in_plan.php @@ -38,10 +38,10 @@ use tool_lp\external\user_competency_summary_in_plan_exporter; */ class user_competency_summary_in_plan implements renderable, templatable { - /** @var competencyid */ + /** @var int competencyid */ protected $competencyid; - /** @var planid */ + /** @var int planid */ protected $planid; /** @@ -58,8 +58,8 @@ class user_competency_summary_in_plan implements renderable, templatable { /** * Export the data. * - * @param renderer_base $output - * @return stdClass + * @param \renderer_base $output + * @return \stdClass */ public function export_for_template(\renderer_base $output) { global $DB; diff --git a/admin/tool/usertours/classes/helper.php b/admin/tool/usertours/classes/helper.php index dcb12f6353a..6c2befa697a 100644 --- a/admin/tool/usertours/classes/helper.php +++ b/admin/tool/usertours/classes/helper.php @@ -66,7 +66,7 @@ class helper { * @param int $stepid The step ID. * @param int $targettype The type of step. * - * @return moodle_url + * @return \moodle_url */ public static function get_edit_step_link($tourid, $stepid = null, $targettype = null) { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -88,7 +88,7 @@ class helper { * @param int $tourid The tour ID. * @param int $direction The direction to move in * - * @return moodle_url + * @return \moodle_url */ public static function get_move_tour_link($tourid, $direction = self::MOVE_DOWN) { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -107,7 +107,7 @@ class helper { * @param int $stepid The step ID. * @param int $direction The direction to move in * - * @return moodle_url + * @return \moodle_url */ public static function get_move_step_link($stepid, $direction = self::MOVE_DOWN) { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -126,7 +126,7 @@ class helper { * @param int $tourid The ID of the tour to attach this step to. * @param int $targettype The type of target. * - * @return moodle_url The required URL. + * @return \moodle_url The required URL. */ public static function get_new_step_link($tourid, $targettype = null) { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -141,7 +141,7 @@ class helper { * Get the link used to view the tour. * * @param int $tourid The ID of the tour to display. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_view_tour_link($tourid) { return new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -154,7 +154,7 @@ class helper { * Get the link used to reset the tour state for all users. * * @param int $tourid The ID of the tour to display. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_reset_tour_for_all_link($tourid) { return new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -168,7 +168,7 @@ class helper { * Get the link used to edit the tour. * * @param int $tourid The ID of the tour to edit. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_edit_tour_link($tourid = null) { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -186,7 +186,7 @@ class helper { /** * Get the link used to import the tour. * - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_import_tour_link() { $link = new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -200,7 +200,7 @@ class helper { * Get the link used to export the tour. * * @param int $tourid The ID of the tour to export. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_export_tour_link($tourid) { $link = new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -215,7 +215,7 @@ class helper { * Get the link used to duplicate the tour. * * @param int $tourid The ID of the tour to duplicate. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_duplicate_tour_link($tourid) { $link = new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -230,7 +230,7 @@ class helper { * Get the link used to delete the tour. * * @param int $tourid The ID of the tour to delete. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_delete_tour_link($tourid) { return new \moodle_url('/admin/tool/usertours/configure.php', [ @@ -243,7 +243,7 @@ class helper { /** * Get the link for listing tours. * - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_list_tour_link() { $link = new \moodle_url('/admin/tool/usertours/configure.php'); @@ -295,7 +295,7 @@ class helper { * Get the link for deleting steps. * * @param int $stepid The ID of the step to display. - * @return moodle_url The URL. + * @return \moodle_url The URL. */ public static function get_delete_step_link($stepid) { return new \moodle_url('/admin/tool/usertours/configure.php', [ diff --git a/admin/tool/usertours/classes/step.php b/admin/tool/usertours/classes/step.php index 0ba9de85c65..95715e177ad 100644 --- a/admin/tool/usertours/classes/step.php +++ b/admin/tool/usertours/classes/step.php @@ -388,7 +388,7 @@ class step { /** * Get the link to move this step up in the sortorder. * - * @return moodle_url + * @return \moodle_url */ public function get_moveup_link() { return helper::get_move_step_link($this->get_id(), helper::MOVE_UP); @@ -397,7 +397,7 @@ class step { /** * Get the link to move this step down in the sortorder. * - * @return moodle_url + * @return \moodle_url */ public function get_movedown_link() { return helper::get_move_step_link($this->get_id(), helper::MOVE_DOWN); @@ -464,7 +464,7 @@ class step { /** * Get the edit link for this step. * - * @return moodle_url + * @return \moodle_url */ public function get_edit_link() { return helper::get_edit_step_link($this->tourid, $this->id); @@ -473,7 +473,7 @@ class step { /** * Get the delete link for this step. * - * @return moodle_url + * @return \moodle_url */ public function get_delete_link() { return helper::get_delete_step_link($this->id); @@ -674,7 +674,7 @@ class step { /** * Add the step configuration to the form. * - * @param MoodleQuickForm $mform The form to add configuration to. + * @param \MoodleQuickForm $mform The form to add configuration to. * @return $this */ public function add_config_to_form(\MoodleQuickForm $mform) { @@ -694,7 +694,7 @@ class step { /** * Add the specified step field configuration to the form. * - * @param MoodleQuickForm $mform The form to add configuration to. + * @param \MoodleQuickForm $mform The form to add configuration to. * @param string $key The key to add. * @return $this */ diff --git a/admin/tool/usertours/classes/tour.php b/admin/tool/usertours/classes/tour.php index be8678c52fe..c51f9e85f0d 100644 --- a/admin/tool/usertours/classes/tour.php +++ b/admin/tool/usertours/classes/tour.php @@ -367,7 +367,7 @@ class tour { /** * The link to view this tour. * - * @return moodle_url + * @return \moodle_url */ public function get_view_link() { return helper::get_view_tour_link($this->id); @@ -376,7 +376,7 @@ class tour { /** * The link to edit this tour. * - * @return moodle_url + * @return \moodle_url */ public function get_edit_link() { return helper::get_edit_tour_link($this->id); diff --git a/auth/db/auth.php b/auth/db/auth.php index bb9ed70363d..3a4d9696104 100644 --- a/auth/db/auth.php +++ b/auth/db/auth.php @@ -541,7 +541,7 @@ class auth_plugin_db extends auth_plugin_base { * Reads user information from DB and return it in an object. * * @param string $username username - * @return array + * @return stdClass */ function get_userinfo_asobj($username) { $user_array = truncate_userinfo($this->get_userinfo($username)); diff --git a/backup/moodle2/restore_plugin.class.php b/backup/moodle2/restore_plugin.class.php index 31a94f50e9f..8f2693662c7 100644 --- a/backup/moodle2/restore_plugin.class.php +++ b/backup/moodle2/restore_plugin.class.php @@ -38,7 +38,7 @@ abstract class restore_plugin { protected $plugintype; /** @var string */ protected $pluginname; - /** @var string */ + /** @var restore_path_element */ protected $connectionpoint; /** @var restore_structure_step */ protected $step; diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 2b8d3321744..007c7885cc4 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -5487,7 +5487,7 @@ class restore_create_question_files extends restore_execution_step { * * @param int $oldctxid Old context id. * @param int $newctxid New context id. - * @param \core\progress $progress Progress object to use. + * @param \core\progress\base $progress Progress object to use. */ private function send_common_files($oldctxid, $newctxid, $progress) { // Add common question files (question and question_answer ones). @@ -5515,7 +5515,7 @@ class restore_create_question_files extends restore_execution_step { * @param text $qtype The qtype name to send. * @param int $oldctxid Old context id. * @param int $newctxid New context id. - * @param \core\progress $progress Progress object to use. + * @param \core\progress\base $progress Progress object to use. */ private function send_qtype_files($qtype, $oldctxid, $newctxid, $progress) { if (!isset($this->qtypecomponentscache[$qtype])) { diff --git a/backup/moodle2/restore_subplugin.class.php b/backup/moodle2/restore_subplugin.class.php index c848219ccf8..226cefb7662 100644 --- a/backup/moodle2/restore_subplugin.class.php +++ b/backup/moodle2/restore_subplugin.class.php @@ -36,10 +36,15 @@ defined('MOODLE_INTERNAL') || die(); */ abstract class restore_subplugin { + /** @var string */ protected $subplugintype; + /** @var string */ protected $subpluginname; + /** @var restore_path_element */ protected $connectionpoint; + /** @var restore_step */ protected $step; + /** @var restore_task */ protected $task; public function __construct($subplugintype, $subpluginname, $step) { diff --git a/backup/util/dbops/restore_dbops.class.php b/backup/util/dbops/restore_dbops.class.php index fa85101ebc0..998049cd06d 100644 --- a/backup/util/dbops/restore_dbops.class.php +++ b/backup/util/dbops/restore_dbops.class.php @@ -206,7 +206,7 @@ abstract class restore_dbops { * @param int $restoreid id of backup * @param string $itemname name of the item * @param int $itemid id of item - * @return array backup id's + * @return stdClass|false record from 'backup_ids_temp' table * @todo MDL-25290 replace static backupids* with MUC code */ protected static function get_backup_ids_cached($restoreid, $itemname, $itemid) { diff --git a/backup/util/plan/backup_structure_step.class.php b/backup/util/plan/backup_structure_step.class.php index e94cfe8022f..6344299aa11 100644 --- a/backup/util/plan/backup_structure_step.class.php +++ b/backup/util/plan/backup_structure_step.class.php @@ -29,11 +29,18 @@ */ abstract class backup_structure_step extends backup_step { - protected $filename; // Name of the file to be generated - protected $contenttransformer; // xml content transformer being used - // (need it here, apart from xml_writer, - // thanks to serialized data to process - - // say thanks to blocks!) + /** + * Name of the file to be generated + * @var string + */ + protected $filename; + + /** + * xml content transformer being used (need it here, apart from xml_writer, + * thanks to serialized data to process - say thanks to blocks!) + * @var backup_xml_transformer|null + */ + protected $contenttransformer; /** * Constructor - instantiates one object of this class diff --git a/backup/util/plan/base_step.class.php b/backup/util/plan/base_step.class.php index 66f1f6bebdb..b1b7a6af508 100644 --- a/backup/util/plan/base_step.class.php +++ b/backup/util/plan/base_step.class.php @@ -29,8 +29,10 @@ */ abstract class base_step implements executable, loggable { - protected $name; // One simple name for identification purposes - protected $task; // Task this is part of + /** @var string One simple name for identification purposes */ + protected $name; + /** @var base_task|null Task this is part of */ + protected $task; /** * Constructor - instantiates one object of this class diff --git a/backup/util/plan/base_task.class.php b/backup/util/plan/base_task.class.php index ce30c063b91..7973aa26ec2 100644 --- a/backup/util/plan/base_task.class.php +++ b/backup/util/plan/base_task.class.php @@ -29,12 +29,17 @@ */ abstract class base_task implements checksumable, executable, loggable { + /** @var string */ protected $name; // One simple name for identification purposes + /** @var backup_plan|restore_plan */ protected $plan; // Plan this is part of + /** @var base_setting[] */ protected $settings; // One array of base_setting elements to define this task + /** @var base_step[] */ protected $steps; // One array of base_step elements - + /** @var bool */ protected $built; // Flag to know if one task has been built + /** @var bool */ protected $executed; // Flag to know if one task has been executed /** diff --git a/backup/util/structure/backup_nested_element.class.php b/backup/util/structure/backup_nested_element.class.php index 32abd9ac19d..0959d80a3cf 100644 --- a/backup/util/structure/backup_nested_element.class.php +++ b/backup/util/structure/backup_nested_element.class.php @@ -29,16 +29,27 @@ */ class backup_nested_element extends base_nested_element implements processable { - protected $var_array; // To be used in case we pass one in-memory structure + /** @var array To be used in case we pass one in-memory structure */ + protected $var_array; + /** @var string */ protected $table; // Table (without prefix) to fetch records from + /** @var string */ protected $tablesortby; // The field to sort by when using the table methods + /** @var string */ protected $sql; // Raw SQL to fetch records from + /** @var mixed */ protected $params; // Unprocessed params as specified in the set_source() call + /** @var array */ protected $procparams;// Processed (path resolved) params array + /** @var array */ protected $aliases; // Define DB->final element aliases + /** @var array */ protected $fileannotations; // array of file areas to be searched by file annotations + /** @var int */ protected $counter; // Number of instances of this element that have been processed + /** @var array */ protected $results; // Logs the results we encounter during the process. + /** @var stdClass[] */ protected $logs; // Some log messages that could be retrieved later. /** diff --git a/backup/util/ui/import_extensions.php b/backup/util/ui/import_extensions.php index 1fd4e507b8d..f39e0dce40d 100644 --- a/backup/util/ui/import_extensions.php +++ b/backup/util/ui/import_extensions.php @@ -207,7 +207,7 @@ class import_ui_stage_confirmation extends backup_ui_stage_confirmation { /** * Initialises the stages moodleform - * @return moodleform + * @return base_moodleform */ protected function initialise_stage_form() { $form = parent::initialise_stage_form(); diff --git a/badges/classes/backpack_api.php b/badges/classes/backpack_api.php index e0db0035400..38627e6a0db 100644 --- a/badges/classes/backpack_api.php +++ b/badges/classes/backpack_api.php @@ -545,7 +545,8 @@ class backpack_api { /** * Authenticate using the stored email and password and save the valid access tokens. * - * @return integer The id of the authenticated user. + * @return mixed The id of the authenticated user as returned by the backpack. Can have + * different formats - numeric, empty, object with 'error' property, etc. */ public function authenticate() { global $SESSION; diff --git a/badges/classes/badge.php b/badges/classes/badge.php index a5186070291..284556154db 100644 --- a/badges/classes/badge.php +++ b/badges/classes/badge.php @@ -164,7 +164,7 @@ class badge { /** * Use to get context instance of a badge. * - * @return context instance. + * @return \context|void instance. */ public function get_context() { if ($this->type == BADGE_TYPE_SITE) { diff --git a/blocks/comments/tests/privacy/provider_test.php b/blocks/comments/tests/privacy/provider_test.php index 8cecd1380ac..f68574c456f 100644 --- a/blocks/comments/tests/privacy/provider_test.php +++ b/blocks/comments/tests/privacy/provider_test.php @@ -26,6 +26,7 @@ namespace block_comments\privacy; use core_privacy\local\metadata\collection; use block_comments\privacy\provider; use core_privacy\local\request\approved_userlist; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -83,7 +84,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { * Posts a comment on a given context. * * @param string $text The comment's text. - * @param context $context The context on which we want to put the comment. + * @param \context $context The context on which we want to put the comment. */ protected function add_comment($text, \context $context) { $args = new \stdClass; @@ -103,9 +104,9 @@ class provider_test extends \core_privacy\tests\provider_testcase { /** * Creates a comments block on a context. * - * @param context $context The context on which we want to put the block. - * @return block_base The created block instance. - * @throws coding_exception + * @param \context $context The context on which we want to put the block. + * @return \block_base The created block instance. + * @throws \coding_exception */ protected function add_comments_block_in_context(\context $context) { global $DB; diff --git a/blocks/html/classes/privacy/provider.php b/blocks/html/classes/privacy/provider.php index aa32e78d8b4..9d987a0d542 100644 --- a/blocks/html/classes/privacy/provider.php +++ b/blocks/html/classes/privacy/provider.php @@ -184,7 +184,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { diff --git a/blocks/html/lib.php b/blocks/html/lib.php index a9891638fea..ecc2d8d45c2 100644 --- a/blocks/html/lib.php +++ b/blocks/html/lib.php @@ -23,7 +23,7 @@ * @category files * @param stdClass $course course object * @param stdClass $birecord_or_cm block instance record - * @param stdClass $context context object + * @param context $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download diff --git a/blocks/myprofile/classes/output/myprofile.php b/blocks/myprofile/classes/output/myprofile.php index b07d7811f8e..de9c7390403 100644 --- a/blocks/myprofile/classes/output/myprofile.php +++ b/blocks/myprofile/classes/output/myprofile.php @@ -56,7 +56,7 @@ class myprofile implements renderable, templatable { * Export this data so it can be used as the context for a mustache template. * * @param \renderer_base $output - * @return stdClass + * @return \stdClass */ public function export_for_template(renderer_base $output) { global $USER, $OUTPUT; diff --git a/blocks/online_users/tests/generator_test.php b/blocks/online_users/tests/generator_test.php index ad5a7dfa079..01079660a6b 100644 --- a/blocks/online_users/tests/generator_test.php +++ b/blocks/online_users/tests/generator_test.php @@ -33,7 +33,7 @@ class generator_test extends \advanced_testcase { $beforeblocks = $DB->count_records('block_instances'); $beforecontexts = $DB->count_records('context'); - /** @var block_online_users_generator $generator */ + /** @var \block_online_users_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('block_online_users'); $this->assertInstanceOf('block_online_users_generator', $generator); $this->assertEquals('online_users', $generator->get_blockname()); diff --git a/blocks/recentlyaccesseditems/classes/output/main.php b/blocks/recentlyaccesseditems/classes/output/main.php index 27741967e8c..dcd10be98ff 100644 --- a/blocks/recentlyaccesseditems/classes/output/main.php +++ b/blocks/recentlyaccesseditems/classes/output/main.php @@ -40,7 +40,7 @@ class main implements renderable, templatable { * Export this data so it can be used as the context for a mustache template. * * @param \renderer_base $output - * @return stdClass + * @return array */ public function export_for_template(renderer_base $output) { diff --git a/blocks/rss_client/classes/output/feed.php b/blocks/rss_client/classes/output/feed.php index 02f7e2db95b..28ea2cf3594 100644 --- a/blocks/rss_client/classes/output/feed.php +++ b/blocks/rss_client/classes/output/feed.php @@ -89,8 +89,8 @@ class feed implements \renderable, \templatable { * Export this for use in a mustache template context. * * @see templatable::export_for_template() - * @param renderer_base $output - * @return stdClass + * @param \renderer_base $output + * @return array */ public function export_for_template(\renderer_base $output) { $data = array( diff --git a/blocks/rss_client/classes/output/item.php b/blocks/rss_client/classes/output/item.php index 4bb603a4365..0db3512eb47 100644 --- a/blocks/rss_client/classes/output/item.php +++ b/blocks/rss_client/classes/output/item.php @@ -112,7 +112,7 @@ class item implements \renderable, \templatable { * Export context for use in mustache templates * * @see templatable::export_for_template() - * @param renderer_base $output + * @param \renderer_base $output * @return array */ public function export_for_template(\renderer_base $output) { diff --git a/blocks/rss_client/classes/output/renderer.php b/blocks/rss_client/classes/output/renderer.php index 39f02fd150b..448121d9563 100644 --- a/blocks/rss_client/classes/output/renderer.php +++ b/blocks/rss_client/classes/output/renderer.php @@ -40,8 +40,8 @@ class renderer extends \plugin_renderer_base { /** * Render an RSS Item * - * @param templatable $item - * @return string|boolean + * @param \templatable $item + * @return string */ public function render_item(\templatable $item) { $data = $item->export_for_template($this); @@ -52,8 +52,8 @@ class renderer extends \plugin_renderer_base { /** * Render an RSS Feed * - * @param templatable $feed - * @return string|boolean + * @param \templatable $feed + * @return string */ public function render_feed(\templatable $feed) { $data = $feed->export_for_template($this); @@ -65,7 +65,7 @@ class renderer extends \plugin_renderer_base { * Render an RSS feeds block * * @param \templatable $block - * @return string|boolean + * @return string */ public function render_block(\templatable $block) { $data = $block->export_for_template($this); @@ -76,8 +76,8 @@ class renderer extends \plugin_renderer_base { /** * Render the block footer * - * @param templatable $footer - * @return string|boolean + * @param \templatable $footer + * @return string */ public function render_footer(\templatable $footer) { $data = $footer->export_for_template($this); diff --git a/blocks/rss_client/classes/privacy/provider.php b/blocks/rss_client/classes/privacy/provider.php index e2b71e63735..2ad457bbde3 100644 --- a/blocks/rss_client/classes/privacy/provider.php +++ b/blocks/rss_client/classes/privacy/provider.php @@ -134,7 +134,7 @@ class provider implements /** * Delete all use data which matches the specified deletion_criteria. * - * @param context $context A user context. + * @param \context $context A user context. */ public static function delete_data_for_all_users_in_context(\context $context) { if ($context instanceof \context_user) { diff --git a/blocks/tag_flickr/classes/privacy/provider.php b/blocks/tag_flickr/classes/privacy/provider.php index d77682a231f..071395fe0d8 100644 --- a/blocks/tag_flickr/classes/privacy/provider.php +++ b/blocks/tag_flickr/classes/privacy/provider.php @@ -91,7 +91,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { } diff --git a/blocks/tag_youtube/block_tag_youtube.php b/blocks/tag_youtube/block_tag_youtube.php index c8ec5fca633..871ed164e27 100644 --- a/blocks/tag_youtube/block_tag_youtube.php +++ b/blocks/tag_youtube/block_tag_youtube.php @@ -279,7 +279,7 @@ class block_tag_youtube extends block_base { /** * Renders the list of items. * - * @param array $videosdata + * @param stdClass $videosdata * @return string HTML */ protected function render_items($videosdata) { diff --git a/blocks/tests/privacy/provider_test.php b/blocks/tests/privacy/provider_test.php index b292847b203..eb6bcf1618e 100644 --- a/blocks/tests/privacy/provider_test.php +++ b/blocks/tests/privacy/provider_test.php @@ -393,10 +393,10 @@ class provider_test extends provider_testcase { * Get the block manager. * * @param array $regions The regions. - * @param context $context The context. + * @param \context $context The context. * @param string $pagetype The page type. * @param string $subpage The sub page. - * @return block_manager + * @return \block_manager */ protected function get_block_manager($regions, $context, $pagetype = 'page-type', $subpage = '') { $page = new \moodle_page(); @@ -415,7 +415,7 @@ class provider_test extends provider_testcase { /** * Set a docked preference. * - * @param block_base $block The block. + * @param \block_base $block The block. * @param bool $value The value. * @param int $userid The user ID. */ @@ -426,7 +426,7 @@ class provider_test extends provider_testcase { /** * Set a hidden preference. * - * @param block_base $block The block. + * @param \block_base $block The block. * @param bool $value The value. * @param int $userid The user ID. */ diff --git a/blocks/timeline/classes/output/main.php b/blocks/timeline/classes/output/main.php index 352242d341f..f5d29945854 100644 --- a/blocks/timeline/classes/output/main.php +++ b/blocks/timeline/classes/output/main.php @@ -145,7 +145,7 @@ class main implements renderable, templatable { * Export this data so it can be used as the context for a mustache template. * * @param \renderer_base $output - * @return stdClass + * @return array */ public function export_for_template(renderer_base $output) { diff --git a/cache/classes/helper.php b/cache/classes/helper.php index e2f8b2300df..5f42b24909c 100644 --- a/cache/classes/helper.php +++ b/cache/classes/helper.php @@ -176,7 +176,7 @@ class cache_helper { * This function explicitly does NOT use core functions as it will in some circumstances be called before Moodle has * finished initialising. This happens when loading configuration for instance. * - * @return string + * @return array */ public static function early_get_cache_plugins() { global $CFG; @@ -211,8 +211,9 @@ class cache_helper { * @param string $component * @param string $area * @param array $identifiers - * @param array $keys + * @param array|string|int $keys * @return boolean + * @throws coding_exception */ public static function invalidate_by_definition($component, $area, array $identifiers = array(), $keys = array()) { $cache = cache::make($component, $area, $identifiers); diff --git a/cache/classes/loaders.php b/cache/classes/loaders.php index e78697be15a..b008ae1079b 100644 --- a/cache/classes/loaders.php +++ b/cache/classes/loaders.php @@ -199,7 +199,7 @@ class cache implements cache_loader { * - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars * - staticacceleration : If set to true the cache will hold onto data passing through it. * - staticaccelerationsize : The max size for the static acceleration array. - * @return cache_application|cache_session|cache_store + * @return cache_application|cache_session|cache_request */ public static function make_from_params($mode, $component, $area, array $identifiers = array(), array $options = array()) { $factory = cache_factory::instance(); diff --git a/calendar/classes/external/calendar_event_exporter.php b/calendar/classes/external/calendar_event_exporter.php index 875865d394c..f290ac32837 100644 --- a/calendar/classes/external/calendar_event_exporter.php +++ b/calendar/classes/external/calendar_event_exporter.php @@ -218,7 +218,7 @@ class calendar_event_exporter extends event_exporter_base { * Return the set of minimum and maximum date timestamp values * for the given event. * - * @param event_interface $event + * @param \core_calendar\local\event\entities\event_interface $event * @return array */ protected function get_course_timestamp_limits($event) { @@ -256,7 +256,7 @@ class calendar_event_exporter extends event_exporter_base { * Return the set of minimum and maximum date timestamp values * for the given event. * - * @param event_interface $event + * @param \core_calendar\local\event\entities\event_interface $event * @return array */ protected function get_module_timestamp_limits($event) { @@ -377,7 +377,7 @@ class calendar_event_exporter extends event_exporter_base { * * @deprecated since Moodle 3.6. Please use get_timestamp_min_limit(). * @todo final deprecation. To be removed in Moodle 3.10 - * @param DateTimeInterface $starttime The event start time + * @param \DateTimeInterface $starttime The event start time * @param array $min The module's minimum limit for the event * @return array Returns an array with mindaytimestamp and mindayerror keys. */ @@ -393,7 +393,7 @@ class calendar_event_exporter extends event_exporter_base { * * @deprecated since Moodle 3.6. Please use get_timestamp_max_limit(). * @todo final deprecation. To be removed in Moodle 3.10 - * @param DateTimeInterface $starttime The event start time + * @param \DateTimeInterface $starttime The event start time * @param array $max The module's maximum limit for the event * @return array Returns an array with maxdaytimestamp and maxdayerror keys. */ diff --git a/calendar/classes/local/event/data_access/event_vault.php b/calendar/classes/local/event/data_access/event_vault.php index 41c64c60f31..1a79f1f19fc 100644 --- a/calendar/classes/local/event/data_access/event_vault.php +++ b/calendar/classes/local/event/data_access/event_vault.php @@ -373,7 +373,7 @@ class event_vault implements event_vault_interface { * Fetches records from DB. * * @param int $userid - * @param string $whereconditions + * @param array|null $whereconditions * @param array $whereparams * @param string $ordersql * @param int $offset diff --git a/calendar/classes/local/event/proxies/cm_info_proxy.php b/calendar/classes/local/event/proxies/cm_info_proxy.php index 7aee7b04f6b..4f68cecfb55 100644 --- a/calendar/classes/local/event/proxies/cm_info_proxy.php +++ b/calendar/classes/local/event/proxies/cm_info_proxy.php @@ -72,7 +72,7 @@ class cm_info_proxy implements proxy_interface { /** * Get the full instance of the proxied class. * - * @return \stdClass + * @return \cm_info */ public function get_proxied_instance() { if (!$this->cm) { diff --git a/calendar/classes/local/event/proxies/proxy_interface.php b/calendar/classes/local/event/proxies/proxy_interface.php index d6ed0214621..54133e5f6cc 100644 --- a/calendar/classes/local/event/proxies/proxy_interface.php +++ b/calendar/classes/local/event/proxies/proxy_interface.php @@ -46,7 +46,7 @@ interface proxy_interface { /** * Get the full instance of the proxied class. * - * @return \stdClass + * @return mixed */ public function get_proxied_instance(); } diff --git a/calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php b/calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php index 183158a0dd2..794ea3e9ae1 100644 --- a/calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php +++ b/calendar/classes/local/event/strategies/raw_event_retrieval_strategy.php @@ -68,7 +68,7 @@ class raw_event_retrieval_strategy implements raw_event_retrieval_strategy_inter * @param array|int|boolean $users array of users, user id or boolean for all/no user events * @param array|int|boolean $groups array of groups, group id or boolean for all/no group events * @param array|int|boolean $courses array of courses, course id or boolean for all/no course events - * @param string $whereconditions The conditions in the WHERE clause. + * @param array $whereconditions The conditions in the WHERE clause. * @param array $whereparams The parameters for the WHERE clause. * @param string $ordersql The ORDER BY clause. * @param int $offset Offset. diff --git a/calendar/classes/privacy/provider.php b/calendar/classes/privacy/provider.php index 369b6012026..63f4b72ed04 100644 --- a/calendar/classes/privacy/provider.php +++ b/calendar/classes/privacy/provider.php @@ -252,7 +252,7 @@ class provider implements /** * Delete all Calendar Event and Calendar Subscription data for all users in the specified context. * - * @param context $context Transform the specific context to delete data for. + * @param \context $context Transform the specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { // Delete all Calendar Events in the specified context in batches. @@ -575,7 +575,7 @@ class provider implements * Helper function to return the Calendar Events for a given user and context list. * * @param approved_contextlist $contextlist - * @return array + * @return \moodle_recordset * @throws \coding_exception * @throws \dml_exception */ @@ -642,7 +642,7 @@ class provider implements * Helper function to return the Calendar Subscriptions for a given user and context list. * * @param approved_contextlist $contextlist - * @return array + * @return \moodle_recordset * @throws \coding_exception * @throws \dml_exception */ diff --git a/calendar/lib.php b/calendar/lib.php index 061fa8daf43..41de255e92d 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -182,7 +182,7 @@ define('CALENDAR_EVENT_TYPE_ACTION', 1); */ class calendar_event { - /** @var array An object containing the event properties can be accessed via the magic __get/set methods */ + /** @var stdClass An object containing the event properties can be accessed via the magic __get/set methods */ protected $properties = null; /** @var string The converted event discription with file paths resolved. @@ -3180,7 +3180,7 @@ function calendar_import_events_from_ical(iCalendar $ical, int $subscriptionid = * Fetch a calendar subscription and update the events in the calendar. * * @param int $subscriptionid The course ID for the calendar. - * @return string A log of the import progress, including errors. + * @return array A log of the import progress, including errors. */ function calendar_update_subscription_events($subscriptionid) { $sub = calendar_get_subscription($subscriptionid); diff --git a/competency/classes/api.php b/competency/classes/api.php index e7e3e573fff..dccc12f3403 100644 --- a/competency/classes/api.php +++ b/competency/classes/api.php @@ -459,7 +459,7 @@ class api { * * @param int $id The id of the competency to read. * @param bool $includerelated Include related tags or not. - * @return stdClass + * @return competency */ public static function read_competency($id, $includerelated = false) { static::require_enabled(); @@ -4043,7 +4043,7 @@ class api { * This method does not copy the related competencies. * * @param int $frameworkid - framework id - * @param competency[] $tree - array of competencies object + * @param stdClass[] $tree - list of framework competency nodes * @param int $oldparent - old parent id * @param int $newparent - new parent id * @return competency[] $matchids - List of old competencies ids matched with new competencies object. @@ -4083,7 +4083,7 @@ class api { /** * Recursively migrate competency rules. * - * @param competency[] $tree - array of competencies object + * @param array $tree - array of competencies object * @param competency[] $matchids - List of old competencies ids matched with new competencies object */ protected static function migrate_competency_tree_rules($tree, $matchids) { @@ -4116,7 +4116,7 @@ class api { /** * Archive user competencies in a plan. * - * @param int $plan The plan object. + * @param plan $plan The plan object. * @return void */ protected static function archive_user_competencies_in_plan($plan) { @@ -4166,7 +4166,7 @@ class api { /** * Delete archived user competencies in a plan. * - * @param int $plan The plan object. + * @param plan $plan The plan object. * @return void */ protected static function remove_archived_user_competencies_in_plan($plan) { diff --git a/competency/classes/competency.php b/competency/classes/competency.php index a6991372910..5942a623369 100644 --- a/competency/classes/competency.php +++ b/competency/classes/competency.php @@ -721,7 +721,7 @@ class competency extends persistent { * Build a framework tree with competency nodes. * * @param int $frameworkid the framework id - * @return node[] tree of framework competency nodes + * @return stdClass[] tree of framework competency nodes */ public static function get_framework_tree($frameworkid) { $competencies = self::search('', $frameworkid); @@ -731,7 +731,7 @@ class competency extends persistent { /** * Get the context from the framework. * - * @return context + * @return \context */ public function get_context() { return $this->get_framework()->get_context(); @@ -742,7 +742,7 @@ class competency extends persistent { * * @param array $all - List of all competency classes. * @param int $parentid - The current parent ID. Pass 0 to build the tree from the top. - * @return node[] $tree tree of nodes + * @return stdClass[] $tree tree of nodes */ protected static function build_tree($all, $parentid) { $tree = array(); diff --git a/competency/classes/competency_framework.php b/competency/classes/competency_framework.php index f47a1abd0ce..d1a6b43b9fa 100644 --- a/competency/classes/competency_framework.php +++ b/competency/classes/competency_framework.php @@ -70,7 +70,7 @@ class competency_framework extends persistent { /** * Get the context. * - * @return context The context + * @return \context The context */ public function get_context() { return context::instance_by_id($this->get('contextid')); diff --git a/competency/classes/user_competency.php b/competency/classes/user_competency.php index 0f99de9af83..5e6777696b9 100644 --- a/competency/classes/user_competency.php +++ b/competency/classes/user_competency.php @@ -216,7 +216,7 @@ class user_competency extends persistent { /** * Get the context. * - * @return context The context. + * @return \context The context. */ public function get_context() { return context_user::instance($this->get('userid')); diff --git a/completion/criteria/completion_criteria_date.php b/completion/criteria/completion_criteria_date.php index e3fbb6d4ab7..b077091d12c 100644 --- a/completion/criteria/completion_criteria_date.php +++ b/completion/criteria/completion_criteria_date.php @@ -54,7 +54,7 @@ class completion_criteria_date extends completion_criteria { /** * Add appropriate form elements to the critieria form * - * @param moodleform $mform Moodle forms object + * @param MoodleQuickForm $mform Moodle forms object * @param stdClass $data not used */ public function config_form_display(&$mform, $data = null) { diff --git a/completion/criteria/completion_criteria_role.php b/completion/criteria/completion_criteria_role.php index 2413fb4215f..a09b8d42098 100644 --- a/completion/criteria/completion_criteria_role.php +++ b/completion/criteria/completion_criteria_role.php @@ -54,7 +54,7 @@ class completion_criteria_role extends completion_criteria { /** * Add appropriate form elements to the critieria form * - * @param moodleform $mform Moodle forms object + * @param MoodleQuickForm $mform Moodle forms object * @param stdClass $data used to set default values of the form */ public function config_form_display(&$mform, $data = null) { diff --git a/course/classes/external/get_enrolled_courses_with_action_events_by_timeline_classification.php b/course/classes/external/get_enrolled_courses_with_action_events_by_timeline_classification.php index 91214f5f61d..7723f878c38 100644 --- a/course/classes/external/get_enrolled_courses_with_action_events_by_timeline_classification.php +++ b/course/classes/external/get_enrolled_courses_with_action_events_by_timeline_classification.php @@ -205,7 +205,7 @@ class get_enrolled_courses_with_action_events_by_timeline_classification extends /** * Returns description of method result value. * - * @return external_description + * @return \core_external\external_description */ public static function execute_returns(): external_single_structure { return new external_single_structure( diff --git a/course/classes/output/content_export_link.php b/course/classes/output/content_export_link.php index cfa667a7896..613ab3c3830 100644 --- a/course/classes/output/content_export_link.php +++ b/course/classes/output/content_export_link.php @@ -37,7 +37,7 @@ class content_export_link { * Prepare and return the various attributes required for a link/button to populate/trigger the download course content modal. * * @param \context $context The context of the content being exported. - * @return stdClass + * @return \stdClass */ public static function get_attributes(\context $context): \stdClass { global $CFG; diff --git a/course/classes/output/course_module_name.php b/course/classes/output/course_module_name.php index 070d4b1ebc3..62d354e3329 100644 --- a/course/classes/output/course_module_name.php +++ b/course/classes/output/course_module_name.php @@ -71,7 +71,7 @@ class course_module_name extends \core\output\inplace_editable { /** * Export this data so it can be used as the context for a mustache template (core/inplace_editable). * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output) { diff --git a/course/classes/privacy/provider.php b/course/classes/privacy/provider.php index ade42dd44d3..2fa4b368672 100644 --- a/course/classes/privacy/provider.php +++ b/course/classes/privacy/provider.php @@ -233,7 +233,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { // Check what context we've been delivered. diff --git a/course/classes/search/course.php b/course/classes/search/course.php index cce89ec3430..b1bab831c08 100644 --- a/course/classes/search/course.php +++ b/course/classes/search/course.php @@ -68,7 +68,7 @@ class course extends \core_search\base { /** * Returns the document associated with this course. * - * @param stdClass $record + * @param \stdClass $record * @param array $options * @return \core_search\document */ diff --git a/course/externallib.php b/course/externallib.php index 550cc920e24..6369ef29a52 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -1956,8 +1956,8 @@ class core_course_external extends external_api { * Sort categories array by path * private function: only used by get_categories * - * @param array $category1 - * @param array $category2 + * @param stdClass $category1 + * @param stdClass $category2 * @return int result of strcmp * @since Moodle 2.3 */ @@ -2637,7 +2637,7 @@ class core_course_external extends external_api { * Returns a course structure definition * * @param boolean $onlypublicdata set to true, to retrieve only fields viewable by anyone when the course is visible - * @return array the course structure + * @return external_single_structure the course structure * @since Moodle 3.2 */ protected static function get_course_structure($onlypublicdata = true) { diff --git a/course/format/classes/base.php b/course/format/classes/base.php index a4c8d45b2ad..faa2757dd95 100644 --- a/course/format/classes/base.php +++ b/course/format/classes/base.php @@ -518,7 +518,7 @@ abstract class base { * Returns the display name of the given section that the course prefers. * * @param int|stdClass $section Section object from database or just field course_sections.section - * @return Display name that the course format prefers, e.g. "Topic 2" + * @return string Display name that the course format prefers, e.g. "Topic 2" */ public function get_section_name($section) { if (is_object($section)) { diff --git a/course/format/classes/output/local/content/section/controlmenu.php b/course/format/classes/output/local/content/section/controlmenu.php index a9bab4f813c..ecc29c1c221 100644 --- a/course/format/classes/output/local/content/section/controlmenu.php +++ b/course/format/classes/output/local/content/section/controlmenu.php @@ -67,7 +67,7 @@ class controlmenu implements named_templatable, renderable { /** * Export this data so it can be used as the context for a mustache template. * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output): stdClass { diff --git a/course/format/classes/output/local/state/section.php b/course/format/classes/output/local/state/section.php index 63ee8f5df4e..a9e32f95640 100644 --- a/course/format/classes/output/local/state/section.php +++ b/course/format/classes/output/local/state/section.php @@ -52,7 +52,7 @@ class section implements renderable { /** * Export this data so it can be used as state object in the course editor. * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output): stdClass { diff --git a/course/togglecompletion.php b/course/togglecompletion.php index c65a99b1c7c..82ae6b625e5 100644 --- a/course/togglecompletion.php +++ b/course/togglecompletion.php @@ -64,6 +64,7 @@ if ($courseid) { require_sesskey(); completion_criteria::factory(array('id'=>$rolec, 'criteriatype'=>COMPLETION_CRITERIA_TYPE_ROLE)); //TODO: this is dumb, because it does not fetch the data?!?! + /** @var completion_criteria_role $criteria */ $criteria = completion_criteria_role::fetch(array('id'=>$rolec)); if ($criteria and user_has_role_assignment($USER->id, $criteria->role, $context->id)) { diff --git a/enrol/classes/privacy/provider.php b/enrol/classes/privacy/provider.php index 4691244a925..8deac388afa 100644 --- a/enrol/classes/privacy/provider.php +++ b/enrol/classes/privacy/provider.php @@ -185,7 +185,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { global $DB; diff --git a/enrol/cohort/classes/privacy/provider.php b/enrol/cohort/classes/privacy/provider.php index c441f4a6fb6..caed9b0b71e 100644 --- a/enrol/cohort/classes/privacy/provider.php +++ b/enrol/cohort/classes/privacy/provider.php @@ -109,7 +109,7 @@ class provider implements /** * Delete all use data which matches the specified deletion_criteria. * - * @param context $context A user context. + * @param \context $context A user context. */ public static function delete_data_for_all_users_in_context(\context $context) { if (empty($context)) { diff --git a/enrol/externallib.php b/enrol/externallib.php index 32c46afca3f..0497bc3fcf3 100644 --- a/enrol/externallib.php +++ b/enrol/externallib.php @@ -1045,7 +1045,7 @@ class core_enrol_external extends external_api { /** * Returns description of submit_user_enrolment_form parameters. * - * @return external_function_parameters. + * @return external_function_parameters */ public static function submit_user_enrolment_form_parameters() { return new external_function_parameters([ diff --git a/enrol/fee/classes/privacy/provider.php b/enrol/fee/classes/privacy/provider.php index 8c9b4c0d4de..fabe13cb405 100644 --- a/enrol/fee/classes/privacy/provider.php +++ b/enrol/fee/classes/privacy/provider.php @@ -153,7 +153,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { if ($context instanceof \context_course) { diff --git a/enrol/flatfile/tests/flatfile_test.php b/enrol/flatfile/tests/flatfile_test.php index 74bdd992761..d72993a96e8 100644 --- a/enrol/flatfile/tests/flatfile_test.php +++ b/enrol/flatfile/tests/flatfile_test.php @@ -74,9 +74,9 @@ class flatfile_test extends \advanced_testcase { global $CFG, $DB; $this->resetAfterTest(); - /** @var enrol_flatfile_plugin $flatfileplugin */ + /** @var \enrol_flatfile_plugin $flatfileplugin */ $flatfileplugin = enrol_get_plugin('flatfile'); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotEmpty($manualplugin); @@ -283,9 +283,9 @@ class flatfile_test extends \advanced_testcase { $this->preventResetByRollback(); - /** @var enrol_flatfile_plugin $flatfileplugin */ + /** @var \enrol_flatfile_plugin $flatfileplugin */ $flatfileplugin = enrol_get_plugin('flatfile'); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotEmpty($manualplugin); @@ -368,9 +368,9 @@ class flatfile_test extends \advanced_testcase { global $DB; $this->resetAfterTest(); - /** @var enrol_flatfile_plugin $flatfileplugin */ + /** @var \enrol_flatfile_plugin $flatfileplugin */ $flatfileplugin = enrol_get_plugin('flatfile'); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotEmpty($manualplugin); diff --git a/enrol/ldap/classes/task/sync_enrolments.php b/enrol/ldap/classes/task/sync_enrolments.php index e34b72a0d46..fbda7ed8a4f 100644 --- a/enrol/ldap/classes/task/sync_enrolments.php +++ b/enrol/ldap/classes/task/sync_enrolments.php @@ -54,7 +54,7 @@ class sync_enrolments extends \core\task\scheduled_task { exit(0); // Note, exit with success code, this is not an error - it's just disabled. } - /** @var enrol_ldap_plugin $enrol */ + /** @var \enrol_ldap_plugin $enrol */ $enrol = enrol_get_plugin('ldap'); $trace = new \text_progress_trace(); diff --git a/enrol/ldap/tests/ldap_test.php b/enrol/ldap/tests/ldap_test.php index 13bea0effdb..c918b19f029 100644 --- a/enrol/ldap/tests/ldap_test.php +++ b/enrol/ldap/tests/ldap_test.php @@ -102,7 +102,7 @@ class ldap_test extends \advanced_testcase { } // Configure enrol plugin. - /** @var enrol_ldap_plugin $enrol */ + /** @var \enrol_ldap_plugin $enrol */ $enrol = enrol_get_plugin('ldap'); $enrol->set_config('host_url', TEST_ENROL_LDAP_HOST_URL); $enrol->set_config('start_tls', 0); diff --git a/enrol/locallib.php b/enrol/locallib.php index 798f789edc7..beeb013e72d 100644 --- a/enrol/locallib.php +++ b/enrol/locallib.php @@ -590,7 +590,7 @@ class course_enrolment_manager { * that SQL, and the filter that was used in constructing the sql. * * @global moodle_database $DB - * @return string + * @return array */ protected function get_instance_sql() { global $DB; diff --git a/enrol/lti/tests/privacy/provider_test.php b/enrol/lti/tests/privacy/provider_test.php index 33f1fea7ee0..1d832501cb8 100644 --- a/enrol/lti/tests/privacy/provider_test.php +++ b/enrol/lti/tests/privacy/provider_test.php @@ -24,6 +24,7 @@ namespace enrol_lti\privacy; use enrol_lti\privacy\provider; +use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -176,7 +177,7 @@ class provider_test extends \core_privacy\tests\provider_testcase { /** * Creates a LTI user given the provided context * - * @param context $context + * @param \context $context * @param int $userid */ private function create_lti_users(\context $context, int $userid) { diff --git a/enrol/meta/classes/privacy/provider.php b/enrol/meta/classes/privacy/provider.php index b91ba1b9241..b2c9a767d29 100644 --- a/enrol/meta/classes/privacy/provider.php +++ b/enrol/meta/classes/privacy/provider.php @@ -109,7 +109,7 @@ class provider implements /** * Delete all use data which matches the specified deletion_criteria. * - * @param context $context A user context. + * @param \context $context A user context. */ public static function delete_data_for_all_users_in_context(\context $context) { if (empty($context)) { diff --git a/enrol/paypal/classes/util.php b/enrol/paypal/classes/util.php index fcb8f3c0fd3..a0d893ce59d 100644 --- a/enrol/paypal/classes/util.php +++ b/enrol/paypal/classes/util.php @@ -39,7 +39,7 @@ final class util { * Alerts site admin of potential problems. * * @param string $subject email subject - * @param stdClass $data PayPal IPN data + * @param \stdClass $data PayPal IPN data */ public static function message_paypal_error_to_admin($subject, $data) { $admin = get_admin(); diff --git a/enrol/paypal/tests/paypal_test.php b/enrol/paypal/tests/paypal_test.php index b576f06e49c..acc8a2fc416 100644 --- a/enrol/paypal/tests/paypal_test.php +++ b/enrol/paypal/tests/paypal_test.php @@ -61,9 +61,9 @@ class paypal_test extends \advanced_testcase { global $DB; $this->resetAfterTest(); - /** @var enrol_paypal_plugin $paypalplugin */ + /** @var \enrol_paypal_plugin $paypalplugin */ $paypalplugin = enrol_get_plugin('paypal'); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotEmpty($manualplugin); diff --git a/enrol/paypal/tests/privacy/provider_test.php b/enrol/paypal/tests/privacy/provider_test.php index e2a17899e8d..75bfa8cb0e8 100644 --- a/enrol/paypal/tests/privacy/provider_test.php +++ b/enrol/paypal/tests/privacy/provider_test.php @@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die(); use core_privacy\local\metadata\collection; use enrol_paypal\privacy\provider; use core_privacy\local\request\writer; +use stdClass; /** * Privacy provider test for enrol_paypal. diff --git a/enrol/tests/course_enrolment_manager_test.php b/enrol/tests/course_enrolment_manager_test.php index ce8d6a97f49..c8cd3bdf38d 100644 --- a/enrol/tests/course_enrolment_manager_test.php +++ b/enrol/tests/course_enrolment_manager_test.php @@ -29,7 +29,7 @@ use course_enrolment_manager; class course_enrolment_manager_test extends \advanced_testcase { /** * The course context used in tests. - * @var stdClass + * @var \stdClass */ private $course = null; /** @@ -250,7 +250,7 @@ class course_enrolment_manager_test extends \advanced_testcase { * Sets up a custom profile field and the showuseridentity option, and creates a test user * with suitable values set. * - * @return stdClass Test user + * @return \stdClass Test user */ protected function setup_for_user_identity_tests(): \stdClass { // Configure extra fields to include one normal user field and one profile field, and diff --git a/enrol/tests/externallib_test.php b/enrol/tests/externallib_test.php index e4f0e243d44..868b444ceb2 100644 --- a/enrol/tests/externallib_test.php +++ b/enrol/tests/externallib_test.php @@ -1198,7 +1198,7 @@ class externallib_test extends externallib_advanced_testcase { $this->resetAfterTest(true); $datagen = $this->getDataGenerator(); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student'], MUST_EXIST); @@ -1277,7 +1277,7 @@ class externallib_test extends externallib_advanced_testcase { $this->resetAfterTest(true); $datagen = $this->getDataGenerator(); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotNull($manualplugin); @@ -1342,7 +1342,7 @@ class externallib_test extends externallib_advanced_testcase { $this->resetAfterTest(true); $datagen = $this->getDataGenerator(); - /** @var enrol_manual_plugin $manualplugin */ + /** @var \enrol_manual_plugin $manualplugin */ $manualplugin = enrol_get_plugin('manual'); $this->assertNotNull($manualplugin); diff --git a/files/tests/conversion_test.php b/files/tests/conversion_test.php index 1cacf28e0e2..ced4d29b5bd 100644 --- a/files/tests/conversion_test.php +++ b/files/tests/conversion_test.php @@ -31,7 +31,7 @@ class conversion_test extends \advanced_testcase { * @param string $filecontent The content of the mocked file * @param string $filename The file name to use in the stored_file * @param string $filerecord Any overrides to the filerecord - * @return stored_file + * @return \stored_file */ protected function create_stored_file($filecontent = 'content', $filename = 'testfile.txt', $filerecord = []) { $filerecord = array_merge([ diff --git a/filter/glossary/tests/filter_test.php b/filter/glossary/tests/filter_test.php index 4fae44c91d6..0f46ac7eb53 100644 --- a/filter/glossary/tests/filter_test.php +++ b/filter/glossary/tests/filter_test.php @@ -125,7 +125,7 @@ class filter_test extends \advanced_testcase { array('course' => $course->id, 'mainglossary' => 1)); // Create two entries with ampersands and one normal entry. - /** @var mod_glossary_generator $generator */ + /** @var \mod_glossary_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); $category = $generator->create_category($glossary, array('name' => 'My category', 'usedynalink' => 1)); @@ -163,7 +163,7 @@ class filter_test extends \advanced_testcase { array('course' => $course->id, 'mainglossary' => 1)); // Create two entries with ampersands and one normal entry. - /** @var mod_glossary_generator $generator */ + /** @var \mod_glossary_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); $normal = $generator->create_content($glossary, array('concept' => 'normal')); $amp1 = $generator->create_content($glossary, array('concept' => 'A&B')); @@ -209,7 +209,7 @@ class filter_test extends \advanced_testcase { array('course' => $course->id, 'mainglossary' => 1)); // Create two entries with ampersands and one normal entry. - /** @var mod_glossary_generator $generator */ + /** @var \mod_glossary_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); $simple = $generator->create_content($glossary, array('concept' => 'simple')); $withbrackets = $generator->create_content($glossary, array('concept' => 'more complex (perhaps)')); @@ -292,7 +292,7 @@ class filter_test extends \advanced_testcase { array('course' => $course->id, 'mainglossary' => 1)); // Create two entries with ampersands and one normal entry. - /** @var mod_glossary_generator $generator */ + /** @var \mod_glossary_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_glossary'); $category = $generator->create_category($glossary, array('name' => 'My category', 'usedynalink' => 1)); diff --git a/grade/grading/form/guide/tests/privacy/provider_test.php b/grade/grading/form/guide/tests/privacy/provider_test.php index c114b8537a5..3b69b4ceb7d 100644 --- a/grade/grading/form/guide/tests/privacy/provider_test.php +++ b/grade/grading/form/guide/tests/privacy/provider_test.php @@ -173,8 +173,8 @@ class provider_test extends provider_testcase { /** * Generate a guide controller with sample data required for testing of this class. * - * @param context_module $context - * @return gradingform_guide_controller + * @param \context_module $context + * @return \gradingform_guide_controller */ protected function get_test_guide(\context_module $context): \gradingform_guide_controller { $generator = \testing_util::get_data_generator(); @@ -186,7 +186,7 @@ class provider_test extends provider_testcase { /** * Fetch a set of sample data. * - * @param gradingform_guide_controller $controller + * @param \gradingform_guide_controller $controller * @param int $itemid * @param float $spellingscore * @param string $spellingremark diff --git a/grade/lib.php b/grade/lib.php index 1bfaa0b128b..559346d1ce1 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -3646,7 +3646,7 @@ abstract class grade_helper { /** * Get information on outcomes * @param int $courseid - * @return grade_plugin_info + * @return grade_plugin_info[]|false */ public static function get_info_outcomes($courseid) { global $CFG, $SITE; diff --git a/grade/report/singleview/classes/local/screen/grade.php b/grade/report/singleview/classes/local/screen/grade.php index 1fddafdb0a4..e42b388f2be 100644 --- a/grade/report/singleview/classes/local/screen/grade.php +++ b/grade/report/singleview/classes/local/screen/grade.php @@ -197,7 +197,7 @@ class grade extends tablelike implements selectable_items, filterable_items { /** * Format a row in the table * - * @param user $item + * @param stdClass $item * @return array */ public function format_line($item): array { diff --git a/group/lib.php b/group/lib.php index 197a2f5a84f..4d4a8b9981c 100644 --- a/group/lib.php +++ b/group/lib.php @@ -241,7 +241,8 @@ function groups_remove_member($grouporid, $userorid) { * @param stdClass $data group properties * @param stdClass $editform * @param array $editoroptions - * @return id of group or false if error + * @return int id of group or throws an exception on error + * @throws moodle_exception */ function groups_create_group($data, $editform = false, $editoroptions = false) { global $CFG, $DB, $USER; @@ -327,7 +328,8 @@ function groups_create_group($data, $editform = false, $editoroptions = false) { * * @param stdClass $data grouping properties * @param array $editoroptions - * @return id of grouping or false if error + * @return int id of grouping or throws an exception on error + * @throws moodle_exception */ function groups_create_grouping($data, $editoroptions=null) { global $DB; diff --git a/h5p/classes/helper.php b/h5p/classes/helper.php index 4cf36b287e4..ac7acf74a70 100644 --- a/h5p/classes/helper.php +++ b/h5p/classes/helper.php @@ -41,8 +41,8 @@ class helper { * Store an H5P file. * * @param factory $factory The \core_h5p\factory object - * @param stored_file $file Moodle file instance - * @param stdClass $config Button options config + * @param \stored_file $file Moodle file instance + * @param \stdClass $config Button options config * @param bool $onlyupdatelibs Whether new libraries can be installed or only the existing ones can be updated * @param bool $skipcontent Should the content be skipped (so only the libraries will be saved)? * @@ -77,10 +77,10 @@ class helper { /** * Get the error messages stored in our H5P framework. * - * @param stdClass $messages The error, exception and info messages, raised while preparing and running an H5P content. + * @param \stdClass $messages The error, exception and info messages, raised while preparing and running an H5P content. * @param factory $factory The \core_h5p\factory object * - * @return stdClass with framework error messages. + * @return \stdClass with framework error messages. */ public static function get_messages(\stdClass $messages, factory $factory): \stdClass { $core = $factory->get_core(); @@ -198,7 +198,7 @@ class helper { * @param string $filepath The filepath of the file * @param int $userid The author of the file * @param \context $context The context where the file will be created - * @return stored_file The file created + * @return \stored_file The file created */ public static function create_fake_stored_file_from_path(string $filepath, int $userid = 0, \context $context = null): \stored_file { diff --git a/lib/accesslib.php b/lib/accesslib.php index 49b5ac874be..1000d93aa94 100644 --- a/lib/accesslib.php +++ b/lib/accesslib.php @@ -1519,7 +1519,7 @@ function unassign_capability($capability, $roleid, $contextid = null) { * @param string $capability capability name (string) * @param string $permission optional, the permission defined for this capability * either CAP_ALLOW, CAP_PREVENT or CAP_PROHIBIT. Defaults to null which means any. - * @param stdClass $context null means any + * @param context|null $context null means any * @return array of role records */ function get_roles_with_capability($capability, $permission = null, $context = null) { @@ -4008,7 +4008,7 @@ function sort_by_roleassignment_authority($users, context $context, $roles = arr * (and $sort by extension) params according to it, as the first field * returned by the database should be unique (ra.id is the best candidate). * - * @param int $roleid (can also be an array of ints!) + * @param int|array $roleid (can also be an array of ints!) * @param context $context * @param bool $parent if true, get list of users assigned in higher context too * @param string $fields fields from user (u.) , role assignment (ra) or role (r.) @@ -4694,7 +4694,7 @@ function role_fix_names($roleoptions, context $context = null, $rolenamedisplay * Most of the time, if the 2 components are different we should print a new line, (e.g. course system->rss client) * but when we are in grade, all reports/import/export capabilities should be together * - * @param string $cap component string a + * @param stdClass $cap component string a * @param string $comp component string b * @param int $contextlevel * @return bool whether 2 component are in different "sections" @@ -4952,7 +4952,7 @@ function prohibit_is_removable($roleid, context $context, $capability) { * it should produce as few overrides as possible. * * @param int $roleid - * @param stdClass $context + * @param stdClass|context $context * @param string $capname capability name * @param int $permission * @return void diff --git a/lib/adminlib.php b/lib/adminlib.php index c698a55e9d3..5aab3eafde8 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -1716,7 +1716,7 @@ class admin_settingpage implements part_of_admin_tree, linkable_settings_page { abstract class admin_setting { /** @var string unique ascii name, either 'mysetting' for settings that in config, or 'myplugin/mysetting' for ones in config_plugins. */ public $name; - /** @var string localised name */ + /** @var lang_string|string localised name */ public $visiblename; /** @var string localised long description in Markdown format */ public $description; @@ -8321,6 +8321,7 @@ class admin_setting_managemediaplayers extends admin_setting { $usedextensions = []; foreach ($plugins as $name => $plugin) { $url->param('media', $name); + /** @var \core\plugininfo\media $plugininfo */ $plugininfo = $pluginmanager->get_plugin_info('media_'.$name); $version = $plugininfo->versiondb; $supports = $plugininfo->supports($usedextensions); diff --git a/lib/authlib.php b/lib/authlib.php index 16e06f7580c..2d742cdc5c3 100644 --- a/lib/authlib.php +++ b/lib/authlib.php @@ -1197,7 +1197,7 @@ function signup_is_enabled() { /** * Helper function used to print locking for auth plugins on admin pages. - * @param stdclass $settings Moodle admin settings instance + * @param admin_settingpage $settings Moodle admin settings instance * @param string $auth authentication plugin shortname * @param array $userfields user profile fields * @param string $helptext help text to be displayed at top of form diff --git a/lib/badgeslib.php b/lib/badgeslib.php index f9716e62c59..d1f4d5ff5f0 100644 --- a/lib/badgeslib.php +++ b/lib/badgeslib.php @@ -131,7 +131,7 @@ class_alias('\core_badges\badge', 'badge'); /** * Sends notifications to users about awarded badges. * - * @param badge $badge Badge that was issued + * @param \core_badges\badge $badge Badge that was issued * @param int $userid Recipient ID * @param string $issued Unique hash of an issued badge * @param string $filepathhash File path hash of an issued badge for attachments @@ -881,7 +881,7 @@ function badges_open_badges_backpack_api(?int $backpackid = null) { * * @param int $id The backpack id. * @param int $userid The owner of the backpack, 0 if it's a sitewide backpack else a user's site backpack - * @return array(stdClass) + * @return stdClass */ function badges_get_site_backpack($id, int $userid = 0) { global $DB; @@ -919,7 +919,7 @@ function badges_get_user_backpack(?int $userid = 0) { /** * Get the primary backpack for the site * - * @return array(stdClass) + * @return stdClass */ function badges_get_site_primary_backpack() { global $DB; diff --git a/lib/behat/classes/behat_core_generator.php b/lib/behat/classes/behat_core_generator.php index 2a81c598de1..8c7fdfb2f0a 100644 --- a/lib/behat/classes/behat_core_generator.php +++ b/lib/behat/classes/behat_core_generator.php @@ -766,7 +766,9 @@ class behat_core_generator extends behat_generator_base { } $data['contextid'] = $context->id; - $this->datagenerator->get_plugin_generator('core_question')->create_question_category($data); + /** @var core_question_generator $qgenerator */ + $qgenerator = $this->datagenerator->get_plugin_generator('core_question'); + $qgenerator->create_question_category($data); } /** @@ -813,7 +815,9 @@ class behat_core_generator extends behat_generator_base { $missingtypespecialcase = true; } - $questiondata = $this->datagenerator->get_plugin_generator('core_question') + /** @var core_question_generator $qgenerator */ + $qgenerator = $this->datagenerator->get_plugin_generator('core_question'); + $questiondata = $qgenerator ->create_question($data['qtype'], $which, $data); if ($missingtypespecialcase) { @@ -962,7 +966,7 @@ class behat_core_generator extends behat_generator_base { /** * Creates an analytics model * - * @param target $data + * @param array $data target * @return void */ protected function process_analytics_model($data) { diff --git a/lib/behat/classes/behat_session_trait.php b/lib/behat/classes/behat_session_trait.php index ae09ebe6e85..8132bddb699 100644 --- a/lib/behat/classes/behat_session_trait.php +++ b/lib/behat/classes/behat_session_trait.php @@ -346,7 +346,7 @@ trait behat_session_trait { * an exception. * * @throws Exception If it timeouts without receiving something != false from the closure - * @param Function|array|string $lambda The function to execute or an array passed to call_user_func (maps to a class method) + * @param callable $lambda The function to execute or an array passed to call_user_func (maps to a class method) * @param mixed $args Arguments to pass to the closure * @param int $timeout Timeout in seconds * @param Exception $exception The exception to throw in case it time outs. @@ -1041,7 +1041,7 @@ EOF; * Helper function to execute api in a given context. * * @param string $contextapi context in which api is defined. - * @param array $params list of params to pass. + * @param array|mixed $params list of params to pass or a single parameter * @throws Exception */ protected function execute($contextapi, $params = array()) { diff --git a/lib/blocklib.php b/lib/blocklib.php index d24855600ed..3ccb07a0734 100644 --- a/lib/blocklib.php +++ b/lib/blocklib.php @@ -345,7 +345,7 @@ class block_manager { * @param string $region region name * @param float $weight weight. May be fractional, since you may want to move a block * between ones with weight 2 and 3, say ($weight would be 2.5). - * @return string URL for moving block $this->movingblock to this position. + * @return moodle_url URL for moving block $this->movingblock to this position. */ protected function get_move_target_url($region, $weight) { return new moodle_url($this->page->url, array('bui_moveid' => $this->movingblock, @@ -1534,6 +1534,7 @@ class block_manager { // At this point we are going to display the block selector, overwrite global $PAGE ready for this. $PAGE = $addpage; // Some functions use $OUTPUT so we need to replace that too. + /** @var core_renderer $OUTPUT */ $OUTPUT = $addpage->get_renderer('core'); $site = get_site(); @@ -1611,6 +1612,7 @@ class block_manager { // overwrite global $PAGE ready for this. (Formslib refers to it.) $PAGE = $deletepage; //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that too + /** @var core_renderer $output */ $output = $deletepage->get_renderer('core'); $OUTPUT = $output; diff --git a/lib/classes/antivirus/scanner.php b/lib/classes/antivirus/scanner.php index bcf30b50566..e36ba57fd29 100644 --- a/lib/classes/antivirus/scanner.php +++ b/lib/classes/antivirus/scanner.php @@ -43,7 +43,7 @@ abstract class scanner { /** Scanning result indicating the error. */ const SCAN_RESULT_ERROR = 2; - /** @var stdClass the config for antivirus */ + /** @var \stdClass the config for antivirus */ protected $config; /** @var string scanning notice */ protected $scanningnotice = ''; diff --git a/lib/classes/check/access/defaultuserrole.php b/lib/classes/check/access/defaultuserrole.php index da15a5743f7..d3407a06450 100644 --- a/lib/classes/check/access/defaultuserrole.php +++ b/lib/classes/check/access/defaultuserrole.php @@ -52,7 +52,7 @@ class defaultuserrole extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { global $CFG; diff --git a/lib/classes/check/access/frontpagerole.php b/lib/classes/check/access/frontpagerole.php index 5fcd3d826cd..54fda55c289 100644 --- a/lib/classes/check/access/frontpagerole.php +++ b/lib/classes/check/access/frontpagerole.php @@ -52,7 +52,7 @@ class frontpagerole extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/access/guestrole.php b/lib/classes/check/access/guestrole.php index 99d13592ddc..de8cc7bccd8 100644 --- a/lib/classes/check/access/guestrole.php +++ b/lib/classes/check/access/guestrole.php @@ -52,7 +52,7 @@ class guestrole extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/access/riskadmin.php b/lib/classes/check/access/riskadmin.php index d751be88297..2b2981d18bb 100644 --- a/lib/classes/check/access/riskadmin.php +++ b/lib/classes/check/access/riskadmin.php @@ -52,7 +52,7 @@ class riskadmin extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/access/riskbackup.php b/lib/classes/check/access/riskbackup.php index 4339bd6fa2e..d50eeca0183 100644 --- a/lib/classes/check/access/riskbackup.php +++ b/lib/classes/check/access/riskbackup.php @@ -50,7 +50,7 @@ class riskbackup extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/access/riskxss.php b/lib/classes/check/access/riskxss.php index 3ce984a19e8..6f19b37f434 100644 --- a/lib/classes/check/access/riskxss.php +++ b/lib/classes/check/access/riskxss.php @@ -57,7 +57,7 @@ class riskxss extends \core\check\check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/check.php b/lib/classes/check/check.php index 8042fe8315b..7abdcafd206 100644 --- a/lib/classes/check/check.php +++ b/lib/classes/check/check.php @@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die(); abstract class check { /** - * @var $string $component - The component / plugin this task belongs to. + * @var string $component - The component / plugin this task belongs to. * * This is autopopulated by the check manager. */ @@ -101,7 +101,7 @@ abstract class check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return null; diff --git a/lib/classes/check/environment/antivirus.php b/lib/classes/check/environment/antivirus.php index 190edd9af57..ce3dd23fb86 100644 --- a/lib/classes/check/environment/antivirus.php +++ b/lib/classes/check/environment/antivirus.php @@ -44,7 +44,7 @@ class antivirus extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/environment/environment.php b/lib/classes/check/environment/environment.php index cf221b72a17..80f9983aeaa 100644 --- a/lib/classes/check/environment/environment.php +++ b/lib/classes/check/environment/environment.php @@ -51,7 +51,7 @@ class environment extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/environment/publicpaths.php b/lib/classes/check/environment/publicpaths.php index 7e5050dc05e..29736b45a72 100644 --- a/lib/classes/check/environment/publicpaths.php +++ b/lib/classes/check/environment/publicpaths.php @@ -295,7 +295,7 @@ class publicpaths extends check { /** * Link to the dev docs for more info. * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/environment/upgradecheck.php b/lib/classes/check/environment/upgradecheck.php index 706f98723bf..077dbc8acf4 100644 --- a/lib/classes/check/environment/upgradecheck.php +++ b/lib/classes/check/environment/upgradecheck.php @@ -51,7 +51,7 @@ class upgradecheck extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/http/cookiesecure.php b/lib/classes/check/http/cookiesecure.php index 3f403be7e5a..a5a5b1caf15 100644 --- a/lib/classes/check/http/cookiesecure.php +++ b/lib/classes/check/http/cookiesecure.php @@ -56,7 +56,7 @@ class cookiesecure extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/backups.php b/lib/classes/check/performance/backups.php index 549e20d1e7f..a33f491a32b 100644 --- a/lib/classes/check/performance/backups.php +++ b/lib/classes/check/performance/backups.php @@ -50,7 +50,7 @@ class backups extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/cachejs.php b/lib/classes/check/performance/cachejs.php index 091c89afc95..3db0aedb949 100644 --- a/lib/classes/check/performance/cachejs.php +++ b/lib/classes/check/performance/cachejs.php @@ -51,7 +51,7 @@ class cachejs extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/dbschema.php b/lib/classes/check/performance/dbschema.php index cdbb8957938..260c0145e7a 100644 --- a/lib/classes/check/performance/dbschema.php +++ b/lib/classes/check/performance/dbschema.php @@ -50,7 +50,7 @@ class dbschema extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/debugging.php b/lib/classes/check/performance/debugging.php index 14bc10a89b3..ba6ddfd573d 100644 --- a/lib/classes/check/performance/debugging.php +++ b/lib/classes/check/performance/debugging.php @@ -50,7 +50,7 @@ class debugging extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/designermode.php b/lib/classes/check/performance/designermode.php index 2703c11bfff..e2549bc15c1 100644 --- a/lib/classes/check/performance/designermode.php +++ b/lib/classes/check/performance/designermode.php @@ -51,7 +51,7 @@ class designermode extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/performance/stats.php b/lib/classes/check/performance/stats.php index 052b51cc5d4..0a96ac79bf2 100644 --- a/lib/classes/check/performance/stats.php +++ b/lib/classes/check/performance/stats.php @@ -51,7 +51,7 @@ class stats extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/result.php b/lib/classes/check/result.php index 2a0a8dc610d..0710f653885 100644 --- a/lib/classes/check/result.php +++ b/lib/classes/check/result.php @@ -164,8 +164,8 @@ class result implements \renderable { /** * Export this data so it can be used as the context for a mustache template. * - * @param renderer_base $output typically, the renderer that's calling this function - * @return stdClass data context for a mustache template + * @param \renderer_base $output typically, the renderer that's calling this function + * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output) { return array( diff --git a/lib/classes/check/security/crawlers.php b/lib/classes/check/security/crawlers.php index e6b00406049..9fce0c3a284 100644 --- a/lib/classes/check/security/crawlers.php +++ b/lib/classes/check/security/crawlers.php @@ -58,7 +58,7 @@ class crawlers extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/security/emailchangeconfirmation.php b/lib/classes/check/security/emailchangeconfirmation.php index 8c4f1069ac1..5fbbdc36fec 100644 --- a/lib/classes/check/security/emailchangeconfirmation.php +++ b/lib/classes/check/security/emailchangeconfirmation.php @@ -52,7 +52,7 @@ class emailchangeconfirmation extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/security/embed.php b/lib/classes/check/security/embed.php index bfdd767b5a2..aae95418577 100644 --- a/lib/classes/check/security/embed.php +++ b/lib/classes/check/security/embed.php @@ -52,7 +52,7 @@ class embed extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/security/openprofiles.php b/lib/classes/check/security/openprofiles.php index b6d5faafa57..50f55b8b36f 100644 --- a/lib/classes/check/security/openprofiles.php +++ b/lib/classes/check/security/openprofiles.php @@ -52,7 +52,7 @@ class openprofiles extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/security/passwordpolicy.php b/lib/classes/check/security/passwordpolicy.php index cc5d1b1a7f9..9e799906c92 100644 --- a/lib/classes/check/security/passwordpolicy.php +++ b/lib/classes/check/security/passwordpolicy.php @@ -52,7 +52,7 @@ class passwordpolicy extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/security/webcron.php b/lib/classes/check/security/webcron.php index f1c6f177e56..8927a42b07b 100644 --- a/lib/classes/check/security/webcron.php +++ b/lib/classes/check/security/webcron.php @@ -52,7 +52,7 @@ class webcron extends check { /** * A link to a place to action this * - * @return action_link|null + * @return \action_link|null */ public function get_action_link(): ?\action_link { return new \action_link( diff --git a/lib/classes/check/table.php b/lib/classes/check/table.php index 3878b917461..dfa3742caba 100644 --- a/lib/classes/check/table.php +++ b/lib/classes/check/table.php @@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die(); class table implements \renderable { /** - * @var moodle_url $url + * @var \moodle_url $url */ protected $url = ''; diff --git a/lib/classes/content/export/exporters/course_exporter.php b/lib/classes/content/export/exporters/course_exporter.php index 3724150ade8..9373e3d170f 100644 --- a/lib/classes/content/export/exporters/course_exporter.php +++ b/lib/classes/content/export/exporters/course_exporter.php @@ -61,7 +61,7 @@ class course_exporter extends component_exporter { /** * Export the course. * - * @param context[] $exportedcontexts A list of contexts which were successfully exported + * @param \context[] $exportedcontexts A list of contexts which were successfully exported */ public function export_course(array $exportedcontexts): void { // A course export is composed of: @@ -155,7 +155,7 @@ class course_exporter extends component_exporter { /** * Fetch data for the specified course section. * - * @param context[] $exportedcontexts A list of contexts which were successfully exported + * @param \context[] $exportedcontexts A list of contexts which were successfully exported * @param section_info $section The section being exported * @return stdClass */ diff --git a/lib/classes/event/tag_added.php b/lib/classes/event/tag_added.php index 6189d43180f..ca178c14dbd 100644 --- a/lib/classes/event/tag_added.php +++ b/lib/classes/event/tag_added.php @@ -78,7 +78,7 @@ class tag_added extends base { * Creates an event from taginstance object * * @since Moodle 3.1 - * @param stdClass $taginstance + * @param \stdClass $taginstance * @param string $tagname * @param string $tagrawname * @param bool $addsnapshot trust that $taginstance has all necessary fields and add it as a record snapshot diff --git a/lib/classes/event/tag_removed.php b/lib/classes/event/tag_removed.php index faa36109b6d..acd083ed289 100644 --- a/lib/classes/event/tag_removed.php +++ b/lib/classes/event/tag_removed.php @@ -78,7 +78,7 @@ class tag_removed extends base { * Creates an event from taginstance object * * @since Moodle 3.1 - * @param stdClass $taginstance + * @param \stdClass $taginstance * @param string $tagname * @param string $tagrawname * @param bool $addsnapshot trust that $taginstance has all necessary fields and add it as a record snapshot diff --git a/lib/classes/external/exporter.php b/lib/classes/external/exporter.php index 960f4970df4..bfaa6ef0918 100644 --- a/lib/classes/external/exporter.php +++ b/lib/classes/external/exporter.php @@ -389,7 +389,7 @@ abstract class exporter { /** * Get the context structure. * - * @return external_single_structure + * @return array */ final protected static function get_context_structure() { return array( diff --git a/lib/classes/hub/registration.php b/lib/classes/hub/registration.php index 1650fc8b505..7b67c9e5b59 100644 --- a/lib/classes/hub/registration.php +++ b/lib/classes/hub/registration.php @@ -46,7 +46,7 @@ class registration { 'contactemail', 'contactable', 'emailalert', 'emailalertemail', 'commnews', 'commnewsemail', 'contactname', 'name', 'description', 'imageurl', 'contactphone', 'regioncode', 'geolocation', 'street']; - /** @var List of new FORM_FIELDS or siteinfo fields added indexed by the version when they were added. + /** @var array List of new FORM_FIELDS or siteinfo fields added indexed by the version when they were added. * If site was already registered, admin will be promted to confirm new registration data manually. Until registration is manually confirmed, * the scheduled task updating registration will be paused. * Keys of this array are not important as long as they increment, use current date to avoid confusions. @@ -64,13 +64,13 @@ class registration { 2023021700 => ['dbtype', 'coursesnodates', 'sitetheme', 'primaryauthtype'], ]; - /** @var Site privacy: not displayed */ + /** @var string Site privacy: not displayed */ const HUB_SITENOTPUBLISHED = 'notdisplayed'; - /** @var Site privacy: public */ + /** @var string Site privacy: public */ const HUB_SITENAMEPUBLISHED = 'named'; - /** @var Site privacy: public and global */ + /** @var string Site privacy: public and global */ const HUB_SITELINKPUBLISHED = 'linked'; /** @var stdClass cached site registration information */ diff --git a/lib/classes/lock/mysql_lock_factory.php b/lib/classes/lock/mysql_lock_factory.php index 29e3abcfadc..94f9d627f8c 100644 --- a/lib/classes/lock/mysql_lock_factory.php +++ b/lib/classes/lock/mysql_lock_factory.php @@ -49,7 +49,7 @@ class mysql_lock_factory implements lock_factory { /** * Return a unique prefix based on the database name and prefix. * @param string $type - Used to prefix lock keys. - * @return string. + * @return string */ protected function get_unique_db_prefix($type) { global $CFG; diff --git a/lib/classes/log/sql_reader.php b/lib/classes/log/sql_reader.php index 5364604157a..dfefc60e9f0 100644 --- a/lib/classes/log/sql_reader.php +++ b/lib/classes/log/sql_reader.php @@ -93,7 +93,7 @@ interface sql_reader extends reader { /** * Returns an event from the log data. * - * @param stdClass $data Log data + * @param \stdClass $data Log data * @return \core\event\base */ public function get_log_event($data); diff --git a/lib/classes/navigation/output/primary.php b/lib/classes/navigation/output/primary.php index 26aa8bfd723..92bf0274e6d 100644 --- a/lib/classes/navigation/output/primary.php +++ b/lib/classes/navigation/output/primary.php @@ -33,7 +33,7 @@ use custom_menu; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class primary implements renderable, templatable { - /** @var moodle_page $page the moodle page that the navigation belongs to */ + /** @var \moodle_page $page the moodle page that the navigation belongs to */ private $page = null; /** diff --git a/lib/classes/navigation/views/view.php b/lib/classes/navigation/views/view.php index 40e22c341fb..5d679989af7 100644 --- a/lib/classes/navigation/views/view.php +++ b/lib/classes/navigation/views/view.php @@ -30,9 +30,9 @@ use navigation_node_collection; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class view extends navigation_node { - /** @var stdClass $context the current context */ + /** @var \stdClass $context the current context */ protected $context; - /** @var moodle_page $page the moodle page that the navigation belongs to */ + /** @var \moodle_page $page the moodle page that the navigation belongs to */ protected $page; /** @var bool $initialised A switch to see if the navigation node is initialised */ protected $initialised = false; diff --git a/lib/classes/notification.php b/lib/classes/notification.php index 52b1543ba92..8d5d1537b70 100644 --- a/lib/classes/notification.php +++ b/lib/classes/notification.php @@ -145,7 +145,7 @@ class notification { /** * Fetch all of the notifications in the stack and clear the stack. * - * @return array All of the notifications in the stack + * @return \core\output\notification[] All of the notifications in the stack */ public static function fetch() { global $SESSION; diff --git a/lib/classes/output/inplace_editable.php b/lib/classes/output/inplace_editable.php index 27cd1822edf..2488fa085d8 100644 --- a/lib/classes/output/inplace_editable.php +++ b/lib/classes/output/inplace_editable.php @@ -243,7 +243,7 @@ class inplace_editable implements templatable, renderable { /** * Export this data so it can be used as the context for a mustache template (core/inplace_editable). * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output) { @@ -275,7 +275,7 @@ class inplace_editable implements templatable, renderable { /** * Renders this element * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return string */ public function render(\renderer_base $output) { diff --git a/lib/classes/output/language_menu.php b/lib/classes/output/language_menu.php index 846362bbe5e..7f9ba9b6490 100644 --- a/lib/classes/output/language_menu.php +++ b/lib/classes/output/language_menu.php @@ -35,7 +35,7 @@ namespace core\output; */ class language_menu implements \renderable, \templatable { - /** @var moodle_page $page the moodle page that the languague menu belongs to */ + /** @var \moodle_page $page the moodle page that the languague menu belongs to */ protected $page; /** @var string current language code */ @@ -47,7 +47,7 @@ class language_menu implements \renderable, \templatable { /** * Language menu constructor. * - * @param moodle_page $page the moodle page that the languague menu belongs to. + * @param \moodle_page $page the moodle page that the languague menu belongs to. */ public function __construct($page) { $this->page = $page; diff --git a/lib/classes/output/notification.php b/lib/classes/output/notification.php index 023193d94a6..b15ef759761 100644 --- a/lib/classes/output/notification.php +++ b/lib/classes/output/notification.php @@ -156,8 +156,8 @@ class notification implements \renderable, \templatable { /** * Export this data so it can be used as the context for a mustache template. * - * @param renderer_base $output typically, the renderer that's calling this function - * @return stdClass data context for a mustache template + * @param \renderer_base $output typically, the renderer that's calling this function + * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output) { return array( diff --git a/lib/classes/output/sticky_footer.php b/lib/classes/output/sticky_footer.php index e1420156b90..a007c2b060e 100644 --- a/lib/classes/output/sticky_footer.php +++ b/lib/classes/output/sticky_footer.php @@ -114,7 +114,7 @@ class sticky_footer implements named_templatable, renderable { /** * Export this data so it can be used as the context for a mustache template (core/inplace_editable). * - * @param renderer_base $output typically, the renderer that's calling this function + * @param \renderer_base $output typically, the renderer that's calling this function * @return array data context for a mustache template */ public function export_for_template(\renderer_base $output) { diff --git a/lib/classes/output/url_rewriter.php b/lib/classes/output/url_rewriter.php index 435bd55afb9..eacd434ed2f 100644 --- a/lib/classes/output/url_rewriter.php +++ b/lib/classes/output/url_rewriter.php @@ -40,8 +40,8 @@ interface url_rewriter { /** * Rewrite moodle_urls into another form. * - * @param moodle_url $url a url to potentially rewrite - * @return moodle_url Returns a new, or the original, moodle_url; + * @param \moodle_url $url a url to potentially rewrite + * @return \moodle_url Returns a new, or the original, moodle_url; */ public static function url_rewrite(\moodle_url $url); diff --git a/lib/classes/persistent.php b/lib/classes/persistent.php index 36e0fa5a4ca..38ec253430c 100644 --- a/lib/classes/persistent.php +++ b/lib/classes/persistent.php @@ -31,7 +31,7 @@ use stdClass; */ abstract class persistent { - /** The table name. */ + /** @var string The table name. */ const TABLE = null; /** @var array The model data. */ diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index 70691271183..2e1505c69e8 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -106,7 +106,7 @@ class core_plugin_manager { /** * Factory method for this class * - * @return core_plugin_manager the singleton instance + * @return static the singleton instance */ public static function instance() { if (is_null(static::$singletoninstance)) { diff --git a/lib/classes/plugininfo/antivirus.php b/lib/classes/plugininfo/antivirus.php index 398f5fd9dfd..bf55a96f29a 100644 --- a/lib/classes/plugininfo/antivirus.php +++ b/lib/classes/plugininfo/antivirus.php @@ -108,6 +108,7 @@ class antivirus extends base { */ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $antivirus = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/auth.php b/lib/classes/plugininfo/auth.php index f5bfe897e38..1c7a4e71be6 100644 --- a/lib/classes/plugininfo/auth.php +++ b/lib/classes/plugininfo/auth.php @@ -102,6 +102,7 @@ class auth extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $auth = $this; // Also to be used inside settings.php. diff --git a/lib/classes/plugininfo/availability.php b/lib/classes/plugininfo/availability.php index bd5715265d0..fb887ed4277 100644 --- a/lib/classes/plugininfo/availability.php +++ b/lib/classes/plugininfo/availability.php @@ -109,6 +109,7 @@ class availability extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. diff --git a/lib/classes/plugininfo/block.php b/lib/classes/plugininfo/block.php index c8b2e8aa060..e1134882dca 100644 --- a/lib/classes/plugininfo/block.php +++ b/lib/classes/plugininfo/block.php @@ -105,6 +105,7 @@ class block extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $block = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/calendartype.php b/lib/classes/plugininfo/calendartype.php index 9e999c2db04..a552d74a810 100644 --- a/lib/classes/plugininfo/calendartype.php +++ b/lib/classes/plugininfo/calendartype.php @@ -49,6 +49,7 @@ class calendartype extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $qtype = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/contenttype.php b/lib/classes/plugininfo/contenttype.php index 57ff81f1590..a90e8d8de73 100644 --- a/lib/classes/plugininfo/contenttype.php +++ b/lib/classes/plugininfo/contenttype.php @@ -63,6 +63,7 @@ class contenttype extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $contenttype = $this; // Also to be used inside settings.php. @@ -102,7 +103,7 @@ class contenttype extends base { * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class - * @param core_plugin_manager $pluginman the plugin manager calling this method + * @param \core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { diff --git a/lib/classes/plugininfo/customfield.php b/lib/classes/plugininfo/customfield.php index c63279e8457..e635337933c 100644 --- a/lib/classes/plugininfo/customfield.php +++ b/lib/classes/plugininfo/customfield.php @@ -136,6 +136,7 @@ class customfield extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. diff --git a/lib/classes/plugininfo/dataformat.php b/lib/classes/plugininfo/dataformat.php index fbad4fdafa2..bd8133510af 100644 --- a/lib/classes/plugininfo/dataformat.php +++ b/lib/classes/plugininfo/dataformat.php @@ -156,6 +156,7 @@ class dataformat extends base { */ public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $dataformat = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/editor.php b/lib/classes/plugininfo/editor.php index d0547a91fab..d6e75e7a582 100644 --- a/lib/classes/plugininfo/editor.php +++ b/lib/classes/plugininfo/editor.php @@ -97,6 +97,7 @@ class editor extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $editor = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/enrol.php b/lib/classes/plugininfo/enrol.php index 3832bc6c486..38fe93afb27 100644 --- a/lib/classes/plugininfo/enrol.php +++ b/lib/classes/plugininfo/enrol.php @@ -93,6 +93,7 @@ class enrol extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $enrol = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/fileconverter.php b/lib/classes/plugininfo/fileconverter.php index 90af54e64e0..ee5927f9c62 100644 --- a/lib/classes/plugininfo/fileconverter.php +++ b/lib/classes/plugininfo/fileconverter.php @@ -65,6 +65,7 @@ class fileconverter extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/filter.php b/lib/classes/plugininfo/filter.php index 14a8ad85472..53ccfe97a77 100644 --- a/lib/classes/plugininfo/filter.php +++ b/lib/classes/plugininfo/filter.php @@ -113,6 +113,7 @@ class filter extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $filter = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/format.php b/lib/classes/plugininfo/format.php index 5d04e69dcbf..16f698085df 100644 --- a/lib/classes/plugininfo/format.php +++ b/lib/classes/plugininfo/format.php @@ -120,6 +120,7 @@ class format extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/media.php b/lib/classes/plugininfo/media.php index 05f3cc1c5df..161098b0d48 100644 --- a/lib/classes/plugininfo/media.php +++ b/lib/classes/plugininfo/media.php @@ -58,6 +58,7 @@ class media extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php $availability = $this; // Also to be used inside settings.php. @@ -113,6 +114,7 @@ class media extends base { if ($enabled && !in_array($pluginname, $plugins)) { // Enable media plugin. + /** @var \core\plugininfo\media[] $pluginsbytype */ $pluginsbytype = \core_plugin_manager::instance()->get_plugins_of_type('media'); if (!array_key_exists($pluginname, $pluginsbytype)) { // Can not be enabled. diff --git a/lib/classes/plugininfo/message.php b/lib/classes/plugininfo/message.php index d2e348f42f2..743b3adb07f 100644 --- a/lib/classes/plugininfo/message.php +++ b/lib/classes/plugininfo/message.php @@ -75,6 +75,7 @@ class message extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/mlbackend.php b/lib/classes/plugininfo/mlbackend.php index be04eefd432..ff3c9e8fa07 100644 --- a/lib/classes/plugininfo/mlbackend.php +++ b/lib/classes/plugininfo/mlbackend.php @@ -63,6 +63,7 @@ class mlbackend extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/mod.php b/lib/classes/plugininfo/mod.php index fe2d34f247f..a30493f778a 100644 --- a/lib/classes/plugininfo/mod.php +++ b/lib/classes/plugininfo/mod.php @@ -139,6 +139,7 @@ class mod extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $module = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/orphaned.php b/lib/classes/plugininfo/orphaned.php index 09f12d6c681..2c496ae9320 100644 --- a/lib/classes/plugininfo/orphaned.php +++ b/lib/classes/plugininfo/orphaned.php @@ -64,7 +64,7 @@ class orphaned extends base { * @param string $type the name of the plugintype, eg. mod, auth or workshopform * @param string $typerootdir full path to the location of the plugin dir * @param string $typeclass the name of the actually called class - * @param core_plugin_manager $pluginman the plugin manager calling this method + * @param \core_plugin_manager $pluginman the plugin manager calling this method * @return array of plugintype classes, indexed by the plugin name */ public static function get_plugins($type, $typerootdir, $typeclass, $pluginman) { diff --git a/lib/classes/plugininfo/paygw.php b/lib/classes/plugininfo/paygw.php index f3708f1d4c5..7b20395fe62 100644 --- a/lib/classes/plugininfo/paygw.php +++ b/lib/classes/plugininfo/paygw.php @@ -46,6 +46,7 @@ class paygw extends base { public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/qbank.php b/lib/classes/plugininfo/qbank.php index 3d2dff03944..aa2ea8cb244 100644 --- a/lib/classes/plugininfo/qbank.php +++ b/lib/classes/plugininfo/qbank.php @@ -139,6 +139,7 @@ class qbank extends base { public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig): void { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/qtype.php b/lib/classes/plugininfo/qtype.php index 25abdd96df0..f6edc557592 100644 --- a/lib/classes/plugininfo/qtype.php +++ b/lib/classes/plugininfo/qtype.php @@ -135,6 +135,7 @@ class qtype extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $qtype = $this; // Also can be used inside settings.php. diff --git a/lib/classes/plugininfo/webservice.php b/lib/classes/plugininfo/webservice.php index 259a04fa112..772dfa7339d 100644 --- a/lib/classes/plugininfo/webservice.php +++ b/lib/classes/plugininfo/webservice.php @@ -97,6 +97,7 @@ class webservice extends base { public function load_settings(part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. $webservice = $this; // Also can be used inside settings.php. diff --git a/lib/classes/privacy/provider.php b/lib/classes/privacy/provider.php index e49598b8e55..eea881ec933 100644 --- a/lib/classes/privacy/provider.php +++ b/lib/classes/privacy/provider.php @@ -159,7 +159,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { // None of the the data from these tables should be deleted. diff --git a/lib/classes/session/manager.php b/lib/classes/session/manager.php index fb1a627c382..d06d15a95f1 100644 --- a/lib/classes/session/manager.php +++ b/lib/classes/session/manager.php @@ -1175,7 +1175,7 @@ class manager { * @param string $component The string component for the message to show on failure. * @param int $frequency The update frequency in seconds. * @param int $timeout The timeout of each request in seconds. - * @throws coding_exception IF the frequency is longer than the session lifetime. + * @throws \coding_exception IF the frequency is longer than the session lifetime. */ public static function keepalive($identifier = 'sessionerroruser', $component = 'error', $frequency = null, $timeout = 0) { global $CFG, $PAGE; diff --git a/lib/classes/string_manager_standard.php b/lib/classes/string_manager_standard.php index 78f5c940f7b..dbcfdcf131e 100644 --- a/lib/classes/string_manager_standard.php +++ b/lib/classes/string_manager_standard.php @@ -43,7 +43,7 @@ class core_string_manager_standard implements core_string_manager { protected $cache; /** @var int get_string() counter */ protected $countgetstring = 0; - /** @var bool use disk cache */ + /** @var array use disk cache */ protected $translist; /** @var array language aliases to use in the language selector */ protected $transaliases = []; diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php index 35c8751f809..354091a4501 100644 --- a/lib/classes/task/manager.php +++ b/lib/classes/task/manager.php @@ -163,7 +163,7 @@ class manager { * Checks if the task with the same classname, component and customdata is already scheduled * * @param adhoc_task $task - * @return bool + * @return \stdClass|false */ protected static function get_queued_adhoc_task_record($task) { global $DB; diff --git a/lib/classes/task/send_failed_login_notifications_task.php b/lib/classes/task/send_failed_login_notifications_task.php index ee75b2477fd..7ba95478437 100644 --- a/lib/classes/task/send_failed_login_notifications_task.php +++ b/lib/classes/task/send_failed_login_notifications_task.php @@ -72,6 +72,7 @@ class send_failed_login_notifications_task extends scheduled_task { // Get all the IPs with more than notifyloginthreshold failures since lastnotifyfailure // and insert them into the cache_flags temp table. $logmang = get_log_manager(); + /** @var \core\log\sql_internal_table_reader[] $readers */ $readers = $logmang->get_readers('\core\log\sql_internal_table_reader'); $reader = reset($readers); $readername = key($readers); diff --git a/lib/classes/task/task_base.php b/lib/classes/task/task_base.php index 4157b1bbe4e..e0485eeffbf 100644 --- a/lib/classes/task/task_base.php +++ b/lib/classes/task/task_base.php @@ -42,7 +42,7 @@ abstract class task_base { /** @var \core\lock\lock $cronlock - The lock controlling the entire cron process. */ private $cronlock = null; - /** @var $string $component - The component this task belongs to. */ + /** @var string $component - The component this task belongs to. */ private $component = ''; /** @var bool $blocking - Does this task block the entire cron process. */ diff --git a/lib/classes/update/api.php b/lib/classes/update/api.php index 2901da2503d..60467f0ce9c 100644 --- a/lib/classes/update/api.php +++ b/lib/classes/update/api.php @@ -154,7 +154,7 @@ class api { * Object validated by this method is guaranteed to contain all the data * provided by the pluginfo.php version this client works with (self::APIVER). * - * @param stdClass $data + * @param \stdClass $data * @return \core\update\remote_info|bool false if data are not valid, original data otherwise */ public function validate_pluginfo_format($data) { @@ -253,7 +253,7 @@ class api { * * @param string $serviceurl * @param array $params - * @return stdClass|bool + * @return \stdClass|bool */ protected function call_service($serviceurl, array $params=array()) { diff --git a/lib/ddl/mysql_sql_generator.php b/lib/ddl/mysql_sql_generator.php index def4c20ed8b..3c969501f75 100644 --- a/lib/ddl/mysql_sql_generator.php +++ b/lib/ddl/mysql_sql_generator.php @@ -32,6 +32,8 @@ require_once($CFG->libdir.'/ddl/sql_generator.php'); * It extends XMLDBgenerator so everything can be * overridden as needed to generate correct SQL. * + * @property mysqli_native_moodle_database $mdb + * * @package core_ddl * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com * 2001-3001 Eloy Lafuente (stronk7) http://contiento.com diff --git a/lib/ddl/sql_generator.php b/lib/ddl/sql_generator.php index 6215eb1e2c0..d9c64a50cd5 100644 --- a/lib/ddl/sql_generator.php +++ b/lib/ddl/sql_generator.php @@ -163,7 +163,7 @@ abstract class sql_generator { /** @var string The prefix to be used for all the DB objects.*/ public $prefix; - /** @var string List of reserved words (in order to quote them properly).*/ + /** @var array List of reserved words (in order to quote them properly).*/ public $reserved_words; /** @var moodle_database The moodle_database instance.*/ @@ -749,7 +749,7 @@ abstract class sql_generator { * @param string $skip_type_clause The type clause on alter columns, NULL by default. * @param string $skip_default_clause The default clause on alter columns, NULL by default. * @param string $skip_notnull_clause The null/notnull clause on alter columns, NULL by default. - * @return string The field altering SQL statement. + * @return array The field altering SQL statement. */ public function getAlterFieldSQL($xmldb_table, $xmldb_field, $skip_type_clause = NULL, $skip_default_clause = NULL, $skip_notnull_clause = NULL) { @@ -1163,7 +1163,7 @@ abstract class sql_generator { /** * Given one XMLDB Statement, build the needed SQL insert sentences to execute it. * - * @param string $statement SQL statement. + * @param mixed $statement SQL statement. * @return array Array of sentences in the SQL statement. */ function getExecuteInsertSQL($statement) { diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 89c14552325..c67a3c9a2e1 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -1787,7 +1787,7 @@ abstract class moodle_database { /** * Insert new record into database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool $returnid Returns id of inserted record. * @param bool $bulk true means repeated inserts expected * @param bool $customsequence true if 'id' included in $params, disables $returnid @@ -1864,7 +1864,7 @@ abstract class moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool $bulk True means repeated updates expected. * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1879,7 +1879,8 @@ abstract class moodle_database { * specify the record to update * * @param string $table The database table to be checked against. - * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified. + * @param stdClass|array $dataobject An object with contents equal to fieldname=>fieldvalue. + * Must have an entry for 'id' to map to the table specified. * @param bool $bulk True means repeated updates expected. * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1891,7 +1892,7 @@ abstract class moodle_database { * * @param string $table The database table to be checked against. * @param string $newfield the field to set. - * @param string $newvalue the value to set the field to. + * @param mixed $newvalue the value to set the field to. * @param array $conditions optional array $fieldname=>requestedvalue with AND in between * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1906,7 +1907,7 @@ abstract class moodle_database { * * @param string $table The database table to be checked against. * @param string $newfield the field to set. - * @param string $newvalue the value to set the field to. + * @param mixed $newvalue the value to set the field to. * @param string $select A fragment of SQL to be used in a where clause in the SQL call. * @param array $params array of sql parameters * @return bool true @@ -2098,8 +2099,8 @@ abstract class moodle_database { * NOTE: The SQL result is a number and can not be used directly in * SQL condition, please compare it to some number to get a bool!! * - * @param int $int1 First integer in the operation. - * @param int $int2 Second integer in the operation. + * @param string $int1 SQL for the first integer in the operation. + * @param string $int2 SQL for the second integer in the operation. * @return string The piece of SQL code to be used in your statement. */ public function sql_bitand($int1, $int2) { diff --git a/lib/dml/mysqli_native_moodle_database.php b/lib/dml/mysqli_native_moodle_database.php index c42e4c57d7b..61e979ca810 100644 --- a/lib/dml/mysqli_native_moodle_database.php +++ b/lib/dml/mysqli_native_moodle_database.php @@ -1656,7 +1656,7 @@ class mysqli_native_moodle_database extends moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1703,7 +1703,8 @@ class mysqli_native_moodle_database extends moodle_database { * specify the record to update * * @param string $table The database table to be checked against. - * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified. + * @param stdClass|array $dataobject An object with contents equal to fieldname=>fieldvalue. + * Must have an entry for 'id' to map to the table specified. * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. diff --git a/lib/dml/oci_native_moodle_database.php b/lib/dml/oci_native_moodle_database.php index 67099bda2c4..e8f9bf0fe55 100644 --- a/lib/dml/oci_native_moodle_database.php +++ b/lib/dml/oci_native_moodle_database.php @@ -47,7 +47,7 @@ class oci_native_moodle_database extends moodle_database { /** @var Default value initialised in connect method, we need the driver to be present.*/ private $commit_status = null; - /** @var To handle oci driver default verbosity.*/ + /** @var null|int To handle oci driver default verbosity.*/ private $last_error_reporting; /** @var To store unique_session_id. Needed for temp tables unique naming.*/ private $unique_session_id; @@ -1355,7 +1355,7 @@ class oci_native_moodle_database extends moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1405,7 +1405,8 @@ class oci_native_moodle_database extends moodle_database { * specify the record to update * * @param string $table The database table to be checked against. - * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified. + * @param stdClass|array $dataobject An object with contents equal to fieldname=>fieldvalue. + * Must have an entry for 'id' to map to the table specified. * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. diff --git a/lib/dml/pdo_moodle_database.php b/lib/dml/pdo_moodle_database.php index ba20e29de12..4dd37dd400b 100644 --- a/lib/dml/pdo_moodle_database.php +++ b/lib/dml/pdo_moodle_database.php @@ -429,7 +429,7 @@ abstract class pdo_moodle_database extends moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool true means repeated updates expected * @return bool success */ diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index 247f371949c..6bef3283aec 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -50,7 +50,7 @@ class pgsql_native_moodle_database extends moodle_database { /** @var array $dbhcursor keep track of open cursors */ private $dbhcursor = []; - /** @var resource $pgsql database resource */ + /** @var resource|PgSql\Connection|null $pgsql database resource */ protected $pgsql = null; protected $last_error_reporting; // To handle pgsql driver default verbosity @@ -972,7 +972,7 @@ class pgsql_native_moodle_database extends moodle_database { * to get the list of field types which it statically caches only for a single request. * This wraps it in a cache keyed by oid to avoid these DB calls on every request. * - * @param resource $result + * @param resource|PgSql\Result $result * @param int $fieldnumber * @return string Field type */ @@ -1305,7 +1305,7 @@ class pgsql_native_moodle_database extends moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1352,7 +1352,8 @@ class pgsql_native_moodle_database extends moodle_database { * specify the record to update * * @param string $table The database table to be checked against. - * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified. + * @param stdClass|array $dataobject An object with contents equal to fieldname=>fieldvalue. + * Must have an entry for 'id' to map to the table specified. * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. diff --git a/lib/dml/pgsql_native_moodle_recordset.php b/lib/dml/pgsql_native_moodle_recordset.php index 61a770c4604..d6ef4113fd1 100644 --- a/lib/dml/pgsql_native_moodle_recordset.php +++ b/lib/dml/pgsql_native_moodle_recordset.php @@ -35,6 +35,7 @@ require_once(__DIR__.'/moodle_recordset.php'); */ class pgsql_native_moodle_recordset extends moodle_recordset { + /** @var PgSql\Result|resource|null */ protected $result; /** @var current row as array.*/ protected $current; @@ -54,7 +55,7 @@ class pgsql_native_moodle_recordset extends moodle_recordset { * * When using cursors, $result will be null initially. * - * @param resource|null $result A pg_query() result object to create a recordset from. + * @param resource|PgSql\Result|null $result A pg_query() result object to create a recordset from. * @param pgsql_native_moodle_database $db Database object (only required when using cursors) * @param string $cursorname Name of cursor or '' if none */ diff --git a/lib/dml/sqlsrv_native_moodle_database.php b/lib/dml/sqlsrv_native_moodle_database.php index 7ba61da93b2..8b8ebf8c7ef 100644 --- a/lib/dml/sqlsrv_native_moodle_database.php +++ b/lib/dml/sqlsrv_native_moodle_database.php @@ -1189,7 +1189,7 @@ class sqlsrv_native_moodle_database extends moodle_database { /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name - * @param mixed $params data record as object or array + * @param stdClass|array $params data record as object or array * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. @@ -1231,7 +1231,8 @@ class sqlsrv_native_moodle_database extends moodle_database { * specify the record to update * * @param string $table The database table to be checked against. - * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified. + * @param stdClass|array $dataobject An object with contents equal to fieldname=>fieldvalue. + * Must have an entry for 'id' to map to the table specified. * @param bool true means repeated updates expected * @return bool true * @throws dml_exception A DML specific exception is thrown for any errors. diff --git a/lib/dml/tests/fixtures/read_slave_moodle_database.php b/lib/dml/tests/fixtures/read_slave_moodle_database.php index ecf5d572b7c..c62b81c62bc 100644 --- a/lib/dml/tests/fixtures/read_slave_moodle_database.php +++ b/lib/dml/tests/fixtures/read_slave_moodle_database.php @@ -119,7 +119,7 @@ class read_slave_moodle_database extends test_moodle_database { * @param string $sql * @param array $params * @return bool true - * @throws Exception + * @throws \Exception */ public function execute($sql, array $params = null) { list($sql, $params, $type) = $this->fix_sql_params($sql, $params); diff --git a/lib/dml/tests/fixtures/read_slave_moodle_database_mock_mysqli.php b/lib/dml/tests/fixtures/read_slave_moodle_database_mock_mysqli.php index e1b5d0a93b9..14289a1d5d3 100644 --- a/lib/dml/tests/fixtures/read_slave_moodle_database_mock_mysqli.php +++ b/lib/dml/tests/fixtures/read_slave_moodle_database_mock_mysqli.php @@ -58,7 +58,7 @@ class read_slave_moodle_database_mock_mysqli extends \mysqli_native_moodle_datab * @param string|array $sql query * @param array|null $tablenames an array of xmldb table names affected by this request. * @return bool true - * @throws ddl_change_structure_exception A DDL specific exception is thrown for any errors. + * @throws \ddl_change_structure_exception A DDL specific exception is thrown for any errors. */ public function change_database_structure($sql, $tablenames = null) { return true; diff --git a/lib/dml/tests/fixtures/test_moodle_database.php b/lib/dml/tests/fixtures/test_moodle_database.php index 90238958ff6..589aafbe865 100644 --- a/lib/dml/tests/fixtures/test_moodle_database.php +++ b/lib/dml/tests/fixtures/test_moodle_database.php @@ -25,6 +25,8 @@ namespace core; +use Exception; + defined('MOODLE_INTERNAL') || die(); require_once(__DIR__.'/../../moodle_database.php'); @@ -168,7 +170,7 @@ abstract class test_moodle_database extends \moodle_database { /** * Default implementation - * @param StdClass $column metadata + * @param \stdClass $column metadata * @param mixed $value * @return mixed $value */ diff --git a/lib/dml/tests/fixtures/test_sql_generator.php b/lib/dml/tests/fixtures/test_sql_generator.php index edf06f34455..5075ea8bf81 100644 --- a/lib/dml/tests/fixtures/test_sql_generator.php +++ b/lib/dml/tests/fixtures/test_sql_generator.php @@ -29,6 +29,9 @@ defined('MOODLE_INTERNAL') || die(); require_once(__DIR__.'/../../../ddl/sql_generator.php'); +use xmldb_table; +use xmldb_field; + /** * Test SQL code generator class * diff --git a/lib/dml/tests/recordset_walk_test.php b/lib/dml/tests/recordset_walk_test.php index 79a452de7bb..a44a00e1b0a 100644 --- a/lib/dml/tests/recordset_walk_test.php +++ b/lib/dml/tests/recordset_walk_test.php @@ -50,6 +50,7 @@ class recordset_walk_test extends \advanced_testcase { public function test_simple_callback() { global $DB; + /** @var \mod_assign_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); $courses = array(); for ($i = 0; $i < 10; $i++) { @@ -74,6 +75,7 @@ class recordset_walk_test extends \advanced_testcase { public function test_extra_params_callback() { global $DB; + /** @var \mod_assign_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); $courses = array(); for ($i = 0; $i < 10; $i++) { diff --git a/lib/dmllib.php b/lib/dmllib.php index b7527e30605..4ec1c561b90 100644 --- a/lib/dmllib.php +++ b/lib/dmllib.php @@ -63,7 +63,7 @@ define('MUST_EXIST', 2); class dml_exception extends moodle_exception { /** * @param string $errorcode The name of the string from error.php to print. - * @param string $a Extra words and phrases that might be required in the error string. + * @param mixed $a Extra words and phrases that might be required in the error string. * @param string $debuginfo Optional debugging information. */ function __construct($errorcode, $a=NULL, $debuginfo=null) { diff --git a/lib/editor/atto/classes/plugininfo/atto.php b/lib/editor/atto/classes/plugininfo/atto.php index d60e8cc5eb0..11099e479ca 100644 --- a/lib/editor/atto/classes/plugininfo/atto.php +++ b/lib/editor/atto/classes/plugininfo/atto.php @@ -54,6 +54,7 @@ class atto extends base { */ public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { global $CFG, $USER, $DB, $OUTPUT, $PAGE; // In case settings.php wants to refer to them. + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/editor/atto/classes/privacy/provider.php b/lib/editor/atto/classes/privacy/provider.php index 102e760bf95..d64802e5615 100644 --- a/lib/editor/atto/classes/privacy/provider.php +++ b/lib/editor/atto/classes/privacy/provider.php @@ -182,7 +182,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { global $DB; diff --git a/lib/editor/tiny/classes/plugininfo/tiny.php b/lib/editor/tiny/classes/plugininfo/tiny.php index b09f51cf62d..57e6cab1354 100644 --- a/lib/editor/tiny/classes/plugininfo/tiny.php +++ b/lib/editor/tiny/classes/plugininfo/tiny.php @@ -64,6 +64,7 @@ class tiny extends \core\plugininfo\base { // In case settings.php wants to refer to them. global $CFG, $USER, $DB, $OUTPUT, $PAGE; + /** @var \admin_root $ADMIN */ $ADMIN = $adminroot; // May be used in settings.php. $plugininfo = $this; // Also can be used inside settings.php. diff --git a/lib/editor/tiny/plugins/autosave/classes/privacy/provider.php b/lib/editor/tiny/plugins/autosave/classes/privacy/provider.php index 24053d3c2b0..c12987fff5d 100644 --- a/lib/editor/tiny/plugins/autosave/classes/privacy/provider.php +++ b/lib/editor/tiny/plugins/autosave/classes/privacy/provider.php @@ -172,7 +172,7 @@ class provider implements /** * Delete all data for all users in the specified context. * - * @param context $context The specific context to delete data for. + * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { global $DB; diff --git a/lib/enrollib.php b/lib/enrollib.php index 186ade3abda..048ca81023f 100644 --- a/lib/enrollib.php +++ b/lib/enrollib.php @@ -2426,7 +2426,7 @@ abstract class enrol_plugin { /** * Returns list of unenrol links for all enrol instances in course. * - * @param int $instance + * @param stdClass $instance * @return moodle_url or NULL if self unenrolment not supported */ public function get_unenrolself_link($instance) { @@ -2708,7 +2708,7 @@ abstract class enrol_plugin { * for enrolment, name of enrolment plugin etc. * * @param stdClass $instance enrolment instance - * @return array instance info. + * @return stdClass|null instance info. */ public function get_enrol_info(stdClass $instance) { return null; diff --git a/lib/excellib.class.php b/lib/excellib.class.php index 5b2d8193d2a..62bda64bffe 100644 --- a/lib/excellib.class.php +++ b/lib/excellib.class.php @@ -50,7 +50,7 @@ use \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; * @package moodlecore */ class MoodleExcelWorkbook { - /** @var PhpSpreadsheet */ + /** @var \PhpOffice\PhpSpreadsheet\Spreadsheet */ protected $objspreadsheet; /** @var string */ diff --git a/lib/external/classes/util.php b/lib/external/classes/util.php index 63540f56d86..c9240ff0b1c 100644 --- a/lib/external/classes/util.php +++ b/lib/external/classes/util.php @@ -572,9 +572,9 @@ class util { /** * Validate text field format against known FORMAT_XXX * - * @param array $format the format to validate - * @return the validated format - * @throws coding_exception + * @param string $format the format to validate + * @return string the validated format + * @throws \moodle_exception * @since Moodle 2.3 */ public static function validate_format($format) { diff --git a/lib/external/tests/privacy/provider_test.php b/lib/external/tests/privacy/provider_test.php index 4e152740637..282b8dcb051 100644 --- a/lib/external/tests/privacy/provider_test.php +++ b/lib/external/tests/privacy/provider_test.php @@ -442,7 +442,7 @@ class provider_test extends provider_testcase { * Create a service. * * @param array $params The params. - * @return stdClass + * @return \stdClass */ protected function create_service(array $params = []) { global $DB; @@ -467,7 +467,7 @@ class provider_test extends provider_testcase { * Create a service user. * * @param array $params The params. - * @return stdClass + * @return \stdClass */ protected function create_service_user(array $params) { global $DB, $USER; diff --git a/lib/filebrowser/file_info.php b/lib/filebrowser/file_info.php index 2127d1f4f60..4c152dd44da 100644 --- a/lib/filebrowser/file_info.php +++ b/lib/filebrowser/file_info.php @@ -34,7 +34,7 @@ defined('MOODLE_INTERNAL') || die(); */ abstract class file_info { - /** @var stdClass File context */ + /** @var context File context */ protected $context; /** @var file_browser File browser instance */ diff --git a/lib/filebrowser/tests/file_browser_test.php b/lib/filebrowser/tests/file_browser_test.php index 48a768fc058..9480fd6eb83 100644 --- a/lib/filebrowser/tests/file_browser_test.php +++ b/lib/filebrowser/tests/file_browser_test.php @@ -20,6 +20,7 @@ use file_info_context_course; use file_info_context_coursecat; use file_info_context_module; use file_info_stored; +use stdClass; /** * Unit tests for file browser @@ -46,7 +47,7 @@ class file_browser_test extends \advanced_testcase { protected $module1; /** @var stdClass */ protected $module2; - /** @var stdClass */ + /** @var array */ protected $course1filerecord; /** @var stdClass */ protected $teacher; diff --git a/lib/filelib.php b/lib/filelib.php index cbd218576b1..59bf8066fda 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -3112,7 +3112,7 @@ function get_moodle_proxy_url() { * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ class curl { - /** @var bool Caches http request contents */ + /** @var curl_cache|false Caches http request contents */ public $cache = false; /** @var bool Uses proxy, null means automatic based on URL */ public $proxy = null; @@ -3458,7 +3458,7 @@ class curl { /** * Set options for individual curl instance * - * @param resource $curl A curl handle + * @param resource|CurlHandle $curl A curl handle * @param array $options * @return resource The curl handle */ diff --git a/lib/filestorage/file_storage.php b/lib/filestorage/file_storage.php index 9c6e3c33937..48bb7883fd4 100644 --- a/lib/filestorage/file_storage.php +++ b/lib/filestorage/file_storage.php @@ -982,7 +982,7 @@ class file_storage { * @param int $itemid item ID * @param string $filepath file path * @param int $userid the user ID - * @return bool success + * @return stored_file|false success */ public function create_directory($contextid, $component, $filearea, $itemid, $filepath, $userid = null) { global $DB; diff --git a/lib/filestorage/tests/file_storage_test.php b/lib/filestorage/tests/file_storage_test.php index 8bd2ce6a7ca..ef110e9ef52 100644 --- a/lib/filestorage/tests/file_storage_test.php +++ b/lib/filestorage/tests/file_storage_test.php @@ -714,6 +714,7 @@ class file_storage_test extends \advanced_testcase { // Create three aliases linking the same original: $aliasfile1 and $aliasfile2 are // created via create_file_from_reference(), $aliasfile3 created from $aliasfile2. + /** @var \stored_file $originalfile */ $originalfile = null; foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { if (!$areafile->is_directory()) { @@ -1862,6 +1863,7 @@ class file_storage_test extends \advanced_testcase { $repos = repository::get_instances(array('type'=>'user')); $repo = reset($repos); + /** @var \stored_file $file */ $file = null; foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { if (!$areafile->is_directory()) { @@ -1892,6 +1894,7 @@ class file_storage_test extends \advanced_testcase { // Create two aliases linking the same original. + /** @var \stored_file $originalfile */ $originalfile = null; foreach ($fs->get_area_files($user->ctxid, 'user', 'private') as $areafile) { if (!$areafile->is_directory()) { diff --git a/lib/filestorage/tests/file_system_filedir_test.php b/lib/filestorage/tests/file_system_filedir_test.php index e75fdc9fdef..2d7532f405d 100644 --- a/lib/filestorage/tests/file_system_filedir_test.php +++ b/lib/filestorage/tests/file_system_filedir_test.php @@ -92,7 +92,7 @@ class file_system_filedir_test extends \advanced_testcase { * @param string $filename The file name to use in the stored_file * @param array $mockedmethods A list of methods you intend to override * If no methods are specified, only abstract functions are mocked. - * @return stored_file + * @return \stored_file */ protected function get_stored_file($filecontent, $filename = null, $mockedmethods = []) { $contenthash = \file_storage::hash_from_string($filecontent); @@ -120,7 +120,7 @@ class file_system_filedir_test extends \advanced_testcase { * * @param array $mockedmethods A list of methods you intend to override * If no methods are specified, only abstract functions are mocked. - * @return file_system + * @return \file_system */ protected function get_testable_mock($mockedmethods = []) { $fs = $this->getMockBuilder(file_system_filedir::class) diff --git a/lib/filestorage/tests/file_system_test.php b/lib/filestorage/tests/file_system_test.php index 94433665e04..e7f1cad1310 100644 --- a/lib/filestorage/tests/file_system_test.php +++ b/lib/filestorage/tests/file_system_test.php @@ -66,7 +66,7 @@ class file_system_test extends \advanced_testcase { * @param string $filename The file name to use in the stored_file * @param array $mockedmethods A list of methods you intend to override * If no methods are specified, only abstract functions are mocked. - * @return stored_file + * @return \stored_file */ protected function get_stored_file($filecontent, $filename = null, $mockedmethods = []) { $contenthash = \file_storage::hash_from_string($filecontent); diff --git a/lib/filestorage/tests/zip_packer_test.php b/lib/filestorage/tests/zip_packer_test.php index 1060fb0003c..41ea6bfffe7 100644 --- a/lib/filestorage/tests/zip_packer_test.php +++ b/lib/filestorage/tests/zip_packer_test.php @@ -612,7 +612,7 @@ class zip_packer_test extends \advanced_testcase implements file_progress { // The archive contains a single encrypted "hello.txt" file. $archive = __DIR__ . '/fixtures/passwordis1.zip'; - /** @var zip_packer $packer */ + /** @var \zip_packer $packer */ $packer = get_file_packer('application/zip'); $result = $packer->extract_to_pathname($archive, make_temp_directory('zip')); diff --git a/lib/form/classes/filetypes_util.php b/lib/form/classes/filetypes_util.php index 6021ce54061..872279134d1 100644 --- a/lib/form/classes/filetypes_util.php +++ b/lib/form/classes/filetypes_util.php @@ -259,7 +259,7 @@ class filetypes_util { * @param string|array $onlytypes Allow selection from these file types only; for example 'web_image'. * @param bool $allowall Allow to select 'All file types'. Does not apply with onlytypes are set. * @param string|array $current Current values that should be selected. - * @return object + * @return array */ public function data_for_browser($onlytypes=null, $allowall=true, $current=null) { diff --git a/lib/form/modgrade.php b/lib/form/modgrade.php index 479d9c8ed8d..e0107fa3187 100644 --- a/lib/form/modgrade.php +++ b/lib/form/modgrade.php @@ -353,7 +353,7 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group { * * @param string $event Name of event * @param mixed $arg event arguments - * @param moodleform $caller calling object + * @param MoodleQuickForm $caller calling object * @return mixed */ public function onQuickFormEvent($event, $arg, &$caller) { diff --git a/lib/form/passwordunmask.php b/lib/form/passwordunmask.php index 2ac89811846..ae0f9af21d8 100644 --- a/lib/form/passwordunmask.php +++ b/lib/form/passwordunmask.php @@ -87,7 +87,7 @@ class MoodleQuickForm_passwordunmask extends MoodleQuickForm_password { * It turned out that wrapping whitespace can easily be pasted by accident when copying the text from elsewhere. * Such a mistake is very hard to debug as the whitespace is not displayed. * - * @param array $value Submitted value. + * @param string $value Submitted value. * @return string|null Validation error message or null. */ public function validateSubmitValue($value) { diff --git a/lib/form/selectgroups.php b/lib/form/selectgroups.php index 0719bedc617..8c61bb44129 100644 --- a/lib/form/selectgroups.php +++ b/lib/form/selectgroups.php @@ -50,7 +50,7 @@ class MoodleQuickForm_selectgroups extends HTML_QuickForm_element implements tem /** @var array Contains the select optgroups */ var $_optGroups = array(); - /** @var string Default values of the SELECT */ + /** @var array Default values of the SELECT */ var $_values = null; /** @var string html for help button, if empty then no help */ diff --git a/lib/form/tests/dateselector_test.php b/lib/form/tests/dateselector_test.php index d5f751b0a13..b3f1cd1fb44 100644 --- a/lib/form/tests/dateselector_test.php +++ b/lib/form/tests/dateselector_test.php @@ -47,7 +47,7 @@ require_once($CFG->libdir.'/formslib.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class dateselector_test extends \advanced_testcase { - /** @var MoodleQuickForm Keeps reference of dummy form object */ + /** @var \MoodleQuickForm Keeps reference of dummy form object */ private $mform; /** @var array test fixtures */ private $testvals; @@ -184,7 +184,7 @@ class temp_form_date extends moodleform { } /** * Returns form reference - * @return MoodleQuickForm + * @return \MoodleQuickForm */ public function getform() { $mform = $this->_form; diff --git a/lib/form/tests/datetimeselector_test.php b/lib/form/tests/datetimeselector_test.php index 3dc55562d11..e33983e9ed1 100644 --- a/lib/form/tests/datetimeselector_test.php +++ b/lib/form/tests/datetimeselector_test.php @@ -47,7 +47,7 @@ require_once($CFG->libdir.'/formslib.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class datetimeselector_test extends \advanced_testcase { - /** @var MoodleQuickForm Keeps reference of dummy form object */ + /** @var \MoodleQuickForm Keeps reference of dummy form object */ private $mform; /** @var array test fixtures */ private $testvals; @@ -198,7 +198,7 @@ class temp_form_datetime extends moodleform { } /** * Returns form reference. - * @return MoodleQuickForm + * @return \MoodleQuickForm */ public function getform() { $mform = $this->_form; diff --git a/lib/formslib.php b/lib/formslib.php index df47c7b09e0..7dde6309dbc 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -134,7 +134,7 @@ abstract class moodleform { /** @var MoodleQuickForm quickform object definition */ protected $_form; - /** @var array globals workaround */ + /** @var mixed globals workaround */ protected $_customdata; /** @var array submitted form data when using mforms with ajax */ @@ -691,7 +691,7 @@ abstract class moodleform { * * note: $slashed param removed * - * @return object submitted data; NULL if not valid or not submitted or cancelled + * @return stdClass|null submitted data; NULL if not valid or not submitted or cancelled */ function get_data() { $mform =& $this->_form; @@ -714,7 +714,7 @@ abstract class moodleform { * Return submitted data without validation or NULL if there is no submitted data. * note: $slashed param removed * - * @return object submitted data; NULL if not submitted + * @return stdClass|null submitted data; NULL if not submitted */ function get_submitted_data() { $mform =& $this->_form; @@ -2026,7 +2026,7 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { * clean their own data. * * @param string $elementname - * @param int $paramtype defines type of data contained in element. Use the constants PARAM_*. + * @param string $paramtype defines type of data contained in element. Use the constants PARAM_*. * {@link lib/moodlelib.php} for defined parameter types */ function setType($elementname, $paramtype) { @@ -2318,9 +2318,9 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { * use addGroupRule instead of addRule. * * @param string $element Form element name - * @param string $message Message to display for invalid data + * @param string|null $message Message to display for invalid data * @param string $type Rule type, use getRegisteredRules() to get types - * @param string $format (optional)Required for extra rule data + * @param mixed $format (optional)Required for extra rule data * @param string $validation (optional)Where to perform validation: "server", "client" * @param bool $reset Client-side validation: reset the form element to its original value if there is an error? * @param bool $force Force the rule to be applied, even if the target form element does not exist @@ -3299,7 +3299,7 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ * Adds required note, form attributes, validation javascript and form content. * * @global moodle_page $PAGE - * @param moodleform $form Passed by reference + * @param MoodleQuickForm $form Passed by reference */ function finishForm(&$form){ global $PAGE; diff --git a/lib/gdlib.php b/lib/gdlib.php index 9c7e50aae8d..bd69ece35fa 100644 --- a/lib/gdlib.php +++ b/lib/gdlib.php @@ -33,8 +33,8 @@ defined('MOODLE_INTERNAL') || die(); * Otherwise it reimplements the same behaviour. See the PHP manual page for more info. * * @link http://php.net/manual/en/function.imagecopyresampled.php - * @param resource $dst_img the destination GD image resource - * @param resource $src_img the source GD image resource + * @param resource|\GdImage $dst_img the destination GD image resource + * @param resource|\GdImage $src_img the source GD image resource * @param int $dst_x vthe X coordinate of the upper left corner in the destination image * @param int $dst_y the Y coordinate of the upper left corner in the destination image * @param int $src_x the X coordinate of the upper left corner in the source image @@ -312,7 +312,7 @@ function resize_image($filepath, $width, $height, $forcecanvas = false) { /** * Resize an image from an image object. * - * @param resource $original The image to work on. + * @param resource|\GdImage $original The image to work on. * @param array $imageinfo Contains [0] => originalwidth, [1] => originalheight. * @param int|null $width The max width of the resized image, or null to only use the height. * @param int|null $height The max height of the resized image, or null to only use the width. diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index f4a195eb2c6..192bcb513c1 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -2558,7 +2558,7 @@ class grade_category extends grade_object { /** * Overrides grade_object::set_properties() to add special handling for changes to category aggregation types * - * @param stdClass $instance the object to set the properties on + * @param grade_category $instance the object to set the properties on * @param array|stdClass $params Either an associative array or an object containing property name, property value pairs */ public static function set_properties(&$instance, $params) { diff --git a/lib/grade/grade_object.php b/lib/grade/grade_object.php index ab2276a71a9..2378a738f9c 100644 --- a/lib/grade/grade_object.php +++ b/lib/grade/grade_object.php @@ -401,7 +401,7 @@ abstract class grade_object { * Given an associated array or object, cycles through each key/variable * and assigns the value to the corresponding variable in this object. * - * @param stdClass $instance The object to set the properties on + * @param grade_object $instance The object to set the properties on * @param array $params An array of properties to set like $propertyname => $propertyvalue * @return array|stdClass Either an associative array or an object containing property name, property value pairs */ diff --git a/lib/grade/tests/grade_category_test.php b/lib/grade/tests/grade_category_test.php index 3644cc6ff66..f5f2b151486 100644 --- a/lib/grade/tests/grade_category_test.php +++ b/lib/grade/tests/grade_category_test.php @@ -409,7 +409,7 @@ class grade_category_test extends \grade_base_testcase { /** * Test grade category aggregation using the supplied grade objects and aggregation method - * @param grade_category $grade_category the category to be tested + * @param \grade_category $grade_category the category to be tested * @param array $grade_items array of instance of grade_item * @param array $grade_grades array of instances of grade_grade * @param int $aggmethod the aggregation method to apply ie GRADE_AGGREGATE_MEAN @@ -433,9 +433,9 @@ class grade_category_test extends \grade_base_testcase { /** * Verify the value of the category grade item for $this->userid - * @param grade_category $grade_category the category to be tested + * @param \grade_category $grade_category the category to be tested * @param int $correctgrade the expected grade - * @param string msg The message that should be displayed if the correct grade is not found + * @param string $msg The message that should be displayed if the correct grade is not found * @return void */ protected function helper_test_grade_aggregation_result($grade_category, $correctgrade, $msg) { diff --git a/lib/grade/tests/grade_item_test.php b/lib/grade/tests/grade_item_test.php index 8f243a70065..53925e0a159 100644 --- a/lib/grade/tests/grade_item_test.php +++ b/lib/grade/tests/grade_item_test.php @@ -796,7 +796,7 @@ class grade_item_test extends \grade_base_testcase { * * @param int $courseid id of course * @param int $sortorder numeric sorting order of item - * @return stdClass grade item object from the database. + * @return \stdClass grade item object from the database. */ private function insert_fake_grade_item_sortorder($courseid, $sortorder) { global $DB, $CFG; diff --git a/lib/gradelib.php b/lib/gradelib.php index 2ea0cff7dde..936fc135c8b 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -439,7 +439,8 @@ function grade_regrade_final_grades_if_required($course, callable $callback = nu * @param string $itemmodule More specific then $itemtype. For example, 'forum' or 'quiz'. May be NULL for some item types * @param int $iteminstance ID of the item module * @param mixed $userid_or_ids Either a single user ID, an array of user IDs or null. If user ID or IDs are not supplied returns information about grade_item - * @return array Array of grade information objects (scaleid, name, grade and locked status, etc.) indexed with itemnumbers + * @return stdClass Object with keys {items, outcomes, errors}, where 'items' is an array of grade + * information objects (scaleid, name, grade and locked status, etc.) indexed with itemnumbers */ function grade_get_grades($courseid, $itemtype, $itemmodule, $iteminstance, $userid_or_ids=null) { global $CFG; @@ -1147,7 +1148,7 @@ function grade_recover_history_grades($userid, $courseid) { * @param int $userid If specified try to do a quick regrading of the grades of this user only * @param object $updated_item Optional grade item to be marked for regrading. It is required if $userid is set. * @param \core\progress\base $progress If provided, will be used to update progress on this long operation. - * @return bool true if ok, array of errors if problems found. Grade item id => error message + * @return array|true true if ok, array of errors if problems found. Grade item id => error message */ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null, $progress=null) { // This may take a very long time and extra memory. diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 3db5c2bb124..a20699e381e 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -7353,7 +7353,7 @@ function get_string_manager($forcereload=false) { * usually expressed as the filename in the language pack without the * .php on the end but can also be written as mod/forum or grade/export/xls. * If none is specified then moodle.php is used. - * @param string|object|array $a An object, string or number that can be used + * @param string|object|array|int $a An object, string or number that can be used * within translation strings * @param bool $lazyload If set to true a string object is returned instead of * the string itself. The string then isn't calculated until it is first used. @@ -7603,7 +7603,7 @@ class emoticon_manager { * * @see self::encode_stored_config() * @param string $encoded - * @return string|null + * @return array|null */ public function decode_stored_config($encoded) { $decoded = json_decode($encoded); @@ -10083,7 +10083,7 @@ function remove_dir($dir, $contentonly=false) { * Detect if an object or a class contains a given property * will take an actual object or the name of a class * - * @param mix $obj Name of class or real object to test + * @param mixed $obj Name of class or real object to test * @param string $property name of property to find * @return bool true if property exists */ @@ -10735,7 +10735,7 @@ class lang_string { * * @param string $identifier The strings identifier * @param string $component The strings component - * @param stdClass|array $a Any arguments the string requires + * @param stdClass|array|mixed $a Any arguments the string requires * @param string $lang The language to use when processing the string. * @throws coding_exception */ diff --git a/lib/navigationlib.php b/lib/navigationlib.php index f3547a6b940..7cb22e6c5bf 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -93,7 +93,7 @@ class navigation_node implements renderable { public $id = null; /** @var string|int The identifier for the node, used to retrieve the node */ public $key = null; - /** @var string The text to use for the node */ + /** @var string|lang_string The text to use for the node */ public $text = null; /** @var string Short text to use if requested [optional] */ public $shorttext = null; @@ -362,7 +362,7 @@ class navigation_node implements renderable { * Adds a navigation node as a child of this node. * * @param string $text - * @param moodle_url|action_link $action + * @param moodle_url|action_link|string $action * @param int $type * @param string $shorttext * @param string|int $key @@ -1166,7 +1166,7 @@ class navigation_node_collection implements IteratorAggregate, Countable { * * @param string|int $key The key of the node we want to find. * @param int $type One of navigation_node::TYPE_*. - * @return navigation_node|null + * @return navigation_node|false */ public function find($key, $type=null) { if ($type !== null && array_key_exists($type, $this->orderedcollection) && array_key_exists($key, $this->orderedcollection[$type])) { @@ -2362,7 +2362,7 @@ class global_navigation extends navigation_node { /** * Loads a stealth module from unavailable section * @param navigation_node $coursenode - * @param stdClass $modinfo + * @param stdClass|course_modinfo $modinfo * @return navigation_node or null if not accessible */ protected function load_stealth_activity(navigation_node $coursenode, $modinfo) { @@ -4267,7 +4267,7 @@ class flat_navigation extends navigation_node_collection { * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class settings_navigation extends navigation_node { - /** @var stdClass the current context */ + /** @var context the current context */ protected $context; /** @var moodle_page the moodle page that the navigation belongs to */ protected $page; @@ -5749,8 +5749,6 @@ class settings_navigation_ajax extends settings_navigation { /** * Initialise the site admin navigation. - * - * @return array An array of the expandable nodes */ public function initialise() { if ($this->initialised || during_initial_install()) { diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index 2fe139b1124..578acbe8a97 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -3265,7 +3265,7 @@ class initials_bar implements renderable, templatable { public $urlvar; /** - * @var string URL object. + * @var moodle_url URL object. */ public $url; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 77a83e3c26c..2bcc1b27619 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -1806,7 +1806,7 @@ class core_renderer extends renderer_base { /** * Renders a Check API result * - * @param result $result + * @param core\check\result $result * @return string HTML fragment */ protected function render_check_result(core\check\result $result) { @@ -1816,7 +1816,7 @@ class core_renderer extends renderer_base { /** * Renders a Check API result * - * @param result $result + * @param core\check\result $result * @return string HTML fragment */ public function check_result(core\check\result $result) { @@ -2764,7 +2764,7 @@ class core_renderer extends renderer_base { * Theme developers: DO NOT OVERRIDE! Please override function * {@link core_renderer::render_file_picker()} instead. * - * @param array $options associative array with file manager options + * @param stdClass $options file manager options * options are: * maxbytes=>-1, * itemid=>0, @@ -4819,7 +4819,7 @@ EOD; * Renders a bar chart. * * @param \core\chart_bar $chart The chart. - * @return string. + * @return string */ public function render_chart_bar(\core\chart_bar $chart) { return $this->render_chart($chart); @@ -4829,7 +4829,7 @@ EOD; * Renders a line chart. * * @param \core\chart_line $chart The chart. - * @return string. + * @return string */ public function render_chart_line(\core\chart_line $chart) { return $this->render_chart($chart); @@ -4839,7 +4839,7 @@ EOD; * Renders a pie chart. * * @param \core\chart_pie $chart The chart. - * @return string. + * @return string */ public function render_chart_pie(\core\chart_pie $chart) { return $this->render_chart($chart); @@ -4850,7 +4850,7 @@ EOD; * * @param \core\chart_base $chart The chart. * @param bool $withtable Whether to include a data table with the chart. - * @return string. + * @return string */ public function render_chart(\core\chart_base $chart, $withtable = true) { $chartdata = json_encode($chart); diff --git a/lib/pagelib.php b/lib/pagelib.php index fc5b7ab32a6..7ec4659a7a3 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -523,7 +523,7 @@ class moodle_page { /** * Please do not call this method directly, use the ->category syntax. {@link moodle_page::__get()}. - * @return stdClass the category that the page course belongs to. If there isn't one + * @return stdClass|null the category that the page course belongs to. If there isn't one * (that is, if this is the front page course) returns null. */ protected function magic_get_category() { @@ -906,7 +906,7 @@ class moodle_page { /** * Returns the primary navigation object - * @return primary + * @return primaryoutput */ protected function magic_get_primarynavcombined() { if ($this->_primarynavcombined === null) { diff --git a/lib/pear/HTML/QuickForm.php b/lib/pear/HTML/QuickForm.php index fe0fcac580b..6cec481f024 100644 --- a/lib/pear/HTML/QuickForm.php +++ b/lib/pear/HTML/QuickForm.php @@ -722,7 +722,7 @@ class HTML_QuickForm extends HTML_Common { * @param string $name (optional)group name * @param string $groupLabel (optional)group label * @param string $separator (optional)string to separate elements - * @param string $appendName (optional)specify whether the group name should be + * @param bool $appendName (optional)specify whether the group name should be * used in the form element name ex: group[element] * @return object reference to added group of elements * @since 2.8 diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index 33583fafa22..5be1b2604b7 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -952,8 +952,8 @@ class phpunit_util extends testing_util { /** * Get the coverage config for the supplied includelist and excludelist configuration. * - * @param array[] $includelists The list of files/folders in the includelist. - * @param array[] $excludelists The list of files/folders in the excludelist. + * @param string[] $includelists The list of files/folders in the includelist. + * @param string[] $excludelists The list of files/folders in the excludelist. * @return string */ protected static function get_coverage_config(array $includelists, array $excludelists) : string { diff --git a/lib/portfolio/exporter.php b/lib/portfolio/exporter.php index 4aded629ef6..142857a63a8 100644 --- a/lib/portfolio/exporter.php +++ b/lib/portfolio/exporter.php @@ -87,7 +87,7 @@ class portfolio_exporter { private $alreadystolen; /** - * @var stored_file files that the exporter has written to this temp area keep track of + * @var stored_file[] files that the exporter has written to this temp area keep track of * this in case of duplicates within one export see MDL-16390 */ private $newfilehashes; diff --git a/lib/portfolio/formats.php b/lib/portfolio/formats.php index 09c45e72ebe..7d64d67a557 100644 --- a/lib/portfolio/formats.php +++ b/lib/portfolio/formats.php @@ -195,7 +195,7 @@ class portfolio_format_image extends portfolio_format_file { /** * Return all mimetypes that use image.gif (eg all images) * - * @return string + * @return array */ public static function mimetypes() { return file_get_typegroup('type', 'image'); diff --git a/lib/portfolio/plugin.php b/lib/portfolio/plugin.php index 9b25f3e5c45..05a1fd3c43f 100644 --- a/lib/portfolio/plugin.php +++ b/lib/portfolio/plugin.php @@ -59,7 +59,7 @@ abstract class portfolio_plugin_base { /** @var bool whether this instance is visible or not */ protected $visible; - /** @var array admin configured config use {@link set_config} and {@get_config} to access */ + /** @var stdClass admin configured config use {@see set_config} and {@see get_config} to access */ protected $config; /** @var array user config cache. keyed on userid and then on config field => value use {@link get_user_config} and {@link set_user_config} to access. */ @@ -634,7 +634,7 @@ abstract class portfolio_plugin_base { * like name, visible etc. * * @param string $field property name - * @return array|string|int|boolean value of the field + * @return mixed value of the field */ public final function get($field) { // This is a legacy change to the way files are get/set. diff --git a/lib/questionlib.php b/lib/questionlib.php index 65e88c94f7a..19c01ec9f0b 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -936,7 +936,7 @@ function question_load_questions($questionids, $extrafields = '', $join = '') { * * @param object $question the question to tidy. * @param stdClass $category The question_categories record for the given $question. - * @param stdClass[]|null $tagobjects The tags for the given $question. + * @param \core_tag_tag[]|null $tagobjects The tags for the given $question. * @param stdClass[]|null $filtercourses The courses to filter the course tags by. */ function _tidy_question($question, $category, array $tagobjects = null, array $filtercourses = null): void { @@ -1037,7 +1037,7 @@ function get_question_options(&$questions, $loadtags = false, $filtercourses = n * This function also search tag instances that may have a context id that don't match either a course or * question context and fix the data setting the correct context id. * - * @param stdClass[] $tagobjects The tags for the given $question. + * @param \core_tag_tag[] $tagobjects The tags for the given $question. * @param stdClass $categorycontext The question categories context. * @param stdClass[]|null $filtercourses The courses to filter the course tags by. * @return stdClass $sortedtagobjects Sorted tag objects. diff --git a/lib/tablelib.php b/lib/tablelib.php index 5109889a4dd..b128e94c3d2 100644 --- a/lib/tablelib.php +++ b/lib/tablelib.php @@ -151,6 +151,7 @@ class flexible_table { */ var $started_output = false; + /** @var table_dataformat_export_format */ var $exportclass = null; /** @@ -158,16 +159,16 @@ class flexible_table { */ private $prefs = array(); - /** @var $sheettitle */ + /** @var string $sheettitle */ protected $sheettitle; - /** @var $filename */ + /** @var string $filename */ protected $filename; /** @var array $hiddencolumns List of hidden columns. */ protected $hiddencolumns; - /** @var $resetting bool Whether the table preferences is resetting. */ + /** @var bool $resetting Whether the table preferences is resetting. */ protected $resetting; /** @@ -221,8 +222,8 @@ class flexible_table { /** * Get, and optionally set, the export class. - * @param $exportclass (optional) if passed, set the table to use this export class. - * @return table_default_export_format_parent the export class in use (after any set). + * @param table_dataformat_export_format $exportclass (optional) if passed, set the table to use this export class. + * @return table_dataformat_export_format the export class in use (after any set). */ function export_class_instance($exportclass = null) { if (!is_null($exportclass)) { @@ -532,7 +533,6 @@ class flexible_table { /** * Must be called after table is defined. Use methods above first. Cannot * use functions below till after calling this method. - * @return type? */ function setup() { @@ -567,7 +567,7 @@ class flexible_table { /** * Get the order by clause from the session or user preferences, for the table with id $uniqueid. * @param string $uniqueid the identifier for a table. - * @return SQL fragment that can be used in an ORDER BY clause. + * @return string SQL fragment that can be used in an ORDER BY clause. */ public static function get_sort_for_table($uniqueid) { global $SESSION; @@ -590,7 +590,7 @@ class flexible_table { /** * Prepare an an order by clause from the list of columns to be sorted. * @param array $cols column name => SORT_ASC or SORT_DESC - * @return SQL fragment that can be used in an ORDER BY clause. + * @return string SQL fragment that can be used in an ORDER BY clause. */ public static function construct_order_by($cols, $textsortcols=array()) { global $DB; @@ -611,7 +611,7 @@ class flexible_table { } /** - * @return SQL fragment that can be used in an ORDER BY clause. + * @return string SQL fragment that can be used in an ORDER BY clause. */ public function get_sql_sort() { return self::construct_order_by($this->get_sort_columns(), $this->column_textsort); @@ -2246,10 +2246,10 @@ class table_dataformat_export_format extends table_default_export_format_parent /** @var \core\dataformat\base $dataformat */ protected $dataformat; - /** @var $rownum */ + /** @var int $rownum */ protected $rownum = 0; - /** @var $columns */ + /** @var array $columns */ protected $columns; /** diff --git a/lib/testing/generator/block_generator.php b/lib/testing/generator/block_generator.php index 3c4d9a480a5..b2aa8a2ef46 100644 --- a/lib/testing/generator/block_generator.php +++ b/lib/testing/generator/block_generator.php @@ -36,7 +36,7 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class testing_block_generator extends component_generator_base { - /** @var number of created instances */ + /** @var int number of created instances */ protected $instancecount = 0; /** diff --git a/lib/testing/generator/data_generator.php b/lib/testing/generator/data_generator.php index 0c426d1fb50..1dc371438f6 100644 --- a/lib/testing/generator/data_generator.php +++ b/lib/testing/generator/data_generator.php @@ -437,7 +437,7 @@ EOD; * Create course section if does not exist yet * @param array|stdClass $record must contain 'course' and 'section' attributes * @param array|null $options - * @return stdClass + * @return section_info * @throws coding_exception */ public function create_course_section($record = null, array $options = null) { @@ -959,7 +959,7 @@ EOD; * * @param int|string $role either an int role id or a string role shortname. * @param int $userid - * @param int $contextid Defaults to the system context + * @param int|context $contextid Defaults to the system context * @return int new/existing id of the assignment */ public function role_assign($role, $userid, $contextid = false) { @@ -1140,7 +1140,7 @@ EOD; /** * Helper function used to create an LTI tool. * - * @param array $data + * @param stdClass $data * @return stdClass the tool */ public function create_lti_tool($data = array()) { @@ -1393,7 +1393,7 @@ EOD; * * @param \stdClass $course The course to enrol in * @param string $role The role to give within the course - * @param \stdClass $userparams User parameters + * @param \stdClass|array $userparams User parameters * @return \stdClass The created user */ public function create_and_enrol($course, $role = 'student', $userparams = null, $enrol = 'manual', diff --git a/lib/testing/generator/module_generator.php b/lib/testing/generator/module_generator.php index bb4ef49f11b..c260242c348 100644 --- a/lib/testing/generator/module_generator.php +++ b/lib/testing/generator/module_generator.php @@ -38,7 +38,7 @@ defined('MOODLE_INTERNAL') || die(); abstract class testing_module_generator extends component_generator_base { /** - * @var number of created instances + * @var int number of created instances */ protected $instancecount = 0; diff --git a/lib/testing/lib.php b/lib/testing/lib.php index bd4ba1e3a78..5622537a9a2 100644 --- a/lib/testing/lib.php +++ b/lib/testing/lib.php @@ -274,7 +274,7 @@ function testing_update_composer_dependencies(bool $selfupdate = true, bool $upd * paths returned by the shell. * * @param string $path - * @return string. + * @return string */ function testing_cli_fix_directory_separator($path) { global $CFG; diff --git a/lib/tests/accesslib_has_capability_test.php b/lib/tests/accesslib_has_capability_test.php index fda323e038a..8a274c6c6fd 100644 --- a/lib/tests/accesslib_has_capability_test.php +++ b/lib/tests/accesslib_has_capability_test.php @@ -514,7 +514,7 @@ class accesslib_has_capability_test extends \advanced_testcase { * * @dataProvider login_as_provider * @param string $loginascontext - * @param string $testcontexts + * @param array $testcontexts */ public function test_login_as_admin(string $loginascontext, array $testcontexts): void { $this->resetAfterTest(); @@ -538,7 +538,7 @@ class accesslib_has_capability_test extends \advanced_testcase { * * @dataProvider login_as_provider * @param string $loginascontext - * @param string $testcontexts + * @param array $testcontexts */ public function test_login_as_user(string $loginascontext, array $testcontexts): void { $this->resetAfterTest(); diff --git a/lib/tests/core_renderer_template_exploit_test.php b/lib/tests/core_renderer_template_exploit_test.php index c003e52d8b8..771ad6be66a 100644 --- a/lib/tests/core_renderer_template_exploit_test.php +++ b/lib/tests/core_renderer_template_exploit_test.php @@ -388,7 +388,7 @@ class core_renderer_template_exploit_test extends \advanced_testcase { /** * Test that the mustache_helper_collection class correctly strips * @dataProvider get_template_testcases() - * @param string $templates The template to add + * @param array $templates The template to add * @param string $torender The name of the template to render * @param array $context The template context * @param array $helpers Mustache helpers to add diff --git a/lib/tests/event/contentbank_content_created_test.php b/lib/tests/event/contentbank_content_created_test.php index 90b76708045..b83e6c5337e 100644 --- a/lib/tests/event/contentbank_content_created_test.php +++ b/lib/tests/event/contentbank_content_created_test.php @@ -63,6 +63,7 @@ class contentbank_content_created_test extends \advanced_testcase { $sink = $this->redirectEvents(); // Create a content bank content. + /** @var \core_contentbank_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); $contents = $generator->generate_contentbank_data('contenttype_testable', 1); $content = array_shift($contents); diff --git a/lib/tests/event/contentbank_content_deleted_test.php b/lib/tests/event/contentbank_content_deleted_test.php index 4af8cc5d45e..8e9191b131a 100644 --- a/lib/tests/event/contentbank_content_deleted_test.php +++ b/lib/tests/event/contentbank_content_deleted_test.php @@ -61,6 +61,7 @@ class contentbank_content_deleted_test extends \advanced_testcase { $systemcontext = \context_system::instance(); // Create a content bank content. + /** @var \core_contentbank_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); $contents = $generator->generate_contentbank_data('contenttype_testable', 3); $content = array_shift($contents); diff --git a/lib/tests/event/contentbank_content_updated_test.php b/lib/tests/event/contentbank_content_updated_test.php index b1a71a3def6..9292785824b 100644 --- a/lib/tests/event/contentbank_content_updated_test.php +++ b/lib/tests/event/contentbank_content_updated_test.php @@ -60,6 +60,7 @@ class contentbank_content_updated_test extends \advanced_testcase { $systemcontext = \context_system::instance(); // Create a content bank content. + /** @var \core_contentbank_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); $contents = $generator->generate_contentbank_data('contenttype_testable', 1); $content = array_shift($contents); diff --git a/lib/tests/event/contentbank_content_viewed_test.php b/lib/tests/event/contentbank_content_viewed_test.php index a8f0524df44..191cdb45c18 100644 --- a/lib/tests/event/contentbank_content_viewed_test.php +++ b/lib/tests/event/contentbank_content_viewed_test.php @@ -61,6 +61,7 @@ class contentbank_content_viewed_test extends \advanced_testcase { $contenttype = new \contenttype_testable\contenttype(); // Create a content bank content. + /** @var \core_contentbank_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank'); $contents = $generator->generate_contentbank_data('contenttype_testable', 1); $content = array_shift($contents); diff --git a/lib/tests/event/context_locked_test.php b/lib/tests/event/context_locked_test.php index c9ebc235ef0..05a875beea3 100644 --- a/lib/tests/event/context_locked_test.php +++ b/lib/tests/event/context_locked_test.php @@ -58,6 +58,7 @@ class context_locked_test extends \advanced_testcase { $catcontext = \context_coursecat::instance($category->id); $course = self::getDataGenerator()->create_course(['category' => $category->id]); $coursecontext = \context_course::instance($course->id); + /** @var \mod_forum_generator $activitygenerator */ $activitygenerator = self::getDataGenerator()->get_plugin_generator('mod_forum'); $activity = $activitygenerator->create_instance(['course' => $course->id]); $activitycontext = \context_module::instance($activity->cmid); diff --git a/lib/tests/fixtures/testable_plugin_manager.php b/lib/tests/fixtures/testable_plugin_manager.php index 507bd000248..8080157eaa2 100644 --- a/lib/tests/fixtures/testable_plugin_manager.php +++ b/lib/tests/fixtures/testable_plugin_manager.php @@ -113,7 +113,7 @@ class testable_core_plugin_manager extends core_plugin_manager { /** * Adds fake plugin information from record. * - * @param stdClass $record + * @param testable_plugininfo_base $record * @return void */ public function add_fake_plugin_info($record): void { diff --git a/lib/tests/h5p_clean_orphaned_records_task_test.php b/lib/tests/h5p_clean_orphaned_records_task_test.php index 561c2516c94..48992e9b168 100644 --- a/lib/tests/h5p_clean_orphaned_records_task_test.php +++ b/lib/tests/h5p_clean_orphaned_records_task_test.php @@ -49,6 +49,7 @@ class h5p_clean_orphaned_records_task_test extends advanced_testcase { $context = context_module::instance($activity->cmid); // Create a fake deploy H5P file. + /** @var \core_h5p_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_h5p'); $generator->create_export_file($activity->filename, $context->id, 'mod_h5pactivity', 'package'); diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php index b78d3d3deb0..0abcc021c3e 100644 --- a/lib/tests/moodlelib_test.php +++ b/lib/tests/moodlelib_test.php @@ -1315,7 +1315,7 @@ class moodlelib_test extends \advanced_testcase { * * @dataProvider shorten_filenames_provider * - * @param string $filenames + * @param array $filenames * @param int $length * @param string $expected * @param boolean $includehash diff --git a/lib/tests/performance/filtersettingsperformancetester.php b/lib/tests/performance/filtersettingsperformancetester.php index 3cea4e089af..c4f4b0b0d82 100644 --- a/lib/tests/performance/filtersettingsperformancetester.php +++ b/lib/tests/performance/filtersettingsperformancetester.php @@ -53,6 +53,7 @@ $requiredtables = array('context', 'filter_active', 'filter_config'); $realdb = $DB; $testdb = moodle_database::get_driver_instance($CFG->dbtype, $CFG->dblibrary); $testdb->connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $CFG->unittestprefix); +/** @var moodle_database $DB */ $DB = $testdb; $dbman = $testdb->get_manager(); $issetup = 0; diff --git a/lib/tests/questionlib_test.php b/lib/tests/questionlib_test.php index 1b93d96d59d..966ed480e29 100644 --- a/lib/tests/questionlib_test.php +++ b/lib/tests/questionlib_test.php @@ -72,6 +72,7 @@ class questionlib_test extends \advanced_testcase { // Generate an assignment with due date (will generate a course event). $quiz = $this->getDataGenerator()->create_module('quiz', $options); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); switch ($type) { @@ -168,6 +169,7 @@ class questionlib_test extends \advanced_testcase { // Create a couple of categories and questions. $context1 = \context_coursecat::instance($coursecat1->id); $context2 = \context_coursecat::instance($coursecat2->id); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $questioncat1 = $questiongenerator->create_question_category(array('contextid' => $context1->id)); @@ -281,6 +283,7 @@ class questionlib_test extends \advanced_testcase { // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); @@ -303,6 +306,7 @@ class questionlib_test extends \advanced_testcase { // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); @@ -1634,7 +1638,8 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); - $questiongenerator = $generator->get_plugin_generator('core_question'); + /** @var \core_question_generator $questiongenerator */ + $questiongenerator = $generator->get_plugin_generator('core_question'); $category = $generator->create_category(); $context = \context_coursecat::instance($category->id); @@ -1715,6 +1720,7 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); $otheruser = $generator->create_user(); @@ -1761,6 +1767,7 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); $otheruser = $generator->create_user(); @@ -1807,6 +1814,7 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); $otheruser = $generator->create_user(); @@ -1853,6 +1861,7 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); $otheruser = $generator->create_user(); @@ -1909,6 +1918,7 @@ class questionlib_test extends \advanced_testcase { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); $otheruser = $generator->create_user(); @@ -1945,6 +1955,7 @@ class questionlib_test extends \advanced_testcase { public function test_question_has_capability_on_wrong_param_type() { // Create the test data. $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $user = $generator->create_user(); @@ -1976,6 +1987,7 @@ class questionlib_test extends \advanced_testcase { public function test_question_categorylist_parents() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); + /** @var \core_question_generator $questiongenerator */ $questiongenerator = $generator->get_plugin_generator('core_question'); $category = $generator->create_category(); $context = \context_coursecat::instance($category->id); @@ -2121,6 +2133,7 @@ class questionlib_test extends \advanced_testcase { public function test_is_latest() { global $DB; $this->resetAfterTest(); + /** @var \core_question_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat1 = $generator->create_question_category(['name' => 'My category', 'sortorder' => 1, 'idnumber' => 'myqcat']); $question = $generator->create_question('shortanswer', null, ['name' => 'q1', 'category' => $qcat1->id]); @@ -2141,6 +2154,7 @@ class questionlib_test extends \advanced_testcase { $this->resetAfterTest(); // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); @@ -2177,6 +2191,7 @@ class questionlib_test extends \advanced_testcase { $this->resetAfterTest(); // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); @@ -2206,6 +2221,7 @@ class questionlib_test extends \advanced_testcase { $this->resetAfterTest(); // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); @@ -2236,6 +2252,7 @@ class questionlib_test extends \advanced_testcase { $this->resetAfterTest(); // Setup. $context = \context_system::instance(); + /** @var \core_question_generator $qgen */ $qgen = $this->getDataGenerator()->get_plugin_generator('core_question'); $qcat = $qgen->create_question_category(array('contextid' => $context->id)); $q1 = $qgen->create_question('shortanswer', null, array('category' => $qcat->id)); diff --git a/lib/tests/task/logging_test.php b/lib/tests/task/logging_test.php index ee0df88197d..e7ab3dba398 100644 --- a/lib/tests/task/logging_test.php +++ b/lib/tests/task/logging_test.php @@ -475,7 +475,7 @@ class logging_test extends \advanced_testcase { /** * Create and configure a mocked task logger. * - * @return task_logger + * @return logging_test_mocked_logger */ protected function get_mocked_logger() { global $CFG; diff --git a/lib/tests/update_api_test.php b/lib/tests/update_api_test.php index 504041ce42f..0e9cd7b03ae 100644 --- a/lib/tests/update_api_test.php +++ b/lib/tests/update_api_test.php @@ -41,6 +41,7 @@ class update_api_test extends \advanced_testcase { */ public function test_convert_branch_numbering_format() { + /** @var \core\update\testable_api $client */ $client = \core\update\testable_api::client(); $this->assertSame('2.9', $client->convert_branch_numbering_format(29)); diff --git a/lib/weblib.php b/lib/weblib.php index bc40502da56..59cbb8c2706 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -113,7 +113,6 @@ function s($var) { * @see s() * * @param string $var the string potentially containing HTML characters - * @return string */ function p($var) { echo s($var); @@ -1237,7 +1236,7 @@ function format_text_menu() { * @param string $text The text to be formatted. This is raw text originally from user input. * @param int $format Identifier of the text format to be used * [FORMAT_MOODLE, FORMAT_HTML, FORMAT_PLAIN, FORMAT_MARKDOWN] - * @param object/array $options text formatting options + * @param stdClass|array $options text formatting options * @param int $courseiddonotuse deprecated course id, use context option instead * @return string */ @@ -2693,7 +2692,7 @@ function print_recent_activity_note($time, $user, $text, $link, $return=false, $ * outputs a simple list structure in XHTML. * The data is taken from the serialised array stored in the course record. * - * @param course $course A {@link $COURSE} object. + * @param stdClass $course A course object. * @param array $sections * @param course_modinfo $modinfo * @param string $strsection @@ -3564,7 +3563,7 @@ class error_log_progress_trace extends progress_trace { * @package core */ class progress_trace_buffer extends progress_trace { - /** @var progres_trace */ + /** @var progress_trace */ protected $trace; /** @var bool do we pass output out */ protected $passthrough; @@ -3734,7 +3733,7 @@ function print_password_policy() { * which format to output the doclink in. * @param string|object|array $a An object, string or number that can be used * within translation strings - * @return Object An object containing: + * @return stdClass An object containing: * - heading: Any heading that there may be for this help string. * - text: The wiki-formatted help string. * - doclink: An object containing a link, the linktext, and any additional diff --git a/lib/xapi/classes/local/statement.php b/lib/xapi/classes/local/statement.php index af69b5a5587..379152c4a2d 100644 --- a/lib/xapi/classes/local/statement.php +++ b/lib/xapi/classes/local/statement.php @@ -66,7 +66,7 @@ class statement implements JsonSerializable { /** @var string The statement stored. */ protected $stored = null; - /** @var authority The statement authority. */ + /** @var item_actor The statement authority. */ protected $authority = null; /** @var string The statement version. */ @@ -414,7 +414,7 @@ class statement implements JsonSerializable { /** * Return the statement authority if it is defined. * - * @return item|null + * @return item_actor|null */ public function get_authority(): ?item_actor { return $this->authority; diff --git a/lib/xapi/classes/local/statement/item_group.php b/lib/xapi/classes/local/statement/item_group.php index 1773793ceb5..323467ffc7c 100644 --- a/lib/xapi/classes/local/statement/item_group.php +++ b/lib/xapi/classes/local/statement/item_group.php @@ -41,10 +41,10 @@ defined('MOODLE_INTERNAL') || die(); */ class item_group extends item_actor { - /** @var timestamp The statement timestamp. */ + /** @var array */ protected $users; - /** @var timestamp The statement timestamp. */ + /** @var stdClass */ protected $group; /** diff --git a/lib/xapi/tests/local/statement/item_attachment_test.php b/lib/xapi/tests/local/statement/item_attachment_test.php index 581ed8940c0..ee1c51f8cb9 100644 --- a/lib/xapi/tests/local/statement/item_attachment_test.php +++ b/lib/xapi/tests/local/statement/item_attachment_test.php @@ -52,7 +52,7 @@ class item_attachment_test extends advanced_testcase { /** * return a generic data to create a valid item. * - * @return sdtClass the creation data + * @return \stdClass the creation data */ private function get_generic_data(): \stdClass { return (object) [ diff --git a/lib/xapi/tests/local/statement/item_result_test.php b/lib/xapi/tests/local/statement/item_result_test.php index 15a12127500..b6c25b8ae7f 100644 --- a/lib/xapi/tests/local/statement/item_result_test.php +++ b/lib/xapi/tests/local/statement/item_result_test.php @@ -56,7 +56,7 @@ class item_result_test extends advanced_testcase { /** * Return a generic data to create a valid item. * - * @return sdtClass the creation data + * @return \stdClass the creation data */ private function get_generic_data(): \stdClass { return (object) [ diff --git a/lib/xmldb/xmldb_field.php b/lib/xmldb/xmldb_field.php index 433911f70ce..970a50131a8 100644 --- a/lib/xmldb/xmldb_field.php +++ b/lib/xmldb/xmldb_field.php @@ -90,7 +90,7 @@ class xmldb_field extends xmldb_object { * @param bool $notnull XMLDB_NOTNULL or null (or false) * @param bool $sequence XMLDB_SEQUENCE or null (or false) * @param mixed $default meaningful default o null (or false) - * @param xmldb_object $previous + * @param string $previous */ public function __construct($name, $type=null, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { $this->type = null; @@ -112,7 +112,7 @@ class xmldb_field extends xmldb_object { * @param bool $notnull XMLDB_NOTNULL or null (or false) * @param bool $sequence XMLDB_SEQUENCE or null (or false) * @param mixed $default meaningful default o null (or false) - * @param xmldb_object $previous + * @param string $previous */ public function set_attributes($type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { $this->type = $type; @@ -535,7 +535,7 @@ class xmldb_field extends xmldb_object { /** * This function will set all the attributes of the xmldb_field object * based on information passed in one ADOField - * @param string $adofield + * @param database_column_info $adofield * @return void, sets $this->type */ public function setFromADOField($adofield) { diff --git a/lib/xmldb/xmldb_object.php b/lib/xmldb/xmldb_object.php index a104ec0a60a..9a69bd8a365 100644 --- a/lib/xmldb/xmldb_object.php +++ b/lib/xmldb/xmldb_object.php @@ -34,10 +34,10 @@ class xmldb_object { /** @var string comment on object */ protected $comment; - /** @var xmldb_object */ + /** @var string */ protected $previous; - /** @var xmldb_object */ + /** @var string */ protected $next; /** @var string hash of object */ @@ -101,7 +101,7 @@ class xmldb_object { /** * This function will return the name of the previous xmldb_object - * @return xmldb_object + * @return string */ public function getPrevious() { return $this->previous; @@ -109,7 +109,7 @@ class xmldb_object { /** * This function will return the name of the next xmldb_object - * @return xmldb_object + * @return string */ public function getNext() { return $this->next; @@ -141,7 +141,7 @@ class xmldb_object { /** * This function will set the previous of the xmldb_object - * @param xmldb_object $previous + * @param string $previous */ public function setPrevious($previous) { $this->previous = $previous; @@ -149,7 +149,7 @@ class xmldb_object { /** * This function will set the next of the xmldb_object - * @param xmldb_object $next + * @param string $next */ public function setNext($next) { $this->next = $next; diff --git a/lib/xmldb/xmldb_structure.php b/lib/xmldb/xmldb_structure.php index d3a69efa497..3195813f810 100644 --- a/lib/xmldb/xmldb_structure.php +++ b/lib/xmldb/xmldb_structure.php @@ -34,7 +34,7 @@ class xmldb_structure extends xmldb_object { /** @var string */ protected $version; - /** @var array tables */ + /** @var xmldb_table[] tables */ protected $tables; /** diff --git a/mod/assign/classes/output/grading_app.php b/mod/assign/classes/output/grading_app.php index f2107c5d034..2770beee0b1 100644 --- a/mod/assign/classes/output/grading_app.php +++ b/mod/assign/classes/output/grading_app.php @@ -66,7 +66,7 @@ class grading_app implements templatable, renderable { * * @param int $userid The user we will open the grading app too. * @param int $groupid If groups are enabled this is the current course group. - * @param assign $assignment The assignment class + * @param \assign $assignment The assignment class */ public function __construct($userid, $groupid, $assignment) { $this->userid = $userid; diff --git a/mod/assign/classes/output/renderer.php b/mod/assign/classes/output/renderer.php index 38a580be60c..3b1f5cf0214 100644 --- a/mod/assign/classes/output/renderer.php +++ b/mod/assign/classes/output/renderer.php @@ -49,8 +49,8 @@ class renderer extends \plugin_renderer_base { * @param int $userid * @param string $filearea * @param string $component - * @param stdClass $course - * @param stdClass $coursemodule + * @param \stdClass $course + * @param \stdClass $coursemodule * @return string */ public function assign_files(\context $context, $userid, $filearea, $component, $course = null, $coursemodule = null) { diff --git a/mod/assign/classes/privacy/assign_plugin_request_data.php b/mod/assign/classes/privacy/assign_plugin_request_data.php index 4bb664d9cc2..f241e9db090 100644 --- a/mod/assign/classes/privacy/assign_plugin_request_data.php +++ b/mod/assign/classes/privacy/assign_plugin_request_data.php @@ -36,7 +36,7 @@ defined('MOODLE_INTERNAL') || die(); */ class assign_plugin_request_data { - /** @var context The context that we are dealing with. */ + /** @var \context The context that we are dealing with. */ protected $context; /** @var object For submisisons the submission object, for feedback the grade object. */ @@ -57,7 +57,7 @@ class assign_plugin_request_data { /** @var array The grades related to the users added. */ protected $grades = []; - /** @var assign The assign object */ + /** @var \assign The assign object */ protected $assign; /** @@ -91,7 +91,7 @@ class assign_plugin_request_data { /** * Getter for this attribute. * - * @return context Context + * @return \context Context */ public function get_context() { return $this->context; @@ -127,7 +127,7 @@ class assign_plugin_request_data { /** * Getter for this attribute. * - * @return assign The assign object. + * @return \assign The assign object. */ public function get_assign() { return $this->assign; diff --git a/mod/assign/classes/privacy/provider.php b/mod/assign/classes/privacy/provider.php index 469e32f515c..79642382fcc 100644 --- a/mod/assign/classes/privacy/provider.php +++ b/mod/assign/classes/privacy/provider.php @@ -487,7 +487,7 @@ class provider implements * Find out if this user has graded any users. * * @param int $userid The user ID (potential teacher). - * @param assign $assign The assignment object. + * @param \assign $assign The assignment object. * @return array If successful an array of objects with userids that this user graded, otherwise false. */ protected static function get_graded_users(int $userid, \assign $assign) { diff --git a/mod/assign/feedback/comments/tests/privacy/provider_test.php b/mod/assign/feedback/comments/tests/privacy/provider_test.php index 19685771315..3403aa459ea 100644 --- a/mod/assign/feedback/comments/tests/privacy/provider_test.php +++ b/mod/assign/feedback/comments/tests/privacy/provider_test.php @@ -41,8 +41,8 @@ class provider_test extends \mod_assign\privacy\provider_test { * Convenience function for creating feedback data. * * @param object $assign assign object - * @param stdClass $student user object - * @param stdClass $teacher user object + * @param \stdClass $student user object + * @param \stdClass $teacher user object * @param string $submissiontext Submission text * @param string $feedbacktext Feedback text * @return array Feedback plugin object and the grade object. diff --git a/mod/assign/feedback/editpdf/classes/annotation.php b/mod/assign/feedback/editpdf/classes/annotation.php index 11ea11e671c..0bf90282a6d 100644 --- a/mod/assign/feedback/editpdf/classes/annotation.php +++ b/mod/assign/feedback/editpdf/classes/annotation.php @@ -68,7 +68,7 @@ class annotation { /** * Convert a compatible stdClass into an instance of this class. - * @param stdClass $record + * @param \stdClass $record */ public function __construct(\stdClass $record = null) { if ($record) { diff --git a/mod/assign/feedback/editpdf/classes/combined_document.php b/mod/assign/feedback/editpdf/classes/combined_document.php index d757599f191..8ff098107f3 100644 --- a/mod/assign/feedback/editpdf/classes/combined_document.php +++ b/mod/assign/feedback/editpdf/classes/combined_document.php @@ -136,7 +136,7 @@ class combined_document { /** * Set the completed combined file. * - * @param stored_file $file The completed document for all files to be combined. + * @param \stored_file $file The completed document for all files to be combined. * @return $this */ public function set_combined_file($file) { @@ -171,7 +171,7 @@ class combined_document { /** * Set all source files which are to be combined. * - * @param stored_file|conversion[] $files The complete list of all source files to be combined. + * @param \stored_file|conversion[] $files The complete list of all source files to be combined. * @return $this */ public function set_source_files($files) { @@ -183,7 +183,7 @@ class combined_document { /** * Add an additional source file to the end of the existing list. * - * @param stored_file|conversion $file The file to add to the end of the list. + * @param \stored_file|conversion $file The file to add to the end of the list. * @return $this */ public function add_source_file($file) { diff --git a/mod/assign/feedback/editpdf/classes/comments_quick_list.php b/mod/assign/feedback/editpdf/classes/comments_quick_list.php index deb8be23708..c9775de34b2 100644 --- a/mod/assign/feedback/editpdf/classes/comments_quick_list.php +++ b/mod/assign/feedback/editpdf/classes/comments_quick_list.php @@ -52,7 +52,7 @@ class comments_quick_list { * @param string $commenttext * @param int $width * @param string $colour - * @return stdClass - the comment record (with new id set) + * @return \stdClass - the comment record (with new id set) */ public static function add_comment($commenttext, $width, $colour) { global $DB, $USER; diff --git a/mod/assign/feedback/editpdf/classes/document_services.php b/mod/assign/feedback/editpdf/classes/document_services.php index 4986b0a6478..522821f2d2e 100644 --- a/mod/assign/feedback/editpdf/classes/document_services.php +++ b/mod/assign/feedback/editpdf/classes/document_services.php @@ -91,7 +91,7 @@ EOD; * This function will take an int or an assignment instance and * return an assignment instance. It is just for convenience. * @param int|\assign $assignment - * @return assign + * @return \assign */ private static function get_assignment_from_param($assignment) { global $CFG; @@ -642,7 +642,7 @@ EOD; * @param int|\assign $assignment * @param int $userid * @param int $attemptnumber (-1 means latest attempt) - * @return stored_file + * @return \stored_file */ public static function generate_feedback_document($assignment, $userid, $attemptnumber) { global $CFG; @@ -826,7 +826,7 @@ EOD; * @param int|\assign $assignment * @param int $userid * @param int $attemptnumber (-1 means latest attempt) - * @return stored_file + * @return \stored_file */ public static function get_feedback_document($assignment, $userid, $attemptnumber) { diff --git a/mod/assign/feedback/editpdf/classes/page_editor.php b/mod/assign/feedback/editpdf/classes/page_editor.php index ce86fee65f0..401b12c42d8 100644 --- a/mod/assign/feedback/editpdf/classes/page_editor.php +++ b/mod/assign/feedback/editpdf/classes/page_editor.php @@ -315,7 +315,7 @@ class page_editor { * being procssed when using applytoall. * * @param int|\assign $assignment - * @param stdClass $grade + * @param \stdClass $grade * @param int $sourceuserid * @return bool */ diff --git a/mod/assign/feedback/editpdf/classes/pdf.php b/mod/assign/feedback/editpdf/classes/pdf.php index fd187be70be..1eb6453fb81 100644 --- a/mod/assign/feedback/editpdf/classes/pdf.php +++ b/mod/assign/feedback/editpdf/classes/pdf.php @@ -705,7 +705,7 @@ class pdf extends TcpdfFpdi { /** * Check to see if PDF is version 1.4 (or below); if not: use ghostscript to convert it * - * @param stored_file $file + * @param \stored_file $file * @return string path to copy or converted pdf (false == fail) */ public static function ensure_pdf_compatible(\stored_file $file) { diff --git a/mod/assign/feedback/editpdf/tests/feedback_test.php b/mod/assign/feedback/editpdf/tests/feedback_test.php index e18a4b994a2..de03154fd08 100644 --- a/mod/assign/feedback/editpdf/tests/feedback_test.php +++ b/mod/assign/feedback/editpdf/tests/feedback_test.php @@ -50,8 +50,8 @@ class feedback_test extends \advanced_testcase { /** * Helper method to add a file to a submission. * - * @param stdClass $student Student submitting. - * @param assign $assign Assignment being submitted. + * @param \stdClass $student Student submitting. + * @param \assign $assign Assignment being submitted. * @param bool $textfile Use textfile fixture instead of pdf. */ protected function add_file_submission($student, $assign, $textfile = false) { diff --git a/mod/assign/feedback/editpdf/tests/privacy/provider_test.php b/mod/assign/feedback/editpdf/tests/privacy/provider_test.php index 0b6f8b9d4ea..0c29df160e2 100644 --- a/mod/assign/feedback/editpdf/tests/privacy/provider_test.php +++ b/mod/assign/feedback/editpdf/tests/privacy/provider_test.php @@ -53,9 +53,9 @@ class provider_test extends \mod_assign\privacy\provider_test { /** * Convenience function for creating feedback data. * - * @param object $assign assign object - * @param stdClass $student user object - * @param stdClass $teacher user object + * @param object $assign assign object + * @param \stdClass $student user object + * @param \stdClass $teacher user object * @return array Feedback plugin object and the grade object. */ protected function create_feedback($assign, $student, $teacher) { diff --git a/mod/assign/feedback/file/tests/privacy/provider_test.php b/mod/assign/feedback/file/tests/privacy/provider_test.php index 96928247662..5eb848cd689 100644 --- a/mod/assign/feedback/file/tests/privacy/provider_test.php +++ b/mod/assign/feedback/file/tests/privacy/provider_test.php @@ -43,8 +43,8 @@ class provider_test extends \mod_assign\privacy\provider_test { * Convenience function for creating feedback data. * * @param object $assign assign object - * @param stdClass $student user object - * @param stdClass $teacher user object + * @param \stdClass $student user object + * @param \stdClass $teacher user object * @param string $submissiontext Submission text * @param string $feedbacktext Feedback text * @return array Feedback plugin object and the grade object. diff --git a/mod/assign/lib.php b/mod/assign/lib.php index 2c2413416a6..9158e763dcc 100644 --- a/mod/assign/lib.php +++ b/mod/assign/lib.php @@ -200,7 +200,7 @@ function assign_reset_gradebook($courseid, $type='') { /** * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the assignment. - * @param moodleform $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function assign_reset_course_form_definition(&$mform) { $mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign')); diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index 656e85e73e3..ab4086dbfc0 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -9629,8 +9629,8 @@ class assign { * Get the correct submission statement depending on single submisison, team submission or team submission * where all team memebers must submit. * - * @param array $adminconfig - * @param assign $instance + * @param stdClass $adminconfig + * @param stdClass $instance * @param context $context * * @return string diff --git a/mod/assign/submission/file/classes/event/assessable_uploaded.php b/mod/assign/submission/file/classes/event/assessable_uploaded.php index d270822f3ff..0d7eb9f41c8 100644 --- a/mod/assign/submission/file/classes/event/assessable_uploaded.php +++ b/mod/assign/submission/file/classes/event/assessable_uploaded.php @@ -74,7 +74,7 @@ class assessable_uploaded extends \core\event\assessable_uploaded { /** * Sets the legacy event data. * - * @param stdClass $legacyfiles legacy event data. + * @param \stdClass $legacyfiles legacy event data. * @return void */ public function set_legacy_files($legacyfiles) { diff --git a/mod/bigbluebuttonbn/classes/recording.php b/mod/bigbluebuttonbn/classes/recording.php index fd8b7fb729d..34bcb7556c0 100644 --- a/mod/bigbluebuttonbn/classes/recording.php +++ b/mod/bigbluebuttonbn/classes/recording.php @@ -208,7 +208,7 @@ class recording extends persistent { * Get select for given group mode and context * * @param int $groupmode - * @param context $context + * @param \context $context * @param int $courseid * @param int $groupid * @param int $groupingid diff --git a/mod/bigbluebuttonbn/classes/settings.php b/mod/bigbluebuttonbn/classes/settings.php index 038726d2902..95cae03cff5 100644 --- a/mod/bigbluebuttonbn/classes/settings.php +++ b/mod/bigbluebuttonbn/classes/settings.php @@ -43,7 +43,7 @@ use mod_bigbluebuttonbn\local\proxy\bigbluebutton_proxy; */ class settings { - /** @var admin_setting shared value */ + /** @var admin_category shared value */ private $admin; /** @var bool Module is enabled */ diff --git a/mod/bigbluebuttonbn/lib.php b/mod/bigbluebuttonbn/lib.php index a1ca80886e1..c51159e8c4a 100644 --- a/mod/bigbluebuttonbn/lib.php +++ b/mod/bigbluebuttonbn/lib.php @@ -273,9 +273,9 @@ function bigbluebuttonbn_get_extra_capabilities() { /** * Called by course/reset.php * - * @param object $mform + * @param MoodleQuickForm $mform */ -function bigbluebuttonbn_reset_course_form_definition(object &$mform) { +function bigbluebuttonbn_reset_course_form_definition(&$mform) { $items = reset::reset_course_items(); $mform->addElement('header', 'bigbluebuttonbnheader', get_string('modulenameplural', 'bigbluebuttonbn')); foreach ($items as $item => $default) { @@ -388,7 +388,7 @@ function bigbluebuttonbn_get_coursemodule_info($coursemodule) { * Serves the bigbluebuttonbn attachments. Implements needed access control ;-). * * @param stdClass $course course object - * @param cm_info $cm course module object + * @param stdClass $cm course module object * @param context $context context object * @param string $filearea file area * @param array $args extra arguments diff --git a/mod/book/lib.php b/mod/book/lib.php index 34cdd815967..d5a0d964862 100644 --- a/mod/book/lib.php +++ b/mod/book/lib.php @@ -191,7 +191,7 @@ function book_reset_userdata($data) { /** * The elements to add the course reset form. * - * @param moodleform $mform + * @param MoodleQuickForm $mform */ function book_reset_course_form_definition(&$mform) { $mform->addElement('header', 'bookheader', get_string('modulenameplural', 'book')); diff --git a/mod/chat/lib.php b/mod/chat/lib.php index 02c61134f8e..2be31aac5aa 100644 --- a/mod/chat/lib.php +++ b/mod/chat/lib.php @@ -1191,7 +1191,7 @@ function chat_print_overview() { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the chat. * - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function chat_reset_course_form_definition(&$mform) { $mform->addElement('header', 'chatheader', get_string('modulenameplural', 'chat')); diff --git a/mod/choice/lib.php b/mod/choice/lib.php index d91cb22e9a2..b9c3cbbbaad 100644 --- a/mod/choice/lib.php +++ b/mod/choice/lib.php @@ -721,7 +721,7 @@ function choice_get_post_actions() { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the choice. * - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function choice_reset_course_form_definition(&$mform) { $mform->addElement('header', 'choiceheader', get_string('modulenameplural', 'choice')); diff --git a/mod/data/lib.php b/mod/data/lib.php index 3aba50ad4fc..6dba4b82548 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -2726,7 +2726,7 @@ function data_preset_path($course, $userid, $shortname) { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the data. * - * @param $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function data_reset_course_form_definition(&$mform) { $mform->addElement('header', 'dataheader', get_string('modulenameplural', 'data')); diff --git a/mod/feedback/item/multichoicerated/lib.php b/mod/feedback/item/multichoicerated/lib.php index ad347c8252d..54e62ccafc8 100644 --- a/mod/feedback/item/multichoicerated/lib.php +++ b/mod/feedback/item/multichoicerated/lib.php @@ -73,6 +73,11 @@ class feedback_item_multichoicerated extends feedback_item_base { $this->item_form = new feedback_multichoicerated_form('edit_item.php', $customdata); } + /** + * Saves item + * + * @return stdClass + */ public function save_item() { global $DB; diff --git a/mod/feedback/lib.php b/mod/feedback/lib.php index 3c7c9f0a3c9..86b9065c969 100644 --- a/mod/feedback/lib.php +++ b/mod/feedback/lib.php @@ -677,7 +677,7 @@ function feedback_reset_userdata($data) { * * @global object * @uses FEEDBACK_RESETFORM_RESET - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function feedback_reset_course_form_definition(&$mform) { global $COURSE, $DB; @@ -1181,7 +1181,7 @@ function feedback_get_receivemail_users($cmid, $groups = false) { * @param int $courseid * @param string $name the name of template shown in the templatelist * @param int $ispublic 0:privat 1:public - * @return int the new templateid + * @return stdClass the new template */ function feedback_create_template($courseid, $name, $ispublic = 0) { global $DB; @@ -1966,7 +1966,7 @@ function feedback_delete_completedtmp() { * * @global object * @param int $feedbackid - * @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item + * @return int|false false if there already is a pagebreak on last position or the id of the pagebreak-item */ function feedback_create_pagebreak($feedbackid) { global $DB; diff --git a/mod/feedback/tests/generator/lib.php b/mod/feedback/tests/generator/lib.php index 1eedc41fb0f..9b39bc191b4 100644 --- a/mod/feedback/tests/generator/lib.php +++ b/mod/feedback/tests/generator/lib.php @@ -179,7 +179,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_info($feedback, $record = array()) { global $DB, $CFG; @@ -195,7 +195,7 @@ class mod_feedback_generator extends testing_module_generator { 'template' => 0, 'name' => 'Feedback question item ' . $position, 'label' => 'Feedback label ' . $position, - 'presentation' => $itemobj::MODE_COURSE, + 'presentation' => \feedback_item_info::MODE_COURSE, 'typ' => 'info', 'hasvalue' => 0, 'position' => $position, @@ -214,7 +214,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_label($feedback, $record = array()) { global $DB, $CFG; @@ -257,7 +257,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_multichoice($feedback, $record = array()) { global $DB, $CFG; @@ -304,7 +304,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_multichoicerated($feedback, $record = array()) { global $DB, $CFG; @@ -353,7 +353,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_numeric($feedback, $record = array()) { global $DB, $CFG; @@ -398,7 +398,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_textarea($feedback, $record = array()) { global $DB, $CFG; @@ -437,7 +437,7 @@ class mod_feedback_generator extends testing_module_generator { * * @param object $feedback feedback record * @param array $record (optional) to override default values - * @return int + * @return stdClass */ public function create_item_textfield($feedback, $record = array()) { global $DB, $CFG; @@ -475,7 +475,7 @@ class mod_feedback_generator extends testing_module_generator { * Create pagebreak. * * @param object $feedback feedback record - * @return mixed false if there already is a pagebreak on last position or the id of the pagebreak-item + * @return int|false false if there already is a pagebreak on last position or the id of the pagebreak-item */ public function create_item_pagebreak($feedback) { global $CFG; diff --git a/mod/forum/classes/output/forum_post.php b/mod/forum/classes/output/forum_post.php index b3862879934..52c51bc8d8e 100644 --- a/mod/forum/classes/output/forum_post.php +++ b/mod/forum/classes/output/forum_post.php @@ -544,7 +544,7 @@ class forum_post implements \renderable, \templatable { * The date of the post, formatted according to the postto user's * preferences. * - * @return string. + * @return string */ public function get_postdate() { global $CFG; diff --git a/mod/forum/lib.php b/mod/forum/lib.php index aa2f40b3db5..d02c887f0d5 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1336,7 +1336,7 @@ function forum_get_user_involved_discussions($forumid, $userid) { * @global object * @param int $forumid * @param int $userid - * @return array of counts or false + * @return stdClass|false collection of counts or false */ function forum_count_user_posts($forumid, $userid) { global $CFG, $DB; @@ -5360,7 +5360,7 @@ function forum_reset_userdata($data) { /** * Called by course/reset.php * - * @param $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function forum_reset_course_form_definition(&$mform) { $mform->addElement('header', 'forumheader', get_string('modulenameplural', 'forum')); diff --git a/mod/glossary/lib.php b/mod/glossary/lib.php index 003c1eccd17..c8bcafaefa5 100644 --- a/mod/glossary/lib.php +++ b/mod/glossary/lib.php @@ -1009,8 +1009,8 @@ function glossary_get_entries($glossaryid, $entrylist, $pivot = "") { /** * @global object * @global object - * @param object $concept - * @param string $courseid + * @param string $concept + * @param int $courseid * @return array */ function glossary_get_entries_search($concept, $courseid) { @@ -2791,7 +2791,7 @@ function glossary_get_post_actions() { /** * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the glossary. - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function glossary_reset_course_form_definition(&$mform) { $mform->addElement('header', 'glossaryheader', get_string('modulenameplural', 'glossary')); diff --git a/mod/h5pactivity/lib.php b/mod/h5pactivity/lib.php index 84dcaa2781c..114abcdbf6b 100644 --- a/mod/h5pactivity/lib.php +++ b/mod/h5pactivity/lib.php @@ -242,7 +242,7 @@ function h5pactivity_rescale_activity_grades(stdClass $course, stdClass $cm, flo * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the H5P activity. * - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function h5pactivity_reset_course_form_definition(&$mform): void { $mform->addElement('header', 'h5pactivityheader', get_string('modulenameplural', 'mod_h5pactivity')); diff --git a/mod/imscp/lib.php b/mod/imscp/lib.php index ad8b4efa260..17a2ad94b80 100644 --- a/mod/imscp/lib.php +++ b/mod/imscp/lib.php @@ -248,7 +248,7 @@ function imscp_get_file_areas($course, $cm, $context) { * * @package mod_imscp * @category files - * @param stdClass $browser file browser + * @param file_browser $browser file browser * @param stdClass $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object diff --git a/mod/lesson/lib.php b/mod/lesson/lib.php index 9e48012c159..f651cdd09d4 100644 --- a/mod/lesson/lib.php +++ b/mod/lesson/lib.php @@ -832,7 +832,7 @@ function lesson_process_post_save(&$lesson) { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the lesson. * - * @param $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function lesson_reset_course_form_definition(&$mform) { $mform->addElement('header', 'lessonheader', get_string('modulenameplural', 'lesson')); @@ -1181,7 +1181,7 @@ function lesson_get_file_areas() { * @package mod_lesson * @category files * @global stdClass $CFG - * @param file_browse $browser file browser instance + * @param file_browser $browser file browser instance * @param array $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object diff --git a/mod/lesson/tests/generator/lib.php b/mod/lesson/tests/generator/lib.php index 53fcfa6a251..e41d07846e0 100644 --- a/mod/lesson/tests/generator/lib.php +++ b/mod/lesson/tests/generator/lib.php @@ -120,7 +120,7 @@ class mod_lesson_generator extends testing_module_generator { * Create True/false question pages. * @param object $lesson * @param array $record - * @return int + * @return \stdClass */ public function create_question_truefalse($lesson, $record = array()) { global $DB, $CFG; diff --git a/mod/lti/classes/local/ltiservice/resource_base.php b/mod/lti/classes/local/ltiservice/resource_base.php index 19fefa51081..f4bcb0823df 100644 --- a/mod/lti/classes/local/ltiservice/resource_base.php +++ b/mod/lti/classes/local/ltiservice/resource_base.php @@ -135,7 +135,7 @@ abstract class resource_base { /** * Get the resource's service. * - * @return mixed + * @return service_base */ public function get_service() { diff --git a/mod/page/lib.php b/mod/page/lib.php index bda4a4fd616..2aad2eceb1a 100644 --- a/mod/page/lib.php +++ b/mod/page/lib.php @@ -259,7 +259,7 @@ function page_get_file_areas($course, $cm, $context) { * * @package mod_page * @category files - * @param stdClass $browser file browser instance + * @param file_browser $browser file browser instance * @param stdClass $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object diff --git a/mod/quiz/lib.php b/mod/quiz/lib.php index f68a84b821e..0f89d9403bc 100644 --- a/mod/quiz/lib.php +++ b/mod/quiz/lib.php @@ -417,7 +417,7 @@ function quiz_delete_all_attempts($quiz) { /** * Delete all the attempts belonging to a user in a particular quiz. * - * @param stdClass $quiz The quiz object. + * @param \mod_quiz\quiz_settings $quiz The quiz object. * @param stdClass $user The user object. */ function quiz_delete_user_attempts($quiz, $user) { @@ -1492,7 +1492,7 @@ function quiz_questions_in_use($questionids) { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the quiz. * - * @param $mform the course reset form that is being built. + * @param MoodleQuickForm $mform the course reset form that is being built. */ function quiz_reset_course_form_definition($mform) { $mform->addElement('header', 'quizheader', get_string('modulenameplural', 'quiz')); diff --git a/mod/quiz/report/statistics/report.php b/mod/quiz/report/statistics/report.php index c99971496ae..d116ea32a44 100644 --- a/mod/quiz/report/statistics/report.php +++ b/mod/quiz/report/statistics/report.php @@ -762,7 +762,8 @@ class quiz_statistics_report extends report_base { * * @param int $lastcachetime the time the stats were last cached. * @param int $quizid the quiz id. - * @param array $groupstudentsjoins (joins, wheres, params) for students in the group or empty array if groups not used. + * @param \core\dml\sql_join $groupstudentsjoins (joins, wheres, params) for students in the group + * or empty array if groups not used. * @param string $whichattempts which attempts to use, represented internally as one of the constants as used in * $quiz->grademethod ie. * QUIZ_GRADEAVERAGE, QUIZ_GRADEHIGHEST, QUIZ_ATTEMPTLAST or QUIZ_ATTEMPTFIRST diff --git a/mod/resource/lib.php b/mod/resource/lib.php index 563d2422bc5..eee7f1e6db2 100644 --- a/mod/resource/lib.php +++ b/mod/resource/lib.php @@ -299,7 +299,7 @@ function resource_get_file_areas($course, $cm, $context) { * * @package mod_resource * @category files - * @param stdClass $browser file browser instance + * @param file_browser $browser file browser instance * @param stdClass $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object diff --git a/mod/scorm/lib.php b/mod/scorm/lib.php index 43457071a11..ddd4864753a 100644 --- a/mod/scorm/lib.php +++ b/mod/scorm/lib.php @@ -342,11 +342,10 @@ function scorm_delete_instance($id) { * user has done with a given particular instance of this module * Used for user activity reports. * - * @global stdClass - * @param int $course Course id - * @param int $user User id - * @param int $mod - * @param int $scorm The scorm id + * @param stdClass $course Course object + * @param stdClass $user User + * @param stdClass $mod + * @param stdClass $scorm The scorm * @return mixed */ function scorm_user_outline($course, $user, $mod, $scorm) { @@ -772,7 +771,7 @@ function scorm_option2text($scorm) { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the scorm. * - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function scorm_reset_course_form_definition(&$mform) { $mform->addElement('header', 'scormheader', get_string('modulenameplural', 'scorm')); diff --git a/mod/survey/lib.php b/mod/survey/lib.php index 3249aec2a85..e3cc8f9b004 100644 --- a/mod/survey/lib.php +++ b/mod/survey/lib.php @@ -395,7 +395,7 @@ function survey_get_user_answers($surveyid, $questionid, $groupid, $sort="sa.ans * @param int $surveyid * @param int $questionid * @param int $userid - * @return array + * @return stdClass|false */ function survey_get_user_answer($surveyid, $questionid, $userid) { global $DB; @@ -722,7 +722,7 @@ function survey_get_post_actions() { * Implementation of the function for printing the form elements that control * whether the course reset functionality affects the survey. * - * @param object $mform form passed by reference + * @param MoodleQuickForm $mform form passed by reference */ function survey_reset_course_form_definition(&$mform) { $mform->addElement('header', 'surveyheader', get_string('modulenameplural', 'survey')); diff --git a/mod/url/classes/search/activity.php b/mod/url/classes/search/activity.php index c5baae213b5..3bcb01aad83 100644 --- a/mod/url/classes/search/activity.php +++ b/mod/url/classes/search/activity.php @@ -49,9 +49,9 @@ class activity extends \core_search\base_activity { * * Overwrites base_activity to add the provided URL as description. * - * @param stdClass $record + * @param \stdClass $record * @param array $options - * @return \core_search\document + * @return \core_search\document|false */ public function get_document($record, $options = array()) { $doc = parent::get_document($record, $options); diff --git a/mod/url/locallib.php b/mod/url/locallib.php index 03465793756..b3998efae91 100644 --- a/mod/url/locallib.php +++ b/mod/url/locallib.php @@ -75,7 +75,7 @@ function url_fix_submitted_url($url) { * * This function does not include any XSS protection. * - * @param string $url + * @param stdClass $url * @param object $cm * @param object $course * @param object $config diff --git a/mod/wiki/locallib.php b/mod/wiki/locallib.php index b4e123067fa..b06909e896e 100644 --- a/mod/wiki/locallib.php +++ b/mod/wiki/locallib.php @@ -509,6 +509,7 @@ function wiki_get_missing_or_empty_pages($swid) { * Get pages list in wiki * @param int $swid sub wiki id * @param string $sort How to sort the pages. By default, title ASC. + * @return stdClass[] */ function wiki_get_page_list($swid, $sort = 'title ASC') { global $DB; @@ -648,7 +649,7 @@ function wiki_parse_content($markup, $pagecontent, $options = array()) { * !!!!!! IMPORTANT !!!!!! * It is critical that you call format_string on the content before it is used. * - * @param string|page_wiki $link name of a page + * @param string|stdClass $link name of a page or page object. * @param array $options * @return array Array('content' => string, 'url' => string, 'new' => bool, 'link_info' => array) * diff --git a/mod/workshop/classes/privacy/provider.php b/mod/workshop/classes/privacy/provider.php index 828461d80a3..5bd88708192 100644 --- a/mod/workshop/classes/privacy/provider.php +++ b/mod/workshop/classes/privacy/provider.php @@ -293,7 +293,7 @@ class provider implements * his/her exported personal data. For example, we need to know what were the instructions for submissions or what * was the phase of the workshop when it was exported. * - * @param context $context Workshop module content. + * @param \context $context Workshop module content. * @param stdClass $user User for which we are exporting data. * @param stdClass $data Base data about the workshop instance to append to. * @param array $subcontext Subcontext path items to eventually write files into. diff --git a/privacy/classes/local/metadata/collection.php b/privacy/classes/local/metadata/collection.php index 0e7668ede3f..805f1265b80 100644 --- a/privacy/classes/local/metadata/collection.php +++ b/privacy/classes/local/metadata/collection.php @@ -44,7 +44,7 @@ class collection { protected $component; /** - * @var array The collection of metadata items. + * @var type[] The collection of metadata items. */ protected $collection = []; @@ -201,7 +201,7 @@ class collection { /** * The content of this collection. * - * @return types\type[] + * @return type[] */ public function get_collection() { return $this->collection; diff --git a/privacy/classes/local/request/writer.php b/privacy/classes/local/request/writer.php index ff04f3d495d..80d77ca281f 100644 --- a/privacy/classes/local/request/writer.php +++ b/privacy/classes/local/request/writer.php @@ -75,7 +75,7 @@ class writer { */ public static function setup_real_writer_instance() { if (!PHPUNIT_TEST) { - throw new coding_exception('setup_real_writer_instance() is only for use with PHPUnit tests.'); + throw new \coding_exception('setup_real_writer_instance() is only for use with PHPUnit tests.'); } $instance = static::instance(); diff --git a/privacy/classes/tests/request/content_writer.php b/privacy/classes/tests/request/content_writer.php index 3a8c64e7e30..3ad7c498869 100644 --- a/privacy/classes/tests/request/content_writer.php +++ b/privacy/classes/tests/request/content_writer.php @@ -231,7 +231,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * Get all data within the subcontext. * * @param array $subcontext The location within the current context that this data belongs. - * @return array The metadata as a series of keys to value + descrition objects. + * @return \stdClass|array The metadata as a series of keys to value + description objects. */ public function get_data(array $subcontext = []) { return $this->fetch_data_root($this->data, $subcontext); @@ -263,7 +263,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * Get all metadata within the subcontext. * * @param array $subcontext The location within the current context that this data belongs. - * @return array The metadata as a series of keys to value + descrition objects. + * @return \stdClass|array The metadata as a series of keys to value + description objects. */ public function get_all_metadata(array $subcontext = []) { return $this->fetch_data_root($this->metadata, $subcontext); @@ -275,7 +275,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * @param array $subcontext The location within the current context that this data belongs. * @param string $key The metadata to be fetched within the context + subcontext. * @param boolean $valueonly Whether to fetch only the value, rather than the value + description. - * @return array The metadata as a series of keys to value + descrition objects. + * @return \stdClass|array|null The metadata as a series of keys to value + description objects. */ public function get_metadata(array $subcontext, $key, $valueonly = true) { $keys = $this->get_all_metadata($subcontext); @@ -312,7 +312,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * * @param array $subcontext The location within the current context that this data belongs. * @param string $filename The name of the intended filename. - * @return array The metadata as a series of keys to value + descrition objects. + * @return \stdClass|array The metadata as a series of keys to value + description objects. */ public function get_related_data(array $subcontext = [], $filename = null) { $current = $this->fetch_data_root($this->relateddata, $subcontext); @@ -510,7 +510,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * @param \stdClass $base The base to use - e.g. $this->data * @param array $subcontext The subcontext to fetch * @param int $temporarycontextid A temporary context ID to use for the fetch. - * @return array + * @return \stdClass|array */ protected function fetch_root($base, $subcontext, $temporarycontextid = null) { $contextid = !empty($temporarycontextid) ? $temporarycontextid : $this->context->id; @@ -540,7 +540,7 @@ class content_writer implements \core_privacy\local\request\content_writer { * * @param \stdClass $base The base to use - e.g. $this->data * @param array $subcontext The subcontext to fetch - * @return array + * @return \stdClass|array */ protected function fetch_data_root($base, $subcontext) { $root = $this->fetch_root($base, $subcontext); diff --git a/question/bank/customfields/classes/customfield/question_handler.php b/question/bank/customfields/classes/customfield/question_handler.php index 14a5ab2142c..71a907a77f7 100644 --- a/question/bank/customfields/classes/customfield/question_handler.php +++ b/question/bank/customfields/classes/customfield/question_handler.php @@ -125,7 +125,7 @@ class question_handler extends \core_customfield\handler { * Used primarily in showing or not the field in the question bank table. * * @param field_controller $field The field trying to be viewed. - * @param context $context The context the field is being displayed in. + * @param \context $context The context the field is being displayed in. * @return bool true if the current can edit custom fields, false otherwise. */ public function can_view_type(field_controller $field, \context $context) : bool { diff --git a/question/classes/engine/variants/least_used_strategy.php b/question/classes/engine/variants/least_used_strategy.php index 346174c62ae..779f88c7709 100644 --- a/question/classes/engine/variants/least_used_strategy.php +++ b/question/classes/engine/variants/least_used_strategy.php @@ -50,8 +50,8 @@ class least_used_strategy implements \question_variant_selection_strategy { /** * Constructor. - * @param question_usage_by_activity $quba the question usage we will be picking variants for. - * @param qubaid_condition $qubaids ids of the usages to consider when counting previous uses of each variant. + * @param \question_usage_by_activity $quba the question usage we will be picking variants for. + * @param \qubaid_condition $qubaids ids of the usages to consider when counting previous uses of each variant. */ public function __construct(\question_usage_by_activity $quba, \qubaid_condition $qubaids) { $questionidtoseed = array(); diff --git a/rating/classes/phpunit/privacy_helper.php b/rating/classes/phpunit/privacy_helper.php index 329d5054e34..b9f14024405 100644 --- a/rating/classes/phpunit/privacy_helper.php +++ b/rating/classes/phpunit/privacy_helper.php @@ -42,7 +42,7 @@ trait privacy_helper { * * @param \context $context The context being stored. * @param array $subcontext The subcontext path to check. - * @return array + * @return \stdClass|array */ protected function get_ratings_on_subcontext(\context $context, array $subcontext) { $writer = \core_privacy\local\request\writer::with_context($context); diff --git a/rating/lib.php b/rating/lib.php index a7339d25d15..d20191d7ff8 100644 --- a/rating/lib.php +++ b/rating/lib.php @@ -46,7 +46,7 @@ define ('RATING_DEFAULT_SCALE', 5); class rating implements renderable { /** - * @var stdClass The context in which this rating exists + * @var context The context in which this rating exists */ public $context; diff --git a/repository/lib.php b/repository/lib.php index 1a66a017a42..f10d82e1912 100644 --- a/repository/lib.php +++ b/repository/lib.php @@ -519,7 +519,7 @@ abstract class repository implements cacheable_object { public $disabled = false; /** @var int repository instance id */ public $id; - /** @var stdClass current context */ + /** @var context current context */ public $context; /** @var array repository options */ public $options; @@ -2307,7 +2307,7 @@ abstract class repository implements cacheable_object { * format and stores formatted values. * * @param array|stdClass $listing result of get_listing() or search() or file_get_drafarea_files() - * @return array + * @return stdClass */ public static function prepare_listing($listing) { $wasobject = false; @@ -2425,7 +2425,7 @@ abstract class repository implements cacheable_object { /** * Edit/Create Admin Settings Moodle form * - * @param moodleform $mform Moodle form (passed by reference) + * @param MoodleQuickForm $mform Moodle form (passed by reference) * @param string $classname repository class name */ public static function type_config_form($mform, $classname = 'repository') { @@ -3118,12 +3118,12 @@ final class repository_type_form extends moodleform { /** * Generate all options needed by filepicker * - * @param array $args including following keys + * @param stdClass $args including following keys * context * accepted_types * return_types * - * @return array the list of repository instances, including meta infomation, containing the following keys + * @return stdClass the list of repository instances, including meta infomation, containing the following keys * externallink * repositories * accepted_types diff --git a/repository/recent/tests/lib_test.php b/repository/recent/tests/lib_test.php index 7038b493d4e..270e1f841aa 100644 --- a/repository/recent/tests/lib_test.php +++ b/repository/recent/tests/lib_test.php @@ -46,7 +46,7 @@ class lib_test extends \advanced_testcase { /** @var repository Recent repository */ private $repo; - /** @var context repository */ + /** @var \context repository */ private $usercontext; /** @@ -170,7 +170,7 @@ class lib_test extends \advanced_testcase { * @param string $filename file name * @param string $filearea file area * @param int $itemid item id - * @return stored_file the newly created file + * @return \stored_file the newly created file */ private function create_test_file($filename, $filearea, $itemid = 0) { global $USER; @@ -192,11 +192,11 @@ class lib_test extends \advanced_testcase { /** * Create reference file * - * @param stored_file $file source file + * @param \stored_file $file source file * @param string $filename file name * @param string $filearea file area * @param int $itemid item id - * @return stored_file the newly created file + * @return \stored_file the newly created file */ private function create_reference_file($file, $filename, $filearea, $itemid = 0) { global $USER, $DB; diff --git a/repository/tests/privacy/provider_test.php b/repository/tests/privacy/provider_test.php index 85dcd5a5356..d6b4b845663 100644 --- a/repository/tests/privacy/provider_test.php +++ b/repository/tests/privacy/provider_test.php @@ -263,7 +263,6 @@ class provider_test extends \core_privacy\tests\provider_testcase { * * @param int $userid The Id of the User used for testing. * @param int $noscenarios The number of repository_instance records to create for the User. - * @throws dml_exception */ private function setup_test_scenario_data($userid, $noscenarios) { global $DB; diff --git a/search/classes/base_activity.php b/search/classes/base_activity.php index 66ea4e1cca2..713fa6d813c 100644 --- a/search/classes/base_activity.php +++ b/search/classes/base_activity.php @@ -81,7 +81,7 @@ abstract class base_activity extends base_mod { * content. Any activity can overwrite this function if it is interested in setting other fields than the * default ones, or to fill description optional fields with extra stuff. * - * @param stdClass $record + * @param \stdClass $record * @param array $options * @return \core_search\document */ diff --git a/search/engine/simpledb/tests/engine_test.php b/search/engine/simpledb/tests/engine_test.php index 01e4e8d22cf..22fdc0ff59e 100644 --- a/search/engine/simpledb/tests/engine_test.php +++ b/search/engine/simpledb/tests/engine_test.php @@ -43,7 +43,7 @@ class engine_test extends \advanced_testcase { protected $engine = null; /** - * @var core_search_generator + * @var \core_search_generator */ protected $generator = null; @@ -337,8 +337,6 @@ class engine_test extends \advanced_testcase { /** * Tries out deleting data for a context or a course. - * - * @throws moodle_exception */ public function test_deleted_contexts_and_courses() { // Create some courses and activities. @@ -375,7 +373,6 @@ class engine_test extends \advanced_testcase { * * @param string $searchword Word to match within the content field * @param string[] $expected Array of expected result titles, in alphabetical order - * @throws dml_exception */ protected function assert_raw_index_contents(string $searchword, array $expected) { global $DB; diff --git a/search/engine/solr/tests/engine_test.php b/search/engine/solr/tests/engine_test.php index 97b505869c7..7b52d2c97c7 100644 --- a/search/engine/solr/tests/engine_test.php +++ b/search/engine/solr/tests/engine_test.php @@ -1287,9 +1287,6 @@ class engine_test extends \advanced_testcase { /** * Tries out deleting data for a context or a course. - * - * @throws coding_exception - * @throws moodle_exception */ public function test_deleted_contexts_and_courses() { // Create some courses and activities. diff --git a/search/tests/base_activity_test.php b/search/tests/base_activity_test.php index 544b7c1f3bf..ebd615e48d8 100644 --- a/search/tests/base_activity_test.php +++ b/search/tests/base_activity_test.php @@ -36,7 +36,7 @@ class base_activity_test extends \advanced_testcase { protected $search = null; /** - * @var Instace of core_search_generator. + * @var \core_search_generator Instace of core_search_generator. */ protected $generator = null; @@ -45,10 +45,10 @@ class base_activity_test extends \advanced_testcase { */ protected $engine = null; - /** @var context[] Array of test contexts */ + /** @var \context[] Array of test contexts */ protected $contexts; - /** @var stdClass[] Array of test forum objects */ + /** @var \stdClass[] Array of test forum objects */ protected $forums; public function setUp(): void { @@ -256,7 +256,7 @@ class base_activity_test extends \advanced_testcase { /** * Utility function to convert recordset to array for testing. * - * @param moodle_recordset $rs Recordset to convert + * @param \moodle_recordset $rs Recordset to convert * @return array Array indexed by number (0, 1, 2, ...) */ protected static function recordset_to_indexed_array(\moodle_recordset $rs) { diff --git a/search/tests/base_block_test.php b/search/tests/base_block_test.php index c802fb28777..7ce367c960b 100644 --- a/search/tests/base_block_test.php +++ b/search/tests/base_block_test.php @@ -216,7 +216,7 @@ class base_block_test extends \advanced_testcase { /** * Utility function to convert recordset to array for testing. * - * @param moodle_recordset $rs Recordset to convert + * @param \moodle_recordset $rs Recordset to convert * @return array Array indexed by number (0, 1, 2, ...) */ protected static function recordset_to_indexed_array(\moodle_recordset $rs) { diff --git a/search/tests/top_result_test.php b/search/tests/top_result_test.php index 9fda6cf16c7..7a69a8f846d 100644 --- a/search/tests/top_result_test.php +++ b/search/tests/top_result_test.php @@ -16,6 +16,8 @@ namespace core_search; +use stdClass; + defined('MOODLE_INTERNAL') || die(); global $CFG; diff --git a/tag/classes/tests/privacy_helper.php b/tag/classes/tests/privacy_helper.php index cba779bd291..0ffe6f0dd6c 100644 --- a/tag/classes/tests/privacy_helper.php +++ b/tag/classes/tests/privacy_helper.php @@ -42,7 +42,7 @@ trait privacy_helper { * * @param \context $context The context being stored. * @param array $subcontext The subcontext path to check. - * @return array + * @return \stdClass|array */ protected function get_tags_on_subcontext(\context $context, array $subcontext) { $writer = \core_privacy\local\request\writer::with_context($context); diff --git a/tag/tests/taglib_test.php b/tag/tests/taglib_test.php index 91a4681c593..1cc7f127592 100644 --- a/tag/tests/taglib_test.php +++ b/tag/tests/taglib_test.php @@ -1977,8 +1977,8 @@ class taglib_test extends \advanced_testcase { * @param string $component * @param string $itemtype * @param int $itemid - * @param context $context - * @return stdClass + * @param \context $context + * @return \stdClass */ protected function add_tag_instance(core_tag_tag $tag, $component, $itemtype, $itemid, $context) { global $DB; diff --git a/user/classes/output/myprofile/manager.php b/user/classes/output/myprofile/manager.php index d3064250344..559692fbe55 100644 --- a/user/classes/output/myprofile/manager.php +++ b/user/classes/output/myprofile/manager.php @@ -37,7 +37,7 @@ class manager { /** * Parse all callbacks and builds the tree. * - * @param integer $user ID of the user for which the profile is displayed. + * @param \stdClass $user user for which the profile is displayed. * @param bool $iscurrentuser true if the profile being viewed is of current user, else false. * @param \stdClass $course Course object * diff --git a/user/editlib.php b/user/editlib.php index 92e829ef857..e02ad6617cf 100644 --- a/user/editlib.php +++ b/user/editlib.php @@ -244,7 +244,7 @@ function useredit_update_interests($user, $interests) { /** * Powerful function that is used by edit and editadvanced to add common form elements/rules/etc. * - * @param moodleform $mform + * @param MoodleQuickForm $mform * @param array $editoroptions * @param array $filemanageroptions * @param stdClass $user diff --git a/user/externallib.php b/user/externallib.php index 8a6e8e0acc2..84127412756 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -1112,7 +1112,7 @@ class core_user_external extends \core_external\external_api { * Create user return value description. * * @param array $additionalfields some additional field - * @return single_structure_description + * @return external_description */ public static function user_description($additionalfields = array()) { $userfields = array( diff --git a/user/lib.php b/user/lib.php index 2ab18a227cd..cb801303d88 100644 --- a/user/lib.php +++ b/user/lib.php @@ -33,7 +33,7 @@ define('USER_FILTER_STRING', 6); * Creates a user * * @throws moodle_exception - * @param stdClass $user user to create + * @param stdClass|array $user user to create * @param bool $updatepassword if true, authentication plugin will update password. * @param bool $triggerevent set false if user_created event should not be triggred. * This will not affect user_password_updated event triggering. @@ -144,7 +144,7 @@ function user_create_user($user, $updatepassword = true, $triggerevent = true) { * Update a user with a user object (will compare against the ID) * * @throws moodle_exception - * @param stdClass $user the user to update + * @param stdClass|array $user the user to update * @param bool $updatepassword if true, authentication plugin will update password. * @param bool $triggerevent set false if user_updated event should not be triggred. * This will not affect user_password_updated event triggering. @@ -1321,7 +1321,7 @@ function user_get_lastaccess_sql($columnname, $accesssince, $tableprefix, $havea * @param string $itemtype - Only user_roles is supported. * @param string $itemid - Courseid and userid separated by a : * @param string $newvalue - json encoded list of roleids. - * @return \core\output\inplace_editable + * @return \core\output\inplace_editable|null */ function core_user_inplace_editable($itemtype, $itemid, $newvalue) { if ($itemtype === 'user_roles') { diff --git a/user/profile/field/social/define.class.php b/user/profile/field/social/define.class.php index 61a02fc4b8e..283da7cd4ed 100644 --- a/user/profile/field/social/define.class.php +++ b/user/profile/field/social/define.class.php @@ -33,7 +33,7 @@ class profile_define_social extends profile_define_base { /** * Prints out the form snippet for the part of creating or editing a profile field common to all data types. * - * @param moodleform $form instance of the moodleform class + * @param MoodleQuickForm $form instance of the moodleform class */ public function define_form_common(&$form) { $availablenetworks = profilefield_social\helper::get_networks(); @@ -53,7 +53,7 @@ class profile_define_social extends profile_define_base { /** * Alter form based on submitted or existing data. * - * @param moodleform $form + * @param MoodleQuickForm $form */ public function define_after_data(&$form) { if (isset($form->_defaultValues['name'])) { diff --git a/user/tests/group_non_members_selector_test.php b/user/tests/group_non_members_selector_test.php index 46e07a01e7b..04524a72cdc 100644 --- a/user/tests/group_non_members_selector_test.php +++ b/user/tests/group_non_members_selector_test.php @@ -35,8 +35,6 @@ class group_non_members_selector_test extends \advanced_testcase { /** * Test find_users that only return group non members - * - * @throws coding_exception */ public function test_find_users_only_return_group_non_member() { $this->resetAfterTest(); diff --git a/user/tests/privacy/provider_test.php b/user/tests/privacy/provider_test.php index ffba864a7b4..a908701a4b7 100644 --- a/user/tests/privacy/provider_test.php +++ b/user/tests/privacy/provider_test.php @@ -405,8 +405,8 @@ class provider_test extends provider_testcase { /** * Create user data for a user. * - * @param stdClass $user A user object. - * @param stdClass $course A course. + * @param \stdClass $user A user object. + * @param \stdClass $course A course. */ protected function create_data_for_user($user, $course) { global $DB; diff --git a/webservice/rest/tests/server_test.php b/webservice/rest/tests/server_test.php index 3d7c47d5602..e1b781b1faa 100644 --- a/webservice/rest/tests/server_test.php +++ b/webservice/rest/tests/server_test.php @@ -201,7 +201,7 @@ class server_test extends \advanced_testcase { /** * @dataProvider xmlize_provider - * @param external_description $description The data structure. + * @param \core_external\external_description $description The data structure. * @param mixed $value The value to xmlise. * @param mixed $expected The expected output. */ diff --git a/webservice/soap/locallib.php b/webservice/soap/locallib.php index 593f2d9c288..3b10ee4a30f 100644 --- a/webservice/soap/locallib.php +++ b/webservice/soap/locallib.php @@ -139,6 +139,7 @@ class webservice_soap_server extends webservice_base_server { 'function' => 'unknown' ) ); + /** @var \core\event\webservice_function_called $event */ $event = \core\event\webservice_function_called::create($params); $event->trigger(); diff --git a/webservice/tests/helpers.php b/webservice/tests/helpers.php index 8d0f2c2c131..025da61c34f 100644 --- a/webservice/tests/helpers.php +++ b/webservice/tests/helpers.php @@ -30,7 +30,7 @@ abstract class externallib_advanced_testcase extends advanced_testcase { * The function creates a student $USER if $USER->id is empty * * @param string $capability capability name - * @param int $contextid + * @param int|context $contextid * @param int $roleid * @return int the role id - mainly returned for creation, so calling function can reuse it */ diff --git a/webservice/tests/lib_test.php b/webservice/tests/lib_test.php index 287485ffacf..4ebc79801a7 100644 --- a/webservice/tests/lib_test.php +++ b/webservice/tests/lib_test.php @@ -146,8 +146,6 @@ class lib_test extends \advanced_testcase { /** * Tests update_token_lastaccess() function. - * - * @throws dml_exception */ public function test_update_token_lastaccess() { global $DB; @@ -286,7 +284,7 @@ class lib_test extends \advanced_testcase { $user = $this->getDataGenerator()->create_user(); - /** @var core_webservice_generator $generator */ + /** @var \core_webservice_generator $generator */ $generator = $this->getDataGenerator()->get_plugin_generator('core_webservice'); $service = $generator->create_service(['name' => 'My test service', 'shortname' => 'mytestservice']); @@ -416,7 +414,7 @@ class webservice_dummy extends \webservice_base_server { /** * Send the error information to the WS client. * - * @param exception $ex + * @param \Exception $ex */ protected function send_error($ex = null) { // Just a method stub. No need to implement at the moment since it's not really being used for this test case for now.