Compare commits

...

13 Commits

Author SHA1 Message Date
Bilal
76940714b0 fix buttons position 2020-09-07 13:34:18 +03:00
Bilal
08a07c2a22 fix specs 2020-09-07 13:19:46 +03:00
Bilal
25fa534760 improve Download button for Talent releases 2020-09-07 13:07:27 +03:00
Bilal
c32e8f5109 improve Download button for Music releases 2020-09-07 13:03:01 +03:00
Bilal
f7c5bb7b0f improve Download button for Misc releases 2020-09-07 13:00:38 +03:00
Bilal
7d93d89e8e improve Download button for Medical releases 2020-09-07 12:54:00 +03:00
Bilal
4128d96941 improve Download button for Material releases 2020-09-07 12:47:31 +03:00
Bilal
1cf18e8f85 fix search match specs for generating contracts 2020-09-07 12:41:55 +03:00
Bilal
3694817fef improve Download button for Location releases 2020-09-07 12:15:09 +03:00
Bilal
a77cf9344c improve Download button for Acq.Media releases 2020-09-07 12:04:34 +03:00
Senad Uka
e5ac3e9345 Upstream sync 2020-09-06 21:42:50 +02: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
86 changed files with 986 additions and 499 deletions

View File

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

View File

@@ -1,8 +1,4 @@
$(document).on("click", "[data-behavior=play_recording]", function() {
if ($(this).hasClass('active')){
return false;
}
$("#broadcast_video").data('videoType', 'recording');
var playback_url = $(this).attr("data-playback-url")
@@ -16,13 +12,6 @@ $(document).on("click", "[data-behavior=play_recording]", function() {
height: '100%',
autoPlay: true
});
$(".dropdown-menu").children().removeClass('active');
$(".dropdown-menu").children().children('i').remove();
$(this).siblings().removeClass('active');
$(this).siblings().children("i").remove();
$(this).addClass('active');
$(this).prepend('<i class="fa fa-check">&nbsp;</i>');
});
$(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

@@ -45,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,

View File

@@ -4,6 +4,7 @@ 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

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

@@ -5,13 +5,25 @@ class BroadcastRecordingsController < ApplicationController
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)
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
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
@@ -23,4 +35,8 @@ class BroadcastRecordingsController < ApplicationController
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

@@ -32,6 +32,7 @@ class BroadcastsController < ApplicationController
@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
@@ -113,7 +114,7 @@ class BroadcastsController < ApplicationController
end
def conference_url_for(broadcast)
broadcast.video_conference_url_override || url_for([broadcast.project, broadcast, :zoom_meeting])
broadcast.video_conference_url_override.presence || url_for([broadcast.project, broadcast, :zoom_meeting])
end
def log_create_analytics

View File

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

View File

@@ -106,7 +106,7 @@ class MaterialReleasesController < ApplicationController
:term_id, :term_text,
:restriction_id, :restriction_text,
:description,
:contract, { photos: [] }
:contract, files: []
)
end

View File

@@ -4,4 +4,16 @@ class PagesController < ApplicationController
skip_after_action :verify_authorized
skip_after_action :verify_policy_scoped
skip_before_action :require_login
layout :layout_for_page
private
def layout_for_page
case params[:id]
when 'nanocosmos_player'
false
else
end
end
end

View File

@@ -44,7 +44,7 @@ class Public::BroadcastsController < Public::BaseController
end
def conference_url_for(broadcast)
broadcast.video_conference_url_override || broadcast_zoom_meeting_url(broadcast.token)
broadcast.video_conference_url_override.presence || broadcast_zoom_meeting_url(broadcast.token)
end
class MultiViewBroadcast

View File

@@ -92,7 +92,7 @@ class Public::MaterialReleasesController < Public::BaseController
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,
:signature_base64,
:locale, :contract_template, :description, photos: []
:locale, :contract_template, :description, files: []
)
end

View File

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

View File

@@ -7,13 +7,14 @@ class GenerateContractsZipJob < ApplicationJob
@project = job.arguments.first
@download = job.arguments.second
@release_type = job.arguments.third
@folder_name = "#{@project.name.parameterize}_#{get_release_name(@release_type).gsub('_', '-')}"
@release_ids = job.arguments.fourth
@search_query = job.arguments.fifth
@type_filter = job.arguments[5]
@folder_name = "#{@project.name.parameterize}_#{release_name.gsub('_', '-')}"
@download.update!(name: @folder_name, status: :pending)
end
def perform(project, download, release_type, release_ids)
releases = project.public_send(get_release_name(release_type)).where(id: release_ids)
def perform(project, download, release_type, release_ids, search_query, type_filter)
::ReleaseContractCollectionService.new(releases, @folder_name).build do |dir, files|
zipfile_name = "#{dir}/#{@folder_name}.zip"
Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
@@ -31,7 +32,7 @@ class GenerateContractsZipJob < ApplicationJob
end
rescue StandardError => e
Rails.logger.error("Failed to generate download for project (##{project.id}) with release type #{release_type}\n" + e.message)
@download.failure!
ProjectsChannel.broadcast_download_generation_update(@download, I18n.t("contract_downloads.download.failure"))
end
@@ -61,7 +62,32 @@ class GenerateContractsZipJob < ApplicationJob
end
end
def get_release_name(release_type)
release_type.constantize.model_name.plural
def release_name
@release_type.constantize.model_name.plural
end
def all_releases
@project.public_send(release_name)
end
def releases
if @release_ids.any?
return all_releases.where(id: @release_ids)
end
results = all_releases
if all_releases.respond_to?(:complete, :incomplete)
results = case @type_filter
when 'complete'
all_releases.complete
when 'incomplete'
all_releases.incomplete
else
all_releases
end
end
results = results.search(@search_query) if @search_query.present?
results
end
end

View File

@@ -15,7 +15,8 @@ class AcquiredMediaRelease < ApplicationRecord
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
include FilesFilterable
class << self
def custom_csv_exportable_headers
%i[name files_count owner_info]
@@ -106,16 +107,4 @@ class AcquiredMediaRelease < ApplicationRecord
def files_count
files.any? ? files.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
end
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

View File

@@ -7,8 +7,10 @@ class BroadcastRecording < ApplicationRecord
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
@@ -16,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,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

@@ -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
@@ -16,11 +16,11 @@ class MaterialRelease < ApplicationRecord
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
include FilesFilterable
class << self
def custom_csv_exportable_headers
%i[name owner_info]
%i[name owner_info files_count]
end
end
@@ -56,6 +56,8 @@ class MaterialRelease < ApplicationRecord
%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
@@ -92,4 +94,8 @@ class MaterialRelease < ApplicationRecord
def uses_edl?
true
end
def files_count
files.any? ? files.size : I18n.t('material_releases.material_release.no_media')
end
end

View File

@@ -1,9 +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?
true
end
def update?
true
end
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
@@ -17,4 +17,14 @@ class SerializableAcquiredMediaRelease < JSONAPI::Serializable::Resource
{ count: @object.file_infos.size }
end
end
has_many :files do
data do
@object.files
end
meta do
{ count: @object.files.size }
end
end
end

View File

@@ -1,5 +1,9 @@
class SerializableUser < JSONAPI::Serializable::Resource
type "user"
attributes :email
attributes :email, :full_name
attribute :company_name do
@object.primary_account.name
end
end

View File

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

View File

@@ -1,16 +1,19 @@
<div class="row">
<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">
<% 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 %>
<% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %>
<% end %>
<% 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..." } %>
<% end %>

View File

@@ -1,3 +1,5 @@
$("#acquired_media_releases").html("<%= j render(@acquired_media_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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

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

View File

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

View File

@@ -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

@@ -1,6 +1 @@
var dom_id = "<%= dom_id(@recording) %>"
$('[data-id="' + dom_id + '"]').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 }) %>");
<%= 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

@@ -1,3 +1 @@
<%= link_to broadcast_recording.download_file_name, "javascript:void(0);", class: "dropdown-item", data: { behavior: "play_recording", playback_url: broadcast_recording.playback_url, id: dom_id(broadcast_recording) } %>
<%= 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,18 +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") %>
<% if (controller.class.module_parent.to_s != "Public" && policy(BroadcastRecording).destroy?) %>
<%= link_to "Hide", [broadcast.project, broadcast, recording], class: "btn-sm btn-primary ml-1 text-decoration-none", remote: true, method: :delete, data: { confirm: t('.confirm_hide') } %>
<% end %>
</li>
<div class="list-group-item list-group-item-action">
<div class="d-flex align-items-start">
<% if 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', data: { behavior: "play_recording", playback_url: recording.playback_url, id: dom_id(recording) }) %>
<div class="ml-auto">
<% if 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

@@ -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>

View File

@@ -9,7 +9,7 @@
<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>

View File

@@ -14,159 +14,155 @@
<% 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">
<% if @multi_view_broadcasts.present? %>
<%= 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 %>
<% else %>
<%= link_to "javascript:void(0);", class: "btn btn-light text-white bg-black border-0 override-dropdown-show-state", role: "button", id: "dropdownMenuLink", 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 %>
<% end %>
<div class="dropdown-menu bg-black" aria-labelledby="dropdownMenuLink">
<%= 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 %>
<% if @broadcast.director_mode_video_embed.present? %>
<h5 class="dropdown-header">Director Mode</h5>
<% unless params[:director_mode] %>
<%= link_to "Enable Director Mode", url_for(params.permit!.merge(director_mode: true)), class: "dropdown-item" %>
<% else %>
<%= link_to "Disable Director Mode", url_for(params.permit!.except(:director_mode)), class: "dropdown-item" %>
<% 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>
<% 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">
<%= 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

@@ -52,7 +52,7 @@
</div>
<% end %>
<% if releasable.class == AcquiredMediaRelease %>
<% if releasable.respond_to?(:image_files) %>
<div class="page">
<%= render "contracts/files", release: releasable, preview: preview %>
</div>

View File

@@ -1,8 +1,11 @@
<div class="row">
<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">
<% 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 %>
<% if @location_releases.any? && policy(LocationRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %>
<% 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..." } %>
<% end %>

View File

@@ -1,3 +1,5 @@
$("#location_releases").html("<%= j render(@location_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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

@@ -57,8 +57,8 @@
<hr>
<%= field_set_tag content_tag(:span, t(".photos.heading"), class: "h6 text-muted text-uppercase") do %>
<%= render "shared/photos_dropzone_fields", form: form, release: material_release %>
<%= field_set_tag content_tag(:span, t(".files.heading"), class: "h6 text-muted text-uppercase") do %>
<%= render "shared/releasable_files_dropzone", form: form, releasable: material_release %>
<div class="<%= class_string("collapse" => !material_release.minor?) %>" data-ujs-target="guardian-fields">
<br>

View File

@@ -9,10 +9,10 @@
<% end %>
</td>
<td>
<% if material_release.photo.attached? %>
<%= image_tag medium_variant(material_release.photo), class: "img-fluid" %>
<% if material_release.files.any? %>
<%= material_release.files.size %>
<% else %>
<%= fa_icon("warning", text: t(".no_photos"), class: "text-danger") %>
<%= fa_icon("warning", text: t(".no_media"), class: "text-danger") %>
<% end %>
</td>
<td>
@@ -41,8 +41,8 @@
<% if policy(material_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, material_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %>
<% if policy(material_release).edit_photos? %>
<%= link_to fa_icon("picture-o fw", text: "Photos"), [:edit, material_release, :photos], class: "dropdown-item" %>
<% if policy(material_release).edit_files? %>
<%= link_to fa_icon("file-o fw", text: "Add Media"), [:edit, material_release, :files], class: "dropdown-item" %>
<% end %>
<% 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" %>

View File

@@ -1,8 +1,11 @@
<div class="row">
<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">
<% 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 %>
<% if @material_releases.any? && policy(MaterialRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %>
<% 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..." } %>
<% end %>
@@ -27,7 +30,7 @@
<tr>
<th data-behavior="all-selectable"><%= check_box_tag "material_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></th>
<th></th>
<th><%= t(".table_headers.files_count") %></th>
<th><%= MaterialRelease.human_attribute_name(:name) %></th>
<th><%= t(".table_headers.owner_info") %>
<th><%= t(".table_headers.notes") %></th>

View File

@@ -1,3 +1,5 @@
$("#material_releases").html("<%= j render(@material_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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="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">
<% if @medical_releases.any? && policy(MedicalRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %>
<div class="ml-auto">
<%= button_to_bulk_tagging(@project) %>
</div>
<% end %>
<% 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..." } %>
<% end %>

View File

@@ -1,3 +1,5 @@
$("#medical_releases").html("<%= j render(@medical_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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="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">
<% if @misc_releases.any? && policy(MiscRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %>
<div class="ml-auto">
<%= button_to_bulk_tagging(@project) %>
</div>
<% end %>
<% 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..." } %>
<% end %>

View File

@@ -1,3 +1,5 @@
$("#misc_releases").html("<%= j render(@misc_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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="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">
<% 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 %>
<% if @music_releases.any? && policy(MusicRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %>
<% 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 %>
<%= 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) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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

@@ -0,0 +1,45 @@
<div>
<div id="playerDiv"></div>
<script type="text/javascript" src="https://demo.nanocosmos.de/nanoplayer/api/release/nanoplayer.4.min.js"></script>
<%= javascript_tag nonce: true do %>
var urlParams = new URLSearchParams(window.location.search);
var streamName = urlParams.get('stream_name');
console.log("streamName", streamName);
var player;
var config = {
"source": {
"entries": [
{
"h5live": {
// your rtmp stream
"rtmp": {
"url": "rtmp://bintu-play.nanocosmos.de/play",
"streamname": streamName,
},
"server": {
"websocket": "wss://bintu-h5live.nanocosmos.de:443/h5live/stream.mp4",
"hls": "https://bintu-h5live.nanocosmos.de:443/h5live/http/playlist.m3u8",
"progressive": "https://bintu-h5live.nanocosmos.de:443/h5live/http/stream.mp4"
}
}
}
]
},
"style": {
"width": "auto",
}
};
function initPlayer() {
player = new NanoPlayer('playerDiv');
player.setup(config).then(function (config) {
console.log('setup ok with config: ' + JSON.stringify(config));
}, function (error) {
console.log(error);
});
}
// load player from playerDiv
document.addEventListener('DOMContentLoaded', function () {
initPlayer();
});
<% end %>
</div>

View File

@@ -45,8 +45,8 @@
<%= render "shared/address_fields", form: form, subject: "person", required: true %>
<% end %>
<%= card_field_set_tag t(".photo.heading") do %>
<%= render "shared/photos_dropzone_fields", form: form, release: @material_release %>
<%= card_field_set_tag t(".files.heading") do %>
<%= render "shared/releasable_files_dropzone", form: form, releasable: @material_release %>
<% end %>
<hr>

View File

@@ -1,8 +1,11 @@
<div class="row">
<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">
<% 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 %>
<% if @talent_releases.any? && policy(TalentRelease).tag_multiple? %>
@@ -10,7 +13,7 @@
<% end %>
<% 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..." } %>
<% end %>

View File

@@ -1,3 +1,5 @@
$("#talent_releases").html("<%= j render(@talent_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#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

@@ -9,12 +9,12 @@ Rails.application.config.content_security_policy do |policy|
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data
policy.object_src :self
policy.script_src :self, :https, AppHost.new.domain_with_port, "https://stream.mux.com", :blob, :unsafe_eval
policy.script_src :self, :https, AppHost.new.domain_with_port, "https://stream.mux.com", "https://demo.nanocosmos.de", :blob, :unsafe_eval
policy.media_src :self, :https, AppHost.new.domain_with_port, "https://stream.mux.com", :data, :blob
# policy.style_src :self, :https, :unsafe_inline
# If you are using webpack-dev-server then specify webpack-dev-server host
# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
policy.connect_src :self, :https, "ws://#{AppHost.new.domain_with_port}", "wss://#{AppHost.new.domain_with_port}"
policy.connect_src :self, :https, "ws://#{AppHost.new.domain_with_port}", "wss://#{AppHost.new.domain_with_port}", "wss://bintu-h5live.nanocosmos.de"
# Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint"

View File

@@ -0,0 +1 @@
Rails.application.config.session_store :cookie_store, key: '_easy_release_session', expire_after: 1.month

View File

@@ -224,6 +224,9 @@ en:
manage: Manage
empty_bookmarks:
empty: Notes will appear here
broadcast_recordings:
edit:
heading: Edit Broadcast Recording
broadcasts:
broadcast:
actions:
@@ -901,6 +904,8 @@ en:
form:
contract_and_rights:
heading: 3 of 4 Contract & Exploitable Rights
files:
heading: Files
guardian_2_info:
heading: Second Guardian Information (if company requires)
guardian_info:
@@ -908,7 +913,7 @@ en:
material_details:
heading: 1 of 3 Material Details
photos:
dropzone_label: Tap to take a photo of Licensed Material (optional)
dropzone_label: "To Add Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
guardian_2_photo:
heading: Second Guardian Photo
guardian_photo:
@@ -923,6 +928,7 @@ en:
empty: Material Releases will appear here
table_headers:
approved: Approved
files_count: No. of Files
name: Name
notes: Notes
owner_info: Owner Info
@@ -934,6 +940,7 @@ en:
review: Review
messages:
approved_tooltip: Approved by %{user} on %{timestamp}
no_media: No Media
no_photos: Needs Photo
new:
heading: Import Material Release (Products / Logos)
@@ -1252,6 +1259,8 @@ en:
cancel: Cancel
contact_info:
heading: Licensor/Owner Contact Information
files:
heading: Files
guardian_2_info:
heading: Second Guardian Information (if company requires)
guardian_2_photo:

View File

@@ -55,7 +55,7 @@ Rails.application.routes.draw do
resources :appearance_releases, except: [:show], concerns: [:contractable, :notable]
resources :appearance_release_imports, only: [:create]
resources :location_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :material_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :material_releases, except: [:show], concerns: [:contractable, :notable, :file_uploadable]
resources :music_releases, except: [:show], concerns: [:contractable, :notable]
resources :talent_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :medical_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
@@ -101,7 +101,9 @@ Rails.application.routes.draw do
delete :destroy_file
end
resource :zoom_meeting, only: [:show]
resources :broadcast_recordings, only: :destroy
resources :broadcast_recordings, only: [:destroy, :edit, :update] do
resources :broadcast_recording_starrings, only: :create
end
end
resources :directories, except: [:index] do
member do
@@ -198,6 +200,7 @@ Rails.application.routes.draw do
get "cookies_disabled" => 'pages#show', id: "cookies_disabled", as: :cookies_disabled
get "accountless_user" => 'pages#show', id: "accountless_user", as: :accountless_user
get "nanocosmos_player" => 'pages#show', id: "nanocosmos_player", as: :nanocosmos_player
resource :session, only: [:new, :create]
resources :password_resets, only: [:new, :create, :edit, :update]

View File

@@ -0,0 +1,9 @@
class MigrateMaterialPhotosToFiles < ActiveRecord::DataMigration
def up
photos = ActiveStorage::Attachment.where(name: "photos", record_type: "MaterialRelease")
photos.each do |photo|
photo.update(name: "files")
end
end
end

View File

@@ -0,0 +1,6 @@
class AddNameAndDescriptionToBroadcastRecordings < ActiveRecord::Migration[6.0]
def change
add_column :broadcast_recordings, :name, :string
add_column :broadcast_recordings, :description, :text
end
end

View File

@@ -0,0 +1,5 @@
class AddStarToBroadcastRecordings < ActiveRecord::Migration[6.0]
def change
add_column :broadcast_recordings, :starred, :boolean, default: false
end
end

View File

@@ -9,20 +9,6 @@ SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--
-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: -
--
@@ -555,7 +541,10 @@ CREATE TABLE public.broadcast_recordings (
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
duration double precision,
hidden boolean DEFAULT false
hidden boolean DEFAULT false,
starred boolean DEFAULT false,
name character varying,
description text
);
@@ -4036,6 +4025,8 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200807190607'),
('20200811102720'),
('20200812060406'),
('20200819070738');
('20200819070738'),
('20200820082501'),
('20200824171649');

View File

@@ -17,6 +17,7 @@ RSpec.describe BroadcastsChannel, type: :channel do
it "broadcasts to the channel" do
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 }
expect {
BroadcastsChannel.broadcast_stream_updates(broadcast)
@@ -27,6 +28,7 @@ RSpec.describe BroadcastsChannel, type: :channel do
full_live_stream_playback_url: broadcast.full_live_stream_playback_url,
status_content: status_content,
video_content: video_content,
live_take_content: live_take,
streamer_status: broadcast.streamer_status
})
end

View File

@@ -30,6 +30,16 @@ RSpec.describe Api::AcquiredMediaReleasesController, type: :controller do
expect(response).to be_successful
end
it 'contains files attachment data' do
tested_release = create(:acquired_media_release, name: 'ct1', project_id: project.id)
sign_in_to_api(current_user)
get :show, params: { id: tested_release.id }
expect(response.body).to match /file_infos/
expect(response.body).to match /files/
end
end
describe '#create' do

View File

@@ -14,6 +14,8 @@ RSpec.describe Api::ProfilesController, type: :controller do
expect(response).to be_successful
expect(response_body_data).to include('id' => current_user.to_param, 'type' => 'user')
expect(response_body_data_attributes).to include('email' => current_user.email)
expect(response_body_data_attributes).to include('full_name' => current_user.full_name)
expect(response_body_data_attributes).to include('company_name' => current_user.primary_account.name)
end
end

View File

@@ -0,0 +1,48 @@
require 'rails_helper'
RSpec.describe BroadcastRecordingStarringsController, type: :controller do
render_views
let(:user) { create(:user) }
let(:account) { user.primary_account }
let(:project) { create(:project, account: user.primary_account) }
before do
sign_in user
stub_mux_live_stream
end
describe "#create" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recordings) { create_list(:broadcast_recording, 5, :with_random_asset_uid, broadcast: broadcast) }
let(:starred_recordings) { create_list(:broadcast_recording, 5, :with_random_asset_uid, broadcast: broadcast, starred: true) }
it "sets star property to true when recording is starred" do
recordings.each do |recording|
expect(recording.starred).to be_falsey
end
post :create, params: { project_id: project, broadcast_id: broadcast, broadcast_recording_id: recordings.first.id }, xhr: true
expect(recordings.first.reload.starred).to eq true
recordings[1..5].each do |recording|
expect(recording.reload.starred).to be_falsey
end
end
it "sets star property to false when recording is unstarred" do
starred_recordings.each do |recording|
expect(recording.starred).to be_truthy
end
post :create, params: { project_id: project, broadcast_id: broadcast, broadcast_recording_id: starred_recordings.first.id }, xhr: true
expect(starred_recordings.first.reload.starred).to eq false
starred_recordings[1..5].each do |recording|
expect(recording.reload.starred).to eq true
end
end
end
end

View File

@@ -9,9 +9,10 @@ RSpec.describe BroadcastRecordingsController, type: :controller do
before do
sign_in user
stub_mux_live_stream
end
describe "#destroy" do
describe "#edit" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recording) { create(:broadcast_recording, broadcast: broadcast) }
@@ -19,6 +20,55 @@ RSpec.describe BroadcastRecordingsController, type: :controller do
stub_mux_live_stream
end
it "assigns project, broadcast, broadcast recording" do
get :edit, params: { project_id: project, broadcast_id: broadcast, id: recording }, xhr: true
expect(assigns(:project)).to have_attributes({
id: project.id,
name: project.name,
account_id: project.account_id
})
expect(assigns(:broadcast)).to have_attributes({
id: broadcast.id,
name: broadcast.name,
project_id: project.id
})
expect(assigns(:recording)).to have_attributes({
id: recording.id,
broadcast_id: broadcast.id,
file_name: "high.mp4"
})
end
end
describe "#update" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recording) { create(:broadcast_recording, broadcast: broadcast) }
let(:recordings) { create_list(:broadcast_recording, 5, :with_random_asset_uid, broadcast: broadcast) }
let(:starred_recordings) { create_list(:broadcast_recording, 5, :with_random_asset_uid, broadcast: broadcast, starred: true) }
before do
stub_mux_live_stream
end
it "updates the recording's name and description" do
expect(recording.name).to eq(recording.download_file_name)
expect(recording.description).to eq("No description provided for this recording.")
patch :update, params: { project_id: project, broadcast_id: broadcast, id: recording, broadcast_recording: { name: "Just for fun", description: "I had fun while making this stream." } }, xhr: true
recording.reload
expect(recording.name).to eq("Just for fun")
expect(recording.description).to eq("I had fun while making this stream.")
end
end
describe "#destroy" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recording) { create(:broadcast_recording, broadcast: broadcast) }
it "hides the broadcast recording" do
expect(recording.hidden).to be false

View File

@@ -150,13 +150,6 @@ RSpec.describe BroadcastsController, type: :controller do
expect(assigns(:broadcast)).to eq(broadcast)
end
it "renders readonly share url" do
get :show, params: { project_id: project.id, id: broadcast.id }
expect(response.body).to have_button "Copy URL"
expect(response.body).to have_xpath "//input[@readonly][@value='#{broadcast_url(broadcast.token)}']"
end
it "displays zoom meeting button" do
get :show, params: { project_id: project.id, id: broadcast.id }
@@ -174,7 +167,7 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with just the current broadcast" do
get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Another Broadcast")
end
end
@@ -185,32 +178,12 @@ RSpec.describe BroadcastsController, type: :controller do
get :show, params: { project_id: project, id: broadcast, multi_view_ids: [broadcast.id, other_broadcast.id] }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Another Broadcast")
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Some Other Broadcast")
end
end
context "when there are no recordings for the current broadcast" do
it "renders the view dropdown with a message" do
get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item", text: "Recordings will appear here")
end
end
context "when there are recordings available" do
it "renders the view dropdown with the recordings" do
recording = create(:broadcast_recording, broadcast: broadcast)
get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: recording.download_file_name)
end
end
context "when virtual director video embed is available" do
let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast",
director_mode_video_embed: "<iframe>video player</iframe>") }
@@ -218,9 +191,8 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with a director mode enable option" do
get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu h5.dropdown-header", text: "Director Mode")
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Enable Director Mode")
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".custom-control-label", text: "Director Mode")
end
context "when director mode is enabled" do
@@ -233,9 +205,8 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with a director mode disable option" do
get :show, params: { project_id: project, id: broadcast, director_mode: true }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu h5.dropdown-header", text: "Director Mode")
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Disable Director Mode")
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".custom-control-label", text: "Director Mode")
end
end
end

View File

@@ -68,13 +68,7 @@ RSpec.describe PhotosController, type: :controller do
it_behaves_like "a photoable releases controller"
end
context "for material releases" do
subject { create(:material_release, project: project) }
it_behaves_like "a photoable releases controller"
end
private
def release_params

View File

@@ -45,7 +45,7 @@ RSpec.describe Public::BroadcastsController, type: :controller do
it "renders the view dropdown with just the current broadcast" do
get :show, params: { token: broadcast.token }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Broadcast")
end
end
@@ -56,7 +56,7 @@ RSpec.describe Public::BroadcastsController, type: :controller do
get :show, params: { token: broadcast.token, multi_view_tokens: [broadcast.token, other_broadcast.token] }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_content broadcast.name
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Broadcast")
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Some Other Broadcast")
end
@@ -66,8 +66,7 @@ RSpec.describe Public::BroadcastsController, type: :controller do
it "renders the view dropdown with a message" do
get :show, params: { token: broadcast.token }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item", text: "Recordings will appear here")
expect(response.body).to have_content broadcast.name
end
end
@@ -77,8 +76,7 @@ RSpec.describe Public::BroadcastsController, type: :controller do
get :show, params: { token: broadcast.token }
expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: recording.download_file_name)
expect(response.body).to have_content broadcast.name
end
end

View File

@@ -10,10 +10,10 @@ describe Public::MaterialReleasesController do
it "allows photos param" do
contract_template = create(:contract_template, project: project)
post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, material_release: material_release_params_with_photos }
post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, material_release: material_release_params_with_files }
expect(response).to be_successful
expect(MaterialRelease.last.photos.attached?).to eq true
expect(MaterialRelease.last.files.attached?).to eq true
end
it "displays validation errors" do
@@ -63,8 +63,8 @@ describe Public::MaterialReleasesController do
attributes_for(:material_release, :native).except(:signature).merge(signature_param)
end
def material_release_params_with_photos
attributes_for(:material_release, :native, :with_photo).except(:signature).merge(signature_param)
def material_release_params_with_files
attributes_for(:material_release, :native, :with_file).except(:signature).merge(signature_param)
end

View File

@@ -5,5 +5,9 @@ FactoryBot.define do
asset_uid "asset_uid"
asset_playback_uid "asset_playback_uid"
hidden { false }
trait :with_random_asset_uid do
sequence(:asset_uid, 'a')
end
end
end

View File

@@ -42,6 +42,12 @@ FactoryBot.define do
end
end
trait :with_file do
files do
path = Rails.root.join("spec", "fixtures", "files", "material_photo.png")
[Rack::Test::UploadedFile.new(path, "image/png")]
end
end
trait :non_native do
contract do

View File

@@ -56,14 +56,32 @@ feature 'User managing broadcasts' do
visit project_broadcast_path(project, broadcast)
expect(page).to have_content('Live stream is waiting to begin.')
expect(page).to have_content('Copy URL')
expect(page).to have_content('Share URL')
within '#files' do
expect(page).to have_content('contract.pdf')
click_on "Files"
expect(page).to have_content('contract.pdf')
click_on 'Takes'
expect(page).to have_content(recording.name)
end
context 'visit show page of active broadcast' do
scenario 'loads full live stream playback url if available' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project, streamer_status: :recording, status: :active)
visit project_broadcast_path(project, broadcast)
expect(page.body).not_to match broadcast.stream_playback_url
expect(page.body).to match broadcast.full_live_stream_playback_url
end
click_on 'Previous Sessions'
expect(page).to have_content(recording.download_file_name)
scenario 'loads full broadcast asset url if available' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project, streamer_status: :recording, status: :active, full_live_stream_playback_uid: '')
visit project_broadcast_path(project, broadcast)
expect(page.body).to match broadcast.stream_playback_url
end
end
scenario 'Clicking Reset URL regenerates broadcast token' do
@@ -73,93 +91,19 @@ feature 'User managing broadcasts' do
visit project_broadcast_path(project, broadcast)
expect(page).to have_content reset_url
expect(page).to have_xpath "//input[@readonly][@value='#{broadcast_url(old_token)}']"
click_link reset_url
expect(Broadcast.last.token).not_to eq old_token
expect(page).to have_xpath "//input[@readonly][@value='#{broadcast_url(Broadcast.last.token)}']"
expect(page).to have_content token_reset_notice
end
scenario 'Player will not reload if stream is reactivated while user is watching previous recording', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast)
visit project_broadcast_path(project, broadcast)
expect(page).to have_content stream_idle_message
broadcast.streamer_status = :recording
broadcast.status = :active
BroadcastsChannel.broadcast_stream_updates(broadcast)
expect(page).to have_content stream_begun_message
expect(page).to have_selector('div#broadcast_video', count: 2)
broadcast.streamer_status = :idle
broadcast.status = :idle
BroadcastsChannel.broadcast_stream_updates(broadcast)
click_on switch_view_dropdown
click_on recording.download_file_name
expect(page).to have_content stream_idle_message
expect(page).to have_selector('div#broadcast_video', count: 1)
broadcast.streamer_status = :recording
broadcast.status = :active
BroadcastsChannel.broadcast_stream_updates(broadcast)
expect(page).to have_content stream_begun_message
expect(page).to have_selector('div#broadcast_video', count: 1)
end
scenario 'user can go back and forth between live session and previous sessions', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast)
visit project_broadcast_path(project, broadcast)
expect(page).to have_content broadcast.name.titleize, count: 1
expect(page).to have_content recording.download_file_name, count: 0
click_on switch_view_dropdown
expect(page).to have_content broadcast.name.titleize, count: 2
expect(page).to have_content recording.download_file_name, count: 1
live_stream_nav_item = page.find('.dropdown-item', text: broadcast.name.titleize)
recording_nav_item = page.find('.dropdown-item', text: recording.download_file_name)
expect(live_stream_nav_item[:class].include?('active')).to eq true
expect(recording_nav_item[:class].include?('active')).to eq false
click_on recording.download_file_name
expect(page).to have_content broadcast.name.titleize, count: 1
expect(page).to have_content recording.download_file_name, count: 0
expect(live_stream_nav_item[:class].include?('active')).to eq false
expect(recording_nav_item[:class].include?('active')).to eq true
click_on switch_view_dropdown
click_on broadcast.name.titleize
expect(page).to have_content broadcast.name.titleize, count: 1
expect(page).to have_content recording.download_file_name, count: 0
# Page is reloaded, we need to get dropdown items again
live_stream_nav_item = page.find('.dropdown-item', text: broadcast.name.titleize, visible: :all)
recording_nav_item = page.find('.dropdown-item', text: recording.download_file_name, visible: :all)
expect(live_stream_nav_item[:class].include?('active')).to eq true
expect(recording_nav_item[:class].include?('active')).to eq false
end
scenario 'form will not submit if user clicks Add files without selected files', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast)
expect(page).to have_content('Live stream is waiting to begin.')
click_on "Files"
expect(page).to have_content add_file_button
click_on add_file_button
@@ -169,7 +113,7 @@ feature 'User managing broadcasts' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast)
click_on "Files"
expect(page).to have_content delete_file_button, count: 3
accept_alert do
@@ -189,9 +133,11 @@ feature 'User managing broadcasts' do
new_window = window_opened_by { click_link 'Multi-View' }
within_window new_window do
expect(page).to have_content switch_view_dropdown
click_on switch_view_dropdown
click_on "Files"
expect(page).to have_content broadcast_one.name
expect(page).to have_content broadcast_two.name
click_on broadcast_one.name
expect(page).to have_link('Broadcast 1')
expect(page).to have_link('Broadcast 2')
@@ -205,24 +151,6 @@ feature 'User managing broadcasts' do
end
end
scenario 'project manager can hide broadcast recordings', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast, asset_uid: "another_asset_uid")
visit project_broadcast_path(project, broadcast)
click_on 'Previous Sessions'
expect(page).to have_content(recording.download_file_name)
expect(page).to have_content('Hide')
accept_alert do
click_link "Hide"
end
expect(page).not_to have_content(recording.download_file_name)
expect(page).to have_content("Recording of the live stream will appear here")
end
context 'When the user is associate' do
let(:current_user) { create(:user, :associate) }
@@ -240,17 +168,6 @@ feature 'User managing broadcasts' do
expect(page).to have_content delete_file_button, count: 0
end
scenario 'associate does not see hide button in front of recording' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast, asset_uid: "another_asset_uid")
visit project_broadcast_path(project, broadcast)
click_on 'Previous Sessions'
expect(page).to have_content(recording.download_file_name)
expect(page).not_to have_content('Hide')
end
end
context 'When the user is account manager' do
@@ -267,7 +184,7 @@ feature 'User managing broadcasts' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast)
click_on "Files"
expect(page).to have_content delete_file_button, count: 3
accept_alert do
@@ -277,26 +194,7 @@ feature 'User managing broadcasts' do
expect(page).to have_content delete_file_button, count: 2
expect(Broadcast.find(broadcast.id).files.count).to eq 2
end
scenario 'account manager can hide broadcast recordings', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast, asset_uid: "another_asset_uid")
visit project_broadcast_path(project, broadcast)
click_on 'Previous Sessions'
expect(page).to have_content(recording.download_file_name)
expect(page).to have_content('Hide')
accept_alert do
click_link "Hide"
end
expect(page).not_to have_content(recording.download_file_name)
expect(page).to have_content("Recording of the live stream will appear here")
end
end
end
private
@@ -320,10 +218,6 @@ feature 'User managing broadcasts' do
all('input[type="checkbox"]')[1].click
end
def switch_view_dropdown
'Switch View'
end
def schedule_demo
t 'broadcasts.splash.actions.book_demo'
end

View File

@@ -37,7 +37,7 @@ feature "User managing material releases" do
click_button submit_release_button
expect(page).to have_content success_submit_message
expect(MaterialRelease.last.photos.attached?).to eq true
expect(MaterialRelease.last.files.attached?).to eq true
end
scenario "creating a release for a minor - guardian fields are required when minor checkbox is checked", js: true do
@@ -225,7 +225,7 @@ feature "User managing material releases" do
click_button create_release_button
expect(page).to have_content(create_release_notice)
expect(page).to have_photo("material_photo.png", visible: :all)
expect(page).to have_content("1")
click_on "Manage"
expect(page).to have_link("Download")
@@ -364,19 +364,19 @@ feature "User managing material releases" do
visit project_material_releases_path(project)
expect(page).to have_content("Needs Photo")
expect(page).to have_content("No Media")
click_on "Manage"
click_on "Photos"
click_on "Add Media"
expect(page).to have_content("Add Photos")
expect(page).to have_content("Add Files")
expect(page).to have_content("Apple MacBook Air")
drop_file Rails.root.join(file_fixture("material_photo.png")), type: :dropzone
click_on "Save Changes"
expect(page).to have_content("The release has been updated")
expect(page).to have_photo("material_photo.png", visible: :all)
expect(page).to have_content("Files added successfully to the release")
expect(page).to have_content("1")
end
scenario "viewing the contract PDF" do

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)
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, :non_native, project: project)
visit project_medical_releases_path(project)
expect(page).to have_content download_all_button
expect(page).to have_content download_button
end
scenario "Download action in Manage menu is visible" do
@@ -264,7 +264,7 @@ feature "User managing medical releases" do
visit project_medical_releases_path(project)
expect(page).not_to have_content download_all_button
expect(page).not_to have_content download_button
end
scenario "Download action in Manage menu is not visible" do
@@ -308,7 +308,7 @@ feature "User managing medical releases" do
visit project_medical_releases_path(project)
expect(page).not_to have_content download_all_button
expect(page).not_to have_content download_button
end
scenario "Download action in Manage menu is not visible" do
@@ -341,8 +341,8 @@ feature "User managing medical releases" do
private
def download_all_button
'Download All'
def download_button
'Download'
end
def download_action

View File

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

View File

@@ -19,7 +19,7 @@ describe GenerateContractsZipJob do
describe ".perform_later" do
it "enqueues a background job for generating zip file" do
expect {
GenerateContractsZipJob.perform_later(project, download, "AppearanceRelease", project.appearance_releases.ids)
GenerateContractsZipJob.perform_later(project, download, "AppearanceRelease", project.appearance_releases.ids, '', '')
}.to have_enqueued_job
end
end
@@ -28,7 +28,7 @@ describe GenerateContractsZipJob do
shared_examples "generates ZIP containig CSV file with all releases data" do
it "generates ZIP containing CSV file with all releases data for all release types" do
lowercase_plural = subject.constantize.model_name.plural
GenerateContractsZipJob.perform_now(project, download, subject, project.public_send(lowercase_plural).ids)
GenerateContractsZipJob.perform_now(project, download, subject, project.public_send(lowercase_plural).ids, '', '')
generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
@@ -50,8 +50,113 @@ describe GenerateContractsZipJob do
end
end
shared_examples "generates ZIP containig CSV file with specific releases data" do
it "generates ZIP containing CSV file with all selected releases data for selected releases" do
lowercase_plural = subject.constantize.model_name.plural
all_releases = project.public_send(lowercase_plural)
included_releases = all_releases.where(id: all_releases.ids[0..1])
not_included_releases = all_releases.where.not(id: all_releases.ids[0..1])
GenerateContractsZipJob.perform_now(project, download, subject, included_releases.ids, '', '')
generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
Zip::InputStream.open(StringIO.new(generated_zip)) do |io|
while entry = io.get_next_entry
next unless entry.name == csv_file_name
csv_file = entry.get_input_stream.read
release_class = Object.const_get subject
release_headers = release_class.csv_headers
release_headers.each do |header|
expect(csv_file).to match header
expect(csv_file).not_to match translation_missing
end
included_releases.each do |release|
expect(csv_file).to match release.person_first_name
end
not_included_releases.each do |release|
expect(csv_file).not_to match release.person_first_name
end
end
end
end
it "generates ZIP containing CSV file with all filtered releases data for filtered releases" do
if subject.respond_to?(:complete) && subject.respond_to?(:incomplete)
lowercase_plural = subject.constantize.model_name.plural
GenerateContractsZipJob.perform_now(project, download, subject, [], '', 'complete')
complete_releases = project.public_send(lowercase_plural).complete
incomplete_releases = project.public_send(lowercase_plural).incomplete
generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
Zip::InputStream.open(StringIO.new(generated_zip)) do |io|
while entry = io.get_next_entry
next unless entry.name == csv_file_name
csv_file = entry.get_input_stream.read
release_class = Object.const_get subject
release_headers = release_class.csv_headers
release_headers.each do |header|
expect(csv_file).to match header
expect(csv_file).not_to match translation_missing
end
complete_releases.each do |release|
expect(csv_file).to match release.person_first_name
end
incomplete_releases.each do |release|
expect(csv_file).not_to match release.person_first_name
end
end
end
end
end
it "generates ZIP containing CSV file with all search query matching releases" do
lowercase_plural = subject.constantize.model_name.plural
matched_releases = project.public_send(lowercase_plural).search('Brad')
not_matched_releases = project.public_send(lowercase_plural).where.not(id: matched_releases.ids)
GenerateContractsZipJob.perform_now(project, download, subject, [], 'Brad', '')
generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
Zip::InputStream.open(StringIO.new(generated_zip)) do |io|
while entry = io.get_next_entry
next unless entry.name == csv_file_name
csv_file = entry.get_input_stream.read
release_class = Object.const_get subject
release_headers = release_class.csv_headers
release_headers.each do |header|
expect(csv_file).to match header
expect(csv_file).not_to match translation_missing
end
matched_releases.each do |release|
expect(csv_file).to match release.person_first_name
end
not_matched_releases.each do |release|
expect(csv_file).not_to match release.person_first_name
end
end
end
end
end
it "updates a download record and creates attachment for it" do
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids, '', '')
expect(download.project).to eq project
expect(download.release_type).to eq "AppearanceRelease"
@@ -61,59 +166,83 @@ describe GenerateContractsZipJob do
end
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' }
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
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") }
let(:complete_release) { create(:appearance_release_with_contract_template, :non_native, project: project, person_name: "Brad") }
subject { 'AppearanceRelease' }
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
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' }
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
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' }
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
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' }
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
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' }
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
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' }
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
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' }
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
context "When there are errors" do
@@ -125,7 +254,7 @@ describe GenerateContractsZipJob do
end
it "updates status to 'failure' and sends user a notification" do
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids, '', '')
expect(download.status).to eq "failure"
expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))

View File

@@ -6,7 +6,8 @@ RSpec.describe BroadcastRecording, type: :model do
end
describe "validations" do
subject { described_class.new(asset_uid: "asset_uid", asset_playback_uid: "playback_uid", file_name: "medium.mp4") }
let(:broadcast) { create(:broadcast, :with_stream, skip_create_callback: true, name: "My Broadcast") }
subject { described_class.new(asset_uid: "asset_uid", asset_playback_uid: "playback_uid", file_name: "medium.mp4", broadcast: broadcast) }
it { is_expected.to validate_uniqueness_of(:asset_uid) }
end
@@ -24,16 +25,20 @@ RSpec.describe BroadcastRecording, type: :model do
let(:broadcast_recording) { create(:broadcast_recording, broadcast: broadcast) }
it "should have a download url" do
download_file_name = broadcast_recording.send(:download_file_name)
expect(broadcast_recording.download_url).to eq("https://stream.mux.com/asset_playback_uid/high.mp4?download=#{download_file_name}")
name = broadcast_recording.name
expect(broadcast_recording.download_url).to eq("https://stream.mux.com/asset_playback_uid/high.mp4?download=#{name}")
end
end
describe "#download_file_name" do
before do
allow_any_instance_of(BroadcastRecording).to receive(:download_file_name).and_return("my-broadcast_date_2020-05-14_time_15-30-00")
end
it "includes the name of the live stream and the created datetime" do
broadcast = create(:broadcast, skip_create_callback: true, name: "My Broadcast")
recording = create(:broadcast_recording, broadcast: broadcast, created_at: DateTime.new(2020, 05, 14, 15, 30, 00))
file_name = recording.download_file_name
recording = create(:broadcast_recording, broadcast: broadcast)
file_name = recording.name
expect(file_name).to eq "my-broadcast_date_2020-05-14_time_15-30-00"
end

View File

@@ -24,7 +24,11 @@ describe MaterialReleasePolicy do
end
end
permissions :edit_photos? do
permissions :edit_files? do
it { is_expected.to permit(:edit_photos) }
end
permissions :update_files? do
it { is_expected.to permit(:edit_photos) }
end