Compare commits

...

11 Commits

Author SHA1 Message Date
Bilal
09f4e4d454 show both, files and file infos in acq.media API response 2020-09-01 22:05:51 +03:00
Bilal
9a1f49f0dc show files attachments instead of file infos in API for acq.media release 2020-09-01 22:05:51 +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
Senad Uka
9cbd8d31a8 Upstream sync 2020-07-29 05:15:02 +00:00
Senad Uka
9c3fac4ab9 Upstream sync 2020-07-27 10:17:56 +00:00
229 changed files with 5174 additions and 1896 deletions

View File

@@ -7,8 +7,6 @@ AWS_SECRET_ACCESS_KEY=
AWS_REGION=
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
REDIS_URL=
@@ -18,7 +16,7 @@ ZOOM_API_KEY=
ZOOM_API_SECRET=
ZOOM_PRO_USERS_LIMIT= # defaults to 3
ZOOM_USER_TYPE= # 'pro' / 'basic'
ZOOM_ENABLE_RECORDINGS=0 # 0 / 1
ZOOM_ENABLE_RECORDINGS= # true / false (default: false)
# Token for webhooks authorization
ZOOM_VERIFICATION_TOKEN=
@@ -27,3 +25,10 @@ MUX_TOKEN_ID=
MUX_TOKEN_SECRET=
MUX_BROADCAST_SERVER_URL=rtmp://global-live.mux.com:5222/app
MUX_TEST_MODE_DISABLED=
# Required for creating user through API
CUSTOM_API_TOKEN=
# Required for simulcasting to Millicast for director mode
MILLICAST_API_SECRET=
MILLICAST_ACCOUNT_ID=

View File

@@ -21,10 +21,13 @@ $(document).on "turbolinks:load", ->
refreshBroadcastVideo: (data) ->
$("#broadcast_updates").html data.status_content
stream_selected = $("#broadcast_video").attr('video-type') == 'stream';
stream_selected = $("#broadcast_video").data('videoType') == 'stream';
if data.streamer_status == 'recording' && data.status == 'active' && stream_selected
$("#broadcast_video").html data.video_content
$("#live_take").html data.live_take_content
new (Clappr.Player)(
<%= "baseUrl: 'http://cdn.clappr.io/latest'," if Rails.env.test? %>
parentId: '#broadcast_video'
source: data.full_live_stream_playback_url
width: '100%',
@@ -34,6 +37,7 @@ $(document).on "turbolinks:load", ->
hlsMinimumDvrSize: 1)
if data.streamer_status == "idle" && data.status == "idle"
$("#broadcast_video").html data.video_content
$("#live_take").html data.live_take_content
showBroadcastRecordings: (data) ->
$(".flash-message").html data.flash_content

View File

@@ -0,0 +1,9 @@
$(document).on("turbolinks:load", function() {
$("#upload_directory_files").on('click', function(e){
const newFilesCount = $('input[name = "directory[files][]"][type = "hidden"]').length;
if (newFilesCount === 0){
e.preventDefault();
}
});
});

View File

@@ -3,7 +3,7 @@ $(document).on("click", "[data-behavior=play_recording]", function() {
return false;
}
$("#broadcast_video").attr('video-type', 'recording');
$("#broadcast_video").data('videoType', 'recording');
var playback_url = $(this).attr("data-playback-url")
$("#broadcast_video").empty();
@@ -25,4 +25,4 @@ $(document).on("click", "[data-behavior=play_recording]", function() {
$(this).prepend('<i class="fa fa-check">&nbsp;</i>');
});
$(document).on("click", "[data-behavior=play_stream]", function() { $("#broadcast_video").attr('video-type', 'stream'); });
$(document).on("click", "[data-behavior=play_stream]", function() { $("#broadcast_video").data('videoType', 'stream'); });

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);
}
// Black background
.bg-black {
background-color: $black;
}
// White background
.bg-white {
background-color: $white;
}
// Custom width
.w-65 {
width: 65% !important;
@@ -422,8 +432,32 @@ a[data-behavior=seekable-timecode] {
max-height: 30rem;
}
// Max-width 75%
.max-w-75 {
max-width: 75%;
}
// Fix height and width
.fix-h-and-w {
width: 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)
status_content = ApplicationController.render partial: "broadcasts/broadcast_status", 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, {
event: :broadcast_stream_update,
@@ -18,6 +19,7 @@ class BroadcastsChannel < ApplicationCable::Channel
playback_url: broadcast.stream_playback_url,
full_live_stream_playback_url: broadcast.full_live_stream_playback_url,
video_content: video_content,
live_take_content: live_take,
status_content: status_content,
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)
if @acquired_media_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@acquired_media_release)
redirect_to [@project, :acquired_media_releases], notice: t(".notice")
else
@@ -56,35 +55,71 @@ class AcquiredMediaReleasesController < ApplicationController
end
end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_company
person_email
person_title
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def acquired_media_release_params
params.require(:acquired_media_release).permit(
:name,
:territory,
:term,
:person_first_name,
:person_last_name,
:person_phone,
:person_email,
:person_company,
:person_title,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
:contract,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
categories: [],
file_infos_attributes: [
:filename,
:content_type,
:byte_size
]
)
params.require(:acquired_media_release).permit(person_params,
guardian_params,
second_guardian_params,
:minor,
:name,
:territory,
:term,
:contract,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
categories: [],
files: []
)
end
def build_acquired_media_release(attrs = {})
@@ -100,8 +135,4 @@ class AcquiredMediaReleasesController < ApplicationController
results
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

View File

@@ -20,6 +20,7 @@ class Admin::AccountsController < Admin::ApplicationController
def show
@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
def edit
@@ -70,4 +71,8 @@ class Admin::AccountsController < Admin::ApplicationController
@account.videos
end
end
def account_broadcasts
@account.broadcasts
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
handle_attachments(release, release_create_params[:photos])
release.save!(context: :native)
log_create_analytics
after_create(release)
handle_response(release, :created)
end
@@ -46,13 +45,14 @@ class Api::ReleasesController < Api::ApiController
if model_name == "acquired_media_release"
mapping = {
"#{model_name.camelize}": SerializableAcquiredMediaRelease,
FileInfo: SerializableFileInfo
FileInfo: SerializableFileInfo,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment,
}
render jsonapi: release,
status: status,
class: mapping,
include: [:file_infos]
include: [:files, :file_infos]
else
mapping = {
"#{model_name.camelize}": show_serializable,
@@ -181,8 +181,4 @@ class Api::ReleasesController < Api::ApiController
parameters = parameters.slice(*keys).except(:created_at, :updated_at, :id, :user_id, :signature)
parameters
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

View File

@@ -1,5 +1,13 @@
# frozen_string_literal: true
require './lib/knock_monkeypatch'
class Api::UserTokenController < Knock::AuthTokenController
include Oath::ControllerHelpers
include RememberMe::Controller
skip_before_action :verify_authenticity_token
before_action :sign_in_user
rescue_from Exception, :with => :return_error
@@ -10,7 +18,7 @@ class Api::UserTokenController < Knock::AuthTokenController
logger.error "==Handled======="
logger.error exception.message
logger.error exception.backtrace.join("\n")
logger.error "==Handled======="
logger.error "==Handled======="
case exception
when ActiveRecord::RecordNotFound
@status = 404
@@ -27,12 +35,18 @@ class Api::UserTokenController < Knock::AuthTokenController
end
# for some reason render json_errors is not working
# simulating JSON API support
render json: {
# simulating JSON API support
render json: {
errors: [{
status: @status.to_s,
title: @message
}]
}
end
private
def sign_in_user
sign_in(entity)
end
end

View File

@@ -0,0 +1,33 @@
# frozen_string_literal: true
class Api::UsersController < Api::ApiController
skip_before_action :authenticate_user
before_action :verify_custom_token, only: :create
def create
if user_params[:email].nil? || user_params[:password].nil?
raise ActionController::ParameterMissing.new 'Missing email or password'
end
user = Oath::Services::SignUp.new(user_params).perform
render json: user.slice(:email, :created_at, :first_name, :last_name)
end
private
def user_params
params.require(:user).permit(%i[
email
password
first_name
last_name
])
end
def verify_custom_token
if token.blank? || token != ENV['CUSTOM_API_TOKEN']
unauthorized_entity(:user)
end
end
end

View File

@@ -18,7 +18,6 @@ class AppearanceReleasesController < ApplicationController
@appearance_release = build_appearance_release(appearance_release_params)
if @appearance_release.save(context: :non_native)
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@appearance_release)
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
view_context.link_to "Import Another", [:new, @project, :appearance_release]
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

View File

@@ -6,9 +6,12 @@ class ApprovalsController < ApplicationController
def create
@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)
else
render :new
end
end
@@ -25,4 +28,21 @@ class ApprovalsController < ApplicationController
def set_project
@project = @releasable.project
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

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

@@ -3,7 +3,7 @@ class BroadcastsController < ApplicationController
before_action :set_project
before_action :build_broadcast, only: [:new, :create]
before_action :set_broadcast, only: [:show, :destroy, :update]
before_action :set_broadcast, only: [:show, :destroy, :update, :destroy_file]
before_action :set_multi_view_broadcasts, only: [:show]
before_action :show_splash_screen, only: :index
@@ -23,12 +23,16 @@ class BroadcastsController < ApplicationController
else
render :new
end
rescue MuxRuby::ApiError, ActiveResource::ConnectionError => e
Raven.capture_exception(e)
redirect_to [@project, :broadcasts], alert: t(".alert")
end
def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@conference_url = conference_url_for(@broadcast)
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application'
end
@@ -39,10 +43,7 @@ class BroadcastsController < ApplicationController
end
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab], page: params[:page], active_files_tab: params[:active_files_tab] })
BroadcastsChannel.broadcast_file_upload_updates(@broadcast, @files, pagination_content)
update_files_section
end
def destroy
@@ -53,8 +54,23 @@ class BroadcastsController < ApplicationController
end
end
def destroy_file
authorize Broadcast
file = ActiveStorage::Attachment.find(params[:file_id])
file.destroy
update_files_section
end
private
def update_files_section
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab], page: params[:page], active_files_tab: params[:active_files_tab] })
BroadcastsChannel.broadcast_file_upload_updates(@broadcast, @files, pagination_content)
end
def show_splash_screen
render :splash if broadcasts.count.zero?
end
@@ -97,6 +113,10 @@ class BroadcastsController < ApplicationController
results
end
def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || url_for([broadcast.project, broadcast, :zoom_meeting])
end
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)
end

View File

@@ -26,6 +26,7 @@ class ContractTemplatesController < ApplicationController
contract = Contract.new releasable_instance, true
send_file contract.to_pdf, download_attributes
elsif @contract_template.save
log_create_analytics
redirect_to [@project, :contract_templates], notice: t('.notice')
else
@release_type = contract_template_params[:release_type]
@@ -82,7 +83,7 @@ class ContractTemplatesController < ApplicationController
params
.require(:contract_template)
.permit(:name, :release_type, :body, :guardian_clause,
:signature_legal_text, :fee,
:signature_legal_text, :fee, :amendment_clause,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text, :accessibility,
@@ -94,7 +95,9 @@ class ContractTemplatesController < ApplicationController
:question_9_text, :question_10_text,
:question_11_text, :question_12_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
def download_attributes
@@ -104,4 +107,8 @@ class ContractTemplatesController < ApplicationController
type: 'application/pdf'
}
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

View File

@@ -1,4 +1,4 @@
class FileInfosController < ApplicationController
class FilesController < ApplicationController
before_action :set_releasable
layout "project"
@@ -16,7 +16,7 @@ class FileInfosController < ApplicationController
if @releasable.update(releasable_params)
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
render :edit
end
@@ -29,16 +29,10 @@ class FileInfosController < ApplicationController
end
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
def releasable_params
params.fetch(releasable_param.name, {}).permit(
file_infos_attributes: [
:filename,
:content_type,
:byte_size
],
)
params.fetch(releasable_param.name, {}).permit(files: [])
end
end

View File

@@ -18,7 +18,6 @@ class LocationReleasesController < ApplicationController
@location_release = build_location_release(location_release_params)
if @location_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@location_release)
redirect_to [@project, :location_releases], notice: t(".notice")
else
@@ -90,8 +89,4 @@ class LocationReleasesController < ApplicationController
results
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

View File

@@ -18,7 +18,6 @@ class MaterialReleasesController < ApplicationController
@material_release = build_material_release(material_release_params)
if @material_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@material_release)
redirect_to [@project, :material_releases], notice: t(".notice")
else
@@ -50,17 +49,64 @@ class MaterialReleasesController < ApplicationController
private
def person_params
%i[
person_first_name
person_last_name
person_phone
person_company
person_email
person_title
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def material_release_params
params.require(:material_release).permit(
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,
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
:description,
:contract, { photos: [] }
:contract, files: []
)
end
@@ -89,8 +135,4 @@ class MaterialReleasesController < ApplicationController
results
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

View File

@@ -22,7 +22,6 @@ class MusicReleasesController < ApplicationController
@music_release = build_music_release(music_release_params)
if @music_release.save
log_create_analytics
SetTagsForReleasableJob.perform_later(@music_release)
redirect_to [@project, :music_releases], notice: t(".notice")
else
@@ -111,8 +110,4 @@ class MusicReleasesController < ApplicationController
results
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

View File

@@ -6,7 +6,7 @@ class ProjectsController < ApplicationController
before_action :set_project, only: [:show, :edit, :update, :destroy]
def index
@projects = policy_scope(Current.account.projects).order_by_name
@projects = filtered_projects.order_by_name
end
def new
@@ -46,6 +46,20 @@ class ProjectsController < ApplicationController
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
@project = authorize projects.find(params[:id])
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)
if @acquired_media_release.save(context: :native)
log_create_analytics
after_create(@acquired_media_release)
else
render :new
@@ -41,31 +40,67 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
end
end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_fax
person_email
person_title
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def acquired_media_release_params
params.require(:acquired_media_release).permit(
:name,
:description,
:person_first_name,
:person_last_name,
:person_email,
:person_title,
:person_phone,
:person_fax,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
:signature_base64,
:locale, :contract_template,
categories: [],
file_infos_attributes: [
:filename,
:content_type,
:byte_size
]
)
params.require(:acquired_media_release).permit(person_params,
guardian_params,
second_guardian_params,
:minor,
:name,
:description,
:signature_base64,
:locale, :contract_template,
categories: [],
files: []
)
end
def acquired_media_release_params_with_locale
@@ -75,8 +110,4 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
def acquired_media_release_params_with_locale_and_contract_template
acquired_media_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -0,0 +1,47 @@
class Public::AmendmentsController < Public::BaseController
skip_after_action :verify_authorized, :verify_policy_scoped
before_action :set_account, :set_project, :set_contract_template, :set_release
def new
if @release.amendment_signed?
render :create, locals: { already_signed: true }
end
end
def create
if @release.amendment_signed?
render :create, locals: { already_signed: true }
return
end
@release.attributes = amendment_params
render :new unless @release.save(context: :amendment)
end
private
def amendment_params
params.require(releasable_param.name).permit(:amendment_signer_name, :amendment_signature_base64)
end
def releasable_param
@releasable_param ||= ReleasableParam.new(params.to_unsafe_h)
end
def set_release
@release = @contract_template.releases.find(releasable_param.id)
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
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)
if @appearance_release.save(context: :native)
log_create_analytics
after_create(@appearance_release)
else
render :new
@@ -87,12 +86,35 @@ class Public::AppearanceReleasesController < Public::BaseController
]
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
params.require(:appearance_release).permit(person_params, guardian_params,
second_guardian_params,
questionnaire_params,
:minor, :signature_base64,
:person_date_of_birth,
:locale, :contract_template)
:locale, :contract_template,
:exhibit_a_answer, :exhibit_b_answer
)
end
def appearance_release_params_with_locale
@@ -102,8 +124,4 @@ class Public::AppearanceReleasesController < Public::BaseController
def appearance_release_params_with_locale_and_contract_template
appearance_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -3,9 +3,9 @@ class Public::BroadcastsController < Public::BaseController
before_action :set_broadcast, only: [:show, :update]
def show
@conference_url = broadcast_zoom_meeting_url(@broadcast.token)
@conference_url = conference_url_for(@broadcast)
@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])
render 'broadcasts/show'
@@ -43,6 +43,10 @@ class Public::BroadcastsController < Public::BaseController
end
end
def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || broadcast_zoom_meeting_url(broadcast.token)
end
class MultiViewBroadcast
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)
if @location_release.save(context: :native)
log_create_analytics
after_create(@location_release)
else
render :new
@@ -76,8 +75,4 @@ class Public::LocationReleasesController < Public::BaseController
def location_release_params_with_locale_and_contract_template
location_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -10,7 +10,6 @@ class Public::MaterialReleasesController < Public::BaseController
@material_release = build_material_release(material_release_params_with_locale_and_contract_template)
if @material_release.save(context: :native)
log_create_analytics
after_create(@material_release)
else
render :new
@@ -39,13 +38,61 @@ class Public::MaterialReleasesController < Public::BaseController
authorize material_releases.build(params)
end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_email
person_title
person_company
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def second_guardian_params
%i[
guardian_2_first_name
guardian_2_last_name
guardian_2_phone
guardian_2_email
guardian_2_photo
guardian_2_address_street1
guardian_2_address_street2
guardian_2_address_city
guardian_2_address_state
guardian_2_address_zip
guardian_2_address_country
]
end
def material_release_params
params.require(:material_release).permit(
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,
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:signature_base64,
:locale, :contract_template, :description, photos: []
:locale, :contract_template, :description, files: []
)
end
@@ -56,8 +103,4 @@ class Public::MaterialReleasesController < Public::BaseController
def material_release_params_with_locale_and_contract_template
material_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -12,7 +12,6 @@ class Public::MedicalReleasesController < Public::BaseController
if @medical_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@medical_release)
end
log_create_analytics
else
render :new
end
@@ -116,8 +115,4 @@ class Public::MedicalReleasesController < Public::BaseController
def medical_release_params_with_locale_and_contract_template
medical_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -12,7 +12,6 @@ class Public::MiscReleasesController < Public::BaseController
if @misc_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@misc_release)
end
log_create_analytics
else
render :new
end
@@ -50,6 +49,14 @@ class Public::MiscReleasesController < Public::BaseController
:signature_base64,
:locale,
:contract_template,
:applicable_medium_id,
:applicable_medium_text,
:territory_id,
:territory_text,
:term_id,
:term_text,
:restriction_id,
:restriction_text,
photos: [],
)
end
@@ -113,8 +120,4 @@ class Public::MiscReleasesController < Public::BaseController
def misc_release_params_with_locale_and_contract_template
misc_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -10,7 +10,6 @@ class Public::TalentReleasesController < Public::BaseController
@talent_release = build_talent_release(talent_release_params_with_locale_and_contract_template)
if @talent_release.save(context: :native)
log_create_analytics
after_create(@talent_release)
else
render :new
@@ -108,8 +107,4 @@ class Public::TalentReleasesController < Public::BaseController
def talent_release_params_with_locale_and_contract_template
talent_release_params_with_locale.merge(contract_template: @contract_template)
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

View File

@@ -35,7 +35,7 @@ class StreamNotificationsController < ApplicationController
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)
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")
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)
if @talent_release.save
log_create_analytics
AddHeadshotCollectionUidToProjectJob.perform_later(@project)
SetTagsForReleasableJob.perform_later(@talent_release)
redirect_to [@project, :talent_releases], notice: t(".notice")
@@ -137,8 +136,4 @@ class TalentReleasesController < ApplicationController
results
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

View File

@@ -6,6 +6,6 @@ module MailHelper
"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."
mail_to "info@bigmedia.ai", content, subject: subject, body: body
mail_to "info@mesuite.ai", content, subject: subject, body: body
end
end

View File

@@ -67,6 +67,23 @@ class ActiveStorageDropzone {
var upload = new that.UploaderClass(file, url, delegate);
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

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

View File

@@ -1,4 +1,4 @@
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"
end

View File

@@ -5,6 +5,7 @@ class Account < ApplicationRecord
has_many :users, through: :account_auths
has_many :projects, dependent: :destroy
has_many :videos, through: :projects
has_many :broadcasts, through: :projects
has_many :contract_templates, through: :projects
validates :name, presence: true
@@ -63,6 +64,19 @@ class Account < ApplicationRecord
])).sum(:byte_size).to_f
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
slug
end
@@ -84,7 +98,7 @@ class Account < ApplicationRecord
end
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
def plan_name

View File

@@ -11,16 +11,22 @@ class AcquiredMediaRelease < ApplicationRecord
include PersonName
include CsvExportable
include Approvable
include GuardianPhotoable
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
include FilesFilterable
class << self
def custom_csv_exportable_headers
%i[name file_infos_count]
%i[name files_count owner_info]
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
accepts_nested_attributes_for :file_infos
has_many_attached :files
composed_of :person_address,
class_name: "Address",
@@ -33,6 +39,38 @@ class AcquiredMediaRelease < ApplicationRecord
%w(person_address_country country)
]
composed_of :guardian_address,
class_name: 'Address',
mapping: [
%w[guardian_address_street1 street1],
%w[guardian_address_street2 street2],
%w[guardian_address_city city],
%w[guardian_address_state state],
%w[guardian_address_zip zip],
%w[guardian_address_country country]
]
composed_of :guardian_2_address,
class_name: 'Address',
mapping: [
%w[guardian_2_address_street1 street1],
%w[guardian_2_address_street2 street2],
%w[guardian_2_address_city city],
%w[guardian_2_address_state state],
%w[guardian_2_address_zip zip],
%w[guardian_2_address_country country]
]
# We don't care for the argument but method WILL receive option name
# when called from inside with_option block, hence * argument
def self.face_photo_acceptable_content_types(*)
['image/png', 'image/jpeg']
end
def self.acceptable_import_file_extensions
['.png', '.jpeg', '.jpg', '.pdf']
end
validates :name, presence: true
validates :person_email, email: true, allow_blank: true
@@ -54,8 +92,8 @@ class AcquiredMediaRelease < ApplicationRecord
# CATEGORIES = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze
CATEGORIES = ["Film Footage", "Video Footage", "Still Photograph"].freeze
def minor?
false
def second_guardian_present?
guardian_2_first_name.present?
end
def contact_person
@@ -66,7 +104,7 @@ class AcquiredMediaRelease < ApplicationRecord
true
end
def file_infos_count
file_infos.any? ? file_infos.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
def files_count
files.any? ? files.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
end
end

View File

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

View File

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

View File

@@ -35,7 +35,11 @@ class Broadcast < ApplicationRecord
end
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
def zoom_meeting_url
@@ -45,11 +49,13 @@ class Broadcast < ApplicationRecord
private
def create_mux_live_stream
stream = MuxLiveStream.new
stream = MuxLiveStream.create_with_simulcast
self.stream_uid = stream.id
self.stream_key = stream.key
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!
end

View File

@@ -5,8 +5,12 @@ class BroadcastRecording < ApplicationRecord
validates :asset_uid, uniqueness: true
scope :visible, -> { where(hidden: false) }
before_save :set_title_and_description
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
def playback_url
@@ -14,6 +18,21 @@ class BroadcastRecording < ApplicationRecord
end
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

View File

@@ -0,0 +1,32 @@
module Amendmenable
extend ActiveSupport::Concern
included do
include ActiveStorageSupport::SupportForBase64
has_one_base64_attached :amendment_signature
with_options on: :amendment do
validates :amendment_signer_name, presence: true
validates :amendment_signature, attached: true
end
end
def amendment_signable?
contract_template.present? && contract_template.amendment_clause.present?
end
def amendment_signed?
amendment_signature.attached?
end
def amendment_signature_base64
nil
end
def amendment_signature_base64=(data_uri)
return if data_uri.blank?
amendment_signature.attach(data: data_uri, filename: "amendment_signature.png", content_type: "image/png", identify: "false")
end
end

View File

@@ -1,15 +1,24 @@
module Approvable
extend ActiveSupport::Concern
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)
return unless approved_at.nil?
self.approved_by_user_name = user.full_name
self.approved_by_user_email = user.email
self.approved_at = Time.zone.now
self.approved_at = BigMediaTime.time_zone_now
end
def approved?
self.approved_at.present?
end

View File

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

@@ -22,6 +22,10 @@ class ContractTemplate < ApplicationRecord
has_rich_text :body
has_rich_text :guardian_clause
has_rich_text :signature_legal_text
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 :release_type, presence: true
@@ -69,6 +73,14 @@ class ContractTemplate < ApplicationRecord
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
end
def has_exhibit_a?
exhibit_a_legal_text.present?
end
def has_exhibit_b?
exhibit_b_legal_text.present?
end
def editable?
releases.size.zero?
end

View File

@@ -12,10 +12,11 @@ class LocationRelease < ApplicationRecord
include PersonName
include CsvExportable
include Approvable
include Amendmenable
class << self
def custom_csv_exportable_headers
%i[name address]
%i[location_info owner_info amendment_signed_column]
end
end
@@ -66,6 +67,18 @@ class LocationRelease < ApplicationRecord
true
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
def end_date_after_start_date

View File

@@ -3,7 +3,7 @@ class MaterialRelease < ApplicationRecord
include Contractable
include Exploitable
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 Searchable
include Signable
@@ -12,10 +12,15 @@ class MaterialRelease < ApplicationRecord
include PersonName
include CsvExportable
include Approvable
include GuardianPhotoable
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
include FilesFilterable
class << self
def custom_csv_exportable_headers
%i[name]
%i[name owner_info files_count]
end
end
@@ -30,6 +35,41 @@ class MaterialRelease < ApplicationRecord
%w(person_address_country country)
]
composed_of :guardian_address,
class_name: 'Address',
mapping: [
%w[guardian_address_street1 street1],
%w[guardian_address_street2 street2],
%w[guardian_address_city city],
%w[guardian_address_state state],
%w[guardian_address_zip zip],
%w[guardian_address_country country]
]
composed_of :guardian_2_address,
class_name: 'Address',
mapping: [
%w[guardian_2_address_street1 street1],
%w[guardian_2_address_street2 street2],
%w[guardian_2_address_city city],
%w[guardian_2_address_state state],
%w[guardian_2_address_zip zip],
%w[guardian_2_address_country country]
]
has_many_attached :files
# We don't care for the argument but method WILL receive option name
# when called from inside with_option block, hence * argument
def self.face_photo_acceptable_content_types(*)
['image/png', 'image/jpeg']
end
def self.acceptable_import_file_extensions
['.png', '.jpeg', '.jpg', '.pdf']
end
validates :name, presence: true
validates :person_email, email: true, allow_blank: true
@@ -47,11 +87,15 @@ class MaterialRelease < ApplicationRecord
@contact_person ||= Contact.new(person_name, person_address, person_email, person_phone)
end
def minor?
false
def second_guardian_present?
guardian_2_first_name.present?
end
def uses_edl?
true
end
def files_count
files.any? ? files.size : I18n.t('material_releases.material_release.no_media')
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 CsvExportable
include Approvable
include Exploitable
class << self
def custom_csv_exportable_headers

View File

@@ -1,4 +1,15 @@
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
live_stream.data.id
end
@@ -15,6 +26,15 @@ class MuxLiveStream
client.delete_live_stream(stream_uid)
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
def live_stream

View File

@@ -2,6 +2,7 @@ class Project < ApplicationRecord
include Archivable
include Filterable
include Syncable
include PgSearch
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)
@@ -42,6 +43,15 @@ class Project < ApplicationRecord
}
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 }
filterable_by :active, :inactive, :archived

View File

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

View File

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

View File

@@ -18,4 +18,12 @@ class BroadcastPolicy < ApplicationPolicy
def update?
true
end
def destroy_file?
if user.nil? || user.user.nil?
return false
end
user.manager? || user.account_manager?
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

@@ -39,6 +39,10 @@ class LocationReleasePolicy < ReleasePolicy
user.account_manager?
end
def sign_amendment?
user.manager? || user.account_manager?
end
def approve?
review?
end

View File

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

View File

@@ -7,7 +7,7 @@ class SerializableAcquiredMediaRelease < JSONAPI::Serializable::Resource
:person_title, :person_company, :created_at, :updated_at, :collection_uid, :territory_old, :term_old,
:applicable_medium_id, :applicable_medium_text, :territory_id, :territory_text, :term_id, :term_text,
:restriction_id, :restriction_text, :categories, :description, :tag_list
has_many :file_infos do
data do
@object.file_infos
@@ -16,5 +16,15 @@ class SerializableAcquiredMediaRelease < JSONAPI::Serializable::Resource
meta do
{ count: @object.file_infos.size }
end
end
end
has_many :files do
data do
@object.files
end
meta do
{ count: @object.files.size }
end
end
end

View File

@@ -169,6 +169,24 @@ class Analytics
)
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

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| %>
<%= 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") }) %>
<% end %>

View File

@@ -12,12 +12,15 @@
<%= acquired_media_release.name %>
</td>
<td>
<% if acquired_media_release.file_infos.any? %>
<%= acquired_media_release.file_infos.size %>
<% if acquired_media_release.files.any? %>
<%= acquired_media_release.files.size %>
<% else %>
<%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %>
<% end %>
</td>
<td>
<%= contact_info_for(acquired_media_release.contact_person) %>
</td>
<td>
<%= notes_preview acquired_media_release.notes.order_by_recent %>
</td>
@@ -37,8 +40,8 @@
<% 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 %>
<% end %>
<% if policy(acquired_media_release).edit_file_infos? %>
<%= link_to fa_icon("file fw", text: "Add Media"), [:edit, acquired_media_release, :file_infos], class: "dropdown-item" %>
<% if policy(acquired_media_release).edit_files? %>
<%= link_to fa_icon("file fw", text: "Media"), [:edit, acquired_media_release, :files], class: "dropdown-item" %>
<% end %>
<% 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" %>

View File

@@ -1,6 +1,10 @@
<%= errors_summary_for acquired_media_release %>
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= field_set_tag content_tag(:span, t(".acquired_media_details.heading"), class: "h6 text-muted text-uppercase") do %>
<%= form.form_group :minor do %>
<%= form.check_box :minor, label: t("helpers.label.talent_release.minor"), data: { target: "[data-ujs-target=guardian-fields]", toggle: "collapse" } %>
<% end %>
<div class="form-row">
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
</div>
@@ -9,6 +13,28 @@
<%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %>
<% end %>
<div class="<%= class_string("collapse" => !acquired_media_release.minor?) %>" data-ujs-target="guardian-fields">
<%= card_field_set_tag t(".guardian_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_first_name, required: acquired_media_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_last_name, required: acquired_media_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian" %>
<% end %>
<%= card_field_set_tag t(".guardian_2_info.heading") do %>
<div class="form-row">
<%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian_2" %>
<% end %>
</div>
<% end %>
<hr>
@@ -18,7 +44,45 @@
<%= 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>
</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">
<br>
<div class="text-left">
<p><%= t(".photos.guardian_photo.heading") %></p>
<div id="guardian-photo-preview" class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span>No photo yet</span>
</div>
</div>
<% if acquired_media_release.guardian_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("#guardian-photo-preview", "<%= url_for(acquired_media_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="d-inline-block">
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if acquired_media_release.guardian_photo.attached?%>
<%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, help: "PNG or JPG only", accept: acquired_media_release.class.face_photo_acceptable_content_types.join(",") %>
</div>
<p><%= t(".photos.guardian_2_photo.heading") %></p>
<div id="guardian-2-photo-preview" class="d-inline-block mb-2" data-behavior="guardian-photo-preview" data-file-input="[data-ujs-target=guardian-2-photo-input]">
<div class="align-items-center d-flex photo-preview img-thumbnail justify-content-center">
<span>No photo yet</span>
</div>
</div>
<% if acquired_media_release.guardian_2_photo.attached? %>
<%= javascript_tag nonce: true do %>
App.PhotoPreview.set("#guardian-2-photo-preview", "<%= url_for(acquired_media_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<div class="d-inline-block">
<%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if acquired_media_release.guardian_2_photo.attached?%>
<%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, help: "PNG or JPG only", accept: acquired_media_release.class.face_photo_acceptable_content_types.join(",") %>
</div>
</div>
<hr>
</div>
<% end %>
<hr>

View File

@@ -28,7 +28,8 @@
<th data-behavior="all-selectable"><%= check_box_tag "acquired_media_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></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.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th>

View File

@@ -8,6 +8,9 @@
<td>
<%= account.projects.size %>
</td>
<td>
<%= account.total_number_of_releases %>
</td>
<td>
<%= number_with_delimiter convert_duration(account.current_month_video_duration_total, from: :seconds, to: :minutes).round %> minutes
</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>Plan</th>
<th># Projects</th>
<th># Releases Signed</th>
<th>Monthly Video Upload Minutes</th>
<th>Total Video Upload Minutes</th>
<th>Total Storage</th>

View File

@@ -9,6 +9,8 @@
<dd class="col-sm-10"><%= @account.users.size %></dd>
<dt class="col-sm-2">Created at</dt>
<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>
<% end %>
@@ -34,5 +36,25 @@
<%= will_paginate @videos %>
</div>
<% 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>

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>
<%= appearance_release.signed_on %>
</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">
<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 } %>
@@ -44,6 +55,9 @@
<% 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 %>
<% 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?) %>
<%= link_to fa_icon("download fw", text: "Download"), [appearance_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>
<% end %>

View File

@@ -51,6 +51,7 @@
<th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th>
<th><%= t '.table_headers.amendment_signed' %></th>
<th></th>
</tr>
</thead>

View File

@@ -1,9 +1,13 @@
<div class="card shadow-sm">
<%= card_header text: t(".heading", release_type: @releasable_param.name.titleize), close_action_path: [@project, "#{@releasable_param.name.pluralize}"] %>
<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| %>
<%= 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">
<%= link_to t("shared.cancel"), [@releasable.project, "#{@releasable_param.name.pluralize}"], class: "col-3 text-reset" %>
<div class="col-9">
@@ -12,4 +16,4 @@
</div>
<% end %>
</div>
</div>
</div>

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">
<%= 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">
<%= 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("key fw", text: "Copy Stream Key"), broadcast.stream_key, 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_server_key, class: "dropdown-item", data: { behavior: "clipboard" } %>
<% if policy(broadcast).show? %>
<%= link_to fa_icon("file-video-o fw", text: "View"), [broadcast.project, broadcast], class: "dropdown-item", target: '_blank' %>
<% 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? %>
<p>Click below to download the recordings of the live stream.</p>
<ul class="mt-2">
<div class="list-group">
<% 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 %>
</ul>
</div>
<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'}) %>
</div>
<% 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 %>

View File

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

View File

@@ -1,12 +1,25 @@
<li class="my-2" id="<%= dom_id(file) %>">
<% if file.variable? %>
<%= link_to image_tag(file.variant(resize_and_pad: [300, 300, background: "#F7F8F9"]), class: "bg-light img-thumbnail img-fluid"), file, target: "_blank" %>
<% else %>
<div class="border rounded bg-light text-muted d-flex justify-content-center align-items-center fix-h-and-w">
<%= link_to file, target: "_blank" do %>
<%= fa_icon("file", style: "font-size: 2rem") %>
<div class="mt-2"><%= file.filename %></div>
<div class="row">
<% broadcast = file.record %>
<% show_delete = controller.class.module_parent.to_s == "Public" ? false : policy(broadcast).destroy_file? %>
<% file_class = show_delete ? "col-8" : "col-12" %>
<div class="<%= file_class %>">
<li class="my-2" id="<%= dom_id(file) %>">
<% if file.variable? %>
<%= link_to image_tag(file.variant(resize_and_pad: [300, 300, background: "#F7F8F9"]), class: "bg-light img-thumbnail img-fluid"), file, target: "_blank" %>
<% else %>
<div class="border rounded bg-light text-muted d-flex justify-content-center align-items-center img-fluid fix-h-and-w">
<%= link_to file, target: "_blank" do %>
<%= fa_icon("file", style: "font-size: 2rem") %>
<div class="mt-2"><%= file.filename %></div>
<% end %>
</div>
<% end %>
</li>
</div>
<% if show_delete %>
<div class="col-4 align-self-center p-0 m-0">
<% url = url_for [:destroy_file, broadcast.project, broadcast, { file_id: file.id }] %>
<%= link_to fa_icon("trash fw", text: t('.actions.delete_file')), url, class: "btn btn-danger", remote: true, method: :delete, data: { confirm: t('.confirm_delete') } %>
</div>
<% end %>
</li>
</div>

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,15 +1,19 @@
<% if broadcast.streamer_recording? && broadcast.active? %>
<div id="broadcast_video" class="embed-responsive-item"></div>
<% 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>
<% else %>
<div id="broadcast_video" class="embed-responsive-item">
<div id="broadcast_video" class="embed-responsive-item" data-video-type="stream">
<table class="w-100 h-100 bg-secondary">
<tbody>
<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.
</td>
</tr>
</tbody>
</table>
</div>
<% end %>
<% end %>

View File

@@ -14,150 +14,135 @@
<% end %>
<% content_for :header do %>
<header class="container-fluid py-3 border-bottom sticky-top bg-light">
<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>
<header></header>
<% end %>
<div class="row">
<div class="col-lg-8 col-md-12 mb-3">
<div class="card shadow-sm">
<div class="card-header">
<div class="d-flex justify-content-between align-items-center">
<h1 class="h3 m-0"><%= @broadcast.name %></h1>
<div class="dropdown">
<%= link_to "Switch View", "#", class: "btn btn-light border dropdown-toggle", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } %>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5>
<%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %>
<% @multi_view_broadcasts.each do |broadcast| %>
<% 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) %>
<div class="row no-gutters m-n3">
<div class="col-lg-8 col-md-12 bg-black">
<div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark">
<%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %>
<div class="ml-4 dropdown">
<%= 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 %>
<i class="fa fa-video-camera text-primary" aria-hidden="true"></i><span class="ml-2" id="selected_stream"><%= @broadcast.name %></span>
<% end %>
<div class="dropdown-menu bg-black" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5>
<%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %>
<% @multi_view_broadcasts.each do |broadcast| %>
<% if 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 %>
<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 %>
</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 class="col-lg-4 col-md-12 mb-3">
<div class="card shadow-sm mb-3">
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs">
<li class="nav-item">
<%= link_to "Home", "#home", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
</li>
<li class="nav-item">
<%= link_to "Previous Sessions", "#recordings", class: class_string("nav-link", "active" => params[:active_tab] == "recordings"), data: { toggle: "tab" } %>
</li>
</ul>
</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 class="col-lg-4 col-md-12 bg-white p-3 min-vh-100 overflow-auto">
<% unless controller.class.module_parent.to_s == "Public" %>
<% if @multi_view_broadcasts.present? %>
<% tokens = @multi_view_broadcasts.map(&:token) %>
<div class="btn-group">
<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>
<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>
<% 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>
<!-- files section -->
<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">
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == "files") %>" id="files">
<% if @multi_view_broadcasts.present? %>
<ul class="nav nav-tabs">
<% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<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" } %>
</li>
<% end %>
</ul>
<% end %>
</div>
<div class="card-body p-3">
<div class="tab-content">
<% if @multi_view_broadcasts.present? %>
<div class="tab-content pt-4">
<% @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 %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %>
</div>
<% end %>
<% else %>
<div class="tab-pane fade show active" id="files_broadcast_<%= @broadcast.id %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
</div>
<% end %>
</div>
<% end %>
</div>
<% else %>
<%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
<% end %>
</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 %>
<div class="form-row">
<%= 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(appearance talent 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) } }, 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 class="form-row mb-3">
<%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %>
@@ -29,6 +29,30 @@
<%= form.rich_text_area :guardian_clause %>
<% end %>
</div>
<div id="amendment_clause">
<%= form.form_group do %>
<%= form.rich_text_area :amendment_clause %>
<% end %>
</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">
<%= form.form_group do %>
<%= form.rich_text_area :signature_legal_text %>

View File

@@ -6,7 +6,8 @@
<%= link_to t(".actions.book_demo"), 'https://meetings.hubspot.com/bray2', class: "btn btn-primary border align-self-center h-50 ml-auto mr-2 pb-2", target: '_blank' %>
<% if policy(ContractTemplate).new? %>
<%= link_to t(".actions.create_template"), [:new, @project, :contract_template], class: "btn btn-success border align-self-center h-50 pb-2" %>
<%= link_to t(".actions.create_template"), [:new, @project, :contract_template], class: "btn btn-success border align-self-center h-50 mr-2 pb-2" %>
<%= link_to t(".actions.import_template"), [:new, @project, :release_template_imports], class: "btn btn-light border align-self-center h-50 pb-2" %>
<% end %>
</div>
@@ -47,4 +48,4 @@
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
<% if preview %>
<h1>PREVIEW ONLY</h1>
<% end %>
<p class="heading"><strong><u><%= t '.heading' %></u></strong></p>
<dl>
<%= description_list_pair "#{t('.description_labels.amendment_clause')}:", releasable.contract_template.amendment_clause %>
<%= description_list_pair "#{t('.description_labels.amendment_signer_name')}:", releasable.amendment_signer_name %>
<dt><%= t('.description_labels.amendment_signature') %>:</dt>
<dd>
<% if preview %>
<%= image_tag dummy_signature %>
<% elsif releasable.amendment_signature.attached? %>
<%= image_tag releasable.amendment_signature.variant(auto_orient: true, resize: "200x200") %>
<% end %>
</dd>
</dl>

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 %>
</p>
<% end %>
<% photos = release.file_infos.photo %>
<% photos = release.image_files %>
<% unless photos.empty? %>
<h3>Photos</h3>
<ul>
<% photos.each do |file_info| %>
<% photos.each do |blob| %>
<li>
<%= file_info.filename %>
<%= blob.filename %>
</li>
<% end %>
</ul>
<% end %>
<% videos = release.file_infos.video %>
<% videos = release.video_files %>
<% unless videos.empty? %>
<h3>Videos</h3>
<ul>
<% videos.each do |file_info| %>
<% videos.each do |blob| %>
<li>
<%= file_info.filename %>
<%= blob.filename %>
</li>
<% end %>
</ul>
<% end %>
<% other = release.file_infos.other %>
<% other = release.other_files %>
<% unless other.empty? %>
<h3>Other files</h3>
<ul>
<% other.each do |file_info| %>
<% other.each do |blob| %>
<li>
<%= file_info.filename %>
<%= blob.filename %>
</li>
<% end %>
</ul>

View File

@@ -10,4 +10,10 @@
<%= description_list_pair t('.description_labels.issued_to'), releasable.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 %>
</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>
<% end %>
<% end %>
<%= contract_template.questionnaire_legal_text %>

View File

@@ -18,10 +18,14 @@
<% end %>
</dd>
<% end %>
<%= description_list_pair_for releasable, :name, append: ":" %>
<%= description_list_pair "Contact Address:", releasable.contact_person.address %>
<%= description_list_pair "Contact Phone:", releasable.contact_person.phone %>
<%= description_list_pair "Contact Email:", releasable.contact_person.email %>
<%= description_list_pair t(".labels.#{releasable.model_name.param_key}.name", default: "Name"), releasable.name, append: ":" %>
<% if releasable.model_name == "LocationRelease" %>
<%= description_list_pair "Location Address:", releasable.address %>
<%= description_list_pair "Owner Name", releasable.person_name, append: ":" %>
<% end %>
<%= description_list_pair t(".labels.#{releasable.model_name.param_key}.contact_person_address", default: "Contact Address"), releasable.contact_person.address, append: ":" %>
<%= description_list_pair t(".labels.#{releasable.model_name.param_key}.contact_person_phone", default: "Contact Phone"), releasable.contact_person.phone, append: ":" %>
<%= description_list_pair t(".labels.#{releasable.model_name.param_key}.contact_person_email", default: "Contact Email"), releasable.contact_person.email, append: ":" %>
<% if releasable.model_name == "AppearanceRelease" %>
<%= description_list_pair "Person Date of Birth:", releasable&.person_date_of_birth&.strftime("%D") %>
<% end %>

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