MDL-66077 mod_forum: Basic forum grader implementation

Part of MDL-66074
This commit is contained in:
Mathew May 2019-07-08 16:23:19 +08:00
parent 34e6dd2475
commit bae674695f
33 changed files with 1205 additions and 29 deletions

View File

@ -0,0 +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")}}})}});
//# sourceMappingURL=grader.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
define ("mod_forum/grades/grader/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={launch:"[data-grade-action=\"launch\"]",gradableItem:"[data-gradable-itemtype]",gradableItems:{wholeForum:"[data-gradable-itemtype=\"forum\"]"}};return a.default});
//# sourceMappingURL=selectors.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/grades/grader/selectors.js"],"names":["launch","gradableItem","gradableItems","wholeForum"],"mappings":"6JAuBe,CACXA,MAAM,CAAE,gCADG,CAEXC,YAAY,CAAE,0BAFH,CAGXC,aAAa,CAAE,CACXC,UAAU,CAAE,oCADD,CAHJ,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 <http://www.gnu.org/licenses/>.\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/selectors\n * @package mod_forum\n * @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n launch: '[data-grade-action=\"launch\"]',\n gradableItem: '[data-gradable-itemtype]',\n gradableItems: {\n wholeForum: '[data-gradable-itemtype=\"forum\"]',\n },\n};\n"],"file":"selectors.min.js"}

View File

@ -0,0 +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<w.length&&w[2]!==void 0?w[2]:{},i=h.initialUserId,j=void 0===i?0:i;a.next=3;return Promise.all([(0,e.createLayout)({fullscreen:!1,showLoader:!1}),b.default.render(n.grader.app,{}),c()]);case 3:k=a.sent;l=g(k,3);m=l[0];r=l[1];s=l[2];t=m.getContainer();b.default.replaceNodeContents(t,r,"");q(m);u=p(t,f);a.next=14;return d.buildPicker(s,j,u);case 14:v=a.sent;o(t,v);case 16:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.launch=r});
//# sourceMappingURL=grader.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +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});
//# sourceMappingURL=selectors.min.js.map

View File

@ -0,0 +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 <http://www.gnu.org/licenses/>.\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 <mathew.solutions>\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"}

View File

@ -0,0 +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<arguments.length;b++){var c=null!=arguments[b]?arguments[b]:{},d=Object.keys(c);if("function"==typeof Object.getOwnPropertySymbols){d=d.concat(Object.getOwnPropertySymbols(c).filter(function(a){return Object.getOwnPropertyDescriptor(c,a).enumerable}))}d.forEach(function(b){j(a,b,c[b])})}return a}function j(a,b,c){if(b in a){Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0})}else{a[b]=c}return a}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=function(){return b.default.render("mod_forum/local/grades/local/grader/user_picker",{})},n=function(a){return b.default.render("mod_forum/local/grades/local/grader/user_picker/user",a)},o=function(){var a=l(regeneratorRuntime.mark(function a(d,f,g,h){var j,k,l,m,o;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:j=i({},f[g],{total:f.length,displayIndex:g+1});a.next=3;return Promise.all([n(j),h(j)]);case 3:k=a.sent;l=e(k,1);m=l[0];o=d.querySelector(c.default.regions.userRegion);b.default.replaceNodeContents(o,m,"");case 8:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}(),p=function(a,b,d,e){a.addEventListener("click",function(f){var g=f.target.closest(c.default.actions.changeUser);if(g){d+=parseInt(g.dataset.direction);o(a,b,d,e)}})},q=function(){var a=l(regeneratorRuntime.mark(function a(c,d,f){var g,h,i,j,k;return regeneratorRuntime.wrap(function(a){while(1){switch(a.prev=a.next){case 0:g=document.createElement("div");a.next=3;return Promise.all([m()]);case 3:h=a.sent;i=e(h,1);j=i[0];b.default.replaceNodeContents(g,j,"");k=c.findIndex(function(a){return a.id===parseInt(d)});a.next=10;return o(g,c,k,f);case 10:p(g,c,k,f);return a.abrupt("return",g);case 12:case"end":return a.stop();}}},a)}));return function(){return a.apply(this,arguments)}}();a.buildPicker=q});
//# sourceMappingURL=user_picker.min.js.map

View File

@ -0,0 +1 @@
{"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","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,CAAqD,CACpEH,CAAI,CAACiB,gBAAL,CAAsB,OAAtB,CAA+B,SAACC,CAAD,CAAO,CAClC,GAAMC,CAAAA,CAAM,CAAGD,CAAC,CAACE,MAAF,CAASC,OAAT,CAAiBR,UAAUS,OAAV,CAAkBC,UAAnC,CAAf,CACA,GAAIJ,CAAJ,CAAY,CACRjB,CAAgB,EAAIsB,QAAQ,CAACL,CAAM,CAACM,OAAP,CAAeC,SAAhB,CAA5B,CACA3B,CAAQ,CAACC,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CACX,CACJ,CAND,CAOH,C,CAEYwB,CAAW,4CAAG,WAAM1B,CAAN,CAAa2B,CAAb,CAA4BzB,CAA5B,iGACnBH,CADmB,CACZ6B,QAAQ,CAACC,aAAT,CAAuB,KAAvB,CADY,gBAGFtB,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,CAAC8B,SAAN,CAAgB,SAAC3B,CAAD,CAAU,CAC/C,MAAOA,CAAAA,CAAI,CAAC4B,EAAL,GAAYR,QAAQ,CAACI,CAAD,CAC9B,CAFwB,CANF,iBAUjB7B,CAAAA,CAAQ,CAACC,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CAVS,SAYvBa,CAAU,CAAChB,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAgCC,CAAhC,CAAV,CAZuB,yBAchBH,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 <http://www.gnu.org/licenses/>.\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 <mathew.solutions>\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"}

View File

@ -0,0 +1,2 @@
define ("mod_forum/local/grades/local/grader/user_picker/selectors",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={regions:{userRegion:"[data-region=\"user_picker/user\"]"},actions:{changeUser:"[data-action=\"change-user\"]"}};return a.default});
//# sourceMappingURL=selectors.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../../src/local/grades/local/grader/user_picker/selectors.js"],"names":["regions","userRegion","actions","changeUser"],"mappings":"qLAwBe,CACXA,OAAO,CAAE,CACLC,UAAU,CAAE,oCADP,CADE,CAIXC,OAAO,CAAE,CACLC,UAAU,CAAE,+BADP,CAJE,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 <http://www.gnu.org/licenses/>.\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/user_picker/selectors\n * @package mod_forum\n * @copyright 2019 Mathew May <mathew.solutions>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nexport default {\n regions: {\n userRegion: '[data-region=\"user_picker/user\"]',\n },\n actions: {\n changeUser: '[data-action=\"change-user\"]',\n }\n};\n\n"],"file":"selectors.min.js"}

View File

@ -0,0 +1,120 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module will tie together all of the different calls the gradable module will make.
*
* @module mod_forum/grades/grader
* @package mod_forum
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import * as Selectors from './grader/selectors';
import Repository from 'mod_forum/repository';
import Templates from 'core/templates';
import * as Grader from '../local/grades/grader';
import Notification from 'core/notification';
import CourseRepository from 'core_course/repository';
const templateNames = {
contentRegion: 'mod_forum/grades/grader/discussion/posts',
};
const getWholeForumFunctions = (cmid) => {
const getPostContextFunction = () => {
return (userid) => {
return Repository.getDiscussionByUserID(userid, cmid);
};
};
const getContentForUserIdFunction = () => {
const postContextFunction = getPostContextFunction(cmid);
return userid => {
return postContextFunction(userid)
.then(context => {
// Rebuild the returned data for the template.
context.discussions = context.discussions.map(discussionPostMapper);
return Templates.render(templateNames.contentRegion, context);
})
.catch(Notification.exception);
};
};
const getUsersForCmidFunction = () => {
return () => {
return CourseRepository.getUsersFromCourseModuleID(cmid)
.then((context) => {
return context.users;
})
.catch(Notification.exception);
};
};
return {
getContentForUserId: getContentForUserIdFunction(),
getUsers: getUsersForCmidFunction()
};
};
const findGradableNode = (node) => {
return node.closest(Selectors.gradableItem);
};
const discussionPostMapper = discussion => {
// Map postid => post.
const parentMap = new Map();
discussion.posts.parentposts.forEach(post => parentMap.set(post.id, post));
const userPosts = discussion.posts.userposts.map(post => {
post.subject = null;
post.readonly = true;
post.starter = !post.parentid;
post.parent = parentMap.get(post.parentid);
return post;
});
return {
id: discussion.id,
name: discussion.name,
posts: userPosts,
};
};
export const registerLaunchListeners = () => {
document.addEventListener('click', (e) => {
if (e.target.matches(Selectors.launch)) {
const rootNode = findGradableNode(e.target);
if (!rootNode) {
throw Error('Unable to find a gradable item');
}
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,
});
e.preventDefault();
} else {
throw Error('Unable to find a valid gradable item');
}
}
});
};

View File

@ -0,0 +1,30 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module will tie together all of the different calls the gradable module will make.
*
* @module mod_forum/grades/grader/selectors
* @package mod_forum
* @copyright 2019 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
export default {
launch: '[data-grade-action="launch"]',
gradableItem: '[data-gradable-itemtype]',
gradableItems: {
wholeForum: '[data-gradable-itemtype="forum"]',
},
};

View File

@ -0,0 +1,92 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module will tie together all of the different calls the gradable module will make.
*
* @module mod_forum/local/grades/grader
* @package mod_forum
* @copyright 2019 Mathew May <mathew.solutions>
* @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 * as UserPicker from './local/grader/user_picker';
import {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';
const templateNames = {
grader: {
app: 'mod_forum/local/grades/grader',
},
};
const displayUserPicker = (root, html) => {
const pickerRegion = root.querySelector(Selectors.regions.pickerRegion);
Templates.replaceNodeContents(pickerRegion, html, '');
};
const getUpdateUserContentFunction = (root, getContentForUser) => {
return async(user) => {
const [
{html, js},
] = await Promise.all([
getContentForUser(user.id).then((html, js) => {
return {html, js};
}),
]);
Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);
};
};
const registerEventListeners = (graderLayout) => {
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)) {
e.stopImmediatePropagation();
e.preventDefault();
graderLayout.close();
}
});
};
// Make this explicit rather than object
export const launch = async(getListOfUsers, getContentForUser, {
initialUserId = 0,
} = {}) => {
const [
graderLayout,
graderHTML,
userList,
] = await Promise.all([
createFullScreenWindow({fullscreen: false, showLoader: false}),
Templates.render(templateNames.grader.app, {}),
getListOfUsers(),
]);
const graderContainer = graderLayout.getContainer();
Templates.replaceNodeContents(graderContainer, graderHTML, '');
registerEventListeners(graderLayout);
const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser);
const pickerHTML = await UserPicker.buildPicker(userList, initialUserId, updateUserContent);
displayUserPicker(graderContainer, pickerHTML);
};

View File

@ -0,0 +1,39 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Define all of the selectors we will be using on the grading interface.
*
* @module mod_forum/local/grades/local/grader/selectors
* @package mod_forum
* @copyright 2019 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const getDataSelector = (name, value) => {
return `[data-${name}="${value}"]`;
};
export default {
buttons: {
toggleFullscreen: getDataSelector('action', 'togglefullscreen'),
closeGrader: getDataSelector('action', 'closegrader'),
},
regions: {
moduleReplace: getDataSelector('region', 'module_content'),
pickerRegion: getDataSelector('region', 'user_picker'),
},
};

View File

@ -0,0 +1,72 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module will tie together all of the different calls the gradable module will make.
*
* @module mod_forum/local/grades/local/grader/user_picker
* @package mod_forum
* @copyright 2019 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Templates from 'core/templates';
import Selectors from './user_picker/selectors';
const renderNavigator = () => {
return Templates.render('mod_forum/local/grades/local/grader/user_picker', {});
};
const renderUserChange = (context) => {
return Templates.render('mod_forum/local/grades/local/grader/user_picker/user', context);
};
const showUser = async(root, users, currentUserIndex, showUserCallback) => {
const user = {
...users[currentUserIndex],
total: users.length,
displayIndex: currentUserIndex + 1,
};
const [html] = await Promise.all([renderUserChange(user), showUserCallback(user)]);
const userRegion = root.querySelector(Selectors.regions.userRegion);
Templates.replaceNodeContents(userRegion, html, '');
};
const bindEvents = (root, users, currentUserIndex, showUserCallback) => {
root.addEventListener('click', (e) => {
const button = e.target.closest(Selectors.actions.changeUser);
if (button) {
currentUserIndex += parseInt(button.dataset.direction);
showUser(root, users, currentUserIndex, showUserCallback);
}
});
};
export const buildPicker = async(users, currentUserID, showUserCallback) => {
let root = document.createElement('div');
const [html] = await Promise.all([renderNavigator()]);
Templates.replaceNodeContents(root, html, '');
const currentUserIndex = users.findIndex((user) => {
return user.id === parseInt(currentUserID);
});
await showUser(root, users, currentUserIndex, showUserCallback);
bindEvents(root, users, currentUserIndex, showUserCallback);
return root;
};

View File

@ -0,0 +1,33 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Define all of the selectors we will be using on the grading interface.
*
* @module mod_forum/local/grades/local/grader/user_picker/selectors
* @package mod_forum
* @copyright 2019 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
export default {
regions: {
userRegion: '[data-region="user_picker/user"]',
},
actions: {
changeUser: '[data-action="change-user"]',
}
};

View File

@ -709,6 +709,10 @@ $string['yournewtopic'] = 'Your new discussion topic';
$string['yourreply'] = 'Your reply';
$string['forumsubjectdeleted'] = 'This forum post has been removed';
$string['forumbodydeleted'] = 'The content of this forum post has been removed and can no longer be accessed.';
$string['gradeusers'] = 'Grade users';
$string['forumgrader'] = 'Forum grader';
$string['grading'] = 'Grading';
$string['viewconversation'] = 'View conversation';
// Deprecated since Moodle 3.8.
$string['cannotdeletediscussioninsinglediscussion'] = 'You cannot delete the first post in a single discussion';

View File

@ -344,3 +344,28 @@ span.unread {
outline: 5px auto -webkit-focus-ring-color;
}
/* stylelint-enable declaration-block-no-duplicate-properties */
/* Forum grading non striked through line */
.hr-sect {
display: flex;
flex-basis: 100%;
font-weight: bold;
align-items: center;
margin: 8px 0px;
}
.hr-sect::before,
.hr-sect::after {
content: "";
flex-grow: 1;
background: rgba(0, 0, 0, 0.35);
height: 1px;
font-size: 0px;
line-height: 0px;
}
.hr-sect::before {
margin-right: 15px;
}
.hr-sect::after {
margin-left: 15px;
}

View File

@ -32,7 +32,12 @@
{
}
}}
<div id="discussion-list-{{uniqid}}">
<div id="discussion-list-{{uniqid}}" {{!
}}data-cmid="{{cmid}}" {{!
}}data-group="{{forum.groupid}}" {{!
}}data-gradable-itemtype="forum" {{!
}}{{#firstgradeduserid}}data-initialuserid="{{firstgradeduserid}}" {{/firstgradeduserid}}{{!
}}>
{{{groupchangemenu}}}
{{#notifications}}
@ -63,6 +68,8 @@
{{/forum.capabilities.selfenrol}}
{{/forum.capabilities.create}}
{{!TODO Add capability check}}
<a class="btn btn-primary" href="" data-grade-action="launch">{{#str}}gradeusers, forum{{/str}}</a>
{{#state.hasdiscussions}}
{{$discussion_top_pagination}}
@ -306,4 +313,8 @@
var root = $('#discussion-list-{{uniqid}}');
View.init(root);
});
require(['mod_forum/grades/grader'], function(Grader) {
Grader.registerLaunchListeners();
});
{{/js}}

View File

@ -0,0 +1,81 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/forum_grader_discussion_posts
Template to render a list of posts for a discussion.
Classes required for JS:
* none
Data attributes required for JS:
* none
Example context (json):
{
}
}}
<div data-region="posts">
{{#discussions}}
<div class="hr-sect mt-0">{{name}}</div>
{{#posts}}
{{#parent}}
{{> mod_forum/forum_discussion_modern_post_reply }}
{{/parent}}
{{#starter}}
{{> mod_forum/forum_discussion_modern_first_post }}
<a class="btn btn-outline-dark"
role="button"
data-action="view-context"
data-discussionid="{{discussionid}}"
data-postid="{{id}}"
data-name="{{name}}"
href="#">
{{#str}} viewconversation, forum {{/str}}
</a>
{{/starter}}
{{^starter}}
<div class="forum-post-container" data-region="replies-container">
<div class="indent replies-container" data-region="replies-container">
<div class="indent replies-container" data-region="replies-container">
{{> mod_forum/forum_discussion_modern_post_reply }}
<a class="btn btn-outline-dark"
role="button"
data-action="view-context"
data-discussionid="{{discussionid}}"
data-postid="{{id}}"
data-name="{{name}}"
href="#">
{{#str}} viewconversation, forum {{/str}}
</a>
</div>
</div>
</div>
{{/starter}}
<hr>
{{/posts}}
{{/discussions}}
{{^discussions}}
<h3>{{#str}} noposts, forum {{/str}}</h3>
{{/discussions}}
</div>
{{#js}}
require(['mod_forum/grades/expandconversation'], function(Conversation) {
Conversation.registerEventListeners();
});
{{/js}}

View File

@ -0,0 +1,45 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="container-fluid" {{!
}}data-region="unified-grader" {{!
}}{{#userid}}data-first-userid="{{userid}}"{{/userid}} {{!
}}data-cmid="{{cmid}}" {{!
}}>
<div class="row-fluid">
{{> mod_forum/local/grades/local/grader/navigation }}
</div>
<div class="row-fluid no-gutters">
{{> mod_forum/local/grades/local/grader/content }}
{{> mod_forum/local/grades/local/grader/grading }}
</div>
</div>

View File

@ -0,0 +1,37 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/content
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="grader-module-content col-sm-12 col-md-8 mb-3">
<div data-region="module_content" class="grader-module-content-display col-sm-12">
{{> core/loading }}
</div>
</div>

View File

@ -0,0 +1,43 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/grade_placeholder
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="bg-pulse-grey w-25" style="height: 20px;"></div>
<div class="bg-pulse-grey w-50 mt-1" style="height: 25px;"></div>
<div class="bg-pulse-grey w-25 mt-3" style="height: 20px;"></div>
<div class="bg-pulse-grey w-50 mt-1" style="height: 25px;"></div>
<div class="bg-pulse-grey w-25 mt-3" style="height: 20px;"></div>
<div class="bg-pulse-grey w-100 mt-1" style="height: 25px;"></div>
<div class="bg-pulse-grey w-25 mt-3" style="height: 20px;"></div>
<div class="bg-pulse-grey w-100 mt-1" style="height: 25px;"></div>

View File

@ -0,0 +1,52 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/grading
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="grader-grading-panel border-left border-secondary col-md-4">
<div class="col-md-12 bg-light px-2 py-3 mb-3">
<!--TODO Manipulate grader panel-->
<h4 class="d-inline font-weight-bold mb-0 fa fa-arrow-right" aria-label="Open or close grader panel" data-action="expandgrader"></h4>
<h4 class="d-inline font-weight-bold mb-0">{{#str}}grading, mod_forum{{/str}}</h4>
</div>
<div data-region="user_picker">
{{> mod_forum/local/grades/local/grader/user_picker_placeholder }}
<hr/>
</div>
<div class="grader-grading-panel-display col-sm-12">
<h4 class="d-inline mb-0 fa fa-magic"></h4>
<h4 class="d-inline mb-0 ">Grade:</h4>
<div data-region="grade" class="col-md-12 mt-3">
{{> mod_forum/local/grades/local/grader/grade_placeholder }}
</div>
<hr/>
</div>
</div>

View File

@ -0,0 +1,59 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/navigation
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="grader-grading_navigation col-sm-12">
<div class="row">
<div class="col-sm-12 col-md-8 py-3">
<div class="d-block">
<h6 class="d-inline btn px-0 font-weight-bold fa fa-folder mb-0"></h6>
<h6 class="d-inline btn px-0 font-weight-bold text-muted mb-0"> > </h6>
<h6 class="d-inline btn px-0 font-weight-bold text-muted mb-0">Forum: Week 3</h6>
<h6 class="d-inline btn px-0 font-weight-bold text-muted mb-0"> > </h6>
<h6 class="d-inline btn px-0 font-weight-bold mb-0">Grading</h6>
</div>
</div>
<div class="col-sm-12 col-md-4 py-3">
<a href="#" class="btn fa fa-arrows-alt float-right" aria-label="Toggle fullscreen" data-action="togglefullscreen"></a>
<a href="#" class="btn btn-secondary float-right" aria-label="Close grade interface" data-action="closegrader">Close</a>
<!--TODO Save & close-->
<a href="#" role="button" class="btn btn-primary float-right" aria-label="Save and quit" data-action="saveclosegrader">Save</a>
<!--TODO Manipulate grader panel see also Grading panel-->
<a href="#" role="button" class="btn fa fa-check-circle float-right" aria-label="Open or close grader panel" data-action="expandgrader"></a>
</div>
</div>
</div>

View File

@ -0,0 +1,64 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/user_picker
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="col-md-12">
<div class="row">
<div class="col-md-8">
<div data-region="user_picker/user"></div>
</div>
<div class="col-md-4">
<ul class="pagination">
<li class="page-item mr-3">
<a class="page-link" href="#" aria-label="Previous" data-action="change-user" data-direction="-1">
<span aria-hidden="true">&langle;</span>
<span class="sr-only">{{#str}} previous {{/str}}</span>
</a>
</li>
<li class="page-item mr-3">
<a class="page-link" href="#" aria-label="Next" data-action="change-user" data-direction="1">
<span aria-hidden="true">&rangle;</span>
<span class="sr-only">{{#str}} next {{/str}}</span>
</a>
</li>
<li class="page-item">
<a class="page-link disabled" href="#" aria-label="Search" data-action="search-user">
<span class="fa fa-search" aria-hidden="true"></span>
<span class="sr-only">{{#str}} search {{/str}}</span>
</a>
</li>
</ul>
</div>
</div>
<hr>
</div>

View File

@ -0,0 +1,34 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/user_picker/user
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="d-block font-weight-bold" data-region="name" data-userid="{{id}}">{{fullname}}</div>
<div class="d-block"><div class="d-inline" data-region="index">{{displayIndex}}</div>/{{total}}</div>

View File

@ -0,0 +1,58 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_forum/local/grades/local/grader/user_picker_placeholder
Classes required for JS:
* TODO
Data attributes required for JS:
* TODO
Context variables required for this template:
* TODO
Example context (json):
{
}
}}
<div class="col-md-12 mt-3">
<div class="row">
<div class="col-md-8">
<div class="bg-pulse-grey w-50" style="height: 20px;"></div>
<div class="bg-pulse-grey w-25 mt-1" style="height: 15px;"></div>
</div>
<div class="col-md-4">
<ul class="pagination">
<li class="page-item mr-3">
<span class="btn bg-pulse-grey" aria-hidden="true">&langle;</span>
<span class="sr-only">{{#str}} previous {{/str}}</span>
</li>
<li class="page-item mr-3">
<span class="btn bg-pulse-grey" aria-hidden="true">&rangle;</span>
<span class="sr-only">{{#str}} next {{/str}}</span>
</li>
<li class="page-item">
<span class="btn bg-pulse-grey fa fa-search" aria-hidden="true"></span>
<span class="sr-only">{{#str}} search {{/str}}</span>
</li>
</ul>
</div>
</div>
</div>

View File

@ -198,6 +198,7 @@ $author-image-margin-sm: 8px;
}
}
#page-mod-forum-view [data-region="unified-grader"],
.path-mod-forum.modern-display-mode {
.discussionsubscription {
margin-top: 0;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long