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
 * Standard Ajax wrapper for Moodle. It calls the central Ajax script,
18
 * which can call any existing webservice using the current session.
19
 * In addition, it can batch multiple requests and return multiple responses.
20
 *
21
 * @module     mod_lti/tool_configure_controller
22
 * @copyright  2015 Ryan Wyllie <ryan@moodle.com>
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 * @since      3.1
25
 */
26
define(['jquery', 'core/ajax', 'core/paged_content_factory', 'core/notification', 'core/templates', 'mod_lti/events',
27
        'mod_lti/keys', 'mod_lti/tool_types_and_proxies', 'mod_lti/tool_type', 'mod_lti/tool_proxy', 'core/str', 'core/config'],
28
        function($, ajax,
29
                 pagedContentFactory, notification, templates, ltiEvents, KEYS,
30
                 toolTypesAndProxies, toolType, toolProxy, str, config) {
31
 
32
    var SELECTORS = {
33
        EXTERNAL_REGISTRATION_CONTAINER: '#external-registration-container',
34
        EXTERNAL_REGISTRATION_PAGE_CONTAINER: '#external-registration-page-container',
35
        EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER: '#external-registration-template-container',
36
        CARTRIDGE_REGISTRATION_CONTAINER: '#cartridge-registration-container',
37
        CARTRIDGE_REGISTRATION_FORM: '#cartridge-registration-form',
38
        ADD_TOOL_FORM: '#add-tool-form',
39
        TOOL_CARD_CONTAINER: '#tool-card-container',
40
        TOOL_LIST_CONTAINER: '#tool-list-container',
41
        TOOL_CREATE_BUTTON: '#tool-create-button',
42
        TOOL_CREATE_LTILEGACY_BUTTON: '#tool-createltilegacy-button',
43
        REGISTRATION_CHOICE_CONTAINER: '#registration-choice-container',
44
        TOOL_URL: '#tool-url'
45
    };
46
 
47
    /**
48
     * Get the tool list container element.
49
     *
50
     * @method getToolListContainer
51
     * @private
52
     * @return {Object} jQuery object
53
     */
54
    var getToolListContainer = function() {
55
        return $(SELECTORS.TOOL_LIST_CONTAINER);
56
    };
57
 
58
    /**
59
     * Get the tool card container element.
60
     *
61
     * @method getToolCardContainer
62
     * @private
63
     * @return {Object} jQuery object
64
     */
65
    const getToolCardContainer = function() {
66
        return $(SELECTORS.TOOL_CARD_CONTAINER);
67
    };
68
 
69
    /**
70
     * Get the external registration container element.
71
     *
72
     * @method getExternalRegistrationContainer
73
     * @private
74
     * @return {Object} jQuery object
75
     */
76
    var getExternalRegistrationContainer = function() {
77
        return $(SELECTORS.EXTERNAL_REGISTRATION_CONTAINER);
78
    };
79
 
80
    /**
81
     * Get the cartridge registration container element.
82
     *
83
     * @method getCartridgeRegistrationContainer
84
     * @private
85
     * @return {Object} jQuery object
86
     */
87
    var getCartridgeRegistrationContainer = function() {
88
        return $(SELECTORS.CARTRIDGE_REGISTRATION_CONTAINER);
89
    };
90
 
91
    /**
92
     * Get the registration choice container element.
93
     *
94
     * @method getRegistrationChoiceContainer
95
     * @private
96
     * @return {Object} jQuery object
97
     */
98
    var getRegistrationChoiceContainer = function() {
99
        return $(SELECTORS.REGISTRATION_CHOICE_CONTAINER);
100
    };
101
 
102
    /**
103
     * Close the LTI Advantage Registration IFrame.
104
     *
105
     * @private
106
     * @param {Object} e post message event sent from the registration frame.
107
     */
108
    var closeLTIAdvRegistration = function(e) {
109
        if (e.data && 'org.imsglobal.lti.close' === e.data.subject) {
110
            $(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER).empty();
111
            hideExternalRegistration();
112
            showRegistrationChoices();
113
            showToolList();
114
            showRegistrationChoices();
115
            reloadToolList();
116
        }
117
    };
118
 
119
    /**
120
     * Load the external registration template and render it in the DOM and display it.
121
     *
122
     * @method initiateRegistration
123
     * @private
124
     * @param {String} url where to send the registration request
125
     */
126
    var initiateRegistration = function(url) {
127
        // Show the external registration page in an iframe.
128
        $(SELECTORS.EXTERNAL_REGISTRATION_PAGE_CONTAINER).removeClass('hidden');
129
        var container = $(SELECTORS.EXTERNAL_REGISTRATION_TEMPLATE_CONTAINER);
130
        container.append($("<iframe src='startltiadvregistration.php?url="
131
                         + encodeURIComponent(url) + "&sesskey=" + config.sesskey + "'></iframe>"));
132
        showExternalRegistration();
133
        window.addEventListener("message", closeLTIAdvRegistration, false);
134
    };
135
 
136
    /**
137
     * Get the tool type URL.
138
     *
139
     * @method getToolURL
140
     * @private
141
     * @return {String} the tool type url
142
     */
143
    var getToolURL = function() {
144
        return $(SELECTORS.TOOL_URL).val();
145
    };
146
 
147
    /**
148
     * Hide the external registration container.
149
     *
150
     * @method hideExternalRegistration
151
     * @private
152
     */
153
    var hideExternalRegistration = function() {
154
        getExternalRegistrationContainer().addClass('hidden');
155
    };
156
 
157
    /**
158
     * Hide the cartridge registration container.
159
     *
160
     * @method hideCartridgeRegistration
161
     * @private
162
     */
163
    var hideCartridgeRegistration = function() {
164
        getCartridgeRegistrationContainer().addClass('hidden');
165
    };
166
 
167
    /**
168
     * Hide the registration choice container.
169
     *
170
     * @method hideRegistrationChoices
171
     * @private
172
     */
173
    var hideRegistrationChoices = function() {
174
        getRegistrationChoiceContainer().addClass('hidden');
175
    };
176
 
177
    /**
178
     * Display the external registration panel and hides the other
179
     * panels.
180
     *
181
     * @method showExternalRegistration
182
     * @private
183
     */
184
    var showExternalRegistration = function() {
185
        hideCartridgeRegistration();
186
        hideRegistrationChoices();
187
        getExternalRegistrationContainer().removeClass('hidden');
188
        screenReaderAnnounce(getExternalRegistrationContainer());
189
    };
190
 
191
    /**
192
     * Display the cartridge registration panel and hides the other
193
     * panels.
194
     *
195
     * @method showCartridgeRegistration
196
     * @param {String} url
197
     * @private
198
     */
199
    var showCartridgeRegistration = function(url) {
200
        hideExternalRegistration();
201
        hideRegistrationChoices();
202
        // Don't save the key and secret from the last tool.
203
        var container = getCartridgeRegistrationContainer();
204
        container.find('input').val('');
205
        container.removeClass('hidden');
206
        container.find(SELECTORS.CARTRIDGE_REGISTRATION_FORM).attr('data-cartridge-url', url);
207
        screenReaderAnnounce(container);
208
    };
209
 
210
    /**
211
     * Display the registration choices panel and hides the other
212
     * panels.
213
     *
214
     * @method showRegistrationChoices
215
     * @private
216
     */
217
    var showRegistrationChoices = function() {
218
        hideExternalRegistration();
219
        hideCartridgeRegistration();
220
        getRegistrationChoiceContainer().removeClass('hidden');
221
        screenReaderAnnounce(getRegistrationChoiceContainer());
222
    };
223
 
224
    /**
225
     * JAWS does not notice visibility changes with aria-live.
226
     * Remove and add the content back to force it to read it out.
227
     * This function can be removed once JAWS supports visibility.
228
     *
229
     * @method screenReaderAnnounce
230
     * @param {Object} element
231
     * @private
232
     */
233
    var screenReaderAnnounce = function(element) {
234
        var children = element.children().detach();
235
        children.appendTo(element);
236
    };
237
 
238
    /**
239
     * Hides the list of tool types.
240
     *
241
     * @method hideToolList
242
     * @private
243
     */
244
    var hideToolList = function() {
245
        getToolListContainer().addClass('hidden');
246
    };
247
 
248
    /**
249
     * Display the list of tool types.
250
     *
251
     * @method hideToolList
252
     * @private
253
     */
254
    var showToolList = function() {
255
        getToolListContainer().removeClass('hidden');
256
    };
257
 
258
    /**
259
     * Display the registration feedback alert and hide the other panels.
260
     *
261
     * @method showRegistrationFeedback
262
     * @param {Object} data
263
     * @private
264
     */
265
    var showRegistrationFeedback = function(data) {
266
        var type = data.error ? 'error' : 'success';
267
        notification.addNotification({
268
            message: data.message,
269
            type: type
270
        });
271
    };
272
 
273
    /**
274
     * Show the loading animation
275
     *
276
     * @method startLoading
277
     * @private
278
     * @param {Object} element jQuery object
279
     */
280
    var startLoading = function(element) {
281
        element.addClass("loading");
282
    };
283
 
284
    /**
285
     * Hide the loading animation
286
     *
287
     * @method stopLoading
288
     * @private
289
     * @param {Object} element jQuery object
290
     */
291
    var stopLoading = function(element) {
292
        element.removeClass("loading");
293
    };
294
 
295
    /**
296
     * Refresh the list of tool types and render the new ones.
297
     *
298
     * @method reloadToolList
299
     * @private
300
     */
301
    var reloadToolList = function() {
302
        // Behat tests should wait for the tool list to load.
303
        M.util.js_pending('reloadToolList');
304
 
305
        const cardContainer = getToolCardContainer();
306
        const listContainer = getToolListContainer();
307
        const limit = 60;
308
        // Get initial data with zero limit and offset.
309
        fetchToolCount().done(function(data) {
310
            pagedContentFactory.createWithTotalAndLimit(
311
                data.count,
312
                limit,
313
                function(pagesData) {
314
                    return pagesData.map(function(pageData) {
315
                        return fetchToolData(pageData.limit, pageData.offset)
316
                            .then(function(data) {
317
                                return renderToolData(data);
318
                            });
319
                    });
320
                },
321
                {
322
                    'showFirstLast': true
323
                })
324
                .done(function(html, js) {
325
                // Add the paged content into the page.
326
                templates.replaceNodeContents(cardContainer, html, js);
327
                })
328
                .always(function() {
329
                    stopLoading(listContainer);
330
                    M.util.js_complete('reloadToolList');
331
                });
332
        });
333
        startLoading(listContainer);
334
    };
335
 
336
    /**
337
     * Fetch the count of tool type and proxy datasets.
338
     *
339
     * @return {*|void}
340
     */
341
    const fetchToolCount = function() {
342
        return toolTypesAndProxies.count({'orphanedonly': true})
343
            .done(function(data) {
344
                return data;
345
            }).catch(function(error) {
346
                // Add debug message, then return empty data.
347
                notification.exception(error);
348
                return {
349
                    'count': 0
350
                };
351
            });
352
    };
353
 
354
    /**
355
     * Fetch the data for tool type and proxy cards.
356
     *
357
     * @param {number} limit Maximum number of datasets to get.
358
     * @param {number} offset Offset count for fetching the data.
359
     * @return {*|void}
360
     */
361
    const fetchToolData = function(limit, offset) {
362
        const args = {'orphanedonly': true};
363
        // Only add limit and offset to args if they are integers and not null, otherwise defaults will be used.
364
        if (limit !== null && !Number.isNaN(limit)) {
365
            args.limit = limit;
366
        }
367
        if (offset !== null && !Number.isNaN(offset)) {
368
            args.offset = offset;
369
        }
370
        return toolTypesAndProxies.query(args)
371
            .done(function(data) {
372
                return data;
373
            }).catch(function(error) {
374
                // Add debug message, then return empty data.
375
                notification.exception(error);
376
                return {
377
                    'types': [],
378
                    'proxies': [],
379
                    'limit': limit,
380
                    'offset': offset
381
                };
382
        });
383
    };
384
 
385
    /**
386
     * Render Tool and Proxy cards from data.
387
     *
388
     * @param {Object} data Contains arrays of data objects to populate cards.
389
     * @return {*}
390
     */
391
    const renderToolData = function(data) {
392
        const context = {
393
            tools: data.types,
394
            proxies: data.proxies,
395
        };
396
        return templates.render('mod_lti/tool_list', context)
397
            .done(function(html, js) {
398
                    return {html, js};
399
                }
400
            );
401
    };
402
 
403
    /**
404
     * Start the LTI Advantage registration.
405
     *
406
     * @method addLTIAdvTool
407
     * @private
408
     */
409
    var addLTIAdvTool = function() {
410
        var url = getToolURL().trim();
411
 
412
        if (url) {
413
            $(SELECTORS.TOOL_URL).val('');
414
            hideToolList();
415
            initiateRegistration(url);
416
        }
417
 
418
    };
419
 
420
    /**
421
     * Trigger appropriate registration process process for the user input
422
     * URL. It can either be a cartridge or a registration url.
423
     *
424
     * @method addLTILegacyTool
425
     * @private
426
     * @return {Promise} jQuery Deferred object
427
     */
428
    var addLTILegacyTool = function() {
429
        var url = getToolURL().trim();
430
 
431
        if (url === "") {
432
            return $.Deferred().resolve();
433
        }
434
        var toolButton = $(SELECTORS.TOOL_CREATE_LTILEGACY_BUTTON);
435
        startLoading(toolButton);
436
 
437
        var promise = toolType.isCartridge(url);
438
 
439
        promise.always(function() {
440
          stopLoading(toolButton);
441
        });
442
 
443
        promise.done(function(result) {
444
            if (result.iscartridge) {
445
                $(SELECTORS.TOOL_URL).val('');
446
                $(document).trigger(ltiEvents.START_CARTRIDGE_REGISTRATION, url);
447
            } else {
448
                $(document).trigger(ltiEvents.START_EXTERNAL_REGISTRATION, {url: url});
449
            }
450
        });
451
 
452
        promise.fail(function() {
453
            str.get_string('errorbadurl', 'mod_lti')
454
                .done(function(s) {
455
                        $(document).trigger(ltiEvents.REGISTRATION_FEEDBACK, {
456
                                message: s,
457
                                error: true
458
                            });
459
                    })
460
                .fail(notification.exception);
461
        });
462
 
463
        return promise;
464
    };
465
 
466
    /**
467
     * Sets up the listeners for user interaction on the page.
468
     *
469
     * @method registerEventListeners
470
     * @private
471
     */
472
    var registerEventListeners = function() {
473
 
474
        // These are events fired by the registration processes. Either
475
        // the cartridge registration or the external registration url.
476
        $(document).on(ltiEvents.NEW_TOOL_TYPE, function() {
477
            reloadToolList();
478
        });
479
 
480
        $(document).on(ltiEvents.START_EXTERNAL_REGISTRATION, function() {
481
            showExternalRegistration();
482
            $(SELECTORS.TOOL_URL).val('');
483
            hideToolList();
484
        });
485
 
486
        $(document).on(ltiEvents.STOP_EXTERNAL_REGISTRATION, function() {
487
            showToolList();
488
            showRegistrationChoices();
489
        });
490
 
491
        $(document).on(ltiEvents.START_CARTRIDGE_REGISTRATION, function(event, url) {
492
            showCartridgeRegistration(url);
493
        });
494
 
495
        $(document).on(ltiEvents.STOP_CARTRIDGE_REGISTRATION, function() {
496
            getCartridgeRegistrationContainer().find(SELECTORS.CARTRIDGE_REGISTRATION_FORM).removeAttr('data-cartridge-url');
497
            showRegistrationChoices();
498
        });
499
 
500
        $(document).on(ltiEvents.REGISTRATION_FEEDBACK, function(event, data) {
501
            showRegistrationFeedback(data);
502
        });
503
 
504
        var addLegacyButton = $(SELECTORS.TOOL_CREATE_LTILEGACY_BUTTON);
505
        addLegacyButton.click(function(e) {
506
            e.preventDefault();
507
            addLTILegacyTool();
508
        });
509
 
510
        var addLTIButton = $(SELECTORS.TOOL_CREATE_BUTTON);
511
        addLTIButton.click(function(e) {
512
            e.preventDefault();
513
            addLTIAdvTool();
514
        });
515
 
516
    };
517
 
518
    return /** @alias module:mod_lti/cartridge_registration_form */ {
519
 
520
        /**
521
         * Initialise this module.
522
         */
523
        init: function() {
524
            registerEventListeners();
525
            reloadToolList();
526
        }
527
    };
528
});