From 41a543f6b8538ea6cab07bd152124e7e3d9aefe4 Mon Sep 17 00:00:00 2001 From: John Ma Date: Tue, 4 Dec 2018 10:48:51 -0500 Subject: [PATCH] Fixed #303 Add the ability to rename rooms and recordings (GRN-18) (#304) * * * * * * * * * * * * Remove modal due to new design * * * * * * <> * * * Update application.js --- app/assets/javascripts/application.js | 2 + app/assets/javascripts/rename.js | 163 ++++++++++++++++++ app/assets/stylesheets/application.scss | 8 + app/assets/stylesheets/rooms.scss | 8 + app/controllers/rooms_controller.rb | 19 ++ app/views/rooms/show.html.erb | 11 +- app/views/shared/_sessions.html.erb | 2 +- .../components/_public_recording_row.html.erb | 8 +- .../shared/components/_recording_row.html.erb | 11 +- .../shared/components/_room_block.html.erb | 12 +- config/locales/en.yml | 6 + config/routes.rb | 1 + spec/controllers/rooms_controller_spec.rb | 43 +++++ 13 files changed, 285 insertions(+), 9 deletions(-) create mode 100644 app/assets/javascripts/rename.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index e579abcd..a8948c7e 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -30,3 +30,5 @@ //= require tabler.plugins //= require turbolinks //= require_tree . +//= require jquery +//= require jquery_ujs diff --git a/app/assets/javascripts/rename.js b/app/assets/javascripts/rename.js new file mode 100644 index 00000000..30c68454 --- /dev/null +++ b/app/assets/javascripts/rename.js @@ -0,0 +1,163 @@ +// 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 . + +$(document).on('turbolinks:load', function(){ + var controller = $("body").data('controller'); + var action = $("body").data('action'); + + if(controller == "rooms" && action == "show" || controller == "rooms" && action == "update"){ + + // Elements that can be renamed + var room_title = $('#room-title'); + var room_blocks = $('#room_block_container').find('.card'); + var recording_rows = $('#recording-table').find('tr'); + + // Configure renaming for room header + configure_room_header(room_title); + + // Configure renaming for room blocks + room_blocks.each(function(){ + var room_block = $(this) + configure_room_block(room_block) + }); + + // Configure renaming for recording rows + recording_rows.each(function(){ + var recording_title = $(this).find('#recording-title'); + configure_recording_row(recording_title); + }); + + // Set a room block rename event + function configure_room_block(room_block){ + if(!room_block.is('#home_room_block')){ + + // Register a click event on each room_block rename dropdown + room_block.find('#rename-room-button').on('click', function(e){ + + room_block.find('#room-name').hide(); + room_block.find('#room-name-editable').show(); + room_block.find('#room-name-editable-input').select() + + // Stop automatic refresh + e.preventDefault(); + + register_window_event(room_block, null, null); + }); + } + } + + // Set a room header rename event + function configure_room_header(room_title){ + room_title.find('.fa-edit').on('click', function(e){ + + // Remove current window events + $(window).off('mousedown keypress'); + + room_title.find('#user-text').fadeTo('medium', 0.7); + room_title.find('#user-text').attr("contenteditable", true); + room_title.find('#user-text').focus(); + + // Stop automatic refresh + e.preventDefault(); + + register_window_event(room_title, 'user-text', '#edit-room', 'edit-room'); + }); + } + + // Set a recording row rename event + function configure_recording_row(recording_title){ + recording_title.find('a').on('click', function(e){ + + // Remove current window events + $(window).off('mousedown keypress'); + + recording_title.fadeTo('medium', 0.7); + recording_title.find('text').attr("contenteditable", true); + recording_title.find('text').focus(); + + // Stop automatic refresh + e.preventDefault(); + + register_window_event(recording_title, 'recording-text', '#edit-record', 'edit-recordid'); + }); + } + + // Register window event to submit new name + // upon click or upon pressing the enter key + function register_window_event(element, textfield_id, edit_button_id, edit_button_data){ + $(window).on('mousedown keypress', function(clickEvent){ + + // Return if the text is clicked + if(clickEvent.type == "mousedown" && clickEvent.target.id == textfield_id){ + return; + } + + // Return if the edit icon is clicked + if(clickEvent.type == "mousedown" && $(clickEvent.target).is(edit_button_id) && + $(clickEvent.target).data(edit_button_data) === element.find(edit_button_id).data(edit_button_data)){ + return; + } + + // Check if event is keypress and enter key is pressed + if(clickEvent.type != "mousedown" && clickEvent.which !== 13){ + return; + } + + submit_rename_request(element); + + // Remove window event when ajax call to update name is submitted + $(window).off('mousedown keypress'); + }); + } + + // Apply ajax request depending on the element that triggered the event + function submit_rename_request(element){ + if(element.data('room-uid')){ + submit_update_request({ + setting: "rename_block", + room_block_uid: element.data('room-uid'), + room_name: element.find('#room-name-editable-input').val(), + }); + } + else if(element.is('#room-title')){ + submit_update_request({ + setting: "rename_header", + room_name: element.find('#user-text').text(), + }); + } + else if(element.is('#recording-title')){ + submit_update_request({ + setting: "rename_recording", + record_id: element.data('recordid'), + record_name: element.find('text').text(), + }); + } + } + + // Helper for submitting ajax requests + function submit_update_request(data){ + // Send ajax request for update + $.ajax({ + url: window.location.pathname, + type: "PATCH", + data: data, + success: function(data){ + console.log("Success"); + }, + }); + } + } +}); diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 52c02fe7..bad0736e 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -58,6 +58,10 @@ a { cursor: pointer; } +.disable-click { + pointer-events: none; +} + .header { height: $header-height; } @@ -117,3 +121,7 @@ a { overflow: scroll; height: 55vh; } + +[contenteditable]:focus { + outline: 0px solid transparent; +} diff --git a/app/assets/stylesheets/rooms.scss b/app/assets/stylesheets/rooms.scss index d7b3bc8c..09fd5cde 100644 --- a/app/assets/stylesheets/rooms.scss +++ b/app/assets/stylesheets/rooms.scss @@ -43,3 +43,11 @@ .btn-del-room { width: 70% !important; } + +.edit_hover_class a{ + visibility: hidden; +} + +.edit_hover_class:hover a { + visibility: visible; +} diff --git a/app/controllers/rooms_controller.rb b/app/controllers/rooms_controller.rb index 737cc28c..72aefe33 100644 --- a/app/controllers/rooms_controller.rb +++ b/app/controllers/rooms_controller.rb @@ -50,6 +50,19 @@ class RoomsController < ApplicationController end end + # PATCH /:room_uid + def update + if params[:setting] == "rename_block" + @room = Room.find_by!(uid: params[:room_block_uid]) + update_room_attributes + elsif params[:setting] == "rename_header" + update_room_attributes + elsif params[:setting] == "rename_recording" + @room.update_recording(params[:record_id], "meta_name" => params[:record_name]) + end + redirect_to room_path + end + # POST /:room_uid def join opts = default_meeting_options @@ -159,6 +172,12 @@ class RoomsController < ApplicationController private + def update_room_attributes + if @room.owned_by?(current_user) && @room != current_user.main_room + @room.update_attributes(name: params[:room_name]) + end + end + def room_params params.require(:room).permit(:name, :auto_join) end diff --git a/app/views/rooms/show.html.erb b/app/views/rooms/show.html.erb index 7869d7f5..c2c5c8d5 100644 --- a/app/views/rooms/show.html.erb +++ b/app/views/rooms/show.html.erb @@ -25,11 +25,14 @@
-

<%= @room.name %> +
+

<%= @room.name %>

<% if current_user.main_room == @room %> - + + <% else %> + <% end %> -

+

<%= @room.sessions %> <%= t("room.sessions") %> | <%= @recordings.length %> <%= t("room.recordings") %>

@@ -54,7 +57,7 @@
-
+
<% if current_user.rooms.length > 1 %>
<%= link_to current_user.main_room do %> diff --git a/app/views/shared/_sessions.html.erb b/app/views/shared/_sessions.html.erb index 8cd27adf..28db684f 100644 --- a/app/views/shared/_sessions.html.erb +++ b/app/views/shared/_sessions.html.erb @@ -37,7 +37,7 @@ <% end %> - + <% if recordings.empty? %> diff --git a/app/views/shared/components/_public_recording_row.html.erb b/app/views/shared/components/_public_recording_row.html.erb index 5f894a7a..194162e7 100644 --- a/app/views/shared/components/_public_recording_row.html.erb +++ b/app/views/shared/components/_public_recording_row.html.erb @@ -15,7 +15,13 @@ -
<%= recording[:name] %>
+
+ <% if recording[:metadata][:name] %> + <%= recording[:metadata][:name] %> + <% else %> + <%= recording[:name] %> + <% end %> +
<%= t("recording.recorded_on", date: recording_date(recording[:startTime])) %>
diff --git a/app/views/shared/components/_recording_row.html.erb b/app/views/shared/components/_recording_row.html.erb index 9eb13ba9..fdfa7bd0 100644 --- a/app/views/shared/components/_recording_row.html.erb +++ b/app/views/shared/components/_recording_row.html.erb @@ -15,7 +15,16 @@ -
<%= recording[:name] %>
+
+ + <% if recording[:metadata][:name] %> + <%= recording[:metadata][:name] %> + <% else %> + <%= recording[:name] %> + <% end %> + + +
<%= t("recording.recorded_on", date: recording_date(recording[:startTime])) %>
diff --git a/app/views/shared/components/_room_block.html.erb b/app/views/shared/components/_room_block.html.erb index 6d3c9d68..1ff66ade 100644 --- a/app/views/shared/components/_room_block.html.erb +++ b/app/views/shared/components/_room_block.html.erb @@ -13,7 +13,7 @@ # with BigBlueButton; if not, see . %> -
+
class="card">
@@ -27,7 +27,12 @@
-

<%= room.name %>

+
+

<%= room.name %>

+
+
<% if room.sessions > 0 %> <%= t("room.last_session", session: recording_date(room.last_session)) %> @@ -47,6 +52,9 @@ <%= t("room.settings") %> <% end %> --> + + <%= t("rename") %> + <%= t("delete") %> diff --git a/config/locales/en.yml b/config/locales/en.yml index e466cc28..a406da1d 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -100,6 +100,11 @@ en: login: or: or with: Sign in with %{provider} + rename_recording: + + rename_room: + name_placeholder: Enter a new room name... + name_update_success: Room name successfully changed! omniauth_error: An error occured while authenticating with omniauth. Please try again or contact an administrator! password: Password provider: @@ -120,6 +125,7 @@ en: visibility: public: Public unlisted: Unlisted + rename: Rename room: invited: You have been invited to join invite_participants: Invite Participants diff --git a/config/routes.rb b/config/routes.rb index 597c78b6..90f6d854 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -61,6 +61,7 @@ Rails.application.routes.draw do # Extended room routes. scope '/:room_uid' do post '/', to: 'rooms#join' + patch '/', to: 'rooms#update', as: :update_room post '/start', to: 'rooms#start', as: :start_room get '/logout', to: 'rooms#logout', as: :logout_room diff --git a/spec/controllers/rooms_controller_spec.rb b/spec/controllers/rooms_controller_spec.rb index 429ce430..c5f16b74 100644 --- a/spec/controllers/rooms_controller_spec.rb +++ b/spec/controllers/rooms_controller_spec.rb @@ -18,6 +18,15 @@ require "rails_helper" +def random_valid_room_params + { + room: { + name: Faker::Name.first_name, + auto_join: false, + }, + } +end + describe RoomsController, type: :controller do describe "GET #show" do before do @@ -186,4 +195,38 @@ describe RoomsController, type: :controller do expect(response).to redirect_to(root_path) end end + + describe "PATCH #update" do + before do + @user = create(:user) + @secondary_room = create(:room, owner: @user) + @editable_room = create(:room, owner: @user) + end + + it "properly updates room name through room block and redirects to current page" do + @request.session[:user_id] = @user.id + + patch :update, params: { room_uid: @secondary_room, room_block_uid: @editable_room, + setting: :rename_block, room_name: :name } + + expect(response).to redirect_to(@secondary_room) + end + + it "properly updates room name through room header and redirects to current page" do + @request.session[:user_id] = @user.id + + patch :update, params: { room_uid: @secondary_room, setting: :rename_header, room_name: :name } + + expect(response).to redirect_to(@secondary_room) + end + + it "properly updates recording name and redirects to current page" do + @request.session[:user_id] = @user.id + + patch :update, params: { room_uid: @secondary_room, recordid: :recordid, + setting: :rename_recording, record_name: :name } + + expect(response).to redirect_to(@secondary_room) + end + end end