From 34eb5fcb6056b84bba1092dabde2738e28ad132d Mon Sep 17 00:00:00 2001 From: Ryan Wyllie Date: Mon, 1 Aug 2016 06:51:30 +0000 Subject: [PATCH] MDL-54698 message: move general settings from preference page --- lang/en/message.php | 5 +- lib/outputrenderers.php | 2 + message/amd/src/disable_all_preference.js | 83 ------------ message/amd/src/message_popover_controller.js | 113 +++++++++++++--- .../src/notification_popover_controller.js | 88 ++++++++++-- ...preferences_general_settings_controller.js | 69 ---------- message/amd/src/user_preference.js | 128 ------------------ .../output/preferences/general_settings.php | 70 ---------- message/renderer.php | 6 +- message/templates/message_popover.mustache | 26 +++- .../notification_content_item.mustache | 4 +- .../templates/notification_popover.mustache | 23 +++- .../preferences_general_settings.mustache | 61 --------- .../less/moodle/popover_region.less | 48 +++++-- theme/bootstrapbase/style/moodle.css | 37 +++-- user/externallib.php | 9 +- 16 files changed, 298 insertions(+), 474 deletions(-) delete mode 100644 message/amd/src/disable_all_preference.js delete mode 100644 message/amd/src/preferences_general_settings_controller.js delete mode 100644 message/amd/src/user_preference.js delete mode 100644 message/classes/output/preferences/general_settings.php delete mode 100644 message/templates/preferences_general_settings.mustache diff --git a/lang/en/message.php b/lang/en/message.php index 49dc7960fa7..777d1347d54 100644 --- a/lang/en/message.php +++ b/lang/en/message.php @@ -48,14 +48,14 @@ $string['defaults'] = 'Defaults'; $string['deletemessage'] = 'Delete message'; $string['deletemessageconfirmation'] = 'Are you sure you want to delete this message? It will only be deleted from your messaging history and will still be viewable by the user who sent or received the message.'; $string['deletemessagesdays'] = 'Number of days before old messages are automatically deleted'; -$string['disableall'] = 'Temporarily disable notifications'; -$string['disableall_help'] = 'Temporarily disable all notifications except those marked as "forced" by the site administrator'; +$string['disableall'] = 'Disable notifications'; $string['disabled'] = 'Messaging is disabled on this site'; $string['disallowed'] = 'Disallowed'; $string['discussion'] = 'Discussion'; $string['emailmessages'] = 'Email messages when I am offline'; $string['emailtagline'] = 'This is a copy of a message sent to you at "{$a->sitename}". Go to {$a->url} to reply.'; $string['emptysearchstring'] = 'You must search for something'; +$string['enableall'] = 'Enable notifications'; $string['enabled'] = 'Enabled'; $string['errorcallingprocessor'] = 'Error calling defined output'; $string['errorwhilesendingmessage'] = 'An error occurred while sending the message; please try again later.'; @@ -174,6 +174,7 @@ $string['togglemessagemenu'] = 'Toggle message menu'; $string['touserdoesntexist'] = 'You can not send a message to a user id ({$a}) that doesn\'t exist'; $string['unabletomessageuser'] = 'You are not permitted to send a message to that user'; $string['unblockcontact'] = 'Unblock contact'; +$string['unblocknoncontacts'] = 'Allow non-contacts to message me'; $string['unreadmessages'] = 'Unread messages ({$a})'; $string['unreadnewmessages'] = 'New messages ({$a})'; $string['unreadnewmessage'] = 'New message from {$a}'; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index c698a25225e..2cb2bb37926 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -3205,6 +3205,7 @@ EOD; if (isloggedin() && $processor->enabled) { $context = [ 'userid' => $USER->id, + 'allnotificationsdisabled' => !empty($USER->emailstop), 'urls' => [ 'preferences' => (new moodle_url('/message/edit.php', ['id' => $USER->id]))->out(), ], @@ -3226,6 +3227,7 @@ EOD; if (isloggedin()) { $context = [ 'userid' => $USER->id, + 'blocknoncontacts' => get_user_preferences('message_blocknoncontacts', '', $USER->id), 'urls' => [ 'preferences' => (new moodle_url('/message/edit.php', ['id' => $USER->id]))->out(), ], diff --git a/message/amd/src/disable_all_preference.js b/message/amd/src/disable_all_preference.js deleted file mode 100644 index 065d88469b2..00000000000 --- a/message/amd/src/disable_all_preference.js +++ /dev/null @@ -1,83 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Handle the disable all notifications user preference on the message - * preferences page - * - * @module core_message/disable_all_preference - * @class disable_all_preference - * @package message - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.2 - */ -define(['jquery', 'core_message/user_preference'], function($, UserPreference) { - /** - * Constructor for the DisableAlPreference. This is a special type - * of UserPreference. - * - * Subclasses UserPreference. - * - * @param element jQuery object root element of the processor - * @param int the current user id - * @return object DisableAllPreference - */ - var DisableAllPreference = function(element, userId) { - UserPreference.call(this, element, userId); - }; - - /** - * Clone the UserPreference prototype. - */ - DisableAllPreference.prototype = Object.create(UserPreference.prototype); - - /** - * Return the request arguments for the save function. - * - * Override UserPreference.prototype.getRequestArguments - * - * @method getRequestArguments - * @return object - */ - DisableAllPreference.prototype.getRequestArguments = function() { - return { - user: { - emailstop: this.isChecked() ? 1 : 0, - }, - }; - }; - - /** - * Persist the preference and fire relevant events after the - * successfully saving. - * - * Override UserPreference.prototype.save - * - * @method save - * @return promise - */ - DisableAllPreference.prototype.save = function() { - return UserPreference.prototype.save.call(this).done(function() { - if (this.isChecked()) { - $(document).trigger('messageprefs:disableall'); - } else { - $(document).trigger('messageprefs:enableall'); - } - }.bind(this)); - }; - - return DisableAllPreference; -}); diff --git a/message/amd/src/message_popover_controller.js b/message/amd/src/message_popover_controller.js index 53e21e5a372..b993b53f986 100644 --- a/message/amd/src/message_popover_controller.js +++ b/message/amd/src/message_popover_controller.js @@ -26,9 +26,9 @@ * @since 3.2 */ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates', 'core/str', - 'core/custom_interaction_events', 'core/popover_region_controller', + 'core/notification', 'core/custom_interaction_events', 'core/popover_region_controller', 'core_message/message_repository', 'core/url'], - function($, bootstrap, ajax, templates, str, CustomEvents, + function($, Bootstrap, Ajax, Templates, Str, Notification, CustomEvents, PopoverController, MessageRepo, URL) { var SELECTORS = { @@ -39,6 +39,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' CONTENT_ITEM_CONTAINER: '.content-item-container', EMPTY_MESSAGE: '.empty-message', LINK_URL: '[data-link-url]', + BLOCK_NON_CONTACTS_BUTTON: '[data-block-non-contacts]', }; /** @@ -53,6 +54,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' PopoverController.call(this, element); this.markAllReadButton = this.root.find(SELECTORS.MARK_ALL_READ_BUTTON); + this.blockNonContactsButton = this.root.find(SELECTORS.BLOCK_NON_CONTACTS_BUTTON); this.content = this.root.find(SELECTORS.CONTENT); this.userId = this.root.attr(SELECTORS.USER_ID); this.limit = 20; @@ -70,6 +72,11 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' */ MessagePopoverController.prototype = Object.create(PopoverController.prototype); + /** + * Make sure the constructor is set correctly. + */ + MessagePopoverController.prototype.constructor = MessagePopoverController; + /** * Get the element holding the messages. * @@ -91,22 +98,22 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' /** * Set the correct aria label on the menu toggle button to be read out by screen - * readers. The message will indicate the state of the unread notifications. + * readers. The message will indicate the state of the unread messages. * * @method updateButtonAriaLabel */ MessagePopoverController.prototype.updateButtonAriaLabel = function() { if (this.isMenuOpen()) { - str.get_string('hidemessagewindow', 'message').done(function(string) { + Str.get_string('hidemessagewindow', 'message').done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } else { if (this.unreadCount) { - str.get_string('showmessagewindowwithcount', 'message', this.unreadCount).done(function(string) { + Str.get_string('showmessagewindowwithcount', 'message', this.unreadCount).done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } else { - str.get_string('showmessagewindownonew', 'message').done(function(string) { + Str.get_string('showmessagewindownonew', 'message').done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } @@ -134,8 +141,8 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Show the unread notification count badge on the menu toggle if there - * are unread notifications, otherwise hide it. + * Show the unread message count badge on the menu toggle if there + * are unread messages, otherwise hide it. * * @method renderUnreadCount */ @@ -151,7 +158,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Hide the unread notification count badge on the menu toggle. + * Hide the unread message count badge on the menu toggle. * * @method hideUnreadCount */ @@ -160,7 +167,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Ask the server how many unread notifications are left, render the value + * Ask the server how many unread messages are left, render the value * as a badge on the menu toggle and update the aria labels on the menu * toggle. * @@ -175,12 +182,12 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Render the notification data with the appropriate template and add it to the DOM. + * Render the message data with the appropriate template and add it to the DOM. * * @method renderMessages * @param messages array message data * @param container jQuery object the container to append the rendered messages - * @return jQuery promise that is resolved when all notifications have been + * @return jQuery promise that is resolved when all messages have been * rendered and added to the DOM */ MessagePopoverController.prototype.renderMessages = function(messages, container) { @@ -197,10 +204,10 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' id: message.userid, }); - var promise = templates.render('message/message_content_item', message); + var promise = Templates.render('message/message_content_item', message); promise.then(function(html, js) { container.append(html); - templates.runTemplateJS(js); + Templates.runTemplateJS(js); }.bind(this)); promises.push(promise); @@ -215,7 +222,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' * loading some and haven't already loaded all of them. * * @method loadMoreMessages - * @return jQuery promise that is resolved when notifications have been + * @return jQuery promise that is resolved when messages have been * retrieved and added to the DOM */ MessagePopoverController.prototype.loadMoreMessages = function() { @@ -248,8 +255,8 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Send a request to the server to mark all unread notifications as read and update - * the unread count and unread notification elements appropriately. + * Send a request to the server to mark all unread messages as read and update + * the unread count and unread messages elements appropriately. * * @method markAllAsRead */ @@ -265,7 +272,65 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' }; /** - * Add all of the required event listeners for this notification popover. + * Update the block messages from non-contacts user preference in the DOM and + * send a request to update on the server. + * + * @method toggleBlockNonContactsStatus + */ + MessagePopoverController.prototype.toggleBlockNonContactsStatus = function() { + var button = this.blockNonContactsButton; + var ischecked = (button.attr('aria-checked') === 'true'); + var blockstring = ''; + var unblockstring = ''; + + button.addClass('loading'); + + return Str.get_strings([ + { + key: 'blocknoncontacts', + component: 'message', + }, + { + key: 'unblocknoncontacts', + component: 'message', + } + ]).then(function(strings) { + // If we could load the strings then update the user preferences. + blockstring = strings[0]; + unblockstring = strings[1]; + + var request = { + methodname: 'core_user_update_user', + args: { + user: { + preferences: [ + { + type: button.attr('data-preference-key'), + value: ischecked ? 0 : 1, + } + ] + } + } + }; + + return Ajax.call([request])[0]; + }) + .done(function() { + // If everything executed correctly then update the DOM. + if (ischecked) { + button.attr('aria-checked', false) + button.attr('data-original-title', blockstring); + } else { + button.attr('aria-checked', true) + button.attr('data-original-title', unblockstring); + } + }) + .fail(Notification.exception) + .always(function() { button.removeClass('loading') }); + }; + + /** + * Add all of the required event listeners for this messages popover. * * @method registerEventListeners */ @@ -274,7 +339,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' CustomEvents.events.keyboardActivate, ]); - // Update the notification information when the menu is opened. + // Update the message information when the menu is opened. this.root.on(this.events().menuOpened, function() { this.hideUnreadCount(); this.updateButtonAriaLabel(); @@ -284,7 +349,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' } }.bind(this)); - // Update the notification information when the menu is opened. + // Update the message information when the menu is opened. this.root.on(this.events().menuClosed, function() { this.renderUnreadCount(); this.updateButtonAriaLabel(); @@ -314,6 +379,14 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' this.navigateToLinkURL(linkItem, false); e.stopPropagation(); }.bind(this)); + + // Update the state of non-contact blocking when button is activated. + this.root.on(CustomEvents.events.activate, SELECTORS.BLOCK_NON_CONTACTS_BUTTON, function(e, data) { + this.toggleBlockNonContactsStatus(); + + e.stopPropagation(); + data.originalEvent.preventDefault(); + }.bind(this)); }; return MessagePopoverController; diff --git a/message/amd/src/notification_popover_controller.js b/message/amd/src/notification_popover_controller.js index 60b130e8057..447aece8b4b 100644 --- a/message/amd/src/notification_popover_controller.js +++ b/message/amd/src/notification_popover_controller.js @@ -28,7 +28,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates', 'core/str', 'core/notification', 'core/custom_interaction_events', 'core/popover_region_controller', 'core_message/notification_repository'], - function($, bootstrap, ajax, templates, str, DebugNotification, CustomEvents, + function($, Bootstrap, Ajax, Templates, Str, DebugNotification, CustomEvents, PopoverController, NotificationRepo) { var SELECTORS = { @@ -45,6 +45,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' CONTENT_BODY_SHORT: '.content-body-short', CONTENT_BODY_FULL: '.content-body-full', LINK_URL: '[data-link-url]', + DISABLE_ALL_BUTTON: '[data-disable-all]', }; var PROCESSOR_NAME = 'popup'; @@ -61,6 +62,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' PopoverController.call(this, element); this.markAllReadButton = this.root.find(SELECTORS.MARK_ALL_READ_BUTTON); + this.disableAllButton = this.root.find(SELECTORS.DISABLE_ALL_BUTTON); this.unreadCount = 0; this.userId = this.root.attr(SELECTORS.USER_ID); this.modeToggle = this.root.find(SELECTORS.MODE_TOGGLE); @@ -91,6 +93,11 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' */ NotificationPopoverController.prototype = Object.create(PopoverController.prototype); + /** + * Make sure the constructor is set correctly. + */ + NotificationPopoverController.prototype.constructor = NotificationPopoverController; + /** * Set the correct aria label on the menu toggle button to be read out by screen * readers. The message will indicate the state of the unread notifications. @@ -99,16 +106,16 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' */ NotificationPopoverController.prototype.updateButtonAriaLabel = function() { if (this.isMenuOpen()) { - str.get_string('hidenotificationwindow', 'message').done(function(string) { + Str.get_string('hidenotificationwindow', 'message').done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } else { if (this.unreadCount) { - str.get_string('shownotificationwindowwithcount', 'message', this.unreadCount).done(function(string) { + Str.get_string('shownotificationwindowwithcount', 'message', this.unreadCount).done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } else { - str.get_string('shownotificationwindownonew', 'message').done(function(string) { + Str.get_string('shownotificationwindownonew', 'message').done(function(string) { this.menuToggle.attr('aria-label', string); }.bind(this)); } @@ -301,10 +308,10 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' } } - var promise = templates.render('message/notification_content_item', notification); + var promise = Templates.render('message/notification_content_item', notification); promise.then(function(html, js) { container.append(html); - templates.runTemplateJS(js); + Templates.runTemplateJS(js); }.bind(this)); promises.push(promise); @@ -382,6 +389,61 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' .always(function() { this.markAllReadButton.removeClass('loading'); }.bind(this)); }; + /** + * Update the disable all notifications user property in the DOM and + * send a request to update on the server. + * + * @method toggleDisableAllStatus + */ + NotificationPopoverController.prototype.toggleDisableAllStatus = function() { + var button = this.disableAllButton; + var ischecked = (button.attr('aria-checked') === 'true'); + var disablestring = ''; + var enablestring = ''; + + button.addClass('loading'); + + return Str.get_strings([ + { + key: 'disableall', + component: 'message', + }, + { + key: 'enableall', + component: 'message', + } + ]).then(function(strings) { + // If we could load the strings then update the user preferences. + disablestring = strings[0]; + enablestring = strings[1]; + + var request = { + methodname: 'core_user_update_user', + args: { + user: { + emailstop: ischecked ? 0 : 1, + } + } + }; + + return Ajax.call([request])[0]; + }) + .done(function() { + // If everything executed correctly then update the DOM. + if (ischecked) { + button.attr('aria-checked', false) + button.attr('data-original-title', disablestring); + $(document).trigger('messageprefs:enableall'); + } else { + button.attr('aria-checked', true) + button.attr('data-original-title', enablestring); + $(document).trigger('messageprefs:disableall'); + } + }) + .fail(DebugNotification.exception) + .always(function() { button.removeClass('loading') }); + }; + /** * Shift focus to the next content item in the list if the content item * list current contains focus, otherwise the first item in the list is @@ -588,7 +650,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' args: args }; - var promise = ajax.call([request])[0]; + var promise = Ajax.call([request])[0]; promise.fail(DebugNotification.exception); promise.always(function() { @@ -662,7 +724,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' this.modeToggle.addClass('off'); this.root.removeClass('unread-only'); - str.get_string('shownewnotifications', 'message').done(function(string) { + Str.get_string('shownewnotifications', 'message').done(function(string) { this.modeToggle.attr('aria-label', string); }.bind(this)); } else { @@ -670,7 +732,7 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' this.modeToggle.addClass('on'); this.root.addClass('unread-only'); - str.get_string('showallnotifications', 'message').done(function(string) { + Str.get_string('showallnotifications', 'message').done(function(string) { this.modeToggle.attr('aria-label', string); }.bind(this)); } @@ -708,6 +770,14 @@ define(['jquery', 'theme_bootstrapbase/bootstrap', 'core/ajax', 'core/templates' e.stopPropagation(); }.bind(this)); + // Update the state of preferences when disable all notifications button is activated. + this.root.on(CustomEvents.events.activate, SELECTORS.DISABLE_ALL_BUTTON, function(e, data) { + this.toggleDisableAllStatus(); + + e.stopPropagation(); + data.originalEvent.preventDefault(); + }.bind(this)); + // Expand all the currently visible content items if the user hits the // asterix key. this.root.on(CustomEvents.events.asterix, function() { diff --git a/message/amd/src/preferences_general_settings_controller.js b/message/amd/src/preferences_general_settings_controller.js deleted file mode 100644 index 356b5c34d37..00000000000 --- a/message/amd/src/preferences_general_settings_controller.js +++ /dev/null @@ -1,69 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Controls the general settings on the message preferences page - * - * @module core_message/preferences_general_settings_controller - * @class preferences_processors_controller - * @package message - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.2 - */ -define(['jquery', 'core_message/user_preference', 'core_message/disable_all_preference'], - function($, UserPreference, DisableAllPreference) { - - var SELECTORS = { - SETTING: '[data-preference-key]', - }; - - /** - * Constructor for the GeneralSettingsController. - * - * @param element jQuery object root element of the processor - * @return object GeneralSettingsController - */ - var GeneralSettingsController = function(element) { - this.root = $(element); - this.userId = this.root.attr('data-user-id'); - - this.root.on('change', function(e) { - var element = $(e.target).closest(SELECTORS.SETTING); - var setting = this.createFromElement(element); - setting.save(); - }.bind(this)); - }; - - /** - * Factory method to return the correct UserPreference instance - * for the given jQuery element. - * - * @method save - * @param object jQuery element - * @return object UserPreference - */ - GeneralSettingsController.prototype.createFromElement = function(element) { - element = $(element); - - if (element.attr('data-preference-key') === "disableall") { - return new DisableAllPreference(element, this.userId); - } else { - return new UserPreference(element, this.userId); - } - }; - - return GeneralSettingsController; -}); diff --git a/message/amd/src/user_preference.js b/message/amd/src/user_preference.js deleted file mode 100644 index 7786066f5d8..00000000000 --- a/message/amd/src/user_preference.js +++ /dev/null @@ -1,128 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Controls a user preference on the message preferences page. - * - * @module core_message/user_preference - * @class user_preference - * @package message - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since 3.2 - */ -define(['jquery', 'core/ajax', 'core/notification'], function($, ajax, notification) { - /** - * Constructor for the UserPreference. - * - * @param element jQuery object root element of the processor - * @param int the current user id - * @return object UserPreference - */ - var UserPreference = function(element, userId) { - this.root = $(element); - this.userId = userId; - }; - - /** - * Check if the preference is checked (enabled). - * - * @return bool - */ - UserPreference.prototype.isChecked = function() { - return this.root.find('input').prop('checked'); - }; - - /** - * Get the unique key that identifies this user preference. - * - * @method getPreferenceKey - * @return string - */ - UserPreference.prototype.getPreferenceKey = function() { - return this.root.attr('data-preference-key'); - }; - - /** - * Flag the preference as loading. - * - * @method startLoading - */ - UserPreference.prototype.startLoading = function() { - this.root.addClass('loading'); - this.root.find('input').prop('disabled', true); - }; - - /** - * Remove the loading flag for this preference. - * - * @method stopLoading - */ - UserPreference.prototype.stopLoading = function() { - this.root.removeClass('loading'); - this.root.find('input').prop('disabled', false); - }; - - /** - * Check if the preference is loading. - * - * @method isLoading - */ - UserPreference.prototype.isLoading = function() { - return this.root.hasClass('loading'); - }; - - /** - * Generate the request arguments for the save function. - * - * @method getRequestArguments - * @return object - */ - UserPreference.prototype.getRequestArguments = function() { - return { - user: { - preferences: [{ - type: this.getPreferenceKey(), - value: this.isChecked() ? 1 : 0, - }], - } - }; - }; - - /** - * Persist the user preference in the server. - * - * @method save - * @return promise - */ - UserPreference.prototype.save = function() { - if (this.isLoading()) { - return $.Deferred().resolve(); - } - - this.startLoading(); - - var request = { - methodname: 'core_user_update_user', - args: this.getRequestArguments(), - }; - - return ajax.call([request])[0] - .fail(notification.exception) - .always(function() { this.stopLoading(); }.bind(this)); - }; - - return UserPreference; -}); diff --git a/message/classes/output/preferences/general_settings.php b/message/classes/output/preferences/general_settings.php deleted file mode 100644 index 17a8513eb0e..00000000000 --- a/message/classes/output/preferences/general_settings.php +++ /dev/null @@ -1,70 +0,0 @@ -. - -/** - * Contains general_settings class for displaying on message preferences - * page. - * - * @package core_message - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace core_message\output\preferences; - -use renderable; -use templatable; - -/** - * Class to create context for the general settings on the message - * preferences page. - * - * @package core_message - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class general_settings implements templatable, renderable { - - /** - * A list of message preferences. - */ - protected $preferences; - - /** - * A user. - */ - protected $user; - - /** - * Constructor. - * - * @param stdClass $preferences - * @param stdClass $user - */ - public function __construct($preferences, $user) { - $this->preferences = $preferences; - $this->user = $user; - } - - public function export_for_template(\renderer_base $output) { - return [ - 'userid' => $this->user->id, - 'blocknoncontacts' => $this->preferences->blocknoncontacts, - 'disableall' => $this->user->emailstop, - 'disableallhelpicon' => $output->help_icon('disableall', 'message'), - ]; - } -} diff --git a/message/renderer.php b/message/renderer.php index 98159bf7acd..77ade34e312 100644 --- a/message/renderer.php +++ b/message/renderer.php @@ -230,11 +230,7 @@ class core_message_renderer extends plugin_renderer_base { $providers = message_get_providers_for_user($user->id); $preferences = get_all_message_preferences($readyprocessors, $providers, $user); $notificationlistoutput = new \core_message\output\preferences\notification_list($readyprocessors, $providers, $preferences, $user); - $generalsettingsoutput = new \core_message\output\preferences\general_settings($preferences, $user); - $output = $this->render_from_template('message/preferences_notifications_list', $notificationlistoutput->export_for_template($this)); - $output .= $this->render_from_template('message/preferences_general_settings', $generalsettingsoutput->export_for_template($this)); - - return $output; + return $this->render_from_template('message/preferences_notifications_list', $notificationlistoutput->export_for_template($this)); } } diff --git a/message/templates/message_popover.mustache b/message/templates/message_popover.mustache index 4f7dd59d0f9..1dad8f93483 100644 --- a/message/templates/message_popover.mustache +++ b/message/templates/message_popover.mustache @@ -47,12 +47,34 @@ {{$headertext}}{{#str}} messages, message {{/str}}{{/headertext}} {{$headeractions}} + + data-original-title="{{#str}} markallread {{/str}}"> {{#pix}} t/markasread, core, {{#str}} markallread {{/str}} {{/pix}} {{> core/loading }} diff --git a/message/templates/notification_content_item.mustache b/message/templates/notification_content_item.mustache index b0c892d78c4..a0bd9b1fbff 100644 --- a/message/templates/notification_content_item.mustache +++ b/message/templates/notification_content_item.mustache @@ -77,13 +77,13 @@
{{#pix}} t/sort_desc {{/pix}}
+ + role="button"> {{#pix}} t/markasread, core, {{#str}} markallread {{/str}} {{/pix}} {{> core/loading }} diff --git a/message/templates/preferences_general_settings.mustache b/message/templates/preferences_general_settings.mustache deleted file mode 100644 index dd8fcae9c8a..00000000000 --- a/message/templates/preferences_general_settings.mustache +++ /dev/null @@ -1,61 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core_message/preferences_general_settings - - The message preferences general settings - - Classes required for JS: - * None - - Data attibutes required for JS: - * None - - Context variables required for this template: - * userid The current user id - * blocknoncontacts If the user is blocking non contacts - * disableall If the user has disabled all notifications - * disablehelpicon HTML for the help icon - - Example context (json): - { - "userid": 1, - "blocknoncontacts": 1, - "disableall": 0, - "disableallhelpicon": "Help icon" - } -}} -

{{#str}} generalsettings, admin {{/str}}

-
- -
- -
-{{#js}} -require(['jquery', 'core_message/preferences_general_settings_controller'], function($, controller) { - new controller($('.general-settings-container')); -}); -{{/js}} diff --git a/theme/bootstrapbase/less/moodle/popover_region.less b/theme/bootstrapbase/less/moodle/popover_region.less index adbcde70caa..50ee5614224 100644 --- a/theme/bootstrapbase/less/moodle/popover_region.less +++ b/theme/bootstrapbase/less/moodle/popover_region.less @@ -52,6 +52,43 @@ > * { margin-left: 5px; } + .loading-icon { + display: none; + height: 12px; + width: 12px; + } + label { + display: inline-block; + } + [role="checkbox"] { + &.loading { + .loading-icon { + display: inline-block; + } + &[aria-checked] { + .checked, + .unchecked { + display: none; + } + } + } + &[aria-checked="true"] { + .checked { + display: inline-block; + } + .unchecked { + display: none; + } + } + &[aria-checked="false"] { + .checked { + display: none; + } + .unchecked { + display: inline-block; + } + } + } } } @@ -258,12 +295,6 @@ .normal-icon { display: inline-block; } - .loading-icon { - display: none; - height: 12px; - width: 12px; - } - &.loading { .normal-icon { display: none; @@ -558,11 +589,6 @@ .normal-icon { display: inline-block; } - .loading-icon { - display: none; - height: 12px; - width: 12px; - } &.loading { .normal-icon { diff --git a/theme/bootstrapbase/style/moodle.css b/theme/bootstrapbase/style/moodle.css index 4a1e35f8019..65a0d35d33a 100644 --- a/theme/bootstrapbase/style/moodle.css +++ b/theme/bootstrapbase/style/moodle.css @@ -7081,6 +7081,33 @@ body.path-question-type .mform fieldset.hidden { .popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions > * { margin-left: 5px; } +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions .loading-icon { + display: none; + height: 12px; + width: 12px; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions label { + display: inline-block; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"].loading .loading-icon { + display: inline-block; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"].loading[aria-checked] .checked, +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"].loading[aria-checked] .unchecked { + display: none; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"][aria-checked="true"] .checked { + display: inline-block; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"][aria-checked="true"] .unchecked { + display: none; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"][aria-checked="false"] .checked { + display: none; +} +.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions [role="checkbox"][aria-checked="false"] .unchecked { + display: inline-block; +} .popover-region .popover-region-container .popover-region-content-container { height: calc(100% - 25px); width: 100%; @@ -7249,11 +7276,6 @@ body.path-question-type .mform fieldset.hidden { .popover-region-notifications.popover-region .popover-region-container .popover-region-header-container .mark-all-read-button .normal-icon { display: inline-block; } -.popover-region-notifications.popover-region .popover-region-container .popover-region-header-container .mark-all-read-button .loading-icon { - display: none; - height: 12px; - width: 12px; -} .popover-region-notifications.popover-region .popover-region-container .popover-region-header-container .mark-all-read-button.loading .normal-icon { display: none; } @@ -7468,11 +7490,6 @@ body.path-question-type .mform fieldset.hidden { .popover-region-messages.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions .mark-all-read-button .normal-icon { display: inline-block; } -.popover-region-messages.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions .mark-all-read-button .loading-icon { - display: none; - height: 12px; - width: 12px; -} .popover-region-messages.popover-region .popover-region-container .popover-region-header-container .popover-region-header-actions .mark-all-read-button.loading .normal-icon { display: none; } diff --git a/user/externallib.php b/user/externallib.php index 9c9431e2da9..e46b9efd28c 100644 --- a/user/externallib.php +++ b/user/externallib.php @@ -22,7 +22,6 @@ * @copyright 2009 Petr Skodak * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - */ require_once("$CFG->libdir/externallib.php"); @@ -453,6 +452,14 @@ class core_user_external extends external_api { $transaction->allow_commit(); + // Everything went well, update the $USER. + foreach ($user as $property => $value) { + // If the $USER knows about this value. + if (isset($USER, $property)) { + $USER->$property = $value; + } + } + return null; }