};
};
+/**
+ * Register listeners to launch the grading panel.
+ */
export const registerLaunchListeners = () => {
- document.addEventListener('click', (e) => {
+ document.addEventListener('click', async(e) => {
if (e.target.matches(Selectors.launch)) {
const rootNode = findGradableNode(e.target);
}
if (rootNode.matches(Selectors.gradableItems.wholeForum)) {
- const wholeForumFunctions = getWholeForumFunctions(rootNode.dataset.cmid);
-
- Grader.launch(wholeForumFunctions.getUsers, wholeForumFunctions.getContentForUserId, {
- groupid: rootNode.dataset.groupid,
- initialUserId: rootNode.dataset.initialuserid,
- });
-
+ // Note: The preventDefault must be before any async function calls because the function becomes async
+ // at that point and the default action is implemented.
e.preventDefault();
+
+ const data = rootNode.dataset;
+ const wholeForumFunctions = getWholeForumFunctions(data.cmid);
+ const gradingPanelFunctions = await Grader.getGradingPanelFunctions(
+ 'mod_forum',
+ data.contextid,
+ data.gradingComponent,
+ data.gradingComponentSubtype,
+ data.gradableItemtype
+ );
+
+ Grader.launch(
+ wholeForumFunctions.getUsers,
+ wholeForumFunctions.getContentForUserId,
+ gradingPanelFunctions.getter,
+ gradingPanelFunctions.setter,
+ {
+ groupid: data.groupid,
+ initialUserId: data.initialuserid,
+ }
+ );
} else {
throw Error('Unable to find a valid gradable item');
}
import Selectors from './local/grader/selectors';
import * as UserPicker from './local/grader/user_picker';
import {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';
+import getGradingPanelFunctions from './local/grader/gradingpanel';
const templateNames = {
grader: {
Templates.replaceNodeContents(pickerRegion, html, '');
};
-const getUpdateUserContentFunction = (root, getContentForUser) => {
+const fetchContentFromRender = (html, js) => {
+ return [html, js];
+};
+
+const getUpdateUserContentFunction = (root, getContentForUser, getGradeForUser) => {
return async(user) => {
const [
- {html, js},
+ [html, js],
+ userGrade,
] = await Promise.all([
- getContentForUser(user.id).then((html, js) => {
- return {html, js};
- }),
+ getContentForUser(user.id).then(fetchContentFromRender),
+ getGradeForUser(user.id),
]);
Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);
+
+ const [
+ gradingPanelHtml,
+ gradingPanelJS
+ ] = await Templates.render(userGrade.templatename, userGrade.grade).then(fetchContentFromRender);
+ Templates.replaceNodeContents(root.querySelector(Selectors.regions.gradingPanel), gradingPanelHtml, gradingPanelJS);
};
};
});
};
+const getSaveUserGradeFunction = (root, setGradeForUser) => {
+ return user => {
+ return setGradeForUser(user.id, root.querySelector(Selectors.regions.gradingPanel));
+ };
+};
+
// Make this explicit rather than object
-export const launch = async(getListOfUsers, getContentForUser, {
+export const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {
initialUserId = 0,
} = {}) => {
Templates.replaceNodeContents(graderContainer, graderHTML, '');
registerEventListeners(graderLayout);
- const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser);
+ const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);
+
+ const pickerHTML = await UserPicker.buildPicker(
+ userList,
+ initialUserId,
+ updateUserContent,
+ getSaveUserGradeFunction(graderContainer, setGradeForUser)
+ );
- const pickerHTML = await UserPicker.buildPicker(userList, initialUserId, updateUserContent);
displayUserPicker(graderContainer, pickerHTML);
};
+
+export {getGradingPanelFunctions};
--- /dev/null
+// 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/>.
+
+/**
+ * Grading panel functions.
+ *
+ * @module mod_forum/local/grades/local/grader/gradingpnael
+ * @package mod_forum
+ * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Get the grade panel setter and getter for the current component.
+ *
+ * @param {String} component The component being graded
+ * @param {Number} context The contextid of the thing being graded
+ * @param {String} gradingComponent The thing providing the grading type
+ * @param {String} gradingSubtype The subtype fo the grading component
+ * @param {String} itemName The name of the thing being graded
+ * @return {Object}
+ */
+export default async(component, context, gradingComponent, gradingSubtype, itemName) => {
+ let gradingMethodHandler = `${gradingComponent}/grades/grader/gradingpanel`;
+ if (gradingSubtype) {
+ gradingMethodHandler += `/${gradingSubtype}`;
+ }
+
+ const GradingMethod = await import(gradingMethodHandler);
+
+ return {
+ getter: userId => GradingMethod.fetchCurrentGrade(component, context, itemName, userId),
+ setter: (userId, formData) => GradingMethod.storeCurrentGrade(component, context, itemName, userId, formData),
+ };
+};
+
regions: {
moduleReplace: getDataSelector('region', 'module_content'),
pickerRegion: getDataSelector('region', 'user_picker'),
+ gradingPanel: getDataSelector('region', 'grade'),
},
};
Templates.replaceNodeContents(userRegion, html, '');
};
-const bindEvents = (root, users, currentUserIndex, showUserCallback) => {
+const bindEvents = (root, users, currentUserIndex, showUserCallback, saveUserCallback) => {
root.addEventListener('click', (e) => {
const button = e.target.closest(Selectors.actions.changeUser);
if (button) {
+ saveUserCallback(users[currentUserIndex]);
currentUserIndex += parseInt(button.dataset.direction);
showUser(root, users, currentUserIndex, showUserCallback);
}
});
};
-export const buildPicker = async(users, currentUserID, showUserCallback) => {
+export const buildPicker = async(users, currentUserID, showUserCallback, saveUserCallback) => {
let root = document.createElement('div');
const [html] = await Promise.all([renderNavigator()]);
await showUser(root, users, currentUserIndex, showUserCallback);
- bindEvents(root, users, currentUserIndex, showUserCallback);
+ bindEvents(root, users, currentUserIndex, showUserCallback, saveUserCallback);
return root;
};