Add optional moderator codes (#2413)

* add column for moderator code

* add interface for moderator access code

* add support for write and update moderator access

* check if correct moderator_code in session

* move access code form into own component

* add support for moderator access code

* add support for moderator access code

* add copy code button for moderator code

* freeze all the things

* add tests for moderator access code

* add helpfer for moderator_access setting

* add setting for moderator access code

* show setting for moderator access code

* add checks for moderator code setting

* use method from room controller for moderator password check

* add tests for login with moderator access code

* add check for moderator code setting

* check if moderator codes are enabled in settings

* only display form for moderator code if enabled in settings

* add newline at end of file

* make check for moderator code available as helper

* align style of join button and access code button

* add localization for moderator codes

* add field for moderator codes

* add field for moderator access code to rooms

* fixes for rubocop

* fix LineLenghts for rubocop

* fix double space

Co-authored-by: Ahmad Farhat <ahmad.af.farhat@gmail.com>
This commit is contained in:
zechmeister
2021-03-14 19:24:30 +01:00
committed by GitHub
parent 4cd41f5aa8
commit 9dc59b1211
19 changed files with 447 additions and 174 deletions

View File

@ -184,17 +184,19 @@ function copyInvite() {
}
}
function copyAccess() {
$('#copy-code').attr("type", "text")
$('#copy-code').select()
function copyAccess(target) {
input = target ? $("#copy-" + target + "-code") : $("#copy-code")
input.attr("type", "text")
input.select()
if (document.execCommand("copy")) {
$('#copy-code').attr("type", "hidden")
copy = $("#copy-access")
input.attr("type", "hidden")
copy = target ? $("#copy-" + target + "-access") : $("#copy-access")
copy.addClass('btn-success');
copy.html("<i class='fas fa-check mr-1'></i>" + getLocalizedString("copied"))
setTimeout(function(){
copy.removeClass('btn-success');
copy.html("<i class='fas fa-copy mr-1'></i>" + getLocalizedString("room.copy_access"))
originalString = target ? getLocalizedString("room.copy_" + target + "_access") : getLocalizedString("room.copy_access")
copy.html("<i class='fas fa-copy mr-1'></i>" + originalString)
}, 1000)
}
}
@ -202,7 +204,9 @@ function copyAccess() {
function showCreateRoom(target) {
$("#create-room-name").val("")
$("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
$("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder"))
$("#room_access_code").val(null)
$("#room_moderator_access_code").val(null)
$("#createRoomModal form").attr("action", $("body").data('relative-root'))
$("#room_mute_on_join").prop("checked", $("#room_mute_on_join").data("default"))
@ -254,6 +258,16 @@ function showUpdateRoom(target) {
$("#create-room-access-code").text(getLocalizedString("modal.create_room.access_code_placeholder"))
$("#room_access_code").val(null)
}
var moderatorAccessCode = modal.closest(".room-block").data("room-moderator-access-code")
if(moderatorAccessCode){
$("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code") + ": " + moderatorAccessCode)
$("#room_moderator_access_code").val(moderatorAccessCode)
} else {
$("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder"))
$("#room_moderator_access_code").val(null)
}
}
function showDeleteRoom(target) {
@ -291,6 +305,24 @@ function ResetAccessCode(){
$("#room_access_code").val(null)
}
function generateModeratorAccessCode(){
const accessCodeLength = 6
var validCharacters = "abcdefghijklmopqrstuvwxyz"
var accessCode = ""
for( var i = 0; i < accessCodeLength; i++){
accessCode += validCharacters.charAt(Math.floor(Math.random() * validCharacters.length));
}
$("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code") + ": " + accessCode)
$("#room_moderator_access_code").val(accessCode)
}
function ResetModeratorAccessCode(){
$("#create-room-moderator-access-code").text(getLocalizedString("modal.create_room.moderator_access_code_placeholder"))
$("#room_moderator_access_code").val(null)
}
function saveAccessChanges() {
let listItemsToAdd = $("#user-list li:not(.remove-shared)").toArray().map(user => $(user).data("uid"))

View File

@ -32,8 +32,8 @@
font-size: 20px !important;
}
.join-input {
height: 48px;
.moderator-code-label {
margin-top: 150px !important;
}
.home-indicator {

View File

@ -186,6 +186,12 @@ class ApplicationController < ActionController::Base
end
helper_method :recording_consent_required?
# Indicates whether users are allowed to add moderator access codes to rooms
def moderator_code_allowed?
@settings.get_value("Moderator Access Codes") == "true"
end
helper_method :moderator_code_allowed?
# Returns a list of allowed file types
def allowed_file_types
Rails.configuration.allowed_file_types

View File

@ -50,10 +50,11 @@ module Joiner
def join_room(opts)
@room_settings = JSON.parse(@room[:room_settings])
if room_running?(@room.bbb_id) || @room.owned_by?(current_user) || room_setting_with_config("anyoneCanStart")
moderator_privileges = @room.owned_by?(current_user) || valid_moderator_access_code(session[:moderator_access_code])
if room_running?(@room.bbb_id) || room_setting_with_config("anyoneCanStart") || moderator_privileges
# Determine if the user needs to join as a moderator.
opts[:user_is_moderator] = @room.owned_by?(current_user) || room_setting_with_config("joinModerator") || @shared_room
opts[:user_is_moderator] = room_setting_with_config("joinModerator") || @shared_room || moderator_privileges
opts[:record] = record_meeting
opts[:require_moderator_approval] = room_setting_with_config("requireModeratorApproval")
opts[:mute_on_start] = room_setting_with_config("muteOnStart")

View File

@ -44,7 +44,9 @@ class RoomsController < ApplicationController
return redirect_to current_user.main_room, flash: { alert: I18n.t("room.room_limit") } if room_limit_exceeded
# Create room
@room = Room.new(name: room_params[:name], access_code: room_params[:access_code])
@room = Room.new(name: room_params[:name],
access_code: room_params[:access_code],
moderator_access_code: room_params[:moderator_access_code])
@room.owner = current_user
@room.room_settings = create_room_settings_string(room_params)
@ -109,8 +111,9 @@ class RoomsController < ApplicationController
@shared_room = room_shared_with_user
unless @room.owned_by?(current_user) || @shared_room
# Don't allow users to join unless they have a valid access code or the room doesn't have an access code
if @room.access_code && !@room.access_code.empty? && @room.access_code != session[:access_code]
# Don't allow users to join unless they have a valid access code or the room doesn't have an access codes
valid_access_code = !@room.access_code.present? || @room.access_code == session[:access_code]
if !valid_access_code && !valid_moderator_access_code(session[:moderator_access_code])
return redirect_to room_path(room_uid: params[:room_uid]), flash: { alert: I18n.t("room.access_code_required") }
end
@ -203,7 +206,8 @@ class RoomsController < ApplicationController
@room.update_attributes(
name: options[:name],
room_settings: room_settings_string,
access_code: options[:access_code]
access_code: options[:access_code],
moderator_access_code: options[:moderator_access_code]
)
flash[:success] = I18n.t("room.update_settings_success")
@ -321,9 +325,16 @@ class RoomsController < ApplicationController
# POST /:room_uid/login
def login
session[:access_code] = room_params[:access_code]
# use same form for access_code and moderator_access_code
if valid_moderator_access_code(room_params[:access_code])
session[:moderator_access_code] = room_params[:access_code]
else
session[:access_code] = room_params[:access_code]
end
flash[:alert] = I18n.t("room.access_code_required") if session[:access_code] != @room.access_code
if session[:access_code] != @room.access_code && !valid_moderator_access_code(session[:moderator_access_code])
flash[:alert] = I18n.t("room.access_code_required")
end
redirect_to room_path(@room.uid)
end
@ -345,7 +356,7 @@ class RoomsController < ApplicationController
def room_params
params.require(:room).permit(:name, :auto_join, :mute_on_join, :access_code,
:require_moderator_approval, :anyone_can_start, :all_join_moderator,
:recording, :presentation)
:recording, :presentation, :moderator_access_code)
end
# Find the room from the uid.
@ -412,6 +423,11 @@ class RoomsController < ApplicationController
end
helper_method :room_limit_exceeded
def valid_moderator_access_code(code)
code == @room.moderator_access_code && !@room.moderator_access_code.blank? && moderator_code_allowed?
end
helper_method :valid_moderator_access_code
def record_meeting
# If the require consent setting is checked, then check the room setting, else, set to true
if recording_consent_required?

View File

@ -89,6 +89,14 @@ module AdminsHelper
end
end
def moderator_codes_string
if @settings.get_value("Moderator Access Codes") == "true"
I18n.t("administrator.site_settings.moderator_codes.enabled")
else
I18n.t("administrator.site_settings.moderator_codes.disabled")
end
end
def log_level_string
case Rails.logger.level
when 0

View File

@ -66,6 +66,8 @@ class Setting < ApplicationRecord
Rails.configuration.shared_access_default
when "Preupload Presentation"
Rails.configuration.preupload_presentation_default
when "Moderator Access Codes"
Rails.configuration.moderator_codes_default
when "Room Configuration Mute On Join"
room_config_setting("mute-on-join")
when "Room Configuration Require Moderator"

View File

@ -143,6 +143,27 @@
</div>
</div>
</div>
<div class="row mb-2">
<div class="col-12">
<div class="form-group">
<label class="form-label"><%= t("administrator.site_settings.moderator_codes.title") %></label>
<label class="form-label text-muted"><%= t("administrator.site_settings.moderator_codes.info") %></label>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<%= moderator_codes_string %>
</button>
<div class="dropdown-menu" aria-labelledby="room-auth">
<%= button_to admin_update_settings_path(setting: "Moderator Access Codes", value: "true"), class: "dropdown-item", "data-disable": "" do %>
<%= t("administrator.site_settings.moderator_codes.enabled") %>
<% end %>
<%= button_to admin_update_settings_path(setting: "Moderator Access Codes", value: "false"), class: "dropdown-item", "data-disable": "" do %>
<%= t("administrator.site_settings.moderator_codes.disabled") %>
<% end %>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-group">

View File

@ -0,0 +1,29 @@
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<%= form_for :room, url: login_room_path(@room.uid) do |f| %>
<div class="input-group join-input">
<%= f.text_field :access_code,
required: true,
class: "form-control join-form",
placeholder: access_code_type == 'moderator' ? t("room.enter_the_moderator_access_code") : t("room.enter_the_access_code"),
value: "" ,
autofocus: true,
maxlength: 26 %>
<span class="input-group-append">
<%= f.button t("room.login"), type: :submit, class: "btn btn-primary btn-sm px-7 form-control join-form" %>
</span>
</div>
<% end %>

View File

@ -13,7 +13,7 @@
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<div data-path="<%= update_settings_path(room) %>" data-room-access-code="<%= room.access_code %>" class="card room-block">
<div data-path="<%= update_settings_path(room) %>" data-room-access-code="<%= room.access_code %>" data-room-moderator-access-code="<%= room.moderator_access_code %>" class="card room-block">
<div class="card-body p-1">
<table class="table table-hover table-vcenter text-wrap table-no-border">
<tbody class="no-border-top">

View File

@ -15,23 +15,15 @@
<% content_for(:page_desc) { t("room.invitation_description", name: @room.name) } %>
<% valid_access_code = @room.access_code.nil? || @room.access_code.empty? || @room.access_code == session[:access_code] %>
<%= render 'rooms/components/room_event', render_recordings: valid_access_code do %>
<% access_code_set = @room.access_code.present? %>
<% valid_access_code = access_code_set && @room.access_code == session[:access_code] %>
<% moderator_access_code_set = @room.moderator_access_code.present? && moderator_code_allowed? %>
<% valid_moderator_access_code = valid_moderator_access_code(session[:moderator_access_code]) %>
<%= render 'rooms/components/room_event', render_recordings: valid_access_code || valid_moderator_access_code do %>
<% if room_authentication_required %>
<h2><%= t("administrator.site_settings.authentication.user-info") %></h2>
<% elsif !valid_access_code %>
<%= form_for :room, url: login_room_path(@room.uid) do |f| %>
<div class="input-group join-input">
<%= f.text_field :access_code,
required: true,
class: "form-control join-form",
placeholder: t("room.enter_the_access_code"),
value: "" ,
autofocus: true %>
<%= f.submit t("room.login"), class: "btn btn-primary btn-sm col-sm-3 form-control join-form" %>
</div>
<% end %>
<% else %>
<% elsif valid_moderator_access_code || valid_access_code || !access_code_set %>
<%= form_for room_path(@room), method: :post do |f| %>
<div class="input-group">
<%= f.hidden_field(:search, :value => params[:search])%>
@ -59,5 +51,12 @@
</label>
<% end %>
<% end %>
<% if moderator_access_code_set && !valid_moderator_access_code %>
<!-- <hr class="mt-2 float-right w-100 moderator-code-hr"> -->
<label class="moderator-code-label form-label"><%= t("room.optional_moderator_access_code") %></label>
<%= render "rooms/components/enter_access_code_form", access_code_type: 'moderator' %>
<% end %>
<% else %>
<%= render "rooms/components/enter_access_code_form", access_code_type: 'standard_access' %>
<% end %>
<% end %>

View File

@ -1,140 +1,147 @@
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<% exceeds_limit = current_room_exceeds_limit(@room)%>
<% if exceeds_limit%>
<div class="alert alert-danger alert-dismissible text-center mb-0">
<%= t("room.room_limit_exceeded", difference: @diff) %>
</div>
<% end %>
<div class="background pb-1">
<div class="container">
<div class="row pt-7 pt-sm-9 mb-7">
<div class="col-lg-9 col-sm-12">
<div id="room-title" class="display-3 form-inline <%= 'edit_hover_class' if current_user.main_room != @room %>" data-path="<%= update_settings_path(@room) %>">
<h1 contenteditable=false id="user-text" class="display-3 text-left mb-3 font-weight-400 text-break"><%= title(@room.name) %></h1>
<% if current_user.main_room == @room %>
<a class="disable-click"><i class="fas fa-home align-top home-indicator ml-2"></i></a>
<% else %>
<a><i id="edit-room" class="fa fa-edit align-top home-indicator ml-2" data-edit-room="<%= @room.uid %>"></i></a>
<% end %>
</div>
<h4 class="text-left mb-6"><%= @room.sessions %> <%= t("room.sessions") %><% unless hide_recording_tables %> | <%= @recordings.length %> <%= t("room.recordings") %><% end %></h4>
<% unless exceeds_limit %>
<label class="form-label"><%= t("room.invite_participants") %></label>
<div class="row">
<div class="col-lg-6 col-md-12 mt-2">
<div class="input-icon invite-link-input">
<span class="input-icon-addon">
<i class="fas fa-link"></i>
</span>
<input id="invite-url" type="text" class="form-control w-100" value="<%= request.base_url + @room.invite_path %>" readonly="">
</div>
</div>
<div class="col-lg-6 pr-lg-7 col-md-12 pl-lg-0">
<div class="row">
<div class="col-sm-6 mt-2">
<button id="copy-invite" class="btn btn-primary btn-block" onclick="copyInvite()">
<i class="fas fa-copy mr-1"></i>
<%= t("copy") %>
</button>
</div>
<div class="col-sm-6 pl-0 mt-2">
<% if @room.access_code.present? %>
<input id="copy-code" value="<%= @room.access_code %>" type="hidden">
<button id="copy-access" class="btn btn-secondary btn-block" onclick="copyAccess()">
<i class="fas fa-copy mr-1"></i>
<%= t("room.copy_access") %>
</button>
<% end %>
<% if Rails.configuration.enable_google_calendar_button %>
<a href="<%= google_calendar_path %>" target="__blank" id="schedule" class="btn btn-primary btn-block mt-2">
<i class="fas fa-calendar-plus"></i>
<%= t("add_to_google_calendar") %>
</a>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
</div>
<div class="col-lg-3 col-sm-12 force-bottom mt-5">
<% if @room_running %>
<%= button_to t("room.join"), room_path(@room), class: "btn btn-primary btn-block px-7 start-button float-right", "data-disable": "" %>
<% else %>
<% unless exceeds_limit %>
<%= button_to t("room.start"), start_room_path(@room), class: "btn btn-primary btn-block px-7 start-button float-right", "data-disable": "" %>
<% end %>
<% end %>
</div>
</div>
<% if total_room_count(current_user) > 5 %>
<div class="input-icon invite-link-input mb-3">
<span class="input-icon-addon">
<i class="fas fa-search"></i>
</span>
<input id="room-search" type="text" placeholder="<%= t("room.search") %>" class="form-control w-100" onChange="filterRooms()" onKeyUp="filterRooms()">
<span id="clear-room-search" class="text-primary" onclick="clearRoomSearch()">
<i class="fas fa-times"></i>
</span>
</div>
<% end %>
<div id="room_block_container" class="row mb-5">
<% if current_user.role.get_permission("can_create_rooms") %>
<% current_user.ordered_rooms.each do |room| %>
<div class="col-lg-4 col-md-6 col-sm-12">
<%= link_to room do %>
<%= render "rooms/components/room_block", room: room %>
<% end %>
</div>
<% end %>
<% end %>
<% if shared_access_allowed %>
<% current_user.shared_rooms.each do |room| %>
<div class="col-lg-4 col-md-6 col-sm-12">
<%= link_to room do %>
<%= render "rooms/components/shared_room_block", room: room %>
<% end %>
</div>
<% end %>
<% end %>
<% if current_user.role.get_permission("can_create_rooms") && !room_limit_exceeded %>
<%= render "rooms/components/create_room_block"%>
<% end %>
</div>
</div>
</div>
<% unless hide_recording_tables %>
<%= render "shared/sessions", recordings: @recordings, pagy: @pagy, only_public: false, shared_room: @shared_room, user_recordings: false, title: t("room.recordings")%>
<% end %>
<%= render "shared/modals/delete_room_modal" %>
<%= render "shared/modals/create_room_modal" %>
<% if preupload_allowed? %>
<%= render "shared/modals/preupload_presentation_modal" %>
<% end %>
<% if shared_access_allowed %>
<%= render "shared/modals/share_room_modal" %>
<%= render "shared/modals/remove_access_modal" %>
<% end %>
<%
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
%>
<% exceeds_limit = current_room_exceeds_limit(@room)%>
<% if exceeds_limit%>
<div class="alert alert-danger alert-dismissible text-center mb-0">
<%= t("room.room_limit_exceeded", difference: @diff) %>
</div>
<% end %>
<div class="background pb-1">
<div class="container">
<div class="row pt-7 pt-sm-9 mb-7">
<div class="col-lg-9 col-sm-12">
<div id="room-title" class="display-3 form-inline <%= 'edit_hover_class' if current_user.main_room != @room %>" data-path="<%= update_settings_path(@room) %>">
<h1 contenteditable=false id="user-text" class="display-3 text-left mb-3 font-weight-400 text-break"><%= title(@room.name) %></h1>
<% if current_user.main_room == @room %>
<a class="disable-click"><i class="fas fa-home align-top home-indicator ml-2"></i></a>
<% else %>
<a><i id="edit-room" class="fa fa-edit align-top home-indicator ml-2" data-edit-room="<%= @room.uid %>"></i></a>
<% end %>
</div>
<h4 class="text-left mb-6"><%= @room.sessions %> <%= t("room.sessions") %><% unless hide_recording_tables %> | <%= @recordings.length %> <%= t("room.recordings") %><% end %></h4>
<% unless exceeds_limit %>
<label class="form-label"><%= t("room.invite_participants") %></label>
<div class="row">
<div class="col-lg-6 col-md-12 mt-2">
<div class="input-icon invite-link-input">
<span class="input-icon-addon">
<i class="fas fa-link"></i>
</span>
<input id="invite-url" type="text" class="form-control w-100" value="<%= request.base_url + @room.invite_path %>" readonly="">
</div>
</div>
<div class="col-lg-6 pr-lg-7 col-md-12 pl-lg-0">
<div class="row">
<div class="col-sm-6 mt-2">
<button id="copy-invite" class="btn btn-primary btn-block" onclick="copyInvite()">
<i class="fas fa-copy mr-1"></i>
<%= t("copy") %>
</button>
</div>
<div class="btn-group-vertical col-sm-6 pl-0 mt-2">
<% if @room.access_code.present? %>
<input id="copy-code" value="<%= @room.access_code %>" type="hidden">
<button id="copy-access" class="btn btn-secondary btn-block" onclick="copyAccess()">
<i class="fas fa-copy mr-1"></i>
<%= t("room.copy_access") %>
</button>
<% end %>
<% if moderator_code_allowed? && @room.moderator_access_code.present? %>
<input id="copy-moderator-code" value="<%= @room.moderator_access_code %>" type="hidden">
<button id="copy-moderator-access" class="btn btn-secondary btn-block" onclick="copyAccess('moderator')">
<i class="fas fa-copy mr-1"></i>
<%= t("room.copy_moderator_access") %>
</button>
<% end %>
<% if Rails.configuration.enable_google_calendar_button %>
<a href="<%= google_calendar_path %>" target="__blank" id="schedule" class="btn btn-primary btn-block mt-2">
<i class="fas fa-calendar-plus"></i>
<%= t("add_to_google_calendar") %>
</a>
<% end %>
</div>
</div>
</div>
</div>
<% end %>
</div>
<div class="col-lg-3 col-sm-12 force-bottom mt-5">
<% if @room_running %>
<%= button_to t("room.join"), room_path(@room), class: "btn btn-primary btn-block px-7 start-button float-right", "data-disable": "" %>
<% else %>
<% unless exceeds_limit %>
<%= button_to t("room.start"), start_room_path(@room), class: "btn btn-primary btn-block px-7 start-button float-right", "data-disable": "" %>
<% end %>
<% end %>
</div>
</div>
<% if total_room_count(current_user) > 5 %>
<div class="input-icon invite-link-input mb-3">
<span class="input-icon-addon">
<i class="fas fa-search"></i>
</span>
<input id="room-search" type="text" placeholder="<%= t("room.search") %>" class="form-control w-100" onChange="filterRooms()" onKeyUp="filterRooms()">
<span id="clear-room-search" class="text-primary" onclick="clearRoomSearch()">
<i class="fas fa-times"></i>
</span>
</div>
<% end %>
<div id="room_block_container" class="row mb-5">
<% if current_user.role.get_permission("can_create_rooms") %>
<% current_user.ordered_rooms.each do |room| %>
<div class="col-lg-4 col-md-6 col-sm-12">
<%= link_to room do %>
<%= render "rooms/components/room_block", room: room %>
<% end %>
</div>
<% end %>
<% end %>
<% if shared_access_allowed %>
<% current_user.shared_rooms.each do |room| %>
<div class="col-lg-4 col-md-6 col-sm-12">
<%= link_to room do %>
<%= render "rooms/components/shared_room_block", room: room %>
<% end %>
</div>
<% end %>
<% end %>
<% if current_user.role.get_permission("can_create_rooms") && !room_limit_exceeded %>
<%= render "rooms/components/create_room_block"%>
<% end %>
</div>
</div>
</div>
<% unless hide_recording_tables %>
<%= render "shared/sessions", recordings: @recordings, pagy: @pagy, only_public: false, shared_room: @shared_room, user_recordings: false, title: t("room.recordings")%>
<% end %>
<%= render "shared/modals/delete_room_modal" %>
<%= render "shared/modals/create_room_modal" %>
<% if preupload_allowed? %>
<%= render "shared/modals/preupload_presentation_modal" %>
<% end %>
<% if shared_access_allowed %>
<%= render "shared/modals/share_room_modal" %>
<%= render "shared/modals/remove_access_modal" %>
<% end %>

View File

@ -43,6 +43,19 @@
</span>
</div>
<% if moderator_code_allowed? %>
<div class="input-icon mb-2">
<span onclick="generateModeratorAccessCode()" class="input-icon-addon allow-icon-click cursor-pointer">
<i class="fas fa-dice"></i>
</span>
<%= f.label :moderator_access_code, t("modal.create_room.moderator_access_code_placeholder"), id: "create-room-moderator-access-code", class: "form-control" %>
<%= f.hidden_field :moderator_access_code %>
<span onclick="ResetModeratorAccessCode()" class="input-icon-addon allow-icon-click cursor-pointer">
<i class="far fa-trash-alt"></i>
</span>
</div>
<% end %>
<% mute = room_configuration("Room Configuration Mute On Join") %>
<% if mute != "disabled" %>
<label class="custom-switch pl-0 mt-3 mb-3 w-100 text-left d-inline-block <%= "enabled-setting" if mute == "enabled" %>">