mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
Merge branch 'mdl-76270-master' of https://github.com/matthewhilton/moodle
This commit is contained in:
commit
c5ac5bcfd5
9
group/amd/build/grouppicker.min.js
vendored
Normal file
9
group/amd/build/grouppicker.min.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
define("core_group/grouppicker",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;return _exports.default=
|
||||
/**
|
||||
* @module core_group/groupPicker
|
||||
* @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class{constructor(){let elementId=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"groups";const pickerDomElement=document.getElementById(elementId);if(!pickerDomElement)throw new Error("Groups picker was not found.");this.element=pickerDomElement}getDomElement(){return this.element}getSelectedValues(){return Array.from(this.element.querySelectorAll("option:checked")).map((el=>parseInt(el.value)))}},_exports.default}));
|
||||
|
||||
//# sourceMappingURL=grouppicker.min.js.map
|
1
group/amd/build/grouppicker.min.js.map
Normal file
1
group/amd/build/grouppicker.min.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"grouppicker.min.js","sources":["../src/grouppicker.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 * @module core_group/groupPicker\n * @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Class used for interfacing with the group select picker.\n *\n * @class core_group/GroupPicker\n */\nexport default class GroupPicker {\n /**\n * Creates the group picker class and finds the corresponding DOM element.\n *\n * @param {String} elementId The DOM element id of the <select> input\n * @throws Error if the element was not found.\n */\n constructor(elementId = \"groups\") {\n const pickerDomElement = document.getElementById(elementId);\n\n if (!pickerDomElement) {\n throw new Error(\"Groups picker was not found.\");\n }\n\n this.element = pickerDomElement;\n }\n\n /**\n * Returns the DOM element this class is linked to.\n *\n * @returns {HTMLElement} The DOM element\n */\n getDomElement() {\n return this.element;\n }\n\n /**\n * Returns the selected group values.\n *\n * @returns {Number[]} The group IDs that are currently selected.\n */\n getSelectedValues() {\n const selectedOptionElements = Array.from(this.element.querySelectorAll(\"option:checked\"));\n const selectedGroups = selectedOptionElements.map(el => parseInt(el.value));\n\n return selectedGroups;\n }\n}\n"],"names":["constructor","elementId","pickerDomElement","document","getElementById","Error","element","getDomElement","this","getSelectedValues","Array","from","querySelectorAll","map","el","parseInt","value"],"mappings":";;;;;;MAgCIA,kBAAYC,iEAAY,eACdC,iBAAmBC,SAASC,eAAeH,eAE5CC,uBACK,IAAIG,MAAM,qCAGfC,QAAUJ,iBAQnBK,uBACWC,KAAKF,QAQhBG,2BACmCC,MAAMC,KAAKH,KAAKF,QAAQM,iBAAiB,mBAC1BC,KAAIC,IAAMC,SAASD,GAAGE"}
|
8
group/amd/build/index.min.js
vendored
Normal file
8
group/amd/build/index.min.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
define("core_group/index",["exports","./grouppicker"],(function(_exports,_grouppicker){var obj;
|
||||
/**
|
||||
* @module core_group/index
|
||||
* @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.updateBulkActionButtons=_exports.setElementEnabled=_exports.init=void 0;const groupPicker=new(_grouppicker=(obj=_grouppicker)&&obj.__esModule?obj:{default:obj}).default;_exports.init=()=>{groupPicker.getDomElement().addEventListener("change",updateBulkActionButtons),updateBulkActionButtons()};const updateBulkActionButtons=()=>{const aGroupIsSelected=0!==groupPicker.getSelectedValues().length,bulkActionsEnabledStatuses={enablemessaging:aGroupIsSelected,disablemessaging:aGroupIsSelected};Object.entries(bulkActionsEnabledStatuses).map((_ref=>{let[buttonId,enabled]=_ref;return setElementEnabled(buttonId,enabled)}))};_exports.updateBulkActionButtons=updateBulkActionButtons;const setElementEnabled=(domElementId,enabled)=>{const element=document.getElementById(domElementId);element&&(enabled?element.removeAttribute("disabled"):element.setAttribute("disabled","disabled"))};_exports.setElementEnabled=setElementEnabled}));
|
||||
|
||||
//# sourceMappingURL=index.min.js.map
|
1
group/amd/build/index.min.js.map
Normal file
1
group/amd/build/index.min.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.min.js","sources":["../src/index.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 * @module core_group/index\n * @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport GroupPicker from \"./grouppicker\";\n\nconst groupPicker = new GroupPicker();\n\n/**\n * Initialise page.\n */\nexport const init = () => {\n // Init event listeners.\n groupPicker.getDomElement().addEventListener(\"change\", updateBulkActionButtons);\n\n // Call initially to set initial button state.\n updateBulkActionButtons();\n};\n\n/**\n * Updates the bulk action buttons depending on specific conditions.\n */\nexport const updateBulkActionButtons = () => {\n const groupsSelected = groupPicker.getSelectedValues();\n const aGroupIsSelected = groupsSelected.length !== 0;\n\n // Collate the conditions where each button is enabled/disabled.\n const bulkActionsEnabledStatuses = {\n 'enablemessaging': aGroupIsSelected,\n 'disablemessaging': aGroupIsSelected\n };\n\n // Update the status of each button.\n Object.entries(bulkActionsEnabledStatuses).map(([buttonId, enabled]) => setElementEnabled(buttonId, enabled));\n};\n\n/**\n * Adds or removes the given element's disabled attribute.\n * @param {string} domElementId ID of the dom element (without the #)\n * @param {bool} enabled If false, the disable attribute is applied, else it is removed.\n */\nexport const setElementEnabled = (domElementId, enabled) => {\n const element = document.getElementById(domElementId);\n\n if (!element) {\n // If there is no element, we do nothing.\n // The element could be purposefully hidden or removed.\n return;\n }\n\n if (!enabled) {\n element.setAttribute('disabled', 'disabled');\n } else {\n element.removeAttribute('disabled');\n }\n};\n"],"names":["groupPicker","getDomElement","addEventListener","updateBulkActionButtons","aGroupIsSelected","getSelectedValues","length","bulkActionsEnabledStatuses","Object","entries","map","_ref","buttonId","enabled","setElementEnabled","domElementId","element","document","getElementById","removeAttribute","setAttribute"],"mappings":";;;;;oJAsBMA,YAAc,6FAKA,KAEhBA,YAAYC,gBAAgBC,iBAAiB,SAAUC,yBAGvDA,iCAMSA,wBAA0B,WAE7BC,iBAA6C,IAD5BJ,YAAYK,oBACKC,OAGlCC,2BAA6B,iBACZH,kCACCA,kBAIxBI,OAAOC,QAAQF,4BAA4BG,KAAIC,WAAEC,SAAUC,qBAAaC,kBAAkBF,SAAUC,4EAQ3FC,kBAAoB,CAACC,aAAcF,iBACtCG,QAAUC,SAASC,eAAeH,cAEnCC,UAMAH,QAGDG,QAAQG,gBAAgB,YAFxBH,QAAQI,aAAa,WAAY"}
|
63
group/amd/src/grouppicker.js
Normal file
63
group/amd/src/grouppicker.js
Normal file
@ -0,0 +1,63 @@
|
||||
// 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/>.
|
||||
/**
|
||||
* @module core_group/groupPicker
|
||||
* @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class used for interfacing with the group select picker.
|
||||
*
|
||||
* @class core_group/GroupPicker
|
||||
*/
|
||||
export default class GroupPicker {
|
||||
/**
|
||||
* Creates the group picker class and finds the corresponding DOM element.
|
||||
*
|
||||
* @param {String} elementId The DOM element id of the <select> input
|
||||
* @throws Error if the element was not found.
|
||||
*/
|
||||
constructor(elementId = "groups") {
|
||||
const pickerDomElement = document.getElementById(elementId);
|
||||
|
||||
if (!pickerDomElement) {
|
||||
throw new Error("Groups picker was not found.");
|
||||
}
|
||||
|
||||
this.element = pickerDomElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DOM element this class is linked to.
|
||||
*
|
||||
* @returns {HTMLElement} The DOM element
|
||||
*/
|
||||
getDomElement() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected group values.
|
||||
*
|
||||
* @returns {Number[]} The group IDs that are currently selected.
|
||||
*/
|
||||
getSelectedValues() {
|
||||
const selectedOptionElements = Array.from(this.element.querySelectorAll("option:checked"));
|
||||
const selectedGroups = selectedOptionElements.map(el => parseInt(el.value));
|
||||
|
||||
return selectedGroups;
|
||||
}
|
||||
}
|
72
group/amd/src/index.js
Normal file
72
group/amd/src/index.js
Normal file
@ -0,0 +1,72 @@
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* @module core_group/index
|
||||
* @copyright 2022 Matthew Hilton <matthewhilton@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import GroupPicker from "./grouppicker";
|
||||
|
||||
const groupPicker = new GroupPicker();
|
||||
|
||||
/**
|
||||
* Initialise page.
|
||||
*/
|
||||
export const init = () => {
|
||||
// Init event listeners.
|
||||
groupPicker.getDomElement().addEventListener("change", updateBulkActionButtons);
|
||||
|
||||
// Call initially to set initial button state.
|
||||
updateBulkActionButtons();
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the bulk action buttons depending on specific conditions.
|
||||
*/
|
||||
export const updateBulkActionButtons = () => {
|
||||
const groupsSelected = groupPicker.getSelectedValues();
|
||||
const aGroupIsSelected = groupsSelected.length !== 0;
|
||||
|
||||
// Collate the conditions where each button is enabled/disabled.
|
||||
const bulkActionsEnabledStatuses = {
|
||||
'enablemessaging': aGroupIsSelected,
|
||||
'disablemessaging': aGroupIsSelected
|
||||
};
|
||||
|
||||
// Update the status of each button.
|
||||
Object.entries(bulkActionsEnabledStatuses).map(([buttonId, enabled]) => setElementEnabled(buttonId, enabled));
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds or removes the given element's disabled attribute.
|
||||
* @param {string} domElementId ID of the dom element (without the #)
|
||||
* @param {bool} enabled If false, the disable attribute is applied, else it is removed.
|
||||
*/
|
||||
export const setElementEnabled = (domElementId, enabled) => {
|
||||
const element = document.getElementById(domElementId);
|
||||
|
||||
if (!element) {
|
||||
// If there is no element, we do nothing.
|
||||
// The element could be purposefully hidden or removed.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
element.setAttribute('disabled', 'disabled');
|
||||
} else {
|
||||
element.removeAttribute('disabled');
|
||||
}
|
||||
};
|
@ -59,6 +59,9 @@ class index_page implements renderable, templatable {
|
||||
/** @var array Groups that can't be deleted by the user. */
|
||||
public $undeletablegroups;
|
||||
|
||||
/** @var bool Whether to show/hide the messaging setting buttons. */
|
||||
public $messagingsettingsvisible;
|
||||
|
||||
/**
|
||||
* index_page constructor.
|
||||
*
|
||||
@ -69,9 +72,10 @@ class index_page implements renderable, templatable {
|
||||
* @param bool $disableaddedit Whether to disable the add members/edit group buttons.
|
||||
* @param bool $disabledelete Whether to disable the delete group button.
|
||||
* @param array $undeletablegroups Groups that can't be deleted by the user.
|
||||
* @param bool $messagingsettingsvisible If the messaging settings buttons should be visible.
|
||||
*/
|
||||
public function __construct($courseid, $groups, $selectedgroupname, $selectedgroupmembers, $disableaddedit, $disabledelete,
|
||||
$undeletablegroups) {
|
||||
$undeletablegroups, $messagingsettingsvisible) {
|
||||
$this->courseid = $courseid;
|
||||
$this->groups = $groups;
|
||||
$this->selectedgroupname = $selectedgroupname;
|
||||
@ -79,6 +83,7 @@ class index_page implements renderable, templatable {
|
||||
$this->disableaddedit = $disableaddedit;
|
||||
$this->disabledelete = $disabledelete;
|
||||
$this->undeletablegroups = $undeletablegroups;
|
||||
$this->messagingsettingsvisible = $messagingsettingsvisible;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -105,6 +110,7 @@ class index_page implements renderable, templatable {
|
||||
$data->groups = $this->groups;
|
||||
$data->members = $this->selectedgroupmembers;
|
||||
$data->selectedgroup = $this->selectedgroupname;
|
||||
$data->messagingsettingsvisible = $this->messagingsettingsvisible;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ UpdatableMembersCombo.prototype.refreshMembers = function () {
|
||||
document.getElementById("deletegroup").disabled = selectionCount == 0;
|
||||
|
||||
if(singleSelection) {
|
||||
var sUrl = this.wwwRoot+"/group/index.php?id="+this.courseId+"&group="+groupId+"&act_ajax_getmembersingroup";
|
||||
var sUrl = this.wwwRoot + "/group/index.php?id=" + this.courseId + "&group=" + groupId + "&action=ajax_getmembersingroup";
|
||||
var self = this;
|
||||
YUI().use('io', function (Y) {
|
||||
Y.io(sUrl, {
|
||||
|
@ -28,8 +28,9 @@ require_once('lib.php');
|
||||
$courseid = required_param('id', PARAM_INT);
|
||||
$groupid = optional_param('group', false, PARAM_INT);
|
||||
$userid = optional_param('user', false, PARAM_INT);
|
||||
$action = groups_param_action();
|
||||
// Support either single group= parameter, or array groups[]
|
||||
$action = optional_param('action', false, PARAM_TEXT);
|
||||
|
||||
// Support either single group= parameter, or array groups[].
|
||||
if ($groupid) {
|
||||
$groupids = array($groupid);
|
||||
} else {
|
||||
@ -40,11 +41,10 @@ $singlegroup = (count($groupids) == 1);
|
||||
$returnurl = $CFG->wwwroot.'/group/index.php?id='.$courseid;
|
||||
|
||||
// Get the course information so we can print the header and
|
||||
// check the course id is valid
|
||||
// check the course id is valid.
|
||||
$course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
|
||||
|
||||
$course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
|
||||
|
||||
$url = new moodle_url('/group/index.php', array('id'=>$courseid));
|
||||
$url = new moodle_url('/group/index.php', array('id' => $courseid));
|
||||
navigation_node::override_active_url($url);
|
||||
if ($userid) {
|
||||
$url->param('user', $userid);
|
||||
@ -63,7 +63,7 @@ require_capability('moodle/course:managegroups', $context);
|
||||
$PAGE->requires->js('/group/clientlib.js', true);
|
||||
$PAGE->requires->js('/group/module.js', true);
|
||||
|
||||
// Check for multiple/no group errors
|
||||
// Check for multiple/no group errors.
|
||||
if (!$singlegroup) {
|
||||
switch($action) {
|
||||
case 'ajax_getmembersingroup':
|
||||
@ -75,7 +75,7 @@ if (!$singlegroup) {
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case false: //OK, display form.
|
||||
case false: // OK, display form.
|
||||
break;
|
||||
|
||||
case 'ajax_getmembersingroup':
|
||||
@ -93,11 +93,11 @@ switch ($action) {
|
||||
|
||||
$viewfullnames = has_capability('moodle/site:viewfullnames', $context);
|
||||
|
||||
foreach($groupmemberroles as $roleid=>$roledata) {
|
||||
foreach ($groupmemberroles as $roleid => $roledata) {
|
||||
$shortroledata = new stdClass();
|
||||
$shortroledata->name = $roledata->name;
|
||||
$shortroledata->users = array();
|
||||
foreach($roledata->users as $member) {
|
||||
foreach ($roledata->users as $member) {
|
||||
$shortmember = new stdClass();
|
||||
$shortmember->id = $member->id;
|
||||
$shortmember->name = fullname($member, $viewfullnames);
|
||||
@ -123,48 +123,60 @@ switch ($action) {
|
||||
throw new \moodle_exception('errorselectsome', 'group', $returnurl);
|
||||
}
|
||||
$groupidlist = implode(',', $groupids);
|
||||
redirect(new moodle_url('/group/delete.php', array('courseid'=>$courseid, 'groups'=>$groupidlist)));
|
||||
redirect(new moodle_url('/group/delete.php', array('courseid' => $courseid, 'groups' => $groupidlist)));
|
||||
break;
|
||||
|
||||
case 'showcreateorphangroupform':
|
||||
redirect(new moodle_url('/group/group.php', array('courseid'=>$courseid)));
|
||||
redirect(new moodle_url('/group/group.php', array('courseid' => $courseid)));
|
||||
break;
|
||||
|
||||
case 'showautocreategroupsform':
|
||||
redirect(new moodle_url('/group/autogroup.php', array('courseid'=>$courseid)));
|
||||
redirect(new moodle_url('/group/autogroup.php', array('courseid' => $courseid)));
|
||||
break;
|
||||
|
||||
case 'showimportgroups':
|
||||
redirect(new moodle_url('/group/import.php', array('id'=>$courseid)));
|
||||
redirect(new moodle_url('/group/import.php', array('id' => $courseid)));
|
||||
break;
|
||||
|
||||
case 'showgroupsettingsform':
|
||||
redirect(new moodle_url('/group/group.php', array('courseid'=>$courseid, 'id'=>$groupids[0])));
|
||||
redirect(new moodle_url('/group/group.php', array('courseid' => $courseid, 'id' => $groupids[0])));
|
||||
break;
|
||||
|
||||
case 'updategroups': //Currently reloading.
|
||||
case 'updategroups': // Currently reloading.
|
||||
break;
|
||||
|
||||
case 'removemembers':
|
||||
break;
|
||||
|
||||
case 'showaddmembersform':
|
||||
redirect(new moodle_url('/group/members.php', array('group'=>$groupids[0])));
|
||||
redirect(new moodle_url('/group/members.php', array('group' => $groupids[0])));
|
||||
break;
|
||||
|
||||
case 'updatemembers': //Currently reloading.
|
||||
case 'updatemembers': // Currently reloading.
|
||||
break;
|
||||
|
||||
default: //ERROR.
|
||||
case 'enablemessaging':
|
||||
set_groups_messaging($groupids, true);
|
||||
redirect($returnurl, get_string('messagingenabled', 'group', count($groupids)), null,
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
|
||||
case 'disablemessaging':
|
||||
set_groups_messaging($groupids, false);
|
||||
redirect($returnurl, get_string('messagingdisabled', 'group', count($groupids)), null,
|
||||
\core\output\notification::NOTIFY_SUCCESS);
|
||||
break;
|
||||
|
||||
default: // ERROR.
|
||||
throw new \moodle_exception('unknowaction', '', $returnurl);
|
||||
break;
|
||||
}
|
||||
|
||||
// Print the page and form
|
||||
// Print the page and form.
|
||||
$strgroups = get_string('groups');
|
||||
$strparticipants = get_string('participants');
|
||||
|
||||
/// Print header
|
||||
// Print header.
|
||||
$PAGE->set_title($strgroups);
|
||||
$PAGE->set_heading($course->fullname);
|
||||
$PAGE->set_pagelayout('standard');
|
||||
@ -244,42 +256,11 @@ if ($singlegroup) {
|
||||
|
||||
$disableaddedit = !$singlegroup;
|
||||
$disabledelete = !empty($groupids);
|
||||
$caneditmessaging = \core_message\api::can_create_group_conversation($USER->id, $context);
|
||||
|
||||
$renderable = new \core_group\output\index_page($courseid, $groupoptions, $selectedname, $members, $disableaddedit, $disabledelete,
|
||||
$preventgroupremoval);
|
||||
$preventgroupremoval, $caneditmessaging);
|
||||
$output = $PAGE->get_renderer('core_group');
|
||||
echo $output->render($renderable);
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
/**
|
||||
* Returns the first button action with the given prefix, taken from
|
||||
* POST or GET, otherwise returns false.
|
||||
* @see /lib/moodlelib.php function optional_param().
|
||||
* @param string $prefix 'act_' as in 'action'.
|
||||
* @return string The action without the prefix, or false if no action found.
|
||||
*/
|
||||
function groups_param_action($prefix = 'act_') {
|
||||
$action = false;
|
||||
//($_SERVER['QUERY_STRING'] && preg_match("/$prefix(.+?)=(.+)/", $_SERVER['QUERY_STRING'], $matches)) { //b_(.*?)[&;]{0,1}/
|
||||
|
||||
if ($_POST) {
|
||||
$form_vars = $_POST;
|
||||
}
|
||||
elseif ($_GET) {
|
||||
$form_vars = $_GET;
|
||||
}
|
||||
if ($form_vars) {
|
||||
foreach ($form_vars as $key => $value) {
|
||||
if (preg_match("/$prefix(.+)/", $key, $matches)) {
|
||||
$action = $matches[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($action && !preg_match('/^\w+$/', $action)) {
|
||||
$action = false;
|
||||
throw new \moodle_exception('unknowaction');
|
||||
}
|
||||
///if (debugging()) echo 'Debug: '.$action;
|
||||
return $action;
|
||||
}
|
||||
|
@ -1208,3 +1208,17 @@ function core_group_inplace_editable($itemtype, $itemid, $newvalue) {
|
||||
return \core_group\output\user_groups_editable::update($itemid, $newvalue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates group messaging to enable/disable in bulk.
|
||||
*
|
||||
* @param array $groupids array of group id numbers.
|
||||
* @param bool $enabled if true, enables messaging else disables messaging
|
||||
*/
|
||||
function set_groups_messaging(array $groupids, bool $enabled): void {
|
||||
foreach ($groupids as $groupid) {
|
||||
$data = groups_get_group($groupid, '*', MUST_EXIST);
|
||||
$data->enablemessaging = $enabled;
|
||||
groups_update_group($data);
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
* groups array The list of groups.
|
||||
* members array The list of members, grouped based on roles.
|
||||
* undeletablegroups string A JSON string containing an array of group IDs that a user cannot delete.
|
||||
* messagingsettingsvisible bool Wether the messaging settings buttons should be visible.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
@ -42,6 +43,7 @@
|
||||
"editgroupsettingsdisabled": false,
|
||||
"deletegroupdisabled": false,
|
||||
"addmembersdisabled": false,
|
||||
"messagingenabled": true,
|
||||
"groups": [
|
||||
{
|
||||
"value": "1",
|
||||
@ -91,23 +93,33 @@
|
||||
{{/groups}}
|
||||
</select>
|
||||
</div>
|
||||
<h3> {{#str}} withselected, group {{/str}} </h3>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_updatemembers" id="updatemembers" value="{{#str}}showmembersforgroup, group{{/str}}" class="btn btn-secondary" />
|
||||
<button type="submit" name="action" id="updatemembers" value="updatemembers" class="btn btn-secondary">{{#str}}showmembersforgroup, group{{/str}}</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_showgroupsettingsform" id="showeditgroupsettingsform" value="{{#str}}editgroupsettings, group{{/str}}" {{#editgroupsettingsdisabled}}disabled="disabled"{{/editgroupsettingsdisabled}} class="btn btn-secondary" />
|
||||
<button type="submit" name="action" id="showeditgroupsettingsform" value="showgroupsettingsform" {{#editgroupsettingsdisabled}}disabled="disabled"{{/editgroupsettingsdisabled}} class="btn btn-secondary">{{#str}}editgroupsettings, group{{/str}}</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_deletegroup" id="deletegroup" value="{{#str}}deleteselectedgroup, group{{/str}}" {{#deletegroupdisabled}}disabled="disabled"{{/deletegroupdisabled}} class="btn btn-secondary" />
|
||||
<button type="submit" name="action" id="deletegroup" value="deletegroup" {{#deletegroupdisabled}}disabled="disabled"{{/deletegroupdisabled}} class="btn btn-secondary">{{#str}}deleteselectedgroup, group{{/str}}</button>
|
||||
</div>
|
||||
{{#messagingsettingsvisible}}
|
||||
<div class="form-group">
|
||||
<button type="submit" name="action" id="disablemessaging" value="disablemessaging" class="btn btn-secondary" disabled="disabled">{{#str}}disablemessagingaction, group{{/str}}</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="submit" name="action" id="enablemessaging" value="enablemessaging" class="btn btn-secondary" disabled="disabled">{{#str}}enablemessagingaction, group{{/str}}</button>
|
||||
</div>
|
||||
{{/messagingsettingsvisible}}
|
||||
<h3> {{#str}} manageactions, group {{/str}} </h3>
|
||||
<div class="form-group">
|
||||
<button type="submit" name="action" id="showcreateorphangroupform" value="showcreateorphangroupform" class="btn btn-secondary">{{#str}}creategroup, group{{/str}}</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_showcreateorphangroupform" id="showcreateorphangroupform" value="{{#str}}creategroup, group{{/str}}" class="btn btn-secondary" />
|
||||
<button type="submit" name="action" id="showautocreategroupsform" value="showautocreategroupsform" class="btn btn-secondary">{{#str}}autocreategroups, group{{/str}}</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_showautocreategroupsform" id="showautocreategroupsform" value="{{#str}}autocreategroups, group{{/str}}" class="btn btn-secondary" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" name="act_showimportgroups" id="showimportgroups" value="{{#str}}importgroups, group{{/str}}" class="btn btn-secondary" />
|
||||
<button type="submit" name="action" id="showimportgroups" value="showimportgroups" class="btn btn-secondary">{{#str}}importgroups, group{{/str}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 mb-1">
|
||||
@ -127,7 +139,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" value="{{#str}}adduserstogroup, group{{/str}}" class="btn btn-secondary" {{#addmembersdisabled}}disabled="disabled"{{/addmembersdisabled}} name="act_showaddmembersform" id="showaddmembersform"/>
|
||||
<button type="submit" value="showaddmembersform" class="btn btn-secondary" {{#addmembersdisabled}}disabled="disabled"{{/addmembersdisabled}} name="action" id="showaddmembersform">{{#str}}adduserstogroup, group{{/str}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -143,3 +155,6 @@
|
||||
M.core_group.groupslist(Y, undeletableGroups);
|
||||
});
|
||||
{{/js}}
|
||||
{{#js}}
|
||||
require(['core_group/index'], (module) => module.init());
|
||||
{{/js}}
|
||||
|
66
group/tests/behat/bulk_messaging.feature
Normal file
66
group/tests/behat/bulk_messaging.feature
Normal file
@ -0,0 +1,66 @@
|
||||
@core @core_group
|
||||
Feature: Bulk update group messaging status
|
||||
In order to update group messaging settings in bulk
|
||||
As a teacher
|
||||
I need to be able to select the groups and update their messaging settings using the buttons provided.
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And I log in as "teacher1"
|
||||
And I am on the "Course 1" "groups" page
|
||||
And I press "Create group"
|
||||
And I set the following fields to these values:
|
||||
| Group name | Group-A-Test |
|
||||
| Group ID number | Group-A-Test |
|
||||
And I press "Save changes"
|
||||
And I press "Create group"
|
||||
And I set the following fields to these values:
|
||||
| Group name | Group-B-Test |
|
||||
| Group ID number | Group-B-Test |
|
||||
And I press "Save changes"
|
||||
And I select "Groups" from the "jump" singleselect
|
||||
|
||||
@javascript
|
||||
Scenario: Bulk enable messaging in groups
|
||||
Given I set the field "groups" to "Group-A-Test (0)"
|
||||
And I press "Edit group settings"
|
||||
And I set the field "id_enablemessaging" to "0"
|
||||
And I press "Save changes"
|
||||
And I wait until the page is ready
|
||||
And the field "groups" matches value "Group-A-Test (0)"
|
||||
And I press "Enable messaging"
|
||||
And I wait until the page is ready
|
||||
And I should see "Successfully enabled messaging in 1 group(s)"
|
||||
And I set the field "groups" to "Group-A-Test (0)"
|
||||
And I press "Edit group settings"
|
||||
Then the field "id_enablemessaging" matches value "1"
|
||||
|
||||
@javascript
|
||||
Scenario: Bulk disable messaging in groups
|
||||
Given I set the field "groups" to "Group-A-Test (0)"
|
||||
And I press "Edit group settings"
|
||||
And I set the field "id_enablemessaging" to "1"
|
||||
And I press "Save changes"
|
||||
And I wait until the page is ready
|
||||
And the field "groups" matches value "Group-A-Test (0)"
|
||||
And I press "Disable messaging"
|
||||
And I wait until the page is ready
|
||||
And I should see "Successfully disabled messaging in 1 group(s)"
|
||||
And I set the field "groups" to "Group-A-Test (0)"
|
||||
And I press "Edit group settings"
|
||||
Then the field "id_enablemessaging" matches value "0"
|
||||
|
||||
@javascript
|
||||
Scenario: Messaging buttons are enabled when a group is selected
|
||||
Given I set the field "groups" to "Group-A-Test (0)"
|
||||
Then the field "groups" matches value "Group-A-Test (0)"
|
||||
And the "Enable messaging" "button" should be enabled
|
||||
And the "Disable messaging" "button" should be enabled
|
@ -40,11 +40,11 @@ Feature: Automatic deletion of groups and groupings
|
||||
@javascript
|
||||
Scenario: Delete groups and groupings with and without ID numbers
|
||||
Given I set the field "groups" to "Group (without ID) (0)"
|
||||
And I press "Delete selected group"
|
||||
And I press "Delete"
|
||||
And I press "Yes"
|
||||
Then the "groups" select box should not contain "Group (without ID) (0)"
|
||||
And I set the field "groups" to "Group (with ID) (0)"
|
||||
And I press "Delete selected group"
|
||||
And I press "Delete"
|
||||
And I press "Yes"
|
||||
And the "groups" select box should not contain "Group (with ID) (0)"
|
||||
And I select "Groupings" from the "jump" singleselect
|
||||
@ -65,9 +65,9 @@ Feature: Automatic deletion of groups and groupings
|
||||
And I log in as "teacher1"
|
||||
And I am on the "Course 1" "groups" page
|
||||
When I set the field "groups" to "Group (with ID) (0)"
|
||||
Then the "Delete selected group" "button" should be disabled
|
||||
Then the "Delete" "button" should be disabled
|
||||
And I set the field "groups" to "Group (without ID) (0)"
|
||||
And I press "Delete selected group"
|
||||
And I press "Delete"
|
||||
And I press "Yes"
|
||||
And I should not see "Group (without ID)"
|
||||
And I select "Groupings" from the "jump" singleselect
|
||||
|
@ -789,4 +789,93 @@ class lib_test extends \advanced_testcase {
|
||||
['prefname' => 'reptile'], 'JOIN {user_preferences} up ON up.userid = u.id');
|
||||
$this->assertEquals('snake', reset($result[0]->users)->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests set_groups_messaging
|
||||
*
|
||||
* @covers \core_group::set_groups_messaging
|
||||
*/
|
||||
public function test_set_groups_messaging() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
$dg = $this->getDataGenerator();
|
||||
$course = $dg->create_course();
|
||||
|
||||
// Create some groups in the course.
|
||||
$groupids = [];
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$group = new \stdClass();
|
||||
$group->courseid = $course->id;
|
||||
$group->name = 'group-'.$i;
|
||||
$group->enablemessaging = 0;
|
||||
$groupids[] = groups_create_group($group);
|
||||
}
|
||||
|
||||
// They should all initially be disabled.
|
||||
$alldisabledinitially = $this->check_groups_messaging_status_is($groupids, $course->id, false);
|
||||
$this->assertTrue($alldisabledinitially);
|
||||
|
||||
// Enable messaging for all the groups.
|
||||
set_groups_messaging($groupids, true);
|
||||
|
||||
// Check they were all enabled.
|
||||
$allenabled = $this->check_groups_messaging_status_is($groupids, $course->id, true);
|
||||
$this->assertTrue($allenabled);
|
||||
|
||||
// Disable messaging for all the groups.
|
||||
set_groups_messaging($groupids, false);
|
||||
|
||||
// Check they were all disabled.
|
||||
$alldisabled = $this->check_groups_messaging_status_is($groupids, $course->id, false);
|
||||
$this->assertTrue($alldisabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests set group messaging where it doesn't exist
|
||||
*
|
||||
* @covers \core_group::set_groups_messaging
|
||||
*/
|
||||
public function test_set_groups_messaging_doesnt_exist() {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$groupids = [-1];
|
||||
|
||||
$this->expectException('dml_exception');
|
||||
set_groups_messaging($groupids, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given list of groups to verify their messaging settings.
|
||||
*
|
||||
* @param array $groupids array of group ids
|
||||
* @param int $courseid the course the groups are in
|
||||
* @param bool $desired the desired setting value
|
||||
* @return bool true if all groups $enablemessaging setting matches the given $desired value, else false
|
||||
*/
|
||||
private function check_groups_messaging_status_is(array $groupids, int $courseid, bool $desired) {
|
||||
$context = \context_course::instance($courseid);
|
||||
|
||||
foreach ($groupids as $groupid) {
|
||||
$conversation = \core_message\api::get_conversation_by_area(
|
||||
'core_group',
|
||||
'groups',
|
||||
$groupid,
|
||||
$context->id
|
||||
);
|
||||
|
||||
// An empty conversation means it has not been enabled yet.
|
||||
if (empty($conversation)) {
|
||||
$conversation = (object) [
|
||||
'enabled' => 0
|
||||
];
|
||||
}
|
||||
|
||||
if ($desired !== boolval($conversation->enabled)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -54,11 +54,13 @@ $string['deletegroupconfirm'] = 'Are you sure you want to delete group \'{$a}\'?
|
||||
$string['deletegrouping'] = 'Delete grouping';
|
||||
$string['deletegroupingconfirm'] = 'Are you sure you want to delete grouping \'{$a}\'? (Groups in the grouping are not deleted.)';
|
||||
$string['deletegroupsconfirm'] = 'Are you sure you want to delete the following groups?';
|
||||
$string['deleteselectedgroup'] = 'Delete selected group';
|
||||
$string['deleteselectedgroup'] = 'Delete';
|
||||
$string['disablemessagingaction'] = 'Disable messaging';
|
||||
$string['editgroupingsettings'] = 'Edit grouping settings';
|
||||
$string['editgroupsettings'] = 'Edit group settings';
|
||||
$string['editusersgroupsa'] = 'Edit groups for "{$a}"';
|
||||
$string['enablemessaging'] = 'Group messaging';
|
||||
$string['enablemessagingaction'] = 'Enable messaging';
|
||||
$string['enablemessaging_help'] = 'If enabled, group members can send messages to the others in their group via the messaging drawer.';
|
||||
$string['encoding'] = 'Encoding';
|
||||
$string['enrolmentkey'] = 'Enrolment key';
|
||||
@ -171,6 +173,9 @@ $string['nousersinrole'] = 'There are no suitable users in the selected role';
|
||||
$string['number'] = 'Group/member count';
|
||||
$string['numgroups'] = 'Number of groups';
|
||||
$string['nummembers'] = 'Members per group';
|
||||
$string['manageactions'] = 'Manage';
|
||||
$string['messagingdisabled'] = 'Successfully disabled messaging in {$a} group(s)';
|
||||
$string['messagingenabled'] = 'Successfully enabled messaging in {$a} group(s)';
|
||||
$string['mygroups'] = 'My groups';
|
||||
$string['othergroups'] = 'Other groups';
|
||||
$string['overview'] = 'Overview';
|
||||
@ -216,3 +221,4 @@ $string['visibilitymembers'] = 'Only visible to members';
|
||||
$string['visibilityown'] = 'Only see own membership';
|
||||
$string['visibilitynone'] = 'Hidden';
|
||||
$string['memberofgroup'] = 'Group member of: {$a}';
|
||||
$string['withselected'] = 'With selected';
|
||||
|
Loading…
x
Reference in New Issue
Block a user