Merge branch 'MDL-68963-master' of git://github.com/bmbrands/moodle
[moodle.git] / enrol / manual / amd / src / quickenrolment.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  * Quick enrolment AMD module.
18  *
19  * @module     enrol_manual/quickenrolment
20  * @copyright  2016 Damyon Wiese <damyon@moodle.com>
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
23 import * as DynamicTable from 'core_table/dynamic';
24 import * as Str from 'core/str';
25 import * as Toast from 'core/toast';
26 import Config from 'core/config';
27 import Fragment from 'core/fragment';
28 import ModalEvents from 'core/modal_events';
29 import ModalFactory from 'core/modal_factory';
30 import Notification from 'core/notification';
31 import jQuery from 'jquery';
32 import Prefetch from 'core/prefetch';
34 const Selectors = {
35     cohortSelector: "#id_cohortlist",
36     triggerButtons: ".enrolusersbutton.enrol_manual_plugin [type='submit']",
37     unwantedHiddenFields: "input[value='_qf__force_multiselect_submission']",
38     buttonWrapper: '[data-region="wrapper"]',
39 };
41 /**
42  * Get the content of the body for the specified context.
43  *
44  * @param {Number} contextId
45  * @returns {Promise}
46  */
47 const getBodyForContext = contextId => {
48     return Fragment.loadFragment('enrol_manual', 'enrol_users_form', contextId, {});
49 };
51 /**
52  * Get the dynamic table for the button.
53  *
54  * @param {HTMLElement} element
55  * @returns {HTMLElement}
56  */
57 const getDynamicTableForElement = element => {
58     const wrapper = element.closest(Selectors.buttonWrapper);
60     return DynamicTable.getTableFromId(wrapper.dataset.tableUniqueid);
61 };
63 /**
64  * Register the event listeners for this contextid.
65  *
66  * @param {Number} contextId
67  */
68 const registerEventListeners = contextId => {
69     document.addEventListener('click', e => {
70         if (e.target.closest(Selectors.triggerButtons)) {
71             e.preventDefault();
73             showModal(getDynamicTableForElement(e.target), contextId);
75             return;
76         }
77     });
78 };
80 /**
81  * Display the modal for this contextId.
82  *
83  * @param {HTMLElement} dynamicTable The table to beb refreshed when changes are made
84  * @param {Number} contextId
85  * @returns {Promise}
86  */
87 const showModal = (dynamicTable, contextId) => {
88     return ModalFactory.create({
89         type: ModalFactory.types.SAVE_CANCEL,
90         large: true,
91         title: Str.get_string('enrolusers', 'enrol_manual'),
92         body: getBodyForContext(contextId),
93     })
94     .then(modal => {
95         modal.getRoot().on(ModalEvents.save, e => {
96             // Trigger a form submission, so that any mform elements can do final tricks before the form submission
97             // is processed.
98             // The actual submit even tis captured in the next handler.
100             e.preventDefault();
101             modal.getRoot().find('form').submit();
102         });
104         modal.getRoot().on('submit', 'form', e => {
105             e.preventDefault();
107             submitFormAjax(dynamicTable, modal);
108         });
110         modal.getRoot().on(ModalEvents.hidden, () => {
111             modal.destroy();
112         });
114         return modal;
115     })
116     .then(modal => {
117         modal.show();
119         return modal;
120     })
121     .then(modal => {
122         modal.setSaveButtonText(Str.get_string('enrolusers', 'enrol_manual'));
124         modal.getBodyPromise().then(body => {
125             if (body.get(0).querySelector(Selectors.cohortSelector)) {
126                 modal.setSaveButtonText(Str.get_string('enroluserscohorts', 'enrol_manual'));
127             }
129             return body;
130         })
131         .catch();
133         return modal;
134     })
135     .catch(Notification.exception);
136 };
138 /**
139  * Submit the form via ajax.
140  *
141  * @param {HTMLElement} dynamicTable
142  * @param {Object} modal
143  */
144 const submitFormAjax = (dynamicTable, modal) => {
145     // Note: We use a jQuery object here so that we can use its serialize functionality.
146     const form = modal.getRoot().find('form');
148     // Before send the data through AJAX, we need to parse and remove some unwanted hidden fields.
149     // This hidden fields are added automatically by mforms and when it reaches the AJAX we get an error.
150     form.get(0).querySelectorAll(Selectors.unwantedHiddenFields).forEach(hiddenField => hiddenField.remove());
152     modal.hide();
153     modal.destroy();
155     jQuery.ajax(
156         `${Config.wwwroot}/enrol/manual/ajax.php?${form.serialize()}`,
157         {
158             type: 'GET',
159             processData: false,
160             contentType: "application/json",
161         }
162     )
163     .then(response => {
164         if (response.error) {
165             throw new Error(response.error);
166         }
168         return response.count;
169     })
170     .then(count => {
171         return Promise.all([
172             Str.get_string('totalenrolledusers', 'enrol', count),
173             DynamicTable.refreshTableContent(dynamicTable),
174         ]);
175     })
176     .then(([notificationBody]) => notificationBody)
177     .then(notificationBody => Toast.add(notificationBody))
178     .catch(error => {
179         Notification.addNotification({
180             message: error.message,
181             type: 'error',
182         });
183     });
184 };
186 /**
187  * Set up quick enrolment for the manual enrolment plugin.
188  *
189  * @param {Number} contextid The context id to setup for
190  */
191 export const init = ({contextid}) => {
192     registerEventListeners(contextid);
194     Prefetch.prefetchStrings('enrol_manual', [
195         'enrolusers',
196         'enroluserscohorts',
197     ]);
199     Prefetch.prefetchString('enrol', 'totalenrolledusers');
200 };