MDL-59756 user: Add edit enrolment button in enrol details modal
[moodle.git] / user / amd / src / status_field.js
CommitLineData
80d13bfe
JP
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/>.
15
16/**
17 * AMD module for the user enrolment status field in the course participants page.
18 *
19 * @module core_user/status_field
20 * @copyright 2017 Jun Pataleta
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 */
23define(['core/templates',
24 'jquery',
25 'core/str',
26 'core/config',
27 'core/notification',
28 'core/modal_factory',
29 'core/modal_events',
30 'core/fragment',
31 'core/ajax'
32 ],
33 function(Template, $, Str, Config, Notification, ModalFactory, ModalEvents, Fragment, Ajax) {
34
35 /**
36 * Action selectors.
37 *
38 * @access private
39 * @type {{EDIT_ENROLMENT: string, SHOW_DETAILS: string, UNENROL: string}}
40 */
41 var SELECTORS = {
42 EDIT_ENROLMENT: '[data-action="editenrolment"]',
43 SHOW_DETAILS: '[data-action="showdetails"]',
44 UNENROL: '[data-action="unenrol"]'
45 };
46
47 /**
48 * Constructor
49 *
50 * @param {Object} options Object containing options. The only valid option at this time is contextid.
51 * Each call to templates.render gets it's own instance of this class.
52 */
53 var StatusFieldActions = function(options) {
54 this.contextid = options.contextid;
55 this.courseid = options.courseid;
56
57 // Bind click event to editenrol buttons.
58 this.bindEditEnrol();
59
60 // Bind click event to unenrol buttons.
61 this.bindUnenrol();
62
63 // Bind click event to status details buttons.
64 this.bindStatusDetails();
65 };
66 // Class variables and functions.
67
68 /** @var {number} courseid The course ID. */
69 StatusFieldActions.prototype.courseid = 0;
70
71 /**
72 * Private method
73 *
74 * @method initModal
75 * @private
76 */
77 StatusFieldActions.prototype.bindEditEnrol = function() {
78 var statusFieldInstsance = this;
79
80 $(SELECTORS.EDIT_ENROLMENT).click(function(e) {
81 e.preventDefault();
82
83 // The particular edit button that was clicked.
84 var clickedEditTrigger = $(this);
85 // Get the parent container (it contains the data attributes associated with the status field).
86 var parentContainer = clickedEditTrigger.parent();
87 // Get the name of the user whose enrolment status is being edited.
88 var fullname = parentContainer.data('fullname');
89 // Get the user enrolment ID.
90 var ueid = clickedEditTrigger.attr('rel');
91
92 $.when(Str.get_string('edituserenrolment', 'enrol', fullname)).then(function(modalTitle) {
93 return ModalFactory.create({
94 large: true,
95 title: modalTitle,
96 type: ModalFactory.types.SAVE_CANCEL
97 });
98 }).done(function(modal) {
99 // Handle save event.
100 modal.getRoot().on(ModalEvents.save, function(e) {
101 // Don't close the modal yet.
102 e.preventDefault();
103 // Submit form data.
104 statusFieldInstsance.submitEditFormAjax(modal);
105 });
106
107 // Handle hidden event.
108 modal.getRoot().on(ModalEvents.hidden, function() {
109 // Destroy when hidden.
110 modal.destroy();
111 });
112
113 // Set the modal body.
114 modal.setBody(statusFieldInstsance.getBody(ueid));
115
116 // Show the modal!
117 modal.show();
118 }).fail(Notification.exception);
119 });
120 };
121
122 /**
123 * Private method
124 *
125 * @method bindUnenrol
126 * @private
127 */
128 StatusFieldActions.prototype.bindUnenrol = function() {
129 $(SELECTORS.UNENROL).click(function(e) {
130 e.preventDefault();
131 var unenrolLink = $(this);
132 var parentContainer = unenrolLink.parent();
133 var strings = [
134 {
135 key: 'unenrol',
136 component: 'enrol'
137 },
138 {
139 key: 'unenrolconfirm',
140 component: 'enrol',
141 param: {
142 user: parentContainer.data('fullname'),
143 course: parentContainer.data('coursename')
144 }
145 }
146 ];
147
148 $.when(Str.get_strings(strings)).then(function(results) {
149 var title = results[0];
150 var confirmMessage = results[1];
151 return ModalFactory.create({
152 body: confirmMessage,
153 large: true,
154 title: title,
155 type: ModalFactory.types.CONFIRM
156 });
157 }).done(function(modal) {
158 // Handle confirm event.
159 modal.getRoot().on(ModalEvents.yes, function() {
160 // Build params.
161 var unenrolParams = {
162 confirm: 1,
163 sesskey: Config.sesskey,
164 ue: $(unenrolLink).attr('rel')
165 };
166 // Send data to unenrol page (which will redirect back to the participants page after unenrol).
167 window.location.href = Config.wwwroot + '/enrol/unenroluser.php?' + $.param(unenrolParams);
168 });
169
170 // Handle hidden event.
171 modal.getRoot().on(ModalEvents.hidden, function() {
172 // Destroy when hidden.
173 modal.destroy();
174 });
175
176 // Display the delete confirmation modal.
177 modal.show();
178 }).fail(Notification.exception);
179 });
180 };
181
182 /**
183 * Private method
184 *
185 * @method bindStatusDetails
186 * @private
187 */
188 StatusFieldActions.prototype.bindStatusDetails = function() {
189 $(SELECTORS.SHOW_DETAILS).click(function(e) {
190 e.preventDefault();
191
192 var detailsButton = $(this);
193 var parentContainer = detailsButton.parent();
194 var context = {
195 "fullname": parentContainer.data('fullname'),
196 "coursename": parentContainer.data('coursename'),
197 "enrolinstancename": parentContainer.data('enrolinstancename'),
198 "status": parentContainer.data('status'),
4544451a 199 "statusclass": parentContainer.find('span').attr('class'),
80d13bfe
JP
200 "timestart": parentContainer.data('timestart'),
201 "timeend": parentContainer.data('timeend')
202 };
203
5982da53
JP
204 // Get default string for the modal and modal type.
205 var strings = [
206 {
207 key: 'enroldetails',
208 component: 'enrol'
209 }
210 ];
211 var modalType = ModalFactory.types.CANCEL;
212
213 // Find the edit enrolment link.
214 var editEnrolLink = detailsButton.next(SELECTORS.EDIT_ENROLMENT);
215 if (editEnrolLink.length) {
216 // If there's an edit enrolment link for this user, use a SAVE_CANCEL type of modal.
217 strings.push({key: 'editenrolment', component: 'enrol'});
218 modalType = ModalFactory.types.SAVE_CANCEL;
219 }
220
221 var modalStringsPromise = Str.get_strings(strings);
222 var modalPromise = ModalFactory.create({large: true, type: modalType});
223 $.when(modalStringsPromise, modalPromise).done(function(strings, modal) {
80d13bfe 224 var modalBodyPromise = Template.render('core_user/status_details', context);
5982da53 225 modal.setTitle(strings[0]);
80d13bfe 226 modal.setBody(modalBodyPromise);
5982da53
JP
227
228 if (modalType === ModalFactory.types.SAVE_CANCEL) {
229 // Set the edit enrolment button text.
230 modal.setSaveButtonText(strings[1]);
231 // Handle event when the "Edit enrolment" button is clicked.
232 modal.getRoot().on(ModalEvents.save, function() {
233 // Trigger click event for the edit enrolment link to show the edit enrolment modal.
234 $(editEnrolLink).trigger('click');
235 });
236 }
237
80d13bfe
JP
238 modal.show();
239
240 // Handle hidden event.
241 modal.getRoot().on(ModalEvents.hidden, function() {
242 // Destroy when hidden.
243 modal.destroy();
244 });
245 }).fail(Notification.exception);
246 });
247 };
248
249 /**
250 * Private method
251 *
252 * @method submitEditFormAjax
253 * @param {Object} modal The the AMD modal object containing the form.
254 * @private
255 */
256 StatusFieldActions.prototype.submitEditFormAjax = function(modal) {
257 var statusFieldInstsance = this;
258 var form = modal.getRoot().find('form');
259
260 // User enrolment ID.
261 var ueid = $(form).find('[name="ue"]').val();
262 // Status.
263 var status = $(form).find('[name="status"]').val();
264
265 var params = {
266 'courseid': this.courseid,
267 'ueid': ueid,
268 'status': status
269 };
270
271 // Enrol time start.
272 var timeStartEnabled = $(form).find('[name="timestart[enabled]"]');
273 if (timeStartEnabled.is(':checked')) {
274 var timeStartYear = $(form).find('[name="timestart[year]"]').val();
275 var timeStartMonth = $(form).find('[name="timestart[month]"]').val() - 1;
276 var timeStartDay = $(form).find('[name="timestart[day]"]').val();
277 var timeStartHour = $(form).find('[name="timestart[hour]"]').val();
278 var timeStartMinute = $(form).find('[name="timestart[minute]"]').val();
279 var timeStart = new Date(timeStartYear, timeStartMonth, timeStartDay, timeStartHour, timeStartMinute);
280 params.timestart = timeStart.getTime() / 1000;
281 }
282
283 // Enrol time end.
284 var timeEndEnabled = $(form).find('[name="timeend[enabled]"]');
285 if (timeEndEnabled.is(':checked')) {
286 var timeEndYear = $(form).find('[name="timeend[year]"]').val();
287 var timeEndMonth = $(form).find('[name="timeend[month]"]').val() - 1;
288 var timeEndDay = $(form).find('[name="timeend[day]"]').val();
289 var timeEndHour = $(form).find('[name="timeend[hour]"]').val();
290 var timeEndMinute = $(form).find('[name="timeend[minute]"]').val();
291 var timeEnd = new Date(timeEndYear, timeEndMonth, timeEndDay, timeEndHour, timeEndMinute);
292 params.timeend = timeEnd.getTime() / 1000;
293 }
294
295 var request = {
296 methodname: 'core_enrol_edit_user_enrolment',
297 args: params
298 };
299
300 Ajax.call([request])[0].done(function(data) {
301 if (data.result) {
302 // Dismiss the modal.
303 modal.hide();
304
305 // Reload the page, don't show changed data warnings.
306 if (typeof window.M.core_formchangechecker !== "undefined") {
307 window.M.core_formchangechecker.reset_form_dirty_state();
308 }
309 window.location.reload();
310
311 } else {
312 // Serialise the form data and reload the form fragment to show validation errors.
313 var formData = JSON.stringify(form.serialize());
314 modal.setBody(statusFieldInstsance.getBody(ueid, formData));
315 }
316 }).fail(Notification.exception);
317 };
318
319 /**
320 * Private method
321 *
322 * @method getBody
323 * @private
324 * @param {Number} ueid The user enrolment ID associated with the user.
325 * @param {string} formData Serialized string of the edit enrolment form data.
326 * @return {Promise}
327 */
328 StatusFieldActions.prototype.getBody = function(ueid, formData) {
329 var params = {
330 'ueid': ueid
331 };
332 if (typeof formData !== 'undefined') {
333 params.formdata = formData;
334 }
335 return Fragment.loadFragment('enrol', 'user_enrolment_form', this.contextid, params).fail(Notification.exception);
336 };
337
338 return /** @alias module:core_user/editenrolment */ {
339 // Public variables and functions.
340 /**
341 * Every call to init creates a new instance of the class with it's own event listeners etc.
342 *
343 * @method init
344 * @public
345 * @param {object} config - config variables for the module.
346 */
347 init: function(config) {
348 (new StatusFieldActions(config));
349 }
350 };
351 });