Skip to content

Commit

Permalink
MDL-79061 core: Mechanism for logging mutation feedbacks
Browse files Browse the repository at this point in the history
* Create a mechanism for logging mutation feedbacks.
* The mutation feedbacks are displayed as a toast by default.
* Apply this logging mechanism on the course homepage to provide
feedback for the results of actions performed on course modules and
course sections.
  • Loading branch information
ferranrecio authored and junpataleta committed Dec 7, 2023
1 parent caacef2 commit 39f03ba
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 9 deletions.
4 changes: 2 additions & 2 deletions course/format/amd/build/local/courseeditor/mutations.min.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions course/format/amd/src/local/courseeditor/mutations.js
Expand Up @@ -14,6 +14,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

import ajax from 'core/ajax';
import {get_string as getString} from "core/str";

/**
* Default mutation manager
Expand Down Expand Up @@ -65,6 +66,11 @@ export default class {
* @param {number} targetCmId optional target cm id (for moving actions)
*/
async _sectionBasicAction(stateManager, action, sectionIds, targetSectionId, targetCmId) {
const logEntry = this._getLoggerEntry(stateManager, action, sectionIds, {
targetSectionId,
targetCmId,
itemType: 'section',
});
const course = stateManager.get('course');
this.sectionLock(stateManager, sectionIds, true);
const updates = await this._callEditWebservice(
Expand All @@ -77,6 +83,7 @@ export default class {
this.bulkReset(stateManager);
stateManager.processUpdates(updates);
this.sectionLock(stateManager, sectionIds, false);
stateManager.addLoggerEntry(await logEntry);
}

/**
Expand All @@ -88,6 +95,11 @@ export default class {
* @param {number} targetCmId optional target cm id (for moving actions)
*/
async _cmBasicAction(stateManager, action, cmIds, targetSectionId, targetCmId) {
const logEntry = this._getLoggerEntry(stateManager, action, cmIds, {
targetSectionId,
targetCmId,
itemType: 'cm',
});
const course = stateManager.get('course');
this.cmLock(stateManager, cmIds, true);
const updates = await this._callEditWebservice(
Expand All @@ -100,6 +112,51 @@ export default class {
this.bulkReset(stateManager);
stateManager.processUpdates(updates);
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 = {}) {
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,
};
}

/**
Expand Down Expand Up @@ -185,6 +242,7 @@ export default class {
* @param {number|undefined} targetCmId the target course module id
*/
async cmDuplicate(stateManager, cmIds, targetSectionId, targetCmId) {
const logEntry = this._getLoggerEntry(stateManager, 'cm_duplicate', cmIds);
const course = stateManager.get('course');
// Lock all target sections.
const sectionIds = new Set();
Expand All @@ -203,6 +261,7 @@ export default class {
stateManager.processUpdates(updates);

this.sectionLock(stateManager, Array.from(sectionIds), false);
stateManager.addLoggerEntry(await logEntry);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion course/format/topics/amd/build/mutations.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion course/format/topics/amd/build/mutations.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions course/format/topics/amd/src/mutations.js
Expand Up @@ -42,11 +42,19 @@ class TopicsMutations extends DefaultMutations {
* @param {array} sectionIds the list of section ids
*/
sectionHighlight = async function(stateManager, sectionIds) {
const logEntry = this._getLoggerEntry(
stateManager,
'section_highlight',
sectionIds,
{component: 'format_topics'}
);
const course = stateManager.get('course');
this.sectionLock(stateManager, sectionIds, true);
const updates = await this._callEditWebservice('section_highlight', course.id, sectionIds);
stateManager.processUpdates(updates);
this.sectionLock(stateManager, sectionIds, false);
stateManager.addLoggerEntry(await logEntry);

};

/**
Expand All @@ -59,11 +67,18 @@ class TopicsMutations extends DefaultMutations {
* @param {array} sectionIds the list of section ids
*/
sectionUnhighlight = async function(stateManager, sectionIds) {
const logEntry = this._getLoggerEntry(
stateManager,
'section_unhighlight',
sectionIds,
{component: 'format_topics'}
);
const course = stateManager.get('course');
this.sectionLock(stateManager, sectionIds, true);
const updates = await this._callEditWebservice('section_unhighlight', course.id, sectionIds);
stateManager.processUpdates(updates);
this.sectionLock(stateManager, sectionIds, false);
stateManager.addLoggerEntry(await logEntry);
};
}

Expand Down
2 changes: 2 additions & 0 deletions course/format/topics/lang/en/format_topics.php
Expand Up @@ -35,6 +35,8 @@
$string['privacy:metadata'] = 'The Topics format plugin does not store any personal data.';
$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['section_highlight_feedback'] = 'Section {$a->name} is highlighted.';
$string['section_unhighlight_feedback'] = 'Highlight removed from section {$a->name}.';
$string['section0name'] = 'General';
$string['sectionavailability_title'] = 'Topic availability';
$string['sectiondelete_title'] = 'Delete topic?';
Expand Down

0 comments on commit 39f03ba

Please sign in to comment.