Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 */
23
 
24
import * as DynamicTable from 'core_table/dynamic';
25
import * as Repository from './repository';
26
import * as Str from 'core/str';
27
import DynamicTableSelectors from 'core_table/local/dynamic/selectors';
28
import Fragment from 'core/fragment';
29
import ModalEvents from 'core/modal_events';
30
import Notification from 'core/notification';
31
import Templates from 'core/templates';
32
import {add as notifyUser} from 'core/toast';
33
import SaveCancelModal from 'core/modal_save_cancel';
34
import CancelModal from 'core/modal_cancel';
35
 
36
const Selectors = {
37
    editEnrolment: '[data-action="editenrolment"]',
38
    showDetails: '[data-action="showdetails"]',
39
    unenrol: '[data-action="unenrol"]',
40
    statusElement: '[data-status]',
41
};
42
 
43
/**
44
 * Get the dynamic table from the specified link.
45
 *
46
 * @param {HTMLElement} link
47
 * @returns {HTMLElement}
48
 */
49
const getDynamicTableFromLink = link => link.closest(DynamicTableSelectors.main.region);
50
 
51
/**
52
 * Get the status container from the specified link.
53
 *
54
 * @param {HTMLElement} link
55
 * @returns {HTMLElement}
56
 */
57
const getStatusContainer = link => link.closest(Selectors.statusElement);
58
 
59
/**
60
 * Get user enrolment id from the specified link
61
 *
62
 * @param {HTMLElement} link
63
 * @returns {Number}
64
 */
65
const getUserEnrolmentIdFromLink = link => link.getAttribute('rel');
66
 
67
/**
68
 * Register all event listeners for the status fields.
69
 *
70
 * @param {Number} contextId
71
 * @param {Number} uniqueId
72
 */
73
const registerEventListeners = (contextId, uniqueId) => {
74
    const getBodyFunction = (userEnrolmentId, formData) => getBody(contextId, userEnrolmentId, formData);
75
 
76
    document.addEventListener('click', e => {
77
        const tableRoot = e.target.closest(DynamicTableSelectors.main.fromRegionId(uniqueId));
78
        if (!tableRoot) {
79
            return;
80
        }
81
 
82
        const editLink = e.target.closest(Selectors.editEnrolment);
83
        if (editLink) {
84
            e.preventDefault();
85
 
86
            showEditDialogue(editLink, getBodyFunction);
87
        }
88
 
89
        const unenrolLink = e.target.closest(Selectors.unenrol);
90
        if (unenrolLink) {
91
            e.preventDefault();
92
 
93
            showUnenrolConfirmation(unenrolLink);
94
        }
95
 
96
        const showDetailsLink = e.target.closest(Selectors.showDetails);
97
        if (showDetailsLink) {
98
            e.preventDefault();
99
 
100
            showStatusDetails(showDetailsLink);
101
        }
102
    });
103
};
104
 
105
/**
106
 * Show the edit dialogue.
107
 *
108
 * @param {HTMLElement} link
109
 * @param {Function} getBody Function to get the body for the specified user enrolment
110
 */
111
const showEditDialogue = (link, getBody) => {
112
    const container = getStatusContainer(link);
113
    const userEnrolmentId = getUserEnrolmentIdFromLink(link);
114
 
115
    SaveCancelModal.create({
116
        large: true,
117
        title: Str.get_string('edituserenrolment', 'enrol', container.dataset.fullname),
118
        body: getBody(userEnrolmentId)
119
    })
120
    .then(modal => {
121
        // Handle save event.
122
        modal.getRoot().on(ModalEvents.save, e => {
123
            // Don't close the modal yet.
124
            e.preventDefault();
125
 
126
            // Submit form data.
127
            submitEditFormAjax(link, getBody, modal, userEnrolmentId, container.dataset);
128
        });
129
 
130
        // Handle hidden event.
131
        modal.getRoot().on(ModalEvents.hidden, () => {
132
            // Destroy when hidden.
133
            modal.destroy();
134
        });
135
 
136
        // Show the modal.
137
        modal.show();
138
 
139
        return modal;
140
    })
141
    .catch(Notification.exception);
142
};
143
 
144
/**
145
 * Show and handle the unenrolment confirmation dialogue.
146
 *
147
 * @param {HTMLElement} link
148
 */
149
const showUnenrolConfirmation = link => {
150
    const container = getStatusContainer(link);
151
    const userEnrolmentId = getUserEnrolmentIdFromLink(link);
152
 
153
    SaveCancelModal.create()
154
    .then(modal => {
155
        // Handle confirm event.
156
        modal.getRoot().on(ModalEvents.save, e => {
157
            // Don't close the modal yet.
158
            e.preventDefault();
159
 
160
            // Submit data.
161
            submitUnenrolFormAjax(
162
                link,
163
                modal,
164
                {
165
                    ueid: userEnrolmentId,
166
                },
167
                container.dataset
168
            );
169
        });
170
 
171
        // Handle hidden event.
172
        modal.getRoot().on(ModalEvents.hidden, () => {
173
            // Destroy when hidden.
174
            modal.destroy();
175
        });
176
 
177
        // Display the delete confirmation modal.
178
        modal.show();
179
 
180
        const stringData = [
181
            {
182
                key: 'unenrol',
183
                component: 'enrol',
184
            },
185
            {
186
                key: 'unenrolconfirm',
187
                component: 'enrol',
188
                param: {
189
                    user: container.dataset.fullname,
190
                    course: container.dataset.coursename,
191
                    enrolinstancename: container.dataset.enrolinstancename,
192
                }
193
            }
194
        ];
195
 
196
        return Promise.all([Str.get_strings(stringData), modal]);
197
    })
198
    .then(([strings, modal]) => {
199
        modal.setTitle(strings[0]);
200
        modal.setSaveButtonText(strings[0]);
201
        modal.setBody(strings[1]);
202
 
203
        return modal;
204
    })
205
    .catch(Notification.exception);
206
};
207
 
208
/**
209
 * Show the user details dialogue.
210
 *
211
 * @param {HTMLElement} link
212
 */
213
const showStatusDetails = link => {
214
    const container = getStatusContainer(link);
215
 
216
    const context = {
217
        editenrollink: '',
218
        statusclass: container.querySelector('span.badge').getAttribute('class'),
219
        ...container.dataset,
220
    };
221
 
222
    // Find the edit enrolment link.
223
    const editEnrolLink = container.querySelector(Selectors.editEnrolment);
224
    if (editEnrolLink) {
225
        // If there's an edit enrolment link for this user, clone it into the context for the modal.
226
        context.editenrollink = editEnrolLink.outerHTML;
227
    }
228
 
229
    CancelModal.create({
230
        large: true,
231
        title: Str.get_string('enroldetails', 'enrol'),
232
        body: Templates.render('core_user/status_details', context),
233
    })
234
    .then(modal => {
235
        if (editEnrolLink) {
236
            modal.getRoot().on('click', Selectors.editEnrolment, e => {
237
                e.preventDefault();
238
                modal.hide();
239
 
240
                // Trigger click event for the edit enrolment link to show the edit enrolment modal.
241
                editEnrolLink.click();
242
            });
243
        }
244
 
245
        modal.show();
246
 
247
        // Handle hidden event.
248
        modal.getRoot().on(ModalEvents.hidden, () => modal.destroy());
249
 
250
        return modal;
251
    })
252
    .catch(Notification.exception);
253
};
254
 
255
/**
256
 * Submit the edit dialogue.
257
 *
258
 * @param {HTMLElement} clickedLink
259
 * @param {Function} getBody
260
 * @param {Object} modal
261
 * @param {Number} userEnrolmentId
262
 * @param {Object} userData
263
 */
264
const submitEditFormAjax = (clickedLink, getBody, modal, userEnrolmentId, userData) => {
265
    const form = modal.getRoot().find('form');
266
 
267
    Repository.submitUserEnrolmentForm(form.serialize())
268
    .then(data => {
269
        if (!data.result) {
270
            throw data.result;
271
        }
272
 
273
        // Dismiss the modal.
274
        modal.hide();
275
        modal.destroy();
276
 
277
        return data;
278
    })
279
    .then(() => {
280
        DynamicTable.refreshTableContent(getDynamicTableFromLink(clickedLink))
281
        .catch(Notification.exception);
282
 
283
        return Str.get_string('enrolmentupdatedforuser', 'core_enrol', userData);
284
    })
285
    .then(notificationString => {
286
        notifyUser(notificationString);
287
 
288
        return;
289
    })
290
    .catch(() => {
291
        modal.setBody(getBody(userEnrolmentId, JSON.stringify(form.serialize())));
292
 
293
        return modal;
294
    });
295
};
296
 
297
/**
298
 * Submit the unenrolment form.
299
 *
300
 * @param {HTMLElement} clickedLink
301
 * @param {Object} modal
302
 * @param {Object} args
303
 * @param {Object} userData
304
 */
305
const submitUnenrolFormAjax = (clickedLink, modal, args, userData) => {
306
    Repository.unenrolUser(args.ueid)
307
    .then(data => {
308
        if (!data.result) {
309
            // Display an alert containing the error message
310
            Notification.alert(data.errors[0].key, data.errors[0].message);
311
 
312
            return data;
313
        }
314
 
315
        // Dismiss the modal.
316
        modal.hide();
317
        modal.destroy();
318
 
319
        return data;
320
    })
321
    .then(() => {
322
        DynamicTable.refreshTableContent(getDynamicTableFromLink(clickedLink))
323
        .catch(Notification.exception);
324
 
325
        return Str.get_string('unenrolleduser', 'core_enrol', userData);
326
    })
327
    .then(notificationString => {
328
        notifyUser(notificationString);
329
 
330
        return;
331
    })
332
    .catch(Notification.exception);
333
};
334
 
335
/**
336
 * Get the body fragment.
337
 *
338
 * @param {Number} contextId
339
 * @param {Number} ueid The user enrolment id
340
 * @param {Object} formdata
341
 * @returns {Promise}
342
 */
343
const getBody = (contextId, ueid, formdata = null) => Fragment.loadFragment(
344
    'enrol',
345
    'user_enrolment_form',
346
    contextId,
347
    {
348
        ueid,
349
        formdata,
350
    }
351
);
352
 
353
/**
354
 * Initialise the statu field handler.
355
 *
356
 * @param {object} param
357
 * @param {Number} param.contextid
358
 * @param {Number} param.uniqueid
359
 */
360
export const init = ({contextid, uniqueid}) => {
361
    registerEventListeners(contextid, uniqueid);
362
};