Commit | Line | Data |
---|---|---|
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/grades/grader | |
20 | * @package mod_forum | |
21 | * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk> | |
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
23 | */ | |
24 | import * as Selectors from './grader/selectors'; | |
25 | import Repository from 'mod_forum/repository'; | |
26 | import Templates from 'core/templates'; | |
27 | import * as Grader from '../local/grades/grader'; | |
28 | import Notification from 'core/notification'; | |
29 | import CourseRepository from 'core_course/repository'; | |
4c98e56c | 30 | import {relativeUrl} from 'core/url'; |
bae67469 MM |
31 | |
32 | const templateNames = { | |
33 | contentRegion: 'mod_forum/grades/grader/discussion/posts', | |
34 | }; | |
35 | ||
046ebd3a MM |
36 | /** |
37 | * Curried function with CMID set, this is then used in unified grader as a fetch a users content. | |
38 | * | |
39 | * @param {Number} cmid | |
40 | * @return {Function} | |
41 | */ | |
42 | const getContentForUserIdFunction = (cmid) => (userid) => { | |
43 | /** | |
44 | * Given the parent function is called with the second param set execute the partially executed function. | |
45 | * | |
46 | * @param {Number} userid | |
47 | */ | |
48 | return Repository.getDiscussionByUserID(userid, cmid) | |
49 | .then(context => { | |
50 | // Rebuild the returned data for the template. | |
51 | context.discussions = context.discussions.map(discussionPostMapper); | |
52 | ||
53 | return Templates.render(templateNames.contentRegion, context); | |
54 | }) | |
55 | .catch(Notification.exception); | |
56 | }; | |
bae67469 | 57 | |
046ebd3a MM |
58 | /** |
59 | * Curried function with CMID set, this is then used in unified grader as a fetch users call. | |
60 | * The function curried fetches all users in a course for a given CMID. | |
61 | * | |
62 | * @param {Number} cmid | |
63 | * @return {Array} Array of users for a given context. | |
64 | */ | |
65 | const getUsersForCmidFunction = (cmid) => async() => { | |
66 | const context = await CourseRepository.getUsersFromCourseModuleID(cmid); | |
bae67469 | 67 | |
046ebd3a | 68 | return context.users; |
bae67469 MM |
69 | }; |
70 | ||
bae67469 | 71 | |
046ebd3a MM |
72 | const findGradableNode = node => node.closest(Selectors.gradableItem); |
73 | ||
74 | /** | |
75 | * For a discussion we need to manipulate it's posts to hide certain UI elements. | |
76 | * | |
77 | * @param {Object} discussion | |
78 | * @return {Array} name, id, posts | |
79 | */ | |
80 | const discussionPostMapper = (discussion) => { | |
bae67469 MM |
81 | // Map postid => post. |
82 | const parentMap = new Map(); | |
83 | discussion.posts.parentposts.forEach(post => parentMap.set(post.id, post)); | |
bae67469 MM |
84 | const userPosts = discussion.posts.userposts.map(post => { |
85 | post.subject = null; | |
86 | post.readonly = true; | |
87 | post.starter = !post.parentid; | |
88 | post.parent = parentMap.get(post.parentid); | |
046ebd3a | 89 | post.html.rating = null; |
bae67469 MM |
90 | |
91 | return post; | |
92 | }); | |
93 | ||
94 | return { | |
95 | id: discussion.id, | |
96 | name: discussion.name, | |
97 | posts: userPosts, | |
98 | }; | |
99 | }; | |
100 | ||
eaee6477 AN |
101 | /** |
102 | * Launch the Grader. | |
103 | * | |
104 | * @param {HTMLElement} rootNode the root HTML element describing what is to be graded | |
105 | */ | |
046ebd3a | 106 | const launchWholeForumGrading = async(rootNode) => { |
eaee6477 | 107 | const data = rootNode.dataset; |
eaee6477 AN |
108 | const gradingPanelFunctions = await Grader.getGradingPanelFunctions( |
109 | 'mod_forum', | |
110 | data.contextid, | |
111 | data.gradingComponent, | |
112 | data.gradingComponentSubtype, | |
113 | data.gradableItemtype | |
114 | ); | |
115 | ||
116 | await Grader.launch( | |
046ebd3a MM |
117 | getUsersForCmidFunction(data.cmid), |
118 | getContentForUserIdFunction(data.cmid), | |
eaee6477 AN |
119 | gradingPanelFunctions.getter, |
120 | gradingPanelFunctions.setter, | |
121 | { | |
122 | groupid: data.groupid, | |
123 | initialUserId: data.initialuserid, | |
4c98e56c RW |
124 | moduleName: data.name, |
125 | courseName: data.courseName, | |
126 | courseUrl: relativeUrl('/course/view.php', {id: data.courseId}) | |
eaee6477 AN |
127 | } |
128 | ); | |
129 | }; | |
130 | ||
f281c616 AN |
131 | /** |
132 | * Register listeners to launch the grading panel. | |
133 | */ | |
bae67469 | 134 | export const registerLaunchListeners = () => { |
046ebd3a | 135 | document.addEventListener('click', async(e) => { |
bae67469 MM |
136 | if (e.target.matches(Selectors.launch)) { |
137 | const rootNode = findGradableNode(e.target); | |
138 | ||
139 | if (!rootNode) { | |
140 | throw Error('Unable to find a gradable item'); | |
141 | } | |
142 | ||
143 | if (rootNode.matches(Selectors.gradableItems.wholeForum)) { | |
f281c616 AN |
144 | // Note: The preventDefault must be before any async function calls because the function becomes async |
145 | // at that point and the default action is implemented. | |
bae67469 | 146 | e.preventDefault(); |
eaee6477 AN |
147 | try { |
148 | await launchWholeForumGrading(rootNode); | |
149 | } catch (error) { | |
150 | Notification.exception(error); | |
151 | } | |
bae67469 MM |
152 | } else { |
153 | throw Error('Unable to find a valid gradable item'); | |
154 | } | |
155 | } | |
156 | }); | |
157 | }; |