mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
Merge branch 'MDL-79061-main-2' of https://github.com/junpataleta/moodle
This commit is contained in:
commit
39a7a380c9
17 changed files with 300 additions and 10 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -14,7 +14,16 @@
|
||||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import ajax from 'core/ajax';
|
import ajax from 'core/ajax';
|
||||||
|
import {getString} from "core/str";
|
||||||
import log from 'core/log';
|
import log from 'core/log';
|
||||||
|
import SRLogger from "core/local/reactive/srlogger";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to determine whether the screen reader-only logger has already been set, so we only need to set it once.
|
||||||
|
*
|
||||||
|
* @type {boolean}
|
||||||
|
*/
|
||||||
|
let isLoggerSet = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default mutation manager
|
* Default mutation manager
|
||||||
|
@ -66,6 +75,11 @@ export default class {
|
||||||
* @param {number} targetCmId optional target cm id (for moving actions)
|
* @param {number} targetCmId optional target cm id (for moving actions)
|
||||||
*/
|
*/
|
||||||
async _sectionBasicAction(stateManager, action, sectionIds, targetSectionId, targetCmId) {
|
async _sectionBasicAction(stateManager, action, sectionIds, targetSectionId, targetCmId) {
|
||||||
|
const logEntry = this._getLoggerEntry(stateManager, action, sectionIds, {
|
||||||
|
targetSectionId,
|
||||||
|
targetCmId,
|
||||||
|
itemType: 'section',
|
||||||
|
});
|
||||||
const course = stateManager.get('course');
|
const course = stateManager.get('course');
|
||||||
this.sectionLock(stateManager, sectionIds, true);
|
this.sectionLock(stateManager, sectionIds, true);
|
||||||
const updates = await this._callEditWebservice(
|
const updates = await this._callEditWebservice(
|
||||||
|
@ -78,6 +92,7 @@ export default class {
|
||||||
this.bulkReset(stateManager);
|
this.bulkReset(stateManager);
|
||||||
stateManager.processUpdates(updates);
|
stateManager.processUpdates(updates);
|
||||||
this.sectionLock(stateManager, sectionIds, false);
|
this.sectionLock(stateManager, sectionIds, false);
|
||||||
|
stateManager.addLoggerEntry(await logEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,6 +104,11 @@ export default class {
|
||||||
* @param {number} targetCmId optional target cm id (for moving actions)
|
* @param {number} targetCmId optional target cm id (for moving actions)
|
||||||
*/
|
*/
|
||||||
async _cmBasicAction(stateManager, action, cmIds, targetSectionId, targetCmId) {
|
async _cmBasicAction(stateManager, action, cmIds, targetSectionId, targetCmId) {
|
||||||
|
const logEntry = this._getLoggerEntry(stateManager, action, cmIds, {
|
||||||
|
targetSectionId,
|
||||||
|
targetCmId,
|
||||||
|
itemType: 'cm',
|
||||||
|
});
|
||||||
const course = stateManager.get('course');
|
const course = stateManager.get('course');
|
||||||
this.cmLock(stateManager, cmIds, true);
|
this.cmLock(stateManager, cmIds, true);
|
||||||
const updates = await this._callEditWebservice(
|
const updates = await this._callEditWebservice(
|
||||||
|
@ -101,6 +121,56 @@ export default class {
|
||||||
this.bulkReset(stateManager);
|
this.bulkReset(stateManager);
|
||||||
stateManager.processUpdates(updates);
|
stateManager.processUpdates(updates);
|
||||||
this.cmLock(stateManager, cmIds, false);
|
this.cmLock(stateManager, cmIds, false);
|
||||||
|
stateManager.addLoggerEntry(await logEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get log entry for the current action.
|
||||||
|
* @param {StateManager} stateManager the current state manager
|
||||||
|
* @param {string} action the action name
|
||||||
|
* @param {int[]|null} itemIds the element ids
|
||||||
|
* @param {Object|undefined} data extra params for the log entry
|
||||||
|
* @param {string|undefined} data.itemType the element type (will be taken from action if none)
|
||||||
|
* @param {int|null|undefined} data.targetSectionId the target section id
|
||||||
|
* @param {int|null|undefined} data.targetCmId the target cm id
|
||||||
|
* @param {String|null|undefined} data.component optional component (for format plugins)
|
||||||
|
* @return {Object} the log entry
|
||||||
|
*/
|
||||||
|
async _getLoggerEntry(stateManager, action, itemIds, data = {}) {
|
||||||
|
if (!isLoggerSet) {
|
||||||
|
// In case the logger has not been set from init(), ensure we set the logger.
|
||||||
|
stateManager.setLogger(new SRLogger());
|
||||||
|
isLoggerSet = true;
|
||||||
|
}
|
||||||
|
const feedbackParams = {
|
||||||
|
action,
|
||||||
|
itemType: data.itemType ?? action.split('_')[0],
|
||||||
|
};
|
||||||
|
let batch = '';
|
||||||
|
if (itemIds.length > 1) {
|
||||||
|
feedbackParams.count = itemIds.length;
|
||||||
|
batch = '_batch';
|
||||||
|
} else if (itemIds.length === 1) {
|
||||||
|
const itemInfo = stateManager.get(feedbackParams.itemType, itemIds[0]);
|
||||||
|
feedbackParams.name = itemInfo.title ?? itemInfo.name;
|
||||||
|
// Apply shortener for modules like label.
|
||||||
|
}
|
||||||
|
if (data.targetSectionId) {
|
||||||
|
feedbackParams.targetSectionName = stateManager.get('section', data.targetSectionId).title;
|
||||||
|
}
|
||||||
|
if (data.targetCmId) {
|
||||||
|
feedbackParams.targetCmName = stateManager.get('cm', data.targetCmId).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = await getString(
|
||||||
|
`${action.toLowerCase()}_feedback${batch}`,
|
||||||
|
data.component ?? 'core_courseformat',
|
||||||
|
feedbackParams
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
feedbackMessage: message,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,10 +181,13 @@ export default class {
|
||||||
* @param {StateManager} stateManager the state manager
|
* @param {StateManager} stateManager the state manager
|
||||||
*/
|
*/
|
||||||
init(stateManager) {
|
init(stateManager) {
|
||||||
// Add a method to prepare the fields when some update is comming from the server.
|
// Add a method to prepare the fields when some update is coming from the server.
|
||||||
stateManager.addUpdateTypes({
|
stateManager.addUpdateTypes({
|
||||||
prepareFields: this._prepareFields,
|
prepareFields: this._prepareFields,
|
||||||
});
|
});
|
||||||
|
// Use the screen reader-only logger (SRLogger) to handle the feedback messages from the mutations.
|
||||||
|
stateManager.setLogger(new SRLogger());
|
||||||
|
isLoggerSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -186,6 +259,7 @@ export default class {
|
||||||
* @param {number|undefined} targetCmId the target course module id
|
* @param {number|undefined} targetCmId the target course module id
|
||||||
*/
|
*/
|
||||||
async cmDuplicate(stateManager, cmIds, targetSectionId, targetCmId) {
|
async cmDuplicate(stateManager, cmIds, targetSectionId, targetCmId) {
|
||||||
|
const logEntry = this._getLoggerEntry(stateManager, 'cm_duplicate', cmIds);
|
||||||
const course = stateManager.get('course');
|
const course = stateManager.get('course');
|
||||||
// Lock all target sections.
|
// Lock all target sections.
|
||||||
const sectionIds = new Set();
|
const sectionIds = new Set();
|
||||||
|
@ -204,6 +278,7 @@ export default class {
|
||||||
stateManager.processUpdates(updates);
|
stateManager.processUpdates(updates);
|
||||||
|
|
||||||
this.sectionLock(stateManager, Array.from(sectionIds), false);
|
this.sectionLock(stateManager, Array.from(sectionIds), false);
|
||||||
|
stateManager.addLoggerEntry(await logEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
define("format_topics/mutations",["exports","core_courseformat/courseeditor","core_courseformat/local/courseeditor/mutations","core_courseformat/local/content/actions"],(function(_exports,_courseeditor,_mutations,_actions){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_mutations=_interopRequireDefault(_mutations),_actions=_interopRequireDefault(_actions);class TopicsMutations extends _mutations.default{constructor(){super(...arguments),_defineProperty(this,"sectionHighlight",(async function(stateManager,sectionIds){const course=stateManager.get("course");this.sectionLock(stateManager,sectionIds,!0);const updates=await this._callEditWebservice("section_highlight",course.id,sectionIds);stateManager.processUpdates(updates),this.sectionLock(stateManager,sectionIds,!1)})),_defineProperty(this,"sectionUnhighlight",(async function(stateManager,sectionIds){const course=stateManager.get("course");this.sectionLock(stateManager,sectionIds,!0);const updates=await this._callEditWebservice("section_unhighlight",course.id,sectionIds);stateManager.processUpdates(updates),this.sectionLock(stateManager,sectionIds,!1)}))}}_exports.init=()=>{(0,_courseeditor.getCurrentCourseEditor)().addMutations(new TopicsMutations),_actions.default.addActions({sectionHighlight:"sectionHighlight",sectionUnhighlight:"sectionUnhighlight"})}}));
|
define("format_topics/mutations",["exports","core_courseformat/courseeditor","core_courseformat/local/courseeditor/mutations","core_courseformat/local/content/actions"],(function(_exports,_courseeditor,_mutations,_actions){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_mutations=_interopRequireDefault(_mutations),_actions=_interopRequireDefault(_actions);class TopicsMutations extends _mutations.default{constructor(){super(...arguments),_defineProperty(this,"sectionHighlight",(async function(stateManager,sectionIds){const logEntry=this._getLoggerEntry(stateManager,"section_highlight",sectionIds,{component:"format_topics"}),course=stateManager.get("course");this.sectionLock(stateManager,sectionIds,!0);const updates=await this._callEditWebservice("section_highlight",course.id,sectionIds);stateManager.processUpdates(updates),this.sectionLock(stateManager,sectionIds,!1),stateManager.addLoggerEntry(await logEntry)})),_defineProperty(this,"sectionUnhighlight",(async function(stateManager,sectionIds){const logEntry=this._getLoggerEntry(stateManager,"section_unhighlight",sectionIds,{component:"format_topics"}),course=stateManager.get("course");this.sectionLock(stateManager,sectionIds,!0);const updates=await this._callEditWebservice("section_unhighlight",course.id,sectionIds);stateManager.processUpdates(updates),this.sectionLock(stateManager,sectionIds,!1),stateManager.addLoggerEntry(await logEntry)}))}}_exports.init=()=>{(0,_courseeditor.getCurrentCourseEditor)().addMutations(new TopicsMutations),_actions.default.addActions({sectionHighlight:"sectionHighlight",sectionUnhighlight:"sectionUnhighlight"})}}));
|
||||||
|
|
||||||
//# sourceMappingURL=mutations.min.js.map
|
//# sourceMappingURL=mutations.min.js.map
|
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"mutations.min.js","sources":["../src/mutations.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Format topics mutations.\n *\n * An instance of this class will be used to add custom mutations to the course editor.\n * To make sure the addMutations method find the proper functions, all functions must\n * be declared as class attributes, not a simple methods. The reason is because many\n * plugins can add extra mutations to the course editor.\n *\n * @module format_topics/mutations\n * @copyright 2022 Ferran Recio <ferran@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport DefaultMutations from 'core_courseformat/local/courseeditor/mutations';\nimport CourseActions from 'core_courseformat/local/content/actions';\n\nclass TopicsMutations extends DefaultMutations {\n\n /**\n * Highlight sections.\n *\n * It is important to note this mutation method is declared as a class attribute,\n * See the class jsdoc for more details on why.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids\n */\n sectionHighlight = async function(stateManager, sectionIds) {\n const course = stateManager.get('course');\n this.sectionLock(stateManager, sectionIds, true);\n const updates = await this._callEditWebservice('section_highlight', course.id, sectionIds);\n stateManager.processUpdates(updates);\n this.sectionLock(stateManager, sectionIds, false);\n };\n\n /**\n * Unhighlight sections.\n *\n * It is important to note this mutation method is declared as a class attribute,\n * See the class jsdoc for more details on why.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids\n */\n sectionUnhighlight = async function(stateManager, sectionIds) {\n const course = stateManager.get('course');\n this.sectionLock(stateManager, sectionIds, true);\n const updates = await this._callEditWebservice('section_unhighlight', course.id, sectionIds);\n stateManager.processUpdates(updates);\n this.sectionLock(stateManager, sectionIds, false);\n };\n}\n\nexport const init = () => {\n const courseEditor = getCurrentCourseEditor();\n // Some plugin (activity or block) may have their own mutations already registered.\n // This is why we use addMutations instead of setMutations here.\n courseEditor.addMutations(new TopicsMutations());\n // Add direct mutation content actions.\n CourseActions.addActions({\n sectionHighlight: 'sectionHighlight',\n sectionUnhighlight: 'sectionUnhighlight',\n });\n};\n"],"names":["TopicsMutations","DefaultMutations","async","stateManager","sectionIds","course","get","sectionLock","updates","this","_callEditWebservice","id","processUpdates","addMutations","addActions","sectionHighlight","sectionUnhighlight"],"mappings":"goBAgCMA,wBAAwBC,8FAWPC,eAAeC,aAAcC,kBACtCC,OAASF,aAAaG,IAAI,eAC3BC,YAAYJ,aAAcC,YAAY,SACrCI,cAAgBC,KAAKC,oBAAoB,oBAAqBL,OAAOM,GAAIP,YAC/ED,aAAaS,eAAeJ,cACvBD,YAAYJ,aAAcC,YAAY,iDAY1BF,eAAeC,aAAcC,kBACxCC,OAASF,aAAaG,IAAI,eAC3BC,YAAYJ,aAAcC,YAAY,SACrCI,cAAgBC,KAAKC,oBAAoB,sBAAuBL,OAAOM,GAAIP,YACjFD,aAAaS,eAAeJ,cACvBD,YAAYJ,aAAcC,YAAY,qBAI/B,MACK,0CAGRS,aAAa,IAAIb,kCAEhBc,WAAW,CACrBC,iBAAkB,mBAClBC,mBAAoB"}
|
{"version":3,"file":"mutations.min.js","sources":["../src/mutations.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Format topics mutations.\n *\n * An instance of this class will be used to add custom mutations to the course editor.\n * To make sure the addMutations method find the proper functions, all functions must\n * be declared as class attributes, not a simple methods. The reason is because many\n * plugins can add extra mutations to the course editor.\n *\n * @module format_topics/mutations\n * @copyright 2022 Ferran Recio <ferran@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getCurrentCourseEditor} from 'core_courseformat/courseeditor';\nimport DefaultMutations from 'core_courseformat/local/courseeditor/mutations';\nimport CourseActions from 'core_courseformat/local/content/actions';\n\nclass TopicsMutations extends DefaultMutations {\n\n /**\n * Highlight sections.\n *\n * It is important to note this mutation method is declared as a class attribute,\n * See the class jsdoc for more details on why.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids\n */\n sectionHighlight = async function(stateManager, sectionIds) {\n const logEntry = this._getLoggerEntry(\n stateManager,\n 'section_highlight',\n sectionIds,\n {component: 'format_topics'}\n );\n const course = stateManager.get('course');\n this.sectionLock(stateManager, sectionIds, true);\n const updates = await this._callEditWebservice('section_highlight', course.id, sectionIds);\n stateManager.processUpdates(updates);\n this.sectionLock(stateManager, sectionIds, false);\n stateManager.addLoggerEntry(await logEntry);\n\n };\n\n /**\n * Unhighlight sections.\n *\n * It is important to note this mutation method is declared as a class attribute,\n * See the class jsdoc for more details on why.\n *\n * @param {StateManager} stateManager the current state manager\n * @param {array} sectionIds the list of section ids\n */\n sectionUnhighlight = async function(stateManager, sectionIds) {\n const logEntry = this._getLoggerEntry(\n stateManager,\n 'section_unhighlight',\n sectionIds,\n {component: 'format_topics'}\n );\n const course = stateManager.get('course');\n this.sectionLock(stateManager, sectionIds, true);\n const updates = await this._callEditWebservice('section_unhighlight', course.id, sectionIds);\n stateManager.processUpdates(updates);\n this.sectionLock(stateManager, sectionIds, false);\n stateManager.addLoggerEntry(await logEntry);\n };\n}\n\nexport const init = () => {\n const courseEditor = getCurrentCourseEditor();\n // Some plugin (activity or block) may have their own mutations already registered.\n // This is why we use addMutations instead of setMutations here.\n courseEditor.addMutations(new TopicsMutations());\n // Add direct mutation content actions.\n CourseActions.addActions({\n sectionHighlight: 'sectionHighlight',\n sectionUnhighlight: 'sectionUnhighlight',\n });\n};\n"],"names":["TopicsMutations","DefaultMutations","async","stateManager","sectionIds","logEntry","this","_getLoggerEntry","component","course","get","sectionLock","updates","_callEditWebservice","id","processUpdates","addLoggerEntry","addMutations","addActions","sectionHighlight","sectionUnhighlight"],"mappings":"goBAgCMA,wBAAwBC,8FAWPC,eAAeC,aAAcC,kBACtCC,SAAWC,KAAKC,gBAClBJ,aACA,oBACAC,WACA,CAACI,UAAW,kBAEVC,OAASN,aAAaO,IAAI,eAC3BC,YAAYR,aAAcC,YAAY,SACrCQ,cAAgBN,KAAKO,oBAAoB,oBAAqBJ,OAAOK,GAAIV,YAC/ED,aAAaY,eAAeH,cACvBD,YAAYR,aAAcC,YAAY,GAC3CD,aAAaa,qBAAqBX,wDAajBH,eAAeC,aAAcC,kBACxCC,SAAWC,KAAKC,gBAClBJ,aACA,sBACAC,WACA,CAACI,UAAW,kBAEVC,OAASN,aAAaO,IAAI,eAC3BC,YAAYR,aAAcC,YAAY,SACrCQ,cAAgBN,KAAKO,oBAAoB,sBAAuBJ,OAAOK,GAAIV,YACjFD,aAAaY,eAAeH,cACvBD,YAAYR,aAAcC,YAAY,GAC3CD,aAAaa,qBAAqBX,4BAItB,MACK,0CAGRY,aAAa,IAAIjB,kCAEhBkB,WAAW,CACrBC,iBAAkB,mBAClBC,mBAAoB"}
|
|
@ -42,11 +42,19 @@ class TopicsMutations extends DefaultMutations {
|
||||||
* @param {array} sectionIds the list of section ids
|
* @param {array} sectionIds the list of section ids
|
||||||
*/
|
*/
|
||||||
sectionHighlight = async function(stateManager, sectionIds) {
|
sectionHighlight = async function(stateManager, sectionIds) {
|
||||||
|
const logEntry = this._getLoggerEntry(
|
||||||
|
stateManager,
|
||||||
|
'section_highlight',
|
||||||
|
sectionIds,
|
||||||
|
{component: 'format_topics'}
|
||||||
|
);
|
||||||
const course = stateManager.get('course');
|
const course = stateManager.get('course');
|
||||||
this.sectionLock(stateManager, sectionIds, true);
|
this.sectionLock(stateManager, sectionIds, true);
|
||||||
const updates = await this._callEditWebservice('section_highlight', course.id, sectionIds);
|
const updates = await this._callEditWebservice('section_highlight', course.id, sectionIds);
|
||||||
stateManager.processUpdates(updates);
|
stateManager.processUpdates(updates);
|
||||||
this.sectionLock(stateManager, sectionIds, false);
|
this.sectionLock(stateManager, sectionIds, false);
|
||||||
|
stateManager.addLoggerEntry(await logEntry);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,11 +67,18 @@ class TopicsMutations extends DefaultMutations {
|
||||||
* @param {array} sectionIds the list of section ids
|
* @param {array} sectionIds the list of section ids
|
||||||
*/
|
*/
|
||||||
sectionUnhighlight = async function(stateManager, sectionIds) {
|
sectionUnhighlight = async function(stateManager, sectionIds) {
|
||||||
|
const logEntry = this._getLoggerEntry(
|
||||||
|
stateManager,
|
||||||
|
'section_unhighlight',
|
||||||
|
sectionIds,
|
||||||
|
{component: 'format_topics'}
|
||||||
|
);
|
||||||
const course = stateManager.get('course');
|
const course = stateManager.get('course');
|
||||||
this.sectionLock(stateManager, sectionIds, true);
|
this.sectionLock(stateManager, sectionIds, true);
|
||||||
const updates = await this._callEditWebservice('section_unhighlight', course.id, sectionIds);
|
const updates = await this._callEditWebservice('section_unhighlight', course.id, sectionIds);
|
||||||
stateManager.processUpdates(updates);
|
stateManager.processUpdates(updates);
|
||||||
this.sectionLock(stateManager, sectionIds, false);
|
this.sectionLock(stateManager, sectionIds, false);
|
||||||
|
stateManager.addLoggerEntry(await logEntry);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ $string['pluginname'] = 'Topics format';
|
||||||
$string['privacy:metadata'] = 'The Topics format plugin does not store any personal data.';
|
$string['privacy:metadata'] = 'The Topics format plugin does not store any personal data.';
|
||||||
$string['indentation'] = 'Allow indentation on course page';
|
$string['indentation'] = 'Allow indentation on course page';
|
||||||
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
|
$string['indentation_help'] = 'Allow teachers, and other users with the manage activities capability, to indent items on the course page.';
|
||||||
|
$string['section_highlight_feedback'] = 'Section {$a->name} is highlighted.';
|
||||||
|
$string['section_unhighlight_feedback'] = 'Highlight removed from section {$a->name}.';
|
||||||
$string['section0name'] = 'General';
|
$string['section0name'] = 'General';
|
||||||
$string['sectionavailability_title'] = 'Topic availability';
|
$string['sectionavailability_title'] = 'Topic availability';
|
||||||
$string['sectiondelete_title'] = 'Delete topic?';
|
$string['sectiondelete_title'] = 'Delete topic?';
|
||||||
|
|
|
@ -33,6 +33,20 @@ $string['bulkeditingcourse'] = 'Bulk edit course: {$a}';
|
||||||
$string['bulkcancel'] = 'Close bulk actions';
|
$string['bulkcancel'] = 'Close bulk actions';
|
||||||
$string['bulkselection'] = '{$a} selected';
|
$string['bulkselection'] = '{$a} selected';
|
||||||
$string['bulkselection_plural'] = '{$a} selected';
|
$string['bulkselection_plural'] = '{$a} selected';
|
||||||
|
$string['cm_delete_feedback'] = '{$a->name} has been deleted.';
|
||||||
|
$string['cm_delete_feedback_batch'] = 'The selected {$a->count} activities have been deleted.';
|
||||||
|
$string['cm_duplicate_feedback'] = '{$a->name} has been duplicated.';
|
||||||
|
$string['cm_duplicate_feedback_batch'] = 'The selected {$a->count} activities have been duplicated.';
|
||||||
|
$string['cm_hide_feedback'] = '{$a->name} is now hidden.';
|
||||||
|
$string['cm_hide_feedback_batch'] = 'The selected {$a->count} activities are now hidden.';
|
||||||
|
$string['cm_moveleft_feedback'] = '{$a->name} has been moved to the left.';
|
||||||
|
$string['cm_moveright_feedback'] = '{$a->name} has been moved to the right.';
|
||||||
|
$string['cm_nogroups_feedback'] = '{$a->name}\'s group mode has been changed to "No groups".';
|
||||||
|
$string['cm_separategroups_feedback'] = '{$a->name}\'s group mode has been changed to "Separate groups".';
|
||||||
|
$string['cm_show_feedback'] = '{$a->name} is now shown.';
|
||||||
|
$string['cm_show_feedback_batch'] = 'The selected {$a->count} activities are now shown.';
|
||||||
|
$string['cm_stealth_feedback'] = '{$a->name} is now available but not shown on the course page.';
|
||||||
|
$string['cm_visiblegroups_feedback'] = '{$a->name}\'s group mode has been changed to "Visible groups".';
|
||||||
$string['cmavailability'] = 'Activity availability';
|
$string['cmavailability'] = 'Activity availability';
|
||||||
$string['cmdelete_info'] = 'This will delete {$a->name} and any user data it contains.';
|
$string['cmdelete_info'] = 'This will delete {$a->name} and any user data it contains.';
|
||||||
$string['cmdelete_title'] = 'Delete activity?';
|
$string['cmdelete_title'] = 'Delete activity?';
|
||||||
|
@ -50,6 +64,12 @@ $string['courseindexoptions'] = 'Course index options';
|
||||||
$string['nobulkaction'] = 'No bulk actions available';
|
$string['nobulkaction'] = 'No bulk actions available';
|
||||||
$string['preference:coursesectionspreferences'] = 'Section user preferences for course {$a}';
|
$string['preference:coursesectionspreferences'] = 'Section user preferences for course {$a}';
|
||||||
$string['privacy:metadata:preference:coursesectionspreferences'] = 'Section user preferences like collapsed and expanded.';
|
$string['privacy:metadata:preference:coursesectionspreferences'] = 'Section user preferences like collapsed and expanded.';
|
||||||
|
$string['section_hide_feedback'] = 'The course section {$a->name} has been hidden.';
|
||||||
|
$string['section_hide_feedback_batch'] = 'The selected {$a->count} course sections have been hidden.';
|
||||||
|
$string['section_show_feedback'] = 'The course section {$a->name} has been shown.';
|
||||||
|
$string['section_show_feedback_batch'] = 'The selected {$a->count} course sections have been shown.';
|
||||||
|
$string['section_delete_feedback'] = 'The course section {$a->name} has been deleted';
|
||||||
|
$string['section_delete_feedback_batch'] = 'The selected {$a->count} course sections have been deleted';
|
||||||
$string['sectionavailability_title'] = 'Section availability';
|
$string['sectionavailability_title'] = 'Section availability';
|
||||||
$string['sectiondelete_info'] = 'This will delete {$a->name} and all the activities it contains.';
|
$string['sectiondelete_info'] = 'This will delete {$a->name} and all the activities it contains.';
|
||||||
$string['sectiondelete_title'] = 'Delete section?';
|
$string['sectiondelete_title'] = 'Delete section?';
|
||||||
|
|
17
lib/amd/build/local/reactive/logger.min.js
vendored
Normal file
17
lib/amd/build/local/reactive/logger.min.js
vendored
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
define("core/local/reactive/logger",["exports","core/toast"],(function(_exports,_toast){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default=
|
||||||
|
/**
|
||||||
|
* Default reactive mutations logger class.
|
||||||
|
*
|
||||||
|
* This logger is used by default by the StateManager to log mutation feedbacks
|
||||||
|
* and actions. By default, feedbacks will be displayed as a toast. However, the
|
||||||
|
* reactive instance can provide alternative loggers to provide advanced logging
|
||||||
|
* capabilities.
|
||||||
|
*
|
||||||
|
* @module core/local/reactive/logger
|
||||||
|
* @class Logger
|
||||||
|
* @copyright 2023 Ferran Recio <ferran@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
class{constructor(){this._debug=!1}add(entry){entry.feedbackMessage&&(0,_toast.add)(entry.feedbackMessage)}},_exports.default}));
|
||||||
|
|
||||||
|
//# sourceMappingURL=logger.min.js.map
|
1
lib/amd/build/local/reactive/logger.min.js.map
Normal file
1
lib/amd/build/local/reactive/logger.min.js.map
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"logger.min.js","sources":["../../../src/local/reactive/logger.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Default reactive mutations logger class.\n *\n * This logger is used by default by the StateManager to log mutation feedbacks\n * and actions. By default, feedbacks will be displayed as a toast. However, the\n * reactive instance can provide alternative loggers to provide advanced logging\n * capabilities.\n *\n * @module core/local/reactive/logger\n * @class Logger\n * @copyright 2023 Ferran Recio <ferran@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Logger entry structure.\n *\n * @typedef {object} LoggerEntry\n * @property {string} feedbackMessage Feedback message.\n */\n\nimport {add as addToast} from 'core/toast';\n\n/**\n * Default reactive mutations logger class.\n * @class Logger\n */\nexport default class Logger {\n /**\n * Constructor.\n */\n constructor() {\n this._debug = false;\n }\n\n /**\n * Add a log entry.\n * @param {LoggerEntry} entry Log entry.\n */\n add(entry) {\n if (entry.feedbackMessage) {\n addToast(entry.feedbackMessage);\n }\n }\n}\n"],"names":["constructor","_debug","add","entry","feedbackMessage"],"mappings":";;;;;;;;;;;;;;MA8CIA,mBACSC,QAAS,EAOlBC,IAAIC,OACIA,MAAMC,gCACGD,MAAMC"}
|
3
lib/amd/build/local/reactive/srlogger.min.js
vendored
Normal file
3
lib/amd/build/local/reactive/srlogger.min.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
define("core/local/reactive/srlogger",["exports","core/local/reactive/logger"],(function(_exports,_logger){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_logger=(obj=_logger)&&obj.__esModule?obj:{default:obj};class SRLogger extends _logger.default{add(entry){if(entry.feedbackMessage){let loggerFeedback=document.getElementById(SRLogger.liveRegionId);loggerFeedback||(loggerFeedback=document.createElement("div"),loggerFeedback.id=SRLogger.liveRegionId,loggerFeedback.classList.add("sr-only"),loggerFeedback.setAttribute("aria-live","polite"),document.body.append(loggerFeedback)),loggerFeedback.innerHTML=entry.feedbackMessage,setTimeout((()=>{loggerFeedback.innerHTML=""}),4e3)}}}return _exports.default=SRLogger,function(obj,key,value){key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value}(SRLogger,"liveRegionId","sr-logger-feedback-container"),_exports.default}));
|
||||||
|
|
||||||
|
//# sourceMappingURL=srlogger.min.js.map
|
1
lib/amd/build/local/reactive/srlogger.min.js.map
Normal file
1
lib/amd/build/local/reactive/srlogger.min.js.map
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"srlogger.min.js","sources":["../../../src/local/reactive/srlogger.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 <http://www.gnu.org/licenses/>.\n\n/**\n * Screen reader-only (sr-only) reactive mutations logger class.\n *\n * This logger can be used by the StateManager to log mutation feedbacks and actions.\n * The feedback messages logged by this logger will be rendered in a sr-only, ARIA live region.\n *\n * @module core/local/reactive/srlogger\n * @class SRLogger\n * @copyright 2023 Jun Pataleta <jun@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Logger from 'core/local/reactive/logger';\n\n/**\n * Logger entry structure.\n *\n * @typedef {object} LoggerEntry\n * @property {string} feedbackMessage Feedback message.\n */\n\n/**\n * Screen reader-only (sr-only) reactive mutations logger class.\n *\n * @class SRLogger\n */\nexport default class SRLogger extends Logger {\n /**\n * The element ID of the ARIA live region where the logger feedback will be rendered.\n *\n * @type {string}\n */\n static liveRegionId = 'sr-logger-feedback-container';\n\n /**\n * Add a log entry.\n * @param {LoggerEntry} entry Log entry.\n */\n add(entry) {\n if (entry.feedbackMessage) {\n // Fetch or create an ARIA live region that will serve as the container for the logger feedback.\n let loggerFeedback = document.getElementById(SRLogger.liveRegionId);\n if (!loggerFeedback) {\n loggerFeedback = document.createElement('div');\n loggerFeedback.id = SRLogger.liveRegionId;\n loggerFeedback.classList.add('sr-only');\n loggerFeedback.setAttribute('aria-live', 'polite');\n document.body.append(loggerFeedback);\n }\n // Set the ARIA live region's contents with the feedback.\n loggerFeedback.innerHTML = entry.feedbackMessage;\n\n // Clear the feedback message after 4 seconds to avoid the contents from being read out in case the user navigates\n // to this region. This is similar to the default timeout of toast messages before disappearing from view.\n setTimeout(() => {\n loggerFeedback.innerHTML = '';\n }, 4000);\n }\n }\n}\n"],"names":["SRLogger","Logger","add","entry","feedbackMessage","loggerFeedback","document","getElementById","liveRegionId","createElement","id","classList","setAttribute","body","append","innerHTML","setTimeout"],"mappings":"iQAyCqBA,iBAAiBC,gBAYlCC,IAAIC,UACIA,MAAMC,gBAAiB,KAEnBC,eAAiBC,SAASC,eAAeP,SAASQ,cACjDH,iBACDA,eAAiBC,SAASG,cAAc,OACxCJ,eAAeK,GAAKV,SAASQ,aAC7BH,eAAeM,UAAUT,IAAI,WAC7BG,eAAeO,aAAa,YAAa,UACzCN,SAASO,KAAKC,OAAOT,iBAGzBA,eAAeU,UAAYZ,MAAMC,gBAIjCY,YAAW,KACPX,eAAeU,UAAY,KAC5B,kLA9BMf,wBAMK"}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
60
lib/amd/src/local/reactive/logger.js
Normal file
60
lib/amd/src/local/reactive/logger.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// This file is part of Moodle - http://moodle.org/
|
||||||
|
//
|
||||||
|
// Moodle is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Moodle is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default reactive mutations logger class.
|
||||||
|
*
|
||||||
|
* This logger is used by default by the StateManager to log mutation feedbacks
|
||||||
|
* and actions. By default, feedbacks will be displayed as a toast. However, the
|
||||||
|
* reactive instance can provide alternative loggers to provide advanced logging
|
||||||
|
* capabilities.
|
||||||
|
*
|
||||||
|
* @module core/local/reactive/logger
|
||||||
|
* @class Logger
|
||||||
|
* @copyright 2023 Ferran Recio <ferran@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger entry structure.
|
||||||
|
*
|
||||||
|
* @typedef {object} LoggerEntry
|
||||||
|
* @property {string} feedbackMessage Feedback message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {add as addToast} from 'core/toast';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default reactive mutations logger class.
|
||||||
|
* @class Logger
|
||||||
|
*/
|
||||||
|
export default class Logger {
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this._debug = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a log entry.
|
||||||
|
* @param {LoggerEntry} entry Log entry.
|
||||||
|
*/
|
||||||
|
add(entry) {
|
||||||
|
if (entry.feedbackMessage) {
|
||||||
|
addToast(entry.feedbackMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
lib/amd/src/local/reactive/srlogger.js
Normal file
75
lib/amd/src/local/reactive/srlogger.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
// This file is part of Moodle - http://moodle.org/
|
||||||
|
//
|
||||||
|
// Moodle is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Moodle is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen reader-only (sr-only) reactive mutations logger class.
|
||||||
|
*
|
||||||
|
* This logger can be used by the StateManager to log mutation feedbacks and actions.
|
||||||
|
* The feedback messages logged by this logger will be rendered in a sr-only, ARIA live region.
|
||||||
|
*
|
||||||
|
* @module core/local/reactive/srlogger
|
||||||
|
* @class SRLogger
|
||||||
|
* @copyright 2023 Jun Pataleta <jun@moodle.com>
|
||||||
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Logger from 'core/local/reactive/logger';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logger entry structure.
|
||||||
|
*
|
||||||
|
* @typedef {object} LoggerEntry
|
||||||
|
* @property {string} feedbackMessage Feedback message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen reader-only (sr-only) reactive mutations logger class.
|
||||||
|
*
|
||||||
|
* @class SRLogger
|
||||||
|
*/
|
||||||
|
export default class SRLogger extends Logger {
|
||||||
|
/**
|
||||||
|
* The element ID of the ARIA live region where the logger feedback will be rendered.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
static liveRegionId = 'sr-logger-feedback-container';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a log entry.
|
||||||
|
* @param {LoggerEntry} entry Log entry.
|
||||||
|
*/
|
||||||
|
add(entry) {
|
||||||
|
if (entry.feedbackMessage) {
|
||||||
|
// Fetch or create an ARIA live region that will serve as the container for the logger feedback.
|
||||||
|
let loggerFeedback = document.getElementById(SRLogger.liveRegionId);
|
||||||
|
if (!loggerFeedback) {
|
||||||
|
loggerFeedback = document.createElement('div');
|
||||||
|
loggerFeedback.id = SRLogger.liveRegionId;
|
||||||
|
loggerFeedback.classList.add('sr-only');
|
||||||
|
loggerFeedback.setAttribute('aria-live', 'polite');
|
||||||
|
document.body.append(loggerFeedback);
|
||||||
|
}
|
||||||
|
// Set the ARIA live region's contents with the feedback.
|
||||||
|
loggerFeedback.innerHTML = entry.feedbackMessage;
|
||||||
|
|
||||||
|
// Clear the feedback message after 4 seconds to avoid the contents from being read out in case the user navigates
|
||||||
|
// to this region. This is similar to the default timeout of toast messages before disappearing from view.
|
||||||
|
setTimeout(() => {
|
||||||
|
loggerFeedback.innerHTML = '';
|
||||||
|
}, 4000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,8 @@
|
||||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Logger from 'core/local/reactive/logger';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State manager class.
|
* State manager class.
|
||||||
*
|
*
|
||||||
|
@ -120,6 +122,8 @@ export default class StateManager {
|
||||||
};
|
};
|
||||||
this.target.addEventListener('state:loaded', initialStateDone);
|
this.target.addEventListener('state:loaded', initialStateDone);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.logger = new Logger();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -443,6 +447,24 @@ export default class StateManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the logger class instance.
|
||||||
|
*
|
||||||
|
* Reactive instances can provide alternative loggers to provide advanced logging.
|
||||||
|
* @param {Logger} logger
|
||||||
|
*/
|
||||||
|
setLogger(logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new log entry into the reactive logger.
|
||||||
|
* @param {LoggerEntry} entry
|
||||||
|
*/
|
||||||
|
addLoggerEntry(entry) {
|
||||||
|
this.logger.add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an element from the state or form an alternative state object.
|
* Get an element from the state or form an alternative state object.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue