MDL-66074 mod_forum: Implement spinner for user change
[moodle.git] / mod / forum / amd / src / local / grades / grader.js
CommitLineData
bae67469
MM
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * This module will tie together all of the different calls the gradable module will make.
18 *
19 * @module mod_forum/local/grades/grader
20 * @package mod_forum
21 * @copyright 2019 Mathew May <mathew.solutions>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24import Templates from 'core/templates';
bae67469 25import Selectors from './local/grader/selectors';
45c0584c 26import getUserPicker from './local/grader/user_picker';
bae67469 27import {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';
f281c616 28import getGradingPanelFunctions from './local/grader/gradingpanel';
77ee8778
AN
29import {add as addToast} from 'core/toast';
30import {get_string as getString} from 'core/str';
bae67469
MM
31
32const templateNames = {
33 grader: {
34 app: 'mod_forum/local/grades/grader',
35 },
36};
37
38const displayUserPicker = (root, html) => {
39 const pickerRegion = root.querySelector(Selectors.regions.pickerRegion);
40 Templates.replaceNodeContents(pickerRegion, html, '');
41};
42
f281c616
AN
43const fetchContentFromRender = (html, js) => {
44 return [html, js];
45};
46
47const getUpdateUserContentFunction = (root, getContentForUser, getGradeForUser) => {
bae67469
MM
48 return async(user) => {
49 const [
f281c616
AN
50 [html, js],
51 userGrade,
bae67469 52 ] = await Promise.all([
f281c616
AN
53 getContentForUser(user.id).then(fetchContentFromRender),
54 getGradeForUser(user.id),
bae67469
MM
55 ]);
56 Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);
f281c616
AN
57
58 const [
59 gradingPanelHtml,
60 gradingPanelJS
61 ] = await Templates.render(userGrade.templatename, userGrade.grade).then(fetchContentFromRender);
62 Templates.replaceNodeContents(root.querySelector(Selectors.regions.gradingPanel), gradingPanelHtml, gradingPanelJS);
bae67469
MM
63 };
64};
65
eaee6477 66const registerEventListeners = (graderLayout, userPicker, saveGradeFunction) => {
bae67469
MM
67 const graderContainer = graderLayout.getContainer();
68 graderContainer.addEventListener('click', (e) => {
69 if (e.target.closest(Selectors.buttons.toggleFullscreen)) {
70 e.stopImmediatePropagation();
71 e.preventDefault();
72 graderLayout.toggleFullscreen();
eaee6477
AN
73
74 return;
75 }
76
77 if (e.target.closest(Selectors.buttons.closeGrader)) {
bae67469
MM
78 e.stopImmediatePropagation();
79 e.preventDefault();
80
81 graderLayout.close();
eaee6477
AN
82
83 return;
84 }
85
86 if (e.target.closest(Selectors.buttons.saveGrade)) {
87 saveGradeFunction(userPicker.currentUser);
bae67469
MM
88 }
89 });
90};
91
77ee8778
AN
92/**
93 * Get the function used to save a user grade.
94 *
95 * @param {Element} root The contaienr
96 * @param {Function} setGradeForUser The function that will be called.
97 * @return {Function}
98 */
f281c616 99const getSaveUserGradeFunction = (root, setGradeForUser) => {
77ee8778
AN
100 return async user => {
101 try {
102 const result = await setGradeForUser(user.id, root.querySelector(Selectors.regions.gradingPanel));
103 addToast(await getString('grades:gradesavedfor', 'mod_forum', user));
104
105 return result;
106 } catch (error) {
107 throw error;
108 }
f281c616
AN
109 };
110};
111
eaee6477
AN
112/**
113 * Launch the grader interface with the specified parameters.
114 *
115 * @param {Function} getListOfUsers A function to get the list of users
116 * @param {Function} getContentForUser A function to get the content for a specific user
117 * @param {Function} getGradeForUser A function get the grade details for a specific user
118 * @param {Function} setGradeForUser A function to set the grade for a specific user
119 */
f281c616 120export const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {
aa04b722 121 initialUserId = null, moduleName
bae67469
MM
122} = {}) => {
123
124 const [
125 graderLayout,
126 graderHTML,
127 userList,
128 ] = await Promise.all([
129 createFullScreenWindow({fullscreen: false, showLoader: false}),
d3b890f8 130 Templates.render(templateNames.grader.app, {moduleName: moduleName}),
bae67469
MM
131 getListOfUsers(),
132 ]);
133 const graderContainer = graderLayout.getContainer();
134
45c0584c
AN
135 const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser);
136
bae67469 137 Templates.replaceNodeContents(graderContainer, graderHTML, '');
f281c616
AN
138 const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);
139
45c0584c
AN
140 // Fetch the userpicker for display.
141 const userPicker = await getUserPicker(
f281c616 142 userList,
f281c616 143 updateUserContent,
aa04b722
AN
144 saveGradeFunction,
145 {
146 initialUserId,
147 },
f281c616 148 );
bae67469 149
eaee6477
AN
150 // Register all event listeners.
151 registerEventListeners(graderLayout, userPicker, saveGradeFunction);
152
45c0584c
AN
153 // Display the newly created user picker.
154 displayUserPicker(graderContainer, userPicker.rootNode);
bae67469 155};
f281c616
AN
156
157export {getGradingPanelFunctions};