Compare commits

..

10 Commits

Author SHA1 Message Date
Bilal
0bda6c3480 rebase 2020-09-01 23:07:50 +03:00
Bilal
98afad4174 remove 2020-09-01 23:07:50 +03:00
Bilal
3471e21429 improve download releases button 2020-09-01 23:07:50 +03:00
Senad Uka
f611382e9e Upstream sync 2020-09-01 17:15:16 +02:00
Senad Uka
95a14ab2f6 Upstream sync 2020-08-31 18:19:00 +02:00
Senad Uka
896cec2259 Upstream sync 2020-08-25 05:24:49 +02:00
Senad Uka
a493076f9b Upstream sync 2020-08-24 15:52:23 +02:00
Senad Uka
41bf88e358 Upstream sync 2020-08-20 06:50:51 +02:00
Senad Uka
190ff2854b Upstream sync 2020-08-06 16:56:40 +00:00
Senad Uka
8214ba9e67 Changes 2020-08-03 21:52:04 +00:00
213 changed files with 3062 additions and 1949 deletions

View File

@@ -7,8 +7,6 @@ AWS_SECRET_ACCESS_KEY=
AWS_REGION= AWS_REGION=
BRAYNIAC_AI_API_ENDPOINT=https://z99cprg2eg.execute-api.us-east-1.amazonaws.com/dev/v0.0.1 BRAYNIAC_AI_API_ENDPOINT=https://z99cprg2eg.execute-api.us-east-1.amazonaws.com/dev/v0.0.1
SOURCE_AUDIO_API_ENDPOINT=https://bigmedia.sourceaudio.com/api
SOURCE_AUDIO_TOKEN=
# Optional # Optional
REDIS_URL= REDIS_URL=
@@ -18,7 +16,7 @@ ZOOM_API_KEY=
ZOOM_API_SECRET= ZOOM_API_SECRET=
ZOOM_PRO_USERS_LIMIT= # defaults to 3 ZOOM_PRO_USERS_LIMIT= # defaults to 3
ZOOM_USER_TYPE= # 'pro' / 'basic' ZOOM_USER_TYPE= # 'pro' / 'basic'
ZOOM_ENABLE_RECORDINGS=0 # 0 / 1 ZOOM_ENABLE_RECORDINGS= # true / false (default: false)
# Token for webhooks authorization # Token for webhooks authorization
ZOOM_VERIFICATION_TOKEN= ZOOM_VERIFICATION_TOKEN=
@@ -30,3 +28,7 @@ MUX_TEST_MODE_DISABLED=
# Required for creating user through API # Required for creating user through API
CUSTOM_API_TOKEN= CUSTOM_API_TOKEN=
# Required for simulcasting to Millicast for director mode
MILLICAST_API_SECRET=
MILLICAST_ACCOUNT_ID=

View File

@@ -24,6 +24,8 @@ $(document).on "turbolinks:load", ->
stream_selected = $("#broadcast_video").data('videoType') == 'stream'; stream_selected = $("#broadcast_video").data('videoType') == 'stream';
if data.streamer_status == 'recording' && data.status == 'active' && stream_selected if data.streamer_status == 'recording' && data.status == 'active' && stream_selected
$("#broadcast_video").html data.video_content $("#broadcast_video").html data.video_content
$("#live_take").html data.live_take_content
new (Clappr.Player)( new (Clappr.Player)(
<%= "baseUrl: 'http://cdn.clappr.io/latest'," if Rails.env.test? %> <%= "baseUrl: 'http://cdn.clappr.io/latest'," if Rails.env.test? %>
parentId: '#broadcast_video' parentId: '#broadcast_video'
@@ -35,6 +37,7 @@ $(document).on "turbolinks:load", ->
hlsMinimumDvrSize: 1) hlsMinimumDvrSize: 1)
if data.streamer_status == "idle" && data.status == "idle" if data.streamer_status == "idle" && data.status == "idle"
$("#broadcast_video").html data.video_content $("#broadcast_video").html data.video_content
$("#live_take").html data.live_take_content
showBroadcastRecordings: (data) -> showBroadcastRecordings: (data) ->
$(".flash-message").html data.flash_content $(".flash-message").html data.flash_content

View File

@@ -0,0 +1,20 @@
$(document).on("click", "#download_releases", function(event) {
event.preventDefault();
const releasable_ids = JSON.parse($("#selected_releases_form").attr('data-releasable-ids'));
const total_entries = $('#total_entries').val();
const input_ids = $('<input>').attr({ type: 'hidden', name: 'release_ids', value: JSON.stringify(releasable_ids) });
const search_query = $('<input>').attr({ type: 'hidden', name: 'search_query', value: $("form input[type='search']").val() });
const type_filter = $('<input>').attr({ type: 'hidden', name: 'type_filter', value: $('#type_filter_value').val() });
const download_count = releasable_ids.length > 0 ? releasable_ids.length : total_entries;
$(this).parent().append(input_ids);
$(this).parent().append(search_query);
$(this).parent().append(type_filter);
if (confirm(`${download_count} release(s) will be downloaded. Is this correct?`)){
Rails.fire($(this).parent()[0], 'submit');
}
});

View File

@@ -0,0 +1,4 @@
$(document).on("click", "#director_mode_switch", function() {
// JQuery click event trigger was not working.
document.getElementById("director_mode_link").click();
});

View File

@@ -412,6 +412,16 @@ a[data-behavior=seekable-timecode] {
background-color: rgba($black, 0.05); background-color: rgba($black, 0.05);
} }
// Black background
.bg-black {
background-color: $black;
}
// White background
.bg-white {
background-color: $white;
}
// Custom width // Custom width
.w-65 { .w-65 {
width: 65% !important; width: 65% !important;
@@ -422,8 +432,32 @@ a[data-behavior=seekable-timecode] {
max-height: 30rem; max-height: 30rem;
} }
// Max-width 75%
.max-w-75 {
max-width: 75%;
}
// Fix height and width // Fix height and width
.fix-h-and-w { .fix-h-and-w {
width: 308px; width: 308px;
height:308px; height:308px;
} }
// Dropdown shown state overrride
.override-dropdown-show-state {
color: $white !important;
background-color: $black !important;
border-color: transparent !important;
}
// Override custom switch color
.override-custom-control-label::before {
background-color: #000000;
}
// Override nav tab design
.override-nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active {
background: transparent;
border-color: transparent;
border-bottom: 3px solid #ff0000;
}

View File

@@ -11,6 +11,7 @@ class BroadcastsChannel < ApplicationCable::Channel
def self.broadcast_stream_updates(broadcast) def self.broadcast_stream_updates(broadcast)
status_content = ApplicationController.render partial: "broadcasts/broadcast_status", locals: { broadcast: broadcast } status_content = ApplicationController.render partial: "broadcasts/broadcast_status", locals: { broadcast: broadcast }
video_content = ApplicationController.render partial: "broadcasts/video", locals: { broadcast: broadcast } video_content = ApplicationController.render partial: "broadcasts/video", locals: { broadcast: broadcast }
live_take = ApplicationController.render partial: "broadcasts/live_take", locals: { broadcast: broadcast }
broadcast_to broadcast, { broadcast_to broadcast, {
event: :broadcast_stream_update, event: :broadcast_stream_update,
@@ -18,6 +19,7 @@ class BroadcastsChannel < ApplicationCable::Channel
playback_url: broadcast.stream_playback_url, playback_url: broadcast.stream_playback_url,
full_live_stream_playback_url: broadcast.full_live_stream_playback_url, full_live_stream_playback_url: broadcast.full_live_stream_playback_url,
video_content: video_content, video_content: video_content,
live_take_content: live_take,
status_content: status_content, status_content: status_content,
streamer_status: broadcast.streamer_status streamer_status: broadcast.streamer_status
} }

View File

@@ -18,7 +18,6 @@ class AcquiredMediaReleasesController < ApplicationController
@acquired_media_release = build_acquired_media_release(acquired_media_release_params) @acquired_media_release = build_acquired_media_release(acquired_media_release_params)
if @acquired_media_release.save if @acquired_media_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@acquired_media_release) SetTagsForReleasableJob.perform_later(@acquired_media_release)
redirect_to [@project, :acquired_media_releases], notice: t(".notice") redirect_to [@project, :acquired_media_releases], notice: t(".notice")
else else
@@ -119,11 +118,8 @@ class AcquiredMediaReleasesController < ApplicationController
:term_id, :term_text, :term_id, :term_text,
:restriction_id, :restriction_text, :restriction_id, :restriction_text,
categories: [], categories: [],
file_infos_attributes: %i[ files: []
filename )
content_type
byte_size
])
end end
def build_acquired_media_release(attrs = {}) def build_acquired_media_release(attrs = {})
@@ -139,8 +135,4 @@ class AcquiredMediaReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AcquiredMediaRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -20,6 +20,7 @@ class Admin::AccountsController < Admin::ApplicationController
def show def show
@videos = filtered_account_videos.order(created_at: :desc, project_id: :desc).paginate(page: params[:page]) @videos = filtered_account_videos.order(created_at: :desc, project_id: :desc).paginate(page: params[:page])
@broadcasts = account_broadcasts.order(created_at: :desc, project_id: :desc).paginate(page: params[:page])
end end
def edit def edit
@@ -70,4 +71,8 @@ class Admin::AccountsController < Admin::ApplicationController
@account.videos @account.videos
end end
end end
def account_broadcasts
@account.broadcasts
end
end end

View File

@@ -0,0 +1,29 @@
class Admin::BroadcastsController < Admin::ApplicationController
before_action :set_broadcast, only: [:edit, :update]
def edit
end
def update
if @broadcast.update(broadcast_update_params)
redirect_to [:admin, @broadcast.project.account], notice: t(".notice")
else
render :edit
end
end
private
def set_broadcast
@broadcast = authorize policy_scope(Broadcast).find(params[:id])
end
def broadcast_update_params
params.require(:broadcast).permit(
:video_conference_url_override,
:stream_url_override,
:stream_key_override,
:director_mode_video_embed
)
end
end

View File

@@ -21,7 +21,6 @@ class Api::ReleasesController < Api::ApiController
release.contract_template_id = @contract_template.id release.contract_template_id = @contract_template.id
handle_attachments(release, release_create_params[:photos]) handle_attachments(release, release_create_params[:photos])
release.save!(context: :native) release.save!(context: :native)
log_create_analytics
after_create(release) after_create(release)
handle_response(release, :created) handle_response(release, :created)
end end
@@ -181,8 +180,4 @@ class Api::ReleasesController < Api::ApiController
parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature) parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature)
parameters parameters
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_native_release, release_type: model_constant.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip, application: :ios)
end
end end

View File

@@ -1,5 +1,13 @@
# frozen_string_literal: true
require './lib/knock_monkeypatch'
class Api::UserTokenController < Knock::AuthTokenController class Api::UserTokenController < Knock::AuthTokenController
include Oath::ControllerHelpers
include RememberMe::Controller
skip_before_action :verify_authenticity_token skip_before_action :verify_authenticity_token
before_action :sign_in_user
rescue_from Exception, :with => :return_error rescue_from Exception, :with => :return_error
@@ -35,4 +43,10 @@ class Api::UserTokenController < Knock::AuthTokenController
}] }]
} }
end end
private
def sign_in_user
sign_in(entity)
end
end end

View File

@@ -18,7 +18,6 @@ class AppearanceReleasesController < ApplicationController
@appearance_release = build_appearance_release(appearance_release_params) @appearance_release = build_appearance_release(appearance_release_params)
if @appearance_release.save(context: :non_native) if @appearance_release.save(context: :non_native)
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project) AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@appearance_release) SetTagsForReleasableJob.perform_later(@appearance_release)
redirect_to [@project, :appearance_releases], notice: "The release has been imported. #{link_to_import_another}" redirect_to [@project, :appearance_releases], notice: "The release has been imported. #{link_to_import_another}"
@@ -127,8 +126,4 @@ class AppearanceReleasesController < ApplicationController
def link_to_import_another def link_to_import_another
view_context.link_to "Import Another", [:new, @project, :appearance_release] view_context.link_to "Import Another", [:new, @project, :appearance_release]
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -6,9 +6,12 @@ class ApprovalsController < ApplicationController
def create def create
@releasable.approve_by(current_user) @releasable.approve_by(current_user)
@releasable.approved_by_user_signature.attach(approved_by_user_signature_params) if signature_data.present?
if @releasable.save if @releasable.save(context: :approval)
redirect_to [@project, "#{@releasable_param.name.pluralize}"], notice: t('.release_approved', release_type: @releasable.model_name.human) redirect_to [@project, "#{@releasable_param.name.pluralize}"], notice: t('.release_approved', release_type: @releasable.model_name.human)
else
render :new
end end
end end
@@ -25,4 +28,21 @@ class ApprovalsController < ApplicationController
def set_project def set_project
@project = @releasable.project @project = @releasable.project
end end
def releasable_params
params.require(releasable_param.name).permit(approved_by_user_signature: :data)
end
def signature_data
releasable_params.dig(:approved_by_user_signature, :data)
end
def approved_by_user_signature_params
{
data: signature_data,
filename: "approved_by_user_signature.png",
content_type: "image/png",
identify: false,
}
end
end end

View File

@@ -0,0 +1,34 @@
class BroadcastRecordingStarringsController < ApplicationController
layout "project"
before_action :set_project
before_action :set_broadcast
before_action :set_recording
def create
@recording.toggle_star
set_recordings
end
private
def broadcast_recording_params
params.require(:broadcast_recording).permit(:name, :description)
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_broadcast
@broadcast = authorize policy_scope(@project.broadcasts).find(params[:broadcast_id])
end
def set_recording
@recording = authorize policy_scope(@broadcast.broadcast_recordings).find(params[:broadcast_recording_id])
end
def set_recordings
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
end
end

View File

@@ -0,0 +1,42 @@
class BroadcastRecordingsController < ApplicationController
layout "project"
before_action :set_project
before_action :set_broadcast
before_action :set_recording
def edit
end
def update
@recording.update(broadcast_recording_params)
set_recordings
end
def destroy
@recording.update(hidden: true)
set_recordings
end
private
def broadcast_recording_params
params.require(:broadcast_recording).permit(:name, :description)
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_broadcast
@broadcast = authorize policy_scope(@project.broadcasts).find(params[:broadcast_id])
end
def set_recording
@recording = authorize policy_scope(@broadcast.broadcast_recordings).find(params[:id])
end
def set_recordings
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
end
end

View File

@@ -23,12 +23,16 @@ class BroadcastsController < ApplicationController
else else
render :new render :new
end end
rescue MuxRuby::ApiError, ActiveResource::ConnectionError => e
Raven.capture_exception(e)
redirect_to [@project, :broadcasts], alert: t(".alert")
end end
def show def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting] @conference_url = conference_url_for(@broadcast)
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application' render layout: 'application'
end end
@@ -109,6 +113,10 @@ class BroadcastsController < ApplicationController
results results
end end
def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || url_for([broadcast.project, broadcast, :zoom_meeting])
end
def log_create_analytics def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_live_stream, user_agent: request.user_agent, user_ip: request.remote_ip) TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_live_stream, user_agent: request.user_agent, user_ip: request.remote_ip)
end end

View File

@@ -7,28 +7,41 @@ class ContractDownloadsController < ApplicationController
def create def create
authorize policy_scope(Download).create authorize policy_scope(Download).create
fetch_releases
download = @project.downloads.create!(release_type: params[:release_type]) download = @project.downloads.create!(release_type: release_type)
other_downloads_in_progress = @project.downloads.unfinished_desc_order.offset(1) other_downloads_in_progress = @project.downloads.unfinished_desc_order.offset(1)
if other_downloads_in_progress.any? if other_downloads_in_progress.any?
in_progress_downloads_details = render_to_string "_other_pending_downloads", locals: { downloads: other_downloads_in_progress, release_type: params[:release_type] }, :layout => false in_progress_downloads_details = render_to_string "_other_pending_downloads", locals: { downloads: other_downloads_in_progress, release_type: release_type }, :layout => false
ProjectsChannel.broadcast_download_generation_update(download, in_progress_downloads_details) ProjectsChannel.broadcast_download_generation_update(download, in_progress_downloads_details)
else else
ProjectsChannel.broadcast_download_generation_update(download, I18n.t("contract_downloads.download.pending", release_type: params[:release_type].titleize)) ProjectsChannel.broadcast_download_generation_update(download, I18n.t("contract_downloads.download.pending", release_type: release_type.titleize))
end end
GenerateContractsZipJob.perform_later(@project, download, params[:release_type], @releases.ids) GenerateContractsZipJob.perform_later(@project, download, release_type, release_ids, search_query, type_filter)
end end
private private
def fetch_releases def release_type
@releases = policy_scope(@project.public_send(releases)) params[:release_type]
end end
def releases def search_query
params[:release_type].constantize.model_name.plural params[:search_query]
end
def type_filter
params[:type_filter]
end
def release_ids
JSON.parse(params[:release_ids])
rescue StandardError
[]
end
def release_name(release_type)
release_type.constantize.model_name.plural
end end
end end

View File

@@ -26,6 +26,7 @@ class ContractTemplatesController < ApplicationController
contract = Contract.new releasable_instance, true contract = Contract.new releasable_instance, true
send_file contract.to_pdf, download_attributes send_file contract.to_pdf, download_attributes
elsif @contract_template.save elsif @contract_template.save
log_create_analytics
redirect_to [@project, :contract_templates], notice: t('.notice') redirect_to [@project, :contract_templates], notice: t('.notice')
else else
@release_type = contract_template_params[:release_type] @release_type = contract_template_params[:release_type]
@@ -94,7 +95,9 @@ class ContractTemplatesController < ApplicationController
:question_9_text, :question_10_text, :question_9_text, :question_10_text,
:question_11_text, :question_12_text, :question_11_text, :question_12_text,
:question_13_text, :question_14_text, :question_13_text, :question_14_text,
:question_15_text) :question_15_text, :questionnaire_legal_text,
:exhibit_a_legal_text, :exhibit_a_question_text,
:exhibit_b_legal_text, :exhibit_b_question_text)
end end
def download_attributes def download_attributes
@@ -104,4 +107,8 @@ class ContractTemplatesController < ApplicationController
type: 'application/pdf' type: 'application/pdf'
} }
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_contract_template, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -1,4 +1,4 @@
class FileInfosController < ApplicationController class FilesController < ApplicationController
before_action :set_releasable before_action :set_releasable
layout "project" layout "project"
@@ -16,7 +16,7 @@ class FileInfosController < ApplicationController
if @releasable.update(releasable_params) if @releasable.update(releasable_params)
SetTagsForReleasableJob.perform_later(@releasable) SetTagsForReleasableJob.perform_later(@releasable)
redirect_to [@project, @releasable.model_name.plural], notice: t(".notice") redirect_to [@project, @releasable.model_name.plural], notice: "Files added successfully to the release."
else else
render :edit render :edit
end end
@@ -29,16 +29,10 @@ class FileInfosController < ApplicationController
end end
def set_releasable def set_releasable
@releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :"#{action_name}_file_infos?" @releasable = authorize policy_scope(releasable_param.type).find(releasable_param.id), :edit_files?
end end
def releasable_params def releasable_params
params.fetch(releasable_param.name, {}).permit( params.fetch(releasable_param.name, {}).permit(files: [])
file_infos_attributes: [
:filename,
:content_type,
:byte_size
],
)
end end
end end

View File

@@ -18,7 +18,6 @@ class LocationReleasesController < ApplicationController
@location_release = build_location_release(location_release_params) @location_release = build_location_release(location_release_params)
if @location_release.save if @location_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@location_release) SetTagsForReleasableJob.perform_later(@location_release)
redirect_to [@project, :location_releases], notice: t(".notice") redirect_to [@project, :location_releases], notice: t(".notice")
else else
@@ -90,8 +89,4 @@ class LocationReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: LocationRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -18,7 +18,6 @@ class MaterialReleasesController < ApplicationController
@material_release = build_material_release(material_release_params) @material_release = build_material_release(material_release_params)
if @material_release.save if @material_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@material_release) SetTagsForReleasableJob.perform_later(@material_release)
redirect_to [@project, :material_releases], notice: t(".notice") redirect_to [@project, :material_releases], notice: t(".notice")
else else
@@ -107,7 +106,7 @@ class MaterialReleasesController < ApplicationController
:term_id, :term_text, :term_id, :term_text,
:restriction_id, :restriction_text, :restriction_id, :restriction_text,
:description, :description,
:contract, { photos: [] } :contract, files: []
) )
end end
@@ -136,8 +135,4 @@ class MaterialReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MaterialRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -22,7 +22,6 @@ class MusicReleasesController < ApplicationController
@music_release = build_music_release(music_release_params) @music_release = build_music_release(music_release_params)
if @music_release.save if @music_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@music_release) SetTagsForReleasableJob.perform_later(@music_release)
redirect_to [@project, :music_releases], notice: t(".notice") redirect_to [@project, :music_releases], notice: t(".notice")
else else
@@ -111,8 +110,4 @@ class MusicReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: MusicRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -6,7 +6,7 @@ class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy] before_action :set_project, only: [:show, :edit, :update, :destroy]
def index def index
@projects = policy_scope(Current.account.projects).order_by_name @projects = filtered_projects.order_by_name
end end
def new def new
@@ -46,6 +46,20 @@ class ProjectsController < ApplicationController
private private
def filtered_projects
results = projects
if params[:query].present?
results = results.search(params[:query])
end
results
end
def projects
authorize policy_scope(Current.account.projects)
end
def set_project def set_project
@project = authorize projects.find(params[:id]) @project = authorize projects.find(params[:id])
end end

View File

@@ -10,7 +10,6 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
@acquired_media_release = build_acquired_media_release(acquired_media_release_params_with_locale_and_contract_template) @acquired_media_release = build_acquired_media_release(acquired_media_release_params_with_locale_and_contract_template)
if @acquired_media_release.save(context: :native) if @acquired_media_release.save(context: :native)
log_create_analytics
after_create(@acquired_media_release) after_create(@acquired_media_release)
else else
render :new render :new
@@ -100,11 +99,8 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
:signature_base64, :signature_base64,
:locale, :contract_template, :locale, :contract_template,
categories: [], categories: [],
file_infos_attributes: %i[ files: []
filename )
content_type
byte_size
])
end end
def acquired_media_release_params_with_locale def acquired_media_release_params_with_locale
@@ -114,8 +110,4 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
def acquired_media_release_params_with_locale_and_contract_template def acquired_media_release_params_with_locale_and_contract_template
acquired_media_release_params_with_locale.merge(contract_template: @contract_template) acquired_media_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AcquiredMediaRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::AppearanceReleasesController < Public::BaseController
@appearance_release = build_appearance_release(appearance_release_params_with_locale_and_contract_template) @appearance_release = build_appearance_release(appearance_release_params_with_locale_and_contract_template)
if @appearance_release.save(context: :native) if @appearance_release.save(context: :native)
log_create_analytics
after_create(@appearance_release) after_create(@appearance_release)
else else
render :new render :new
@@ -87,12 +86,35 @@ class Public::AppearanceReleasesController < Public::BaseController
] ]
end end
def questionnaire_params
[
:question_1_answer,
:question_2_answer,
:question_3_answer,
:question_4_answer,
:question_5_answer,
:question_6_answer,
:question_7_answer,
:question_8_answer,
:question_9_answer,
:question_10_answer,
:question_11_answer,
:question_12_answer,
:question_13_answer,
:question_14_answer,
:question_15_answer,
]
end
def appearance_release_params def appearance_release_params
params.require(:appearance_release).permit(person_params, guardian_params, params.require(:appearance_release).permit(person_params, guardian_params,
second_guardian_params, second_guardian_params,
questionnaire_params,
:minor, :signature_base64, :minor, :signature_base64,
:person_date_of_birth, :person_date_of_birth,
:locale, :contract_template) :locale, :contract_template,
:exhibit_a_answer, :exhibit_b_answer
)
end end
def appearance_release_params_with_locale def appearance_release_params_with_locale
@@ -102,8 +124,4 @@ class Public::AppearanceReleasesController < Public::BaseController
def appearance_release_params_with_locale_and_contract_template def appearance_release_params_with_locale_and_contract_template
appearance_release_params_with_locale.merge(contract_template: @contract_template) appearance_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: AppearanceRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -3,9 +3,9 @@ class Public::BroadcastsController < Public::BaseController
before_action :set_broadcast, only: [:show, :update] before_action :set_broadcast, only: [:show, :update]
def show def show
@conference_url = broadcast_zoom_meeting_url(@broadcast.token) @conference_url = conference_url_for(@broadcast)
@multi_view_broadcasts = multi_view_broadcasts @multi_view_broadcasts = multi_view_broadcasts
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render 'broadcasts/show' render 'broadcasts/show'
@@ -43,6 +43,10 @@ class Public::BroadcastsController < Public::BaseController
end end
end end
def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || broadcast_zoom_meeting_url(broadcast.token)
end
class MultiViewBroadcast class MultiViewBroadcast
include Rails.application.routes.url_helpers include Rails.application.routes.url_helpers

View File

@@ -10,7 +10,6 @@ class Public::LocationReleasesController < Public::BaseController
@location_release = build_location_release(location_release_params_with_locale_and_contract_template) @location_release = build_location_release(location_release_params_with_locale_and_contract_template)
if @location_release.save(context: :native) if @location_release.save(context: :native)
log_create_analytics
after_create(@location_release) after_create(@location_release)
else else
render :new render :new
@@ -76,8 +75,4 @@ class Public::LocationReleasesController < Public::BaseController
def location_release_params_with_locale_and_contract_template def location_release_params_with_locale_and_contract_template
location_release_params_with_locale.merge(contract_template: @contract_template) location_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: LocationRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::MaterialReleasesController < Public::BaseController
@material_release = build_material_release(material_release_params_with_locale_and_contract_template) @material_release = build_material_release(material_release_params_with_locale_and_contract_template)
if @material_release.save(context: :native) if @material_release.save(context: :native)
log_create_analytics
after_create(@material_release) after_create(@material_release)
else else
render :new render :new
@@ -93,7 +92,7 @@ class Public::MaterialReleasesController < Public::BaseController
params.require(:material_release).permit(person_params, guardian_params, second_guardian_params, :minor, params.require(:material_release).permit(person_params, guardian_params, second_guardian_params, :minor,
:name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country, :name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country,
:signature_base64, :signature_base64,
:locale, :contract_template, :description, photos: [] :locale, :contract_template, :description, files: []
) )
end end
@@ -104,8 +103,4 @@ class Public::MaterialReleasesController < Public::BaseController
def material_release_params_with_locale_and_contract_template def material_release_params_with_locale_and_contract_template
material_release_params_with_locale.merge(contract_template: @contract_template) material_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MaterialRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -12,7 +12,6 @@ class Public::MedicalReleasesController < Public::BaseController
if @medical_release.contract_template.present? if @medical_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@medical_release) AttachContractToReleasableJob.perform_later(@medical_release)
end end
log_create_analytics
else else
render :new render :new
end end
@@ -116,8 +115,4 @@ class Public::MedicalReleasesController < Public::BaseController
def medical_release_params_with_locale_and_contract_template def medical_release_params_with_locale_and_contract_template
medical_release_params_with_locale.merge(contract_template: @contract_template) medical_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MedicalRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -12,7 +12,6 @@ class Public::MiscReleasesController < Public::BaseController
if @misc_release.contract_template.present? if @misc_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@misc_release) AttachContractToReleasableJob.perform_later(@misc_release)
end end
log_create_analytics
else else
render :new render :new
end end
@@ -50,6 +49,14 @@ class Public::MiscReleasesController < Public::BaseController
:signature_base64, :signature_base64,
:locale, :locale,
:contract_template, :contract_template,
:applicable_medium_id,
:applicable_medium_text,
:territory_id,
:territory_text,
:term_id,
:term_text,
:restriction_id,
:restriction_text,
photos: [], photos: [],
) )
end end
@@ -113,8 +120,4 @@ class Public::MiscReleasesController < Public::BaseController
def misc_release_params_with_locale_and_contract_template def misc_release_params_with_locale_and_contract_template
misc_release_params_with_locale.merge(contract_template: @contract_template) misc_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MiscRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -10,7 +10,6 @@ class Public::TalentReleasesController < Public::BaseController
@talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template) @talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template)
if @talent_release.save(context: :native) if @talent_release.save(context: :native)
log_create_analytics
after_create(@talent_release) after_create(@talent_release)
else else
render :new render :new
@@ -108,8 +107,4 @@ class Public::TalentReleasesController < Public::BaseController
def talent_release_params_with_locale_and_contract_template def talent_release_params_with_locale_and_contract_template
talent_release_params_with_locale.merge(contract_template: @contract_template) talent_release_params_with_locale.merge(contract_template: @contract_template)
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: TalentRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -35,7 +35,7 @@ class StreamNotificationsController < ApplicationController
duration = notification.dig(:data, :duration) duration = notification.dig(:data, :duration)
recording = @broadcast.broadcast_recordings.create!(asset_uid: asset_uid, asset_playback_uid: playback_uid, file_name: file_name, duration: duration) recording = @broadcast.broadcast_recordings.create!(asset_uid: asset_uid, asset_playback_uid: playback_uid, file_name: file_name, duration: duration)
recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank") link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank")
message = "Your recent live stream has been recorded and is available for download here: #{link}" message = "Your recent live stream has been recorded and is available for download here: #{link}"

View File

@@ -18,7 +18,6 @@ class TalentReleasesController < ApplicationController
@talent_release = build_talent_release(talent_release_params) @talent_release = build_talent_release(talent_release_params)
if @talent_release.save if @talent_release.save
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project) AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@talent_release) SetTagsForReleasableJob.perform_later(@talent_release)
redirect_to [@project, :talent_releases], notice: t(".notice") redirect_to [@project, :talent_releases], notice: t(".notice")
@@ -137,8 +136,4 @@ class TalentReleasesController < ApplicationController
results results
end end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: TalentRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end end

View File

@@ -6,6 +6,6 @@ module MailHelper
"1. Tell us the name of the video: \n\n" \ "1. Tell us the name of the video: \n\n" \
"2. Attach each EDL to this email. Please make sure to indicate whether the EDL is a Video Only, Graphics Only, or Audio Only EDL." "2. Attach each EDL to this email. Please make sure to indicate whether the EDL is a Video Only, Graphics Only, or Audio Only EDL."
mail_to "info@bigmedia.ai", content, subject: subject, body: body mail_to "info@mesuite.ai", content, subject: subject, body: body
end end
end end

View File

@@ -17,6 +17,7 @@ module TagsHelper
disable_with: disabled_content, disable_with: disabled_content,
}, },
form: { form: {
id: "selected_releases_form",
data: { data: {
releasable_ids: [], releasable_ids: [],
}, },

View File

@@ -67,6 +67,23 @@ class ActiveStorageDropzone {
var upload = new that.UploaderClass(file, url, delegate); var upload = new that.UploaderClass(file, url, delegate);
createUpload(this, upload); createUpload(this, upload);
}); });
this.on("addedfile", function(file) {
// Show download link in dropzone previews
let div = document.createElement("div");
let anchor = document.createElement("a");
let download_icon = "<i class='fa fa-download' aria-hidden='true'></i> Download";
anchor.innerHTML = download_icon;
anchor.href = file.dataURL;
anchor.setAttribute('target', '_blank');
anchor.setAttribute('style', 'background-color: rgba(255, 255, 255, 0.4); padding: 0 0.4em; border: 1px solid transparent; text-decoration: none;');
div.append(anchor);
div.setAttribute('class', 'dz-download-link')
div.setAttribute('style', 'margin-top: 1em;')
$(file.previewElement.childNodes[3]).append(div);
});
}, },
}); });

View File

@@ -7,13 +7,14 @@ class GenerateContractsZipJob < ApplicationJob
@project = job.arguments.first @project = job.arguments.first
@download = job.arguments.second @download = job.arguments.second
@release_type = job.arguments.third @release_type = job.arguments.third
@folder_name = "#{@project.name.parameterize}_#{get_release_name(@release_type).gsub('_', '-')}" @release_ids = job.arguments.fourth
@search_query = job.arguments.fifth
@type_filter = job.arguments[5]
@folder_name = "#{@project.name.parameterize}_#{release_name.gsub('_', '-')}"
@download.update!(name: @folder_name, status: :pending) @download.update!(name: @folder_name, status: :pending)
end end
def perform(project, download, release_type, release_ids) def perform(project, download, release_type, release_ids, search_query, type_filter)
releases = project.public_send(get_release_name(release_type)).where(id: release_ids)
::ReleaseContractCollectionService.new(releases, @folder_name).build do |dir, files| ::ReleaseContractCollectionService.new(releases, @folder_name).build do |dir, files|
zipfile_name = "#{dir}/#{@folder_name}.zip" zipfile_name = "#{dir}/#{@folder_name}.zip"
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile| Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
@@ -61,7 +62,32 @@ class GenerateContractsZipJob < ApplicationJob
end end
end end
def get_release_name(release_type) def release_name
release_type.constantize.model_name.plural @release_type.constantize.model_name.plural
end
def all_releases
@project.public_send(release_name)
end
def releases
if @release_ids.any?
return all_releases.where(id: @release_ids)
end
results = all_releases
if all_releases.respond_to?(:complete, :incomplete)
results = case @type_filter
when 'complete'
all_releases.complete
when 'incomplete'
all_releases.incomplete
else
all_releases
end
end
results = results.search(@search_query) if @search_query.present?
results
end end
end end

View File

@@ -1,5 +1,5 @@
class AdminMailer < ApplicationMailer class AdminMailer < ApplicationMailer
default to: %w(bray@bigmedia.ai lee@bigmedia.ai) default to: %w[bray@mesuite.ai]
def new_video(video) def new_video(video)
@video = video @video = video

View File

@@ -1,4 +1,4 @@
class ApplicationMailer < ActionMailer::Base class ApplicationMailer < ActionMailer::Base
default from: ENV.fetch("MAILER_FROM_ADDRESS") { "support@bigmedia.ai" } default from: ENV.fetch("MAILER_FROM_ADDRESS") { "support@mesuite.ai" }
layout "mailer" layout "mailer"
end end

View File

@@ -5,6 +5,7 @@ class Account < ApplicationRecord
has_many :users, through: :account_auths has_many :users, through: :account_auths
has_many :projects, dependent: :destroy has_many :projects, dependent: :destroy
has_many :videos, through: :projects has_many :videos, through: :projects
has_many :broadcasts, through: :projects
has_many :contract_templates, through: :projects has_many :contract_templates, through: :projects
validates :name, presence: true validates :name, presence: true
@@ -63,6 +64,19 @@ class Account < ApplicationRecord
])).sum(:byte_size).to_f ])).sum(:byte_size).to_f
end end
def total_number_of_releases
[
MiscRelease.where(project: projects).size,
AppearanceRelease.where(project: projects).size,
TalentRelease.where(project: projects).size,
MaterialRelease.where(project: projects).size,
MedicalRelease.where(project: projects).size,
LocationRelease.where(project: projects).size,
AcquiredMediaRelease.where(project: projects).size,
MusicRelease.where(project: projects).size
].sum
end
def to_param def to_param
slug slug
end end
@@ -84,7 +98,7 @@ class Account < ApplicationRecord
end end
def taskme_enabled? def taskme_enabled?
ENV["TASKME_ENABLED"] && (plan_uid.to_s == "me_suite" || plan_uid.to_s == "taskme") plan_uid.to_s == "me_suite" || plan_uid.to_s == "taskme"
end end
def plan_name def plan_name

View File

@@ -15,16 +15,18 @@ class AcquiredMediaRelease < ApplicationRecord
include SecondGuardianPhotoable include SecondGuardianPhotoable
include GuardianName include GuardianName
include SecondGuardianName include SecondGuardianName
include FilesFilterable
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name file_infos_count] %i[name files_count owner_info]
end end
end end
# This association needs to be removed after changing the API. Removing it right now will cause failure in API specs.
has_many :file_infos, as: :releasable, dependent: :destroy has_many :file_infos, as: :releasable, dependent: :destroy
accepts_nested_attributes_for :file_infos has_many_attached :files
composed_of :person_address, composed_of :person_address,
class_name: "Address", class_name: "Address",
@@ -102,7 +104,7 @@ class AcquiredMediaRelease < ApplicationRecord
true true
end end
def file_infos_count def files_count
file_infos.any? ? file_infos.size : I18n.t('acquired_media_releases.acquired_media_release.no_media') files.any? ? files.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
end end
end end

View File

@@ -40,7 +40,7 @@ class AppHost
use_ssl: false, use_ssl: false,
}, },
production: { production: {
host: "bigmedia.ai", host: "mesuite.ai",
use_ssl: true, use_ssl: true,
} }
} }

View File

@@ -17,6 +17,9 @@ class AppearanceRelease < ApplicationRecord
include SecondGuardianName include SecondGuardianName
include CsvExportable include CsvExportable
include Approvable include Approvable
include Amendmenable
NUMBER_OF_CUSTOM_FIELDS = 15
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers

View File

@@ -35,7 +35,11 @@ class Broadcast < ApplicationRecord
end end
def stream_server_url def stream_server_url
ENV['MUX_BROADCAST_SERVER_URL'] stream_url_override.presence || ENV["MUX_BROADCAST_SERVER_URL"]
end
def stream_server_key
stream_key_override.presence || stream_key
end end
def zoom_meeting_url def zoom_meeting_url
@@ -45,11 +49,13 @@ class Broadcast < ApplicationRecord
private private
def create_mux_live_stream def create_mux_live_stream
stream = MuxLiveStream.new stream = MuxLiveStream.create_with_simulcast
self.stream_uid = stream.id self.stream_uid = stream.id
self.stream_key = stream.key self.stream_key = stream.key
self.stream_playback_uid = stream.playback_id self.stream_playback_uid = stream.playback_id
self.simulcast_uid = stream.simulcast_id
self.director_mode_video_embed ||= stream.simulcast_destination.try(:playback_embed)
self.save! self.save!
end end

View File

@@ -5,8 +5,12 @@ class BroadcastRecording < ApplicationRecord
validates :asset_uid, uniqueness: true validates :asset_uid, uniqueness: true
scope :visible, -> { where(hidden: false) }
before_save :set_title_and_description
def download_url def download_url
"https://stream.mux.com/#{asset_playback_uid}/#{file_name}?download=#{download_file_name}" "https://stream.mux.com/#{asset_playback_uid}/#{file_name}?download=#{name}"
end end
def playback_url def playback_url
@@ -14,6 +18,21 @@ class BroadcastRecording < ApplicationRecord
end end
def download_file_name def download_file_name
"#{broadcast_name}_Date_#{created_at.in_time_zone(broadcast.shoot_location_time_zone).strftime("%Y-%m-%d")}_Time_#{created_at.in_time_zone(broadcast.shoot_location_time_zone).strftime("%T")}".parameterize "#{broadcast_name}_Date_#{Time.now.in_time_zone(broadcast.shoot_location_time_zone).strftime("%Y-%m-%d")}_Time_#{Time.now.in_time_zone(broadcast.shoot_location_time_zone).strftime("%T")}".parameterize
end
def toggle_star
toggle! :starred
end
def thumbnail_url(width = 300)
"https://image.mux.com/#{asset_playback_uid}/thumbnail.jpg?width=#{width}"
end
private
def set_title_and_description
self.name ||= download_file_name
self.description ||= "No description provided for this recording."
end end
end end

View File

@@ -2,12 +2,21 @@ module Approvable
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
include ActiveStorageSupport::SupportForBase64
has_one_base64_attached :approved_by_user_signature
# Requires signature when saving in the approval context
with_options on: :approval do
validates :approved_by_user_signature, attached: true
end
def approve_by(user) def approve_by(user)
return unless approved_at.nil? return unless approved_at.nil?
self.approved_by_user_name = user.full_name self.approved_by_user_name = user.full_name
self.approved_by_user_email = user.email self.approved_by_user_email = user.email
self.approved_at = Time.zone.now self.approved_at = BigMediaTime.time_zone_now
end end
def approved? def approved?

View File

@@ -3,8 +3,8 @@
module CsvExportable module CsvExportable
extend ActiveSupport::Concern extend ActiveSupport::Concern
COMMON_HEADERS = %i[approved? notes tags signed_at].freeze COMMON_HEADERS = %i[approved notes tags signed_at].freeze
COMMON_VALUES = %w[clean_notes clean_tags signed_on].freeze COMMON_VALUES = %w[approved? clean_notes clean_tags signed_on].freeze
included do included do
class << self class << self
@@ -29,11 +29,20 @@ module CsvExportable
private private
def owner_info
compact_contact_info(name: person_name, address: person_address, phone: person_phone, email: person_email)
end
def contact_info def contact_info
owner_info
end
def compact_contact_info(name: nil, address: nil, phone: nil, email: nil)
contact_info = '' contact_info = ''
contact_info += "#{person_address}; " if person_address.present? contact_info += "#{name}; " if name.present?
contact_info += "P: #{person_phone}; " if person_phone.present? contact_info += "#{address}; " if address.present?
contact_info += "E: #{person_email}" if person_email.present? contact_info += "P: #{phone}; " if phone.present?
contact_info += "E: #{email}" if email.present?
contact_info.delete_suffix '; ' contact_info.delete_suffix '; '
end end

View File

@@ -0,0 +1,17 @@
module FilesFilterable
extend ActiveSupport::Concern
included do
def image_files
files_blobs.where("content_type ILIKE ?", "%image%")
end
def video_files
files_blobs.where("content_type ILIKE ?", "%video%")
end
def other_files
files_blobs.where("NOT content_type ILIKE ANY (array[?])", ["%image%", "%video%"])
end
end
end

View File

@@ -23,6 +23,9 @@ class ContractTemplate < ApplicationRecord
has_rich_text :guardian_clause has_rich_text :guardian_clause
has_rich_text :signature_legal_text has_rich_text :signature_legal_text
has_rich_text :amendment_clause has_rich_text :amendment_clause
has_rich_text :exhibit_a_legal_text
has_rich_text :exhibit_b_legal_text
has_rich_text :questionnaire_legal_text
validates :name, presence: true validates :name, presence: true
validates :release_type, presence: true validates :release_type, presence: true
@@ -70,6 +73,14 @@ class ContractTemplate < ApplicationRecord
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence } (1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
end end
def has_exhibit_a?
exhibit_a_legal_text.present?
end
def has_exhibit_b?
exhibit_b_legal_text.present?
end
def editable? def editable?
releases.size.zero? releases.size.zero?
end end

View File

@@ -16,7 +16,7 @@ class LocationRelease < ApplicationRecord
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name address] %i[location_info owner_info amendment_signed_column]
end end
end end
@@ -67,6 +67,18 @@ class LocationRelease < ApplicationRecord
true true
end end
def location_info
compact_contact_info(name: name, address: address)
end
def amendment_signed_column
if amendment_signable?
amendment_signed?
else
I18n.t('location_releases.csv.no_amendment_clause')
end
end
private private
def end_date_after_start_date def end_date_after_start_date

View File

@@ -3,7 +3,7 @@ class MaterialRelease < ApplicationRecord
include Contractable include Contractable
include Exploitable include Exploitable
include Notable include Notable
include Photoable include Photoable # This association needs to be removed after changing the API. Removing it right now will cause failure in API specs.
include Releasable include Releasable
include Searchable include Searchable
include Signable include Signable
@@ -16,11 +16,11 @@ class MaterialRelease < ApplicationRecord
include SecondGuardianPhotoable include SecondGuardianPhotoable
include GuardianName include GuardianName
include SecondGuardianName include SecondGuardianName
include FilesFilterable
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers
%i[name] %i[name owner_info files_count]
end end
end end
@@ -57,6 +57,8 @@ class MaterialRelease < ApplicationRecord
%w[guardian_2_address_country country] %w[guardian_2_address_country country]
] ]
has_many_attached :files
# We don't care for the argument but method WILL receive option name # We don't care for the argument but method WILL receive option name
# when called from inside with_option block, hence * argument # when called from inside with_option block, hence * argument
def self.face_photo_acceptable_content_types(*) def self.face_photo_acceptable_content_types(*)
@@ -92,4 +94,8 @@ class MaterialRelease < ApplicationRecord
def uses_edl? def uses_edl?
true true
end end
def files_count
files.any? ? files.size : I18n.t('material_releases.material_release.no_media')
end
end end

View File

@@ -0,0 +1,41 @@
class MillicastDestination
attr_reader :name, :token
def self.create
token_stream_name = SecureRandom.urlsafe_base64
publish_token = Millicast::PublishToken.create(
label: SecureRandom.urlsafe_base64,
streams: [
{ streamName: token_stream_name }
]
)
new(token_stream_name, publish_token.data.token)
end
def initialize(name, token)
@name = name
@token = token
end
def account_id
ENV["MILLICAST_ACCOUNT_ID"]
end
def key
"#{name}?token=#{token}"
end
def url
"rtmp://live-rtmp-pub.millicast.com:1935/v2/pub"
end
def playback_url
"https://viewer.millicast.com/v2?streamId=#{account_id}/#{name}"
end
def playback_embed
"<iframe src=\"#{playback_url}\" allowfullscreen width=\"640\" height=\"480\"></iframe>"
end
end

View File

@@ -11,6 +11,7 @@ class MiscRelease < ApplicationRecord
include GuardianPhotoable include GuardianPhotoable
include CsvExportable include CsvExportable
include Approvable include Approvable
include Exploitable
class << self class << self
def custom_csv_exportable_headers def custom_csv_exportable_headers

View File

@@ -1,4 +1,15 @@
class MuxLiveStream class MuxLiveStream
attr_accessor :simulcast_id, :simulcast_destination
def self.create_with_simulcast(destination = nil)
destination ||= MillicastDestination.create
MuxLiveStream.new.tap do |stream|
stream.id # force the live stream to be created by calling for its id
stream.create_simulcast(destination)
end
end
def id def id
live_stream.data.id live_stream.data.id
end end
@@ -15,6 +26,15 @@ class MuxLiveStream
client.delete_live_stream(stream_uid) client.delete_live_stream(stream_uid)
end end
def create_simulcast(destination)
return if test_mode_enabled?
request = MuxRuby::CreateSimulcastTargetRequest.new(stream_key: destination.key, url: destination.url)
result = client.create_live_stream_simulcast_target(id, request)
self.simulcast_destination = destination
self.simulcast_id = result.data.id
end
private private
def live_stream def live_stream

View File

@@ -2,6 +2,7 @@ class Project < ApplicationRecord
include Archivable include Archivable
include Filterable include Filterable
include Syncable include Syncable
include PgSearch
SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical misc) SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical misc)
AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical misc) AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical misc)
@@ -42,6 +43,15 @@ class Project < ApplicationRecord
} }
end end
pg_search_scope :search, {
against: [:name],
using: {
tsearch: {any_word: true, prefix: true},
trigram: {},
dmetaphone: {any_word: true}
}
}
validates :name, presence: true, uniqueness: { scope: :account_id } validates :name, presence: true, uniqueness: { scope: :account_id }
filterable_by :active, :inactive, :archived filterable_by :active, :inactive, :archived

View File

@@ -19,11 +19,7 @@ class AcquiredMediaReleasePolicy < ApplicationPolicy
true true
end end
def edit_file_infos? def edit_files?
true
end
def update_file_infos?
true true
end end

View File

@@ -34,4 +34,8 @@ class AppearanceReleasePolicy < ReleasePolicy
def approve? def approve?
review? review?
end end
def sign_amendment?
user.manager? || user.account_manager?
end
end end

View File

@@ -0,0 +1,21 @@
class BroadcastRecordingPolicy < ApplicationPolicy
def create?
true
end
def destroy?
if user.nil? || user.user.nil?
return false
end
user.manager? || user.account_manager?
end
def edit?
destroy?
end
def update?
edit?
end
end

View File

@@ -19,12 +19,16 @@ class MaterialReleasePolicy < ReleasePolicy
user.manager? || user.account_manager? user.manager? || user.account_manager?
end end
def edit_photos? def edit_files?
true true
end end
def update_files?
edit_files?
end
def update_photos? def update_photos?
edit_photos? edit_files?
end end
def tag_multiple? def tag_multiple?

View File

@@ -24,7 +24,7 @@ class ReleaseContractCollectionService
end end
files = Dir.entries("#{dir}/").select { |f| !File.directory? f } files = Dir.entries("#{dir}/").select { |f| !File.directory? f }
raise StandardError.new "Contracts or Contract Templates not found." unless files.any? # raise StandardError.new "Contracts or Contract Templates not found." unless files.any?
yield(dir, files) yield(dir, files)
} }
end end

View File

@@ -170,6 +170,24 @@ class Analytics
end end
end end
def track_create_contract_template(user_agent:, user_ip:)
if analytics_enabled?
identify
track(
{
user_id: user.id,
event: "Contract Template Created",
properties: {
account: account.try(:name),
account_id: account.try(:id),
user_agent: user_agent,
ip: user_ip,
},
}
)
end
end
private private
attr_reader :user, :account, :backend attr_reader :user, :account, :backend

View File

@@ -1,4 +1,4 @@
<%= bootstrap_form_with model: account, url: account_path, html: { autocorrect: :off, autocapitalize: :none, autocomplete: :off, spellcheck: false }, layout: :inline, remote: true do |form| %> <%= bootstrap_form_with model: account, url: account_path, html: { autocorrect: :off, autocapitalize: :none, autocomplete: :off, spellcheck: false }, layout: :inline, remote: true do |form| %>
<%= form.file_field :logo, hide_label: true, accept: "image/*", placeholder: "Upload Logo", direct_upload: true, wrapper_class: "mr-1" %> <%= form.file_field :logo, hide_label: true, accept: "image/*", placeholder: "Upload Logo", direct_upload: true, wrapper_class: "mr-1", required: true %>
<%= form.button(fa_icon("upload", text: t(".submit")), class: "btn btn-md btn-primary", data: { disable_with: t("shared.disable_with") }) %> <%= form.button(fa_icon("upload", text: t(".submit")), class: "btn btn-md btn-primary", data: { disable_with: t("shared.disable_with") }) %>
<% end %> <% end %>

View File

@@ -12,12 +12,15 @@
<%= acquired_media_release.name %> <%= acquired_media_release.name %>
</td> </td>
<td> <td>
<% if acquired_media_release.file_infos.any? %> <% if acquired_media_release.files.any? %>
<%= acquired_media_release.file_infos.size %> <%= acquired_media_release.files.size %>
<% else %> <% else %>
<%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %> <%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %>
<% end %> <% end %>
</td> </td>
<td>
<%= contact_info_for(acquired_media_release.contact_person) %>
</td>
<td> <td>
<%= notes_preview acquired_media_release.notes.order_by_recent %> <%= notes_preview acquired_media_release.notes.order_by_recent %>
</td> </td>
@@ -37,8 +40,8 @@
<% if policy(acquired_media_release.tags).new? %> <% if policy(acquired_media_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, acquired_media_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, acquired_media_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %> <% end %>
<% if policy(acquired_media_release).edit_file_infos? %> <% if policy(acquired_media_release).edit_files? %>
<%= link_to fa_icon("file fw", text: "Add Media"), [:edit, acquired_media_release, :file_infos], class: "dropdown-item" %> <%= link_to fa_icon("file fw", text: "Media"), [:edit, acquired_media_release, :files], class: "dropdown-item" %>
<% end %> <% end %>
<% if policy(Contract).show? && (acquired_media_release.contract.attached? || acquired_media_release.contract_template.present?) %> <% if policy(Contract).show? && (acquired_media_release.contract.attached? || acquired_media_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [acquired_media_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <%= link_to fa_icon("download fw", text: "Download"), [acquired_media_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>

View File

@@ -44,7 +44,7 @@
<%= fa_icon "warning" %> <%= fa_icon "warning" %>
<strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong> <strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong>
</div> </div>
<%= render "shared/file_infos_dropzone", form: form, releasable: acquired_media_release %> <%= render "shared/releasable_files_dropzone", form: form, releasable: acquired_media_release %>
<div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields"> <div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<br> <br>

View File

@@ -28,7 +28,8 @@
<th data-behavior="all-selectable"><%= check_box_tag "acquired_media_release_ids[]", false, false %></th> <th data-behavior="all-selectable"><%= check_box_tag "acquired_media_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></th> <th><%= t '.table_headers.approved'%></th>
<th><%= AcquiredMediaRelease.human_attribute_name(:name) %></th> <th><%= AcquiredMediaRelease.human_attribute_name(:name) %></th>
<th><%= t(".table_headers.file_infos_count") %></th> <th><%= t(".table_headers.files_count") %></th>
<th><%= t(".table_headers.owner_info") %></th>
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th> <th><%= t(".table_headers.signed_at") %></th>

View File

@@ -8,6 +8,9 @@
<td> <td>
<%= account.projects.size %> <%= account.projects.size %>
</td> </td>
<td>
<%= account.total_number_of_releases %>
</td>
<td> <td>
<%= number_with_delimiter convert_duration(account.current_month_video_duration_total, from: :seconds, to: :minutes).round %> minutes <%= number_with_delimiter convert_duration(account.current_month_video_duration_total, from: :seconds, to: :minutes).round %> minutes
</td> </td>

View File

@@ -0,0 +1,13 @@
<tr>
<td><%= broadcast.project.name %></td>
<td><%= broadcast.name %></td>
<td class="text-right">
<div class="btn-group">
<%= button_tag "Manage", class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
<div class="dropdown-menu dropdown-menu-right">
<%= link_to "View on Mux", "#{ENV['MUX_LIVE_STREAM_DASHBOARD_URL']}/#{broadcast.stream_uid}", class: "dropdown-item", target: "_blank" %>
<%= link_to "Edit", [:edit, :admin, broadcast, locale: I18n.locale], class: "dropdown-item" %>
</div>
</div>
</td>
</tr>

View File

@@ -15,6 +15,7 @@
<th>Name</th> <th>Name</th>
<th>Plan</th> <th>Plan</th>
<th># Projects</th> <th># Projects</th>
<th># Releases Signed</th>
<th>Monthly Video Upload Minutes</th> <th>Monthly Video Upload Minutes</th>
<th>Total Video Upload Minutes</th> <th>Total Video Upload Minutes</th>
<th>Total Storage</th> <th>Total Storage</th>

View File

@@ -9,6 +9,8 @@
<dd class="col-sm-10"><%= @account.users.size %></dd> <dd class="col-sm-10"><%= @account.users.size %></dd>
<dt class="col-sm-2">Created at</dt> <dt class="col-sm-2">Created at</dt>
<dd class="col-sm-10"><%= time_ago_in_words(@account.created_at) %> ago</dd> <dd class="col-sm-10"><%= time_ago_in_words(@account.created_at) %> ago</dd>
<dt class="col-sm-2"># of Releases</dt>
<dd class="col-sm-10"><%= @account.total_number_of_releases %></dd>
</dl> </dl>
<% end %> <% end %>
@@ -34,5 +36,25 @@
<%= will_paginate @videos %> <%= will_paginate @videos %>
</div> </div>
<% end %> <% end %>
<hr>
<%= card_field_set_tag "Broadcasts" do %>
<div class="table-responsive-sm">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Project</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody id="broadcasts">
<%= render partial: "admin/accounts/broadcast", collection: @broadcasts %>
</tbody>
</table>
</div>
<div id="broadcasts_pagination">
<%= will_paginate @broadcasts %>
</div>
<% end %>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,15 @@
<%= errors_summary_for broadcast %>
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.text_field :video_conference_url_override %>
<%= form.text_field :stream_url_override %>
<%= form.text_field :stream_key_override %>
<%= form.text_area :director_mode_video_embed %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [:admin, broadcast.project.account], class: "col-3 text-reset" %>
<div class="col-9">
<%= form.submit class: class_string("btn btn-block", ["btn-success", "btn-primary"] => broadcast.new_record?), data: { disable_with: t("shared.disable_with") } %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,6 @@
<div class="card shadow-sm">
<%= card_header text: t(".heading"), close_action_path: [:admin, @broadcast.project.account] %>
<div class="card-body">
<%= render "form", model: [:admin, @broadcast], broadcast: @broadcast %>
</div>
</div>

View File

@@ -34,6 +34,17 @@
<td> <td>
<%= appearance_release.signed_on %> <%= appearance_release.signed_on %>
</td> </td>
<td class="text-center">
<% if appearance_release.amendment_signed? %>
<i class="fa fa-check-square-o text-dark"
data-toggle="tooltip"
title="<%= t '.messages.amendment_signed_tooltip' %>"></i>
<% elsif appearance_release.amendment_signable? %>
<i class="fa fa-square-o"
data-toggle="tooltip"
title="<%= t '.messages.amendment_not_signed_tooltip' %>"></i>
<% end %>
</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> <div class="btn-group">
<%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %> <%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
@@ -44,6 +55,9 @@
<% if policy(appearance_release.tags).new? %> <% if policy(appearance_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, appearance_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, appearance_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %> <% end %>
<% if policy(appearance_release).sign_amendment? && appearance_release.amendment_signable? && !appearance_release.amendment_signed? %>
<%= link_to fa_icon("file-text fw", text: t('.actions.sign_amendment')), [:new, appearance_release.project.account, appearance_release.project, appearance_release.contract_template, appearance_release, :amendment], class: "dropdown-item", target: "_blank" %>
<% end %>
<% if policy(Contract).show? && (appearance_release.contract.attached? || appearance_release.contract_template.present?) %> <% if policy(Contract).show? && (appearance_release.contract.attached? || appearance_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [appearance_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <%= link_to fa_icon("download fw", text: "Download"), [appearance_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>
<% end %> <% end %>

View File

@@ -1,5 +1,6 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @appearance_releases.total_entries %> />
<div id="upload-progress-container" class="mb-1"></div> <div id="upload-progress-container" class="mb-1"></div>
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-2"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-2">
<% if policy(AppearanceRelease).new? %> <% if policy(AppearanceRelease).new? %>
@@ -16,7 +17,7 @@
<% end %> <% end %>
<% if @appearance_releases.any? && policy(AppearanceRelease).download_multiple? %> <% if @appearance_releases.any? && policy(AppearanceRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @appearance_releases.name], method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: { disable_with: "Please wait..." } %> <%= button_to "Download", [@project, :contract_downloads, release_type: @appearance_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: { disable_with: "Please wait..." } %>
<% end %> <% end %>
</div> </div>
</div> </div>
@@ -51,6 +52,7 @@
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th> <th><%= t(".table_headers.signed_at") %></th>
<th><%= t '.table_headers.amendment_signed' %></th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>

View File

@@ -3,3 +3,5 @@ $("form input[type='search']").val("<%= params[:query] %>");
$("#type_filter_actions").html("<%= j render 'type_filter_actions' %>"); $("#type_filter_actions").html("<%= j render 'type_filter_actions' %>");
$("#appearance_releases_pagination").html("<%= j will_paginate(@appearance_releases) %>"); $("#appearance_releases_pagination").html("<%= j will_paginate(@appearance_releases) %>");
$('#type_filter_value').val("<%= params[:type_filter] %>"); $('#type_filter_value').val("<%= params[:type_filter] %>");
$("#selected_releases_form").attr('data-releasable-ids', JSON.stringify([]));
$("#total_entries").val(<%= @appearance_releases.total_entries %>);

View File

@@ -1,9 +1,13 @@
<div class="card shadow-sm"> <div class="card shadow-sm">
<%= card_header text: t(".heading", release_type: @releasable_param.name.titleize), close_action_path: [@project, "#{@releasable_param.name.pluralize}"] %> <%= card_header text: t(".heading", release_type: @releasable_param.name.titleize), close_action_path: [@project, "#{@releasable_param.name.pluralize}"] %>
<div class="card-body"> <div class="card-body">
<embed class="embeded-contract-preview" type="application/pdf" src="<%= url_for [@releasable, :contracts, format: "pdf"] %>" width="90%" height="1200" /> <embed class="embeded-contract-preview mb-3" type="application/pdf" src="<%= url_for [@releasable, :contracts, format: "pdf"] %>" width="90%" height="1200" />
<%= errors_summary_for @releasable %>
<%= bootstrap_form_with model: @releasable, method: :post, url: public_send("#{@releasable_param.name}_approvals_path", @releasable), local: true do |form| %> <%= bootstrap_form_with model: @releasable, method: :post, url: public_send("#{@releasable_param.name}_approvals_path", @releasable), local: true do |form| %>
<%= card_field_set_tag 'Signature' do %>
<%= render "shared/signature_fields", form: form, signature_field: 'approved_by_user_signature[data]' %>
<% end %>
<div class="row align-items-center text-center mt-4"> <div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [@releasable.project, "#{@releasable_param.name.pluralize}"], class: "col-3 text-reset" %> <%= link_to t("shared.cancel"), [@releasable.project, "#{@releasable_param.name.pluralize}"], class: "col-3 text-reset" %>
<div class="col-9"> <div class="col-9">

View File

@@ -0,0 +1 @@
$("#broadcast_recordings").html("<%= j render(partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast }) %>");

View File

@@ -0,0 +1,24 @@
<%= content_tag :div, class: "modal modal-right", id: "edit_broadcast_recording_modal", aria: { labelledby: "modalLabel", hidden: true }, role: "dialog", tabindex: -1 do %>
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Edit Broadcast Recording</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<%= bootstrap_form_with model: [broadcast.project, broadcast, recording], layout: :horizontal, label_col: "col-3", control_col: "col-9" do |form| %>
<div class="modal-body">
<div id="broadcast_recording_fields">
<%= form.text_field :name %>
<%= form.text_area :description %>
</div>
</div>
<div class="modal-footer">
<%= form.button "Close", class: "btn btn-secondary", data: { dismiss: "modal" } %>
<%= form.submit "Update Broadcast Recording", class: "btn btn-primary", data: { disable_with: t("shared.disable_with") } %>
</div>
<% end %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,11 @@
$('[data-id="<%= dom_id(@recording) %>"]').remove();
<% if @recordings.empty? %>
$("#broadcast_recordings_nav").append('<p class="dropdown-item text-muted">Recordings will appear here</p>')
<% end %>
$("#broadcast_recordings").html("<%= j render(partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast }) %>");
// Close and remove the modal
$("#edit_broadcast_recording_modal").on("hidden.bs.modal", function (e) {
$("#edit_broadcast_recording_modal").remove();
});
$("#edit_broadcast_recording_modal").modal("hide");

View File

@@ -0,0 +1 @@
<%= render("broadcast_recordings/refresh_recordings_list") %>

View File

@@ -0,0 +1,6 @@
<% # Remove the modal if it already exists %>
$("#edit_broadcast_recording_modal").remove();
<% # Create and show the modal %>
$("body").append("<%= j render(partial: 'edit_broadcast_recording_modal', locals: { project: @project, broadcast: @broadcast, recording: @recording }) %>");
$("#edit_broadcast_recording_modal").modal("toggle");

View File

@@ -0,0 +1 @@
<%= render("broadcast_recordings/refresh_recordings_list") %>

View File

@@ -16,8 +16,8 @@
<div class="btn-group"> <div class="btn-group">
<%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %> <%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
<%= link_to fa_icon("link fw", text: "Copy Stream URL"), ENV['MUX_BROADCAST_SERVER_URL'], class: "dropdown-item", data: { behavior: "clipboard" } %> <%= link_to fa_icon("link fw", text: "Copy Stream URL"), broadcast.stream_server_url, class: "dropdown-item", data: { behavior: "clipboard" } %>
<%= link_to fa_icon("key fw", text: "Copy Stream Key"), broadcast.stream_key, class: "dropdown-item", data: { behavior: "clipboard" } %> <%= link_to fa_icon("key fw", text: "Copy Stream Key"), broadcast.stream_server_key, class: "dropdown-item", data: { behavior: "clipboard" } %>
<% if policy(broadcast).show? %> <% if policy(broadcast).show? %>
<%= link_to fa_icon("file-video-o fw", text: "View"), [broadcast.project, broadcast], class: "dropdown-item", target: '_blank' %> <%= link_to fa_icon("file-video-o fw", text: "View"), [broadcast.project, broadcast], class: "dropdown-item", target: '_blank' %>
<% end %> <% end %>

View File

@@ -1,2 +1 @@
<%= link_to broadcast_recording.download_file_name, "javascript:void(0);", class: "dropdown-item", data: { behavior: "play_recording", playback_url: broadcast_recording.playback_url } %> <%= link_to broadcast_recording.name, "javascript:void(0);", class: "dropdown-item", data: { behavior: "play_recording", playback_url: broadcast_recording.playback_url, id: dom_id(broadcast_recording) } %>

View File

@@ -1,13 +1,29 @@
<% if recordings.present? %> <% if recordings.present? %>
<p>Click below to download the recordings of the live stream.</p> <div class="list-group">
<ul class="mt-2">
<% recordings.each do |recording| %> <% recordings.each do |recording| %>
<li><%= link_to(recording.download_file_name, recording.download_url, target: "_blank") %></li> <div class="list-group-item list-group-item-action">
<div class="d-flex align-items-start">
<% if (controller.class.module_parent.to_s != "Public" && policy(BroadcastRecording).update?) %>
<%= link_to fa_icon("#{recording.starred ? 'star' : 'star-o'} fw"), [broadcast.project, broadcast, recording, :broadcast_recording_starrings], method: :post, class: "text-warning mr-3", remote: true %>
<% end %>
<%= image_tag(recording.thumbnail_url, class: 'img-thumbnail img-fluid max-w-75') %>
<div class="ml-auto">
<% if (controller.class.module_parent.to_s != "Public" && policy(BroadcastRecording).edit?) %>
<%= link_to fa_icon('edit'), [:edit, broadcast.project, broadcast, recording], remote: true %>
<% end %>
<%= link_to(fa_icon('download'), recording.download_url, target: "_blank") %>
</div>
</div>
<div class="d-flex flex-column align-items-start justify-content-start p-4">
<h5><%= recording.name %></h5>
<p><%= recording.description %></p>
</div>
</div>
<% end %> <% end %>
</ul> </div>
<div id="recordings_pagination" class="row mt-5 justify-content-center"> <div id="recordings_pagination" class="row mt-5 justify-content-center">
<%= will_paginate(recordings, params: {controller: "broadcasts", action: "show", project_id: broadcast.project_id, id: broadcast.id, page: params[:page], active_tab: 'recordings'}) %> <%= will_paginate(recordings, params: {controller: "broadcasts", action: "show", project_id: broadcast.project_id, id: broadcast.id, page: params[:page], active_tab: 'recordings'}) %>
</div> </div>
<% else %> <% else %>
<p>Recording of the live stream will appear here.</p> <p class="mt-4">Recording of the live stream will appear here.</p>
<% end %> <% end %>

View File

@@ -1,21 +1,13 @@
<% if broadcast.streamer_connected? || (broadcast.streamer_recording? && !broadcast.active?) %> <% if broadcast.streamer_connected? || (broadcast.streamer_recording? && !broadcast.active?) %>
<div class="alert alert-info text-center text-md-left"> <p class="mb-1">Live stream has connected successfully and will be available soon.</p>
<%= fa_icon "info-circle" %> <div class="badge badge-pill badge-success mb-2 text-uppercase">Connected</div>
<strong>Live stream has connected successfully and will be available soon.</strong>
</div>
<% elsif broadcast.streamer_recording? && broadcast.active? %> <% elsif broadcast.streamer_recording? && broadcast.active? %>
<div class="alert alert-success text-center text-md-left"> <p class="mb-1">Live stream has begun, click play to watch it.</p>
<%= fa_icon "success" %> <div class="badge badge-pill badge-danger mb-2 text-uppercase">Live</div>
<strong>Live stream has begun, click play to watch it.</strong>
</div>
<% elsif broadcast.streamer_disconnected? %> <% elsif broadcast.streamer_disconnected? %>
<div class="alert alert-warning text-center text-md-left"> <p class="mb-1">Live stream got disconnected.</p>
<%= fa_icon "warning" %> <div class="badge badge-pill badge-warning mb-2 text-uppercase">Disconnected</div>
<strong>Live stream got disconnected.</strong>
</div>
<% elsif (broadcast.idle? && broadcast.streamer_idle?) || (broadcast.created? && broadcast.streamer_idle?) %> <% elsif (broadcast.idle? && broadcast.streamer_idle?) || (broadcast.created? && broadcast.streamer_idle?) %>
<div class="alert alert-info text-center text-md-left"> <p class="mb-1">Live stream is waiting to begin.</p>
<%= fa_icon "info-circle" %> <div class="badge badge-pill badge-primary mb-2 text-uppercase">Idle</div>
<strong>Live stream is waiting to begin.</strong>
</div>
<% end %> <% end %>

View File

@@ -0,0 +1,12 @@
<div class="list-group">
<div class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between mb-1">
<h5 class="mb-1"><%= broadcast.name %></h5>
<small>Created - <%= time_ago_in_words(broadcast.created_at) + " ago" %></small>
</div>
<div id="broadcast_updates">
<%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %>
</div>
</div>
</div>
<hr/>

View File

@@ -1,11 +1,15 @@
<% if broadcast.streamer_recording? && broadcast.active? %> <% if broadcast.director_mode_video_embed.present? && params[:director_mode].present? %>
<div class="embed-responsive-item" data-video-type="stream">
<%= raw broadcast.director_mode_video_embed %>
</div>
<% elsif broadcast.streamer_recording? && broadcast.active? %>
<div id="broadcast_video" class="embed-responsive-item" data-video-type="stream"></div> <div id="broadcast_video" class="embed-responsive-item" data-video-type="stream"></div>
<% else %> <% else %>
<div id="broadcast_video" class="embed-responsive-item" data-video-type="stream"> <div id="broadcast_video" class="embed-responsive-item" data-video-type="stream">
<table class="w-100 h-100 bg-secondary"> <table class="w-100 h-100 bg-secondary">
<tbody> <tbody>
<tr> <tr>
<td class="text-center align-middle text-white"> <td class="text-center align-middle text-white bg-black">
Video player will appear here when the stream becomes available. Video player will appear here when the stream becomes available.
</td> </td>
</tr> </tr>

View File

@@ -14,150 +14,135 @@
<% end %> <% end %>
<% content_for :header do %> <% content_for :header do %>
<header class="container-fluid py-3 border-bottom sticky-top bg-light"> <header></header>
<div class="row align-items-center justify-content-center">
<div class="col-4 text-center">
<%= product_wordmark(:direct_me, class: 'navbar-brand') %>
</div>
</div>
</header>
<% end %> <% end %>
<div class="row"> <div class="row no-gutters m-n3">
<div class="col-lg-8 col-md-12 mb-3"> <div class="col-lg-8 col-md-12 bg-black">
<div class="card shadow-sm"> <div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark">
<div class="card-header"> <%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %>
<div class="d-flex justify-content-between align-items-center"> <div class="ml-4 dropdown">
<h1 class="h3 m-0"><%= @broadcast.name %></h1> <%= link_to "#", class: "btn btn-light dropdown-toggle text-white bg-black border-0 override-dropdown-show-state", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } do %>
<div class="dropdown"> <i class="fa fa-video-camera text-primary" aria-hidden="true"></i><span class="ml-2" id="selected_stream"><%= @broadcast.name %></span>
<%= link_to "Switch View", "#", class: "btn btn-light border dropdown-toggle", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } %> <% end %>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu bg-black" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5> <h5 class="dropdown-header">Live Streams</h5>
<%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %> <%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %>
<% @multi_view_broadcasts.each do |broadcast| %> <% @multi_view_broadcasts.each do |broadcast| %>
<% if broadcast.id != @broadcast.id %> <% if broadcast.id != @broadcast.id %>
<%= link_to broadcast.name.titleize, broadcast.url, data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %> <% if params[:director_mode] %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(director_mode: true, token: broadcast.token)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% else %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(director_mode: true, id: broadcast.id)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% end %>
<% else %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(token: broadcast.token).except(:director_mode)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% else %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(id: broadcast.id).except(:director_mode)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% end %> <% end %>
<% end %> <% end %>
<h5 class="dropdown-header">Previous Sessions</h5>
<div id="broadcast_recordings_nav">
<% if @recordings.any? %>
<%= render partial: "broadcasts/broadcast_recording_nav", collection: @recordings, as: :broadcast_recording %>
<% else %>
<p class="dropdown-item text-muted">Recordings will appear here</p>
<% end %>
</div>
</div>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="embed-responsive embed-responsive-16by9">
<%= render partial: 'broadcasts/video', locals: { broadcast: @broadcast } %>
<% if @broadcast.streamer_recording? && @broadcast.active? %>
<%= javascript_tag nonce: true do %>
new Clappr.Player({
parentId: '#broadcast_video',
source: "<%= @broadcast.stream_playback_url %>",
width: '100%',
height: '100%',
mute: true,
autoPlay: true,
hlsMinimumDvrSize: 1
});
<% end %> <% end %>
<% end %> <% end %>
</div> </div>
</div> </div>
<% if @broadcast.director_mode_video_embed.present? %>
<% if params[:director_mode] %>
<div class="custom-control custom-switch ml-auto">
<input type="checkbox" name="director_mode" value="true" class="custom-control-input" id="director_mode_switch" checked="checked" />
<label class="custom-control-label text-white override-custom-control-label" for="director_mode_switch">Director Mode</label>
</div>
<%= link_to "Disable Director Mode", url_for(params.permit!.except(:director_mode)), class: "d-none", id: "director_mode_link" %>
<% else %>
<div class="custom-control custom-switch ml-auto">
<input type="checkbox" name="director_mode" value="true" class="custom-control-input" id="director_mode_switch" />
<label class="custom-control-label text-white override-custom-control-label" for="director_mode_switch">Director Mode</label>
</div>
<%= link_to "Enable Director Mode", url_for(params.permit!.merge(director_mode: true)), class: "d-none", id: "director_mode_link" %>
<% end %>
<% end %>
</div>
<div class="embed-responsive embed-responsive-16by9" id="video_content">
<%= render partial: 'broadcasts/video', locals: { broadcast: @broadcast } %>
<% if @broadcast.streamer_recording? && @broadcast.active? %>
<%= javascript_tag nonce: true do %>
new Clappr.Player({
parentId: '#broadcast_video',
source: "<%= @broadcast.full_live_stream_playback_url %>",
width: '100%',
height: '100%',
mute: true,
autoPlay: true,
hlsMinimumDvrSize: 1
});
<% end %>
<% end %>
</div> </div>
</div> </div>
<div class="col-lg-4 col-md-12 mb-3"> <div class="col-lg-4 col-md-12 bg-white p-3 min-vh-100 overflow-auto">
<div class="card shadow-sm mb-3"> <% unless controller.class.module_parent.to_s == "Public" %>
<div class="card-header"> <% if @multi_view_broadcasts.present? %>
<ul class="nav nav-tabs card-header-tabs"> <% tokens = @multi_view_broadcasts.map(&:token) %>
<li class="nav-item"> <div class="btn-group">
<%= link_to "Home", "#home", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %> <button type="button" class="btn btn-primary" id="broadcast_share_url" data-behavior="clipboard" href="<%= broadcast_url(@broadcast.token, multi_view_tokens: tokens) %>">Share URL</button>
</li> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<li class="nav-item"> <span class="sr-only">Toggle Dropdown</span>
<%= link_to "Previous Sessions", "#recordings", class: class_string("nav-link", "active" => params[:active_tab] == "recordings"), data: { toggle: "tab" } %> </button>
</li> <div class="dropdown-menu">
</ul> <%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %>
</div>
<div class="card-body p-3">
<div class="tab-content">
<div class="<%= class_string("tab-pane fade show", "active" => !params[:active_tab].present?) %>" id="home">
<div id="broadcast_updates">
<%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: @broadcast } %>
</div>
<% unless controller.class.module_parent.to_s == "Public" %>
<hr>
<div class="form-group">
<label for="broadcast_share_url">To share the stream, copy the URL below. Anyone with the link can view the stream.</label>
<div class="input-group">
<% if @multi_view_broadcasts.present? %>
<% tokens = @multi_view_broadcasts.map(&:token) %>
<input type="text" class="form-control" value="<%= broadcast_url(@broadcast.token, multi_view_tokens: tokens) %>" readonly>
<div class="input-group-append">
<button type="button" id="broadcast_share_url" class="btn btn-success" data-behavior="clipboard" href="<%= broadcast_url(@broadcast.token, multi_view_tokens: tokens) %>">
<i class="fa fa-clipboard"></i>
Copy URL
</button>
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "btn btn-danger" %>
</div>
<% else %>
<input type="text" class="form-control" value="<%= broadcast_url(@broadcast.token) %>" readonly>
<div class="input-group-append">
<button type="button" id="broadcast_share_url" class="btn btn-success" data-behavior="clipboard" href="<%= broadcast_url(@broadcast.token) %>">
<i class="fa fa-clipboard"></i>
Copy URL
</button>
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "btn btn-danger" %>
</div>
<% end %>
</div>
</div>
<hr>
<% end %>
<p class="card-text">If you want to join the ZOOM meeting dedicated to this broadcast, follow the link below.</p>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary btn-block', target: '_blank' %>
</div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings">
<div id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
</div>
</div> </div>
</div> </div>
<% else %>
<div class="btn-group">
<button type="button" class="btn btn-primary" id="broadcast_share_url" data-behavior="clipboard" href="<%= broadcast_url(@broadcast.token) %>">Share URL</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu">
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %>
</div>
</div>
<% end %>
<% end %>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary', target: '_blank' %>
<hr/>
<ul class="nav nav-tabs override-nav-tabs mb-3">
<li class="nav-item">
<%= link_to "Takes", "#recordings", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
</li>
<li class="nav-item">
<%= link_to "Files", "#files", class: class_string("nav-link", "active" => params[:active_tab] == "files"), data: { toggle: "tab" } %>
</li>
</ul>
<div class="tab-content">
<div class="<%= class_string("tab-pane fade show", "active" => !params[:active_tab].present?) %>" id="recordings">
<div id="live_take">
<%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %>
</div>
<div id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
</div>
</div> </div>
</div> <div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == "files") %>" id="files">
<% if @multi_view_broadcasts.present? %>
<!-- files section --> <ul class="nav nav-tabs">
<div id="files" class="card shadow-sm mb-3">
<div class="card-header">
<h2 class="h5">Files</h2>
<% if @multi_view_broadcasts %>
<ul class="nav nav-tabs card-header-tabs">
<% @multi_view_broadcasts.each_with_index do |mvb, index| %> <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<li class="nav-item"> <li class="nav-item">
<%= link_to mvb.name, "#files_broadcast_#{mvb.token}", class: class_string("nav-link", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))), data: { toggle: "tab" } %> <%= link_to mvb.name, "#files_broadcast_#{mvb.token}", class: class_string("nav-link", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))), data: { toggle: "tab" } %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<% end %> <div class="tab-content pt-4">
</div>
<div class="card-body p-3">
<div class="tab-content">
<% if @multi_view_broadcasts.present? %>
<% @multi_view_broadcasts.each_with_index do |mvb, index| %> <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>"> <div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %> <%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %>
</div> </div>
<% end %> <% end %>
<% else %> </div>
<div class="tab-pane fade show active" id="files_broadcast_<%= @broadcast.id %>"> <% else %>
<%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %> <%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
</div> <% end %>
<% end %>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@
<%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %> <%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row"> <div class="form-row">
<%= form.text_field :name, wrapper_class: "col-sm-6" %> <%= form.text_field :name, wrapper_class: "col-sm-6" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(acquired_media appearance talent material misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical misc), "#amendment_clause": %w(location) } }, class: "form-control custom-select" %> <%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(acquired_media appearance talent material misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media misc), "#custom_fields": %w(medical misc appearance), "#amendment_clause": %w(appearance location), "#exhibit_fields": %w(appearance) } }, class: "form-control custom-select" %>
</div> </div>
<div class="form-row mb-3"> <div class="form-row mb-3">
<%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %> <%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %>
@@ -34,6 +34,25 @@
<%= form.rich_text_area :amendment_clause %> <%= form.rich_text_area :amendment_clause %>
<% end %> <% end %>
</div> </div>
<div id="exhibit_fields">
<%= form.form_group do %>
<%= form.rich_text_area :exhibit_a_legal_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.text_area :exhibit_a_question_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.rich_text_area :exhibit_b_legal_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
<%= form.form_group do %>
<%= form.text_area :exhibit_b_question_text %>
<small class="form-text text-muted mb-4"><%= t(".exhibits.help.option_field")%></small>
<% end %>
</div>
<div id="signature_legal_text"> <div id="signature_legal_text">
<%= form.form_group do %> <%= form.form_group do %>
<%= form.rich_text_area :signature_legal_text %> <%= form.rich_text_area :signature_legal_text %>

View File

@@ -0,0 +1,8 @@
<p class="heading"><strong><u><%= t ".heading.#{releasable.model_name.param_key}" %></u></strong></p>
<h4>Legal</h4>
<p><%= releasable.contract_template.exhibit_a_legal_text %></p>
<% if releasable.contract_template.exhibit_a_question_text.present? %>
<h4>Question</h4>
<p><strong><%= releasable.contract_template.exhibit_a_question_text %></strong></p>
<p><%= releasable.exhibit_a_answer %></p>
<% end %>

View File

@@ -0,0 +1,8 @@
<p class="heading"><strong><u><%= t ".heading.#{releasable.model_name.param_key}" %></u></strong></p>
<h4>Legal</h4>
<p><%= releasable.contract_template.exhibit_b_legal_text %></p>
<% if releasable.contract_template.exhibit_b_question_text.present? %>
<h4>Question</h4>
<p><strong><%= releasable.contract_template.exhibit_b_question_text %></strong></p>
<p><%= releasable.exhibit_b_answer %></p>
<% end %>

View File

@@ -8,38 +8,37 @@
Description: <%= release.description %> Description: <%= release.description %>
</p> </p>
<% end %> <% end %>
<% photos = release.image_files %>
<% photos = release.file_infos.photo %>
<% unless photos.empty? %> <% unless photos.empty? %>
<h3>Photos</h3> <h3>Photos</h3>
<ul> <ul>
<% photos.each do |file_info| %> <% photos.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
<% videos = release.file_infos.video %> <% videos = release.video_files %>
<% unless videos.empty? %> <% unless videos.empty? %>
<h3>Videos</h3> <h3>Videos</h3>
<ul> <ul>
<% videos.each do |file_info| %> <% videos.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>
<% other = release.file_infos.other %> <% other = release.other_files %>
<% unless other.empty? %> <% unless other.empty? %>
<h3>Other files</h3> <h3>Other files</h3>
<ul> <ul>
<% other.each do |file_info| %> <% other.each do |blob| %>
<li> <li>
<%= file_info.filename %> <%= blob.filename %>
</li> </li>
<% end %> <% end %>
</ul> </ul>

View File

@@ -11,3 +11,9 @@
<%= description_list_pair t('.description_labels.issued_by'), releasable.approved_by_user_name %> <%= description_list_pair t('.description_labels.issued_by'), releasable.approved_by_user_name %>
<%= description_list_pair t('.description_labels.date_issued'), releasable.approved_at %> <%= description_list_pair t('.description_labels.date_issued'), releasable.approved_at %>
</dl> </dl>
<% if preview %>
<%= image_tag dummy_signature %>
<% elsif releasable.approved_by_user_signature.attached? %>
<%= image_tag releasable.approved_by_user_signature.variant(auto_orient: true, resize: "200x200") %>
<% end %>

View File

@@ -6,3 +6,5 @@
<p><%= releasable.public_send("question_#{n}_answer") %></p> <p><%= releasable.public_send("question_#{n}_answer") %></p>
<% end %> <% end %>
<% end %> <% end %>
<%= contract_template.questionnaire_legal_text %>

View File

@@ -16,7 +16,7 @@
<%= contract_template.guardian_clause %> <%= contract_template.guardian_clause %>
<% end %> <% end %>
<% if releasable.model_name.in? %w(MedicalRelease MiscRelease) %> <% if releasable.respond_to?(:question_1_answer) %>
<div class="page"> <div class="page">
<%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %> <%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>
</div> </div>
@@ -30,15 +30,29 @@
<div class="page"> <div class="page">
<%= render "contracts/amendment_page", releasable: releasable, preview: preview %> <%= render "contracts/amendment_page", releasable: releasable, preview: preview %>
</div> </div>
<%end %> <% end %>
<% if releasable.respond_to?(:approved?) && releasable.approved? %> <% if releasable.respond_to?(:exhibit_a_answer) %>
<% if contract_template.has_exhibit_a? %>
<div class="page">
<%= render "contracts/exhibit_a_page", releasable: releasable, preview: preview %>
</div>
<% end %>
<% if contract_template.has_exhibit_b? %>
<div class="page">
<%= render "contracts/exhibit_b_page", releasable: releasable, preview: preview %>
</div>
<% end %>
<% end %>
<% if releasable.try(:approved?) %>
<div class="page"> <div class="page">
<%= render "contracts/for_office_use_only", releasable: releasable, preview: preview %> <%= render "contracts/for_office_use_only", releasable: releasable, preview: preview %>
</div> </div>
<% end %> <% end %>
<% if releasable.class == AcquiredMediaRelease %> <% if releasable.respond_to?(:image_files) %>
<div class="page"> <div class="page">
<%= render "contracts/files", release: releasable, preview: preview %> <%= render "contracts/files", release: releasable, preview: preview %>
</div> </div>

View File

@@ -1,7 +1,7 @@
<div class="card shadow-sm"> <div class="card shadow-sm">
<%= card_header text: t(".heading"), subtext: @releasable.name, close_action_path: [@project, @releasable.model_name.plural] %> <%= card_header text: t(".heading"), subtext: @releasable.name, close_action_path: [@project, @releasable.model_name.plural] %>
<div class="card-body"> <div class="card-body">
<% if @releasable.file_infos.any? %> <% if @releasable.files.any? %>
<div class="alert alert-info text-center text-md-left"> <div class="alert alert-info text-center text-md-left">
<%= fa_icon "info-circle" %> <%= fa_icon "info-circle" %>
<strong>To Add Photos & Videos to the release: Drag & Drop Files or Click or Tap here to browse media.</strong> <strong>To Add Photos & Videos to the release: Drag & Drop Files or Click or Tap here to browse media.</strong>
@@ -11,8 +11,8 @@
<%= fa_icon "warning" %> <%= fa_icon "warning" %>
<strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong> <strong>For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.</strong>
</div> </div>
<%= bootstrap_form_with model: @releasable, url: [@releasable, :file_infos] do |form| %> <%= bootstrap_form_with model: @releasable, url: [@releasable, :files] do |form| %>
<%= render "shared/file_infos_dropzone", form: form, releasable: @releasable %> <%= render "shared/releasable_files_dropzone", form: form, releasable: @releasable %>
<div class="row align-items-center text-center mt-4"> <div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [@project, @releasable.model_name.plural], class: "col-3 text-reset" %> <%= link_to t("shared.cancel"), [@project, @releasable.model_name.plural], class: "col-3 text-reset" %>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<%= I18n.locale %>"> <html lang="<%= I18n.locale %>">
<head> <head>
<title>BiGMedia.ai App</title> <title>ME Suite</title>
<%= csrf_meta_tags %> <%= csrf_meta_tags %>
<%= csp_meta_tag %> <%= csp_meta_tag %>

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="<%= I18n.locale %>"> <html lang="<%= I18n.locale %>">
<head> <head>
<title>BiGMedia.ai App</title> <title>ME Suite</title>
<%= csrf_meta_tags %> <%= csrf_meta_tags %>
<%= csp_meta_tag %> <%= csp_meta_tag %>

View File

@@ -16,10 +16,10 @@
<% end %> <% end %>
</td> </td>
<td> <td>
<%= location_release.name %> <%= contact_info(name: location_release.name, address: location_release.address) %>
</td> </td>
<td> <td>
<%= contact_info address: location_release.address %> <%= contact_info_for(location_release.contact_person) %>
</td> </td>
<td> <td>
<%= notes_preview location_release.notes.order_by_recent %> <%= notes_preview location_release.notes.order_by_recent %>

View File

@@ -28,8 +28,8 @@
<th data-behavior="all-selectable"><%= check_box_tag "location_release_ids[]", false, false %></th> <th data-behavior="all-selectable"><%= check_box_tag "location_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></th> <th><%= t '.table_headers.approved'%></th>
<th></th> <th></th>
<th><%= t(".table_headers.name") %></th> <th><%= t(".table_headers.location_info") %></th>
<th><%= t(".table_headers.address") %> <th><%= t(".table_headers.owner_info") %>
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th> <th><%= t(".table_headers.signed_at") %></th>

Some files were not shown because too many files have changed in this diff Show More