Issues (40)

app/assets/javascripts/room.js (7 issues)

1
// BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
2
//
3
// Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
4
//
5
// This program is free software; you can redistribute it and/or modify it under the
6
// terms of the GNU Lesser General Public License as published by the Free Software
7
// Foundation; either version 3.0 of the License, or (at your option) any later
8
// version.
9
//
10
// BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12
// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
13
//
14
// You should have received a copy of the GNU Lesser General Public License along
15
// with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
16
17
// Room specific js for copy button and email link.
18
$(document).on('turbolinks:load', function(){
19
  var controller = $("body").data('controller');
20
  var action = $("body").data('action');
21
22
  // highlight current room
23
  $('.room-block').removeClass('current');
24
  $('a[href="' + window.location.pathname + '"] .room-block').addClass('current');
25
26
  // Only run on room pages.
27
  if (controller == "rooms" && action == "show"){
28
    // Display and update all fields related to creating a room in the createRoomModal
29
    $("#create-room-block").click(function(){
30
      showCreateRoom(this)
31
    })
32
33
    checkIfAutoJoin()
34
  }
35
36
    // Autofocus on the Room Name label when creating a room only
37
  $('#createRoomModal').on('shown.bs.modal', function (){
38
    if ($(".create-only").css("display") == "block"){
39
      $('#create-room-name').focus()
40
    }
41
  })
42
43
  if (controller == "rooms" && action == "show" || controller == "admins" && action == "server_rooms"){
44
    // Display and update all fields related to creating a room in the createRoomModal
45
    $(".update-room").click(function(){
46
      showUpdateRoom(this)
47
    })
48
49
    $(".delete-room").click(function() {
50
      showDeleteRoom(this)
51
    })
52
53
    $('.selectpicker').selectpicker({
54
      liveSearchPlaceholder: getLocalizedString('javascript.search.start')
55
    });
56
    // Fixes turbolinks issue with bootstrap select
57
    $(window).trigger('load.bs.select.data-api');
58
59
    $(".share-room").click(function() {
60
      // Update the path of save button
61
      $("#save-access").attr("data-path", $(this).data("path"))
62
      $("#room-owner-uid").val($(this).data("owner"))
63
64
      // Get list of users shared with and display them
65
      displaySharedUsers($(this).data("users-path"))
66
    })
67
68
    $("#shareRoomModal").on("show.bs.modal", function() {
69
      $(".selectpicker").selectpicker('val','')
70
    })
71
72
    $(".bootstrap-select").on("click", function() {
73
      $(".bs-searchbox").siblings().hide()
74
    })
75
76
    $("#share-room-select ~ button").on("click", function() {
77
      $(".bs-searchbox").siblings().hide()
78
    })
79
80
    $(".bs-searchbox input").on("input", function() {
81
      if ($(".bs-searchbox input").val() == '' || $(".bs-searchbox input").val().length < 3) {
82
        $(".select-options").remove()
83
        $(".bs-searchbox").siblings().hide()
84
      } else {
85
        // Manually populate the dropdown
86
        $.get($("#share-room-select").data("path"), { search: $(".bs-searchbox input").val(), owner_uid: $("#room-owner-uid").val() }, function(users) {
87
          $(".select-options").remove()
88
          if (users.length > 0) {
89
            users.forEach(function(user) {
90
              let opt = document.createElement("option")
91
              $(opt).val(user.uid)
92
              $(opt).text(user.name)
93
              $(opt).addClass("select-options")
94
              $(opt).attr("data-subtext", user.uid)
95
              $("#share-room-select").append(opt)
96
            })
97
            // Only refresh the select dropdown if there are results to show
98
            $('#share-room-select').selectpicker('refresh');
99
          } 
100
          $(".bs-searchbox").siblings().show()
101
        })     
102
      }
103
    })
104
105
    $(".remove-share-room").click(function() {
106
      $("#remove-shared-confirm").parent().attr("action", $(this).data("path"))
107
    })
108
109
    // User selects an option from the Room Access dropdown
110
    $(".bootstrap-select").on("changed.bs.select", function(){
111
      // Get the uid of the selected user
112
      let uid = $(".selectpicker").selectpicker('val')
113
114
      // If the value was changed to blank, ignore it
115
      if (uid == "") return
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
116
117
      let currentListItems = $("#user-list li").toArray().map(user => $(user).data("uid"))
118
119
      // Check to make sure that the user is not already there
120
      if (!currentListItems.includes(uid)) {
121
        // Create the faded list item and display it
122
        let option = $("option[value='" + uid + "']")
123
124
        let listItem = document.createElement("li")
125
        listItem.setAttribute('class', 'list-group-item text-left not-saved add-access');
126
        listItem.setAttribute("data-uid", uid)
127
128
        let spanItemAvatar = document.createElement("span"),
129
            spanItemName = document.createElement("span"),
130
            spanItemUser = document.createElement("span");
131
        spanItemAvatar.setAttribute('class', 'avatar float-left mr-2');
132
        spanItemAvatar.innerText = option.text().charAt(0);
133
        spanItemName.setAttribute('class', 'shared-user');
134
        spanItemName.innerText = option.text();
135
        spanItemUser.setAttribute('class', 'text-muted');
136
        spanItemUser.innerText = option.data('subtext');
137
        spanItemName.append(spanItemUser);
138
139
        listItem.innerHTML = "<span class='text-primary float-right shared-user cursor-pointer' onclick='removeSharedUser(this)'><i class='fas fa-times'></i></span>"
140
        listItem.prepend(spanItemName);
141
        listItem.prepend(spanItemAvatar);
142
143
        $("#user-list").append(listItem)
144
      }
145
    })
146
147
    $("#presentation-upload").change(function(data) {
148
      var file = data.target.files[0]
149
150
      // Check file type and size to make sure they aren't over the limit
151
      if (validFileUpload(file)) {
152
        $("#presentation-upload-label").text(file.name)
153
      } else {
154
        $("#invalid-file-type").show()
155
        $("#presentation-upload").val("")
156
        $("#presentation-upload-label").text($("#presentation-upload-label").data("placeholder"))
157
      }
158
    })
159
160
    $(".preupload-room").click(function() {
161
      updatePreuploadPresentationModal(this)
162
    })
163
164
    $("#remove-presentation").click(function(data) {
165
      removePreuploadPresentation($(this).data("remove"))
166
    })
167
168
    // trigger initial room filter
169
    filterRooms();
170
  }
171
});
172
173
function copyInvite() {
174
  $('#invite-url').select()
175
  if (document.execCommand("copy")) {
176
    $('#invite-url').blur();
177
    copy = $("#copy-invite")
0 ignored issues
show
The variable copy seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.copy.
Loading history...
178
    copy.addClass('btn-success');
179
    copy.html("<i class='fas fa-check mr-1'></i>" + getLocalizedString("copied"))
180
    setTimeout(function(){
181
      copy.removeClass('btn-success');
182
      copy.html("<i class='fas fa-copy mr-1'></i>" + getLocalizedString("copy"))
183
    }, 1000)
184
  }
185
}
186
187
function copyAccess() {
188
  $('#copy-code').attr("type", "text")
189
  $('#copy-code').select()
190
  if (document.execCommand("copy")) {
191
    $('#copy-code').attr("type", "hidden")
192
    copy = $("#copy-access")
0 ignored issues
show
The variable copy seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.copy.
Loading history...
193
    copy.addClass('btn-success');
194
    copy.html("<i class='fas fa-check mr-1'></i>" + getLocalizedString("copied"))
195
    setTimeout(function(){
196
      copy.removeClass('btn-success');
197
      copy.html("<i class='fas fa-copy mr-1'></i>" + getLocalizedString("room.copy_access"))
198
    }, 1000)
199
  }
200
}
201
202
function showCreateRoom(target) {
0 ignored issues
show
The parameter target is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
203
  $("#create-room-name").val("")
204
  $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
205
  $("#room_access_code").val(null)
206
207
  $("#createRoomModal form").attr("action", $("body").data('relative-root'))
208
  $("#room_mute_on_join").prop("checked", $("#room_mute_on_join").data("default"))
209
  $("#room_require_moderator_approval").prop("checked", $("#room_require_moderator_approval").data("default"))
210
  $("#room_anyone_can_start").prop("checked", $("#room_anyone_can_start").data("default"))
211
  $("#room_all_join_moderator").prop("checked", $("#room_all_join_moderator").data("default"))
212
  $("#room_recording").prop("checked", $("#room_recording").data("default"))
213
214
  //show all elements & their children with a create-only class
215
  $(".create-only").each(function() {
216
    $(this).show()
217
    if($(this).children().length > 0) { $(this).children().show() }
218
  })
219
220
  //hide all elements & their children with a update-only class
221
  $(".update-only").each(function() {
222
    $(this).attr('style',"display:none !important")
223
    if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") }
224
  })
225
}
226
227
function showUpdateRoom(target) {
228
  var modal = $(target)
229
  var update_path = modal.closest(".room-block").data("path")
230
  var settings_path = modal.data("settings-path")
231
  $("#create-room-name").val(modal.closest(".room-block").find(".room-name-text").text().trim())
232
  $("#createRoomModal form").attr("action", update_path)
233
234
  //show all elements & their children with a update-only class
235
  $(".update-only").each(function() {
236
    $(this).show()
237
    if($(this).children().length > 0) { $(this).children().show() }
238
  })
239
240
  //hide all elements & their children with a create-only class
241
  $(".create-only").each(function() {
242
    $(this).attr('style',"display:none !important")
243
    if($(this).children().length > 0) { $(this).children().attr('style',"display:none !important") }
244
  })
245
246
  updateCurrentSettings(settings_path)
247
248
  var accessCode = modal.closest(".room-block").data("room-access-code")
249
250
  if(accessCode){
251
    $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code") + ": " + accessCode)
252
    $("#room_access_code").val(accessCode)
253
  } else {
254
    $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
255
    $("#room_access_code").val(null)
256
  }
257
}
258
259
function showDeleteRoom(target) {
260
  $("#delete-header").text(getLocalizedString("modal.delete_room.confirm").replace("%{room}", $(target).data("name")))
261
  $("#delete-confirm").parent().attr("action", $(target).data("path"))
262
}
263
264
//Update the createRoomModal to show the correct current settings
265
function updateCurrentSettings(settings_path){
266
  // Get current room settings and set checkbox
267
  $.get(settings_path, function(settings) {
268
    $("#room_mute_on_join").prop("checked", $("#room_mute_on_join").data("default") || settings.muteOnStart)
269
    $("#room_require_moderator_approval").prop("checked", $("#room_require_moderator_approval").data("default") || settings.requireModeratorApproval)
270
    $("#room_anyone_can_start").prop("checked", $("#room_anyone_can_start").data("default") || settings.anyoneCanStart)
271
    $("#room_all_join_moderator").prop("checked", $("#room_all_join_moderator").data("default") || settings.joinModerator)
272
    $("#room_recording").prop("checked", $("#room_recording").data("default") || Boolean(settings.recording))
273
  })
274
}
275
276
function generateAccessCode(){
277
  const accessCodeLength = 6
278
  var validCharacters = "0123456789"
279
  var accessCode = ""
280
281
  for( var i = 0; i < accessCodeLength; i++){
282
    accessCode += validCharacters.charAt(Math.floor(Math.random() * validCharacters.length));
283
  }
284
285
  $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code") + ": " + accessCode)
286
  $("#room_access_code").val(accessCode)
287
}
288
289
function ResetAccessCode(){
290
  $("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
291
  $("#room_access_code").val(null)
292
}
293
294
function saveAccessChanges() {
295
  let listItemsToAdd = $("#user-list li:not(.remove-shared)").toArray().map(user => $(user).data("uid"))
296
297
  $.post($("#save-access").data("path"), {add: listItemsToAdd})
298
}
299
300
// Get list of users shared with and display them
301
function displaySharedUsers(path) {
302
  $.get(path, function(users) {
303
    // Create list element and add to user list
304
    var user_list_html = ""
305
306
    users.forEach(function(user) {
307
      user_list_html += "<li class='list-group-item text-left' data-uid='" + user.uid + "'>"
308
309
      if (user.image) {
310
        user_list_html += "<img id='user-image' class='avatar float-left mr-2' src='" + user.image + "'></img>"
311
      } else {
312
        user_list_html += "<span class='avatar float-left mr-2'>" + user.name.charAt(0) + "</span>"
313
      }
314
      user_list_html += "<span class='shared-user'>" + user.name + "<span class='text-muted ml-1'>" + user.uid + "</span></span>"
315
      user_list_html += "<span class='text-primary float-right shared-user cursor-pointer' onclick='removeSharedUser(this)'><i class='fas fa-times'></i></span>"
316
      user_list_html += "</li>"
317
    })
318
319
    $("#user-list").html(user_list_html)
320
  });
321
}
322
323
// Removes the user from the list of shared users
324
function removeSharedUser(target) {
325
  let parentLI = target.closest("li")
326
327
  if (parentLI.classList.contains("not-saved")) {
328
    parentLI.parentNode.removeChild(parentLI)
329
  } else {
330
    parentLI.removeChild(target)
331
    parentLI.classList.add("remove-shared")
332
  }
333
}
334
335
function updatePreuploadPresentationModal(target) {
336
  $.get($(target).data("settings-path"), function(presentation) {
337
    if(presentation.attached) {
338
      $("#current-presentation").show()
339
      $("#presentation-name").text(presentation.name)
340
      $("#change-pres").show()
341
      $("#use-pres").hide()
342
    } else {
343
      $("#current-presentation").hide()
344
      $("#change-pres").hide()
345
      $("#use-pres").show()
346
    }
347
  });
348
  
349
  $("#preuploadPresentationModal form").attr("action", $(target).data("path"))
350
  $("#remove-presentation").data("remove",  $(target).data("remove"))
351
  
352
  // Reset values to original to prevent confusion
353
  $("#presentation-upload").val("")
354
  $("#presentation-upload-label").text($("#presentation-upload-label").data("placeholder"))
355
  $("#invalid-file-type").hide()
356
}
357
358
function removePreuploadPresentation(path) {
359
  $.post(path, {})
360
}
361
362
function validFileUpload(file) {
363
  return file.size/1024/1024 <= 30
364
}
365
366
// Automatically click the join button if this is an action cable reload
367
function checkIfAutoJoin() {
368
  var url = new URL(window.location.href)
0 ignored issues
show
The variable URL seems to be never declared. If this is a global, consider adding a /** global: URL */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
369
370
  if (url.searchParams.get("reload") == "true") {
371
    $("#joiner-consent").click()
372
    $("#room-join").click()
373
  }
374
}
375
376
function filterRooms() {
377
  let search = $('#room-search').val()
378
379
  if (search == undefined) { return }
0 ignored issues
show
Comparing search to undefined using the == operator is not safe. Consider using === instead.
Loading history...
380
381
  let search_term = search.toLowerCase(),
382
        rooms = $('#room_block_container > div:not(:last-child)');
383
        clear_room_search = $('#clear-room-search');
0 ignored issues
show
The variable clear_room_search seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.clear_room_search.
Loading history...
384
385
  if (search_term) {
386
    clear_room_search.show();
387
  } else {
388
    clear_room_search.hide();
389
  }
390
391
  rooms.each(function(i, room) {
392
    let text = $(this).find('h4').text();
393
    room.style.display = (text.toLowerCase().indexOf(search_term) < 0) ? 'none' : 'block';
394
  })
395
}
396
397
function clearRoomSearch() {
398
  $('#room-search').val(''); 
399
  filterRooms()
400
}
401