diff --git a/mod/forum/amd/build/grades/grader.min.js b/mod/forum/amd/build/grades/grader.min.js
index d1ba5d53ccf..1c6d8eeb4d4 100644
--- a/mod/forum/amd/build/grades/grader.min.js
+++ b/mod/forum/amd/build/grades/grader.min.js
@@ -1,2 +1,2 @@
-define ("mod_forum/grades/grader",["exports","./grader/selectors","mod_forum/repository","core/templates","../local/grades/grader","core/notification","core_course/repository"],function(a,b,c,d,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.registerLaunchListeners=void 0;b=j(b);c=i(c);d=i(d);f=j(f);g=i(g);h=i(h);function i(a){return a&&a.__esModule?a:{default:a}}function j(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}var k={contentRegion:"mod_forum/grades/grader/discussion/posts"},l=function(a){var b=function(){return function(b){return c.default.getDiscussionByUserID(b,a)}};return{getContentForUserId:function getContentForUserIdFunction(){var c=b(a);return function(a){return c(a).then(function(a){a.discussions=a.discussions.map(n);return d.default.render(k.contentRegion,a)}).catch(g.default.exception)}}(),getUsers:function getUsersForCmidFunction(){return function(){return h.default.getUsersFromCourseModuleID(a).then(function(a){return a.users}).catch(g.default.exception)}}()}},m=function(a){return a.closest(b.gradableItem)},n=function(a){var b=new Map;a.posts.parentposts.forEach(function(a){return b.set(a.id,a)});var c=a.posts.userposts.map(function(a){a.subject=null;a.readonly=!0;a.starter=!a.parentid;a.parent=b.get(a.parentid);return a});return{id:a.id,name:a.name,posts:c}};a.registerLaunchListeners=function registerLaunchListeners(){document.addEventListener("click",function(a){if(a.target.matches(b.launch)){var c=m(a.target);if(!c){throw Error("Unable to find a gradable item")}if(c.matches(b.gradableItems.wholeForum)){var d=l(c.dataset.cmid);f.launch(d.getUsers,d.getContentForUserId,{groupid:c.dataset.groupid,initialUserId:c.dataset.initialuserid});a.preventDefault()}else{throw Error("Unable to find a valid gradable item")}}})}});
+define ("mod_forum/grades/grader",["exports","./grader/selectors","mod_forum/repository","core/templates","../local/grades/grader","core/notification","core_course/repository"],function(a,b,c,d,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.registerLaunchListeners=void 0;b=j(b);c=i(c);d=i(d);f=j(f);g=i(g);h=i(h);function i(a){return a&&a.__esModule?a:{default:a}}function j(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}function k(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function l(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){k(h,d,e,f,g,"next",a)}function g(a){k(h,d,e,f,g,"throw",a)}f(void 0)})}}var m={contentRegion:"mod_forum/grades/grader/discussion/posts"},n=function(a){var b=function(){return function(b){return c.default.getDiscussionByUserID(b,a)}};return{getContentForUserId:function getContentForUserIdFunction(){var c=b(a);return function(a){return c(a).then(function(a){a.discussions=a.discussions.map(p);return d.default.render(m.contentRegion,a)}).catch(g.default.exception)}}(),getUsers:function getUsersForCmidFunction(){return function(){return h.default.getUsersFromCourseModuleID(a).then(function(a){return a.users}).catch(g.default.exception)}}()}},o=function(a){return a.closest(b.gradableItem)},p=function(a){var b=new Map;a.posts.parentposts.forEach(function(a){return b.set(a.id,a)});var c=a.posts.userposts.map(function(a){a.subject=null;a.readonly=!0;a.starter=!a.parentid;a.parent=b.get(a.parentid);return a});return{id:a.id,name:a.name,posts:c}};a.registerLaunchListeners=function registerLaunchListeners(){document.addEventListener("click",function(){var a=l(regeneratorRuntime.mark(function a(c){var d,e,g,h;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:if(!c.target.matches(b.launch)){a.next=15;break}d=o(c.target);if(d){a.next=4;break}throw Error("Unable to find a gradable item");case 4:if(!d.matches(b.gradableItems.wholeForum)){a.next=14;break}c.preventDefault();e=d.dataset;g=n(e.cmid);a.next=10;return f.getGradingPanelFunctions("mod_forum",e.contextid,e.gradingComponent,e.gradingComponentSubtype,e.gradableItemtype);case 10:h=a.sent;f.launch(g.getUsers,g.getContentForUserId,h.getter,h.setter,{groupid:e.groupid,initialUserId:e.initialuserid});a.next=15;break;case 14:throw Error("Unable to find a valid gradable item");case 15:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}())}});
//# sourceMappingURL=grader.min.js.map
diff --git a/mod/forum/amd/build/grades/grader.min.js.map b/mod/forum/amd/build/grades/grader.min.js.map
index 1f3914be7af..e6430300e63 100644
--- a/mod/forum/amd/build/grades/grader.min.js.map
+++ b/mod/forum/amd/build/grades/grader.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../src/grades/grader.js"],"names":["templateNames","contentRegion","getWholeForumFunctions","cmid","getPostContextFunction","userid","Repository","getDiscussionByUserID","getContentForUserId","getContentForUserIdFunction","postContextFunction","then","context","discussions","map","discussionPostMapper","Templates","render","catch","Notification","exception","getUsers","getUsersForCmidFunction","CourseRepository","getUsersFromCourseModuleID","users","findGradableNode","node","closest","Selectors","gradableItem","discussion","parentMap","Map","posts","parentposts","forEach","post","set","id","userPosts","userposts","subject","readonly","starter","parentid","parent","get","name","registerLaunchListeners","document","addEventListener","e","target","matches","launch","rootNode","Error","gradableItems","wholeForum","wholeForumFunctions","dataset","Grader","groupid","initialUserId","initialuserid","preventDefault"],"mappings":"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","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 .\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/grades/grader\n * @package mod_forum\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport * as Selectors from './grader/selectors';\nimport Repository from 'mod_forum/repository';\nimport Templates from 'core/templates';\nimport * as Grader from '../local/grades/grader';\nimport Notification from 'core/notification';\nimport CourseRepository from 'core_course/repository';\n\nconst templateNames = {\n contentRegion: 'mod_forum/grades/grader/discussion/posts',\n};\n\nconst getWholeForumFunctions = (cmid) => {\n const getPostContextFunction = () => {\n return (userid) => {\n return Repository.getDiscussionByUserID(userid, cmid);\n };\n };\n\n const getContentForUserIdFunction = () => {\n const postContextFunction = getPostContextFunction(cmid);\n return userid => {\n return postContextFunction(userid)\n .then(context => {\n // Rebuild the returned data for the template.\n context.discussions = context.discussions.map(discussionPostMapper);\n\n return Templates.render(templateNames.contentRegion, context);\n })\n .catch(Notification.exception);\n };\n };\n\n const getUsersForCmidFunction = () => {\n return () => {\n return CourseRepository.getUsersFromCourseModuleID(cmid)\n .then((context) => {\n return context.users;\n })\n .catch(Notification.exception);\n };\n };\n\n return {\n getContentForUserId: getContentForUserIdFunction(),\n getUsers: getUsersForCmidFunction()\n };\n};\n\nconst findGradableNode = (node) => {\n return node.closest(Selectors.gradableItem);\n};\n\nconst discussionPostMapper = discussion => {\n // Map postid => post.\n const parentMap = new Map();\n discussion.posts.parentposts.forEach(post => parentMap.set(post.id, post));\n\n const userPosts = discussion.posts.userposts.map(post => {\n post.subject = null;\n post.readonly = true;\n post.starter = !post.parentid;\n post.parent = parentMap.get(post.parentid);\n\n return post;\n });\n\n return {\n id: discussion.id,\n name: discussion.name,\n posts: userPosts,\n };\n};\n\nexport const registerLaunchListeners = () => {\n document.addEventListener('click', (e) => {\n if (e.target.matches(Selectors.launch)) {\n const rootNode = findGradableNode(e.target);\n\n if (!rootNode) {\n throw Error('Unable to find a gradable item');\n }\n\n if (rootNode.matches(Selectors.gradableItems.wholeForum)) {\n const wholeForumFunctions = getWholeForumFunctions(rootNode.dataset.cmid);\n\n Grader.launch(wholeForumFunctions.getUsers, wholeForumFunctions.getContentForUserId, {\n groupid: rootNode.dataset.groupid,\n initialUserId: rootNode.dataset.initialuserid,\n });\n\n e.preventDefault();\n } else {\n throw Error('Unable to find a valid gradable item');\n }\n }\n });\n};\n"],"file":"grader.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../src/grades/grader.js"],"names":["templateNames","contentRegion","getWholeForumFunctions","cmid","getPostContextFunction","userid","Repository","getDiscussionByUserID","getContentForUserId","getContentForUserIdFunction","postContextFunction","then","context","discussions","map","discussionPostMapper","Templates","render","catch","Notification","exception","getUsers","getUsersForCmidFunction","CourseRepository","getUsersFromCourseModuleID","users","findGradableNode","node","closest","Selectors","gradableItem","discussion","parentMap","Map","posts","parentposts","forEach","post","set","id","userPosts","userposts","subject","readonly","starter","parentid","parent","get","name","registerLaunchListeners","document","addEventListener","e","target","matches","launch","rootNode","Error","gradableItems","wholeForum","preventDefault","data","dataset","wholeForumFunctions","Grader","getGradingPanelFunctions","contextid","gradingComponent","gradingComponentSubtype","gradableItemtype","gradingPanelFunctions","getter","setter","groupid","initialUserId","initialuserid"],"mappings":"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","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 .\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/grades/grader\n * @package mod_forum\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport * as Selectors from './grader/selectors';\nimport Repository from 'mod_forum/repository';\nimport Templates from 'core/templates';\nimport * as Grader from '../local/grades/grader';\nimport Notification from 'core/notification';\nimport CourseRepository from 'core_course/repository';\n\nconst templateNames = {\n contentRegion: 'mod_forum/grades/grader/discussion/posts',\n};\n\nconst getWholeForumFunctions = (cmid) => {\n const getPostContextFunction = () => {\n return (userid) => {\n return Repository.getDiscussionByUserID(userid, cmid);\n };\n };\n\n const getContentForUserIdFunction = () => {\n const postContextFunction = getPostContextFunction(cmid);\n return userid => {\n return postContextFunction(userid)\n .then(context => {\n // Rebuild the returned data for the template.\n context.discussions = context.discussions.map(discussionPostMapper);\n\n return Templates.render(templateNames.contentRegion, context);\n })\n .catch(Notification.exception);\n };\n };\n\n const getUsersForCmidFunction = () => {\n return () => {\n return CourseRepository.getUsersFromCourseModuleID(cmid)\n .then((context) => {\n return context.users;\n })\n .catch(Notification.exception);\n };\n };\n\n return {\n getContentForUserId: getContentForUserIdFunction(),\n getUsers: getUsersForCmidFunction()\n };\n};\n\nconst findGradableNode = (node) => {\n return node.closest(Selectors.gradableItem);\n};\n\nconst discussionPostMapper = discussion => {\n // Map postid => post.\n const parentMap = new Map();\n discussion.posts.parentposts.forEach(post => parentMap.set(post.id, post));\n\n const userPosts = discussion.posts.userposts.map(post => {\n post.subject = null;\n post.readonly = true;\n post.starter = !post.parentid;\n post.parent = parentMap.get(post.parentid);\n\n return post;\n });\n\n return {\n id: discussion.id,\n name: discussion.name,\n posts: userPosts,\n };\n};\n\n/**\n * Register listeners to launch the grading panel.\n */\nexport const registerLaunchListeners = () => {\n document.addEventListener('click', async(e) => {\n if (e.target.matches(Selectors.launch)) {\n const rootNode = findGradableNode(e.target);\n\n if (!rootNode) {\n throw Error('Unable to find a gradable item');\n }\n\n if (rootNode.matches(Selectors.gradableItems.wholeForum)) {\n // Note: The preventDefault must be before any async function calls because the function becomes async\n // at that point and the default action is implemented.\n e.preventDefault();\n\n const data = rootNode.dataset;\n const wholeForumFunctions = getWholeForumFunctions(data.cmid);\n const gradingPanelFunctions = await Grader.getGradingPanelFunctions(\n 'mod_forum',\n data.contextid,\n data.gradingComponent,\n data.gradingComponentSubtype,\n data.gradableItemtype\n );\n\n Grader.launch(\n wholeForumFunctions.getUsers,\n wholeForumFunctions.getContentForUserId,\n gradingPanelFunctions.getter,\n gradingPanelFunctions.setter,\n {\n groupid: data.groupid,\n initialUserId: data.initialuserid,\n }\n );\n } else {\n throw Error('Unable to find a valid gradable item');\n }\n }\n });\n};\n"],"file":"grader.min.js"}
\ No newline at end of file
diff --git a/mod/forum/amd/build/local/grades/grader.min.js b/mod/forum/amd/build/local/grades/grader.min.js
index d140999c677..9a7b35d2e91 100644
--- a/mod/forum/amd/build/local/grades/grader.min.js
+++ b/mod/forum/amd/build/local/grades/grader.min.js
@@ -1,2 +1,2 @@
-define ("mod_forum/local/grades/grader",["exports","core/templates","./local/grader/selectors","./local/grader/user_picker","mod_forum/local/layout/fullscreen"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.launch=void 0;b=f(b);c=f(c);d=function(a){if(a&&a.__esModule){return a}else{var b={};if(null!=a){for(var c in a){if(Object.prototype.hasOwnProperty.call(a,c)){var d=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(a,c):{};if(d.get||d.set){Object.defineProperty(b,c,d)}else{b[c]=a[c]}}}}b.default=a;return b}}(d);function f(a){return a&&a.__esModule?a:{default:a}}function g(a,b){return k(a)||j(a,b)||h()}function h(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function j(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function k(a){if(Array.isArray(a))return a}function l(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function m(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){l(h,d,e,f,g,"next",a)}function g(a){l(h,d,e,f,g,"throw",a)}f(void 0)})}}var n={grader:{app:"mod_forum/local/grades/grader"}},o=function(a,d){var e=a.querySelector(c.default.regions.pickerRegion);b.default.replaceNodeContents(e,d,"")},p=function(a,d){return function(){var e=m(regeneratorRuntime.mark(function e(f){var h,i,j,k,l;return regeneratorRuntime.wrap(function(e){while(1){switch(e.prev=e.next){case 0:e.next=2;return Promise.all([d(f.id).then(function(a,b){return{html:a,js:b}})]);case 2:h=e.sent;i=g(h,1);j=i[0];k=j.html;l=j.js;b.default.replaceNodeContents(a.querySelector(c.default.regions.moduleReplace),k,l);case 8:case"end":return e.stop();}}},e)}));return function(){return e.apply(this,arguments)}}()},q=function(a){var b=a.getContainer();b.addEventListener("click",function(b){if(b.target.closest(c.default.buttons.toggleFullscreen)){b.stopImmediatePropagation();b.preventDefault();a.toggleFullscreen()}else if(b.target.closest(c.default.buttons.closeGrader)){b.stopImmediatePropagation();b.preventDefault();a.close()}})},r=function(){var a=m(regeneratorRuntime.mark(function a(c,f){var h,i,j,k,l,m,r,s,t,u,v,w=arguments;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:h=2.\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/local/grades/grader\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Templates from 'core/templates';\n// TODO import Notification from 'core/notification';\nimport Selectors from './local/grader/selectors';\nimport * as UserPicker from './local/grader/user_picker';\nimport {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';\n\nconst templateNames = {\n grader: {\n app: 'mod_forum/local/grades/grader',\n },\n};\n\nconst displayUserPicker = (root, html) => {\n const pickerRegion = root.querySelector(Selectors.regions.pickerRegion);\n Templates.replaceNodeContents(pickerRegion, html, '');\n};\n\nconst getUpdateUserContentFunction = (root, getContentForUser) => {\n return async(user) => {\n const [\n {html, js},\n ] = await Promise.all([\n getContentForUser(user.id).then((html, js) => {\n return {html, js};\n }),\n ]);\n Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);\n };\n};\n\nconst registerEventListeners = (graderLayout) => {\n const graderContainer = graderLayout.getContainer();\n graderContainer.addEventListener('click', (e) => {\n if (e.target.closest(Selectors.buttons.toggleFullscreen)) {\n e.stopImmediatePropagation();\n e.preventDefault();\n graderLayout.toggleFullscreen();\n } else if (e.target.closest(Selectors.buttons.closeGrader)) {\n e.stopImmediatePropagation();\n e.preventDefault();\n\n graderLayout.close();\n }\n });\n};\n\n// Make this explicit rather than object\nexport const launch = async(getListOfUsers, getContentForUser, {\n initialUserId = 0,\n} = {}) => {\n\n const [\n graderLayout,\n graderHTML,\n userList,\n ] = await Promise.all([\n createFullScreenWindow({fullscreen: false, showLoader: false}),\n Templates.render(templateNames.grader.app, {}),\n getListOfUsers(),\n ]);\n const graderContainer = graderLayout.getContainer();\n\n Templates.replaceNodeContents(graderContainer, graderHTML, '');\n registerEventListeners(graderLayout);\n const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser);\n\n const pickerHTML = await UserPicker.buildPicker(userList, initialUserId, updateUserContent);\n displayUserPicker(graderContainer, pickerHTML);\n};\n"],"file":"grader.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../src/local/grades/grader.js"],"names":["templateNames","grader","app","displayUserPicker","root","html","pickerRegion","querySelector","Selectors","regions","Templates","replaceNodeContents","fetchContentFromRender","js","getUpdateUserContentFunction","getContentForUser","getGradeForUser","user","Promise","all","id","then","userGrade","moduleReplace","render","templatename","grade","gradingPanelHtml","gradingPanelJS","gradingPanel","registerEventListeners","graderLayout","graderContainer","getContainer","addEventListener","e","target","closest","buttons","toggleFullscreen","stopImmediatePropagation","preventDefault","closeGrader","close","getSaveUserGradeFunction","setGradeForUser","launch","getListOfUsers","initialUserId","fullscreen","showLoader","graderHTML","userList","updateUserContent","UserPicker","buildPicker","pickerHTML"],"mappings":"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","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 .\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/local/grades/grader\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport Templates from 'core/templates';\n// TODO import Notification from 'core/notification';\nimport Selectors from './local/grader/selectors';\nimport * as UserPicker from './local/grader/user_picker';\nimport {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';\nimport getGradingPanelFunctions from './local/grader/gradingpanel';\n\nconst templateNames = {\n grader: {\n app: 'mod_forum/local/grades/grader',\n },\n};\n\nconst displayUserPicker = (root, html) => {\n const pickerRegion = root.querySelector(Selectors.regions.pickerRegion);\n Templates.replaceNodeContents(pickerRegion, html, '');\n};\n\nconst fetchContentFromRender = (html, js) => {\n return [html, js];\n};\n\nconst getUpdateUserContentFunction = (root, getContentForUser, getGradeForUser) => {\n return async(user) => {\n const [\n [html, js],\n userGrade,\n ] = await Promise.all([\n getContentForUser(user.id).then(fetchContentFromRender),\n getGradeForUser(user.id),\n ]);\n Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);\n\n const [\n gradingPanelHtml,\n gradingPanelJS\n ] = await Templates.render(userGrade.templatename, userGrade.grade).then(fetchContentFromRender);\n Templates.replaceNodeContents(root.querySelector(Selectors.regions.gradingPanel), gradingPanelHtml, gradingPanelJS);\n };\n};\n\nconst registerEventListeners = (graderLayout) => {\n const graderContainer = graderLayout.getContainer();\n graderContainer.addEventListener('click', (e) => {\n if (e.target.closest(Selectors.buttons.toggleFullscreen)) {\n e.stopImmediatePropagation();\n e.preventDefault();\n graderLayout.toggleFullscreen();\n } else if (e.target.closest(Selectors.buttons.closeGrader)) {\n e.stopImmediatePropagation();\n e.preventDefault();\n\n graderLayout.close();\n }\n });\n};\n\nconst getSaveUserGradeFunction = (root, setGradeForUser) => {\n return user => {\n return setGradeForUser(user.id, root.querySelector(Selectors.regions.gradingPanel));\n };\n};\n\n// Make this explicit rather than object\nexport const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {\n initialUserId = 0,\n} = {}) => {\n\n const [\n graderLayout,\n graderHTML,\n userList,\n ] = await Promise.all([\n createFullScreenWindow({fullscreen: false, showLoader: false}),\n Templates.render(templateNames.grader.app, {}),\n getListOfUsers(),\n ]);\n const graderContainer = graderLayout.getContainer();\n\n Templates.replaceNodeContents(graderContainer, graderHTML, '');\n registerEventListeners(graderLayout);\n const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);\n\n const pickerHTML = await UserPicker.buildPicker(\n userList,\n initialUserId,\n updateUserContent,\n getSaveUserGradeFunction(graderContainer, setGradeForUser)\n );\n\n displayUserPicker(graderContainer, pickerHTML);\n};\n\nexport {getGradingPanelFunctions};\n"],"file":"grader.min.js"}
\ No newline at end of file
diff --git a/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js b/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js
new file mode 100644
index 00000000000..f3cd71291f0
--- /dev/null
+++ b/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js
@@ -0,0 +1,2 @@
+define ("mod_forum/local/grades/local/grader/gradingpanel",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var d="undefined"!=typeof window?window:"undefined"!=typeof self?self:"undefined"!=typeof global?global:{};function b(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function c(a){return function(){var c=this,d=arguments;return new Promise(function(e,f){var i=a.apply(c,d);function g(a){b(i,e,f,g,h,"next",a)}function h(a){b(i,e,f,g,h,"throw",a)}g(void 0)})}}var e=function(){var a=c(regeneratorRuntime.mark(function a(b,c,e,f,g){var h,i;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:h="".concat(e,"/grades/grader/gradingpanel");if(f){h+="/".concat(f)}a.next=4;return"function"==typeof d.define&&d.define.amd?new Promise(function(a,b){d.require([h],a,b)}):"undefined"!=typeof module&&module.exports&&"undefined"!=typeof require||"undefined"!=typeof module&&module.component&&d.require&&"component"===d.require.loader?Promise.resolve(require((h))):Promise.resolve(d[h]);case 4:i=a.sent;return a.abrupt("return",{getter:function(a){return i.fetchCurrentGrade(b,c,g,a)},setter:function(a,d){return i.storeCurrentGrade(b,c,g,a,d)}});case 6:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.default=e;return a.default});
+//# sourceMappingURL=gradingpanel.min.js.map
diff --git a/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js.map b/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js.map
new file mode 100644
index 00000000000..a0b91126f66
--- /dev/null
+++ b/mod/forum/amd/build/local/grades/local/grader/gradingpanel.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../../../../src/local/grades/local/grader/gradingpanel.js"],"names":["component","context","gradingComponent","gradingSubtype","itemName","gradingMethodHandler","GradingMethod","getter","userId","fetchCurrentGrade","setter","formData","storeCurrentGrade"],"mappings":"6nBAkCe,WAAMA,CAAN,CAAiBC,CAAjB,CAA0BC,CAA1B,CAA4CC,CAA5C,CAA4DC,CAA5D,2FACPC,CADO,WACmBH,CADnB,gCAEX,GAAIC,CAAJ,CAAoB,CAChBE,CAAoB,aAAQF,CAAR,CACvB,CAJU,8FAMwBE,CANxB,mMAMwBA,CANxB,sBAMwBA,CANxB,UAMLC,CANK,iCAQJ,CACHC,MAAM,CAAE,SAAAC,CAAM,QAAIF,CAAAA,CAAa,CAACG,iBAAd,CAAgCT,CAAhC,CAA2CC,CAA3C,CAAoDG,CAApD,CAA8DI,CAA9D,CAAJ,CADX,CAEHE,MAAM,CAAE,SAACF,CAAD,CAASG,CAAT,QAAsBL,CAAAA,CAAa,CAACM,iBAAd,CAAgCZ,CAAhC,CAA2CC,CAA3C,CAAoDG,CAApD,CAA8DI,CAA9D,CAAsEG,CAAtE,CAAtB,CAFL,CARI,0C","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 .\n\n/**\n * Grading panel functions.\n *\n * @module mod_forum/local/grades/local/grader/gradingpnael\n * @package mod_forum\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Get the grade panel setter and getter for the current component.\n *\n * @param {String} component The component being graded\n * @param {Number} context The contextid of the thing being graded\n * @param {String} gradingComponent The thing providing the grading type\n * @param {String} gradingSubtype The subtype fo the grading component\n * @param {String} itemName The name of the thing being graded\n * @return {Object}\n */\nexport default async(component, context, gradingComponent, gradingSubtype, itemName) => {\n let gradingMethodHandler = `${gradingComponent}/grades/grader/gradingpanel`;\n if (gradingSubtype) {\n gradingMethodHandler += `/${gradingSubtype}`;\n }\n\n const GradingMethod = await import(gradingMethodHandler);\n\n return {\n getter: userId => GradingMethod.fetchCurrentGrade(component, context, itemName, userId),\n setter: (userId, formData) => GradingMethod.storeCurrentGrade(component, context, itemName, userId, formData),\n };\n};\n\n"],"file":"gradingpanel.min.js"}
\ No newline at end of file
diff --git a/mod/forum/amd/build/local/grades/local/grader/selectors.min.js b/mod/forum/amd/build/local/grades/local/grader/selectors.min.js
index e0cdf7daabe..2c1440db8be 100644
--- a/mod/forum/amd/build/local/grades/local/grader/selectors.min.js
+++ b/mod/forum/amd/build/local/grades/local/grader/selectors.min.js
@@ -1,2 +1,2 @@
-define ("mod_forum/local/grades/local/grader/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b=function(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")},c={buttons:{toggleFullscreen:b("action","togglefullscreen"),closeGrader:b("action","closegrader")},regions:{moduleReplace:b("region","module_content"),pickerRegion:b("region","user_picker")}};a.default=c;return a.default});
+define ("mod_forum/local/grades/local/grader/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;var b=function(a,b){return"[data-".concat(a,"=\"").concat(b,"\"]")},c={buttons:{toggleFullscreen:b("action","togglefullscreen"),closeGrader:b("action","closegrader")},regions:{moduleReplace:b("region","module_content"),pickerRegion:b("region","user_picker"),gradingPanel:b("region","grade")}};a.default=c;return a.default});
//# sourceMappingURL=selectors.min.js.map
diff --git a/mod/forum/amd/build/local/grades/local/grader/selectors.min.js.map b/mod/forum/amd/build/local/grades/local/grader/selectors.min.js.map
index c5f76885df9..d3dfc8f963d 100644
--- a/mod/forum/amd/build/local/grades/local/grader/selectors.min.js.map
+++ b/mod/forum/amd/build/local/grades/local/grader/selectors.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../../../../../src/local/grades/local/grader/selectors.js"],"names":["getDataSelector","name","value","buttons","toggleFullscreen","closeGrader","regions","moduleReplace","pickerRegion"],"mappings":"kKAwBMA,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAOC,CAAP,CAAiB,CACrC,sBAAgBD,CAAhB,eAAyBC,CAAzB,OACH,C,GAEc,CACXC,OAAO,CAAE,CACLC,gBAAgB,CAAEJ,CAAe,CAAC,QAAD,CAAW,kBAAX,CAD5B,CAELK,WAAW,CAAEL,CAAe,CAAC,QAAD,CAAW,aAAX,CAFvB,CADE,CAKXM,OAAO,CAAE,CACLC,aAAa,CAAEP,CAAe,CAAC,QAAD,CAAW,gBAAX,CADzB,CAELQ,YAAY,CAAER,CAAe,CAAC,QAAD,CAAW,aAAX,CAFxB,CALE,C","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 .\n\n/**\n * Define all of the selectors we will be using on the grading interface.\n *\n * @module mod_forum/local/grades/local/grader/selectors\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n buttons: {\n toggleFullscreen: getDataSelector('action', 'togglefullscreen'),\n closeGrader: getDataSelector('action', 'closegrader'),\n },\n regions: {\n moduleReplace: getDataSelector('region', 'module_content'),\n pickerRegion: getDataSelector('region', 'user_picker'),\n },\n};\n\n"],"file":"selectors.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../../../src/local/grades/local/grader/selectors.js"],"names":["getDataSelector","name","value","buttons","toggleFullscreen","closeGrader","regions","moduleReplace","pickerRegion","gradingPanel"],"mappings":"kKAwBMA,CAAAA,CAAe,CAAG,SAACC,CAAD,CAAOC,CAAP,CAAiB,CACrC,sBAAgBD,CAAhB,eAAyBC,CAAzB,OACH,C,GAEc,CACXC,OAAO,CAAE,CACLC,gBAAgB,CAAEJ,CAAe,CAAC,QAAD,CAAW,kBAAX,CAD5B,CAELK,WAAW,CAAEL,CAAe,CAAC,QAAD,CAAW,aAAX,CAFvB,CADE,CAKXM,OAAO,CAAE,CACLC,aAAa,CAAEP,CAAe,CAAC,QAAD,CAAW,gBAAX,CADzB,CAELQ,YAAY,CAAER,CAAe,CAAC,QAAD,CAAW,aAAX,CAFxB,CAGLS,YAAY,CAAET,CAAe,CAAC,QAAD,CAAW,OAAX,CAHxB,CALE,C","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 .\n\n/**\n * Define all of the selectors we will be using on the grading interface.\n *\n * @module mod_forum/local/grades/local/grader/selectors\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n buttons: {\n toggleFullscreen: getDataSelector('action', 'togglefullscreen'),\n closeGrader: getDataSelector('action', 'closegrader'),\n },\n regions: {\n moduleReplace: getDataSelector('region', 'module_content'),\n pickerRegion: getDataSelector('region', 'user_picker'),\n gradingPanel: getDataSelector('region', 'grade'),\n },\n};\n\n"],"file":"selectors.min.js"}
\ No newline at end of file
diff --git a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
index 4b3772b5418..93e39935457 100644
--- a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
+++ b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js
@@ -1,2 +1,2 @@
-define ("mod_forum/local/grades/local/grader/user_picker",["exports","core/templates","./user_picker/selectors"],function(a,b,c){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.buildPicker=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a,b){return h(a)||g(a,b)||f()}function f(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function g(a,b){var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function h(a){if(Array.isArray(a))return a}function i(a){for(var b=1;b.\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/local/grades/local/grader/user_picker\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Selectors from './user_picker/selectors';\n\nconst renderNavigator = () => {\n return Templates.render('mod_forum/local/grades/local/grader/user_picker', {});\n};\n\nconst renderUserChange = (context) => {\n return Templates.render('mod_forum/local/grades/local/grader/user_picker/user', context);\n};\n\nconst showUser = async(root, users, currentUserIndex, showUserCallback) => {\n const user = {\n ...users[currentUserIndex],\n total: users.length,\n displayIndex: currentUserIndex + 1,\n };\n const [html] = await Promise.all([renderUserChange(user), showUserCallback(user)]);\n const userRegion = root.querySelector(Selectors.regions.userRegion);\n Templates.replaceNodeContents(userRegion, html, '');\n};\n\nconst bindEvents = (root, users, currentUserIndex, showUserCallback) => {\n root.addEventListener('click', (e) => {\n const button = e.target.closest(Selectors.actions.changeUser);\n if (button) {\n currentUserIndex += parseInt(button.dataset.direction);\n showUser(root, users, currentUserIndex, showUserCallback);\n }\n });\n};\n\nexport const buildPicker = async(users, currentUserID, showUserCallback) => {\n let root = document.createElement('div');\n\n const [html] = await Promise.all([renderNavigator()]);\n Templates.replaceNodeContents(root, html, '');\n\n const currentUserIndex = users.findIndex((user) => {\n return user.id === parseInt(currentUserID);\n });\n\n await showUser(root, users, currentUserIndex, showUserCallback);\n\n bindEvents(root, users, currentUserIndex, showUserCallback);\n\n return root;\n};\n"],"file":"user_picker.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../../../../../src/local/grades/local/grader/user_picker.js"],"names":["renderNavigator","Templates","render","renderUserChange","context","showUser","root","users","currentUserIndex","showUserCallback","user","total","length","displayIndex","Promise","all","html","userRegion","querySelector","Selectors","regions","replaceNodeContents","bindEvents","saveUserCallback","addEventListener","e","button","target","closest","actions","changeUser","parseInt","dataset","direction","buildPicker","currentUserID","document","createElement","findIndex","id"],"mappings":"oNAwBA,OACA,O,ouCAEMA,CAAAA,CAAe,CAAG,UAAM,CAC1B,MAAOC,WAAUC,MAAV,CAAiB,iDAAjB,CAAoE,EAApE,CACV,C,CAEKC,CAAgB,CAAG,SAACC,CAAD,CAAa,CAClC,MAAOH,WAAUC,MAAV,CAAiB,sDAAjB,CAAyEE,CAAzE,CACV,C,CAEKC,CAAQ,4CAAG,WAAMC,CAAN,CAAYC,CAAZ,CAAmBC,CAAnB,CAAqCC,CAArC,iGACPC,CADO,MAENH,CAAK,CAACC,CAAD,CAFC,EAGTG,KAAK,CAAEJ,CAAK,CAACK,MAHJ,CAITC,YAAY,CAAEL,CAAgB,CAAG,CAJxB,kBAMQM,CAAAA,OAAO,CAACC,GAAR,CAAY,CAACZ,CAAgB,CAACO,CAAD,CAAjB,CAAyBD,CAAgB,CAACC,CAAD,CAAzC,CAAZ,CANR,0BAMNM,CANM,MAOPC,CAPO,CAOMX,CAAI,CAACY,aAAL,CAAmBC,UAAUC,OAAV,CAAkBH,UAArC,CAPN,CAQbhB,UAAUoB,mBAAV,CAA8BJ,CAA9B,CAA0CD,CAA1C,CAAgD,EAAhD,EARa,wCAAH,uD,CAWRM,CAAU,CAAG,SAAChB,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CAAkDc,CAAlD,CAAuE,CACtFjB,CAAI,CAACkB,gBAAL,CAAsB,OAAtB,CAA+B,SAACC,CAAD,CAAO,CAClC,GAAMC,CAAAA,CAAM,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBT,UAAUU,OAAV,CAAkBC,UAAnC,CAAf,CACA,GAAIJ,CAAJ,CAAY,CACRH,CAAgB,CAAChB,CAAK,CAACC,CAAD,CAAN,CAAhB,CACAA,CAAgB,EAAIuB,QAAQ,CAACL,CAAM,CAACM,OAAP,CAAeC,SAAhB,CAA5B,CACA5B,CAAQ,CAACC,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CACX,CACJ,CAPD,CAQH,C,CAEYyB,CAAW,4CAAG,WAAM3B,CAAN,CAAa4B,CAAb,CAA4B1B,CAA5B,CAA8Cc,CAA9C,iGACnBjB,CADmB,CACZ8B,QAAQ,CAACC,aAAT,CAAuB,KAAvB,CADY,gBAGFvB,CAAAA,OAAO,CAACC,GAAR,CAAY,CAACf,CAAe,EAAhB,CAAZ,CAHE,0BAGhBgB,CAHgB,MAIvBf,UAAUoB,mBAAV,CAA8Bf,CAA9B,CAAoCU,CAApC,CAA0C,EAA1C,EAEMR,CANiB,CAMED,CAAK,CAAC+B,SAAN,CAAgB,SAAC5B,CAAD,CAAU,CAC/C,MAAOA,CAAAA,CAAI,CAAC6B,EAAL,GAAYR,QAAQ,CAACI,CAAD,CAC9B,CAFwB,CANF,iBAUjB9B,CAAAA,CAAQ,CAACC,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CAVS,SAYvBa,CAAU,CAAChB,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CAAkDc,CAAlD,CAAV,CAZuB,yBAchBjB,CAdgB,2CAAH,uD","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 .\n\n/**\n * This module will tie together all of the different calls the gradable module will make.\n *\n * @module mod_forum/local/grades/local/grader/user_picker\n * @package mod_forum\n * @copyright 2019 Mathew May \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Selectors from './user_picker/selectors';\n\nconst renderNavigator = () => {\n return Templates.render('mod_forum/local/grades/local/grader/user_picker', {});\n};\n\nconst renderUserChange = (context) => {\n return Templates.render('mod_forum/local/grades/local/grader/user_picker/user', context);\n};\n\nconst showUser = async(root, users, currentUserIndex, showUserCallback) => {\n const user = {\n ...users[currentUserIndex],\n total: users.length,\n displayIndex: currentUserIndex + 1,\n };\n const [html] = await Promise.all([renderUserChange(user), showUserCallback(user)]);\n const userRegion = root.querySelector(Selectors.regions.userRegion);\n Templates.replaceNodeContents(userRegion, html, '');\n};\n\nconst bindEvents = (root, users, currentUserIndex, showUserCallback, saveUserCallback) => {\n root.addEventListener('click', (e) => {\n const button = e.target.closest(Selectors.actions.changeUser);\n if (button) {\n saveUserCallback(users[currentUserIndex]);\n currentUserIndex += parseInt(button.dataset.direction);\n showUser(root, users, currentUserIndex, showUserCallback);\n }\n });\n};\n\nexport const buildPicker = async(users, currentUserID, showUserCallback, saveUserCallback) => {\n let root = document.createElement('div');\n\n const [html] = await Promise.all([renderNavigator()]);\n Templates.replaceNodeContents(root, html, '');\n\n const currentUserIndex = users.findIndex((user) => {\n return user.id === parseInt(currentUserID);\n });\n\n await showUser(root, users, currentUserIndex, showUserCallback);\n\n bindEvents(root, users, currentUserIndex, showUserCallback, saveUserCallback);\n\n return root;\n};\n"],"file":"user_picker.min.js"}
\ No newline at end of file
diff --git a/mod/forum/amd/src/grades/grader.js b/mod/forum/amd/src/grades/grader.js
index 9a2636e6bf1..55af0b11cf1 100644
--- a/mod/forum/amd/src/grades/grader.js
+++ b/mod/forum/amd/src/grades/grader.js
@@ -94,8 +94,11 @@ const discussionPostMapper = discussion => {
};
};
+/**
+ * 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);
@@ -104,14 +107,30 @@ export const registerLaunchListeners = () => {
}
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');
}
diff --git a/mod/forum/amd/src/local/grades/grader.js b/mod/forum/amd/src/local/grades/grader.js
index 5f2c958e4aa..bbe702f1cdf 100644
--- a/mod/forum/amd/src/local/grades/grader.js
+++ b/mod/forum/amd/src/local/grades/grader.js
@@ -26,6 +26,7 @@ import Templates from 'core/templates';
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: {
@@ -38,16 +39,26 @@ const displayUserPicker = (root, html) => {
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);
};
};
@@ -67,8 +78,14 @@ const registerEventListeners = (graderLayout) => {
});
};
+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,
} = {}) => {
@@ -85,8 +102,16 @@ export const launch = async(getListOfUsers, getContentForUser, {
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};
diff --git a/mod/forum/amd/src/local/grades/local/grader/gradingpanel.js b/mod/forum/amd/src/local/grades/local/grader/gradingpanel.js
new file mode 100644
index 00000000000..5d765f81926
--- /dev/null
+++ b/mod/forum/amd/src/local/grades/local/grader/gradingpanel.js
@@ -0,0 +1,48 @@
+// 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 .
+
+/**
+ * Grading panel functions.
+ *
+ * @module mod_forum/local/grades/local/grader/gradingpnael
+ * @package mod_forum
+ * @copyright 2019 Andrew Nicols
+ * @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),
+ };
+};
+
diff --git a/mod/forum/amd/src/local/grades/local/grader/selectors.js b/mod/forum/amd/src/local/grades/local/grader/selectors.js
index 4b407a8db08..12fa5620d89 100644
--- a/mod/forum/amd/src/local/grades/local/grader/selectors.js
+++ b/mod/forum/amd/src/local/grades/local/grader/selectors.js
@@ -34,6 +34,7 @@ export default {
regions: {
moduleReplace: getDataSelector('region', 'module_content'),
pickerRegion: getDataSelector('region', 'user_picker'),
+ gradingPanel: getDataSelector('region', 'grade'),
},
};
diff --git a/mod/forum/amd/src/local/grades/local/grader/user_picker.js b/mod/forum/amd/src/local/grades/local/grader/user_picker.js
index 40b82465507..51f381849c7 100644
--- a/mod/forum/amd/src/local/grades/local/grader/user_picker.js
+++ b/mod/forum/amd/src/local/grades/local/grader/user_picker.js
@@ -44,17 +44,18 @@ const showUser = async(root, users, currentUserIndex, showUserCallback) => {
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()]);
@@ -66,7 +67,7 @@ export const buildPicker = async(users, currentUserID, showUserCallback) => {
await showUser(root, users, currentUserIndex, showUserCallback);
- bindEvents(root, users, currentUserIndex, showUserCallback);
+ bindEvents(root, users, currentUserIndex, showUserCallback, saveUserCallback);
return root;
};