weekly release 5.0dev
[moodle.git] / admin / tool / policy / amd / src / acceptmodal.js
blob1d6c564339e75ee0d5c5d3e8f90479e5a79bcbce
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.
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  * Add policy consent modal to the page
18  *
19  * @module     tool_policy/acceptmodal
20  * @copyright  2018 Marina Glancy
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
23 define([
24     'jquery',
25     'core/str',
26     'core/modal_save_cancel',
27     'core/modal_events',
28     'core/notification',
29     'core/fragment',
30     'core/ajax',
31     'core_form/changechecker',
32 ], function(
33     $,
34     Str,
35     ModalSaveCancel,
36     ModalEvents,
37     Notification,
38     Fragment,
39     Ajax,
40     FormChangeChecker
41 ) {
43         "use strict";
45         /**
46          * Constructor
47          *
48          * @param {int} contextid
49          *
50          * Each call to init gets it's own instance of this class.
51          */
52         var AcceptOnBehalf = function(contextid) {
53             this.contextid = contextid;
54             this.init();
55         };
57         /**
58          * @var {Modal} modal
59          * @private
60          */
61         AcceptOnBehalf.prototype.modal = null;
63         /**
64          * @var {int} contextid
65          * @private
66          */
67         AcceptOnBehalf.prototype.contextid = -1;
69         /**
70          * @var {object} currentTrigger The triggered HTML jQuery object
71          * @private
72          */
73         AcceptOnBehalf.prototype.currentTrigger = null;
75         /**
76          * @var {object} triggers The trigger selectors
77          * @private
78          */
79         AcceptOnBehalf.prototype.triggers = {
80             SINGLE: 'a[data-action=acceptmodal]',
81             BULK: 'input[data-action=acceptmodal]'
82         };
84         /**
85          * Initialise the class.
86          *
87          * @private
88          */
89         AcceptOnBehalf.prototype.init = function() {
90             // Initialise for links accepting policies for individual users.
91             $(this.triggers.SINGLE).on('click', function(e) {
92                 e.preventDefault();
93                 this.currentTrigger = $(e.currentTarget);
94                 var href = $(e.currentTarget).attr('href'),
95                     formData = href.slice(href.indexOf('?') + 1);
96                 this.showFormModal(formData);
97             }.bind(this));
99             // Initialise for multiple users acceptance form.
100             $(this.triggers.BULK).on('click', function(e) {
101                 e.preventDefault();
102                 this.currentTrigger = $(e.currentTarget);
103                 var form = $(e.currentTarget).closest('form');
104                 if (form.find('input[type=checkbox][name="userids[]"]:checked').length) {
105                     var formData = form.serialize();
106                     this.showFormModal(formData);
107                 } else {
108                     Str.get_strings([
109                         {key: 'notice'},
110                         {key: 'selectusersforconsent', component: 'tool_policy'},
111                         {key: 'ok'}
112                     ]).then(function(strings) {
113                         Notification.alert(strings[0], strings[1], strings[2]);
114                         return;
115                     }).fail(Notification.exception);
116                 }
117             }.bind(this));
118         };
120         /**
121          * Show modal with a form
122          *
123          * @param {String} formData
124          */
125         AcceptOnBehalf.prototype.showFormModal = function(formData) {
126             var action;
127             var params = formData.split('&');
128             for (var i = 0; i < params.length; i++) {
129                 var pair = params[i].split('=');
130                 if (pair[0] == 'action') {
131                     action = pair[1];
132                 }
133             }
134             // Fetch the title string.
135             Str.get_strings([
136                 {key: 'statusformtitleaccept', component: 'tool_policy'},
137                 {key: 'iagreetothepolicy', component: 'tool_policy'},
138                 {key: 'statusformtitlerevoke', component: 'tool_policy'},
139                 {key: 'irevokethepolicy', component: 'tool_policy'},
140                 {key: 'statusformtitledecline', component: 'tool_policy'},
141                 {key: 'declinethepolicy', component: 'tool_policy'}
142             ]).then(function(strings) {
143                 var title;
144                 var saveText;
145                 if (action == 'accept') {
146                     title = strings[0];
147                     saveText = strings[1];
148                 } else if (action == 'revoke') {
149                     title = strings[2];
150                     saveText = strings[3];
151                 } else if (action == 'decline') {
152                     title = strings[4];
153                     saveText = strings[5];
154                 }
155                 // Create the modal.
156                 return ModalSaveCancel.create({
157                     title: title,
158                     body: ''
159                 }).then(function(modal) {
160                     this.modal = modal;
161                     this.setupFormModal(formData, saveText);
162                 }.bind(this));
163             }.bind(this))
164                 .catch(Notification.exception);
165         };
167         /**
168          * Setup form inside a modal
169          *
170          * @param {String} formData
171          * @param {String} saveText
172          */
173         AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {
174             var modal = this.modal;
176             modal.setLarge();
178             modal.setSaveButtonText(saveText);
180             // We want to reset the form every time it is opened.
181             modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
183             modal.setBody(this.getBody(formData));
185             // We catch the modal save event, and use it to submit the form inside the modal.
186             // Triggering a form submission will give JS validation scripts a chance to check for errors.
187             modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
188             // We also catch the form submit event and use it to submit the form with ajax.
189             modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
191             modal.show();
192         };
194         /**
195          * Load the body of the modal (contains the form)
196          *
197          * @method getBody
198          * @private
199          * @param {String} formData
200          * @return {Promise}
201          */
202         AcceptOnBehalf.prototype.getBody = function(formData) {
203             if (typeof formData === "undefined") {
204                 formData = {};
205             }
206             // Get the content of the modal.
207             var params = {jsonformdata: JSON.stringify(formData)};
208             return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);
209         };
211         /**
212          * Submit the form inside the modal via AJAX request
213          *
214          * @method submitFormAjax
215          * @private
216          * @param {Event} e Form submission event.
217          */
218         AcceptOnBehalf.prototype.submitFormAjax = function(e) {
219             // We don't want to do a real form submission.
220             e.preventDefault();
222             // Convert all the form elements values to a serialised string.
223             var formData = this.modal.getRoot().find('form').serialize();
225             var requests = Ajax.call([{
226                 methodname: 'tool_policy_submit_accept_on_behalf',
227                 args: {jsonformdata: JSON.stringify(formData)}
228             }]);
229             requests[0].done(function(data) {
230                 if (data.validationerrors) {
231                     this.modal.setBody(this.getBody(formData));
232                 } else {
233                     this.close();
234                 }
235             }.bind(this)).fail(Notification.exception);
236         };
238         /**
239          * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
240          *
241          * @method submitForm
242          * @param {Event} e Form submission event.
243          * @private
244          */
245         AcceptOnBehalf.prototype.submitForm = function(e) {
246             e.preventDefault();
247             this.modal.getRoot().find('form').submit();
248         };
250         /**
251          * Close the modal
252          */
253         AcceptOnBehalf.prototype.close = function() {
254             this.destroy();
255             document.location.reload();
256         };
258         /**
259          * Destroy the modal
260          */
261         AcceptOnBehalf.prototype.destroy = function() {
262             FormChangeChecker.resetAllFormDirtyStates();
263             this.modal.destroy();
264             this.currentTrigger.focus();
265         };
267         return /** @alias module:tool_policy/acceptmodal */ {
268             // Public variables and functions.
269             /**
270              * Attach event listeners to initialise this module.
271              *
272              * @method init
273              * @param {int} contextid The contextid for the course.
274              * @return {AcceptOnBehalf}
275              */
276             getInstance: function(contextid) {
277                 return new AcceptOnBehalf(contextid);
278             }
279         };
280     });