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 the Zoom plugin for 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
 * Populates or de-populates password field based on whether the
18
 * password is required or not.
19
 *
20
 * @copyright  2018 UC Regents
21
 * @author     Kubilay Agi
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
define(['jquery', 'core/form-autocomplete', 'core/str', 'core/notification'], function($, autocomplete, str, notification) {
26
 
27
    /**
28
     * CSS selectors used throughout the file.
29
     *
30
     * @type {object}
31
     */
32
    var SELECTORS = {
33
        REPEAT_SELECT: 'select[name="recurrence_type"]',
34
        REPEAT_INTERVAL: '.repeat_interval',
35
        REPEAT_INTERVAL_DAILY: '#interval_daily',
36
        REPEAT_INTERVAL_WEEKLY: '#interval_weekly',
37
        REPEAT_INTERVAL_MONTHLY: '#interval_monthly',
38
        REPEAT_INTERVAL_OPTIONS: 'select[name="repeat_interval"] option',
39
        START_TIME: 'select[name*="start_time"]',
40
        DURATION: '*[name*="duration"]',
41
        RECURRING: 'input[name="recurring"][type!="hidden"]',
42
        OPTION_JBH: 'input[name="option_jbh"][type!="hidden"]',
43
        OPTION_WAITING_ROOM: 'input[name="option_waiting_room"][type!="hidden"]'
44
    };
45
 
46
    /**
47
     * Repeat interval options.
48
     *
49
     * @type {object}
50
     */
51
    var REPEAT_OPTIONS = {
52
        REPEAT_OPTION_NONE: 0,
53
        REPEAT_OPTION_DAILY: 1,
54
        REPEAT_OPTION_WEEKLY: 2,
55
        REPEAT_OPTION_MONTHLY: 3
56
    };
57
 
58
    /**
59
     * The max values for each repeat option.
60
     *
61
     * @type {object}
62
     */
63
    var REPEAT_MAX_OPTIONS = {
64
        REPEAT_OPTION_DAILY: 90,
65
        REPEAT_OPTION_WEEKLY: 12,
66
        REPEAT_OPTION_MONTHLY: 3
67
    };
68
 
69
    /**
70
     * The init function.
71
     */
72
    var init = function() {
73
        var optionJoinBeforeHost = $(SELECTORS.OPTION_JBH);
74
        var optionWaitingRoom = $(SELECTORS.OPTION_WAITING_ROOM);
75
        optionJoinBeforeHost.change(function() {
76
            if (optionJoinBeforeHost.is(':checked') === true) {
77
                optionWaitingRoom.prop('checked', false);
78
            }
79
        });
80
        optionWaitingRoom.change(function() {
81
            if (optionWaitingRoom.is(':checked') === true) {
82
                optionJoinBeforeHost.prop('checked', false);
83
            }
84
        });
85
 
86
        // First toggle the values based on initial selections.
87
        toggleStartTimeDuration();
88
        toggleRepeatIntervalText();
89
        limitRepeatValues();
90
        // Add listerner to "Repeat Every" drop-down.
91
        $(SELECTORS.REPEAT_SELECT).change(function() {
92
            toggleStartTimeDuration();
93
            toggleRepeatIntervalText();
94
            limitRepeatValues();
95
        });
96
        // Add listener for the "Recurring" checkbox
97
        $(SELECTORS.RECURRING).change(function() {
98
            toggleStartTimeDuration();
99
        });
100
 
101
        var breakoutroomsEditor = new BreakoutroomsEditor();
102
        breakoutroomsEditor.init();
103
    };
104
 
105
    /**
106
     * Toggle start time and duration elements.
107
     */
108
    var toggleStartTimeDuration = function() {
109
        // Disable start time and duration if "No Fixed Time" recurring meeting/webinar selected.
110
        var disabled = false;
111
        var repeatVal = parseInt($(SELECTORS.REPEAT_SELECT).val(), 10);
112
        if ($(SELECTORS.RECURRING).prop('checked') && repeatVal === REPEAT_OPTIONS.REPEAT_OPTION_NONE) {
113
            disabled = true;
114
        }
115
        $(SELECTORS.START_TIME).prop('disabled', disabled);
116
        $(SELECTORS.DURATION).prop('disabled', disabled);
117
    };
118
 
119
    /**
120
     * Toggle the text based on repeat type.
121
     * To show either Days, Weeks or Months
122
     */
123
    var toggleRepeatIntervalText = function() {
124
        $(SELECTORS.REPEAT_INTERVAL).hide();
125
        var repeatSelectVal = parseInt($(SELECTORS.REPEAT_SELECT).val(), 10);
126
        if (repeatSelectVal === REPEAT_OPTIONS.REPEAT_OPTION_DAILY) {
127
            $(SELECTORS.REPEAT_INTERVAL_DAILY).show();
128
        } else if (repeatSelectVal === REPEAT_OPTIONS.REPEAT_OPTION_WEEKLY) {
129
            $(SELECTORS.REPEAT_INTERVAL_WEEKLY).show();
130
        } else if (repeatSelectVal === REPEAT_OPTIONS.REPEAT_OPTION_MONTHLY) {
131
            $(SELECTORS.REPEAT_INTERVAL_MONTHLY).show();
132
        }
133
    };
134
 
135
    /**
136
     * Limit the options shown in the drop-down based on repeat type selected.
137
     * Max value for daily meeting is 90.
138
     * Max value for weekly meeting is 12.
139
     * Max value for monthly meeting is 3.
140
     */
141
    var limitRepeatValues = function() {
142
        var selectedValue = parseInt($(SELECTORS.REPEAT_SELECT).val(), 10);
143
        // Restrict options if weekly or monthly option selected.
144
        $(SELECTORS.REPEAT_INTERVAL_OPTIONS).each(function() {
145
            if (selectedValue === REPEAT_OPTIONS.REPEAT_OPTION_WEEKLY) {
146
                if (this.value > REPEAT_MAX_OPTIONS.REPEAT_OPTION_WEEKLY) {
147
                    $(this).hide();
148
                }
149
            } else if (selectedValue === REPEAT_OPTIONS.REPEAT_OPTION_MONTHLY) {
150
                if (this.value > REPEAT_MAX_OPTIONS.REPEAT_OPTION_MONTHLY) {
151
                    $(this).hide();
152
                }
153
            } else {
154
                $(this).show();
155
            }
156
        });
157
    };
158
 
159
    /**
160
     * Tabs component.
161
     * @param {object} tabsColumn
162
     * @param {object} tabsContentColumn
163
     * @param {int}    initialTabsCount
164
     * @param {object} emptyAlert
165
     */
166
    var TabsComponent = function(tabsColumn, tabsContentColumn, initialTabsCount, emptyAlert) {
167
        this.tabsColumn = tabsColumn;
168
        this.tabsContentColumn = tabsContentColumn;
169
        this.emptyAlert = emptyAlert;
170
        this.countTabs = initialTabsCount;
171
 
172
        /**
173
         * Build tab
174
         * @param {object} item
175
         * @returns {object} tab element
176
         */
177
        this.buildTab = function(item) {
178
            var tab = item.tab.element;
179
            var tabLink = $(".nav-link", tab);
180
 
181
            // Setting tab id.
182
            tab.attr('id', 'tab-' + this.countTabs);
183
 
184
            // Setting tab name.
185
            $(".tab-name", tabLink).text(item.tab.name);
186
 
187
            // Setting tab href.
188
            tabLink.attr('href', '#link' + this.countTabs);
189
 
190
            // Activating tab
191
            $("li a", this.tabsColumn).removeClass('active');
192
            tabLink.addClass('active');
193
 
194
            return tab;
195
        };
196
 
197
        /**
198
         * Build tab content.
199
         * @param {object} item
200
         * @returns {object} content of tab element
201
         */
202
        this.buildTabContent = function(item) {
203
            var tabContent = item.tabContent.element;
204
 
205
            // Setting tabContent id.
206
            tabContent.attr('id', 'link' + this.countTabs);
207
 
208
            // Activating tabContent.
209
            $(".tab-pane", this.tabsContentColumn).removeClass('active');
210
            tabContent.addClass('active');
211
 
212
            return tabContent;
213
        };
214
 
215
 
216
        /**
217
         * Add tab
218
         * @param {object} item
219
         * @returns {object} tab element
220
         */
221
        this.addTab = function(item) {
222
            var tab = this.buildTab(item);
223
            var tabContent = this.buildTabContent(item);
224
 
225
            this.emptyAlert.addClass('hidden');
226
            $("ul", this.tabsColumn).append(tab);
227
            $(".tab-content", this.tabsContentColumn).append(tabContent);
228
 
229
            return {"element": tab, "content": tabContent};
230
        };
231
 
232
        /**
233
         * Delete tab
234
         * @param {object} item
235
         */
236
        this.deleteTab = function(item) {
237
            var tab = item;
238
            var tabContent = $($('a', tab).attr('href'));
239
 
240
            tab.remove();
241
            tabContent.remove();
242
 
243
            var countTabs = $("li", this.tabsColumn).length;
244
            if (!countTabs) {
245
                this.emptyAlert.removeClass('hidden');
246
            } else {
247
                var countActiveTabs = $("li a.active", this.tabsColumn).length;
248
                if (!countActiveTabs) {
249
                    $("li:first-child a", this.tabsColumn).trigger('click');
250
                }
251
            }
252
        };
253
    };
254
 
255
    /**
256
     * Breakout rooms editor.
257
     */
258
    var BreakoutroomsEditor = function() {
259
        this.roomsListColumn = $("#mod-zoom-meeting-rooms-list");
260
        this.roomsList = $("ul", this.roomsListColumn);
261
        this.addBtn = $("#add-room", this.roomsListColumn);
262
        this.emptyAlert = $(".empty-alert", this.roomsListColumn);
263
        this.deleteBtn = $(".delete-room", this.roomsListColumn);
264
        this.roomsDataColumn = $("#mod-zoom-meeting-rooms-data");
265
        this.roomItemToClone = $('#rooms-list-item').html();
266
        this.roomItemDataToClone = $('#rooms-list-item-data').html();
267
        this.initialRoomsCount = parseInt(this.roomsListColumn.attr('data-initial-rooms-count'));
268
        this.tabsComponent = new TabsComponent(this.roomsListColumn, this.roomsDataColumn, this.initialRoomsCount, this.emptyAlert);
269
 
270
        // Add room event.
271
        this.init = function() {
272
            var stringkeys = [{key: 'room', component: 'zoom'}];
273
            str.get_strings(stringkeys).then(function() {
274
                return null;
275
            }).fail(notification.exception);
276
 
277
            this.addRoomEvent();
278
            this.deleteRoomEvent();
279
            var countRooms = $("li", this.roomsListColumn).length;
280
            if (countRooms) {
281
                this.changeRoomNameEvent();
282
                this.buildAutocompleteComponents();
283
            } else {
284
                this.emptyAlert.removeClass('hidden');
285
            }
286
        };
287
        // Add room event.
288
        this.addRoomEvent = function() {
289
            var thisObject = this;
290
 
291
            // Adding addroom button click event.
292
            thisObject.addBtn.click(function() {
293
                thisObject.tabsComponent.countTabs++;
294
 
295
                var newRoomName = M.util.get_string('room', 'zoom') + ' ' + thisObject.tabsComponent.countTabs;
296
                var newRoomElement = $(thisObject.roomItemToClone);
297
                var newRoomDataElement = $(thisObject.roomItemDataToClone);
298
                var newRoomIndex = thisObject.tabsComponent.countTabs;
299
 
300
                // Setting new room name.
301
                var roomNameInputId = 'room-name-' + newRoomIndex;
302
                $("input[type=text]", newRoomDataElement).prev().attr('for', roomNameInputId);
303
                $("input[type=text]", newRoomDataElement).attr('id', roomNameInputId);
304
                $("input[type=text]", newRoomDataElement).attr('name', roomNameInputId);
305
                $("input[type=text]", newRoomDataElement).val(newRoomName);
306
                $("input[type=text]", newRoomDataElement).next().attr('name', 'rooms[' + newRoomIndex + ']');
307
                $("input[type=text]", newRoomDataElement).next().val(newRoomName);
308
 
309
                // Setting new room participants select id/name.
310
                var roomParticipantsSelectId = 'participants-' + newRoomIndex;
311
                $(".room-participants", newRoomDataElement).attr('id', roomParticipantsSelectId);
312
                $(".room-participants", newRoomDataElement).attr('name', 'roomsparticipants[' + newRoomIndex + '][]');
313
 
314
                // Setting new room participant groups select id/name.
315
                var roomGroupsSelectId = 'groups-' + newRoomIndex;
316
                $(".room-groups", newRoomDataElement).attr('id', roomGroupsSelectId);
317
                $(".room-groups", newRoomDataElement).attr('name', 'roomsgroups[' + newRoomIndex + '][]');
318
 
319
                // Add new room tab
320
                var newRoom = {"tab": {"name": newRoomName, "element": newRoomElement},
321
                    "tabContent": {"element": newRoomDataElement}};
322
 
323
                var addedTab = thisObject.tabsComponent.addTab(newRoom);
324
 
325
                // Adding new room tab delete button click event.
326
                $("li:last .delete-room", thisObject.roomsList).click(function() {
327
                    var thisItem = $(this).closest('li');
328
                    thisObject.tabsComponent.deleteTab(thisItem);
329
                });
330
 
331
                // Adding new room change name event.
332
                $("input[type=text]", addedTab.content).on("change keyup paste", function() {
333
                    var newHiddenValue = this.value;
334
                    $(this).next().val(newHiddenValue);
335
 
336
                    $(".tab-name", addedTab.element).text(this.value);
337
                });
338
 
339
                // Convert select dropdowns to autocomplete component.
340
                thisObject.buildAutocompleteComponent(roomParticipantsSelectId, 'addparticipant');
341
                thisObject.buildAutocompleteComponent(roomGroupsSelectId, 'addparticipantgroup');
342
            });
343
        };
344
 
345
        // Delete room event.
346
        this.deleteRoomEvent = function() {
347
            var thisObject = this;
348
 
349
            // Adding deleteroom button click event.
350
            thisObject.deleteBtn.click(function() {
351
                var thisItem = $(this).closest('li');
352
                thisObject.tabsComponent.deleteTab(thisItem);
353
            });
354
        };
355
 
356
        // Change room name event.
357
        this.changeRoomNameEvent = function() {
358
            var thisObject = this;
359
 
360
            $("li", this.roomsListColumn).each(function() {
361
                var tabIdArr = $(this).attr('id').split('-');
362
                var tabIndex = tabIdArr[1];
363
                $('input[name="room-name-' + tabIndex + '"]', thisObject.roomsDataColumn).on("change keyup paste", function() {
364
                    var newHiddenValue = this.value;
365
                    $(this).next().val(newHiddenValue);
366
 
367
                    $("#tab-" + tabIndex + " .tab-name").text(this.value);
368
                });
369
            });
370
        };
371
 
372
        /**
373
         * Build autocomplete components.
374
         */
375
        this.buildAutocompleteComponents = function() {
376
            var thisObject = this;
377
            $(".room-participants", thisObject.roomsDataColumn).each(function() {
378
                var thisItemId = $(this).attr('id');
379
                thisObject.buildAutocompleteComponent(thisItemId, 'addparticipant');
380
            });
381
 
382
            $(".room-groups", thisObject.roomsDataColumn).each(function() {
383
                var thisItemId = $(this).attr('id');
384
                thisObject.buildAutocompleteComponent(thisItemId, 'addparticipantgroup');
385
            });
386
        };
387
 
388
        /**
389
         * Build autocomplete component.
390
         * @param {string} id
391
         * @param {string} placeholder
392
         */
393
        this.buildAutocompleteComponent = function(id, placeholder) {
394
            var stringkeys = [{key: placeholder, component: 'zoom'}, {key: 'selectionarea', component: 'zoom'}];
395
            str.get_strings(stringkeys).then(function(langstrings) {
396
                var placeholderString = langstrings[0];
397
                var noSelectionString = langstrings[1];
398
 
399
                autocomplete.enhance('#' + id, false, '', placeholderString, false, true, noSelectionString, true);
400
                return null;
401
            }).fail(notification.exception);
402
        };
403
    };
404
 
405
    return {
406
        init: init
407
    };
408
});