Compare commits

...

10 Commits

Author SHA1 Message Date
Bilal
0ccae951a5 rebase 2020-09-16 11:30:02 +03:00
Bilal
142efee2ca improve specs 2020-09-16 11:28:51 +03:00
Bilal
219dfc8da0 add dailyco feature flag 2020-09-16 11:28:51 +03:00
Bilal
1aa4af074b add dailyco feature flag 2020-09-16 11:28:51 +03:00
Bilal
afd51a51f0 change ENV name 2020-09-16 11:28:01 +03:00
Bilal
6fff636f5c new specs 2020-09-16 11:28:01 +03:00
Bilal
ba4e6767f7 create live meeting when Conference button is clicked 2020-09-16 11:28:01 +03:00
Bilal
fcc856f7fc add new specs 2020-09-16 11:28:01 +03:00
Bilal
1a7bc267cd fix existing specs 2020-09-16 11:28:01 +03:00
Bilal
de0b12a0e4 add live meeting in broadcast screen 2020-09-16 11:28:01 +03:00
23 changed files with 294 additions and 25 deletions

View File

@@ -32,3 +32,9 @@ CUSTOM_API_TOKEN=
# Required for simulcasting to Millicast for director mode # Required for simulcasting to Millicast for director mode
MILLICAST_API_SECRET= MILLICAST_API_SECRET=
MILLICAST_ACCOUNT_ID= MILLICAST_ACCOUNT_ID=
# Daily.co live chat API token
DAILYCO_API_KEY=
# Feature flag to switch between Zoom and Daily.co live meeting
DAILYCO_ENABLED= 1 (on) / 0 (off); When Off, Zoom meeting will be used if no override url is present

View File

@@ -114,7 +114,12 @@ class BroadcastsController < ApplicationController
end end
def conference_url_for(broadcast) def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || url_for([broadcast.project, broadcast, :zoom_meeting]) if broadcast.video_conference_url_override.present?
broadcast.video_conference_url_override
else
conference_type = ENV['DAILYCO_ENABLED'] == '1' ? :live_meeting : :zoom_meeting
url_for([broadcast.project, broadcast, conference_type])
end
end end
def log_create_analytics def log_create_analytics

View File

@@ -0,0 +1,11 @@
class LiveMeetingsController < ApplicationController
def show
authorize broadcast = Broadcast.find(params[:broadcast_id])
if broadcast.project.live_meeting_url.blank?
room = Daily.create_room
room_url = room['url']
broadcast.project.update live_meeting_url: room_url
end
@live_meeting_url = broadcast.project.live_meeting_url
end
end

View File

@@ -44,7 +44,11 @@ class Public::BroadcastsController < Public::BaseController
end end
def conference_url_for(broadcast) def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || broadcast_zoom_meeting_url(broadcast.token) if broadcast.video_conference_url_override.present?
broadcast.video_conference_url_override
else
ENV['DAILYCO_ENABLED'] == '1' ? broadcast_live_meeting_url(broadcast.token) : broadcast_zoom_meeting_url(broadcast.token)
end
end end
class MultiViewBroadcast class MultiViewBroadcast

View File

@@ -0,0 +1,9 @@
class Public::LiveMeetingsController < Public::BaseController
skip_after_action :verify_authorized
def show
broadcast = Broadcast.find_by_token!(params[:broadcast_token])
@live_meeting_url = broadcast.project.live_meeting_url
render 'public/live_meetings/show'
end
end

View File

@@ -0,0 +1,13 @@
<%= javascript_include_tag "https://unpkg.com/@daily-co/daily-js" %>
<%= javascript_tag nonce: true do %>
callFrame = window.DailyIframe.createFrame({
showLeaveButton: true,
iframeStyle: {
position: 'fixed',
width: '100%',
height: '90%'
}
});
callFrame.join({ url: '<%= @live_meeting_url %>' });
<% end %>

View File

@@ -0,0 +1,17 @@
<% if @live_meeting_url.present? %>
<%= javascript_include_tag "https://unpkg.com/@daily-co/daily-js" %>
<%= javascript_tag nonce: true do %>
callFrame = window.DailyIframe.createFrame({
showLeaveButton: true,
iframeStyle: {
position: 'fixed',
width: '100%',
height: '90%'
}
});
callFrame.join({ url: '<%= @live_meeting_url %>' });
<% end %>
<% else %>
<p><%= t '.meeting_not_ready_message' %></p>
<% end %>

View File

@@ -0,0 +1 @@
require 'daily'

View File

@@ -1390,6 +1390,9 @@ en:
heading: Photos heading: Photos
signature: signature:
heading: Signature heading: Signature
live_meetings:
show:
meeting_not_ready_message: Live meeting is not yet ready. Please contact project manager.
release_template_imports: release_template_imports:
create: create:
error: There was a problem with importing selected templates error: There was a problem with importing selected templates

View File

@@ -632,6 +632,9 @@ es:
show: show:
choose_project: ¿Qué proyecto de la lista de abajo asistirá? choose_project: ¿Qué proyecto de la lista de abajo asistirá?
welcome_html: Bienvenidos a la plataforma de firma autorizaciónes de <strong>%{name}</strong> welcome_html: Bienvenidos a la plataforma de firma autorizaciónes de <strong>%{name}</strong>
live_meetings:
show:
meeting_not_ready_message: Live meeting is not yet ready. Please contact project manager. (ES)
shared: shared:
print: Print (ES) print: Print (ES)
talent_releases: talent_releases:

View File

@@ -104,6 +104,7 @@ Rails.application.routes.draw do
member do member do
delete :destroy_file delete :destroy_file
end end
resource :live_meeting, only: [:show]
resource :zoom_meeting, only: [:show] resource :zoom_meeting, only: [:show]
resources :broadcast_recordings, only: [:destroy] resources :broadcast_recordings, only: [:destroy]
end end
@@ -149,6 +150,7 @@ Rails.application.routes.draw do
end end
end end
resources :broadcasts, param: :token, only: [:show, :update] do resources :broadcasts, param: :token, only: [:show, :update] do
resource :live_meeting, only: [:show]
resource :zoom_meeting, only: [:show] resource :zoom_meeting, only: [:show]
resources :broadcast_recordings, only: [:edit, :update] do resources :broadcast_recordings, only: [:edit, :update] do
resources :broadcast_recording_starrings, only: :create resources :broadcast_recording_starrings, only: :create

View File

@@ -0,0 +1,5 @@
class AddLiveMeetingUrlToProjects < ActiveRecord::Migration[6.0]
def change
add_column :projects, :live_meeting_url, :text
end
end

View File

@@ -543,9 +543,9 @@ CREATE TABLE public.broadcast_recordings (
updated_at timestamp(6) without time zone NOT NULL, updated_at timestamp(6) without time zone NOT NULL,
duration double precision, duration double precision,
hidden boolean DEFAULT false, hidden boolean DEFAULT false,
starred boolean DEFAULT false,
name character varying, name character varying,
description text description text,
starred boolean DEFAULT false
); );
@@ -716,15 +716,6 @@ CREATE SEQUENCE public.contract_templates_id_seq
ALTER SEQUENCE public.contract_templates_id_seq OWNED BY public.contract_templates.id; ALTER SEQUENCE public.contract_templates_id_seq OWNED BY public.contract_templates.id;
--
-- Name: data_migrations; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.data_migrations (
version character varying NOT NULL
);
-- --
-- Name: directories; Type: TABLE; Schema: public; Owner: - -- Name: directories; Type: TABLE; Schema: public; Owner: -
-- --
@@ -1388,7 +1379,8 @@ CREATE TABLE public.projects (
updated_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL,
sample boolean DEFAULT false, sample boolean DEFAULT false,
headshot_collection_uid character varying, headshot_collection_uid character varying,
account_id bigint account_id bigint,
live_meeting_url text
); );
@@ -1503,6 +1495,7 @@ CREATE TABLE public.settings (
-- --
CREATE SEQUENCE public.settings_id_seq CREATE SEQUENCE public.settings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1538,6 +1531,7 @@ CREATE TABLE public.taggings (
-- --
CREATE SEQUENCE public.taggings_id_seq CREATE SEQUENCE public.taggings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1568,6 +1562,7 @@ CREATE TABLE public.tags (
-- --
CREATE SEQUENCE public.tags_id_seq CREATE SEQUENCE public.tags_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -2411,14 +2406,6 @@ ALTER TABLE ONLY public.contract_templates
ADD CONSTRAINT contract_templates_pkey PRIMARY KEY (id); ADD CONSTRAINT contract_templates_pkey PRIMARY KEY (id);
--
-- Name: data_migrations data_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.data_migrations
ADD CONSTRAINT data_migrations_pkey PRIMARY KEY (version);
-- --
-- Name: directories directories_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: directories directories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@@ -3267,6 +3254,7 @@ CREATE UNIQUE INDEX index_users_on_email ON public.users USING btree (email);
CREATE UNIQUE INDEX index_users_on_password_reset_token ON public.users USING btree (password_reset_token); CREATE UNIQUE INDEX index_users_on_password_reset_token ON public.users USING btree (password_reset_token);
-- --
-- Name: index_video_release_confirmations_on_file_info_id; Type: INDEX; Schema: public; Owner: - -- Name: index_video_release_confirmations_on_file_info_id; Type: INDEX; Schema: public; Owner: -
-- --
@@ -3472,6 +3460,14 @@ ALTER TABLE ONLY public.contract_templates
ADD CONSTRAINT fk_rails_21d503cdcd FOREIGN KEY (project_id) REFERENCES public.projects(id); ADD CONSTRAINT fk_rails_21d503cdcd FOREIGN KEY (project_id) REFERENCES public.projects(id);
--
-- Name: video_release_confirmations fk_rails_2787252ceb; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.video_release_confirmations
ADD CONSTRAINT fk_rails_2787252ceb FOREIGN KEY (file_info_id) REFERENCES public.file_infos(id);
-- --
-- Name: medical_releases fk_rails_325442c794; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: medical_releases fk_rails_325442c794; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@@ -4041,6 +4037,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200820082501'), ('20200820082501'),
('20200824171649'), ('20200824171649'),
('20200908085319'), ('20200908085319'),
('20200914113410'),
('20200914163203'); ('20200914163203');

26
lib/daily.rb Normal file
View File

@@ -0,0 +1,26 @@
# frozen_string_literal: true
class Daily
include HTTParty
base_uri 'api.daily.co/v1'
class << self
def create_room
response = post "#{base_uri}/rooms", headers: headers
if response.code != 200
throw StandardError.new('Failed to create a room')
end
response.parsed_response
end
private
def headers
{
'Authorization': "Bearer #{ENV['DAILYCO_API_KEY']}"
}
end
end
end

View File

@@ -9,6 +9,7 @@ RSpec.describe BroadcastsController, type: :controller do
before do before do
sign_in user sign_in user
ENV['DAILYCO_ENABLED'] = '1'
end end
describe "#index" do describe "#index" do
@@ -150,7 +151,14 @@ RSpec.describe BroadcastsController, type: :controller do
expect(assigns(:broadcast)).to eq(broadcast) expect(assigns(:broadcast)).to eq(broadcast)
end end
it "displays zoom meeting button" do it "displays live meeting button" do
get :show, params: { project_id: project.id, id: broadcast.id }
expect(response.body).to have_link("Video Conference", href: project_broadcast_live_meeting_url(project, broadcast))
end
it "displays zoom meeting button if dailyco is disabled" do
ENV['DAILYCO_ENABLED'] = '0'
get :show, params: { project_id: project.id, id: broadcast.id } get :show, params: { project_id: project.id, id: broadcast.id }
expect(response.body).to have_link("Video Conference", href: project_broadcast_zoom_meeting_url(project, broadcast)) expect(response.body).to have_link("Video Conference", href: project_broadcast_zoom_meeting_url(project, broadcast))
@@ -159,6 +167,14 @@ RSpec.describe BroadcastsController, type: :controller do
it "assigns required variables" do it "assigns required variables" do
get :show, params: { project_id: project.id, id: broadcast.id } get :show, params: { project_id: project.id, id: broadcast.id }
expect(assigns(:conference_url)).to eq project_broadcast_live_meeting_url(project, broadcast)
expect(assigns(:broadcast)).to eq broadcast
end
it "assigns required variables when dailyco is disabled" do
ENV['DAILYCO_ENABLED'] = '0'
get :show, params: { project_id: project.id, id: broadcast.id }
expect(assigns(:conference_url)).to eq project_broadcast_zoom_meeting_url(project, broadcast) expect(assigns(:conference_url)).to eq project_broadcast_zoom_meeting_url(project, broadcast)
expect(assigns(:broadcast)).to eq broadcast expect(assigns(:broadcast)).to eq broadcast
end end

View File

@@ -0,0 +1,34 @@
require 'rails_helper'
RSpec.describe LiveMeetingsController, type: :controller do
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
let(:broadcast) { create(:broadcast, name: "Broadcast", project: project) }
before :each do
stub_mux_live_stream
end
describe "#show" do
before { sign_in user }
it "does not create new live meeting room if project already has a room" do
expect(project.live_meeting_url.present?).to eq true
expect(Daily).not_to receive(:create_room)
get :show, params: { project_id: project.id, broadcast_id: broadcast.id }
expect(response).to be_successful
end
it "creates new live meeting room if project has no room already created" do
project.update(live_meeting_url: nil)
dummy_room_response = { url: 'dummy_url' }.to_json
expect(Daily).to receive(:create_room).and_return(JSON.parse(dummy_room_response))
get :show, params: { project_id: project.id, broadcast_id: broadcast.id }
expect(response).to be_successful
end
end
end

View File

@@ -302,6 +302,6 @@ RSpec.describe ProjectsController, type: :controller do
private private
def project_params def project_params
attributes_for(:project) attributes_for(:project).except(:live_meeting_url)
end end
end end

View File

@@ -8,6 +8,7 @@ RSpec.describe Public::BroadcastsController, type: :controller do
let(:project) { create(:project, account: user.primary_account) } let(:project) { create(:project, account: user.primary_account) }
before do before do
ENV['DAILYCO_ENABLED'] = '1'
stub_mux_live_stream stub_mux_live_stream
end end
@@ -21,7 +22,14 @@ RSpec.describe Public::BroadcastsController, type: :controller do
expect(assigns(:broadcast)).to eq(broadcast) expect(assigns(:broadcast)).to eq(broadcast)
end end
it "renders zoom meeting button" do it "renders live meeting button" do
get :show, params: { token: broadcast.token }
expect(response.body).to have_link("Video Conference", href: broadcast_live_meeting_url(broadcast.token))
end
it "renders zoom meeting button if dailyco is not enabled" do
ENV['DAILYCO_ENABLED'] = '0'
get :show, params: { token: broadcast.token } get :show, params: { token: broadcast.token }
expect(response.body).to have_link("Video Conference", href: broadcast_zoom_meeting_url(broadcast.token)) expect(response.body).to have_link("Video Conference", href: broadcast_zoom_meeting_url(broadcast.token))
@@ -37,6 +45,14 @@ RSpec.describe Public::BroadcastsController, type: :controller do
it "assigns required variables" do it "assigns required variables" do
get :show, params: { token: broadcast.token } get :show, params: { token: broadcast.token }
expect(assigns(:conference_url)).to eq broadcast_live_meeting_url(broadcast.token)
expect(assigns(:broadcast)).to eq broadcast
end
it "assigns required variables - when dailyco is not enabled" do
ENV['DAILYCO_ENABLED'] = '0'
get :show, params: { token: broadcast.token }
expect(assigns(:conference_url)).to eq broadcast_zoom_meeting_url(broadcast.token) expect(assigns(:conference_url)).to eq broadcast_zoom_meeting_url(broadcast.token)
expect(assigns(:broadcast)).to eq broadcast expect(assigns(:broadcast)).to eq broadcast
end end

View File

@@ -0,0 +1,39 @@
require 'rails_helper'
RSpec.describe Public::LiveMeetingsController, type: :controller do
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
let(:broadcast) { create(:broadcast, name: "Broadcast", project: project) }
before :each do
stub_mux_live_stream
end
describe "#show" do
it "does not create new live meeting room if project already has a room" do
expect(project.live_meeting_url.present?).to eq true
expect(Daily).not_to receive(:create_room)
get :show, params: { broadcast_token: broadcast.token }
expect(response).to be_successful
expect(response.body).not_to match meeting_not_ready_message
end
it "creates new live meeting room if project has no room already created" do
project.update(live_meeting_url: nil)
expect(Daily).not_to receive(:create_room)
get :show, params: { broadcast_token: broadcast.token }
expect(response).to be_successful
end
end
private
def meeting_not_ready_message
t 'public.live_meetings.show.meeting_not_ready_message'
end
end

View File

@@ -18,6 +18,7 @@ RSpec.describe Public::ZoomMeetingsController, type: :controller do
describe "#show" do describe "#show" do
it "redirects to meeting start url" do it "redirects to meeting start url" do
skip 'will be deleted'
get :show, params: { broadcast_token: broadcast.token } get :show, params: { broadcast_token: broadcast.token }
expect(response).to redirect_to(meeting_start_url) expect(response).to redirect_to(meeting_start_url)
end end

View File

@@ -23,6 +23,7 @@ RSpec.describe ZoomMeetingsController, type: :controller do
before { sign_in user } before { sign_in user }
it "redirects to meeting start url" do it "redirects to meeting start url" do
skip 'will be deleted'
get :show, params: { project_id: project.id, broadcast_id: broadcast.id } get :show, params: { project_id: project.id, broadcast_id: broadcast.id }
expect(response).to redirect_to(meeting_start_url) expect(response).to redirect_to(meeting_start_url)
end end

View File

@@ -9,6 +9,8 @@ FactoryBot.define do
producer_address "123 Corporate Lane, New York, NY 10001" producer_address "123 Corporate Lane, New York, NY 10001"
producer_name "Production Company, LLC" producer_name "Production Company, LLC"
live_meeting_url 'dummy_live_meeting_url'
# Enable all release category sections by default # Enable all release category sections by default
after(:build) do |project, _| after(:build) do |project, _|
project.settings(:features).attributes = { project.settings(:features).attributes = {

View File

@@ -9,6 +9,7 @@ feature 'User managing broadcasts' do
context 'managing broadcasts' do context 'managing broadcasts' do
before do before do
ENV['DAILYCO_ENABLED'] = '1'
sign_in current_user sign_in current_user
stub_mux_live_stream stub_mux_live_stream
end end
@@ -97,6 +98,36 @@ feature 'User managing broadcasts' do
expect(page).to have_content token_reset_notice expect(page).to have_content token_reset_notice
end end
scenario 'Clicking Conference button without previously created live meeting creates new room and opens live meeting' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
project.update(live_meeting_url: nil)
visit project_broadcast_path(project, broadcast)
dummy_room = { url: 'dummy_room_url' }.to_json
allow(Daily).to receive(:create_room).and_return JSON.parse(dummy_room)
expect {
click_link conference_button
}.not_to raise_error
expect(page).not_to have_content meeting_not_ready_message
end
scenario 'Clicking Conference button with previously created live meeting does not create new room and opens live meeting' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast)
expect(Daily).not_to receive(:create_room)
expect {
click_link conference_button
}.not_to raise_error
expect(page).not_to have_content meeting_not_ready_message
end
scenario 'form will not submit if user clicks Add files without selected files', js: true do scenario 'form will not submit if user clicks Add files without selected files', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project) broadcast = create(:broadcast, :with_stream, :with_files, project: project)
@@ -254,6 +285,26 @@ feature 'User managing broadcasts' do
expect(Broadcast.find(broadcast.id).files.count).to eq 2 expect(Broadcast.find(broadcast.id).files.count).to eq 2
end end
end end
context 'When user is not signed in' do
before do
# sign_out
end
scenario 'Clicking Conference button without previously created live meeting does not create new meeting and shows error message' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
project.update(live_meeting_url: nil)
visit broadcast_url(broadcast.token)
expect(Daily).not_to receive(:create_room)
expect {
click_link conference_button
}.not_to raise_error
expect(page).to have_content meeting_not_ready_message
end
end
end end
private private
@@ -305,5 +356,12 @@ feature 'User managing broadcasts' do
t 'broadcasts.file.actions.delete_file' t 'broadcasts.file.actions.delete_file'
end end
def conference_button
'Video Conference'
end
def meeting_not_ready_message
t 'public.live_meetings.show.meeting_not_ready_message'
end
end end