diff --git a/CHANGES.md b/CHANGES.md index 5960cf2..74953f9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,12 @@ CHANGELOG ========= +Changes in v5.2-r1 +---------------------------------- + +- support for Moodle 5.2 +- add CHANGES.md for user-visible changes + Changes in v5.0-r1 (since v4.5-r1) ---------------------------------- diff --git a/amd/build/blocks_groups_visibility.min.js b/amd/build/blocks_groups_visibility.min.js index b38aca0..61e53d3 100644 --- a/amd/build/blocks_groups_visibility.min.js +++ b/amd/build/blocks_groups_visibility.min.js @@ -5,6 +5,6 @@ * @copyright 2016/17 N Herrmann * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -define("block_groups/blocks_groups_visibility",["jquery","core/ajax","core/url","core/notification","core/str"],(function($,ajax,url,notification,str){var removeWarning=function(identifier){$(".block_groups").find(".warning"+identifier).remove()},removeSpinner=function(groupid){var divgroup=$(".block_groups");divgroup.find(".spinner"+groupid).remove(),divgroup.find(".imggroup-"+groupid).show()},removeSpinners=function(){var divgroups=$(".block_groups");divgroups.find(".spinner-all").remove(),divgroups.find(".imggroup").show()},reloadPage=function(){location.reload(!0)},createWarningMessage=function(){str.get_strings([{key:"errortitle",component:"block_groups"},{key:"nochangeindatabasepossiblereload",component:"block_groups"},{key:"yes"},{key:"no"}]).done((function(s){notification.confirm(s[0],s[1],s[2],s[3],reloadPage)})).fail(notification.exception)},addWarning=function(identifier){var divgroups=$(".block_groups");if(divgroups.find(".warning"+identifier).length)return removeSpinner(identifier),!1;"all"===identifier?removeSpinners():removeSpinner(identifier);var imgurl=url.imageUrl("i/warning","moodle"),warning=document.createElement("img");return warning.className="warning"+identifier+" block-groups-warning",warning.src=imgurl,createWarningMessage(),divgroups.find(".imggroup-"+identifier).before(warning),divgroups.find(".imggroup-"+identifier).on("click",createWarningMessage),divgroups.find(".warning"+identifier).on("click",createWarningMessage),!1},changevisibility=function(event){var divgroups=$(".block_groups"),groupid=$(this).data("groupid");if(divgroups.find(".spinner"+$(this).data("groupid")).length>0||divgroups.find(".spinner-all").length>0)return!1;!function(groupid){var divgroups=$(".block_groups");divgroups.find(".warning"+groupid).length>0&&removeWarning(groupid);var imgurl=url.imageUrl("i/loading_small","moodle"),spinner=document.createElement("img");spinner.className="spinner"+groupid+" spinner block-groups-spinner",spinner.src=imgurl,spinner.hidden=!1,divgroups.find(".imggroup-"+groupid).before(spinner),divgroups.find(".imggroup-"+groupid).hide()}($(this).data("groupid"));var promises=ajax.call([{methodname:"block_groups_create_output",args:{groups:{id:$(this).data("groupid"),courseid:event.data.courseid}}}]);return $(document).ajaxError((function(){return addWarning(groupid),!1})),promises[0].then((function(response){return null===response||!0===response.error?(addWarning(groupid),!1):(divgroups.find(".group-"+response.id).replaceWith(response.newelement),0===response.visibility&&divgroups.find(".membergroup-"+response.id).removeClass("hiddengroups"),1===response.visibility&&divgroups.find(".membergroup-"+response.id).addClass("hiddengroups"),divgroups.find(".group-"+response.id+" .block_groups_toggle").on("click",{courseid:event.data.courseid},changevisibility),removeSpinner(response.id),!1)})).fail((function(){return addWarning(groupid),!1})),!1},addNotification=function(type,text){notification.addNotification({message:text,type:type})},changeVisibilityAll=function(event){if($(".block_groups").find(".spinner").length>0)return!1;var warningexist=$(".block_groups").find(".block-groups-warning");if(void 0!==warningexist&&warningexist.length>0)return addWarning("all"),!1;!function(){var divgroups=$(".block_groups");divgroups.find(".warningall").length>0&&removeWarning("all");var imgurl=url.imageUrl("i/loading_small","moodle"),spinner=document.createElement("img");spinner.className="spinner-all spinner block-groups-spinner",spinner.src=imgurl,spinner.hidden=!1,divgroups.find(".imggroup").before(spinner),divgroups.find(".imggroup").hide()}();var promises=ajax.call([{methodname:"block_groups_create_allgroups_output",args:{groups:{action:$(this).data("action"),courseid:event.data.courseid}}}]);return $(document).ajaxError((function(){return addWarning("all"),!1})),promises[0].then((function(response){var divgroups=$(".block_groups");return null===response||!0===response.error?(addWarning("all"),!1):0===response.visibility?(divgroups.find(".content").replaceWith(response.newelement),str.get_strings([{key:"nogroups",component:"block_groups"}]).done((function(s){addNotification("error",s[0])})).fail(notification.exception),!1):(divgroups.find(".wrapperlistgroup").replaceWith(response.newelement),divgroups.find(".block_groups_toggle").on("click",{courseid:event.data.courseid},changevisibility),function(response){var membergroup=$(".block-groups-membergroup"),visibility=response.visibility;2===visibility&&membergroup.removeClass("hiddengroups"),1===visibility&&membergroup.addClass("hiddengroups")}(response),str.get_strings([{key:"groupschangedhidden",component:"block_groups"},{key:"groupschangedvisible",component:"block_groups"},{key:"allgroupsinstatehidden",component:"block_groups"},{key:"allgroupsinstatevisible",component:"block_groups"}]).done((function(s){switch(response.visibility){case 1:addNotification("success",s[0]);break;case 2:addNotification("success",s[1]);break;case 3:addNotification("warning",s[2]);break;case 4:addNotification("warning",s[3])}})).fail(notification.exception),!1)})).fail((function(){return addWarning("all"),!1})),removeSpinners(),!1};return{initialise:function(courseid){$(".block_groups_toggle").on("click",{courseid:courseid},changevisibility),$(".block_groups_all_toggle").on("click",{courseid:courseid},changeVisibilityAll)}}})); +define("block_groups/blocks_groups_visibility",["jquery","core/ajax","core/url","core/notification","core/str"],(function($,ajax,url,notification,str){var removeWarning=function(identifier){$(".block_groups").find(".warning"+identifier).remove()},removeSpinner=function(groupid){var divgroup=$(".block_groups");divgroup.find(".spinner"+groupid).remove(),divgroup.find(".imggroup-"+groupid).show()},removeSpinners=function(){var divgroups=$(".block_groups");divgroups.find(".spinner-all").remove(),divgroups.find(".imggroup").show()},reloadPage=function(){location.reload(!0)},createWarningMessage=function(){str.get_strings([{key:"errortitle",component:"block_groups"},{key:"nochangeindatabasepossiblereload",component:"block_groups"},{key:"yes"},{key:"no"}]).done((function(s){notification.confirm(s[0],s[1],s[2],s[3],reloadPage)})).fail(notification.exception)},addWarning=function(identifier){var divgroups=$(".block_groups");if(divgroups.find(".warning"+identifier).length)return removeSpinner(identifier),!1;"all"===identifier?removeSpinners():removeSpinner(identifier);var imgurl=url.imageUrl("i/warning","moodle"),warning=document.createElement("img");return warning.className="warning"+identifier+" block-groups-warning",warning.src=imgurl,createWarningMessage(),divgroups.find(".imggroup-"+identifier).before(warning),divgroups.find(".imggroup-"+identifier).on("click",createWarningMessage),divgroups.find(".warning"+identifier).on("click",createWarningMessage),!1},changevisibility=function(event){var divgroups=$(".block_groups"),groupid=$(this).data("groupid");if(divgroups.find(".spinner"+$(this).data("groupid")).length>0||divgroups.find(".spinner-all").length>0)return!1;!function(groupid){var divgroups=$(".block_groups");divgroups.find(".warning"+groupid).length>0&&removeWarning(groupid);var imgurl=url.imageUrl("i/loading_small","moodle"),spinner=document.createElement("img");spinner.className="spinner"+groupid+" spinner block-groups-spinner",spinner.src=imgurl,spinner.hidden=!1,divgroups.find(".imggroup-"+groupid).before(spinner),divgroups.find(".imggroup-"+groupid).hide()}($(this).data("groupid"));var promises=ajax.call([{methodname:"block_groups_create_output",args:{groups:{id:$(this).data("groupid"),courseid:event.data.courseid}}}]);return $(document).ajaxError((function(){return addWarning(groupid),!1})),promises[0].then((function(response){return null===response||!0===response.error?(addWarning(groupid),!1):(divgroups.find(".group-"+response.id).replaceWith(response.newelement),0===response.visibility&&divgroups.find(".membergroup-"+response.id).removeClass("hiddengroups"),1===response.visibility&&divgroups.find(".membergroup-"+response.id).addClass("hiddengroups"),divgroups.find(".group-"+response.id+" .block_groups_toggle").on("click",{courseid:event.data.courseid},changevisibility),removeSpinner(response.id),!1)})).fail((function(){return addWarning(groupid),!1})),!1},addNotification=function(type,text){notification.addNotification({message:text,type:type})},changeVisibilityAll=function(event){if($(".block_groups").find(".spinner").length>0)return!1;var warningexist=$(".block_groups").find(".block-groups-warning");if(void 0!==warningexist&&warningexist.length>0)return addWarning("all"),!1;!function(){var divgroups=$(".block_groups");divgroups.find(".warningall").length>0&&removeWarning("all");var imgurl=url.imageUrl("i/loading_small","moodle"),spinner=document.createElement("img");spinner.className="spinner-all spinner block-groups-spinner",spinner.src=imgurl,spinner.hidden=!1,divgroups.find(".imggroup").before(spinner),divgroups.find(".imggroup").hide()}();var promises=ajax.call([{methodname:"block_groups_create_allgroups_output",args:{groups:{action:$(this).data("action"),courseid:event.data.courseid}}}]);return $(document).ajaxError((function(){return addWarning("all"),!1})),promises[0].then((function(response){var divgroups=$(".block_groups");return null===response||!0===response.error?(addWarning("all"),!1):0===response.visibility?(divgroups.find(".content").replaceWith(response.newelement),str.get_strings([{key:"nogroups",component:"block_groups"}]).done((function(s){addNotification("error",s[0])})).fail(notification.exception),!1):(divgroups.find(".wrapperlistgroup").replaceWith(response.newelement),divgroups.find(".block_groups_toggle").on("click",{courseid:event.data.courseid},changevisibility),function(response){var membergroup=$(".block-groups-membergroup"),visibility=response.visibility;2===visibility&&membergroup.removeClass("hiddengroups"),1===visibility&&membergroup.addClass("hiddengroups")}(response),str.get_strings([{key:"groupschangedhidden",component:"block_groups"},{key:"groupschangedvisible",component:"block_groups"},{key:"allgroupsinstatehidden",component:"block_groups"},{key:"allgroupsinstatevisible",component:"block_groups"}]).done((function(s){switch(response.visibility){case 1:addNotification("success",s[0]);break;case 2:addNotification("success",s[1]);break;case 3:addNotification("warning",s[2]);break;case 4:addNotification("warning",s[3])}})).fail(notification.exception),!1)})).fail((function(){return addWarning("all"),!1})),removeSpinners(),!1},changeVisibilityGrouping=function(event){var divgroups=$(".block_groups"),groupingid=$(this).data("groupingid"),action=$(this).data("action");if(divgroups.find(".spinner").length>0)return!1;var warningexist=divgroups.find(".block-groups-warning");if(void 0!==warningexist&&warningexist.length>0)return addWarning(groupingid),!1;!function(groupingid){var divgroups=$(".block_groups"),imgurl=url.imageUrl("i/loading_small","moodle");divgroups.find(".imggroup-grouping-"+groupingid).each((function(){var spinner=document.createElement("img");spinner.className="spinner-grouping-"+groupingid+" spinner block-groups-spinner",spinner.src=imgurl,spinner.hidden=!1,$(this).before(spinner),$(this).hide()}))}(groupingid);var promises=ajax.call([{methodname:"block_groups_create_grouping_output",args:{grouping:{groupingid:groupingid,courseid:event.data.courseid,action:action}}}]);return $(document).ajaxError((function(){return addWarning(groupingid),!1})),promises[0].then((function(response){return null===response||!0===response.error?(addWarning(groupingid),!1):(divgroups.find(".wrapperlistgroup").replaceWith(response.newelement),divgroups.find(".block_groups_toggle").on("click",{courseid:event.data.courseid},changevisibility),divgroups.find(".block_groups_grouping_toggle").on("click",{courseid:event.data.courseid},changeVisibilityGrouping),checkGroupingMembers(response),str.get_strings([{key:"groupingchangedhidden",component:"block_groups"},{key:"groupingchangedvisible",component:"block_groups"},{key:"groupinginstatehidden",component:"block_groups"},{key:"groupinginstatevisible",component:"block_groups"},{key:"nogroups",component:"block_groups"}]).done((function(s){switch(response.visibility){case 0:addNotification("warning",s[4]);break;case 1:addNotification("success",s[0]);break;case 2:addNotification("success",s[1]);break;case 3:addNotification("warning",s[2]);break;case 4:addNotification("warning",s[3])}})).fail(notification.exception),function(groupingid){var divgroups=$(".block_groups");divgroups.find(".spinner-grouping-"+groupingid).remove(),divgroups.find(".imggroup-grouping-"+groupingid).show()}(groupingid),!1)})).fail((function(){return addWarning(groupingid),!1})),!1},checkGroupingMembers=function(response){response.changedgroups.forEach((function(group){var membergroup=$(".membergroup-"+group.groupid);2===response.visibility&&membergroup.removeClass("hiddengroups"),1===response.visibility&&membergroup.addClass("hiddengroups")}))};return{initialise:function(courseid){$(".block_groups_toggle").on("click",{courseid:courseid},changevisibility),$(".block_groups_all_toggle").on("click",{courseid:courseid},changeVisibilityAll),$(".block_groups_grouping_toggle").on("click",{courseid:courseid},changeVisibilityGrouping)}}})); //# sourceMappingURL=blocks_groups_visibility.min.js.map \ No newline at end of file diff --git a/amd/build/blocks_groups_visibility.min.js.map b/amd/build/blocks_groups_visibility.min.js.map index 79bf1d2..a179b05 100644 --- a/amd/build/blocks_groups_visibility.min.js.map +++ b/amd/build/blocks_groups_visibility.min.js.map @@ -1 +1 @@ -{"version":3,"file":"blocks_groups_visibility.min.js","sources":["../src/blocks_groups_visibility.js"],"sourcesContent":["// 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// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n\n/**\n * Javascript module for block_groups\n *\n * @module block_groups\n * @copyright 2016/17 N Herrmann\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/url', 'core/notification', 'core/str'], function($, ajax, url, notification, str) {\n /**\n * Methode to remove warnings\n * @param {(Number|String)} identifier\n */\n var removeWarning = function(identifier) {\n $('.block_groups').find('.warning' + identifier).remove();\n };\n /**\n * Removes the Spinner Class of a single group.\n * @param {Number} groupid that identifies to which group the spinner belongs to.\n */\n var removeSpinner = function(groupid) {\n var divgroup = $('.block_groups');\n divgroup.find('.spinner' + groupid).remove();\n divgroup.find('.imggroup-' + groupid).show();\n };\n /**\n * Removes all spinners.\n */\n var removeSpinners = function() {\n var divgroups = $('.block_groups');\n divgroups.find('.spinner-all').remove();\n divgroups.find('.imggroup').show();\n };\n /**\n * Reloads the current page.\n */\n var reloadPage = function() {\n location.reload(true);\n };\n /**\n * Creates a warning message.\n */\n var createWarningMessage = function() {\n\n str.get_strings([\n {'key': 'errortitle', component: 'block_groups'},\n {'key': 'nochangeindatabasepossiblereload', component: 'block_groups'},\n {'key': 'yes'},\n {'key': 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], s[1], s[2], s[3], reloadPage);\n }).fail(notification.exception);\n };\n /**\n * Initialises Spinner for a single group.\n * @param {Number} groupid\n */\n var addSpinner = function(groupid) {\n var divgroups = $('.block_groups');\n if (divgroups.find('.warning' + groupid).length > 0) {\n\n removeWarning(groupid);\n }\n var imgurl = url.imageUrl(\"i/loading_small\", 'moodle');\n var spinner = document.createElement(\"img\");\n spinner.className = 'spinner' + groupid + ' spinner block-groups-spinner';\n spinner.src = imgurl;\n spinner.hidden = false;\n\n divgroups.find('.imggroup-' + groupid).before(spinner);\n divgroups.find('.imggroup-' + groupid).hide();\n };\n /**\n * Adds a warning(triangle with exclamation mark) in case the response is empty or the response throws an error.\n * @param {(Number|String)} identifier\n * @returns {Boolean} false\n */\n var addWarning = function(identifier) {\n var divgroups = $('.block_groups');\n var warningexist = divgroups.find('.warning' + identifier);\n if (warningexist.length) {\n removeSpinner(identifier);\n return false;\n } else {\n if (identifier === 'all') {\n removeSpinners();\n } else {\n removeSpinner(identifier);\n }\n var imgurl = url.imageUrl(\"i/warning\", 'moodle');\n var warning = document.createElement(\"img\");\n warning.className = 'warning' + identifier + ' block-groups-warning';\n warning.src = imgurl;\n createWarningMessage();\n (divgroups.find('.imggroup-' + identifier).before(warning));\n divgroups.find('.imggroup-' + identifier).on('click', createWarningMessage);\n divgroups.find('.warning' + identifier).on('click', createWarningMessage);\n }\n return false;\n };\n /**\n * Method that calls for an ajax script and replaces and/or changes the output components for a single group.\n * @param {*} event\n * @return {Boolean}\n */\n var changevisibility = function(event) {\n var divgroups = $('.block_groups');\n\n var groupid = $(this).data('groupid');\n if (divgroups.find('.spinner' + $(this).data('groupid')).length > 0 ||\n divgroups.find('.spinner-all').length > 0) {\n return false;\n }\n addSpinner($(this).data('groupid'));\n var promises = ajax.call([\n\n {\n methodname: 'block_groups_create_output', args: {\n groups: {\n id: $(this).data('groupid'),\n courseid: event.data.courseid\n }\n\n }\n }\n ]);\n $(document).ajaxError(function() {\n addWarning(groupid);\n return false;\n });\n\n promises[0].then(function(response) {\n if (response === null || response.error === true) {\n addWarning(groupid);\n return false;\n }\n divgroups.find('.group-' + response.id).replaceWith(response.newelement);\n // Replaces the used element, therefore removes the spinner.\n if (response.visibility === 0) {\n divgroups.find('.membergroup-' + response.id).removeClass('hiddengroups');\n }\n if (response.visibility === 1) {\n divgroups.find('.membergroup-' + response.id).addClass('hiddengroups');\n }\n divgroups.find('.group-' + response.id + ' .block_groups_toggle').on('click',\n {courseid: event.data.courseid}, changevisibility);\n removeSpinner(response.id);\n return false;\n }).fail(function() {\n addWarning(groupid);\n return false;\n });\n return false;\n };\n var checkMember = function(response) {\n var membergroup = $('.block-groups-membergroup');\n var visibility = response.visibility;\n if (visibility === 2) {\n membergroup.removeClass('hiddengroups');\n }\n if (visibility === 1) {\n membergroup.addClass('hiddengroups');\n }\n };\n /**\n * Initialises spinners for all groups.\n */\n var addSpinners = function() {\n var divgroups = $('.block_groups');\n if (divgroups.find('.warningall').length > 0) {\n removeWarning('all');\n }\n var imgurl = url.imageUrl(\"i/loading_small\", 'moodle');\n var spinner = document.createElement(\"img\");\n spinner.className = 'spinner-all spinner block-groups-spinner';\n spinner.src = imgurl;\n spinner.hidden = false;\n divgroups.find('.imggroup').before(spinner);\n divgroups.find('.imggroup').hide();\n };\n\n var addNotification = function(type, text) {\n notification.addNotification({\n message: text,\n type: type\n });\n };\n /**\n * Method that calls for an ajax script and replaces and/or changes the output components for all groups.\n * @param {Number} event\n * @return {Boolean}\n */\n var changeVisibilityAll = function(event) {\n if ($('.block_groups').find('.spinner').length > 0) {\n return false;\n }\n var warningexist = $('.block_groups').find('.block-groups-warning');\n if (typeof warningexist !== 'undefined' && warningexist.length > 0) {\n addWarning('all');\n return false;\n }\n addSpinners();\n // Calls for the externallib.\n var promises = ajax.call([\n {\n methodname: 'block_groups_create_allgroups_output', args: {\n groups: {\n action: $(this).data('action'),\n courseid: event.data.courseid\n }\n }\n }\n ]);\n $(document).ajaxError(function() {\n addWarning('all');\n return false;\n });\n // Response is processed.\n promises[0].then(function(response) {\n var divgroups = $('.block_groups');\n // Catch misleading responses.\n if (response === null || response.error === true) {\n addWarning('all');\n return false;\n }\n if (response.visibility === 0) {\n // Is nearly impossible since group has to be deleted during the request, however it is\n // possible, therefore a special message is thrown.\n divgroups.find('.content').replaceWith(response.newelement);\n str.get_strings([\n {key: 'nogroups', component: 'block_groups'}\n ]).done(function(s) {\n addNotification('error', s[0]);\n }).fail(notification.exception);\n return false;\n }\n\n // Old Elements are replaced and on click event added.\n divgroups.find('.wrapperlistgroup').replaceWith(response.newelement);\n divgroups.find('.block_groups_toggle').on('click', {courseid: event.data.courseid}, changevisibility);\n checkMember(response);\n // Outputvisibility 0->nogroups 1 -> hidden 2->visible 3-> all are hidden 4-> all are visible.\n str.get_strings([\n {key: 'groupschangedhidden', component: 'block_groups'},\n {key: 'groupschangedvisible', component: 'block_groups'},\n {key: 'allgroupsinstatehidden', component: 'block_groups'},\n {key: 'allgroupsinstatevisible', component: 'block_groups'}\n ]).done(function(s) {\n switch (response.visibility) {\n case 1:\n addNotification('success', s[0]);\n break;\n case 2:\n addNotification('success', s[1]);\n break;\n case 3:\n addNotification('warning', s[2]);\n break;\n case 4:\n addNotification('warning', s[3]);\n break;\n default:\n break;\n }\n }).fail(notification.exception);\n return false;\n }).fail(function() {\n addWarning('all');\n return false;\n });\n removeSpinners();\n return false;\n };\n\n /**\n * Calls for the main method. Either single groups are changed with block_groups_toggle or all groups with\n * block_groups_all_toggle.\n * @param {Number} courseid\n */\n return {\n initialise: function(courseid) {\n $('.block_groups_toggle').on('click', {courseid: courseid}, changevisibility);\n $('.block_groups_all_toggle').on('click', {courseid: courseid}, changeVisibilityAll);\n\n }\n };\n});\n"],"names":["define","$","ajax","url","notification","str","removeWarning","identifier","find","remove","removeSpinner","groupid","divgroup","show","removeSpinners","divgroups","reloadPage","location","reload","createWarningMessage","get_strings","component","done","s","confirm","fail","exception","addWarning","length","imgurl","imageUrl","warning","document","createElement","className","src","before","on","changevisibility","event","this","data","spinner","hidden","hide","addSpinner","promises","call","methodname","args","groups","id","courseid","ajaxError","then","response","error","replaceWith","newelement","visibility","removeClass","addClass","addNotification","type","text","message","changeVisibilityAll","warningexist","addSpinners","action","key","membergroup","checkMember","initialise"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"blocks_groups_visibility.min.js","sources":["../src/blocks_groups_visibility.js"],"sourcesContent":["// 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// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n\n/**\n * Javascript module for block_groups\n *\n * @module block_groups\n * @copyright 2016/17 N Herrmann\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\ndefine(['jquery', 'core/ajax', 'core/url', 'core/notification', 'core/str'], function($, ajax, url, notification, str) {\n /**\n * Methode to remove warnings\n * @param {(Number|String)} identifier\n */\n var removeWarning = function(identifier) {\n $('.block_groups').find('.warning' + identifier).remove();\n };\n /**\n * Removes the Spinner Class of a single group.\n * @param {Number} groupid that identifies to which group the spinner belongs to.\n */\n var removeSpinner = function(groupid) {\n var divgroup = $('.block_groups');\n divgroup.find('.spinner' + groupid).remove();\n divgroup.find('.imggroup-' + groupid).show();\n };\n /**\n * Removes all spinners.\n */\n var removeSpinners = function() {\n var divgroups = $('.block_groups');\n divgroups.find('.spinner-all').remove();\n divgroups.find('.imggroup').show();\n };\n /**\n * Reloads the current page.\n */\n var reloadPage = function() {\n location.reload(true);\n };\n /**\n * Creates a warning message.\n */\n var createWarningMessage = function() {\n\n str.get_strings([\n {'key': 'errortitle', component: 'block_groups'},\n {'key': 'nochangeindatabasepossiblereload', component: 'block_groups'},\n {'key': 'yes'},\n {'key': 'no'}\n ]).done(function(s) {\n notification.confirm(s[0], s[1], s[2], s[3], reloadPage);\n }).fail(notification.exception);\n };\n /**\n * Initialises Spinner for a single group.\n * @param {Number} groupid\n */\n var addSpinner = function(groupid) {\n var divgroups = $('.block_groups');\n if (divgroups.find('.warning' + groupid).length > 0) {\n\n removeWarning(groupid);\n }\n var imgurl = url.imageUrl(\"i/loading_small\", 'moodle');\n var spinner = document.createElement(\"img\");\n spinner.className = 'spinner' + groupid + ' spinner block-groups-spinner';\n spinner.src = imgurl;\n spinner.hidden = false;\n\n divgroups.find('.imggroup-' + groupid).before(spinner);\n divgroups.find('.imggroup-' + groupid).hide();\n };\n /**\n * Adds spinners for both visibility icons of one grouping.\n *\n * @param {Number} groupingid\n */\n var addGroupingSpinners = function(groupingid) {\n var divgroups = $('.block_groups');\n var imgurl = url.imageUrl(\"i/loading_small\", 'moodle');\n\n divgroups.find('.imggroup-grouping-' + groupingid).each(function() {\n var spinner = document.createElement(\"img\");\n spinner.className = 'spinner-grouping-' + groupingid + ' spinner block-groups-spinner';\n spinner.src = imgurl;\n spinner.hidden = false;\n $(this).before(spinner);\n $(this).hide();\n });\n };\n /**\n * Removes spinners for both visibility icons of one grouping.\n *\n * @param {Number} groupingid\n */\n var removeGroupingSpinners = function(groupingid) {\n var divgroups = $('.block_groups');\n\n divgroups.find('.spinner-grouping-' + groupingid).remove();\n divgroups.find('.imggroup-grouping-' + groupingid).show();\n };\n /**\n * Adds a warning(triangle with exclamation mark) in case the response is empty or the response throws an error.\n * @param {(Number|String)} identifier\n * @returns {Boolean} false\n */\n var addWarning = function(identifier) {\n var divgroups = $('.block_groups');\n var warningexist = divgroups.find('.warning' + identifier);\n if (warningexist.length) {\n removeSpinner(identifier);\n return false;\n } else {\n if (identifier === 'all') {\n removeSpinners();\n } else {\n removeSpinner(identifier);\n }\n var imgurl = url.imageUrl(\"i/warning\", 'moodle');\n var warning = document.createElement(\"img\");\n warning.className = 'warning' + identifier + ' block-groups-warning';\n warning.src = imgurl;\n createWarningMessage();\n (divgroups.find('.imggroup-' + identifier).before(warning));\n divgroups.find('.imggroup-' + identifier).on('click', createWarningMessage);\n divgroups.find('.warning' + identifier).on('click', createWarningMessage);\n }\n return false;\n };\n /**\n * Method that calls for an ajax script and replaces and/or changes the output components for a single group.\n * @param {*} event\n * @return {Boolean}\n */\n var changevisibility = function(event) {\n var divgroups = $('.block_groups');\n\n var groupid = $(this).data('groupid');\n if (divgroups.find('.spinner' + $(this).data('groupid')).length > 0 ||\n divgroups.find('.spinner-all').length > 0) {\n return false;\n }\n addSpinner($(this).data('groupid'));\n var promises = ajax.call([\n\n {\n methodname: 'block_groups_create_output', args: {\n groups: {\n id: $(this).data('groupid'),\n courseid: event.data.courseid\n }\n\n }\n }\n ]);\n $(document).ajaxError(function() {\n addWarning(groupid);\n return false;\n });\n\n promises[0].then(function(response) {\n if (response === null || response.error === true) {\n addWarning(groupid);\n return false;\n }\n divgroups.find('.group-' + response.id).replaceWith(response.newelement);\n // Replaces the used element, therefore removes the spinner.\n if (response.visibility === 0) {\n divgroups.find('.membergroup-' + response.id).removeClass('hiddengroups');\n }\n if (response.visibility === 1) {\n divgroups.find('.membergroup-' + response.id).addClass('hiddengroups');\n }\n divgroups.find('.group-' + response.id + ' .block_groups_toggle').on('click',\n {courseid: event.data.courseid}, changevisibility);\n removeSpinner(response.id);\n return false;\n }).fail(function() {\n addWarning(groupid);\n return false;\n });\n return false;\n };\n var checkMember = function(response) {\n var membergroup = $('.block-groups-membergroup');\n var visibility = response.visibility;\n if (visibility === 2) {\n membergroup.removeClass('hiddengroups');\n }\n if (visibility === 1) {\n membergroup.addClass('hiddengroups');\n }\n };\n /**\n * Initialises spinners for all groups.\n */\n var addSpinners = function() {\n var divgroups = $('.block_groups');\n if (divgroups.find('.warningall').length > 0) {\n removeWarning('all');\n }\n var imgurl = url.imageUrl(\"i/loading_small\", 'moodle');\n var spinner = document.createElement(\"img\");\n spinner.className = 'spinner-all spinner block-groups-spinner';\n spinner.src = imgurl;\n spinner.hidden = false;\n divgroups.find('.imggroup').before(spinner);\n divgroups.find('.imggroup').hide();\n };\n\n var addNotification = function(type, text) {\n notification.addNotification({\n message: text,\n type: type\n });\n };\n /**\n * Method that calls for an ajax script and replaces and/or changes the output components for all groups.\n * @param {Number} event\n * @return {Boolean}\n */\n var changeVisibilityAll = function(event) {\n if ($('.block_groups').find('.spinner').length > 0) {\n return false;\n }\n var warningexist = $('.block_groups').find('.block-groups-warning');\n if (typeof warningexist !== 'undefined' && warningexist.length > 0) {\n addWarning('all');\n return false;\n }\n addSpinners();\n // Calls for the externallib.\n var promises = ajax.call([\n {\n methodname: 'block_groups_create_allgroups_output', args: {\n groups: {\n action: $(this).data('action'),\n courseid: event.data.courseid\n }\n }\n }\n ]);\n $(document).ajaxError(function() {\n addWarning('all');\n return false;\n });\n // Response is processed.\n promises[0].then(function(response) {\n var divgroups = $('.block_groups');\n // Catch misleading responses.\n if (response === null || response.error === true) {\n addWarning('all');\n return false;\n }\n if (response.visibility === 0) {\n // Is nearly impossible since group has to be deleted during the request, however it is\n // possible, therefore a special message is thrown.\n divgroups.find('.content').replaceWith(response.newelement);\n str.get_strings([\n {key: 'nogroups', component: 'block_groups'}\n ]).done(function(s) {\n addNotification('error', s[0]);\n }).fail(notification.exception);\n return false;\n }\n\n // Old Elements are replaced and on click event added.\n divgroups.find('.wrapperlistgroup').replaceWith(response.newelement);\n divgroups.find('.block_groups_toggle').on('click', {courseid: event.data.courseid}, changevisibility);\n checkMember(response);\n // Outputvisibility 0->nogroups 1 -> hidden 2->visible 3-> all are hidden 4-> all are visible.\n str.get_strings([\n {key: 'groupschangedhidden', component: 'block_groups'},\n {key: 'groupschangedvisible', component: 'block_groups'},\n {key: 'allgroupsinstatehidden', component: 'block_groups'},\n {key: 'allgroupsinstatevisible', component: 'block_groups'}\n ]).done(function(s) {\n switch (response.visibility) {\n case 1:\n addNotification('success', s[0]);\n break;\n case 2:\n addNotification('success', s[1]);\n break;\n case 3:\n addNotification('warning', s[2]);\n break;\n case 4:\n addNotification('warning', s[3]);\n break;\n default:\n break;\n }\n }).fail(notification.exception);\n return false;\n }).fail(function() {\n addWarning('all');\n return false;\n });\n removeSpinners();\n return false;\n };\n\n /**\n * Method that calls for an ajax script and changes the visibility of all groups in one grouping.\n *\n * @param {*} event\n * @return {Boolean}\n */\n var changeVisibilityGrouping = function(event) {\n var divgroups = $('.block_groups');\n var groupingid = $(this).data('groupingid');\n var action = $(this).data('action');\n\n if (divgroups.find('.spinner').length > 0) {\n return false;\n }\n\n var warningexist = divgroups.find('.block-groups-warning');\n if (typeof warningexist !== 'undefined' && warningexist.length > 0) {\n addWarning(groupingid);\n return false;\n }\n\n addGroupingSpinners(groupingid);\n\n var promises = ajax.call([\n {\n methodname: \"block_groups_create_grouping_output\",\n args: {\n grouping: {\n groupingid: groupingid,\n courseid:event.data.courseid,\n action: action\n }\n }\n }\n ]);\n\n $(document).ajaxError(function() {\n addWarning(groupingid);\n return false;\n });\n\n promises[0].then(function(response) {\n if (response === null || response.error === true) {\n addWarning(groupingid);\n return false;\n }\n\n divgroups.find('.wrapperlistgroup').replaceWith(response.newelement);\n divgroups.find('.block_groups_toggle').on(\n 'click',\n {courseid: event.data.courseid}, changevisibility);\n divgroups.find('.block_groups_grouping_toggle').on(\n 'click',\n {courseid: event.data.courseid},\n changeVisibilityGrouping\n );\n checkGroupingMembers(response);\n\n str.get_strings([\n {key: 'groupingchangedhidden', component: 'block_groups'},\n {key: 'groupingchangedvisible', component: 'block_groups'},\n {key: 'groupinginstatehidden', component: 'block_groups'},\n {key: 'groupinginstatevisible', component: 'block_groups'},\n {key: 'nogroups', component: 'block_groups'}\n ]).done(function(s) {\n switch (response.visibility) {\n case 0:\n addNotification('warning', s[4]);\n break;\n case 1:\n addNotification('success', s[0]);\n break;\n case 2:\n addNotification('success', s[1]);\n break;\n case 3:\n addNotification('warning', s[2]);\n break;\n case 4:\n addNotification('warning', s[3]);\n break;\n default:\n break;\n }\n }).fail(notification.exception);\n\n removeGroupingSpinners(groupingid);\n return false;\n }).fail(function() {\n addWarning(groupingid);\n return false;\n });\n return false;\n };\n\n /**\n * Updates member group visibility only for groups changed by grouping action.\n *\n * @param {Object} response\n */\n var checkGroupingMembers = function(response) {\n response.changedgroups.forEach(function(group) {\n var membergroup = $('.membergroup-' + group.groupid);\n\n if (response.visibility === 2) {\n membergroup.removeClass('hiddengroups');\n }\n\n if (response.visibility === 1) {\n membergroup.addClass('hiddengroups');\n }\n });\n };\n\n /**\n * Calls for the main method. Either single groups are changed with block_groups_toggle or all groups with\n * block_groups_all_toggle.\n * @param {Number} courseid\n */\n return {\n initialise: function(courseid) {\n $('.block_groups_toggle').on('click', {courseid: courseid}, changevisibility);\n $('.block_groups_all_toggle').on('click', {courseid: courseid}, changeVisibilityAll);\n $('.block_groups_grouping_toggle').on('click', {courseid: courseid}, changeVisibilityGrouping);\n }\n };\n});\n"],"names":["define","$","ajax","url","notification","str","removeWarning","identifier","find","remove","removeSpinner","groupid","divgroup","show","removeSpinners","divgroups","reloadPage","location","reload","createWarningMessage","get_strings","component","done","s","confirm","fail","exception","addWarning","length","imgurl","imageUrl","warning","document","createElement","className","src","before","on","changevisibility","event","this","data","spinner","hidden","hide","addSpinner","promises","call","methodname","args","groups","id","courseid","ajaxError","then","response","error","replaceWith","newelement","visibility","removeClass","addClass","addNotification","type","text","message","changeVisibilityAll","warningexist","addSpinners","action","key","membergroup","checkMember","changeVisibilityGrouping","groupingid","each","addGroupingSpinners","grouping","checkGroupingMembers","removeGroupingSpinners","changedgroups","forEach","group","initialise"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/blocks_groups_visibility.js b/amd/src/blocks_groups_visibility.js index 420bc2e..42ee67b 100644 --- a/amd/src/blocks_groups_visibility.js +++ b/amd/src/blocks_groups_visibility.js @@ -90,6 +90,35 @@ define(['jquery', 'core/ajax', 'core/url', 'core/notification', 'core/str'], fun divgroups.find('.imggroup-' + groupid).before(spinner); divgroups.find('.imggroup-' + groupid).hide(); }; + /** + * Adds spinners for both visibility icons of one grouping. + * + * @param {Number} groupingid + */ + var addGroupingSpinners = function(groupingid) { + var divgroups = $('.block_groups'); + var imgurl = url.imageUrl("i/loading_small", 'moodle'); + + divgroups.find('.imggroup-grouping-' + groupingid).each(function() { + var spinner = document.createElement("img"); + spinner.className = 'spinner-grouping-' + groupingid + ' spinner block-groups-spinner'; + spinner.src = imgurl; + spinner.hidden = false; + $(this).before(spinner); + $(this).hide(); + }); + }; + /** + * Removes spinners for both visibility icons of one grouping. + * + * @param {Number} groupingid + */ + var removeGroupingSpinners = function(groupingid) { + var divgroups = $('.block_groups'); + + divgroups.find('.spinner-grouping-' + groupingid).remove(); + divgroups.find('.imggroup-grouping-' + groupingid).show(); + }; /** * Adds a warning(triangle with exclamation mark) in case the response is empty or the response throws an error. * @param {(Number|String)} identifier @@ -292,6 +321,120 @@ define(['jquery', 'core/ajax', 'core/url', 'core/notification', 'core/str'], fun return false; }; + /** + * Method that calls for an ajax script and changes the visibility of all groups in one grouping. + * + * @param {*} event + * @return {Boolean} + */ + var changeVisibilityGrouping = function(event) { + var divgroups = $('.block_groups'); + var groupingid = $(this).data('groupingid'); + var action = $(this).data('action'); + + if (divgroups.find('.spinner').length > 0) { + return false; + } + + var warningexist = divgroups.find('.block-groups-warning'); + if (typeof warningexist !== 'undefined' && warningexist.length > 0) { + addWarning(groupingid); + return false; + } + + addGroupingSpinners(groupingid); + + var promises = ajax.call([ + { + methodname: "block_groups_create_grouping_output", + args: { + grouping: { + groupingid: groupingid, + courseid:event.data.courseid, + action: action + } + } + } + ]); + + $(document).ajaxError(function() { + addWarning(groupingid); + return false; + }); + + promises[0].then(function(response) { + if (response === null || response.error === true) { + addWarning(groupingid); + return false; + } + + divgroups.find('.wrapperlistgroup').replaceWith(response.newelement); + divgroups.find('.block_groups_toggle').on( + 'click', + {courseid: event.data.courseid}, changevisibility); + divgroups.find('.block_groups_grouping_toggle').on( + 'click', + {courseid: event.data.courseid}, + changeVisibilityGrouping + ); + checkGroupingMembers(response); + + str.get_strings([ + {key: 'groupingchangedhidden', component: 'block_groups'}, + {key: 'groupingchangedvisible', component: 'block_groups'}, + {key: 'groupinginstatehidden', component: 'block_groups'}, + {key: 'groupinginstatevisible', component: 'block_groups'}, + {key: 'nogroups', component: 'block_groups'} + ]).done(function(s) { + switch (response.visibility) { + case 0: + addNotification('warning', s[4]); + break; + case 1: + addNotification('success', s[0]); + break; + case 2: + addNotification('success', s[1]); + break; + case 3: + addNotification('warning', s[2]); + break; + case 4: + addNotification('warning', s[3]); + break; + default: + break; + } + }).fail(notification.exception); + + removeGroupingSpinners(groupingid); + return false; + }).fail(function() { + addWarning(groupingid); + return false; + }); + return false; + }; + + /** + * Updates member group visibility only for groups changed by grouping action. + * + * @param {Object} response + */ + var checkGroupingMembers = function(response) { + response.changedgroups.forEach(function(group) { + var membergroup = $('.membergroup-' + group.groupid); + + if (response.visibility === 2) { + membergroup.removeClass('hiddengroups'); + } + + if (response.visibility === 1) { + membergroup.addClass('hiddengroups'); + } + }); + }; + /** * Calls for the main method. Either single groups are changed with block_groups_toggle or all groups with * block_groups_all_toggle. @@ -301,7 +444,7 @@ define(['jquery', 'core/ajax', 'core/url', 'core/notification', 'core/str'], fun initialise: function(courseid) { $('.block_groups_toggle').on('click', {courseid: courseid}, changevisibility); $('.block_groups_all_toggle').on('click', {courseid: courseid}, changeVisibilityAll); - + $('.block_groups_grouping_toggle').on('click', {courseid: courseid}, changeVisibilityGrouping); } }; }); diff --git a/block_groups.php b/block_groups.php index e59289f..f09b046 100644 --- a/block_groups.php +++ b/block_groups.php @@ -181,8 +181,13 @@ public function build_grouping_array($allgroupings, $courseid) { foreach ($allgroupings as $g => $value) { if (is_object($value) && property_exists($value, 'name')) { // Necessary DB query to prohibit multiple ids of grouping members. - $countgroupingmember = $arrayofmembers[$value->id]->number; - $groupingsarray[$g] = $renderer->get_grouping($value->name, $countgroupingmember); + $countgroupingmember = 0; + + if (isset($arrayofmembers[$value->id])) { + $countgroupingmember = $arrayofmembers[$value->id]->number; + } + + $groupingsarray[$g] = $renderer->get_grouping($value, $countgroupingmember); } } return $groupingsarray; diff --git a/classes/external/create_grouping_output.php b/classes/external/create_grouping_output.php new file mode 100644 index 0000000..79714ea --- /dev/null +++ b/classes/external/create_grouping_output.php @@ -0,0 +1,229 @@ +. + +namespace block_groups\external; + +use context_course; +use core_external\external_api; +use core_external\external_function_parameters; +use core_external\external_multiple_structure; +use core_external\external_single_structure; +use core_external\external_value; +use html_writer; +use moodle_url; + +/** + * create_grouping_output external function + * + * @package block_groups + * @copyright 2026 Lena Herfeldt + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class create_grouping_output extends external_api { + /** + * Specifies the input parameters. + * @return external_function_parameters + */ + public static function execute_parameters() { + return new external_function_parameters( + [ + 'grouping' => new external_single_structure( + [ + 'groupingid' => new external_value(PARAM_INT, 'id of grouping'), + 'courseid' => new external_value(PARAM_INT, 'id of course'), + 'action' => new external_value(PARAM_ALPHA, 'show or hide'), + ] + ), + ] + ); + } + + /** + * Specifies the output parameters. + * @return external_single_structure + */ + public static function execute_returns() { + return new external_single_structure( + [ + 'courseid' => new external_value(PARAM_INT, 'id of course'), + 'groupingid' => new external_value(PARAM_INT, 'id of grouping'), + 'newelement' => new external_value(PARAM_RAW, 'replace html-element'), + 'visibility' => new external_value(PARAM_INT, 'returns the visibility value'), + 'changedgroups' => new external_multiple_structure( + new external_single_structure( + [ + 'groupid' => new external_value(PARAM_INT, 'group-id'), + ] + ) + ), + ] + ); + } + + /** + * Changed the Database and returns the updated html content. + * create_grouping_output + * @param array $grouping + * @return array + */ + public static function execute($grouping) { + global $CFG, $PAGE, $DB; + $params = self::validate_parameters(self::execute_parameters(), ['grouping' => $grouping]); + $courseid = $params['grouping']['courseid']; + $groupingid = $params['grouping']['groupingid']; + $action = $params['grouping']['action']; + $context = context_course::instance($courseid); + + $PAGE->set_context($context); + self::validate_context($context); + require_capability('moodle/course:managegroups', $context); + + require_once($CFG->dirroot . '/blocks/groups/locallib.php'); + require_once($CFG->dirroot . '/group/lib.php'); + + $groupingexists = $DB->get_record('groupings', [ + 'id' => $groupingid, + 'courseid' => $courseid, + ]); + + if (!$groupingexists) { + throw new \invalid_parameter_exception('Grouping does not exist or does not belong to course'); + } + + $groupids = self::get_group_ids_for_grouping($groupingid, $courseid); + + if (empty($groupids)) { + return [ + 'courseid' => $courseid, + 'groupingid' => $groupingid, + 'newelement' => self::generate_groups_html($courseid), + 'visibility' => 0, + 'changedgroups' => [], + ]; + } + + $changedgroups = self::update_group_visibility($groupids, $courseid, $action); + $statuscode = self::get_status_code($action, $changedgroups); + + return [ + 'courseid' => $courseid, + 'groupingid' => $groupingid, + 'newelement' => self::generate_groups_html($courseid), + 'visibility' => $statuscode, + 'changedgroups' => $changedgroups, + ]; + } + + /** + * Returns all group ids belonging to a grouping. + * + * @param int $groupingid + * @param int $courseid + * @return array + */ + private static function get_group_ids_for_grouping($groupingid, $courseid) { + global $DB; + + $sql = "SELECT g.id + FROM {groups} g + JOIN {groupings_groups} gg ON gg.groupid = g.id + WHERE gg.groupingid = :groupingid AND g.courseid = :courseid + ORDER BY g.id ASC"; + + $records = $DB->get_records_sql($sql, [ + 'groupingid' => $groupingid, + 'courseid' => $courseid, + ]); + + return array_keys($records); + } + + /** + * Changes the visibility of the groups in the database. + * @param array $groupids + * @param int $courseid + * @param string $action + * @return array + */ + private static function update_group_visibility($groupids, $courseid, $action) { + global $DB; + + $changedgroups = []; + $targetvisible = ($action === 'show'); + + foreach ($groupids as $groupid) { + $currentlyvisible = $DB->record_exists('block_groups_hide', ['id' => $groupid]); + + if ($targetvisible === $currentlyvisible) { + continue; + } + + block_groups_set_visibility($groupid, $courseid, $targetvisible); + $changedgroups[] = ['groupid' => $groupid]; + } + return $changedgroups; + } + + /** + * Generates the complete updated group list html. + * + * @param int $courseid + * @return string + */ + private static function generate_groups_html($courseid) { + global $PAGE, $DB; + + $renderer = $PAGE->get_renderer('block_groups'); + $groups = $DB->get_records('groups', ['courseid' => $courseid], 'id ASC'); + $groupsarray = []; + + foreach ($groups as $group) { + $fullgroup = groups_get_group($group->id); + $href = new moodle_url( + '/blocks/groups/changevisibility.php', + [ + 'courseid' => $courseid, + 'groupid' => $group->id, + ] + ); + $countmembers = count(groups_get_members($group->id)); + $groupvisible = $DB->record_exists('block_groups_hide', ['id' => $group->id]); + $hiddenforrenderer = !$groupvisible; + $groupsarray[] = $renderer->get_string_group( + $fullgroup, + $href, + $countmembers, + $hiddenforrenderer, + ); + } + return html_writer::alist($groupsarray, ['class' => 'wrapperlistgroup']); + } + + /** + * Returns status code depending on action and whether anything changed. + * + * @param string $action + * @param array $changedgroups + * @return int + */ + private static function get_status_code($action, $changedgroups) { + if (empty($changedgroups)) { + return ($action === 'show') ? 4 : 3; + } + + return ($action === 'hide') ? 1 : 2; + } +} diff --git a/classes/output/renderer.php b/classes/output/renderer.php index de2a007..11563d2 100644 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -92,12 +92,20 @@ public function get_string_group($value, $href, $countmembers, $visibility) { } /** * Generates string for a grouping list item - * @param string $name + * @param stdClass $grouping * @param integer $counter * @return string html-string */ - public function get_grouping($name, $counter) { - return $name . ' ' . get_string('brackets', 'block_groups', $counter); + public function get_grouping($grouping, $counter) { + $line = html_writer::span( + $grouping->name . ' ' . get_string('brackets', 'block_groups', $counter), + 'wrapperblockgroupsgrouping' + ); + + $showlink = $this->create_grouping_link('show', $grouping->id, false); + $hidelink = $this->create_grouping_link('hide', $grouping->id, false); + + return html_writer::span($line . $showlink . $hidelink, 'grouping-' . $grouping->id); } /** * Renders line to change all groups. @@ -166,4 +174,46 @@ private function create_all_groups_link($action, $reverseimage = true) { $rightaligndiv = html_writer::div($icon, 'rightalign'); return html_writer::link($urlhide, $rightaligndiv, ['data-action' => $reverse, 'class' => 'block_groups_all_toggle']); } + + /** + * Creates a link to change visibility of all groups in one grouping. + * + * @param string $action show/hide + * @param int $groupingid grouping id + * @param bool $reverseimage whether to reverse the icon. + * @return string html-link + */ + private function create_grouping_link($action, $groupingid, $reverseimage = true) { + global $CFG, $COURSE; + if ($action === 'hide') { + $actionnumber = 0; + $reverse = 'show'; + } else { + $actionnumber = 1; + $reverse = 'hide'; + } + + $url = new moodle_url( + $CFG->wwwroot . '/blocks/groups/changegrouping.php', + ['courseid' => $COURSE->id, 'groupingid' => $groupingid, 'hide' => $actionnumber] + ); + + $icon = $this->output->pix_icon( + 't/' . ($reverseimage ? $reverse : $action), + get_string($reverse . 'grouping', 'block_groups'), + 'moodle', + ['class' => 'imggroup-grouping-' . $groupingid . ' imggroup'] + ); + $rightaligndiv = html_writer::div($icon, 'rightalign'); + + return html_writer::link( + $url, + $rightaligndiv, + [ + 'data-groupingid' => $groupingid, + 'data-action' => $reverse, + 'class' => 'block_groups_grouping_toggle', + ] + ); + } } diff --git a/db/services.php b/db/services.php index 81e87e1..cd9603b 100644 --- a/db/services.php +++ b/db/services.php @@ -38,4 +38,11 @@ 'capabilities' => 'moodle/course:managegroups', 'ajax' => true, ], + 'block_groups_create_grouping_output' => [ + 'classname' => 'block_groups\external\create_grouping_output', + 'description' => 'Service to allow changing the visibility of groupings', + 'type' => 'write', + 'capabilities' => 'moodle/course:managegroups', + 'ajax' => true, + ], ]; diff --git a/lang/en/block_groups.php b/lang/en/block_groups.php index 3f50174..8339522 100644 --- a/lang/en/block_groups.php +++ b/lang/en/block_groups.php @@ -31,11 +31,16 @@ $string['errortitle'] = 'Synchronization error'; $string['group'] = 'Groups '; $string['grouping'] = 'Groupings '; +$string['groupingchangedhidden'] = 'All groups in this grouping are hidden.'; +$string['groupingchangedvisible'] = 'All groups in this grouping are visible.'; +$string['groupinginstatehidden'] = 'The grouping is already hidden.'; +$string['groupinginstatevisible'] = 'The grouping is already visible.'; $string['groups:addinstance'] = 'Add a new Group block'; $string['groups:myaddinstance'] = 'Add a new Group block to Dashboard'; $string['groupschangedhidden'] = 'All groups are hidden.'; $string['groupschangedvisible'] = 'All groups are visible.'; $string['hidegroup'] = 'hide group'; +$string['hidegrouping'] = 'hide grouping'; $string['introduction'] = 'You are enrolled in the following groups'; $string['modify'] = 'modify groups'; $string['nochangeindatabasepossible'] = 'The required change was not possible. Please reload the page.'; @@ -46,4 +51,5 @@ $string['pluginname2'] = 'Groups'; $string['privacy:metadata'] = 'The Group block only displays information about groups, but does not effect or store any personal data. The existing groups and groupings data are stored in other locations.'; $string['showgroup'] = 'show group'; +$string['showgrouping'] = 'show grouping'; $string['showgroupsdefaultsetting'] = 'Show groups and groupings by default'; diff --git a/locallib.php b/locallib.php index 63dee37..57c9eb4 100644 --- a/locallib.php +++ b/locallib.php @@ -60,3 +60,41 @@ function count_grouping_members($courseid) { GROUP BY g.id, gg.groupingid ORDER BY gg.groupingid DESC'); } + +/** + * Sets the visibility of a group. + * @param int $groupid + * @param int $courseid + * @param bool $visible if target visibility is visible or not + * @return bool true if something changed, false otherwise + */ +function block_groups_set_visibility($groupid, $courseid, $visible) { + global $DB; + + $transaction = $DB->start_delegated_transaction(); + $groupsuitable = $DB->get_record('groups', ['id' => $groupid, 'courseid' => $courseid]); + + if (empty($groupsuitable)) { + $transaction->allow_commit(); + return false; + } + + $currentlyvisible = $DB->record_exists('block_groups_hide', ['id' => $groupid]); + + // The group is currently not visible and should be visible now. + if ($visible && !$currentlyvisible) { + $DB->insert_record_raw('block_groups_hide', ['id' => $groupid], true, false, true); + $transaction->allow_commit(); + return true; + } + + // The group is currently visible and should be not visible now. + if (!$visible && $currentlyvisible) { + $DB->delete_records('block_groups_hide', ['id' => $groupid]); + $transaction->allow_commit(); + return true; + } + + $transaction->allow_commit(); + return false; +} diff --git a/tests/behat/behat_block_groups.php b/tests/behat/behat_block_groups.php index 754c19c..c40ace0 100644 --- a/tests/behat/behat_block_groups.php +++ b/tests/behat/behat_block_groups.php @@ -78,7 +78,7 @@ public function i_click_on_the_eye_icon_of_group_name_without_javascript_enabled * * @When /^I click in the groups block on all groups "(?P(?:[^"]|\\")*)"$/ * - * @param string $action identifier of the Group + * @param string $action identifier of the action show/hide */ public function i_click_in_the_groups_block_on_all_groups($action) { if ($action == 'hide') { @@ -96,6 +96,37 @@ public function i_click_in_the_groups_block_on_all_groups($action) { $eyeicon->click(); } + /** + * Clicks on all groups + * + * @When /^I click in the groups block on the grouping "(?P(?:[^"]|\\")*)" "(?P(?:[^"]|\\")*)"$/ + * + * @param string $groupingname identifier of the grouping + * @param string $action identifier of the action show/hide + */ + public function i_click_in_the_groups_block_on_the_grouping($groupingname, $action) { + $checkbox = $this->find('css', '#checkboxgrouping'); + if (!$checkbox->isChecked()) { + $label = $this->find('css', 'label[for="checkboxgrouping"]'); + $label->click(); + } + + if ($action == 'hide') { + $eyeicon = $this->find( + 'xpath', + "//span[contains(@class, 'grouping-')][contains(., " . behat_context_helper::escape($groupingname) . ")]//a[1]" + ); + } else if ($action == 'show') { + $eyeicon = $this->find( + 'xpath', + "//span[contains(@class, 'grouping-')][contains(., " . behat_context_helper::escape($groupingname) . ")]//a[2]" + ); + } else { + throw new \Exception('Unknwon action: ' . $action); + } + $eyeicon->click(); + } + /** * Sets the group default visibility setting to a specific value (0 or 1). * This step allows tests to configure whether groups are visible or hidden by default. diff --git a/tests/behat/change_grouping.feature b/tests/behat/change_grouping.feature new file mode 100644 index 0000000..e5572bd --- /dev/null +++ b/tests/behat/change_grouping.feature @@ -0,0 +1,126 @@ +@block @block_groups @groups_change_grouping +Feature: Feature: Change group visibility by grouping in the groups block + In order to change the visibility of groups in a grouping with one click + As a course administrator + I need to change the visibility of all groups in a grouping + + Background: + Given the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "users" exist: + | username | firstname | lastname | email | idnumber | + | teacher1 | Teacher | 1 | teacher1@example.com | T1 | + | student1 | Student | 1 | student1@example.com | S1 | + | student2 | Student | 2 | student2@example.com | S2 | + | student3 | Student | 3 | student3@example.com | S3 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + | student1 | C1 | student | + | student2 | C1 | student | + | student3 | C1 | student | + And the following "groups" exist: + | name | course | idnumber | + | Group 1 | C1 | G1 | + | Group 2 | C1 | G2 | + | Group 3 | C1 | G3 | + | Group 4 | C1 | G4 | + And the following "groupings" exist: + | name | course | idnumber | + | Grouping 1 | C1 | GG1 | + | Grouping 2 | C1 | GG2 | + And the following "group members" exist: + | user | group | + | student1 | G1 | + | student2 | G1 | + | student2 | G2 | + | student3 | G3 | + | student3 | G4 | + And the following "grouping groups" exist: + | grouping | group | + | GG1 | G1 | + | GG1 | G2 | + | GG2 | G2 | + | GG2 | G4 | + And I log in as "teacher1" + And I am on "Course 1" course homepage with editing mode on + And I add the "Groups and Groupings" block + And I log out + + @javascript + Scenario: Showing a grouping shows all groups in that grouping + Given I log in as "teacher1" + And I am on "Course 1" course homepage + When I click in the groups block on the grouping "Grouping 1" "show" + Then I wait until the page is ready + Then "Groups and Groupings" "block" should exist + And I should see "All groups in this grouping are visible." in the "region-main" "region" + And I log out + + When I log in as "student1" + And I am on "Course 1" course homepage + Then I should see "Group 1" in the "Groups" "block" + And I log out + + When I log in as "student2" + And I am on "Course 1" course homepage + Then I should see "Group 1" in the "Groups" "block" + And I should see "Group 2" in the "Groups" "block" + And I log out + + When I log in as "student3" + And I am on "Course 1" course homepage + Then "Groups" "block" should not exist + And I log out + + @javascript + Scenario: Showing overlapping groupings shows shared and grouping-specific groups + Given I log in as "teacher1" + And I am on "Course 1" course homepage + When I click in the groups block on the grouping "Grouping 1" "show" + And I click in the groups block on the grouping "Grouping 2" "show" + Then I wait until the page is ready + Then "Groups and Groupings" "block" should exist + And I should see "All groups in this grouping are visible." in the "region-main" "region" + And I log out + + When I log in as "student1" + And I am on "Course 1" course homepage + Then I should see "Group 1" in the "Groups" "block" + And I log out + + When I log in as "student2" + And I am on "Course 1" course homepage + Then I should see "Group 1" in the "Groups" "block" + And I should see "Group 2" in the "Groups" "block" + And I log out + + When I log in as "student3" + And I am on "Course 1" course homepage + Then I should see "Group 4" in the "Groups" "block" + And I should not see "Group 3" in the "Groups" "block" + And I log out + + @javascript + Scenario: Hiding a grouping hides all groups in that grouping + Given I log in as "teacher1" + And I am on "Course 1" course homepage + When I click in the groups block on the grouping "Grouping 1" "show" + And I click in the groups block on the grouping "Grouping 2" "show" + And I click in the groups block on the grouping "Grouping 1" "hide" + Then I wait until the page is ready + Then "Groups and Groupings" "block" should exist + And I should see "All groups in this grouping are hidden." in the "region-main" "region" + And I log out + + When I log in as "student2" + And I am on "Course 1" course homepage + Then "Groups" "block" should not exist + And I log out + + When I log in as "student3" + And I am on "Course 1" course homepage + Then I should see "Group 4" in the "Groups" "block" + And I should not see "Group 3" in the "Groups" "block" + And I log out diff --git a/tests/block_groups_test.php b/tests/block_groups_test.php index 5392747..5ba31f1 100644 --- a/tests/block_groups_test.php +++ b/tests/block_groups_test.php @@ -73,6 +73,36 @@ public function test_locallib(): void { // Test empty grouping. $this->assertEquals(0, $functioncount[$data['grouping3']->id]->number); } + /** + * Function to test setting the grouping visibility. + * @covers \block_groups_set_visibility + */ + public function test_block_groups_set_visibility(): void { + global $DB, $CFG; + require_once($CFG->dirroot . '/blocks/groups/locallib.php'); + $data = $this->set_up(); + $groupid = $data['group1']->id; + $courseid = $data['course2']->id; + + // At first, the groups are all hidden. + $this->assertFalse($DB->record_exists('block_groups_hide', ['id' => $groupid])); + + // Setting the group to visible should add a record to the database and report a change. + $this->assertTrue(block_groups_set_visibility($groupid, $courseid, true)); + $this->assertTrue($DB->record_exists('block_groups_hide', ['id' => $groupid])); + + // Setting the group to visible again should not change anything. + $this->assertFalse(block_groups_set_visibility($groupid, $courseid, true)); + $this->assertTrue($DB->record_exists('block_groups_hide', ['id' => $groupid])); + + // Setting the group to hidden should remove the record from the database and report a change. + $this->assertTrue(block_groups_set_visibility($groupid, $courseid, false)); + $this->assertFalse($DB->record_exists('block_groups_hide', ['id' => $groupid])); + + // Setting the group to hidden again should not change anything. + $this->assertFalse(block_groups_set_visibility($groupid, $courseid, false)); + $this->assertFalse($DB->record_exists('block_groups_hide', ['id' => $groupid])); + } /** * Methodes recommended by moodle to assure database and dataroot is reset. * @coversNothing diff --git a/version.php b/version.php index 70d5e4a..4e467a7 100644 --- a/version.php +++ b/version.php @@ -24,8 +24,8 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2026052001; // The current plugin version (Date: YYYYMMDDXX). -$plugin->requires = 2022112800; // Requires 4.1+ Moodle version. +$plugin->version = 2026061700; // The current plugin version (Date: YYYYMMDDXX). +$plugin->requires = 2024100712; // Requires 4.5+ Moodle version. $plugin->component = 'block_groups'; // Full name of the plugin (used for diagnostics). -$plugin->release = 'v5.0-r1'; +$plugin->release = 'v5.2-r1'; $plugin->maturity = MATURITY_STABLE;