MDL-80750 mod_assign: Show bulk action controls on the sticky footer

This commit is contained in:
Shamim Rezaie 2024-07-18 08:33:24 +10:00 committed by Mihail Geshoski
parent 5f6fe3e02f
commit fc5b396a69
45 changed files with 1179 additions and 274 deletions

View File

@ -0,0 +1,19 @@
issueNumber: MDL-80750
notes:
mod_assign:
- message: >
A new method named `get_grading_batch_operation_details` has been added
to the `assign_feedback_plugin` abstract class. Assignment feedback
plugins can now override this method to define bulk action buttons that
will appear in the sticky footer on the assignment grading page.
type: improved
- message: >
The `assign_feedback_plugin::get_grading_batch_operations` method is now
deprecated. Use
`assign_feedback_plugin::get_grading_batch_operation_details` instead.
type: deprecated
- message: >
The `assign_grading_table::plugingradingbatchoperations` property is
removed. You can use
`assign_feedback_plugin::get_grading_batch_operation_details` instead.
type: deprecated

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
define("mod_assign/bulkactions/grading/delete",["exports","core/bulkactions/bulk_action","core/notification","core/templates","core/str"],(function(_exports,_bulk_action,_notification,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';var _cmid=new WeakMap,_sesskey=new WeakMap;class _default extends _bulk_action.default{constructor(cmid,sesskey){super(),_classPrivateFieldInitSpec(this,_cmid,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_sesskey,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_cmid,cmid),_classPrivateFieldSet(this,_sesskey,sesskey)}getBulkActionTriggerSelector(){return'button[data-action="removesubmission"]'}async triggerBulkAction(){_notification.default.deleteCancelPromise((0,_str.getString)("removesubmission","mod_assign"),(0,_str.getString)("batchoperationconfirmremovesubmission","mod_assign"),(0,_str.getString)("batchoperationremovesubmission","mod_assign")).then((()=>{const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value)),url=new URL(window.location.href);url.searchParams.set("id",_classPrivateFieldGet(this,_cmid));const form=document.createElement("form");form.method="POST",form.action=url.toString(),((form,hiddenInputs)=>{for(const[name,value]of Object.entries(hiddenInputs)){const input=document.createElement("input");input.type="hidden",input.name=name,input.value=value,form.appendChild(input)}})(form,{action:"gradingbatchoperation",operation:"removesubmission",selectedusers:selectedUsers.join(","),sesskey:_classPrivateFieldGet(this,_sesskey)}),document.body.appendChild(form),form.submit(),form.remove()})).catch((()=>{}))}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_delete_trigger",{})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=delete.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"delete.min.js","sources":["../../../src/bulkactions/grading/delete.js"],"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 * Class that defines the bulk action for removing submissions in the assignment grading page.\n *\n * @module mod_assign/bulkactions/grading/delete\n * @copyright 2024 Shamim Rezaie <shamim@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BulkAction from 'core/bulkactions/bulk_action';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport {getString} from 'core/str';\n\nconst Selectors = {\n selectBulkItemCheckbox: 'input[type=\"checkbox\"][name=\"selectedusers\"]:checked',\n};\n\nexport default class extends BulkAction {\n /** @type {number} The course module ID. */\n #cmid;\n\n /** @type {string} The session key. */\n #sesskey;\n\n /**\n * The class constructor.\n *\n * @param {number} cmid The course module ID.\n * @param {string} sesskey The session key.\n */\n constructor(cmid, sesskey) {\n super();\n this.#cmid = cmid;\n this.#sesskey = sesskey;\n }\n\n getBulkActionTriggerSelector() {\n return 'button[data-action=\"removesubmission\"]';\n }\n\n async triggerBulkAction() {\n Notification.deleteCancelPromise(\n getString('removesubmission', 'mod_assign'),\n getString('batchoperationconfirmremovesubmission', 'mod_assign'),\n getString('batchoperationremovesubmission', 'mod_assign'),\n ).then(() => {\n const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);\n const url = new URL(window.location.href);\n url.searchParams.set('id', this.#cmid);\n\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = url.toString();\n\n // Create hidden inputs for the form.\n ((form, hiddenInputs) => {\n for (const [name, value] of Object.entries(hiddenInputs)) {\n const input = document.createElement('input');\n input.type = 'hidden';\n input.name = name;\n input.value = value;\n form.appendChild(input);\n }\n })(form, {\n action: 'gradingbatchoperation',\n operation: 'removesubmission',\n selectedusers: selectedUsers.join(','),\n sesskey: this.#sesskey,\n });\n\n // Append the form to the body, submit it, and then remove it from the DOM.\n document.body.appendChild(form);\n form.submit();\n form.remove();\n\n return;\n }).catch(() => {\n return;\n });\n }\n\n async renderBulkActionTrigger() {\n return Templates.render('mod_assign/bulkactions/grading/bulk_delete_trigger', {});\n }\n}\n"],"names":["Selectors","BulkAction","constructor","cmid","sesskey","getBulkActionTriggerSelector","deleteCancelPromise","then","selectedUsers","document","querySelectorAll","map","checkbox","value","url","URL","window","location","href","searchParams","set","this","form","createElement","method","action","toString","hiddenInputs","name","Object","entries","input","type","appendChild","operation","selectedusers","join","body","submit","remove","catch","Templates","render"],"mappings":"qhDA4BMA,iCACsB,yHAGCC,qBAazBC,YAAYC,KAAMC,yLAEDD,0CACGC,SAGpBC,qCACW,yFAIMC,qBACT,kBAAU,mBAAoB,eAC9B,kBAAU,wCAAyC,eACnD,kBAAU,iCAAkC,eAC9CC,MAAK,WACGC,cAAgB,IAAIC,SAASC,iBAAiBV,mCAAmCW,KAAIC,UAAYA,SAASC,QAC1GC,IAAM,IAAIC,IAAIC,OAAOC,SAASC,MACpCJ,IAAIK,aAAaC,IAAI,2BAAMC,mBAErBC,KAAOb,SAASc,cAAc,QACpCD,KAAKE,OAAS,OACdF,KAAKG,OAASX,IAAIY,aAGhBJ,KAAMK,oBACC,MAAOC,KAAMf,SAAUgB,OAAOC,QAAQH,cAAe,OAChDI,MAAQtB,SAASc,cAAc,SACrCQ,MAAMC,KAAO,SACbD,MAAMH,KAAOA,KACbG,MAAMlB,MAAQA,MACdS,KAAKW,YAAYF,UAEtBT,KAAM,CACLG,OAAQ,wBACRS,UAAW,mBACXC,cAAe3B,cAAc4B,KAAK,KAClChC,8BAASiB,iBAIbZ,SAAS4B,KAAKJ,YAAYX,MAC1BA,KAAKgB,SACLhB,KAAKiB,YAGNC,OAAM,gDAMFC,mBAAUC,OAAO,qDAAsD"}

View File

@ -0,0 +1,3 @@
define("mod_assign/bulkactions/grading/extend",["exports","core/bulkactions/bulk_action","core/notification","core/templates","core/str"],(function(_exports,_bulk_action,_notification,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';var _cmid=new WeakMap;class _default extends _bulk_action.default{constructor(cmid){super(),_classPrivateFieldInitSpec(this,_cmid,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_cmid,cmid)}getBulkActionTriggerSelector(){return'button[data-action="grantextension"]'}async triggerBulkAction(){_notification.default.saveCancelPromise((0,_str.getString)("grantextension","mod_assign"),(0,_str.getString)("batchoperationconfirmgrantextension","mod_assign"),(0,_str.getString)("batchoperationgrantextension","mod_assign")).then((()=>{const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value)),url=new URL(window.location.href);var receiver;url.searchParams.set("id",function(receiver,descriptor){return descriptor.get?descriptor.get.call(receiver):descriptor.value}(receiver=this,_classExtractFieldDescriptor(receiver,_cmid,"get"))),url.searchParams.set("action","grantextension"),url.searchParams.set("selectedusers",selectedUsers.join(",")),window.location=url})).catch((()=>{}))}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_extend_trigger",{})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=extend.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"extend.min.js","sources":["../../../src/bulkactions/grading/extend.js"],"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 * Class that defines the bulk action to extend the assignment deadline in the assignment grading page.\n *\n * @module mod_assign/bulkactions/grading/extend\n * @copyright 2024 Shamim Rezaie <shamim@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BulkAction from 'core/bulkactions/bulk_action';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport {getString} from 'core/str';\n\nconst Selectors = {\n selectBulkItemCheckbox: 'input[type=\"checkbox\"][name=\"selectedusers\"]:checked',\n};\n\nexport default class extends BulkAction {\n /** @type {number} The course module ID. */\n #cmid;\n\n /**\n * The class constructor.\n *\n * @param {number} cmid The course module ID.\n */\n constructor(cmid) {\n super();\n this.#cmid = cmid;\n }\n\n getBulkActionTriggerSelector() {\n return 'button[data-action=\"grantextension\"]';\n }\n\n async triggerBulkAction() {\n Notification.saveCancelPromise(\n getString('grantextension', 'mod_assign'),\n getString('batchoperationconfirmgrantextension', 'mod_assign'),\n getString('batchoperationgrantextension', 'mod_assign'),\n ).then(() => {\n const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);\n const url = new URL(window.location.href);\n url.searchParams.set('id', this.#cmid);\n url.searchParams.set('action', 'grantextension');\n url.searchParams.set('selectedusers', selectedUsers.join(','));\n window.location = url;\n\n return;\n }).catch(() => {\n return;\n });\n }\n\n async renderBulkActionTrigger() {\n return Templates.render('mod_assign/bulkactions/grading/bulk_extend_trigger', {});\n }\n}\n"],"names":["Selectors","BulkAction","constructor","cmid","getBulkActionTriggerSelector","saveCancelPromise","then","selectedUsers","document","querySelectorAll","map","checkbox","value","url","URL","window","location","href","searchParams","set","this","join","catch","Templates","render"],"mappings":"0yCA4BMA,iCACsB,oGAGCC,qBASzBC,YAAYC,iHAEKA,MAGjBC,qCACW,uFAIMC,mBACT,kBAAU,iBAAkB,eAC5B,kBAAU,sCAAuC,eACjD,kBAAU,+BAAgC,eAC5CC,MAAK,WACGC,cAAgB,IAAIC,SAASC,iBAAiBT,mCAAmCU,KAAIC,UAAYA,SAASC,QAC1GC,IAAM,IAAIC,IAAIC,OAAOC,SAASC,mBACpCJ,IAAIK,aAAaC,IAAI,kHAAMC,0DAC3BP,IAAIK,aAAaC,IAAI,SAAU,kBAC/BN,IAAIK,aAAaC,IAAI,gBAAiBZ,cAAcc,KAAK,MACzDN,OAAOC,SAAWH,OAGnBS,OAAM,gDAMFC,mBAAUC,OAAO,qDAAsD"}

View File

@ -0,0 +1,3 @@
define("mod_assign/bulkactions/grading/general_action",["exports","core/bulkactions/bulk_action","core/notification","core/templates"],(function(_exports,_bulk_action,_notification,_templates){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldGet(receiver,privateMap){return function(receiver,descriptor){if(descriptor.get)return descriptor.get.call(receiver);return descriptor.value}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"get"))}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';var _cmid=new WeakMap,_buttonIcon=new WeakMap,_buttonLabel=new WeakMap,_confirmationTitle=new WeakMap,_confirmationQuestion=new WeakMap,_confirmationYes=new WeakMap,_sesskey=new WeakMap;class _default extends _bulk_action.default{constructor(cmid,sesskey,actionKey,buttonLabel,buttonIcon,confirmationTitle,confirmationQuestion,confirmationYes){var obj,key,value;super(),value=void 0,(key="actionKey")in(obj=this)?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,_classPrivateFieldInitSpec(this,_cmid,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_buttonIcon,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_buttonLabel,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_confirmationTitle,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_confirmationQuestion,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_confirmationYes,{writable:!0,value:void 0}),_classPrivateFieldInitSpec(this,_sesskey,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_cmid,cmid),_classPrivateFieldSet(this,_sesskey,sesskey),this.actionKey=actionKey,_classPrivateFieldSet(this,_buttonLabel,buttonLabel),_classPrivateFieldSet(this,_buttonIcon,buttonIcon),_classPrivateFieldSet(this,_confirmationTitle,confirmationTitle),_classPrivateFieldSet(this,_confirmationQuestion,confirmationQuestion),_classPrivateFieldSet(this,_confirmationYes,confirmationYes)}getBulkActionTriggerSelector(){return'button[data-action="'.concat(this.actionKey,'"]')}async triggerBulkAction(){_notification.default.saveCancelPromise(_classPrivateFieldGet(this,_confirmationTitle),_classPrivateFieldGet(this,_confirmationQuestion),_classPrivateFieldGet(this,_confirmationYes)).then((()=>{const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value)),url=new URL(window.location.href);url.searchParams.set("id",_classPrivateFieldGet(this,_cmid));const form=document.createElement("form");form.method="POST",form.action=url.toString(),((form,hiddenInputs)=>{for(const[name,value]of Object.entries(hiddenInputs)){const input=document.createElement("input");input.type="hidden",input.name=name,input.value=value,form.appendChild(input)}})(form,{action:"gradingbatchoperation",operation:this.actionKey,selectedusers:selectedUsers.join(","),sesskey:_classPrivateFieldGet(this,_sesskey)}),document.body.appendChild(form),form.submit(),form.remove()})).catch((()=>{}))}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_general_action_trigger",{action:this.actionKey,title:await _classPrivateFieldGet(this,_buttonLabel),icon:await _classPrivateFieldGet(this,_buttonIcon)})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=general_action.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
define("mod_assign/bulkactions/grading/message",["exports","core/bulkactions/bulk_action","core/templates","core_message/message_send_bulk"],(function(_exports,_bulk_action,_templates,_message_send_bulk){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Bulk action for messaging users in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/message
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';class _default extends _bulk_action.default{getBulkActionTriggerSelector(){return'button[data-action="message"]'}triggerBulkAction(){const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value));(0,_message_send_bulk.showModal)(selectedUsers)}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_message_trigger",{})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=message.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"message.min.js","sources":["../../../src/bulkactions/grading/message.js"],"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 * Bulk action for messaging users in the assignment grading page.\n *\n * @module mod_assign/bulkactions/grading/message\n * @copyright 2024 Shamim Rezaie <shamim@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BulkAction from 'core/bulkactions/bulk_action';\nimport Templates from 'core/templates';\nimport {showModal as showMessageModal} from 'core_message/message_send_bulk';\n\nconst Selectors = {\n selectBulkItemCheckbox: 'input[type=\"checkbox\"][name=\"selectedusers\"]:checked',\n};\n\nexport default class extends BulkAction {\n getBulkActionTriggerSelector() {\n return 'button[data-action=\"message\"]';\n }\n\n triggerBulkAction() {\n const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);\n showMessageModal(selectedUsers);\n }\n\n async renderBulkActionTrigger() {\n return Templates.render('mod_assign/bulkactions/grading/bulk_message_trigger', {});\n }\n}\n"],"names":["Selectors","BulkAction","getBulkActionTriggerSelector","triggerBulkAction","selectedUsers","document","querySelectorAll","map","checkbox","value","Templates","render"],"mappings":";;;;;;;2LA2BMA,iCACsB,8EAGCC,qBACzBC,qCACW,gCAGVC,0BACSC,cAAgB,IAAIC,SAASC,iBAAiBN,mCAAmCO,KAAIC,UAAYA,SAASC,yCAC9FL,sDAIXM,mBAAUC,OAAO,sDAAuD"}

View File

@ -0,0 +1,3 @@
define("mod_assign/bulkactions/grading/setmarkingallocation",["exports","core/bulkactions/bulk_action","core/notification","core/templates","core/str"],(function(_exports,_bulk_action,_notification,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';var _cmid=new WeakMap;class _default extends _bulk_action.default{constructor(cmid){super(),_classPrivateFieldInitSpec(this,_cmid,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_cmid,cmid)}getBulkActionTriggerSelector(){return'button[data-action="setmarkingallocation"]'}async triggerBulkAction(){_notification.default.saveCancelPromise((0,_str.getString)("setmarkingallocation","mod_assign"),(0,_str.getString)("batchoperationconfirmsetmarkingallocation","mod_assign"),(0,_str.getString)("batchoperationsetmarkingallocation","mod_assign")).then((()=>{const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value)),url=new URL(window.location.href);var receiver;url.searchParams.set("id",function(receiver,descriptor){return descriptor.get?descriptor.get.call(receiver):descriptor.value}(receiver=this,_classExtractFieldDescriptor(receiver,_cmid,"get"))),url.searchParams.set("action","viewbatchmarkingallocation"),url.searchParams.set("selectedusers",selectedUsers.join(",")),window.location=url})).catch((()=>{}))}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_setmarkingallocation_trigger",{})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=setmarkingallocation.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"setmarkingallocation.min.js","sources":["../../../src/bulkactions/grading/setmarkingallocation.js"],"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 * Bulk action for allocating markers in the assignment grading page.\n *\n * @module mod_assign/bulkactions/grading/setmarkingallocation\n * @copyright 2024 Shamim Rezaie <shamim@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BulkAction from 'core/bulkactions/bulk_action';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport {getString} from 'core/str';\n\nconst Selectors = {\n selectBulkItemCheckbox: 'input[type=\"checkbox\"][name=\"selectedusers\"]:checked',\n};\n\nexport default class extends BulkAction {\n /** @type {number} The course module ID. */\n #cmid;\n\n /**\n * The class constructor.\n *\n * @param {number} cmid The course module ID.\n */\n constructor(cmid) {\n super();\n this.#cmid = cmid;\n }\n\n getBulkActionTriggerSelector() {\n return 'button[data-action=\"setmarkingallocation\"]';\n }\n\n async triggerBulkAction() {\n Notification.saveCancelPromise(\n getString('setmarkingallocation', 'mod_assign'),\n getString('batchoperationconfirmsetmarkingallocation', 'mod_assign'),\n getString('batchoperationsetmarkingallocation', 'mod_assign'),\n ).then(() => {\n const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);\n const url = new URL(window.location.href);\n url.searchParams.set('id', this.#cmid);\n url.searchParams.set('action', 'viewbatchmarkingallocation');\n url.searchParams.set('selectedusers', selectedUsers.join(','));\n window.location = url;\n\n return;\n }).catch(() => {\n return;\n });\n }\n\n async renderBulkActionTrigger() {\n return Templates.render('mod_assign/bulkactions/grading/bulk_setmarkingallocation_trigger', {});\n }\n}\n"],"names":["Selectors","BulkAction","constructor","cmid","getBulkActionTriggerSelector","saveCancelPromise","then","selectedUsers","document","querySelectorAll","map","checkbox","value","url","URL","window","location","href","searchParams","set","this","join","catch","Templates","render"],"mappings":"wzCA4BMA,iCACsB,oGAGCC,qBASzBC,YAAYC,iHAEKA,MAGjBC,qCACW,6FAIMC,mBACT,kBAAU,uBAAwB,eAClC,kBAAU,4CAA6C,eACvD,kBAAU,qCAAsC,eAClDC,MAAK,WACGC,cAAgB,IAAIC,SAASC,iBAAiBT,mCAAmCU,KAAIC,UAAYA,SAASC,QAC1GC,IAAM,IAAIC,IAAIC,OAAOC,SAASC,mBACpCJ,IAAIK,aAAaC,IAAI,kHAAMC,0DAC3BP,IAAIK,aAAaC,IAAI,SAAU,8BAC/BN,IAAIK,aAAaC,IAAI,gBAAiBZ,cAAcc,KAAK,MACzDN,OAAOC,SAAWH,OAGnBS,OAAM,gDAMFC,mBAAUC,OAAO,mEAAoE"}

View File

@ -0,0 +1,3 @@
define("mod_assign/bulkactions/grading/setmarkingworkflowstate",["exports","core/bulkactions/bulk_action","core/notification","core/templates","core/str"],(function(_exports,_bulk_action,_notification,_templates,_str){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _classPrivateFieldInitSpec(obj,privateMap,value){!function(obj,privateCollection){if(privateCollection.has(obj))throw new TypeError("Cannot initialize the same private elements twice on an object")}(obj,privateMap),privateMap.set(obj,value)}function _classPrivateFieldSet(receiver,privateMap,value){return function(receiver,descriptor,value){if(descriptor.set)descriptor.set.call(receiver,value);else{if(!descriptor.writable)throw new TypeError("attempted to set read only private field");descriptor.value=value}}(receiver,_classExtractFieldDescriptor(receiver,privateMap,"set"),value),value}function _classExtractFieldDescriptor(receiver,privateMap,action){if(!privateMap.has(receiver))throw new TypeError("attempted to "+action+" private field on non-instance");return privateMap.get(receiver)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_bulk_action=_interopRequireDefault(_bulk_action),_notification=_interopRequireDefault(_notification),_templates=_interopRequireDefault(_templates);const Selectors_selectBulkItemCheckbox='input[type="checkbox"][name="selectedusers"]:checked';var _cmid=new WeakMap;class _default extends _bulk_action.default{constructor(cmid){super(),_classPrivateFieldInitSpec(this,_cmid,{writable:!0,value:void 0}),_classPrivateFieldSet(this,_cmid,cmid)}getBulkActionTriggerSelector(){return'button[data-action="setmarkingworkflowstate"]'}async triggerBulkAction(){_notification.default.saveCancelPromise((0,_str.getString)("setmarkingworkflowstate","mod_assign"),(0,_str.getString)("batchoperationconfirmsetmarkingworkflowstate","mod_assign"),(0,_str.getString)("batchoperationsetmarkingworkflowstate","mod_assign")).then((()=>{const selectedUsers=[...document.querySelectorAll(Selectors_selectBulkItemCheckbox)].map((checkbox=>checkbox.value)),url=new URL(window.location.href);var receiver;url.searchParams.set("id",function(receiver,descriptor){return descriptor.get?descriptor.get.call(receiver):descriptor.value}(receiver=this,_classExtractFieldDescriptor(receiver,_cmid,"get"))),url.searchParams.set("action","viewbatchsetmarkingworkflowstate"),url.searchParams.set("selectedusers",selectedUsers.join(",")),window.location=url})).catch((()=>{}))}async renderBulkActionTrigger(){return _templates.default.render("mod_assign/bulkactions/grading/bulk_setmarkingworkflowstate_trigger",{})}}return _exports.default=_default,_exports.default}));
//# sourceMappingURL=setmarkingworkflowstate.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"setmarkingworkflowstate.min.js","sources":["../../../src/bulkactions/grading/setmarkingworkflowstate.js"],"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 * Class that defines the bulk action for setting marking workflow state in the assignment grading page.\n *\n * @module mod_assign/bulkactions/grading/setmarkingworkflowstate\n * @copyright 2024 Shamim Rezaie <shamim@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport BulkAction from 'core/bulkactions/bulk_action';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport {getString} from 'core/str';\n\nconst Selectors = {\n selectBulkItemCheckbox: 'input[type=\"checkbox\"][name=\"selectedusers\"]:checked',\n};\n\nexport default class extends BulkAction {\n /** @type {number} The course module ID. */\n #cmid;\n\n /**\n * The class constructor.\n *\n * @param {number} cmid The course module ID.\n */\n constructor(cmid) {\n super();\n this.#cmid = cmid;\n }\n\n getBulkActionTriggerSelector() {\n return 'button[data-action=\"setmarkingworkflowstate\"]';\n }\n\n async triggerBulkAction() {\n Notification.saveCancelPromise(\n getString('setmarkingworkflowstate', 'mod_assign'),\n getString('batchoperationconfirmsetmarkingworkflowstate', 'mod_assign'),\n getString('batchoperationsetmarkingworkflowstate', 'mod_assign'),\n ).then(() => {\n const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);\n const url = new URL(window.location.href);\n url.searchParams.set('id', this.#cmid);\n url.searchParams.set('action', 'viewbatchsetmarkingworkflowstate');\n url.searchParams.set('selectedusers', selectedUsers.join(','));\n window.location = url;\n\n return;\n }).catch(() => {\n return;\n });\n }\n\n async renderBulkActionTrigger() {\n return Templates.render('mod_assign/bulkactions/grading/bulk_setmarkingworkflowstate_trigger', {});\n }\n}\n"],"names":["Selectors","BulkAction","constructor","cmid","getBulkActionTriggerSelector","saveCancelPromise","then","selectedUsers","document","querySelectorAll","map","checkbox","value","url","URL","window","location","href","searchParams","set","this","join","catch","Templates","render"],"mappings":"2zCA4BMA,iCACsB,oGAGCC,qBASzBC,YAAYC,iHAEKA,MAGjBC,qCACW,gGAIMC,mBACT,kBAAU,0BAA2B,eACrC,kBAAU,+CAAgD,eAC1D,kBAAU,wCAAyC,eACrDC,MAAK,WACGC,cAAgB,IAAIC,SAASC,iBAAiBT,mCAAmCU,KAAIC,UAAYA,SAASC,QAC1GC,IAAM,IAAIC,IAAIC,OAAOC,SAASC,mBACpCJ,IAAIK,aAAaC,IAAI,kHAAMC,0DAC3BP,IAAIK,aAAaC,IAAI,SAAU,oCAC/BN,IAAIK,aAAaC,IAAI,gBAAiBZ,cAAcc,KAAK,MACzDN,OAAOC,SAAWH,OAGnBS,OAAM,gDAMFC,mBAAUC,OAAO,sEAAuE"}

View File

@ -0,0 +1,233 @@
// 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/>.
/**
* Class for defining the bulk actions area in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/bulk_actions
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkActions from 'core/bulkactions/bulk_actions';
import GeneralAction from './general_action';
import DeleteAction from './delete';
import ExtendAction from './extend';
import MessageAction from './message';
import SetMarkingAllocationAction from './setmarkingallocation';
import SetMarkingWorkflowStateAction from './setmarkingworkflowstate';
import Templates from 'core/templates';
import {getString} from 'core/str';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]',
selectBulkItemTrigger: 'input[type="checkbox"][name="selectedusers"], input[type="checkbox"][name="selectall"]',
};
export default class extends BulkActions {
/** @type {number} The course module ID. */
#cmid;
/** @type {boolean} Whether to show the extend action. */
#extend;
/** @type {boolean} Whether to show the grant extension action. */
#grantAttempt;
/** @type {boolean} Whether to show the set marking allocation action. */
#markingAllocation;
/** @type {string} Whether to show the message action. */
#message;
/** @type {Array} The list of plugin operations. */
#pluginOperations;
/** @type {boolean} Whether to show the remove submission action. */
#removeSubmission;
/** @type {string} The session key. */
#sesskey;
/** @type {boolean} Whether to show the revert to draft action. */
#submissionDrafts;
/** @type {boolean} Whether to show the set workflow state action. */
#workflowState;
/**
* Returns the instance of the class.
*
* @param {Object} options - The options object.
* @param {number} options.cmid - The course module ID.
* @param {string} options.message - Whether to show the message action.
* @param {boolean} options.submissiondrafts - Whether to show the revert to draft action.
* @param {boolean} options.removesubmission - Whether to show the remove submission action.
* @param {boolean} options.extend - Whether to show the grant extension action.
* @param {boolean} options.grantattempt - Whether to show the grant attempt action.
* @param {boolean} options.workflowstate - Whether to show the set workflow state action.
* @param {boolean} options.markingallocation - Whether to show the set marking allocation action.
* @param {Array} options.pluginoperations - The list of plugin operations.
* @param {string} options.sesskey - The session key.
* @returns {this} An instance of the anonymous class extending BulkActions.
*/
static init(options) {
return new this(options);
}
/**
* The class constructor
*
* @param {Object} options - The options object.
* @param {number} options.cmid - The course module ID.
* @param {string} options.message - Whether to show the message action.
* @param {boolean} options.submissiondrafts - Whether to show the revert to draft action.
* @param {boolean} options.removesubmission - Whether to show the remove submission action.
* @param {boolean} options.extend - Whether to show the grant extension action.
* @param {boolean} options.grantattempt - Whether to show the grant attempt action.
* @param {boolean} options.workflowstate - Whether to show the set workflow state action.
* @param {boolean} options.markingallocation - Whether to show the set marking allocation action.
* @param {Array} options.pluginoperations - The list of plugin operations.
* @param {string} options.sesskey - The session key.
*/
constructor({
cmid, message, submissiondrafts, removesubmission, extend,
grantattempt, workflowstate, markingallocation, pluginoperations, sesskey
}) {
super();
this.#cmid = cmid;
this.#message = message;
this.#submissionDrafts = submissiondrafts;
this.#removeSubmission = removesubmission;
this.#extend = extend;
this.#grantAttempt = grantattempt;
this.#workflowState = workflowstate;
this.#markingAllocation = markingallocation;
this.#sesskey = sesskey;
this.#pluginOperations = pluginoperations;
}
getBulkActions() {
const actions = [
new GeneralAction(
this.#cmid,
this.#sesskey,
'lock',
getString('batchoperationlock', 'mod_assign'),
Templates.renderPix('i/lock', 'core'),
getString('locksubmissions', 'mod_assign'),
getString('batchoperationconfirmlock', 'mod_assign'),
getString('batchoperationlock', 'mod_assign'),
),
new GeneralAction(
this.#cmid,
this.#sesskey,
'unlock',
getString('batchoperationunlock', 'mod_assign'),
Templates.renderPix('i/unlock', 'core'),
getString('unlocksubmissions', 'mod_assign'),
getString('batchoperationconfirmunlock', 'mod_assign'),
getString('batchoperationunlock', 'mod_assign'),
),
new GeneralAction(
this.#cmid,
this.#sesskey,
'downloadselected',
getString('batchoperationdownloadselected', 'mod_assign'),
Templates.renderPix('t/download', 'core'),
getString('downloadselectedsubmissions', 'mod_assign'),
getString('batchoperationconfirmdownloadselected', 'mod_assign'),
getString('batchoperationdownloadselected', 'mod_assign'),
),
];
if (this.#removeSubmission) {
actions.push(new DeleteAction(this.#cmid, this.#sesskey));
}
if (this.#extend) {
actions.push(new ExtendAction(this.#cmid));
}
if (this.#grantAttempt) {
actions.push(
new GeneralAction(
this.#cmid,
this.#sesskey,
'addattempt',
getString('batchoperationaddattempt', 'mod_assign'),
Templates.renderPix('t/add', 'core'),
getString('addattempt', 'mod_assign'),
getString('batchoperationconfirmaddattempt', 'mod_assign'),
getString('batchoperationaddattempt', 'mod_assign'),
)
);
}
if (this.#workflowState) {
actions.push(new SetMarkingWorkflowStateAction(this.#cmid));
}
if (this.#markingAllocation) {
actions.push(new SetMarkingAllocationAction(this.#cmid));
}
if (this.#submissionDrafts) {
actions.push(
new GeneralAction(
this.#cmid,
this.#sesskey,
'reverttodraft',
getString('batchoperationreverttodraft', 'mod_assign'),
Templates.renderPix('e/undo', 'core'),
getString('reverttodraft', 'mod_assign'),
getString('batchoperationconfirmreverttodraft', 'mod_assign'),
getString('batchoperationreverttodraft', 'mod_assign'),
)
);
}
if (this.#message) {
actions.push(new MessageAction());
}
for (const operation of this.#pluginOperations) {
actions.push(
new GeneralAction(
this.#cmid,
this.#sesskey,
operation.key,
operation.label,
operation.icon,
operation.confirmationtitle,
operation.confirmationquestion,
)
);
}
return actions;
}
getSelectedItems() {
return document.querySelectorAll(`${Selectors.selectBulkItemCheckbox}:checked`);
}
registerItemSelectChangeEvent(eventHandler) {
const itemSelectCheckboxes = document.querySelectorAll(Selectors.selectBulkItemTrigger);
itemSelectCheckboxes.forEach((checkbox) => {
checkbox.addEventListener('change', eventHandler.bind(this));
});
}
}

View File

@ -0,0 +1,100 @@
// 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/>.
/**
* Class that defines the bulk action for removing submissions in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/delete
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Notification from 'core/notification';
import Templates from 'core/templates';
import {getString} from 'core/str';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
/** @type {number} The course module ID. */
#cmid;
/** @type {string} The session key. */
#sesskey;
/**
* The class constructor.
*
* @param {number} cmid The course module ID.
* @param {string} sesskey The session key.
*/
constructor(cmid, sesskey) {
super();
this.#cmid = cmid;
this.#sesskey = sesskey;
}
getBulkActionTriggerSelector() {
return 'button[data-action="removesubmission"]';
}
async triggerBulkAction() {
Notification.deleteCancelPromise(
getString('removesubmission', 'mod_assign'),
getString('batchoperationconfirmremovesubmission', 'mod_assign'),
getString('batchoperationremovesubmission', 'mod_assign'),
).then(() => {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
const url = new URL(window.location.href);
url.searchParams.set('id', this.#cmid);
const form = document.createElement('form');
form.method = 'POST';
form.action = url.toString();
// Create hidden inputs for the form.
((form, hiddenInputs) => {
for (const [name, value] of Object.entries(hiddenInputs)) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = name;
input.value = value;
form.appendChild(input);
}
})(form, {
action: 'gradingbatchoperation',
operation: 'removesubmission',
selectedusers: selectedUsers.join(','),
sesskey: this.#sesskey,
});
// Append the form to the body, submit it, and then remove it from the DOM.
document.body.appendChild(form);
form.submit();
form.remove();
return;
}).catch(() => {
return;
});
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_delete_trigger', {});
}
}

View File

@ -0,0 +1,73 @@
// 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/>.
/**
* Class that defines the bulk action to extend the assignment deadline in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/extend
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Notification from 'core/notification';
import Templates from 'core/templates';
import {getString} from 'core/str';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
/** @type {number} The course module ID. */
#cmid;
/**
* The class constructor.
*
* @param {number} cmid The course module ID.
*/
constructor(cmid) {
super();
this.#cmid = cmid;
}
getBulkActionTriggerSelector() {
return 'button[data-action="grantextension"]';
}
async triggerBulkAction() {
Notification.saveCancelPromise(
getString('grantextension', 'mod_assign'),
getString('batchoperationconfirmgrantextension', 'mod_assign'),
getString('batchoperationgrantextension', 'mod_assign'),
).then(() => {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
const url = new URL(window.location.href);
url.searchParams.set('id', this.#cmid);
url.searchParams.set('action', 'grantextension');
url.searchParams.set('selectedusers', selectedUsers.join(','));
window.location = url;
return;
}).catch(() => {
return;
});
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_extend_trigger', {});
}
}

View File

@ -0,0 +1,134 @@
// 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/>.
/**
* Class that defines the bulk action for general actions in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/general_action
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Notification from 'core/notification';
import Templates from 'core/templates';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
/** @type {string} The action key. */
actionKey;
/** @type {number} The course module ID. */
#cmid;
/** @type {Promise<string>} The action button's icon. */
#buttonIcon;
/** @type {Promise<string>} The action button's label. */
#buttonLabel;
/** @type {Promise<string>} Title of the confirmation dialog. */
#confirmationTitle;
/** @type {Promise<string>} Question of the confirmation dialog. */
#confirmationQuestion;
/** @type {Promise<string>} Text for the confirmation yes button. */
#confirmationYes;
/** @type {string} The session key. */
#sesskey;
/**
* The class constructor.
*
* @param {int} cmid The course module ID.
* @param {string} sesskey The session key.
* @param {string} actionKey The action key.
* @param {Promise<string>} buttonLabel The action button's label.
* @param {Promise<string>} buttonIcon The action button's icon.
* @param {Promise<string>} confirmationTitle Title of the confirmation dialog.
* @param {Promise<string>} confirmationQuestion Question of the confirmation dialog.
* @param {Promise<string>} confirmationYes Text for the confirmation yes button.
*/
constructor(cmid, sesskey, actionKey, buttonLabel, buttonIcon, confirmationTitle, confirmationQuestion, confirmationYes) {
super();
this.#cmid = cmid;
this.#sesskey = sesskey;
this.actionKey = actionKey;
this.#buttonLabel = buttonLabel;
this.#buttonIcon = buttonIcon;
this.#confirmationTitle = confirmationTitle;
this.#confirmationQuestion = confirmationQuestion;
this.#confirmationYes = confirmationYes;
}
getBulkActionTriggerSelector() {
return `button[data-action="${this.actionKey}"]`;
}
async triggerBulkAction() {
Notification.saveCancelPromise(
this.#confirmationTitle,
this.#confirmationQuestion,
this.#confirmationYes,
).then(() => {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
const url = new URL(window.location.href);
url.searchParams.set('id', this.#cmid);
const form = document.createElement('form');
form.method = 'POST';
form.action = url.toString();
// Create hidden inputs for the form.
((form, hiddenInputs) => {
for (const [name, value] of Object.entries(hiddenInputs)) {
const input = document.createElement('input');
input.type = 'hidden';
input.name = name;
input.value = value;
form.appendChild(input);
}
})(form, {
action: 'gradingbatchoperation',
operation: this.actionKey,
selectedusers: selectedUsers.join(','),
sesskey: this.#sesskey,
});
// Append the form to the body, submit it, and then remove it from the DOM.
document.body.appendChild(form);
form.submit();
form.remove();
return;
}).catch(() => {
return;
});
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_general_action_trigger', {
action: this.actionKey,
title: await this.#buttonLabel,
icon: await this.#buttonIcon,
});
}
}

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/>.
/**
* Bulk action for messaging users in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/message
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Templates from 'core/templates';
import {showModal as showMessageModal} from 'core_message/message_send_bulk';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
getBulkActionTriggerSelector() {
return 'button[data-action="message"]';
}
triggerBulkAction() {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
showMessageModal(selectedUsers);
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_message_trigger', {});
}
}

View File

@ -0,0 +1,73 @@
// 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/>.
/**
* Bulk action for allocating markers in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/setmarkingallocation
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Notification from 'core/notification';
import Templates from 'core/templates';
import {getString} from 'core/str';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
/** @type {number} The course module ID. */
#cmid;
/**
* The class constructor.
*
* @param {number} cmid The course module ID.
*/
constructor(cmid) {
super();
this.#cmid = cmid;
}
getBulkActionTriggerSelector() {
return 'button[data-action="setmarkingallocation"]';
}
async triggerBulkAction() {
Notification.saveCancelPromise(
getString('setmarkingallocation', 'mod_assign'),
getString('batchoperationconfirmsetmarkingallocation', 'mod_assign'),
getString('batchoperationsetmarkingallocation', 'mod_assign'),
).then(() => {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
const url = new URL(window.location.href);
url.searchParams.set('id', this.#cmid);
url.searchParams.set('action', 'viewbatchmarkingallocation');
url.searchParams.set('selectedusers', selectedUsers.join(','));
window.location = url;
return;
}).catch(() => {
return;
});
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_setmarkingallocation_trigger', {});
}
}

View File

@ -0,0 +1,73 @@
// 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/>.
/**
* Class that defines the bulk action for setting marking workflow state in the assignment grading page.
*
* @module mod_assign/bulkactions/grading/setmarkingworkflowstate
* @copyright 2024 Shamim Rezaie <shamim@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import BulkAction from 'core/bulkactions/bulk_action';
import Notification from 'core/notification';
import Templates from 'core/templates';
import {getString} from 'core/str';
const Selectors = {
selectBulkItemCheckbox: 'input[type="checkbox"][name="selectedusers"]:checked',
};
export default class extends BulkAction {
/** @type {number} The course module ID. */
#cmid;
/**
* The class constructor.
*
* @param {number} cmid The course module ID.
*/
constructor(cmid) {
super();
this.#cmid = cmid;
}
getBulkActionTriggerSelector() {
return 'button[data-action="setmarkingworkflowstate"]';
}
async triggerBulkAction() {
Notification.saveCancelPromise(
getString('setmarkingworkflowstate', 'mod_assign'),
getString('batchoperationconfirmsetmarkingworkflowstate', 'mod_assign'),
getString('batchoperationsetmarkingworkflowstate', 'mod_assign'),
).then(() => {
const selectedUsers = [...document.querySelectorAll(Selectors.selectBulkItemCheckbox)].map(checkbox => checkbox.value);
const url = new URL(window.location.href);
url.searchParams.set('id', this.#cmid);
url.searchParams.set('action', 'viewbatchsetmarkingworkflowstate');
url.searchParams.set('selectedusers', selectedUsers.join(','));
window.location = url;
return;
}).catch(() => {
return;
});
}
async renderBulkActionTrigger() {
return Templates.render('mod_assign/bulkactions/grading/bulk_setmarkingworkflowstate_trigger', {});
}
}

View File

@ -1131,23 +1131,6 @@ class renderer extends \plugin_renderer_base {
$o .= $this->output->box_start('boxaligncenter gradingtable position-relative');
$this->page->requires->js_init_call('M.mod_assign.init_grading_table', array());
$this->page->requires->string_for_js('nousersselected', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmgrantextension', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmlock', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmremovesubmission', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmreverttodraft', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmunlock', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmaddattempt', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmdownloadselected', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmsetmarkingworkflowstate', 'assign');
$this->page->requires->string_for_js('batchoperationconfirmsetmarkingallocation', 'assign');
$this->page->requires->string_for_js('editaction', 'assign');
foreach ($table->plugingradingbatchoperations as $plugin => $operations) {
foreach ($operations as $operation => $description) {
$this->page->requires->string_for_js('batchoperationconfirm' . $operation,
'assignfeedback_' . $plugin);
}
}
$o .= $this->flexible_table($table, $table->get_rows_per_page(), true);
$o .= $this->output->box_end();

View File

@ -23,6 +23,7 @@
*/
$string['batchoperationconfirmuploadfiles'] = 'Upload one or more feedback files for all selected users?';
$string['batchoperationuploadfiles'] = 'Upload feedback';
$string['batchuploadfiles'] = 'Upload feedback files for multiple users';
$string['batchuploadfilesforusers'] = 'Send feedback files to {$a} selected user(s).';
$string['configmaxbytes'] = 'Maximum file size';

View File

@ -433,14 +433,18 @@ class assign_feedback_file extends assign_feedback_plugin {
return true;
}
/**
* Return a list of the batch grading operations performed by this plugin.
* This plugin supports batch upload files and upload zip.
*
* @return array The list of batch grading operations
*/
public function get_grading_batch_operations() {
return array('uploadfiles'=>get_string('uploadfiles', 'assignfeedback_file'));
public function get_grading_batch_operation_details() {
global $OUTPUT;
return [
(object) [
'key' => 'uploadfiles',
'label' => get_string('batchoperationuploadfiles', 'assignfeedback_file'),
'icon' => $OUTPUT->pix_icon('i/upload', ''),
'confirmationtitle' => get_string('uploadfiles', 'assignfeedback_file'),
'confirmationquestion' => get_string('batchoperationconfirmuploadfiles', 'assignfeedback_file'),
],
];
}
/**

View File

@ -158,14 +158,33 @@ abstract class assign_feedback_plugin extends assign_plugin {
return false;
}
/**
* Return a list of detailed batch grading operations supported by this plugin.
*
* @return array - An array of objects containing batch operation details. Each object should contain:
* - 'key': the action identifier (string)
* - 'label': the button label (string)
* - 'icon': the button icon (string)
* - 'confirmationtitle': the title for the confirmation modal (string)
* - 'confirmationquestion': the question for the confirmation modal (string)
*/
public function get_grading_batch_operation_details() {
return [];
}
/**
* Return a list of the batch grading operations supported by this plugin.
*
* @return array - An array of action and description strings.
* The action will be passed to grading_batch_operation.
* @deprecated since 4.5, use get_grading_batch_operation_details() instead.
* @todo Final deprecation in Moodle 6.0. See MDL-82856.
*/
#[\core\attribute\deprecated('get_grading_batch_operation_details', since: '4.5', mdl: 'MDL-80750')]
public function get_grading_batch_operations() {
return array();
\core\deprecation::emit_deprecation_if_present([$this, __FUNCTION__]);
return array_column(static::get_grading_batch_operation_details(), 'confirmationtitle', 'key');
}
/**

View File

@ -33,12 +33,30 @@ require_once($CFG->dirroot . '/mod/assign/locallib.php');
* @package mod_assign
* @copyright 2012 NetSpot {@link http://www.netspot.com.au}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @deprecated since 4.5
* @todo Final deprecation in Moodle 6.0. See MDL-82869.
*/
#[\core\attribute\deprecated(
replacement: null,
since: '4.5',
reason: 'It is no longer used.',
mdl: 'MDL-80750',
)]
class mod_assign_grading_batch_operations_form extends moodleform {
/**
* Define this form - called by the parent constructor.
*
* @deprecated since 4.5
*/
#[\core\attribute\deprecated(
replacement: null,
since: '4.5',
reason: 'It is no longer used.',
mdl: 'MDL-80750'
)]
public function definition() {
\core\deprecation::emit_deprecation_if_present([$this, __FUNCTION__]);
global $CFG;
$mform = $this->_form;
$instance = $this->_customdata;
@ -100,4 +118,3 @@ class mod_assign_grading_batch_operations_form extends moodleform {
$mform->addElement('group', 'actionsgrp', $batchdescription, $objs, ' ', false);
}
}

View File

@ -60,8 +60,6 @@ class assign_grading_table extends table_sql implements renderable {
private $groupsubmissions = array();
/** @var array $submissiongroups - A static cache of submission groups */
private $submissiongroups = array();
/** @var string $plugingradingbatchoperations - List of plugin supported batch operations */
public $plugingradingbatchoperations = array();
/** @var array $plugincache - A cache of plugin lookups to match a column name to a plugin efficiently */
private $plugincache = array();
/** @var array $scale - A list of the keys and descriptions for the custom scale */
@ -102,16 +100,6 @@ class assign_grading_table extends table_sql implements renderable {
$this->hasviewblind = has_capability('mod/assign:viewblinddetails',
$this->assignment->get_context());
foreach ($assignment->get_feedback_plugins() as $plugin) {
if ($plugin->is_visible() && $plugin->is_enabled()) {
foreach ($plugin->get_grading_batch_operations() as $action => $description) {
if (empty($this->plugingradingbatchoperations)) {
$this->plugingradingbatchoperations[$plugin->get_type()] = array();
}
$this->plugingradingbatchoperations[$plugin->get_type()][$action] = $description;
}
}
}
$this->perpage = $perpage;
$this->quickgrading = $quickgrading && $this->hasgrade;
$this->output = $PAGE->get_renderer('mod_assign');
@ -931,6 +919,7 @@ class assign_grading_table extends table_sql implements renderable {
$selectcol .= get_string('selectuser', 'assign', $this->assignment->fullname($row));
$selectcol .= '</label>';
$selectcol .= '<input type="checkbox"
class="ignoredirty"
id="selectuser_' . $row->userid . '"
name="selectedusers"
value="' . $row->userid . '"/>';

View File

@ -122,6 +122,7 @@ $string['attemptreopenmethod_untilpass_help'] = 'After each attempt, the next wi
$string['availability'] = 'Availability';
$string['back'] = 'Back';
$string['backtoassignment'] = 'Back to assignment';
$string['batchoperationaddattempt'] = 'Grant attempt';
$string['batchoperationsdescription'] = 'With selected...';
$string['batchoperationconfirmlock'] = 'Lock all selected submissions?';
$string['batchoperationconfirmgrantextension'] = 'Grant an extension to all selected submissions?';
@ -132,9 +133,14 @@ $string['batchoperationconfirmaddattempt'] = 'Allow another attempt for selected
$string['batchoperationconfirmsetmarkingworkflowstate'] = 'Set marking workflow state for all selected submissions?';
$string['batchoperationconfirmsetmarkingallocation'] = 'Set marking allocation for all selected submissions?';
$string['batchoperationconfirmdownloadselected'] = 'Download selected submissions?';
$string['batchoperationlock'] = 'lock submissions';
$string['batchoperationunlock'] = 'unlock submissions';
$string['batchoperationreverttodraft'] = 'revert submissions to draft';
$string['batchoperationdownloadselected'] = 'Download';
$string['batchoperationgrantextension'] = 'Extend';
$string['batchoperationlock'] = 'Lock';
$string['batchoperationremovesubmission'] = 'Delete';
$string['batchoperationunlock'] = 'Unlock';
$string['batchoperationreverttodraft'] = 'Revert to draft';
$string['batchoperationsetmarkingallocation'] = 'Allocate marker';
$string['batchoperationsetmarkingworkflowstate'] = 'Change marking state';
$string['batchsetallocatedmarker'] = 'Set allocated marker for {$a} selected user(s).';
$string['batchsetmarkingworkflowstateforusers'] = 'Set marking workflow state for {$a} selected user(s).';
$string['beginassignment'] = 'Begin assignment';
@ -209,7 +215,6 @@ $string['editsubmission'] = 'Edit submission';
$string['editsubmissionother'] = 'Edit submission for {$a}';
$string['editsubmission_help'] = 'You can still make changes to your submission.';
$string['editingstatus'] = 'Editing status';
$string['editaction'] = 'Actions...';
$string['enabled'] = 'Enabled';
$string['enabletimelimit'] = 'Enable timed assignments';
$string['enabletimelimit_help'] = 'If enabled, you can set a time limit on assignment settings page.';
@ -702,6 +707,7 @@ $string['xofy'] = '{$a->x} of {$a->y}';
$string['attemptreopenmethod_none'] = 'Never';
$string['choosegradingaction'] = 'Grading action';
$string['downloadasfolders_help'] = 'Assignment submissions may be downloaded in folders. Each submission is then put in a separate folder, with the folder structure kept for any subfolders, and files are not renamed.';
$string['editaction'] = 'Actions...';
$string['groupoverridesdeleted'] = 'Group overrides deleted';
$string['updategrade'] = 'Update grade';
$string['useroverridesdeleted'] = 'User overrides deleted';

View File

@ -5,3 +5,4 @@ choosegradingaction,mod_assign
updategrade,mod_assign
viewgrader,mod_assign
downloadasfolders_help,mod_assign
editaction,mod_assign

View File

@ -594,7 +594,7 @@ class assign {
$action = 'viewsubmitforgradingerror';
}
} else if ($action == 'gradingbatchoperation') {
$action = $this->process_grading_batch_operation($mform);
$action = $this->process_grading_batch_operation();
if ($action == 'grading') {
$action = 'redirect';
$nextpageparams['action'] = 'grading';
@ -699,20 +699,20 @@ class assign {
} else if ($action == 'grantextension') {
$o .= $this->view_grant_extension($mform);
} else if ($action == 'revealidentities') {
$o .= $this->view_reveal_identities_confirm($mform);
$o .= $this->view_reveal_identities_confirm();
} else if ($action == 'removesubmissionconfirm') {
$PAGE->add_body_class('limitedwidth');
$o .= $this->view_remove_submission_confirm();
} else if ($action == 'plugingradingbatchoperation') {
$o .= $this->view_plugin_grading_batch_operation($mform);
$o .= $this->view_plugin_grading_batch_operation();
} else if ($action == 'viewpluginpage') {
$o .= $this->view_plugin_page();
} else if ($action == 'viewcourseindex') {
$o .= $this->view_course_index();
} else if ($action == 'viewbatchsetmarkingworkflowstate') {
$o .= $this->view_batch_set_workflow_state($mform);
$o .= $this->view_batch_set_workflow_state();
} else if ($action == 'viewbatchmarkingallocation') {
$o .= $this->view_batch_markingallocation($mform);
$o .= $this->view_batch_markingallocation();
} else if ($action == 'viewsubmitforgradingerror') {
$o .= $this->view_error_page(get_string('submitforgrading', 'assign'), $notices);
} else if ($action == 'fixrescalednullgrades') {
@ -4483,7 +4483,6 @@ class assign {
// Include grading options form.
require_once($CFG->dirroot . '/mod/assign/gradingoptionsform.php');
require_once($CFG->dirroot . '/mod/assign/quickgradingform.php');
require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
$submittedfilter = optional_param('status', null, PARAM_ALPHA);
if (isset($submittedfilter)) {
@ -4570,26 +4569,6 @@ class assign {
'',
$classoptions);
$batchformparams = array('cm'=>$cmid,
'submissiondrafts'=>$this->get_instance()->submissiondrafts,
'duedate'=>$this->get_instance()->duedate,
'maxattempts' => $this->get_instance()->maxattempts,
'attemptreopenmethod'=>$this->get_instance()->attemptreopenmethod,
'feedbackplugins'=>$this->get_feedback_plugins(),
'context'=>$this->get_context(),
'markingworkflow'=>$markingworkflow,
'markingallocation'=>$markingallocation);
$classoptions = [
'class' => 'gradingbatchoperationsform',
'data-double-submit-protection' => 'off',
];
$gradingbatchoperationsform = new mod_assign_grading_batch_operations_form(null,
$batchformparams,
'post',
'',
$classoptions);
$gradingoptionsdata = new stdClass();
$gradingoptionsdata->markerfilter = $markerfilter;
$gradingoptionsform->set_data($gradingoptionsdata);
@ -4655,17 +4634,49 @@ class assign {
$SESSION->mod_assign_useridlist[$this->get_useridlist_key()] = $useridlist;
}
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
$users = array_keys($this->list_participants($currentgroup, true));
if (count($users) != 0 && $this->can_grade()) {
// If no enrolled user in a course then don't display the batch operations feature.
$assignform = new assign_form('gradingbatchoperationsform', $gradingbatchoperationsform);
$o .= $this->get_renderer()->render($assignform);
}
$assignform = new assign_form('gradingoptionsform',
$gradingoptionsform,
'M.mod_assign.init_grading_options');
$o .= $this->get_renderer()->render($assignform);
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
$users = array_keys($this->list_participants($currentgroup, true));
if (count($users) != 0 && $this->can_grade()) {
$jsparams = [];
$jsparams['message'] = !empty($CFG->messaging)
&& has_all_capabilities(['moodle/site:sendmessage', 'moodle/course:bulkmessaging'], $this->context);
$jsparams['submissiondrafts'] = !empty($this->get_instance()->submissiondrafts);
$jsparams['removesubmission'] = has_capability('mod/assign:editothersubmission', $this->context);
$jsparams['extend'] = $this->get_instance()->duedate && has_capability('mod/assign:grantextension', $this->context);
$multipleattemptsallowed = $this->get_instance()->maxattempts > 1
|| $this->get_instance()->maxattempts == ASSIGN_UNLIMITED_ATTEMPTS;
$jsparams['grantattempt'] =
$multipleattemptsallowed && $this->get_instance()->attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL;
$jsparams['pluginoperations'] = [];
foreach ($this->get_feedback_plugins() as $plugin) {
if ($plugin->is_visible() && $plugin->is_enabled()) {
foreach ($plugin->get_grading_batch_operation_details() as $operation) {
$jsparams['pluginoperations'][] = [
'key' => 'plugingradingbatchoperation_' . $plugin->get_type() . '_' . $operation->key,
'label' => $operation->label,
'icon' => $operation->icon,
'confirmationtitle' => $operation->confirmationtitle,
'confirmationquestion' => $operation->confirmationquestion,
];
}
}
}
$jsparams['workflowstate'] = !empty($this->get_instance()->markingworkflow);
$jsparams['markingallocation'] = !empty($this->get_instance()->markingallocation);
$jsparams['cmid'] = $this->get_course_module()->id;
$jsparams['sesskey'] = sesskey();
$PAGE->requires->js_call_amd('mod_assign/bulkactions/grading/bulk_actions', 'init', [$jsparams]);
}
return $o;
}
@ -5017,112 +5028,84 @@ class assign {
/**
* Allows the plugin to show a batch grading operation page.
* You should confirm sesskey before calling this function.
*
* @param moodleform $mform
* @return none
*/
protected function view_plugin_grading_batch_operation($mform) {
protected function view_plugin_grading_batch_operation() {
require_capability('mod/assign:grade', $this->context);
$prefix = 'plugingradingbatchoperation_';
if ($data = $mform->get_data()) {
$tail = substr($data->operation, strlen($prefix));
list($plugintype, $action) = explode('_', $tail, 2);
$operation = required_param('operation', PARAM_ALPHAEXT);
$plugin = $this->get_feedback_plugin_by_type($plugintype);
if ($plugin) {
$users = $data->selectedusers;
$userlist = explode(',', $users);
echo $plugin->grading_batch_operation($action, $userlist);
return;
}
$tail = substr($operation, strlen($prefix));
list($plugintype, $action) = explode('_', $tail, 2);
$plugin = $this->get_feedback_plugin_by_type($plugintype);
if ($plugin) {
$users = required_param('selectedusers', PARAM_SEQUENCE);
$userlist = explode(',', $users);
echo $plugin->grading_batch_operation($action, $userlist);
return;
}
throw new \moodle_exception('invalidformdata', '');
}
/**
* Ask the user to confirm they want to perform this batch operation
*
* @param moodleform $mform Set to a grading batch operations form
* @return string - the page to view after processing these actions
*/
protected function process_grading_batch_operation(& $mform) {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
protected function process_grading_batch_operation() {
require_sesskey();
$markingallocation = $this->get_instance()->markingworkflow &&
$this->get_instance()->markingallocation &&
has_capability('mod/assign:manageallocations', $this->context);
$operation = required_param('operation', PARAM_ALPHAEXT);
$selectedusers = required_param('selectedusers', PARAM_SEQUENCE);
$batchformparams = array('cm'=>$this->get_course_module()->id,
'submissiondrafts'=>$this->get_instance()->submissiondrafts,
'duedate'=>$this->get_instance()->duedate,
'maxattempts' => $this->get_instance()->maxattempts,
'attemptreopenmethod'=>$this->get_instance()->attemptreopenmethod,
'feedbackplugins'=>$this->get_feedback_plugins(),
'context'=>$this->get_context(),
'markingworkflow'=>$this->get_instance()->markingworkflow,
'markingallocation'=>$markingallocation);
$formclasses = [
'class' => 'gradingbatchoperationsform',
'data-double-submit-protection' => 'off'
];
// Get the list of users.
$userlist = explode(',', $selectedusers);
$mform = new mod_assign_grading_batch_operations_form(null,
$batchformparams,
'post',
'',
$formclasses);
$prefix = 'plugingradingbatchoperation_';
if ($data = $mform->get_data()) {
// Get the list of users.
$users = $data->selectedusers;
$userlist = explode(',', $users);
if ($operation == 'grantextension') {
return 'grantextension';
} else if ($operation == 'setmarkingworkflowstate') {
return 'viewbatchsetmarkingworkflowstate';
} else if ($operation == 'setmarkingallocation') {
return 'viewbatchmarkingallocation';
} else if (strpos($operation, $prefix) === 0) {
$tail = substr($operation, strlen($prefix));
list($plugintype, $action) = explode('_', $tail, 2);
$prefix = 'plugingradingbatchoperation_';
if ($data->operation == 'grantextension') {
// Reset the form so the grant extension page will create the extension form.
$mform = null;
return 'grantextension';
} else if ($data->operation == 'setmarkingworkflowstate') {
return 'viewbatchsetmarkingworkflowstate';
} else if ($data->operation == 'setmarkingallocation') {
return 'viewbatchmarkingallocation';
} else if (strpos($data->operation, $prefix) === 0) {
$tail = substr($data->operation, strlen($prefix));
list($plugintype, $action) = explode('_', $tail, 2);
$plugin = $this->get_feedback_plugin_by_type($plugintype);
if ($plugin) {
return 'plugingradingbatchoperation';
}
$plugin = $this->get_feedback_plugin_by_type($plugintype);
if ($plugin) {
return 'plugingradingbatchoperation';
}
}
if ($data->operation == 'downloadselected') {
$this->download_submissions($userlist);
} else {
foreach ($userlist as $userid) {
if ($data->operation == 'lock') {
$this->process_lock_submission($userid);
} else if ($data->operation == 'unlock') {
$this->process_unlock_submission($userid);
} else if ($data->operation == 'reverttodraft') {
$this->process_revert_to_draft($userid);
} else if ($data->operation == 'removesubmission') {
$this->process_remove_submission($userid);
} else if ($data->operation == 'addattempt') {
if (!$this->get_instance()->teamsubmission) {
$this->process_add_attempt($userid);
}
if ($operation == 'downloadselected') {
$this->download_submissions($userlist);
} else {
foreach ($userlist as $userid) {
if ($operation == 'lock') {
$this->process_lock_submission($userid);
} else if ($operation == 'unlock') {
$this->process_unlock_submission($userid);
} else if ($operation == 'reverttodraft') {
$this->process_revert_to_draft($userid);
} else if ($operation == 'removesubmission') {
$this->process_remove_submission($userid);
} else if ($operation == 'addattempt') {
if (!$this->get_instance()->teamsubmission) {
$this->process_add_attempt($userid);
}
}
}
if ($this->get_instance()->teamsubmission && $data->operation == 'addattempt') {
// This needs to be handled separately so that each team submission is only re-opened one time.
$this->process_add_attempt_group($userlist);
}
}
if ($this->get_instance()->teamsubmission && $operation == 'addattempt') {
// This needs to be handled separately so that each team submission is only re-opened one time.
$this->process_add_attempt_group($userlist);
}
return 'grading';
@ -5130,19 +5113,18 @@ class assign {
/**
* Shows a form that allows the workflow state for selected submissions to be changed.
* You should confirm sesskey before calling this function.
*
* @param moodleform $mform Set to a grading batch operations form
* @return string - the page to view after processing these actions
*/
protected function view_batch_set_workflow_state($mform) {
protected function view_batch_set_workflow_state() {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/batchsetmarkingworkflowstateform.php');
$o = '';
$submitteddata = $mform->get_data();
$users = $submitteddata->selectedusers;
$users = required_param('selectedusers', PARAM_SEQUENCE);
$userlist = explode(',', $users);
$formdata = array('id' => $this->get_course_module()->id,
@ -5195,19 +5177,18 @@ class assign {
/**
* Shows a form that allows the allocated marker for selected submissions to be changed.
* You should confirm sesskey before calling this function.
*
* @param moodleform $mform Set to a grading batch operations form
* @return string - the page to view after processing these actions
*/
public function view_batch_markingallocation($mform) {
public function view_batch_markingallocation() {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/assign/batchsetallocatedmarkerform.php');
$o = '';
$submitteddata = $mform->get_data();
$users = $submitteddata->selectedusers;
$users = required_param('selectedusers', PARAM_SEQUENCE);
$userlist = explode(',', $users);
$formdata = array('id' => $this->get_course_module()->id,

View File

@ -69,53 +69,6 @@ M.mod_assign.init_grading_table = function(Y) {
});
}
const batchform = Y.one('form.gradingbatchoperationsform');
if (batchform) {
batchform.on('submit', function(e) {
M.util.js_pending('mod_assign/module.js:batch:submit');
let selectedusers = [];
checkboxes.each(function(node) {
if (node.get('checked')) {
selectedusers.push(node.get('value'));
}
});
const operation = Y.one('#id_operation');
const usersinput = Y.one('input.selectedusers');
usersinput.set('value', selectedusers.join(','));
if (selectedusers.length === 0) {
alert(M.util.get_string('nousersselected', 'assign'));
e.preventDefault();
} else {
let action = operation.get('value');
const prefix = 'plugingradingbatchoperation_';
let confirmmessage = false;
if (action.indexOf(prefix) === 0) {
const pluginaction = action.slice(prefix.length);
const plugin = pluginaction.split('_')[0];
action = pluginaction.slice(plugin.length + 1);
confirmmessage = M.util.get_string('batchoperationconfirm' + action, 'assignfeedback_' + plugin);
} else if (action === 'message') {
e.preventDefault();
require(['core_message/message_send_bulk'], function(BulkSender) {
BulkSender.showModal(selectedusers, function() {
document.getElementById('page-header').scrollIntoView();
});
});
} else {
confirmmessage = M.util.get_string('batchoperationconfirm' + operation.get('value'), 'assign');
}
// Complete here the action (js_complete event) when we send a bulk message, or we have a confirmation message.
// When the confirmation dialogue is completed, the event is fired.
if (action === 'message' || confirmmessage !== false && !confirm(confirmmessage)) {
M.util.js_complete('mod_assign/module.js:batch:submit');
e.preventDefault();
}
// Note: Do not js_complete. The page being reloaded will empty it.
}
});
}
var quickgrade = Y.all('.gradingtable .quickgrade');
quickgrade.each(function(quick) {
quick.on('change', function(e) {

View File

@ -135,14 +135,6 @@
display: table-cell;
}
.path-mod-assign .gradingbatchoperationsform {
display: none;
}
.path-mod-assign.jsenabled .gradingbatchoperationsform {
display: block;
}
.path-mod-assign .gradingtable table {
border-collapse: separate;
border-spacing: 0;

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/>.
}}
{{!
@template mod_assign/bulkactions/grading/bulk_delete_trigger
Renders the bulk delete trigger element in assignment grading page.
Context variables required for this template:
* none
Example context (json):
{
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}removesubmission{{/action}}
{{$title}}{{#str}} batchoperationremovesubmission, mod_assign {{/str}}{{/title}}
{{$icon}}{{#pix}} i/delete, core {{/pix}}{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

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/>.
}}
{{!
@template mod_assign/bulkactions/grading/bulk_extend_trigger
Renders the bulk extend trigger element in assignment grading page.
Context variables required for this template:
* none
Example context (json):
{
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}grantextension{{/action}}
{{$title}}{{#str}} batchoperationgrantextension, mod_assign {{/str}}{{/title}}
{{$icon}}{{#pix}} i/duration, core {{/pix}}{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

View File

@ -0,0 +1,38 @@
{{!
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_assign/bulkactions/grading/bulk_general_action_trigger
Renders the general bulk action trigger element in assignment grading page.
Context variables required for this template:
* action: The action to be performed.
* title: The title of the action button.
* icon: The icon of the action button.
Example context (json):
{
"action": "lock",
"title": "Lock",
"icon": "<i class=\"icon fa fa-lock fa-fw\"></i>"
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}{{action}}{{/action}}
{{$title}}{{title}}{{/title}}
{{$icon}}{{{icon}}}{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

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/>.
}}
{{!
@template mod_assign/bulkactions/grading/bulk_message_trigger
Renders the bulk message trigger element in assignment grading page.
Context variables required for this template:
* none
Example context (json):
{
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}message{{/action}}
{{$title}}{{#str}} message, core {{/str}}{{/title}}
{{$icon}}{{#pix}} t/message, core {{/pix}}{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

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/>.
}}
{{!
@template mod_assign/bulkactions/grading/bulk_setmarkingallocation_trigger
Renders the bulk set allocated marker trigger element in assignment grading page.
Context variables required for this template:
* none
Example context (json):
{
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}setmarkingallocation{{/action}}
{{$title}}{{#str}} batchoperationsetmarkingallocation, mod_assign {{/str}}{{/title}}
{{$icon}}<i class="icon fa fa-pen-to-square fa-fw"></i>{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

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/>.
}}
{{!
@template mod_assign/bulkactions/grading/bulk_setmarkingworkflowstate_trigger
Renders the bulk set marking workflow state trigger element in assignment grading page.
Context variables required for this template:
* none
Example context (json):
{
}
}}
{{< core/bulkactions/bulk_action_trigger }}
{{$action}}setmarkingworkflowstate{{/action}}
{{$title}}{{#str}} batchoperationsetmarkingworkflowstate, mod_assign {{/str}}{{/title}}
{{$icon}}<i class="icon fa fa-diagram-project fa-fw"></i>{{/icon}}
{{/ core/bulkactions/bulk_action_trigger }}

View File

@ -113,9 +113,8 @@ Feature: In an assignment, students start a new attempt based on their previous
And I should see "The grade changes were saved"
And I press "Continue"
And I click on "Student 1" "checkbox"
And I set the following fields to these values:
| operation | Allow another attempt |
And I click on "Go" "button" confirming the dialogue
And I click on "Grant attempt" "button" in the "sticky-footer" "region"
And I click on "Grant attempt" "button" in the "Allow another attempt" "dialogue"
And I should not see "The grades were not saved because someone has modified one or more records more recently than when you loaded the page."
And I log out
And I am on the "Test assignment name" Activity page logged in as student3

View File

@ -67,8 +67,8 @@ Feature: Bulk released grades should not be sent to gradebook while submissions
@javascript @_alert
Scenario: Grades are released in bulk before student identities are revealed.
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
And I click on "Change marking state" "button" in the "sticky-footer" "region"
And I click on "Change marking state" "button" in the "Set marking workflow state" "dialogue"
Then I should not see "Student 1 (student1@example.com)"
And I should not see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
@ -102,8 +102,8 @@ Feature: Bulk released grades should not be sent to gradebook while submissions
When I choose the "Reveal student identities" item in the "Actions" action menu
And I press "Continue"
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
And I click on "Change marking state" "button" in the "sticky-footer" "region"
And I click on "Change marking state" "button" in the "Set marking workflow state" "dialogue"
Then I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"
@ -128,8 +128,8 @@ Feature: Bulk released grades should not be sent to gradebook while submissions
And I press "Save and display"
And I navigate to "Submissions" in current page administration
When I set the field "selectall" to "1"
And I set the field "operation" to "Set marking workflow state"
And I click on "Go" "button" confirming the dialogue
And I click on "Change marking state" "button" in the "sticky-footer" "region"
And I click on "Change marking state" "button" in the "Set marking workflow state" "dialogue"
Then I should not see "Student 1 (student1@example.com)"
And I should not see "Student 2 (student2@example.com)"
And I set the field "Marking workflow state" to "Released"

View File

@ -45,8 +45,8 @@ Feature: Bulk remove submissions
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
And I click on "Delete" "button" in the "sticky-footer" "region"
And I click on "Delete" "button" in the "Remove submission" "dialogue"
Then I should not see "I'm the student1 submission"
And I should not see "I'm the student2 submission"
And I log out
@ -78,7 +78,7 @@ Feature: Bulk remove submissions
And I should see "I'm the student1 submission"
And I should see "I'm the student2 submission"
And I set the field "selectall" to "1"
Then I should not see "Remove submission" in the "Choose operation" "select"
Then I should not see "Delete" in the "sticky-footer" "region"
@javascript @skip_chrome_zerosize
Scenario: Bulk remove submission when shared group users are added to the bulk
@ -111,8 +111,8 @@ Feature: Bulk remove submissions
And I should see "I'm the student2 submission"
And I should not see "I'm the student3 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
When I click on "Delete" "button" in the "sticky-footer" "region"
And I click on "Delete" "button" in the "Remove submission" "dialogue"
Then I should not see "I'm the student1 submission"
Then I should not see "I'm the student2 submission"
@ -147,8 +147,8 @@ Feature: Bulk remove submissions
And I should see "I'm the student2 submission"
And I should see "I'm the student3 submission"
And I set the field "selectall" to "1"
When I set the field "operation" to "Remove submission"
And I click on "Go" "button" confirming the dialogue
When I click on "Delete" "button" in the "sticky-footer" "region"
And I click on "Delete" "button" in the "Remove submission" "dialogue"
Then I should not see "I'm the student1 submission"
And I should not see "I'm the student2 submission"
And I should not see "I'm the student3 submission"

View File

@ -53,8 +53,8 @@ Feature: Grant an extension to an offline student
And I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Submissions" in current page administration
And I set the field "selectall" to "1"
And I set the field "operation" to "Grant extension"
And I click on "Go" "button" confirming the dialogue
And I click on "Extend" "button" in the "sticky-footer" "region"
And I click on "Extend" "button" in the "Grant extension" "dialogue"
And I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I should see "Student 3 (student3@example.com)"
@ -102,8 +102,8 @@ Feature: Grant an extension to an offline student
And I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Submissions" in current page administration
And I set the field "selectall" to "1"
And I set the field "operation" to "Grant extension"
And I click on "Go" "button" confirming the dialogue
And I click on "Extend" "button" in the "sticky-footer" "region"
And I click on "Extend" "button" in the "Grant extension" "dialogue"
And I should see "Student 1 (student1@example.com)"
And I should see "Student 2 (student2@example.com)"
And I should see "Student 3 (student3@example.com)"

View File

@ -80,7 +80,8 @@ Feature: Prevent or allow assignment submission changes
And I am on the "Test assignment name" Activity page logged in as teacher1
When I navigate to "Submissions" in current page administration
And I set the field "selectall" to "1"
And I click on "Go" "button" confirming the dialogue
And I click on "Lock" "button" in the "sticky-footer" "region"
And I click on "Lock" "button" in the "Lock submissions" "dialogue"
Then I should see "Submission changes not allowed" in the "Student 1" "table_row"
And I should see "Submission changes not allowed" in the "Student 2" "table_row"
And I log out
@ -92,8 +93,8 @@ Feature: Prevent or allow assignment submission changes
And I am on the "Test assignment name" Activity page logged in as teacher1
And I navigate to "Submissions" in current page administration
And I set the field "selectall" to "1"
And I set the field "id_operation" to "Unlock submissions"
And I click on "Go" "button" confirming the dialogue
And I click on "Unlock" "button" in the "sticky-footer" "region"
And I click on "Unlock" "button" in the "Unlock submissions" "dialogue"
And I should not see "Submission changes not allowed" in the "Student 1" "table_row"
And I should not see "Submission changes not allowed" in the "Student 2" "table_row"
And I log out

View File

@ -117,44 +117,15 @@ class mod_assign_testable_assign extends assign {
public function testable_view_batch_set_workflow_state($selectedusers) {
global $PAGE;
$PAGE->set_url('/mod/assign/view.php');
$mform = $this->testable_grading_batch_operations_form('setmarkingworkflowstate', $selectedusers);
return parent::view_batch_set_workflow_state($mform);
$_POST['selectedusers'] = $selectedusers;
return parent::view_batch_set_workflow_state();
}
public function testable_view_batch_markingallocation($selectedusers) {
global $PAGE;
$PAGE->set_url('/mod/assign/view.php');
$mform = $this->testable_grading_batch_operations_form('setmarkingallocation', $selectedusers);
return parent::view_batch_markingallocation($mform);
}
public function testable_grading_batch_operations_form($operation, $selectedusers) {
global $CFG;
require_once($CFG->dirroot . '/mod/assign/gradingbatchoperationsform.php');
// Mock submit the grading operations form.
$data = array();
$data['id'] = $this->get_course_module()->id;
$data['selectedusers'] = $selectedusers;
$data['returnaction'] = 'grading';
$data['operation'] = $operation;
mod_assign_grading_batch_operations_form::mock_submit($data);
// Set required variables in the form.
$formparams = array();
$formparams['submissiondrafts'] = 1;
$formparams['duedate'] = 1;
$formparams['maxattempts'] = ASSIGN_UNLIMITED_ATTEMPTS;
$formparams['attemptreopenmethod'] = ASSIGN_ATTEMPT_REOPEN_METHOD_MANUAL;
$formparams['feedbackplugins'] = array();
$formparams['markingworkflow'] = 1;
$formparams['markingallocation'] = 1;
$formparams['cm'] = $this->get_course_module()->id;
$formparams['context'] = $this->get_context();
$mform = new mod_assign_grading_batch_operations_form(null, $formparams);
return $mform;
$_POST['selectedusers'] = $selectedusers;
return parent::view_batch_markingallocation();
}
public function testable_update_activity_completion_records($teamsubmission,