message/amd/src/message_drawer_view_settings.js

  1. // This file is part of Moodle - http://moodle.org/
  2. //
  3. // Moodle is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // Moodle is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Controls the settings page in the message drawer.
  17. *
  18. * @module core_message/message_drawer_view_settings
  19. * @copyright 2018 Ryan Wyllie <ryan@moodle.com>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. define(
  23. [
  24. 'jquery',
  25. 'core/notification',
  26. 'core/str',
  27. 'core/pubsub',
  28. 'core/templates',
  29. 'core_message/message_repository',
  30. 'core/custom_interaction_events',
  31. 'core_message/message_drawer_events'
  32. ],
  33. function(
  34. $,
  35. Notification,
  36. Str,
  37. PubSub,
  38. Templates,
  39. Repository,
  40. CustomEvents,
  41. MessageDrawerEvents
  42. ) {
  43. var SELECTORS = {
  44. CHECKBOX: 'input[type="checkbox"]',
  45. SETTINGS: '[data-region="settings"]',
  46. PRIVACY_PREFERENCE: '[data-preference="blocknoncontacts"] input[type="radio"]',
  47. NOTIFICATIONS_PREFERENCE: '[data-preference="notifications"] input[type="checkbox"]',
  48. ENTER_TO_SEND_PREFERENCE: '[data-preference="entertosend"] input[type="checkbox"]',
  49. NOTIFICATION_PREFERENCES_CONTAINER: '[data-region="notification-preference-container"]',
  50. CONTENT_CONTAINER: '[data-region="content-container"]',
  51. PLACEHOLDER_CONTAINER: '[data-region="placeholder-container"]'
  52. };
  53. var TEMPLATES = {
  54. NOTIFICATION_PREFERENCES: 'core_message/message_drawer_view_settings_body_content_notification_preferences'
  55. };
  56. var NOTIFICATION_PREFERENCES_KEY = 'message_provider_moodle_instantmessage';
  57. /**
  58. * Select the correct radio button in the DOM for the privacy preference.
  59. *
  60. * @param {Object} body The settings body element.
  61. * @param {Number} value Which radio button should be set
  62. */
  63. var setPrivacyPreference = function(body, value) {
  64. var inputs = body.find(SELECTORS.PRIVACY_PREFERENCE);
  65. inputs.each(function(index, input) {
  66. input = $(input);
  67. if (input.val() == value) {
  68. input.prop('checked', true);
  69. } else {
  70. input.prop('checked', false);
  71. }
  72. });
  73. };
  74. /**
  75. * Set the "enter to send" checkbox to the correct value in the DOM.
  76. *
  77. * @param {Object} body The settings body element.
  78. * @param {Bool} value Whether enter to send is enabled or disabled.
  79. */
  80. var setEnterToSend = function(body, value) {
  81. var checkbox = body.find(SELECTORS.ENTER_TO_SEND_PREFERENCE);
  82. if (value) {
  83. checkbox.prop('checked', true);
  84. } else {
  85. checkbox.prop('checked', false);
  86. }
  87. };
  88. /**
  89. * Send a request to the server to save the given preferences. Also publish
  90. * a preferences updated event for the rest of the message drawer to
  91. * subscribe to.
  92. *
  93. * @param {Number} loggedInUserId The logged in user id.
  94. * @param {Array} preferences The preferences to set.
  95. * @return {Object} jQuery promise
  96. */
  97. var savePreferences = function(loggedInUserId, preferences) {
  98. return Repository.savePreferences(loggedInUserId, preferences)
  99. .then(function() {
  100. PubSub.publish(MessageDrawerEvents.PREFERENCES_UPDATED, preferences);
  101. return;
  102. })
  103. .catch(Notification.exception);
  104. };
  105. /**
  106. * Create all of the event listeners for the message preferences page.
  107. *
  108. * @method registerEventListeners
  109. * @param {Object} body The settings body element.
  110. * @param {Number} loggedInUserId The logged in user id.
  111. */
  112. var registerEventListeners = function(body, loggedInUserId) {
  113. var settingsContainer = body.find(SELECTORS.SETTINGS);
  114. CustomEvents.define(settingsContainer, [
  115. CustomEvents.events.activate
  116. ]);
  117. settingsContainer.on(CustomEvents.events.activate, SELECTORS.NOTIFICATIONS_PREFERENCE, function(e) {
  118. var container = $(e.target).closest(SELECTORS.NOTIFICATION_PREFERENCES_CONTAINER);
  119. var checkboxes = container.find(SELECTORS.CHECKBOX);
  120. if (!checkboxes.length) {
  121. return;
  122. }
  123. // The preference value is all of the enabled processors, comma separated, so let's
  124. // see which ones are enabled.
  125. var values = checkboxes.toArray().reduce(function(carry, checkbox) {
  126. checkbox = $(checkbox);
  127. if (checkbox.prop('checked')) {
  128. carry.push(checkbox.attr('data-name'));
  129. }
  130. return carry;
  131. }, []);
  132. var newValue = values.length ? values.join(',') : 'none';
  133. var preferences = [
  134. {
  135. type: 'message_provider_moodle_instantmessage_enabled',
  136. value: newValue
  137. }
  138. ];
  139. savePreferences(loggedInUserId, preferences);
  140. });
  141. settingsContainer.on('change', SELECTORS.PRIVACY_PREFERENCE, function(e) {
  142. var newValue = $(e.target).val();
  143. var preferences = [
  144. {
  145. type: 'message_blocknoncontacts',
  146. value: newValue
  147. }
  148. ];
  149. savePreferences(loggedInUserId, preferences);
  150. });
  151. settingsContainer.on(CustomEvents.events.activate, SELECTORS.ENTER_TO_SEND_PREFERENCE, function(e) {
  152. var newValue = $(e.target).prop('checked');
  153. var preferences = [
  154. {
  155. type: 'message_entertosend',
  156. value: newValue
  157. }
  158. ];
  159. savePreferences(loggedInUserId, preferences);
  160. });
  161. };
  162. /**
  163. * Initialise the module by loading the user's messaging preferences from the server and
  164. * rendering them in the settings page.
  165. *
  166. * Moodle may have many (or no) message processors enabled to notify the user when they
  167. * receive messages. We need to dynamically build the settings page based on which processors
  168. * are configured for the user.
  169. *
  170. * @param {Object} body The settings body element.
  171. * @param {Number} loggedInUserId The logged in user id.
  172. */
  173. var init = function(body, loggedInUserId) {
  174. // Load the message preferences from the server.
  175. Repository.getUserMessagePreferences(loggedInUserId)
  176. .then(function(response) {
  177. // Set the values of the stright forward preferences.
  178. setPrivacyPreference(body, response.blocknoncontacts);
  179. setEnterToSend(body, response.entertosend);
  180. // Parse the list of other preferences into a more usable format.
  181. var notificationProcessors = [];
  182. if (response.preferences.components.length) {
  183. response.preferences.components.forEach(function(component) {
  184. if (component.notifications.length) {
  185. // Filter down to just the notification processors that work on instant
  186. // messaging. We don't care about another other ones.
  187. var notificationPreferences = component.notifications.filter(function(notification) {
  188. return notification.preferencekey == NOTIFICATION_PREFERENCES_KEY;
  189. });
  190. if (notificationPreferences.length) {
  191. // Messaging only has one config at the moment which is for notifications
  192. // on personal messages.
  193. var configuration = component.notifications[0];
  194. notificationProcessors = configuration.processors.map(function(processor) {
  195. // Consider the the processor enabled if either preference is set. This is
  196. // for backwards compatibility. Going forward they will be treated as one
  197. // setting.
  198. var checked = processor.enabled;
  199. return {
  200. displayname: processor.displayname,
  201. name: processor.name,
  202. checked: checked,
  203. // The admin can force processors to be enabled at a site level so
  204. // we need to check if this processor has been locked by the admin.
  205. locked: processor.locked,
  206. lockedmessage: processor.lockedmessage || null,
  207. };
  208. });
  209. }
  210. }
  211. });
  212. }
  213. var container = body.find(SELECTORS.NOTIFICATION_PREFERENCES_CONTAINER);
  214. if (notificationProcessors.length) {
  215. // We have processors (i.e. email, mobile, jabber) to show.
  216. container.removeClass('hidden');
  217. // Render the processor options.
  218. return Templates.render(TEMPLATES.NOTIFICATION_PREFERENCES, {processors: notificationProcessors})
  219. .then(function(html) {
  220. container.append(html);
  221. return html;
  222. });
  223. } else {
  224. return true;
  225. }
  226. })
  227. .then(function() {
  228. // We're done loading so hide the loading placeholder and show the settings.
  229. body.find(SELECTORS.CONTENT_CONTAINER).removeClass('hidden');
  230. body.find(SELECTORS.PLACEHOLDER_CONTAINER).addClass('hidden');
  231. // Register the event listers for if the user wants to change the preferences.
  232. registerEventListeners(body, loggedInUserId);
  233. return;
  234. })
  235. .catch(Notification.exception);
  236. };
  237. /**
  238. * Initialise the settings page by adding event listeners to
  239. * the checkboxes.
  240. *
  241. * @param {string} namespace The route namespace.
  242. * @param {Object} header The settings header element.
  243. * @param {Object} body The settings body element.
  244. * @param {Object} footer The footer body element.
  245. * @param {Number} loggedInUserId The logged in user id.
  246. * @return {Object} jQuery promise
  247. */
  248. var show = function(namespace, header, body, footer, loggedInUserId) {
  249. if (!body.attr('data-init')) {
  250. init(body, loggedInUserId);
  251. body.attr('data-init', true);
  252. }
  253. return $.Deferred().resolve().promise();
  254. };
  255. /**
  256. * String describing this page used for aria-labels.
  257. *
  258. * @return {Object} jQuery promise
  259. */
  260. var description = function() {
  261. return Str.get_string('messagedrawerviewsettings', 'core_message');
  262. };
  263. return {
  264. show: show,
  265. description: description,
  266. };
  267. });