Merge branch 'MDL-68977-master' of git://github.com/andrewnicols/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 Pending from 'core/pending';
33 import Prefetch from 'core/prefetch';
35 const Selectors = {
36     cohortSelector: "#id_cohortlist",
37     triggerButtons: ".enrolusersbutton.enrol_manual_plugin [type='submit']",
38     unwantedHiddenFields: "input[value='_qf__force_multiselect_submission']",
39     buttonWrapper: '[data-region="wrapper"]',
40 };
42 /**
43  * Get the content of the body for the specified context.
44  *
45  * @param {Number} contextId
46  * @returns {Promise}
47  */
48 const getBodyForContext = contextId => {
49     return Fragment.loadFragment('enrol_manual', 'enrol_users_form', contextId, {});
50 };
52 /**
53  * Get the dynamic table for the button.
54  *
55  * @param {HTMLElement} element
56  * @returns {HTMLElement}
57  */
58 const getDynamicTableForElement = element => {
59     const wrapper = element.closest(Selectors.buttonWrapper);
61     return DynamicTable.getTableFromId(wrapper.dataset.tableUniqueid);
62 };
64 /**
65  * Register the event listeners for this contextid.
66  *
67  * @param {Number} contextId
68  */
69 const registerEventListeners = contextId => {
70     document.addEventListener('click', e => {
71         if (e.target.closest(Selectors.triggerButtons)) {
72             e.preventDefault();
74             showModal(getDynamicTableForElement(e.target), contextId);
76             return;
77         }
78     });
79 };
81 /**
82  * Display the modal for this contextId.
83  *
84  * @param {HTMLElement} dynamicTable The table to beb refreshed when changes are made
85  * @param {Number} contextId
86  * @returns {Promise}
87  */
88 const showModal = (dynamicTable, contextId) => {
89     const pendingPromise = new Pending('enrol_manual/quickenrolment:showModal');
91     return ModalFactory.create({
92         type: ModalFactory.types.SAVE_CANCEL,
93         large: true,
94         title: Str.get_string('enrolusers', 'enrol_manual'),
95         body: getBodyForContext(contextId),
96     })
97     .then(modal => {
98         modal.getRoot().on(ModalEvents.save, e => {
99             // Trigger a form submission, so that any mform elements can do final tricks before the form submission
100             // is processed.
101             // The actual submit even tis captured in the next handler.
103             e.preventDefault();
104             modal.getRoot().find('form').submit();
105         });
107         modal.getRoot().on('submit', 'form', e => {
108             e.preventDefault();
110             submitFormAjax(dynamicTable, modal);
111         });
113         modal.getRoot().on(ModalEvents.hidden, () => {
114             modal.destroy();
115         });
117         return modal;
118     })
119     .then(modal => {
120         modal.show();
122         return modal;
123     })
124     .then(modal => {
125         modal.setSaveButtonText(Str.get_string('enrolusers', 'enrol_manual'));
127         modal.getBodyPromise().then(body => {
128             if (body.get(0).querySelector(Selectors.cohortSelector)) {
129                 modal.setSaveButtonText(Str.get_string('enroluserscohorts', 'enrol_manual'));
130             }
132             return body;
133         })
134         .catch();
136         pendingPromise.resolve();
138         return modal;
139     })
140     .catch(Notification.exception);
141 };
143 /**
144  * Submit the form via ajax.
145  *
146  * @param {HTMLElement} dynamicTable
147  * @param {Object} modal
148  */
149 const submitFormAjax = (dynamicTable, modal) => {
150     // Note: We use a jQuery object here so that we can use its serialize functionality.
151     const form = modal.getRoot().find('form');
153     // Before send the data through AJAX, we need to parse and remove some unwanted hidden fields.
154     // This hidden fields are added automatically by mforms and when it reaches the AJAX we get an error.
155     form.get(0).querySelectorAll(Selectors.unwantedHiddenFields).forEach(hiddenField => hiddenField.remove());
157     modal.hide();
158     modal.destroy();
160     jQuery.ajax(
161         `${Config.wwwroot}/enrol/manual/ajax.php?${form.serialize()}`,
162         {
163             type: 'GET',
164             processData: false,
165             contentType: "application/json",
166         }
167     )
168     .then(response => {
169         if (response.error) {
170             throw new Error(response.error);
171         }
173         return response.count;
174     })
175     .then(count => {
176         return Promise.all([
177             Str.get_string('totalenrolledusers', 'enrol', count),
178             DynamicTable.refreshTableContent(dynamicTable),
179         ]);
180     })
181     .then(([notificationBody]) => notificationBody)
182     .then(notificationBody => Toast.add(notificationBody))
183     .catch(error => {
184         Notification.addNotification({
185             message: error.message,
186             type: 'error',
187         });
188     });
189 };
191 /**
192  * Set up quick enrolment for the manual enrolment plugin.
193  *
194  * @param {Number} contextid The context id to setup for
195  */
196 export const init = ({contextid}) => {
197     registerEventListeners(contextid);
199     Prefetch.prefetchStrings('enrol_manual', [
200         'enrolusers',
201         'enroluserscohorts',
202     ]);
204     Prefetch.prefetchString('enrol', 'totalenrolledusers');
205 };