Upstream sync

This commit is contained in:
Senad Uka
2020-09-13 20:09:48 +02:00
parent 3db230de9b
commit 5cf7be6f13
59 changed files with 613 additions and 188 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

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

View File

@@ -1,4 +1,7 @@
$(document).on("click", "[data-behavior=play_recording]", function() { $(document).on("click", "[data-behavior=play_recording]", function() {
clearPlayingHighlight();
$(this).parent().parent().addClass('playing-highlight');
$("#broadcast_video").data('videoType', 'recording'); $("#broadcast_video").data('videoType', 'recording');
var playback_url = $(this).attr("data-playback-url") var playback_url = $(this).attr("data-playback-url")
@@ -14,4 +17,11 @@ $(document).on("click", "[data-behavior=play_recording]", function() {
}); });
}); });
$(document).on("click", "[data-behavior=play_stream]", function() { $("#broadcast_video").data('videoType', 'stream'); }); $(document).on("click", "[data-behavior=play_stream]", function() {
// clearPlayingHighlight();
$("#broadcast_video").data('videoType', 'stream');
});
function clearPlayingHighlight() {
$(".playing-highlight").removeClass("playing-highlight");
}

View File

@@ -468,3 +468,30 @@ trix-toolbar {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z'/%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z'/%3E%3C/svg%3E");
} }
} }
// Play button SVG
.play-btn {
width: 60%;
height: auto;
}
.play-btn-svg{
transition: 0.3s;
stroke:#fedfc2;
opacity: 0;
}
.play-btn:hover .play-btn-svg {
fill-opacity: 0;
opacity: 1;
}
// Play button in video thumbnail preview
.play-thumbnail { position: relative; }
.play-thumbnail img { display: block; }
.play-thumbnail .play-btn { position: absolute; bottom:5px; left:10px; }
// Active recording highlight
.playing-highlight {
background-color: scale-color($primary, $lightness: 80%);
}

View File

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

View File

@@ -1,4 +1,5 @@
class AccountSessionsController < ApplicationController class AccountSessionsController < ApplicationController
skip_before_action :redirect_locked_accounts
def update def update
authorize :account_session, :update? authorize :account_session, :update?
session[:active_account] = account_session_params[:account_id] session[:active_account] = account_session_params[:account_id]

View File

@@ -0,0 +1,31 @@
class Admin::AccountLocksController < Admin::ApplicationController
before_action :set_account
def create
authorize :account_lock, :create?
@account.update(locked: true)
redirect_to admin_accounts_path, notice: 'Account locked'
end
def destroy
authorize :account_lock, :destroy?
@account.update(locked: false)
redirect_to admin_accounts_path, notice: 'Account unlocked'
end
private
def set_account
if params[:account_id].present?
@account = Account.find_by(slug: params[:account_id])
else
failure_redirect
end
rescue ActiveRecord::RecordNotFound
failure_redirect
end
def failure_redirect
redirect_to admin_accounts_path, alert: 'Failed to find the account'
end
end

View File

@@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base
include SetCurrentRequestDetails include SetCurrentRequestDetails
before_action :redirect_accountless before_action :redirect_accountless
before_action :redirect_locked_accounts
private private
@@ -29,6 +30,12 @@ class ApplicationController < ActionController::Base
end end
end end
def redirect_locked_accounts
if Current.user && !Current.user.admin? && Current.account.present? && Current.account.locked?
redirect_to locked_account_path
end
end
def signed_in_as_admin? def signed_in_as_admin?
signed_in? && current_user.admin? signed_in? && current_user.admin?
end end

View File

@@ -0,0 +1,10 @@
class LockedAccountsController < ApplicationController
skip_before_action :redirect_locked_accounts
skip_after_action :verify_policy_scoped
def index
unless Current.account.locked?
redirect_to projects_path
end
end
end

View File

@@ -40,4 +40,13 @@ module DropzoneHelper
{ name: file_info.filename, size: file_info.byte_size, type: file_info.content_type } { name: file_info.filename, size: file_info.byte_size, type: file_info.content_type }
end.to_json end.to_json
end end
def dropzone_file_size_limit_for(releasable)
case releasable.model_name.param_key
when "material_release", "acquired_media_release"
1000000
else
256
end
end
end end

View File

@@ -12,6 +12,7 @@ class ActiveStorageDropzone {
var acceptedFiles = $(element).data("accepted-files") || "image/*"; var acceptedFiles = $(element).data("accepted-files") || "image/*";
var dictDefaultMessage = $(element).data("placeholder") || "Drop files here"; var dictDefaultMessage = $(element).data("placeholder") || "Drop files here";
var submitButton = $($(element).data("submit-button")); var submitButton = $($(element).data("submit-button"));
var maxFileSize = $(element).data("max-file-size");
var that = this; var that = this;
this.myDropzone = new this.DropzoneClass(element, { this.myDropzone = new this.DropzoneClass(element, {
@@ -20,6 +21,7 @@ class ActiveStorageDropzone {
acceptedFiles: acceptedFiles, acceptedFiles: acceptedFiles,
parallelUploads: 30, parallelUploads: 30,
dictDefaultMessage: dictDefaultMessage, dictDefaultMessage: dictDefaultMessage,
maxFilesize: maxFileSize,
init: function () { init: function () {
this.on("sending", (file, xhr, formData) => { this.on("sending", (file, xhr, formData) => {

View File

@@ -15,6 +15,7 @@ class MatchAppearanceReleasesJob < ApplicationJob
matches = response.matches || [] matches = response.matches || []
key_signed_id_hash = Hash[filtered_attachments_object[:keys].zip(filtered_attachments_object[:signed_ids])] key_signed_id_hash = Hash[filtered_attachments_object[:keys].zip(filtered_attachments_object[:signed_ids])]
handle_matches matches, project, key_signed_id_hash handle_matches matches, project, key_signed_id_hash
handle_unmatches matches, project, key_signed_id_hash
matching_request.destroy matching_request.destroy
end end
@@ -40,6 +41,21 @@ class MatchAppearanceReleasesJob < ApplicationJob
end end
end end
def handle_unmatches(matches, project, key_signed_id_hash)
matched_keys = matches.flat_map { |match| match.contracts + match.headshots }
unmatches = key_signed_id_hash.find_all { |key, _| !key.in?(matched_keys) }
unmatches.each do |key, signed_id|
blob = ActiveStorage::Blob.find_signed signed_id
if blob.image?
create_release(project, nil, signed_id, nil)
else
create_release(project, signed_id, nil, nil)
end
end
end
def create_release(project, contract, headshot, identifier) def create_release(project, contract, headshot, identifier)
random_contract_no = AppearanceRelease.random_contract_number.to_s random_contract_no = AppearanceRelease.random_contract_number.to_s
is_incomplete = contract.nil? || headshot.nil? is_incomplete = contract.nil? || headshot.nil?

View File

@@ -0,0 +1,9 @@
class AccountLockPolicy < ApplicationPolicy
def create?
user.admin?
end
def destroy?
user.admin?
end
end

View File

@@ -6,7 +6,7 @@
<%= form.email_field :email, class: "form-group" %> <%= form.email_field :email, class: "form-group" %>
<%= form.password_field :password %> <%= form.password_field :password %>
<%= form.text_field :account_name, label: 'Account Name' %> <%= form.text_field :account_name, label: 'Account Name' %>
<%= form.select :interested_product_name, options_for_select(["I'm interested in all products", "DirectME", "ReleaseME", "CastME", "EditME", "DeliverME", "ExpenseME"]), { label: "What product are you most interested in?" }, { class: "form-control custom-select" } %> <%= form.select :interested_product_name, options_for_select(["I'm interested in all products", "ME Suite PRO", "DirectME", "ReleaseME", "CastME", "EditME", "DeliverME", "ExpenseME"]), { label: "What product are you most interested in?" }, { class: "form-control custom-select" } %>
<div class="pt-3"> <div class="pt-3">
<%= form.submit "Start Free Trial", class: "btn btn-block btn-danger font-weight-bold" %> <%= form.submit "Start Free Trial", class: "btn btn-block btn-danger font-weight-bold" %>
</div> </div>

View File

@@ -4,6 +4,9 @@
<h3>Welcome To <%= suite_wordmark("d-inline-block") %></h3> <h3>Welcome To <%= suite_wordmark("d-inline-block") %></h3>
<div class="mt-4"> <div class="mt-4">
<p>Sign up for a <strong>14 Day Free Trial</strong> which includes full access to the following products. No credit card required!</p> <p>Sign up for a <strong>14 Day Free Trial</strong> which includes full access to the following products. No credit card required!</p>
<div class="d-flex justify-content-between pb-2">
<div><%= image_tag "ME_PRO_black.png", width: "96.66%" %></div>
</div>
<div class="d-flex justify-content-between pb-2"> <div class="d-flex justify-content-between pb-2">
<div><%= image_tag "logo_directme.png", width: "90%" %></div> <div><%= image_tag "logo_directme.png", width: "90%" %></div>
<div><%= image_tag "logo_releaseme.png", width: "90%" %></div> <div><%= image_tag "logo_releaseme.png", width: "90%" %></div>

View File

@@ -1,8 +1,11 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @acquired_media_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(AcquiredMediaRelease).new? %> <% if policy(AcquiredMediaRelease).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :acquired_media_release], class: "btn btn-primary mr-2 mb-2" %> <div class="mr-auto">
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :acquired_media_release], class: "btn btn-primary mr-2 mb-2" %>
</div>
<% end %> <% end %>
<% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).tag_multiple? %> <% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %> <% end %>
<% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).download_multiple? %> <% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @acquired_media_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @acquired_media_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -30,6 +30,11 @@
<%= link_to fa_icon("arrow-right", text: "Overview"), admin_account_path(account), class: "dropdown-item" %> <%= link_to fa_icon("arrow-right", text: "Overview"), admin_account_path(account), class: "dropdown-item" %>
<%= link_to fa_icon("pencil", text: "Edit"), edit_admin_account_path(account), class: "dropdown-item" %> <%= link_to fa_icon("pencil", text: "Edit"), edit_admin_account_path(account), class: "dropdown-item" %>
<%= link_to fa_icon("arrow-right", text: "Account Managers"), account_auths_path({ account_id: account.id}), class: "dropdown-item" %> <%= link_to fa_icon("arrow-right", text: "Account Managers"), account_auths_path({ account_id: account.id}), class: "dropdown-item" %>
<% if account.locked? %>
<%= link_to fa_icon("unlock", text: "Unlock Account"), [:admin, account, :lock], method: :delete, class: "dropdown-item" %>
<% else %>
<%= link_to fa_icon("lock", text: "Lock Account"), [:admin, account, :lock], method: :post, class: "dropdown-item" %>
<% end %>
</div> </div>
</div> </div>
</td> </td>

View File

@@ -1,29 +1,31 @@
<% if recordings.present? %> <ul class="list-unstyled">
<div class="list-group"> <% recordings.each do |recording| %>
<% recordings.each do |recording| %> <li class="media p-3">
<div class="list-group-item list-group-item-action"> <% if policy(BroadcastRecording).update? %>
<div class="d-flex align-items-start"> <%= link_to fa_icon("#{recording.starred ? 'star' : 'star-o'} fw"), [broadcast.project, broadcast, recording, :broadcast_recording_starrings], method: :post, class: "text-warning mr-2", remote: true %>
<% if policy(BroadcastRecording).update? %> <% end %>
<%= 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 %> <div class="play-thumbnail">
<%= image_tag(recording.thumbnail_url, class: 'img-thumbnail img-fluid max-w-75', data: { behavior: "play_recording", playback_url: recording.playback_url, id: dom_id(recording) }) %> <%= image_tag(recording.thumbnail_url, class: 'mr-2', size: "64x64") %>
<div class="ml-auto"> <%= content_tag :div, class: "play-btn", data: { behavior: "play_recording", playback_url: recording.playback_url, id: dom_id(recording) } do %>
<% if policy(BroadcastRecording).edit? %> <%= render "broadcasts/play_button_svg" %>
<%= link_to fa_icon('edit'), [:edit, broadcast.project, broadcast, recording], remote: true %> <% end %>
<% 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> </div>
<% end %>
</div> <div class="media-body">
<div id="recordings_pagination" class="row mt-5 justify-content-center"> <h5 class="mt-0 mb-1"><%= recording.name %></h5>
<%= will_paginate(recordings, params: {controller: "broadcasts", action: "show", project_id: broadcast.project_id, id: broadcast.id, page: params[:page], active_tab: 'recordings'}) %> <small class="text-muted"><%= recording.description %></small>
</div> </div>
<% else %>
<p class="mt-4">Recording of the live stream will appear here.</p> <% if policy(BroadcastRecording).edit? %>
<% end %> <%= link_to fa_icon('edit'), [:edit, broadcast.project, broadcast, recording], class: "mr-3", remote: true %>
<% end %>
<%= link_to(fa_icon('download'), recording.download_url, target: "_blank") %>
</li>
<% end %>
</ul>
<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>

View File

@@ -1,13 +1,9 @@
<% if broadcast.streamer_connected? || (broadcast.streamer_recording? && !broadcast.active?) %> <% if broadcast.streamer_connected? || (broadcast.streamer_recording? && !broadcast.active?) %>
<p class="mb-1">Live stream has connected successfully and will be available soon.</p> <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? %> <% elsif broadcast.streamer_recording? && broadcast.active? %>
<p class="mb-1">Live stream has begun, click play to watch it.</p> <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? %> <% elsif broadcast.streamer_disconnected? %>
<p class="mb-1">Live stream got disconnected.</p> <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?) %> <% elsif (broadcast.idle? && broadcast.streamer_idle?) || (broadcast.created? && broadcast.streamer_idle?) %>
<p class="mb-1">Live stream is waiting to begin.</p> <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 %> <% end %>

View File

@@ -1,4 +1,4 @@
<div class="text-center pb-2" id="broadcast_file_form_<%= broadcast.token %>"> <div class="text-center p-3" id="broadcast_file_form_<%= broadcast.token %>">
<% if controller.class.module_parent.to_s == "Public" %> <% if controller.class.module_parent.to_s == "Public" %>
<%= render partial: "public/broadcasts/file_form", locals: { model: [broadcast], token: broadcast.token } %> <%= render partial: "public/broadcasts/file_form", locals: { model: [broadcast], token: broadcast.token } %>
<% else %> <% else %>

View File

@@ -1,12 +1,35 @@
<div class="list-group"> <% # TODO: Refactor this %>
<div class="list-group-item list-group-item-action flex-column align-items-start"> <% if params[:director_mode] %>
<div class="d-flex w-100 justify-content-between mb-1"> <% if controller.class.module_parent.to_s == "Public" %>
<h5 class="mb-1"><%= broadcast.name %></h5> <% live_take_url = url_for(params.permit!.merge(director_mode: true, token: broadcast.token)) %>
<small>Created - <%= time_ago_in_words(broadcast.created_at) + " ago" %></small> <% else %>
</div> <% live_take_url = url_for(params.permit!.merge(director_mode: true, id: broadcast.id)) %>
<div id="broadcast_updates"> <% end %>
<hr/>
<% else %>
<% if controller.class.module_parent.to_s == "Public" %>
<% live_take_url = url_for(params.permit!.merge(token: broadcast.token).except(:director_mode)) %>
<% else %>
<% live_take_url = url_for(params.permit!.merge(id: broadcast.id).except(:director_mode)) %>
<% end %>
<% end %>
<div id="live-take" class="media p-3 playing-highlight">
<div id="recording_status">
<%= render 'broadcasts/recording_status', broadcast: broadcast %>
</div>
<div class="play-thumbnail">
<%= image_tag "live_icon.png", class: "mr-2", width: 64, alt: "Live stream thumbnail" %>
<%= link_to live_take_url, class: "play-btn", data: { behavior: "play_stream" } do %>
<%= render "broadcasts/play_button_svg" %>
<% end %>
</div>
<div class="media-body">
<h5 class="mt-0"><%= broadcast.name %></h5>
<small id="broadcast_updates" class="text-muted">
<%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %> <%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %>
</div> </small>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26">
<polygon class="play-btn-svg" points="9.33 6.69 9.33 19.39 19.3 13.04 9.33 6.69"/>
</svg>

After

Width:  |  Height:  |  Size: 153 B

View File

@@ -0,0 +1 @@
<%= fa_icon "circle fw", class: class_string('mr-2', 'text-danger' => broadcast.streamer_recording? && broadcast.active?) %>

View File

@@ -13,12 +13,18 @@
<% end %> <% end %>
<% end %> <% end %>
<style>
body {
overflow-x: hidden;
}
</style>
<% content_for :header do %> <% content_for :header do %>
<header></header> <header></header>
<% end %> <% end %>
<div class="row no-gutters m-n3"> <div class="row no-gutters m-n3">
<div class="col-lg-8 col-md-12 bg-black"> <div class="col-lg-9 col-md-12 bg-black vh-100">
<div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark"> <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') %> <%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %>
<div class="ml-4 dropdown"> <div class="ml-4 dropdown">
@@ -85,32 +91,34 @@
<% end %> <% end %>
</div> </div>
</div> </div>
<div class="col-lg-4 col-md-12 bg-white p-3 min-vh-100 overflow-auto"> <div class="col-lg-3 col-md-12 bg-white vh-100 overflow-auto">
<% unless controller.class.module_parent.to_s == "Public" %> <div class="px-3 pt-3">
<% if @multi_view_broadcasts.present? %> <% unless controller.class.module_parent.to_s == "Public" %>
<% tokens = @multi_view_broadcasts.map(&:token) %> <% if @multi_view_broadcasts.present? %>
<div class="btn-group"> <% tokens = @multi_view_broadcasts.map(&:token) %>
<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> <div class="btn-group">
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <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>
<span class="sr-only">Toggle Dropdown</span> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button> <span class="sr-only">Toggle Dropdown</span>
<div class="dropdown-menu"> </button>
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %> <div class="dropdown-menu">
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %>
</div>
</div> </div>
</div> <% else %>
<% else %> <div class="btn-group">
<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" 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">
<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>
<span class="sr-only">Toggle Dropdown</span> </button>
</button> <div class="dropdown-menu">
<div class="dropdown-menu"> <%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %>
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %> </div>
</div> </div>
</div> <% end %>
<% end %> <% end %>
<% end %> <%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary', target: '_blank' %>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary', target: '_blank' %> </div>
<hr/> <hr/>
<ul class="nav nav-tabs override-nav-tabs mb-3"> <ul class="nav nav-tabs override-nav-tabs mb-3">
<li class="nav-item"> <li class="nav-item">
@@ -125,21 +133,6 @@
<div id="live_take"> <div id="live_take">
<%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %> <%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %>
</div> </div>
<% if params[:director_mode] %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(director_mode: true, token: @broadcast.token)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% else %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(director_mode: true, id: @broadcast.id)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% end %>
<hr/>
<% else %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(token: @broadcast.token).except(:director_mode)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% else %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(id: @broadcast.id).except(:director_mode)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% end %>
<hr/>
<% end %>
<div id="broadcast_recordings"> <div id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %> <%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
</div> </div>
@@ -153,7 +146,7 @@
</li> </li>
<% end %> <% end %>
</ul> </ul>
<div class="tab-content pt-4"> <div class="tab-content">
<% @multi_view_broadcasts.each_with_index do |mvb, index| %> <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>"> <div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %> <%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %>

View File

@@ -0,0 +1,37 @@
<% has_logo = local_assigns[:logo] %>
<% has_user_photo = releasable.model_name == "AppearanceRelease" && releasable.person_photo.attached? %>
<% if has_logo || has_user_photo %>
<table class="heading-table">
<tr>
<td>
<% if has_logo %>
<div class="logo">
<%= render "blank_contracts/logo", logo: logo %>
</div>
<% end %>
</td>
<td class="embed-person-photo">
<% if has_user_photo %>
<%= image_tag releasable.photos.first.variant(auto_orient: true, resize: "200x200"), id: "top-person-photo" %>
<% end %>
</td>
</tr>
</table>
<hr>
<% end %>
<% if preview %>
<h1>PREVIEW ONLY</h1>
<% end %>
<% if contract_template.body.present? %>
<%= contract_template.body %>
<br/>
<% end %>
<% if releasable.minor? && contract_template.guardian_clause.present? %>
<p class="text-left"><strong>Guardian Clause</strong></p>
<%= contract_template.guardian_clause %>
<% end %>

View File

@@ -1,33 +1,12 @@
<% if local_assigns[:logo] %> <% logo = local_assigns[:logo] ? local_assigns[:logo] : nil %>
<div class="logo">
<%= render "contracts/logo", logo: logo %> <% if logo || (releasable.model_name == 'AppearanceRelease' && releasable.person_photo.attached?) ||
contract_template.body.present? || (releasable.minor? && contract_template.guardian_clause.present?) %>
<div class="page">
<%= render "contracts/logo_page", logo: logo, preview: preview, releasable: releasable, contract_template: contract_template %>
</div> </div>
<hr>
<% end %> <% end %>
<div class="page">
<% if preview %>
<h1>PREVIEW ONLY</h1>
<% end %>
<% if releasable.model_name == "AppearanceRelease" && releasable.person_photo.attached? %>
<div class="embed-person-photo">
<%= image_tag releasable.photos.first.variant(auto_orient: true, resize: "200x200"), id: "top-person-photo" %>
</div>
<hr>
<% end %>
<% if contract_template.body.present? %>
<%= contract_template.body %>
<br/>
<% end %>
<% if releasable.minor? && contract_template.guardian_clause.present? %>
<p class="text-left"><strong>Guardian Clause</strong></p>
<%= contract_template.guardian_clause %>
<% end %>
</div>
<% if contract_template.present? && contract_template.has_questionnaire? %> <% if contract_template.present? && contract_template.has_questionnaire? %>
<div class="page"> <div class="page">
<%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %> <%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>

View File

@@ -1,8 +1,11 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @location_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(LocationRelease).new? %> <% if policy(LocationRelease).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :location_release], class: "btn btn-primary mr-2 mb-2" %> <div class="mr-auto">
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :location_release], class: "btn btn-primary mr-2 mb-2" %>
</div>
<% end %> <% end %>
<% if @location_releases.any? && policy(LocationRelease).tag_multiple? %> <% if @location_releases.any? && policy(LocationRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %> <% end %>
<% if @location_releases.any? && policy(LocationRelease).download_multiple? %> <% if @location_releases.any? && policy(LocationRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @location_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @location_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -0,0 +1 @@
<p><%= t '.account_locked_message' %></p>

View File

@@ -42,7 +42,7 @@
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, material_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %> <%= link_to fa_icon("tags fw", text: "Tags"), [:new, material_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %> <% end %>
<% if policy(material_release).edit_files? %> <% if policy(material_release).edit_files? %>
<%= link_to fa_icon("file-o fw", text: "Add Media"), [:edit, material_release, :files], class: "dropdown-item" %> <%= link_to fa_icon("file-o fw", text: "Media"), [:edit, material_release, :files], class: "dropdown-item" %>
<% end %> <% end %>
<% if policy(Contract).show? && (material_release.contract.attached? || material_release.contract_template.present?) %> <% if policy(Contract).show? && (material_release.contract.attached? || material_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [material_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %> <%= link_to fa_icon("download fw", text: "Download"), [material_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>

View File

@@ -1,8 +1,11 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @material_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(MaterialRelease).new? %> <% if policy(MaterialRelease).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :material_release], class: "btn btn-primary mr-2 mb-2" %> <div class="mr-auto">
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :material_release], class: "btn btn-primary mr-2 mb-2" %>
</div>
<% end %> <% end %>
<% if @material_releases.any? && policy(MaterialRelease).tag_multiple? %> <% if @material_releases.any? && policy(MaterialRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %> <% end %>
<% if @material_releases.any? && policy(MaterialRelease).download_multiple? %> <% if @material_releases.any? && policy(MaterialRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @material_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @material_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -1,12 +1,15 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @medical_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if @medical_releases.any? && policy(MedicalRelease).tag_multiple? %> <% if @medical_releases.any? && policy(MedicalRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %> <div class="ml-auto">
<%= button_to_bulk_tagging(@project) %>
</div>
<% end %> <% end %>
<% if @medical_releases.any? && policy(MedicalRelease).download_multiple? %> <% if @medical_releases.any? && policy(MedicalRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @medical_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @medical_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -1,12 +1,15 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @misc_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if @misc_releases.any? && policy(MiscRelease).tag_multiple? %> <% if @misc_releases.any? && policy(MiscRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %> <div class="ml-auto">
<%= button_to_bulk_tagging(@project) %>
</div>
<% end %> <% end %>
<% if @misc_releases.any? && policy(MiscRelease).download_multiple? %> <% if @misc_releases.any? && policy(MiscRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @misc_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @misc_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -1,8 +1,11 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @music_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(MusicRelease).new? %> <% if policy(MusicRelease).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :music_release], class: "btn btn-primary mr-2 mb-2" %> <div class="mr-auto">
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :music_release], class: "btn btn-primary mr-2 mb-2" %>
</div>
<% end %> <% end %>
<% if @music_releases.any? && policy(MusicRelease).tag_multiple? %> <% if @music_releases.any? && policy(MusicRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %> <% end %>
<% if @music_releases.any? && policy(MusicRelease).download_multiple? %> <% if @music_releases.any? && policy(MusicRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @music_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2" %> <%= button_to "Download", [@project, :contract_downloads, release_type: @music_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2" %>
<% end %> <% end %>
<%= bootstrap_form_with url: [@project, :music_releases], method: :get, remote: true, layout: :inline, id: "search" do |form| %> <%= bootstrap_form_with url: [@project, :music_releases], method: :get, remote: true, layout: :inline, id: "search" do |form| %>

View File

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

View File

@@ -14,4 +14,5 @@
data-file-input-id="releasable_files" data-file-input-id="releasable_files"
data-existing-files="<%= mock_photos_json(releasable.files) %>" data-existing-files="<%= mock_photos_json(releasable.files) %>"
data-placeholder="<%= dropzone_placeholder_message_for(releasable) %>" data-placeholder="<%= dropzone_placeholder_message_for(releasable) %>"
data-submit-button="#submit_folder"></div> data-submit-button="#submit_folder"
data-max-file-size="<%= dropzone_file_size_limit_for(releasable) %>"></div>

View File

@@ -1,8 +1,11 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @talent_releases.total_entries %> />
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(TalentRelease).new? %> <% if policy(TalentRelease).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :talent_release], class: "btn btn-primary mr-2 mb-2" %> <div class="mr-auto">
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :talent_release], class: "btn btn-primary mr-2 mb-2" %>
</div>
<% end %> <% end %>
<% if @talent_releases.any? && policy(TalentRelease).tag_multiple? %> <% if @talent_releases.any? && policy(TalentRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %> <% end %>
<% if @talent_releases.any? && policy(TalentRelease).download_multiple? %> <% if @talent_releases.any? && policy(TalentRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @talent_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { <%= button_to "Download", [@project, :contract_downloads, release_type: @talent_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: {
disable_with: "Please wait..." } %> disable_with: "Please wait..." } %>
<% end %> <% end %>

View File

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

View File

@@ -1651,3 +1651,6 @@ en:
edit: Edit edit: Edit
report: Report report: Report
generating: Generating... generating: Generating...
locked_accounts:
index:
account_locked_message: This account is locked. Please contact a BIG admin.

View File

@@ -705,3 +705,6 @@ es:
production_elements_logs: Production Elements Logs, and more (ES) production_elements_logs: Production Elements Logs, and more (ES)
reduces_labor_cost: Reduces labor costs (ES) reduces_labor_cost: Reduces labor costs (ES)
simplifies_cue_sheets: Simplifies Music Cue Sheets, Graphic Cue Sheets (ES) simplifies_cue_sheets: Simplifies Music Cue Sheets, Graphic Cue Sheets (ES)
locked_accounts:
index:
account_locked_message: This account is locked. Please contact a BIG admin. (ES)

View File

@@ -30,7 +30,9 @@ Rails.application.routes.draw do
namespace :admin do namespace :admin do
mount Sidekiq::Web => '/background_queue', as: :background_queue mount Sidekiq::Web => '/background_queue', as: :background_queue
resources :accounts, only: [:index, :new, :create, :edit, :update, :show] resources :accounts, only: [:index, :new, :create, :edit, :update, :show] do
resource :account_lock, path: :lock, as: :lock, only: [:create, :destroy]
end
resources :users, only: [:index, :new, :create, :edit, :update, :destroy] do resources :users, only: [:index, :new, :create, :edit, :update, :destroy] do
resource :masquerade, only: :create resource :masquerade, only: :create
end end
@@ -48,7 +50,9 @@ Rails.application.routes.draw do
scope "(:locale)", locale: AVAILABLE_LOCALES_REGEX do scope "(:locale)", locale: AVAILABLE_LOCALES_REGEX do
resource :account_session, only: [:update] resource :account_session, only: [:update]
resource :session, only: [:destroy] resource :session, only: [:destroy]
resource :account, only: [:new, :create, :update] resource :account, only: [:new, :create, :update] do
get 'locked' => 'locked_accounts#index'
end
resources :account_auths, only: [:index, :create, :update, :destroy] resources :account_auths, only: [:index, :create, :update, :destroy]
resources :projects, shallow: true do resources :projects, shallow: true do
resources :acquired_media_releases, except: [:show], concerns: [:contractable, :notable, :file_uploadable] resources :acquired_media_releases, except: [:show], concerns: [:contractable, :notable, :file_uploadable]

View File

@@ -0,0 +1,5 @@
class AddLockedToAccounts < ActiveRecord::Migration[6.0]
def change
add_column :accounts, :locked, :boolean, default: false
end
end

View File

@@ -95,7 +95,8 @@ CREATE TABLE public.accounts (
slug character varying, slug character varying,
plan_uid character varying, plan_uid character varying,
created_at timestamp without time zone NOT NULL, created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL updated_at timestamp without time zone NOT NULL,
locked boolean DEFAULT false
); );
@@ -4027,6 +4028,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200812060406'), ('20200812060406'),
('20200819070738'), ('20200819070738'),
('20200820082501'), ('20200820082501'),
('20200824171649'); ('20200824171649'),
('20200908085319');

View File

@@ -17,7 +17,7 @@ RSpec.describe BroadcastsChannel, type: :channel do
it "broadcasts to the channel" do it "broadcasts to the channel" do
status_content = ApplicationController.render partial: "broadcasts/broadcast_status", locals: { broadcast: broadcast } status_content = ApplicationController.render partial: "broadcasts/broadcast_status", locals: { broadcast: broadcast }
video_content = ApplicationController.render partial: "broadcasts/video", locals: { broadcast: broadcast } video_content = ApplicationController.render partial: "broadcasts/video", locals: { broadcast: broadcast }
live_take = ApplicationController.render partial: "broadcasts/live_take", locals: { broadcast: broadcast } recording_status_content = ApplicationController.render partial: "broadcasts/recording_status", locals: { broadcast: broadcast }
expect { expect {
BroadcastsChannel.broadcast_stream_updates(broadcast) BroadcastsChannel.broadcast_stream_updates(broadcast)
@@ -28,7 +28,7 @@ RSpec.describe BroadcastsChannel, type: :channel do
full_live_stream_playback_url: broadcast.full_live_stream_playback_url, full_live_stream_playback_url: broadcast.full_live_stream_playback_url,
status_content: status_content, status_content: status_content,
video_content: video_content, video_content: video_content,
live_take_content: live_take, recording_status_content: recording_status_content,
streamer_status: broadcast.streamer_status streamer_status: broadcast.streamer_status
}) })
end end

View File

@@ -30,6 +30,24 @@ feature "Admin managing accounts" do
expect(page).to have_content "Created at less than a minute ago" expect(page).to have_content "Created at less than a minute ago"
end end
scenario "locks and unlocks account" do
sign_in current_user
visit admin_signed_in_root_path
expect(Account.last.locked?).to eq false
click_button "Manage"
expect(page).not_to have_content "Unlock Account"
click_link "Lock Account"
expect(Account.last.locked?).to eq true
click_button "Manage"
expect(page).not_to have_content "Lock Account"
click_link "Unlock Account"
expect(Account.last.locked?).to eq false
end
scenario "sees videos for an account in the system" do scenario "sees videos for an account in the system" do
visit_account_overview_page visit_account_overview_page

View File

@@ -1,6 +1,13 @@
require "rails_helper" require "rails_helper"
feature "Guest account sign up" do feature "Guest account sign up" do
scenario "guest can select ME Suite PRO in 'interested in' dropdown" do
visit new_account_path
expect(page).to have_selector("img[src*='ME_PRO_black']")
select "ME Suite PRO", from: interested_in_product_dropdown
end
scenario "creates a new account and signs in successfully" do scenario "creates a new account and signs in successfully" do
visit new_account_path visit new_account_path
@@ -38,4 +45,10 @@ feature "Guest account sign up" do
expect(page).to have_content "Sign Up" expect(page).to have_content "Sign Up"
end end
private
def interested_in_product_dropdown
"user[interested_product_name]"
end
end end

View File

@@ -684,6 +684,15 @@ feature 'User managing appearance releases' do
expect(page).to have_selector("#top-person-photo[src^='#{person_photo_url}']") expect(page).to have_selector("#top-person-photo[src^='#{person_photo_url}']")
end end
scenario "viewing the contract PDF - it shows person photo on first page if person photo is attached" do
appearance_release = create(:appearance_release_with_contract_template, :native, :minor_with_guardian_photo, project: project)
visit view_release_pdf_html_preview_link_for(appearance_release)
person_photo_url = url_for(appearance_release.person_photo.variant(auto_orient: true, resize: "200x200")).to_s
expect(page).to have_selector("#top-person-photo[src^='#{person_photo_url}']")
end
scenario 'deleting a release', js: true do scenario 'deleting a release', js: true do
appearance_release = create(:appearance_release, project: project) appearance_release = create(:appearance_release, project: project)

View File

@@ -151,6 +151,41 @@ feature 'User managing broadcasts' do
end end
end end
scenario 'broadcast recordings are shown in correct layout', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
create(:broadcast_recording, broadcast: broadcast, asset_uid: "asset_uid_1")
visit project_broadcast_path(project, broadcast)
expect(page).to have_selector("li.media")
expect(page).to have_selector("div.play-thumbnail")
expect(page).to have_selector("div.media-body")
expect(page).to have_selector("div.play-btn")
end
scenario 'active playing media has highlighted background (live take or recording)', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
create(:broadcast_recording, broadcast: broadcast, asset_uid: "asset_uid_1")
create(:broadcast_recording, broadcast: broadcast, asset_uid: "asset_uid_2")
visit project_broadcast_path(project, broadcast)
expect(page).to have_selector("#live-take.playing-highlight")
expect(page).to have_selector(".play-btn-svg", count: 3, visible: false)
first("[data-behavior='play_recording']").click
expect(page).not_to have_selector("#live-take.playing-highlight")
expect(page).to have_selector("li.media.playing-highlight", count: 1)
expect(page).to have_selector("li.media", count: 2)
first("[data-behavior='play_stream']").click
expect(page).to have_selector("#live-take.playing-highlight")
expect(page).to have_selector("li.media", count: 2)
expect(page).not_to have_selector("li.media.playing-highlight")
end
context 'When the user is associate' do context 'When the user is associate' do
let(:current_user) { create(:user, :associate) } let(:current_user) { create(:user, :associate) }

View File

@@ -0,0 +1,34 @@
require "rails_helper"
feature "User managing locked account" do
let(:user) { create(:user, :account_manager) }
let(:project) { create(:project) }
before do
sign_in(user)
user.accounts.first.update(locked: true)
end
scenario "user is redirected to custom landing page when opens projects index page" do
paths = [
projects_path,
project_path(project),
project_task_requests_path(project),
project_contract_templates_path(project),
project_broadcasts_path(project),
project_videos_path(project),
]
paths.each do |path|
visit path
expect(page).to have_content locked_account_warning
end
end
private
def locked_account_warning
t 'locked_accounts.index.account_locked_message'
end
end

View File

@@ -367,7 +367,7 @@ feature "User managing material releases" do
expect(page).to have_content("No Media") expect(page).to have_content("No Media")
click_on "Manage" click_on "Manage"
click_on "Add Media" click_on "Media"
expect(page).to have_content("Add Files") expect(page).to have_content("Add Files")
expect(page).to have_content("Apple MacBook Air") expect(page).to have_content("Apple MacBook Air")

View File

@@ -197,13 +197,13 @@ feature "User managing medical releases" do
expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1) expect(page).to have_css('i.fa.fa-check-circle.fa-2x', count: 1)
end end
scenario "Download All is visible" do scenario "Download button is visible" do
create(:medical_release_with_contract_template, :native, project: project) create(:medical_release_with_contract_template, :native, project: project)
create(:medical_release_with_contract_template, :non_native, project: project) create(:medical_release_with_contract_template, :non_native, project: project)
visit project_medical_releases_path(project) visit project_medical_releases_path(project)
expect(page).to have_content download_all_button expect(page).to have_content download_button
end end
scenario "Download action in Manage menu is visible" do scenario "Download action in Manage menu is visible" do
@@ -285,7 +285,7 @@ feature "User managing medical releases" do
visit project_medical_releases_path(project) visit project_medical_releases_path(project)
expect(page).not_to have_content download_all_button expect(page).not_to have_content download_button
end end
scenario "Download action in Manage menu is not visible" do scenario "Download action in Manage menu is not visible" do
@@ -329,7 +329,7 @@ feature "User managing medical releases" do
visit project_medical_releases_path(project) visit project_medical_releases_path(project)
expect(page).not_to have_content download_all_button expect(page).not_to have_content download_button
end end
scenario "Download action in Manage menu is not visible" do scenario "Download action in Manage menu is not visible" do
@@ -362,8 +362,8 @@ feature "User managing medical releases" do
private private
def download_all_button def download_button
'Download All' 'Download'
end end
def download_action def download_action

View File

@@ -62,12 +62,12 @@ feature "User managing misc releases" do
sign_in current_user sign_in current_user
end end
scenario "Download All is visible" do scenario "Download is visible" do
create(:misc_release_with_contract_template, :native, project: project) create(:misc_release_with_contract_template, :native, project: project)
visit project_misc_releases_path(project) visit project_misc_releases_path(project)
expect(page).to have_content download_all_button expect(page).to have_content download_button
end end
scenario "Downloading PDF of native misc release is possible" do scenario "Downloading PDF of native misc release is possible" do
@@ -165,8 +165,8 @@ feature "User managing misc releases" do
private private
def download_all_button def download_button
'Download All' 'Download'
end end
def view_release_pdf_link_for(release) def view_release_pdf_link_for(release)

View File

@@ -86,34 +86,36 @@ describe GenerateContractsZipJob do
end end
it "generates ZIP containing CSV file with all filtered releases data for filtered releases" do it "generates ZIP containing CSV file with all filtered releases data for filtered releases" do
lowercase_plural = subject.constantize.model_name.plural if subject.respond_to?(:complete) && subject.respond_to?(:incomplete)
GenerateContractsZipJob.perform_now(project, download, subject, [], '', 'complete') lowercase_plural = subject.constantize.model_name.plural
GenerateContractsZipJob.perform_now(project, download, subject, [], '', 'complete')
complete_releases = project.public_send(lowercase_plural).complete complete_releases = project.public_send(lowercase_plural).complete
incomplete_releases = project.public_send(lowercase_plural).incomplete incomplete_releases = project.public_send(lowercase_plural).incomplete
generated_zip = download.file.blob.download generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv" csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
Zip::InputStream.open(StringIO.new(generated_zip)) do |io| Zip::InputStream.open(StringIO.new(generated_zip)) do |io|
while entry = io.get_next_entry while entry = io.get_next_entry
next unless entry.name == csv_file_name next unless entry.name == csv_file_name
csv_file = entry.get_input_stream.read csv_file = entry.get_input_stream.read
release_class = Object.const_get subject release_class = Object.const_get subject
release_headers = release_class.csv_headers release_headers = release_class.csv_headers
release_headers.each do |header| release_headers.each do |header|
expect(csv_file).to match header expect(csv_file).to match header
expect(csv_file).not_to match translation_missing expect(csv_file).not_to match translation_missing
end end
complete_releases.each do |release| complete_releases.each do |release|
expect(csv_file).to match release.person_first_name expect(csv_file).to match release.person_first_name
end end
incomplete_releases.each do |release| incomplete_releases.each do |release|
expect(csv_file).not_to match release.person_first_name expect(csv_file).not_to match release.person_first_name
end
end end
end end
end end
@@ -164,16 +166,19 @@ describe GenerateContractsZipJob do
end end
context "generates ZIP for acquired media releases" do context "generates ZIP for acquired media releases" do
let(:release) { create(:acquired_media_release_with_contract_template, :native, project: project) } let(:release) { create(:acquired_media_release_with_contract_template, :native, project: project, name: "John Doe") }
let(:release2) { create(:acquired_media_release_with_contract_template, :native, project: project, name: "Jane Doe") }
let(:release3) { create(:acquired_media_release_with_contract_template, :native, project: project, name: "Brad Doe") }
subject { 'AcquiredMediaRelease' } subject { 'AcquiredMediaRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for appearance releases" do context "generates ZIP for appearance releases" do
let(:release) { create(:appearance_release_with_contract_template, :native, project: project, person_name: "John Doe") } let(:release) { create(:appearance_release_with_contract_template, :native, project: project, person_name: "John") }
let(:incomplete_release) { create(:appearance_release_with_contract_template, project: project, person_name: "Jane Doe") } let(:incomplete_release) { create(:appearance_release_with_contract_template, project: project, person_name: "Jane") }
let(:complete_release) { create(:appearance_release_with_contract_template, :non_native, project: project, person_name: "Brad Doe") } let(:complete_release) { create(:appearance_release_with_contract_template, :non_native, project: project, person_name: "Brad") }
subject { 'AppearanceRelease' } subject { 'AppearanceRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
@@ -181,45 +186,63 @@ describe GenerateContractsZipJob do
end end
context "generates ZIP for location releases" do context "generates ZIP for location releases" do
let(:release) { create(:location_release_with_contract_template, :native, project: project) } let(:release) { create(:location_release_with_contract_template, :native, project: project, name: "John") }
let(:release2) { create(:location_release_with_contract_template, :native, project: project, name: "Jane") }
let(:release3) { create(:location_release_with_contract_template, :native, project: project, name: "Brad") }
subject { 'LocationRelease' } subject { 'LocationRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for material releases" do context "generates ZIP for material releases" do
let(:release) { create(:material_release_with_contract_template, :native, project: project) } let(:release) { create(:material_release_with_contract_template, :native, project: project, name: "John") }
let(:release2) { create(:material_release_with_contract_template, :native, project: project, name: "Jane") }
let(:release3) { create(:material_release_with_contract_template, :native, project: project, name: "Brad") }
subject { 'MaterialRelease' } subject { 'MaterialRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for medical releases" do context "generates ZIP for medical releases" do
let(:release) { create(:medical_release_with_contract_template, :native, project: project) } let(:release) { create(:medical_release_with_contract_template, :native, project: project, person_name: "John Doe") }
let(:release2) { create(:medical_release_with_contract_template, :native, project: project, person_name: "Jane Doe") }
let(:release3) { create(:medical_release_with_contract_template, :native, project: project, person_name: "Brad Doe") }
subject { 'MedicalRelease' } subject { 'MedicalRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for misc releases" do context "generates ZIP for misc releases" do
let(:release) { create(:misc_release_with_contract_template, :native, project: project) } let(:release) { create(:misc_release_with_contract_template, :native, project: project, person_name: "John Doe") }
let(:release2) { create(:misc_release_with_contract_template, :native, project: project, person_name: "Jane Doe") }
let(:release3) { create(:misc_release_with_contract_template, :native, project: project, person_name: "Brad Doe") }
subject { 'MiscRelease' } subject { 'MiscRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for music releases" do context "generates ZIP for music releases" do
let(:release) { create(:music_release_with_contract_template, project: project) } let(:release) { create(:music_release_with_contract_template, project: project, name: "John") }
let(:release2) { create(:music_release_with_contract_template, project: project, name: "Jane") }
let(:release3) { create(:music_release_with_contract_template, project: project, name: "Brad") }
subject { 'MusicRelease' } subject { 'MusicRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for talent releases" do context "generates ZIP for talent releases" do
let(:release) { create(:talent_release_with_contract_template, :native, project: project) } let(:release) { create(:talent_release_with_contract_template, :native, project: project, person_name: "John Doe") }
let(:release2) { create(:talent_release_with_contract_template, :native, project: project, person_name: "Jane Doe") }
let(:release3) { create(:talent_release_with_contract_template, :native, project: project, person_name: "Brad Doe") }
subject { 'TalentRelease' } subject { 'TalentRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "When there are errors" do context "When there are errors" do

View File

@@ -23,7 +23,7 @@ describe MatchAppearanceReleasesJob do
MatchAppearanceReleasesJob.perform_now project, attachments MatchAppearanceReleasesJob.perform_now project, attachments
end end
it "does not create new appearance release if BrayniacAI returns empty matches array" do it "creates a new incomplete appearance release for headshots which cannot be matched by BrayniacAI" do
signed_ids = [dummy_appearance_release.person_photo.blob.signed_id] signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
keys = [dummy_appearance_release.person_photo.key] keys = [dummy_appearance_release.person_photo.key]
payload = { payload = {
@@ -44,9 +44,41 @@ describe MatchAppearanceReleasesJob do
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response) expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy) expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids expect {
MatchAppearanceReleasesJob.perform_now project, signed_ids
}.to change{AppearanceRelease.count}.by(1)
expect(AppearanceRelease.last).to eq dummy_appearance_release expect(AppearanceRelease.last.contract).not_to be_attached
expect(AppearanceRelease.last.person_photo).to be_attached
end
it "creates a new incomplete appearance release for contracts which cannot be matched by BrayniacAI" do
signed_ids = [dummy_appearance_release.contract.blob.signed_id]
keys = [dummy_appearance_release.contract.key]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: []
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
expect {
MatchAppearanceReleasesJob.perform_now project, signed_ids
}.to change{AppearanceRelease.count}.by(1)
expect(AppearanceRelease.last.contract).to be_attached
expect(AppearanceRelease.last.person_photo).not_to be_attached
end end
it "creates new incomplete appearance release if BrayniacAI returns single headshot match" do it "creates new incomplete appearance release if BrayniacAI returns single headshot match" do
@@ -84,6 +116,49 @@ describe MatchAppearanceReleasesJob do
expect(AppearanceRelease.last.contract).not_to be_attached expect(AppearanceRelease.last.contract).not_to be_attached
end end
it "creates new appearance releases for matches and unmatches at the same time" do
signed_ids = [dummy_appearance_release.contract.blob.signed_id, dummy_appearance_release.person_photo.blob.signed_id]
keys = [dummy_appearance_release.contract.key, dummy_appearance_release.person_photo.blob.key]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
mock_match = double(
headshots: [],
contracts: [keys.first],
unknowns: [],
identifier: 'some/identifier/123'
)
matches = [mock_match]
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: matches
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
expect {
MatchAppearanceReleasesJob.perform_now project, signed_ids
}.to change{AppearanceRelease.count}.by(2)
matched_release, unmatched_release = AppearanceRelease.last(2)
expect(matched_release.identifier).to eq mock_match.identifier
expect(matched_release.person_photo).not_to be_attached
expect(matched_release.contract).to be_attached
expect(unmatched_release.identifier).to be_nil
expect(unmatched_release.person_photo).to be_attached
expect(unmatched_release.contract).not_to be_attached
end
it "creates new incomplete appearance release if BrayniacAI returns single contract match" do it "creates new incomplete appearance release if BrayniacAI returns single contract match" do
signed_ids = [dummy_appearance_release.contract.blob.signed_id] signed_ids = [dummy_appearance_release.contract.blob.signed_id]
keys = [dummy_appearance_release.contract.key] keys = [dummy_appearance_release.contract.key]