From eaee64778b94955df248960ddac7503ec3ffbf55 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Sat, 5 Oct 2019 16:08:45 +0800 Subject: [PATCH] MDL-66845 mod_forum: Hook up save button Part of MDL-66074 --- mod/forum/amd/build/grades/grader.min.js | 2 +- mod/forum/amd/build/grades/grader.min.js.map | 2 +- .../amd/build/local/grades/grader.min.js | 2 +- .../amd/build/local/grades/grader.min.js.map | 2 +- .../grades/local/grader/selectors.min.js | 2 +- .../grades/local/grader/selectors.min.js.map | 2 +- .../grades/local/grader/user_picker.min.js | 2 +- .../local/grader/user_picker.min.js.map | 2 +- mod/forum/amd/src/grades/grader.js | 58 +++++++++++-------- mod/forum/amd/src/local/grades/grader.js | 28 +++++++-- .../local/grades/local/grader/selectors.js | 1 + .../local/grades/local/grader/user_picker.js | 6 +- .../grades/local/grader/navigation.mustache | 3 +- 13 files changed, 71 insertions(+), 41 deletions(-) diff --git a/mod/forum/amd/build/grades/grader.min.js b/mod/forum/amd/build/grades/grader.min.js index 6169ac5c9c7..2bb04a842c4 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}}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,moduleName:e.name});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)}}())}}); +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,e,f,g){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.registerLaunchListeners=void 0;b=i(b);c=h(c);d=h(d);e=i(e);f=h(f);g=h(g);function h(a){return a&&a.__esModule?a:{default:a}}function i(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 j(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 k(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){j(h,d,e,f,g,"next",a)}function g(a){j(h,d,e,f,g,"throw",a)}f(void 0)})}}var l={contentRegion:"mod_forum/grades/grader/discussion/posts"},m=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(o);return d.default.render(l.contentRegion,a)}).catch(f.default.exception)}}(),getUsers:function getUsersForCmidFunction(){return function(){return g.default.getUsersFromCourseModuleID(a).then(function(a){return a.users}).catch(f.default.exception)}}()}},n=function(a){return a.closest(b.gradableItem)},o=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}},p=function(){var a=k(regeneratorRuntime.mark(function a(b){var c,d,f;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:c=b.dataset;d=m(c.cmid);a.next=4;return e.getGradingPanelFunctions("mod_forum",c.contextid,c.gradingComponent,c.gradingComponentSubtype,c.gradableItemtype);case 4:f=a.sent;a.next=7;return e.launch(d.getUsers,d.getContentForUserId,f.getter,f.setter,{groupid:c.groupid,initialUserId:c.initialuserid,moduleName:c.name});case 7:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.registerLaunchListeners=function registerLaunchListeners(){document.addEventListener("click",function(){var a=k(regeneratorRuntime.mark(function a(c){var d;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:if(!c.target.matches(b.launch)){a.next=17;break}d=n(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=16;break}c.preventDefault();a.prev=6;a.next=9;return p(d);case 9:a.next=14;break;case 11:a.prev=11;a.t0=a["catch"](6);f.default.exception(a.t0);case 14:a.next=17;break;case 16:throw Error("Unable to find a valid gradable item");case 17:case"end":return a.stop();}}},a,null,[[6,11]])}));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 5b80040f8ef..2769244a14f 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","preventDefault","data","dataset","wholeForumFunctions","Grader","getGradingPanelFunctions","contextid","gradingComponent","gradingComponentSubtype","gradableItemtype","gradingPanelFunctions","getter","setter","groupid","initialUserId","initialuserid","moduleName"],"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 moduleName: data.name\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 +{"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","launchWholeForumGrading","rootNode","data","dataset","wholeForumFunctions","Grader","getGradingPanelFunctions","contextid","gradingComponent","gradingComponentSubtype","gradableItemtype","gradingPanelFunctions","launch","getter","setter","groupid","initialUserId","initialuserid","moduleName","registerLaunchListeners","document","addEventListener","e","target","matches","Error","gradableItems","wholeForum","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\n/**\n * Launch the Grader.\n *\n * @param {HTMLElement} rootNode the root HTML element describing what is to be graded\n */\nconst launchWholeForumGrading = async rootNode => {\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 await Grader.launch(\n wholeForumFunctions.getUsers,\n wholeForumFunctions.getContentForUserId,\n gradingPanelFunctions.getter,\n gradingPanelFunctions.setter,\n {\n groupid: data.groupid,\n initialUserId: data.initialuserid,\n moduleName: data.name\n }\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 try {\n await launchWholeForumGrading(rootNode);\n } catch (error) {\n Notification.exception(error);\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 8db2e6caabe..d4e333cf27d 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","./local/grader/gradingpanel","core/toast","core/str"],function(a,b,c,d,e,f,g,h){"use strict";Object.defineProperty(a,"__esModule",{value:!0});Object.defineProperty(a,"getGradingPanelFunctions",{enumerable:!0,get:function get(){return f.default}});a.launch=void 0;b=i(b);c=i(c);d=i(d);f=i(f);function i(a){return a&&a.__esModule?a:{default:a}}function j(a,b){return m(a)||l(a,b)||k()}function k(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}function l(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 m(a){if(Array.isArray(a))return a}function n(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 o(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){n(h,d,e,f,g,"next",a)}function g(a){n(h,d,e,f,g,"throw",a)}f(void 0)})}}var p={grader:{app:"mod_forum/local/grades/grader"}},q=function(a,d){var e=a.querySelector(c.default.regions.pickerRegion);b.default.replaceNodeContents(e,d,"")},r=function(a,b){return[a,b]},s=function(a,d,e){return function(){var f=o(regeneratorRuntime.mark(function f(g){var h,i,k,l,m,n,o,p,q,s;return regeneratorRuntime.wrap(function(f){while(1){switch(f.prev=f.next){case 0:f.next=2;return Promise.all([d(g.id).then(r),e(g.id)]);case 2:h=f.sent;i=j(h,2);k=j(i[0],2);l=k[0];m=k[1];n=i[1];b.default.replaceNodeContents(a.querySelector(c.default.regions.moduleReplace),l,m);f.next=11;return b.default.render(n.templatename,n.grade).then(r);case 11:o=f.sent;p=j(o,2);q=p[0];s=p[1];b.default.replaceNodeContents(a.querySelector(c.default.regions.gradingPanel),q,s);case 16:case"end":return f.stop();}}},f)}));return function(){return f.apply(this,arguments)}}()},t=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()}})},u=function(a,b){return function(){var d=o(regeneratorRuntime.mark(function d(e){var f;return regeneratorRuntime.wrap(function(d){while(1){switch(d.prev=d.next){case 0:d.prev=0;d.next=3;return b(e.id,a.querySelector(c.default.regions.gradingPanel));case 3:f=d.sent;d.t0=g.add;d.next=7;return(0,h.get_string)("grades:gradesavedfor","mod_forum",e);case 7:d.t1=d.sent;(0,d.t0)(d.t1);return d.abrupt("return",f);case 12:d.prev=12;d.t2=d["catch"](0);throw d.t2;case 15:case"end":return d.stop();}}},d,null,[[0,12]])}));return function(){return d.apply(this,arguments)}}()},v=function(){var a=o(regeneratorRuntime.mark(function a(c,f,g,h){var i,k,l,m,n,o,r,v,w,x,y,z,A,B=arguments;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:i=4.\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 getUserPicker from './local/grader/user_picker';\nimport {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';\nimport getGradingPanelFunctions from './local/grader/gradingpanel';\nimport {add as addToast} from 'core/toast';\nimport {get_string as getString} from 'core/str';\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\n/**\n * Get the function used to save a user grade.\n *\n * @param {Element} root The contaienr\n * @param {Function} setGradeForUser The function that will be called.\n * @return {Function}\n */\nconst getSaveUserGradeFunction = (root, setGradeForUser) => {\n return async user => {\n try {\n const result = await setGradeForUser(user.id, root.querySelector(Selectors.regions.gradingPanel));\n addToast(await getString('grades:gradesavedfor', 'mod_forum', user));\n\n return result;\n } catch (error) {\n throw error;\n }\n };\n};\n\n// Make this explicit rather than object\nexport const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {\n initialUserId = 0, moduleName\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, {moduleName: moduleName}),\n getListOfUsers(),\n ]);\n const graderContainer = graderLayout.getContainer();\n\n const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser);\n\n Templates.replaceNodeContents(graderContainer, graderHTML, '');\n registerEventListeners(graderLayout);\n const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);\n\n // Fetch the userpicker for display.\n const userPicker = await getUserPicker(\n userList,\n initialUserId,\n updateUserContent,\n saveGradeFunction\n );\n\n // Display the newly created user picker.\n displayUserPicker(graderContainer, userPicker.rootNode);\n};\n\nexport {getGradingPanelFunctions};\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","userPicker","saveGradeFunction","graderContainer","getContainer","addEventListener","e","target","closest","buttons","toggleFullscreen","stopImmediatePropagation","preventDefault","closeGrader","close","saveGrade","currentUser","getSaveUserGradeFunction","setGradeForUser","result","addToast","launch","getListOfUsers","initialUserId","moduleName","fullscreen","showLoader","graderHTML","userList","updateUserContent","rootNode"],"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';\nimport Selectors from './local/grader/selectors';\nimport getUserPicker from './local/grader/user_picker';\nimport {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';\nimport getGradingPanelFunctions from './local/grader/gradingpanel';\nimport {add as addToast} from 'core/toast';\nimport {get_string as getString} from 'core/str';\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, userPicker, saveGradeFunction) => {\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\n return;\n }\n\n if (e.target.closest(Selectors.buttons.closeGrader)) {\n e.stopImmediatePropagation();\n e.preventDefault();\n\n graderLayout.close();\n\n return;\n }\n\n if (e.target.closest(Selectors.buttons.saveGrade)) {\n saveGradeFunction(userPicker.currentUser);\n }\n });\n};\n\n/**\n * Get the function used to save a user grade.\n *\n * @param {Element} root The contaienr\n * @param {Function} setGradeForUser The function that will be called.\n * @return {Function}\n */\nconst getSaveUserGradeFunction = (root, setGradeForUser) => {\n return async user => {\n try {\n const result = await setGradeForUser(user.id, root.querySelector(Selectors.regions.gradingPanel));\n addToast(await getString('grades:gradesavedfor', 'mod_forum', user));\n\n return result;\n } catch (error) {\n throw error;\n }\n };\n};\n\n/**\n * Launch the grader interface with the specified parameters.\n *\n * @param {Function} getListOfUsers A function to get the list of users\n * @param {Function} getContentForUser A function to get the content for a specific user\n * @param {Function} getGradeForUser A function get the grade details for a specific user\n * @param {Function} setGradeForUser A function to set the grade for a specific user\n */\nexport const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {\n initialUserId = 0, moduleName\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, {moduleName: moduleName}),\n getListOfUsers(),\n ]);\n const graderContainer = graderLayout.getContainer();\n\n const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser);\n\n Templates.replaceNodeContents(graderContainer, graderHTML, '');\n const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser);\n\n // Fetch the userpicker for display.\n const userPicker = await getUserPicker(\n userList,\n initialUserId,\n updateUserContent,\n saveGradeFunction\n );\n\n // Register all event listeners.\n registerEventListeners(graderLayout, userPicker, saveGradeFunction);\n\n // Display the newly created user picker.\n displayUserPicker(graderContainer, userPicker.rootNode);\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/selectors.min.js b/mod/forum/amd/build/local/grades/local/grader/selectors.min.js index 2c1440db8be..f63728b83f5 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"),gradingPanel:b("region","grade")}};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"),saveGrade:b("action","savegrade")},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 d3dfc8f963d..79f26b43fe4 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","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 +{"version":3,"sources":["../../../../../src/local/grades/local/grader/selectors.js"],"names":["getDataSelector","name","value","buttons","toggleFullscreen","closeGrader","saveGrade","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,CAGLM,SAAS,CAAEN,CAAe,CAAC,QAAD,CAAW,WAAX,CAHrB,CADE,CAMXO,OAAO,CAAE,CACLC,aAAa,CAAER,CAAe,CAAC,QAAD,CAAW,gBAAX,CADzB,CAELS,YAAY,CAAET,CAAe,CAAC,QAAD,CAAW,aAAX,CAFxB,CAGLU,YAAY,CAAEV,CAAe,CAAC,QAAD,CAAW,OAAX,CAHxB,CANE,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 saveGrade: getDataSelector('action', 'savegrade'),\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 9cb271e743c..4fb0c82361d 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.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){for(var b=1;bthis.currentUserIndex){this.currentUserIndex=this.userList.length-1}else if(this.currentUserIndex>this.userList.length-1){this.currentUserIndex=0}return this.currentUserIndex}},{key:"currentUser",get:function get(){return e({},this.userList[this.currentUserIndex],{total:this.userList.length,displayIndex:this.currentUserIndex+1})}},{key:"rootNode",get:function get(){return this.root}}]);return a}(),r=function(){var a=m(regeneratorRuntime.mark(function a(b,c,d,e){var f;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:f=new q(b,c,d,e,!1);a.next=3;return f.render();case 3:return a.abrupt("return",f);case 4:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.default=r;return a.default}); +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.default=void 0;b=d(b);c=d(c);function d(a){return a&&a.__esModule?a:{default:a}}function e(a){for(var b=1;bthis.currentUserIndex){this.currentUserIndex=this.userList.length-1}else if(this.currentUserIndex>this.userList.length-1){this.currentUserIndex=0}return this.currentUserIndex}},{key:"currentUser",get:function get(){return e({},this.userList[this.currentUserIndex],{total:this.userList.length,displayIndex:this.currentUserIndex+1})}},{key:"rootNode",get:function get(){return this.root}}]);return a}(),r=function(){var a=m(regeneratorRuntime.mark(function a(b,c,d,e){var f;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:f=new q(b,c,d,e,!1);a.next=3;return f.render();case 3:return a.abrupt("return",f);case 4:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.default=r;return a.default}); //# sourceMappingURL=user_picker.min.js.map diff --git a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map index 67fb8a63232..a2afa808948 100644 --- a/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map +++ b/mod/forum/amd/build/local/grades/local/grader/user_picker.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../../../../../src/local/grades/local/grader/user_picker.js"],"names":["UserPicker","userList","initialUserId","showUserCallback","preChangeUserCallback","render","currentUserIndex","findIndex","user","id","parseInt","bind","root","document","createElement","renderNavigator","html","js","Templates","replaceNodeContents","showUser","currentUser","registerEventListeners","renderForPromise","context","Promise","all","renderUserChange","userRegion","querySelector","Selectors","regions","addEventListener","e","button","target","closest","actions","changeUser","updateIndex","dataset","direction","length","total","displayIndex","users","currentUserID","userPicker"],"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/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 templatePath = 'mod_forum/local/grades/local/grader';\n\nclass UserPicker {\n\n /**\n * Constructor for the User Picker.\n *\n * @param {Array} userList List of users\n * @param {Number} initialUserId The ID of the initial user to display\n * @param {Function} showUserCallback The callback used to display the user\n * @param {Function} preChangeUserCallback The callback to use before changing user\n * @param {Bool} render Whether to render on instantiation\n */\n constructor(userList, initialUserId, showUserCallback, preChangeUserCallback, render = true) {\n this.userList = userList;\n this.showUserCallback = showUserCallback;\n this.preChangeUserCallback = preChangeUserCallback;\n\n // Determine the current index.\n this.currentUserIndex = userList.findIndex(user => {\n return user.id === parseInt(initialUserId);\n });\n\n // Ensure that render is bound correctly.\n this.render = this.render.bind(this);\n\n if (render) {\n this.render();\n }\n }\n\n /**\n * Render the user picker.\n */\n async render() {\n // Create the root node.\n this.root = document.createElement('div');\n\n const {html, js} = await this.renderNavigator();\n Templates.replaceNodeContents(this.root, html, js);\n\n // Call the showUser function to show the first user immediately.\n await this.showUser(this.currentUser);\n\n // Ensure that the event listeners are all bound.\n this.registerEventListeners();\n }\n\n /**\n * Render the navigator itself.\n *\n * @returns {Promise}\n */\n renderNavigator() {\n return Templates.renderForPromise(`${templatePath}/user_picker`, {});\n }\n\n /**\n * Render the current user details for the picker.\n *\n * @param {Object} context The data used to render the user picker.\n * @returns {Promise}\n */\n renderUserChange(context) {\n return Templates.renderForPromise(`${templatePath}/user_picker/user`, context);\n }\n\n /**\n * Show the specified user in the picker.\n *\n * @param {Object} user\n */\n async showUser(user) {\n const [{html, js}] = await Promise.all([this.renderUserChange(user), this.showUserCallback(user)]);\n const userRegion = this.root.querySelector(Selectors.regions.userRegion);\n Templates.replaceNodeContents(userRegion, html, js);\n }\n\n /**\n * Register the event listeners for the user picker.\n */\n registerEventListeners() {\n this.root.addEventListener('click', (e) => {\n const button = e.target.closest(Selectors.actions.changeUser);\n if (button) {\n this.preChangeUserCallback(this.currentUser);\n this.updateIndex(parseInt(button.dataset.direction));\n this.showUser(this.currentUser);\n }\n });\n }\n\n /**\n * Update the current user index.\n *\n * @param {Number} direction\n * @returns {Number}}\n */\n updateIndex(direction) {\n this.currentUserIndex += direction;\n\n // Loop around the edges.\n if (this.currentUserIndex < 0) {\n this.currentUserIndex = this.userList.length - 1;\n } else if (this.currentUserIndex > this.userList.length - 1) {\n this.currentUserIndex = 0;\n }\n\n return this.currentUserIndex;\n }\n\n /**\n * Get the details of the user currently shown with the total number of users, and the 1-indexed count of the\n * current user.\n *\n * @returns {Object}\n */\n get currentUser() {\n return {\n ...this.userList[this.currentUserIndex],\n total: this.userList.length,\n displayIndex: this.currentUserIndex + 1,\n };\n }\n\n /**\n * Get the root node for the User Picker.\n *\n * @returns {HTMLElement}\n */\n get rootNode() {\n return this.root;\n }\n}\n\n/**\n * Create a new user picker.\n *\n * @param {Array} users The list of users\n * @param {Number} currentUserID The userid of the current user\n * @param {Function} showUserCallback The function to call to show a specific user\n * @param {Function} preChangeUserCallback The fucntion to call to save the grade for the current user\n * @returns {UserPicker}\n */\nexport default async(users, currentUserID, showUserCallback, preChangeUserCallback) => {\n const userPicker = new UserPicker(users, currentUserID, showUserCallback, preChangeUserCallback, false);\n await userPicker.render();\n\n return userPicker;\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":["UserPicker","userList","initialUserId","showUserCallback","preChangeUserCallback","render","currentUserIndex","findIndex","user","id","parseInt","bind","root","document","createElement","renderNavigator","html","js","Templates","replaceNodeContents","showUser","currentUser","registerEventListeners","renderForPromise","context","Promise","all","renderUserChange","userRegion","querySelector","Selectors","regions","addEventListener","e","button","target","closest","actions","changeUser","updateIndex","dataset","direction","length","total","displayIndex","users","currentUserID","userPicker"],"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/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 templatePath = 'mod_forum/local/grades/local/grader';\n\nclass UserPicker {\n\n /**\n * Constructor for the User Picker.\n *\n * @param {Array} userList List of users\n * @param {Number} initialUserId The ID of the initial user to display\n * @param {Function} showUserCallback The callback used to display the user\n * @param {Function} preChangeUserCallback The callback to use before changing user\n * @param {Bool} render Whether to render on instantiation\n */\n constructor(userList, initialUserId, showUserCallback, preChangeUserCallback, render = true) {\n this.userList = userList;\n this.showUserCallback = showUserCallback;\n this.preChangeUserCallback = preChangeUserCallback;\n\n // Determine the current index.\n this.currentUserIndex = userList.findIndex(user => {\n return user.id === parseInt(initialUserId);\n });\n\n // Ensure that render is bound correctly.\n this.render = this.render.bind(this);\n\n if (render) {\n this.render();\n }\n }\n\n /**\n * Render the user picker.\n */\n async render() {\n // Create the root node.\n this.root = document.createElement('div');\n\n const {html, js} = await this.renderNavigator();\n Templates.replaceNodeContents(this.root, html, js);\n\n // Call the showUser function to show the first user immediately.\n await this.showUser(this.currentUser);\n\n // Ensure that the event listeners are all bound.\n this.registerEventListeners();\n }\n\n /**\n * Render the navigator itself.\n *\n * @returns {Promise}\n */\n renderNavigator() {\n return Templates.renderForPromise(`${templatePath}/user_picker`, {});\n }\n\n /**\n * Render the current user details for the picker.\n *\n * @param {Object} context The data used to render the user picker.\n * @returns {Promise}\n */\n renderUserChange(context) {\n return Templates.renderForPromise(`${templatePath}/user_picker/user`, context);\n }\n\n /**\n * Show the specified user in the picker.\n *\n * @param {Object} user\n */\n async showUser(user) {\n const [{html, js}] = await Promise.all([this.renderUserChange(user), this.showUserCallback(user)]);\n const userRegion = this.root.querySelector(Selectors.regions.userRegion);\n Templates.replaceNodeContents(userRegion, html, js);\n }\n\n /**\n * Register the event listeners for the user picker.\n */\n registerEventListeners() {\n this.root.addEventListener('click', async e => {\n const button = e.target.closest(Selectors.actions.changeUser);\n if (button) {\n await this.preChangeUserCallback(this.currentUser);\n this.updateIndex(parseInt(button.dataset.direction));\n await this.showUser(this.currentUser);\n }\n });\n }\n\n /**\n * Update the current user index.\n *\n * @param {Number} direction\n * @returns {Number}}\n */\n updateIndex(direction) {\n this.currentUserIndex += direction;\n\n // Loop around the edges.\n if (this.currentUserIndex < 0) {\n this.currentUserIndex = this.userList.length - 1;\n } else if (this.currentUserIndex > this.userList.length - 1) {\n this.currentUserIndex = 0;\n }\n\n return this.currentUserIndex;\n }\n\n /**\n * Get the details of the user currently shown with the total number of users, and the 1-indexed count of the\n * current user.\n *\n * @returns {Object}\n */\n get currentUser() {\n return {\n ...this.userList[this.currentUserIndex],\n total: this.userList.length,\n displayIndex: this.currentUserIndex + 1,\n };\n }\n\n /**\n * Get the root node for the User Picker.\n *\n * @returns {HTMLElement}\n */\n get rootNode() {\n return this.root;\n }\n}\n\n/**\n * Create a new user picker.\n *\n * @param {Array} users The list of users\n * @param {Number} currentUserID The userid of the current user\n * @param {Function} showUserCallback The function to call to show a specific user\n * @param {Function} preChangeUserCallback The fucntion to call to save the grade for the current user\n * @returns {UserPicker}\n */\nexport default async(users, currentUserID, showUserCallback, preChangeUserCallback) => {\n const userPicker = new UserPicker(users, currentUserID, showUserCallback, preChangeUserCallback, false);\n await userPicker.render();\n\n return userPicker;\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 a44979a0f09..2ff4512d594 100644 --- a/mod/forum/amd/src/grades/grader.js +++ b/mod/forum/amd/src/grades/grader.js @@ -94,11 +94,40 @@ const discussionPostMapper = discussion => { }; }; +/** + * Launch the Grader. + * + * @param {HTMLElement} rootNode the root HTML element describing what is to be graded + */ +const launchWholeForumGrading = async rootNode => { + const data = rootNode.dataset; + const wholeForumFunctions = getWholeForumFunctions(data.cmid); + const gradingPanelFunctions = await Grader.getGradingPanelFunctions( + 'mod_forum', + data.contextid, + data.gradingComponent, + data.gradingComponentSubtype, + data.gradableItemtype + ); + + await Grader.launch( + wholeForumFunctions.getUsers, + wholeForumFunctions.getContentForUserId, + gradingPanelFunctions.getter, + gradingPanelFunctions.setter, + { + groupid: data.groupid, + initialUserId: data.initialuserid, + moduleName: data.name + } + ); +}; + /** * Register listeners to launch the grading panel. */ export const registerLaunchListeners = () => { - document.addEventListener('click', async(e) => { + document.addEventListener('click', async e => { if (e.target.matches(Selectors.launch)) { const rootNode = findGradableNode(e.target); @@ -110,28 +139,11 @@ export const registerLaunchListeners = () => { // 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, - moduleName: data.name - } - ); + try { + await launchWholeForumGrading(rootNode); + } catch (error) { + Notification.exception(error); + } } 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 0a842c4c1cf..637820d5f52 100644 --- a/mod/forum/amd/src/local/grades/grader.js +++ b/mod/forum/amd/src/local/grades/grader.js @@ -22,7 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import Templates from 'core/templates'; -// TODO import Notification from 'core/notification'; import Selectors from './local/grader/selectors'; import getUserPicker from './local/grader/user_picker'; import {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen'; @@ -64,18 +63,28 @@ const getUpdateUserContentFunction = (root, getContentForUser, getGradeForUser) }; }; -const registerEventListeners = (graderLayout) => { +const registerEventListeners = (graderLayout, userPicker, saveGradeFunction) => { const graderContainer = graderLayout.getContainer(); graderContainer.addEventListener('click', (e) => { if (e.target.closest(Selectors.buttons.toggleFullscreen)) { e.stopImmediatePropagation(); e.preventDefault(); graderLayout.toggleFullscreen(); - } else if (e.target.closest(Selectors.buttons.closeGrader)) { + + return; + } + + if (e.target.closest(Selectors.buttons.closeGrader)) { e.stopImmediatePropagation(); e.preventDefault(); graderLayout.close(); + + return; + } + + if (e.target.closest(Selectors.buttons.saveGrade)) { + saveGradeFunction(userPicker.currentUser); } }); }; @@ -100,7 +109,14 @@ const getSaveUserGradeFunction = (root, setGradeForUser) => { }; }; -// Make this explicit rather than object +/** + * Launch the grader interface with the specified parameters. + * + * @param {Function} getListOfUsers A function to get the list of users + * @param {Function} getContentForUser A function to get the content for a specific user + * @param {Function} getGradeForUser A function get the grade details for a specific user + * @param {Function} setGradeForUser A function to set the grade for a specific user + */ export const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, { initialUserId = 0, moduleName } = {}) => { @@ -119,7 +135,6 @@ export const launch = async(getListOfUsers, getContentForUser, getGradeForUser, const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser); Templates.replaceNodeContents(graderContainer, graderHTML, ''); - registerEventListeners(graderLayout); const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser); // Fetch the userpicker for display. @@ -130,6 +145,9 @@ export const launch = async(getListOfUsers, getContentForUser, getGradeForUser, saveGradeFunction ); + // Register all event listeners. + registerEventListeners(graderLayout, userPicker, saveGradeFunction); + // Display the newly created user picker. displayUserPicker(graderContainer, userPicker.rootNode); }; 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 12fa5620d89..8f55bba75e7 100644 --- a/mod/forum/amd/src/local/grades/local/grader/selectors.js +++ b/mod/forum/amd/src/local/grades/local/grader/selectors.js @@ -30,6 +30,7 @@ export default { buttons: { toggleFullscreen: getDataSelector('action', 'togglefullscreen'), closeGrader: getDataSelector('action', 'closegrader'), + saveGrade: getDataSelector('action', 'savegrade'), }, regions: { moduleReplace: getDataSelector('region', 'module_content'), 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 252ecfa9ac4..9cbf1ee60be 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 @@ -107,12 +107,12 @@ class UserPicker { * Register the event listeners for the user picker. */ registerEventListeners() { - this.root.addEventListener('click', (e) => { + this.root.addEventListener('click', async e => { const button = e.target.closest(Selectors.actions.changeUser); if (button) { - this.preChangeUserCallback(this.currentUser); + await this.preChangeUserCallback(this.currentUser); this.updateIndex(parseInt(button.dataset.direction)); - this.showUser(this.currentUser); + await this.showUser(this.currentUser); } }); } diff --git a/mod/forum/templates/local/grades/local/grader/navigation.mustache b/mod/forum/templates/local/grades/local/grader/navigation.mustache index c7aaa3ab7cb..a99a0251c21 100644 --- a/mod/forum/templates/local/grades/local/grader/navigation.mustache +++ b/mod/forum/templates/local/grades/local/grader/navigation.mustache @@ -46,8 +46,7 @@ Close - - Save + Save