MDL-61575 message_notification: replace lp/dialogue with core/modal
[moodle.git] / message / amd / src / notification_processor_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/>.
16 /**
17  * Load the settings for a message processor.
18  *
19  * @module     core_message/notification_processor_settings
20  * @class      notification_processor_settings
21  * @package    message
22  * @copyright  2016 Ryan Wyllie <ryan@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
25 define([
26         'jquery',
27         'core/ajax',
28         'core/str',
29         'core/notification',
30         'core/custom_interaction_events',
31         'core/modal',
32         'core/modal_registry',
33         'core/fragment',
34         ],
35         function(
36             $,
37             Ajax,
38             Str,
39             Notification,
40             CustomEvents,
41             Modal,
42             ModalRegistry,
43             Fragment
44         ) {
46     var registered = false;
47     var SELECTORS = {
48         SAVE_BUTTON: '[data-action="save"]',
49         CANCEL_BUTTON: '[data-action="cancel"]',
50         PROCESSOR: '[data-processor-name]',
51         PREFERENCE_ROW: '[data-region="preference-row"]',
52     };
54     /**
55      * Constructor for the Modal.
56      *
57      * @param {object} root The root jQuery element for the modal.
58      */
59     var NotificationProcessorSettings = function(root) {
60         Modal.call(this, root);
61         this.name = null;
62         this.userId = null;
63         this.contextId = null;
64         this.element = null;
65         this.saveButton = this.getFooter().find(SELECTORS.SAVE_BUTTON);
66         this.cancelButton = this.getFooter().find(SELECTORS.CANCEL_BUTTON);
67     };
69     NotificationProcessorSettings.TYPE = 'core_message-notification_processor_settings';
70     NotificationProcessorSettings.prototype = Object.create(Modal.prototype);
71     NotificationProcessorSettings.prototype.constructor = NotificationProcessorSettings;
73     /**
74      * Set the userid to the given value.
75      *
76      * @method setUserId
77      * @param {int} id The notification userid
78      */
79     NotificationProcessorSettings.prototype.setUserId = function(id) {
80         this.userId = id;
81     };
83     /**
84      * Retrieve the current userid, if any.
85      *
86      * @method getUserId
87      * @return {int|null} The notification userid
88      */
89     NotificationProcessorSettings.prototype.getUserId = function() {
90         return this.userId;
91     };
93     /**
94      * Set the object to the given value.
95      *
96      * @method setElement
97      * @param {object} element The notification node element.
98      */
99     NotificationProcessorSettings.prototype.setElement = function(element) {
100         this.element = element;
101     };
103     /**
104      * Retrieve the current element, if any.
105      *
106      * @method getElement
107      * @return {object|null} The notification node element.
108      */
109     NotificationProcessorSettings.prototype.getElement = function() {
110         return this.element;
111     };
113     /**
114      * Set the name to the given value.
115      *
116      * @method setName
117      * @param {string} name The notification name.
118      */
119     NotificationProcessorSettings.prototype.setName = function(name) {
120         this.name = name;
121     };
123     /**
124      * Retrieve the current name, if any.
125      *
126      * @method getName
127      * @return {string|null} The notification name.
128      */
129     NotificationProcessorSettings.prototype.getName = function() {
130         return this.name;
131     };
132     /**
133      * Set the context id to the given value.
134      *
135      * @method setContextId
136      * @param {Number} id The notification context id
137      */
138     NotificationProcessorSettings.prototype.setContextId = function(id) {
139         this.contextId = id;
140     };
142     /**
143      * Retrieve the current context id, if any.
144      *
145      * @method getContextId
146      * @return {Number|null} The notification context id
147      */
148     NotificationProcessorSettings.prototype.getContextId = function() {
149         return this.contextId;
150     };
152     /**
153      * Get the form element from the modal.
154      *
155      * @method getForm
156      * @return {object}
157      */
158     NotificationProcessorSettings.prototype.getForm = function() {
159         return this.getBody().find('form');
160     };
162     /**
163      * Disable the buttons in the footer.
164      *
165      * @method disableButtons
166      */
167     NotificationProcessorSettings.prototype.disableButtons = function() {
168         this.saveButton.prop('disabled', true);
169         this.cancelButton.prop('disabled', true);
170     };
172     /**
173      * Enable the buttons in the footer.
174      *
175      * @method enableButtons
176      */
177     NotificationProcessorSettings.prototype.enableButtons = function() {
178         this.saveButton.prop('disabled', false);
179         this.cancelButton.prop('disabled', false);
180     };
182     /**
183      * Load the title for the modal to the appropriate value
184      * depending on message outputs.
185      *
186      * @method loadTitleContent
187      * @return {object} A promise resolved with the new title text.
188      */
189     NotificationProcessorSettings.prototype.loadTitleContent = function() {
190         this.titlePromise = Str.get_string('processorsettings', 'message');
191         this.setTitle(this.titlePromise);
193         return this.titlePromise;
194     };
196     /**
197      * Load the body for the modal to the appropriate value
198      * depending on message outputs.
199      *
200      * @method loadBodyContent
201      * @return {object} A promise resolved with the fragment html and js from
202      */
203     NotificationProcessorSettings.prototype.loadBodyContent = function() {
204         this.disableButtons();
206         var args = {
207             userid: this.getUserId(),
208             type: this.getName(),
209         };
211         this.bodyPromise = Fragment.loadFragment('message', 'processor_settings', this.getContextId(), args);
212         this.setBody(this.bodyPromise);
214         this.bodyPromise.then(function() {
215             this.enableButtons();
216             return;
217         }.bind(this))
218         .fail(Notification.exception);
220         return this.bodyPromise;
221     };
223     /**
224      * Load both the title and body content.
225      *
226      * @method loadAllContent
227      * @return {object} promise
228      */
229     NotificationProcessorSettings.prototype.loadAllContent = function() {
230         return $.when(this.loadTitleContent(), this.loadBodyContent());
231     };
233     /**
234      * Load the modal content before showing it. This
235      * is to allow us to re-use the same modal for creating and
236      * editing different message outputs within the page.
237      *
238      * @method show
239      */
240     NotificationProcessorSettings.prototype.show = function() {
241         this.loadAllContent();
242         Modal.prototype.show.call(this);
243     };
245     /**
246      * Clear the notification from the modal when it's closed so
247      * that it is loaded fresh next time it's displayed.
248      *
249      * @method hide
250      */
251     NotificationProcessorSettings.prototype.hide = function() {
252         Modal.prototype.hide.call(this);
253         this.setContextId(null);
254         this.setName(null);
255         this.setUserId(null);
256     };
258     /**
259      * Checks if the processor has been configured. If so then remove the unconfigured
260      * status from the interface.
261      *
262      * @method updateConfiguredStatus
263      * @return {Promise|boolean}
264      */
265     NotificationProcessorSettings.prototype.updateConfiguredStatus = function() {
266         var processorHeader = $(this.getElement()).closest(SELECTORS.PROCESSOR);
268         if (!processorHeader.hasClass('unconfigured')) {
269             return false;
270         }
272         var processorName = processorHeader.attr('data-processor-name');
273         var request = {
274             methodname: 'core_message_get_message_processor',
275             args: {
276                 name: processorName,
277                 userid: this.userId,
278             },
279         };
281         return Ajax.call([request])[0]
282             .fail(Notification.exception)
283             .done(function(result) {
284                 // Check if the user has figured configuring the processor.
285                 if (result.userconfigured) {
286                     // If they have then we can enable the settings.
287                     var notifications = $(SELECTORS.PREFERENCE_ROW + ' [data-processor-name="' + processorName + '"]');
288                     processorHeader.removeClass('unconfigured');
289                     notifications.removeClass('disabled');
290                 }
291             });
292     };
294     /**
295      * Set up all of the event handling for the modal.
296      *
297      * @method registerEventListeners
298      */
299     NotificationProcessorSettings.prototype.registerEventListeners = function() {
300         // Apply parent event listeners.
301         Modal.prototype.registerEventListeners.call(this);
303         // When the user clicks the save button we trigger the form submission.
304         this.getModal().on(CustomEvents.events.activate, SELECTORS.SAVE_BUTTON, function(e, data) {
305             this.getForm().submit();
306             data.originalEvent.preventDefault();
307         }.bind(this));
309         this.getModal().on('mpp:formsubmitted', function(e) {
310             this.hide();
311             this.updateConfiguredStatus();
312             e.stopPropagation();
313         }.bind(this));
315         this.getModal().on(CustomEvents.events.activate, SELECTORS.CANCEL_BUTTON, function(e, data) {
316             this.hide();
317             data.originalEvent.preventDefault();
318             e.stopPropagation();
319         }.bind(this));
320     };
322     // Automatically register with the modal registry the first time this module is imported
323     // so that you can create modals
324     // of this type using the modal factory.
325     if (!registered) {
326         ModalRegistry.register(
327                                 NotificationProcessorSettings.TYPE,
328                                 NotificationProcessorSettings,
329                                 'core/modal_save_cancel');
330         registered = true;
331     }
333     return NotificationProcessorSettings;
334 });