MDL-61864 tool_policy: user agreement reports
[moodle.git] / admin / tool / policy / amd / src / acceptmodal.js
blobd7ff943c252a8e4115d38820c7f6611905be0428
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  * @class      AcceptOnBehalf
21  * @package    tool_policy
22  * @copyright  2018 Marina Glancy
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
25 define(['jquery', 'core/str', 'core/modal_factory', 'core/modal_events', 'core/notification', 'core/fragment',
26         'core/ajax', 'core/yui'],
27     function($, Str, ModalFactory, ModalEvents, Notification, Fragment, Ajax, Y) {
29         "use strict";
31         /**
32          * Constructor
33          *
34          * @param {int} contextid
35          *
36          * Each call to init gets it's own instance of this class.
37          */
38         var AcceptOnBehalf = function(contextid) {
39             this.contextid = contextid;
40             this.init();
41         };
43         /**
44          * @var {Modal} modal
45          * @private
46          */
47         AcceptOnBehalf.prototype.modal = null;
49         /**
50          * @var {int} contextid
51          * @private
52          */
53         AcceptOnBehalf.prototype.contextid = -1;
55         /**
56          * @var {Array} strings
57          * @private
58          */
59         AcceptOnBehalf.prototype.stringKeys = [
60             {
61                 key: 'consentdetails',
62                 component: 'tool_policy'
63             },
64             {
65                 key: 'iagreetothepolicy',
66                 component: 'tool_policy'
67             },
68             {
69                 key: 'selectusersforconsent',
70                 component: 'tool_policy'
71             },
72             {
73                 key: 'ok'
74             }
75         ];
77         /**
78          * Initialise the class.
79          *
80          * @private
81          */
82         AcceptOnBehalf.prototype.init = function() {
83             // Initialise for links accepting policies for individual users.
84             var triggers = $('a[data-action=acceptmodal]');
85             triggers.on('click', function(e) {
86                 e.preventDefault();
87                 var href = $(e.currentTarget).attr('href'),
88                     formData = href.slice(href.indexOf('?') + 1);
89                 this.showFormModal(formData);
90             }.bind(this));
92             // Initialise for multiple users acceptance form.
93             triggers = $('form[data-action=acceptmodal]');
94             triggers.on('submit', function(e) {
95                 e.preventDefault();
96                 if ($(e.currentTarget).find('input[type=checkbox][name="userids[]"]:checked').length) {
97                     var formData = $(e.currentTarget).serialize();
98                     this.showFormModal(formData, triggers);
99                 } else {
100                     Str.get_strings(this.stringKeys).done(function (strings) {
101                         Notification.alert('', strings[2], strings[3]);
102                     });
103                 }
104             }.bind(this));
105         };
107         /**
108          * Show modal with a form
109          *
110          * @param {String} formData
111          * @param {object} triggerElement The trigger HTML jQuery object
112          */
113         AcceptOnBehalf.prototype.showFormModal = function(formData, triggerElement) {
114             // Fetch the title string.
115             Str.get_strings(this.stringKeys).done(function(strings) {
116                 // Create the modal.
117                 ModalFactory.create({
118                     type: ModalFactory.types.SAVE_CANCEL,
119                     title: strings[0],
120                     body: ''
121                 }, triggerElement).done(function(modal) {
122                     this.modal = modal;
123                     this.setupFormModal(formData, strings[1]);
124                 }.bind(this));
125             }.bind(this))
126                 .fail(Notification.exception);
127         };
129         /**
130          * Setup form inside a modal
131          *
132          * @param {String} formData
133          * @param {String} saveText
134          */
135         AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {
136             var modal = this.modal;
138             modal.setLarge();
140             modal.setSaveButtonText(saveText);
142             // We want to reset the form every time it is opened.
143             modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
145             modal.setBody(this.getBody(formData));
147             // We catch the modal save event, and use it to submit the form inside the modal.
148             // Triggering a form submission will give JS validation scripts a chance to check for errors.
149             modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
150             // We also catch the form submit event and use it to submit the form with ajax.
151             modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
153             modal.show();
154         };
156         /**
157          * Load the body of the modal (contains the form)
158          *
159          * @method getBody
160          * @private
161          * @param {String} formData
162          * @return {Promise}
163          */
164         AcceptOnBehalf.prototype.getBody = function(formData) {
165             if (typeof formData === "undefined") {
166                 formData = {};
167             }
168             // Get the content of the modal.
169             var params = {jsonformdata: JSON.stringify(formData)};
170             return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);
171         };
173         /**
174          * Submit the form inside the modal via AJAX request
175          *
176          * @method submitFormAjax
177          * @private
178          * @param {Event} e Form submission event.
179          */
180         AcceptOnBehalf.prototype.submitFormAjax = function(e) {
181             // We don't want to do a real form submission.
182             e.preventDefault();
184             // Convert all the form elements values to a serialised string.
185             var formData = this.modal.getRoot().find('form').serialize();
187             var requests = Ajax.call([{
188                 methodname: 'tool_policy_submit_accept_on_behalf',
189                 args: {jsonformdata: JSON.stringify(formData)}
190             }]);
191             requests[0].done(function(data) {
192                 if (data.validationerrors) {
193                     this.modal.setBody(this.getBody(formData));
194                 } else {
195                     this.close();
196                 }
197             }.bind(this)).fail(Notification.exception);
198         };
200         /**
201          * This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
202          *
203          * @method submitForm
204          * @param {Event} e Form submission event.
205          * @private
206          */
207         AcceptOnBehalf.prototype.submitForm = function(e) {
208             e.preventDefault();
209             this.modal.getRoot().find('form').submit();
210         };
212         /**
213          * Close the modal
214          */
215         AcceptOnBehalf.prototype.close = function() {
216             this.destroy();
217             document.location.reload();
218         };
220         /**
221          * Destroy the modal
222          */
223         AcceptOnBehalf.prototype.destroy = function() {
224             Y.use('moodle-core-formchangechecker', function() {
225                 M.core_formchangechecker.reset_form_dirty_state();
226             });
227             this.modal.destroy();
228         };
230         return /** @alias module:tool_policy/acceptmodal */ {
231             // Public variables and functions.
232             /**
233              * Attach event listeners to initialise this module.
234              *
235              * @method init
236              * @param {string} selector The CSS selector used to find nodes that will trigger this module.
237              * @param {int} contextid The contextid for the course.
238              * @return {Promise}
239              */
240             getInstance: function(contextid) {
241                 new AcceptOnBehalf(contextid);
242             }
243         };
244     });