From 01f13bee19fd679d58d04955246a4e9908913bb3 Mon Sep 17 00:00:00 2001 From: raortegar Date: Sat, 9 Nov 2024 21:34:47 +0100 Subject: [PATCH] MDL-73909 core_message: Admin notification preferences saved on toggle --- admin/message.php | 70 +------ lang/en/message.php | 4 + lib/db/services.php | 6 + .../default_notification_preferences.min.js | 5 +- ...efault_notification_preferences.min.js.map | 2 +- .../src/default_notification_preferences.js | 42 ++++ .../message_set_default_notification.php | 192 ++++++++++++++++++ message/renderer.php | 8 +- version.php | 2 +- 9 files changed, 253 insertions(+), 78 deletions(-) create mode 100644 message/classes/external/message_set_default_notification.php diff --git a/admin/message.php b/admin/message.php index 1178a574f45..530e9398fb6 100644 --- a/admin/message.php +++ b/admin/message.php @@ -43,61 +43,6 @@ $providers = get_message_providers(); $preferences = get_message_output_default_preferences(); if (($form = data_submitted()) && confirm_sesskey()) { - $newpreferences = array(); - // Prepare default message outputs settings. - foreach ($providers as $provider) { - $componentproviderbase = $provider->component.'_'.$provider->name; - $disableprovidersetting = $componentproviderbase.'_disable'; - if (!isset($form->$disableprovidersetting)) { - $newpreferences[$disableprovidersetting] = 1; - } else { - $newpreferences[$disableprovidersetting] = 0; - } - - $componentprovidersetting = $componentproviderbase.'_locked'; - foreach ($processors as $processor) { - $value = 0; - if (isset($form->{$componentprovidersetting}[$processor->name])) { - $value = $form->{$componentprovidersetting}[$processor->name]; - if ($value == 'on') { - $value = 1; - } - } - - // Record the site preference. - $newpreferences[$processor->name.'_provider_'.$componentprovidersetting] = $value; - } - - $componentprovidersetting = $componentproviderbase.'_enabled'; - $newsettings = []; - if (isset($form->$componentprovidersetting)) { - // Store defined comma-separated processors as setting value. - // Using array_filter eliminates elements set to 0 above. - $newsettings = array_keys(array_filter($form->{$componentprovidersetting})); - } - - // Let's join existing setting values for disabled processors. - $property = 'message_provider_'.$componentprovidersetting; - if (property_exists($preferences, $property)) { - $existingsetting = $preferences->$property; - foreach ($disabledprocessors as $disable) { - if (strpos($existingsetting, $disable->name) > -1) { - $newsettings[] = $disable->name; - } - } - } - - $value = join(',', $newsettings); - if (empty($value)) { - $value = null; - } - - // Record the site preference. - $newpreferences['message_provider_'.$componentprovidersetting] = $value; - } - - // Update database. - $transaction = $DB->start_delegated_transaction(); // Save processors enabled/disabled status. foreach ($allprocessors as $processor) { @@ -106,24 +51,11 @@ if (($form = data_submitted()) && confirm_sesskey()) { $class::enable_plugin($processor->name, $enabled); } - foreach ($newpreferences as $name => $value) { - $old = isset($preferences->$name) ? $preferences->$name : ''; - - if ($old != $value) { - add_to_config_log($name, $old, $value, 'core'); - } - - set_config($name, $value, 'message'); - } - $transaction->allow_commit(); - - core_plugin_manager::reset_caches(); - $url = new moodle_url('message.php'); redirect($url); } -// Page settings +// Page settings. $PAGE->set_context(context_system::instance()); $renderer = $PAGE->get_renderer('core', 'message'); diff --git a/lang/en/message.php b/lang/en/message.php index 7f178f66493..f62b9ece055 100644 --- a/lang/en/message.php +++ b/lang/en/message.php @@ -245,6 +245,10 @@ $string['showmessagewindownonew'] = 'Show message window with no new messages'; $string['showmessagewindowwithcount'] = 'Show message window with {$a} new messages'; $string['shownotificationwindownonew'] = 'Show notification window with no new notifications'; $string['shownotificationwindowwithcount'] = 'Show notification window with {$a} new notifications'; +$string['successproviderenabled'] = '\'{$a->provider}\' for \'{$a->processor}\' updated.'; +$string['successproviderlocked'] = '\'{$a->provider}\' for \'{$a->processor}\' locked.'; +$string['successproviderunlocked'] = '\'{$a->provider}\' for \'{$a->processor}\' unlocked.'; +$string['successproviderupdate'] = '\'{$a}\' updated.'; $string['togglenotificationmenu'] = 'Toggle notifications menu'; $string['togglemessagemenu'] = 'Toggle messaging drawer'; $string['totalconversations'] = '{$a} total conversations'; diff --git a/lib/db/services.php b/lib/db/services.php index 33133f07619..f6f649a8405 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1634,6 +1634,12 @@ $functions = array( 'type' => 'read', 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], ], + 'core_message_set_default_notification' => [ + 'classname' => 'core_message\external\message_set_default_notification', + 'description' => 'Set the default notification preferences toggle', + 'type' => 'write', + 'ajax' => true, + ], 'core_my_view_page' => [ 'classname' => '\core_my\external\view_page', 'methodname' => 'execute', diff --git a/message/amd/build/default_notification_preferences.min.js b/message/amd/build/default_notification_preferences.min.js index 93f996c61f7..a1bcd6858a8 100644 --- a/message/amd/build/default_notification_preferences.min.js +++ b/message/amd/build/default_notification_preferences.min.js @@ -1,4 +1,4 @@ -define("core_message/default_notification_preferences",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0; +define("core_message/default_notification_preferences",["exports","core/ajax","core/notification"],(function(_exports,Ajax,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Ajax=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj} /** * Controls the default settings for the list of notification types on the * notifications admin page @@ -8,7 +8,6 @@ define("core_message/default_notification_preferences",["exports"],(function(_ex * @copyright 2021 Moodle * @author Pau Ferrer Ocaña * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -const selectors_provider=".defaultmessageoutputs .provider_enabled",selectors_lockSetting=".locked_message_setting",selectors_allSettings=".locked_message_setting, .enabled_message_setting";var _default={init:()=>{(()=>{const toggleLockSetting=lockedElement=>{const isEnabled=lockedElement.checked||!1,enabledId=lockedElement.id.replace("_locked[","_enabled[");document.getElementById(enabledId).closest("div.custom-control").classList.toggle("dimmed_text",isEnabled)},toggleEnableProviderSettings=providerEnabledElement=>{const isEnabled=providerEnabledElement.checked||!1;providerEnabledElement.closest("tr").querySelectorAll(selectors_allSettings).forEach((element=>{element.toggleAttribute("disabled",!isEnabled)}))},container=document.querySelector(".preferences-container");container.querySelectorAll(selectors_provider).forEach((providerEnabledElement=>{providerEnabledElement.checked||toggleEnableProviderSettings(providerEnabledElement),providerEnabledElement.addEventListener("change",(e=>{toggleEnableProviderSettings(e.target)}))})),container.querySelectorAll(selectors_lockSetting).forEach((lockedElement=>{lockedElement.checked&&toggleLockSetting(lockedElement),lockedElement.addEventListener("change",(e=>{toggleLockSetting(e.target)}))}))})()}};return _exports.default=_default,_exports.default})); + */(Ajax),_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};const selectors_provider=".defaultmessageoutputs .provider_enabled",selectors_lockSetting=".locked_message_setting",selectors_enabledSetting=".enabled_message_setting",selectors_allSettings=".locked_message_setting, .enabled_message_setting";var _default={init:()=>{(()=>{const toggleLockSetting=lockedElement=>{const isEnabled=lockedElement.checked||!1,enabledId=lockedElement.id.replace("_locked[","_enabled[");document.getElementById(enabledId).closest("div.custom-control").classList.toggle("dimmed_text",isEnabled)},toggleEnableProviderSettings=providerEnabledElement=>{const isEnabled=providerEnabledElement.checked||!1;providerEnabledElement.closest("tr").querySelectorAll(selectors_allSettings).forEach((element=>{element.toggleAttribute("disabled",!isEnabled)}))},setDefaultNotification=(isEnabled,preference)=>{Ajax.call([{methodname:"core_message_set_default_notification",args:{preference:preference,state:isEnabled?1:0}}])[0].done((data=>{_notification.default.addNotification({message:data.successmessage,type:"success"})})).fail(_notification.default.exception)},container=document.querySelector(".preferences-container");container.querySelectorAll(selectors_provider).forEach((providerEnabledElement=>{providerEnabledElement.checked||toggleEnableProviderSettings(providerEnabledElement),providerEnabledElement.addEventListener("change",(e=>{toggleEnableProviderSettings(e.target),setDefaultNotification(e.target.checked,providerEnabledElement.parentElement.parentElement.dataset.preference)}))})),container.querySelectorAll(selectors_lockSetting).forEach((lockedElement=>{lockedElement.checked&&toggleLockSetting(lockedElement),lockedElement.addEventListener("change",(e=>{toggleLockSetting(e.target),setDefaultNotification(e.target.checked,lockedElement.parentElement.parentElement.dataset.preference)}))})),container.querySelectorAll(selectors_enabledSetting).forEach((enabledElement=>{enabledElement.addEventListener("change",(e=>{setDefaultNotification(e.target.checked,enabledElement.parentElement.parentElement.dataset.preference)}))}))})()}};return _exports.default=_default,_exports.default})); //# sourceMappingURL=default_notification_preferences.min.js.map \ No newline at end of file diff --git a/message/amd/build/default_notification_preferences.min.js.map b/message/amd/build/default_notification_preferences.min.js.map index b507cb30c3d..d4d59534049 100644 --- a/message/amd/build/default_notification_preferences.min.js.map +++ b/message/amd/build/default_notification_preferences.min.js.map @@ -1 +1 @@ -{"version":3,"file":"default_notification_preferences.min.js","sources":["../src/default_notification_preferences.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 .\n\n/**\n * Controls the default settings for the list of notification types on the\n * notifications admin page\n *\n * @module core_message/default_notification_preferences\n * @class default_notification_preferences\n * @copyright 2021 Moodle\n * @author Pau Ferrer Ocaña \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst selectors = {\n provider: '.defaultmessageoutputs .provider_enabled',\n lockSetting: '.locked_message_setting',\n enabledSetting: '.enabled_message_setting',\n allSettings: '.locked_message_setting, .enabled_message_setting'\n};\n\n/**\n * Register event listeners for the default_notification_preferences page.\n */\nconst registerEventListeners = () => {\n\n /**\n * Update the dimmed status of the \"enabled\" toggle on the notification setting.\n *\n * @param {HTMLElement} lockedElement Element that receives the event.\n */\n const toggleLockSetting = (lockedElement) => {\n const isEnabled = lockedElement.checked || false;\n const enabledId = lockedElement.id.replace('_locked[', '_enabled[');\n\n const enabledElement = document.getElementById(enabledId).closest('div.custom-control');\n enabledElement.classList.toggle('dimmed_text', isEnabled);\n };\n\n /**\n * Enable/Disable all settings of the provider.\n *\n * @param {HTMLElement} providerEnabledElement Element that receives the event.\n */\n const toggleEnableProviderSettings = (providerEnabledElement) => {\n const isEnabled = providerEnabledElement.checked || false;\n const parentRow = providerEnabledElement.closest('tr');\n\n const elements = parentRow.querySelectorAll(selectors.allSettings);\n elements.forEach((element) => {\n element.toggleAttribute('disabled', !isEnabled);\n });\n };\n\n const container = document.querySelector('.preferences-container');\n\n container.querySelectorAll(selectors.provider).forEach((providerEnabledElement) => {\n // Set the initial statuses.\n if (!providerEnabledElement.checked) {\n toggleEnableProviderSettings(providerEnabledElement);\n }\n\n providerEnabledElement.addEventListener('change', (e) => {\n toggleEnableProviderSettings(e.target);\n });\n });\n\n container.querySelectorAll(selectors.lockSetting).forEach((lockedElement) => {\n // Set the initial statuses.\n if (lockedElement.checked) {\n toggleLockSetting(lockedElement);\n }\n\n lockedElement.addEventListener('change', (e) => {\n toggleLockSetting(e.target);\n });\n });\n};\n\n/**\n * Initialize the page.\n */\nconst init = () => {\n registerEventListeners();\n};\n\nexport default {\n init: init,\n};\n"],"names":["selectors","init","toggleLockSetting","lockedElement","isEnabled","checked","enabledId","id","replace","document","getElementById","closest","classList","toggle","toggleEnableProviderSettings","providerEnabledElement","querySelectorAll","forEach","element","toggleAttribute","container","querySelector","addEventListener","e","target","registerEventListeners"],"mappings":";;;;;;;;;;;MA0BMA,mBACQ,2CADRA,sBAEW,0BAFXA,sBAIW,iEAoEF,CACXC,KALS,KA1DkB,YAOrBC,kBAAqBC,sBACjBC,UAAYD,cAAcE,UAAW,EACrCC,UAAYH,cAAcI,GAAGC,QAAQ,WAAY,aAEhCC,SAASC,eAAeJ,WAAWK,QAAQ,sBACnDC,UAAUC,OAAO,cAAeT,YAQ7CU,6BAAgCC,+BAC5BX,UAAYW,uBAAuBV,UAAW,EAClCU,uBAAuBJ,QAAQ,MAEtBK,iBAAiBhB,uBACnCiB,SAASC,UACdA,QAAQC,gBAAgB,YAAaf,eAIvCgB,UAAYX,SAASY,cAAc,0BAEzCD,UAAUJ,iBAAiBhB,oBAAoBiB,SAASF,yBAE/CA,uBAAuBV,SACxBS,6BAA6BC,wBAGjCA,uBAAuBO,iBAAiB,UAAWC,IAC/CT,6BAA6BS,EAAEC,cAIvCJ,UAAUJ,iBAAiBhB,uBAAuBiB,SAASd,gBAEnDA,cAAcE,SACdH,kBAAkBC,eAGtBA,cAAcmB,iBAAiB,UAAWC,IACtCrB,kBAAkBqB,EAAEC,eAS5BC"} \ No newline at end of file +{"version":3,"file":"default_notification_preferences.min.js","sources":["../src/default_notification_preferences.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 .\n\n/**\n * Controls the default settings for the list of notification types on the\n * notifications admin page\n *\n * @module core_message/default_notification_preferences\n * @class default_notification_preferences\n * @copyright 2021 Moodle\n * @author Pau Ferrer Ocaña \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport * as Ajax from 'core/ajax';\nimport Notification from 'core/notification';\n\nconst selectors = {\n provider: '.defaultmessageoutputs .provider_enabled',\n lockSetting: '.locked_message_setting',\n enabledSetting: '.enabled_message_setting',\n allSettings: '.locked_message_setting, .enabled_message_setting'\n};\n\n/**\n * Register event listeners for the default_notification_preferences page.\n */\nconst registerEventListeners = () => {\n\n /**\n * Update the dimmed status of the \"enabled\" toggle on the notification setting.\n *\n * @param {HTMLElement} lockedElement Element that receives the event.\n */\n const toggleLockSetting = (lockedElement) => {\n const isEnabled = lockedElement.checked || false;\n const enabledId = lockedElement.id.replace('_locked[', '_enabled[');\n\n const enabledElement = document.getElementById(enabledId).closest('div.custom-control');\n enabledElement.classList.toggle('dimmed_text', isEnabled);\n };\n\n /**\n * Enable/Disable all settings of the provider.\n *\n * @param {HTMLElement} providerEnabledElement Element that receives the event.\n */\n const toggleEnableProviderSettings = (providerEnabledElement) => {\n const isEnabled = providerEnabledElement.checked || false;\n const parentRow = providerEnabledElement.closest('tr');\n\n const elements = parentRow.querySelectorAll(selectors.allSettings);\n elements.forEach((element) => {\n element.toggleAttribute('disabled', !isEnabled);\n });\n };\n\n /**\n * AJAX call to update the default notification element status on the server.\n *\n * @param {Boolean} isEnabled\n * @param {string} preference\n */\n const setDefaultNotification = (isEnabled, preference) => {\n // AJAX call to update the provider's enable status on the server.\n Ajax.call([{\n methodname: 'core_message_set_default_notification',\n args: {\n preference: preference,\n state: isEnabled ? 1 : 0\n }\n }])[0].done((data) => {\n // Display success notification.\n Notification.addNotification({\n message: data.successmessage,\n type: 'success'\n });\n })\n .fail(Notification.exception);\n };\n\n const container = document.querySelector('.preferences-container');\n\n container.querySelectorAll(selectors.provider).forEach((providerEnabledElement) => {\n // Set the initial statuses.\n if (!providerEnabledElement.checked) {\n toggleEnableProviderSettings(providerEnabledElement);\n }\n\n providerEnabledElement.addEventListener('change', (e) => {\n toggleEnableProviderSettings(e.target);\n\n setDefaultNotification(\n e.target.checked,\n providerEnabledElement.parentElement.parentElement.dataset.preference);\n });\n });\n\n container.querySelectorAll(selectors.lockSetting).forEach((lockedElement) => {\n // Set the initial statuses.\n if (lockedElement.checked) {\n toggleLockSetting(lockedElement);\n }\n\n lockedElement.addEventListener('change', (e) => {\n toggleLockSetting(e.target);\n\n setDefaultNotification(\n e.target.checked,\n lockedElement.parentElement.parentElement.dataset.preference);\n });\n });\n\n container.querySelectorAll(selectors.enabledSetting).forEach((enabledElement) => {\n enabledElement.addEventListener('change', (e) => {\n setDefaultNotification(\n e.target.checked,\n enabledElement.parentElement.parentElement.dataset.preference);\n });\n });\n};\n\n/**\n * Initialize the page.\n */\nconst init = () => {\n registerEventListeners();\n};\n\nexport default {\n init: init,\n};\n"],"names":["selectors","init","toggleLockSetting","lockedElement","isEnabled","checked","enabledId","id","replace","document","getElementById","closest","classList","toggle","toggleEnableProviderSettings","providerEnabledElement","querySelectorAll","forEach","element","toggleAttribute","setDefaultNotification","preference","Ajax","call","methodname","args","state","done","data","addNotification","message","successmessage","type","fail","Notification","exception","container","querySelector","addEventListener","e","target","parentElement","dataset","enabledElement","registerEventListeners"],"mappings":";;;;;;;;;;sFA4BMA,mBACQ,2CADRA,sBAEW,0BAFXA,yBAGc,2BAHdA,sBAIW,iEA4GF,CACXC,KALS,KAlGkB,YAOrBC,kBAAqBC,sBACjBC,UAAYD,cAAcE,UAAW,EACrCC,UAAYH,cAAcI,GAAGC,QAAQ,WAAY,aAEhCC,SAASC,eAAeJ,WAAWK,QAAQ,sBACnDC,UAAUC,OAAO,cAAeT,YAQ7CU,6BAAgCC,+BAC5BX,UAAYW,uBAAuBV,UAAW,EAClCU,uBAAuBJ,QAAQ,MAEtBK,iBAAiBhB,uBACnCiB,SAASC,UACdA,QAAQC,gBAAgB,YAAaf,eAUvCgB,uBAAyB,CAAChB,UAAWiB,cAEvCC,KAAKC,KAAK,CAAC,CACPC,WAAY,wCACZC,KAAM,CACFJ,WAAYA,WACZK,MAAOtB,UAAY,EAAI,MAE3B,GAAGuB,MAAMC,6BAEIC,gBAAgB,CACzBC,QAASF,KAAKG,eACdC,KAAM,eAGbC,KAAKC,sBAAaC,YAGjBC,UAAY3B,SAAS4B,cAAc,0BAEzCD,UAAUpB,iBAAiBhB,oBAAoBiB,SAASF,yBAE/CA,uBAAuBV,SACxBS,6BAA6BC,wBAGjCA,uBAAuBuB,iBAAiB,UAAWC,IAC/CzB,6BAA6ByB,EAAEC,QAE/BpB,uBACImB,EAAEC,OAAOnC,QACTU,uBAAuB0B,cAAcA,cAAcC,QAAQrB,kBAIvEe,UAAUpB,iBAAiBhB,uBAAuBiB,SAASd,gBAEnDA,cAAcE,SACdH,kBAAkBC,eAGtBA,cAAcmC,iBAAiB,UAAWC,IACtCrC,kBAAkBqC,EAAEC,QAEpBpB,uBACImB,EAAEC,OAAOnC,QACTF,cAAcsC,cAAcA,cAAcC,QAAQrB,kBAI9De,UAAUpB,iBAAiBhB,0BAA0BiB,SAAS0B,iBAC1DA,eAAeL,iBAAiB,UAAWC,IACvCnB,uBACImB,EAAEC,OAAOnC,QACTsC,eAAeF,cAAcA,cAAcC,QAAQrB,mBAS/DuB"} \ No newline at end of file diff --git a/message/amd/src/default_notification_preferences.js b/message/amd/src/default_notification_preferences.js index 07a36a02898..21ba5d86412 100644 --- a/message/amd/src/default_notification_preferences.js +++ b/message/amd/src/default_notification_preferences.js @@ -23,6 +23,8 @@ * @author Pau Ferrer Ocaña * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +import * as Ajax from 'core/ajax'; +import Notification from 'core/notification'; const selectors = { provider: '.defaultmessageoutputs .provider_enabled', @@ -64,6 +66,30 @@ const registerEventListeners = () => { }); }; + /** + * AJAX call to update the default notification element status on the server. + * + * @param {Boolean} isEnabled + * @param {string} preference + */ + const setDefaultNotification = (isEnabled, preference) => { + // AJAX call to update the provider's enable status on the server. + Ajax.call([{ + methodname: 'core_message_set_default_notification', + args: { + preference: preference, + state: isEnabled ? 1 : 0 + } + }])[0].done((data) => { + // Display success notification. + Notification.addNotification({ + message: data.successmessage, + type: 'success' + }); + }) + .fail(Notification.exception); + }; + const container = document.querySelector('.preferences-container'); container.querySelectorAll(selectors.provider).forEach((providerEnabledElement) => { @@ -74,6 +100,10 @@ const registerEventListeners = () => { providerEnabledElement.addEventListener('change', (e) => { toggleEnableProviderSettings(e.target); + + setDefaultNotification( + e.target.checked, + providerEnabledElement.parentElement.parentElement.dataset.preference); }); }); @@ -85,6 +115,18 @@ const registerEventListeners = () => { lockedElement.addEventListener('change', (e) => { toggleLockSetting(e.target); + + setDefaultNotification( + e.target.checked, + lockedElement.parentElement.parentElement.dataset.preference); + }); + }); + + container.querySelectorAll(selectors.enabledSetting).forEach((enabledElement) => { + enabledElement.addEventListener('change', (e) => { + setDefaultNotification( + e.target.checked, + enabledElement.parentElement.parentElement.dataset.preference); }); }); }; diff --git a/message/classes/external/message_set_default_notification.php b/message/classes/external/message_set_default_notification.php new file mode 100644 index 00000000000..a5b7ff96a07 --- /dev/null +++ b/message/classes/external/message_set_default_notification.php @@ -0,0 +1,192 @@ +. + +namespace core_message\external; + +use context_system; +use core_external\external_api; +use core_external\external_function_parameters; +use core_external\external_value; + +/** + * Webservice to enable or disable the default notification. + * + * @package core_message + * @copyright 2024 Raquel Ortega + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class message_set_default_notification extends external_api { + /** + * Returns description of method parameters. + * + * @return external_function_parameters + */ + public static function execute_parameters(): external_function_parameters { + return new external_function_parameters([ + 'preference' => new external_value( + PARAM_TEXT, + 'The name of the preference', + VALUE_REQUIRED, + ), + 'state' => new external_value( + PARAM_INT, + 'The target state', + VALUE_REQUIRED, + ), + ]); + } + /** + * Set the default notification action state. + * + * @param string $preference The name of the preference. + * @param int $state The target state. + * @return array + */ + public static function execute( + string $preference, + int $state, + ): array { + + global $DB; + // Parameter validation. + [ + 'preference' => $preference, + 'state' => $state, + ] = self::validate_parameters(self::execute_parameters(), [ + 'preference' => $preference, + 'state' => $state, + ]); + + $context = context_system::instance(); + self::validate_context($context); + require_capability('moodle/site:config', $context); + + // Fetch all message processors and filter out disabled ones. + $allprocessors = get_message_processors(); + $processors = array_filter($allprocessors, function($processor) { + return $processor->enabled; + }); + $preferences = get_message_output_default_preferences(); + + // Get the provider name and provider component from the given preference. + $providers = get_message_providers(); + $providername = ''; + $providercomponent = ''; + foreach ($providers as $provider) { + if (str_contains($preference, $provider->component . '_' . $provider->name)) { + $providername = $provider->name; + $providercomponent = $provider->component; + break; + } + } + // Initialize variables to store new preferences. + $preferencename = ''; + $value = 0; + $successmessage = ''; + if (!empty($providername) && !empty($providercomponent)) { + $componentproviderbase = $providercomponent.'_'.$providername; + $providerdisplayname = get_string('messageprovider:'.$providername, $providercomponent); + + // Enabled / disabled toggle for providers. + if ($preference === $componentproviderbase . '_disable') { + // If $state is true, set the preference to disabled; otherwise, enable it. + $preferencename = $preference; + $value = $state ? 0 : 1; + $successmessage = get_string('successproviderupdate', 'message', $providerdisplayname); + + } else { + // Prepare data to use it for the component settings. + $currentprocessorname = ''; + $componentprovidersetting = ''; + foreach ($processors as $processor) { + if (str_contains($preference, '[' . $processor->name . ']')) { + $currentprocessorname = $processor->name; + $componentprovidersetting = str_replace('[' . $processor->name . ']', '', $preference); + $labelparams = [ + 'provider' => $providerdisplayname, + 'processor' => get_string('pluginname', 'message_' . $processor->name), + ]; + break; + } + } + + // Locked toggle. + if ($preference === $componentproviderbase.'_locked' . '[' . $currentprocessorname . ']') { + $preferencename = $currentprocessorname.'_provider_'.$componentproviderbase . '_locked'; + $value = $state ? 1 : 0; + if ($value === 1) { + $successmessage = get_string('successproviderlocked', 'message', $labelparams); + } else { + $successmessage = get_string('successproviderunlocked', 'message', $labelparams); + } + } + // Enabled toggle. + if ($preference === $componentproviderbase.'_enabled' . '[' . $currentprocessorname . ']') { + // Fetch the default message output preferences. + $preferencename = 'message_provider_'.$componentprovidersetting; + $successmessage = get_string('successproviderenabled', 'message', $labelparams); + $newsettings = []; + if (!empty($state)) { + $newsettings[] = $currentprocessorname; + } + // Check if the property exists within the preferences to maintain existing values. + if (property_exists($preferences, $preferencename)) { + $newsettings = array_merge($newsettings, explode(',', $preferences->$preferencename)); + + if (in_array($currentprocessorname, $newsettings) && empty($state)) { + if (($key = array_search($currentprocessorname, $newsettings)) !== false) { + unset($newsettings[$key]); + } + } + } + $value = join(',', $newsettings); + if (empty($value)) { + $value = null; + } + } + } + } + // Update preferences. + if (!empty($preferencename)) { + $transaction = $DB->start_delegated_transaction(); + $old = isset($preferences->$preferencename) ? $preferences->$preferencename : ''; + + if ($old != $value) { + add_to_config_log($preferencename, $old, $value, 'message'); + } + + set_config($preferencename, $value, 'message'); + $transaction->allow_commit(); + + \core_plugin_manager::reset_caches(); + } + + return [ + 'successmessage' => $successmessage, + ]; + } + + /** + * Describe the return structure of the external service. + * + * @return external_function_parameters + */ + public static function execute_returns(): external_function_parameters { + return new external_function_parameters([ + 'successmessage' => new external_value(PARAM_TEXT, 'Success notification message.'), + ]); + } +} diff --git a/message/renderer.php b/message/renderer.php index 3afe2c82fe3..b7ad12cb264 100644 --- a/message/renderer.php +++ b/message/renderer.php @@ -53,16 +53,16 @@ class core_message_renderer extends plugin_renderer_base { $output .= $this->heading(get_string('messageoutputs', 'message')); $output .= $this->manage_messageoutputs($allprocessors); - // Add active message output processors settings. - $output .= $this->manage_defaultmessageoutputs($processors, $providers, $preferences); - - $output .= html_writer::start_tag('div', array('class' => 'form-buttons')); + $output .= html_writer::start_tag('div', ['class' => 'form-buttons mb-3']); $output .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('savechanges', 'admin'), 'class' => 'form-submit btn btn-primary') ); $output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('form'); + // Add active message output processors settings. + $output .= $this->manage_defaultmessageoutputs($processors, $providers, $preferences); + return $output; } diff --git a/version.php b/version.php index 79d7bbf8ebd..5ce882bc91c 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2024120500.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2024120500.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '5.0dev (Build: 20241205)'; // Human-friendly version name