Compare commits

..

3 Commits

Author SHA1 Message Date
Bilal
14445aeb14 do not use remember_me, set cookie expiration 2020-08-25 05:25:16 +02:00
Bilal
01da597f3e modify specs 2020-08-25 05:25:16 +02:00
Bilal
663a6d5c33 add remember_me token 2020-08-25 05:25:16 +02:00
60 changed files with 437 additions and 784 deletions

View File

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

View File

@@ -1,20 +0,0 @@
$(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,4 +0,0 @@
$(document).on("click", "#director_mode_switch", function() {
// JQuery click event trigger was not working.
document.getElementById("director_mode_link").click();
});

View File

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

View File

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

View File

@@ -1,34 +0,0 @@
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,25 +5,13 @@ class BroadcastRecordingsController < ApplicationController
before_action :set_broadcast before_action :set_broadcast
before_action :set_recording before_action :set_recording
def edit
end
def update
@recording.update(broadcast_recording_params)
set_recordings
end
def destroy def destroy
@recording.update(hidden: true) @recording.update(hidden: true)
set_recordings @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
end end
private private
def broadcast_recording_params
params.require(:broadcast_recording).permit(:name, :description)
end
def set_project def set_project
@project = policy_scope(Project).find(params[:project_id]) @project = policy_scope(Project).find(params[:project_id])
end end
@@ -35,8 +23,4 @@ class BroadcastRecordingsController < ApplicationController
def set_recording def set_recording
@recording = authorize policy_scope(@broadcast.broadcast_recordings).find(params[:id]) @recording = authorize policy_scope(@broadcast.broadcast_recordings).find(params[:id])
end end
def set_recordings
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
end
end end

View File

@@ -32,7 +32,6 @@ class BroadcastsController < ApplicationController
@conference_url = conference_url_for(@broadcast) @conference_url = conference_url_for(@broadcast)
@recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.visible.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application' render layout: 'application'
end end
@@ -114,7 +113,7 @@ class BroadcastsController < ApplicationController
end end
def conference_url_for(broadcast) def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || url_for([broadcast.project, broadcast, :zoom_meeting]) broadcast.video_conference_url_override || url_for([broadcast.project, broadcast, :zoom_meeting])
end end
def log_create_analytics def log_create_analytics

View File

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

View File

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

View File

@@ -44,7 +44,7 @@ class Public::BroadcastsController < Public::BaseController
end end
def conference_url_for(broadcast) def conference_url_for(broadcast)
broadcast.video_conference_url_override.presence || broadcast_zoom_meeting_url(broadcast.token) broadcast.video_conference_url_override || broadcast_zoom_meeting_url(broadcast.token)
end end
class MultiViewBroadcast 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, params.require(:material_release).permit(person_params, guardian_params, second_guardian_params, :minor,
:name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country, :name, :address_street1, :address_street2, :address_city, :address_state, :address_zip, :address_country,
:signature_base64, :signature_base64,
:locale, :contract_template, :description, files: [] :locale, :contract_template, :description, photos: []
) )
end end

View File

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

View File

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

View File

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

@@ -7,10 +7,8 @@ class BroadcastRecording < ApplicationRecord
scope :visible, -> { where(hidden: false) } scope :visible, -> { where(hidden: false) }
before_save :set_title_and_description
def download_url def download_url
"https://stream.mux.com/#{asset_playback_uid}/#{file_name}?download=#{name}" "https://stream.mux.com/#{asset_playback_uid}/#{file_name}?download=#{download_file_name}"
end end
def playback_url def playback_url
@@ -18,21 +16,6 @@ class BroadcastRecording < ApplicationRecord
end end
def download_file_name def download_file_name
"#{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 "#{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
end
def toggle_star
toggle! :starred
end
def thumbnail_url(width = 300)
"https://image.mux.com/#{asset_playback_uid}/thumbnail.jpg?width=#{width}"
end
private
def set_title_and_description
self.name ||= download_file_name
self.description ||= "No description provided for this recording."
end end
end end

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<input id="total_entries" type=hidden value=<%= @appearance_releases.total_entries %> />
<div id="upload-progress-container" class="mb-1"></div> <div id="upload-progress-container" class="mb-1"></div>
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-2"> <div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-2">
<% if policy(AppearanceRelease).new? %> <% if policy(AppearanceRelease).new? %>
@@ -17,7 +16,7 @@
<% end %> <% end %>
<% if @appearance_releases.any? && policy(AppearanceRelease).download_multiple? %> <% if @appearance_releases.any? && policy(AppearanceRelease).download_multiple? %>
<%= 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..." } %> <%= 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..." } %>
<% end %> <% end %>
</div> </div>
</div> </div>

View File

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

View File

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

View File

@@ -1,24 +0,0 @@
<%= 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

@@ -1,11 +0,0 @@
$('[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 +1,6 @@
<%= render("broadcast_recordings/refresh_recordings_list") %> 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 }) %>");

View File

@@ -1,6 +0,0 @@
<% # 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

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

View File

@@ -1 +1,3 @@
<%= 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) } %> <%= 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) } %>

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
<table class="w-100 h-100 bg-secondary"> <table class="w-100 h-100 bg-secondary">
<tbody> <tbody>
<tr> <tr>
<td class="text-center align-middle text-white bg-black"> <td class="text-center align-middle text-white">
Video player will appear here when the stream becomes available. Video player will appear here when the stream becomes available.
</td> </td>
</tr> </tr>

View File

@@ -14,135 +14,159 @@
<% end %> <% end %>
<% content_for :header do %> <% content_for :header do %>
<header></header> <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>
<% end %> <% end %>
<div class="row no-gutters m-n3"> <div class="row">
<div class="col-lg-8 col-md-12 bg-black"> <div class="col-lg-8 col-md-12 mb-3">
<div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark"> <div class="card shadow-sm">
<%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %> <div class="card-header">
<div class="ml-4 dropdown"> <div class="d-flex justify-content-between align-items-center">
<%= 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 %> <h1 class="h3 m-0"><%= @broadcast.name %></h1>
<i class="fa fa-video-camera text-primary" aria-hidden="true"></i><span class="ml-2" id="selected_stream"><%= @broadcast.name %></span> <div class="dropdown">
<% end %> <%= 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 bg-black" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5> <h5 class="dropdown-header">Live Streams</h5>
<%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %> <%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %>
<% @multi_view_broadcasts.each do |broadcast| %> <% @multi_view_broadcasts.each do |broadcast| %>
<% if broadcast.id != @broadcast.id %> <% if broadcast.id != @broadcast.id %>
<% if params[:director_mode] %> <%= link_to broadcast.name.titleize, broadcast.url, data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(director_mode: true, token: broadcast.token)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% else %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(director_mode: true, id: broadcast.id)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% end %>
<% else %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(token: broadcast.token).except(:director_mode)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% else %>
<%= link_to broadcast.name.titleize, url_for(params.permit!.merge(id: broadcast.id).except(:director_mode)), data: { behavior: "play_stream"}, class: class_string("dropdown-item", "active" => @broadcast.id == broadcast.id) %>
<% end %> <% end %>
<% end %> <% end %>
<% 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 %>
<% end %> <% end %>
</div> </div>
</div> </div>
<% if @broadcast.director_mode_video_embed.present? %>
<% if params[:director_mode] %>
<div class="custom-control custom-switch ml-auto">
<input type="checkbox" name="director_mode" value="true" class="custom-control-input" id="director_mode_switch" checked="checked" />
<label class="custom-control-label text-white override-custom-control-label" for="director_mode_switch">Director Mode</label>
</div>
<%= link_to "Disable Director Mode", url_for(params.permit!.except(:director_mode)), class: "d-none", id: "director_mode_link" %>
<% else %>
<div class="custom-control custom-switch ml-auto">
<input type="checkbox" name="director_mode" value="true" class="custom-control-input" id="director_mode_switch" />
<label class="custom-control-label text-white override-custom-control-label" for="director_mode_switch">Director Mode</label>
</div>
<%= link_to "Enable Director Mode", url_for(params.permit!.merge(director_mode: true)), class: "d-none", id: "director_mode_link" %>
<% end %>
<% end %>
</div>
<div class="embed-responsive embed-responsive-16by9" id="video_content">
<%= render partial: 'broadcasts/video', locals: { broadcast: @broadcast } %>
<% if @broadcast.streamer_recording? && @broadcast.active? %>
<%= javascript_tag nonce: true do %>
new Clappr.Player({
parentId: '#broadcast_video',
source: "<%= @broadcast.full_live_stream_playback_url %>",
width: '100%',
height: '100%',
mute: true,
autoPlay: true,
hlsMinimumDvrSize: 1
});
<% end %>
<% end %>
</div> </div>
</div> </div>
<div class="col-lg-4 col-md-12 bg-white p-3 min-vh-100 overflow-auto"> <div class="col-lg-4 col-md-12 mb-3">
<% unless controller.class.module_parent.to_s == "Public" %> <div class="card shadow-sm mb-3">
<% if @multi_view_broadcasts.present? %> <div class="card-header">
<% tokens = @multi_view_broadcasts.map(&:token) %> <ul class="nav nav-tabs card-header-tabs">
<div class="btn-group"> <li class="nav-item">
<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> <%= link_to "Home", "#home", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> </li>
<span class="sr-only">Toggle Dropdown</span> <li class="nav-item">
</button> <%= link_to "Previous Sessions", "#recordings", class: class_string("nav-link", "active" => params[:active_tab] == "recordings"), data: { toggle: "tab" } %>
<div class="dropdown-menu"> </li>
<%= link_to t('.actions.reset_url'), [@project, @broadcast], method: :patch, class: "dropdown-item" %> </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>
</div> <div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings">
<% else %> <div id="broadcast_recordings">
<div class="btn-group"> <%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
<button type="button" class="btn btn-primary" id="broadcast_share_url" data-behavior="clipboard" href="<%= broadcast_url(@broadcast.token) %>">Share URL</button> </div>
<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>
</div> </div>
<% end %>
<% end %>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary', target: '_blank' %>
<hr/>
<ul class="nav nav-tabs override-nav-tabs mb-3">
<li class="nav-item">
<%= link_to "Takes", "#recordings", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
</li>
<li class="nav-item">
<%= link_to "Files", "#files", class: class_string("nav-link", "active" => params[:active_tab] == "files"), data: { toggle: "tab" } %>
</li>
</ul>
<div class="tab-content">
<div class="<%= class_string("tab-pane fade show", "active" => !params[:active_tab].present?) %>" id="recordings">
<div id="live_take">
<%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %>
</div>
<div id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
</div>
</div> </div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == "files") %>" id="files"> </div>
<% if @multi_view_broadcasts.present? %>
<ul class="nav nav-tabs"> <!-- 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">
<% @multi_view_broadcasts.each_with_index do |mvb, index| %> <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<li class="nav-item"> <li class="nav-item">
<%= link_to mvb.name, "#files_broadcast_#{mvb.token}", class: class_string("nav-link", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))), data: { toggle: "tab" } %> <%= link_to mvb.name, "#files_broadcast_#{mvb.token}", class: class_string("nav-link", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))), data: { toggle: "tab" } %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<div class="tab-content pt-4"> <% end %>
</div>
<div class="card-body p-3">
<div class="tab-content">
<% if @multi_view_broadcasts.present? %>
<% @multi_view_broadcasts.each_with_index do |mvb, index| %> <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>"> <div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %> <%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %>
</div> </div>
<% end %> <% end %>
</div> <% else %>
<% else %> <div class="tab-pane fade show active" id="files_broadcast_<%= @broadcast.id %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %> <%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
<% end %> </div>
<% end %>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

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

View File

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

View File

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

View File

@@ -27,7 +27,7 @@
<tr> <tr>
<th data-behavior="all-selectable"><%= check_box_tag "material_release_ids[]", false, false %></th> <th data-behavior="all-selectable"><%= check_box_tag "material_release_ids[]", false, false %></th>
<th><%= t '.table_headers.approved'%></th> <th><%= t '.table_headers.approved'%></th>
<th><%= t(".table_headers.files_count") %></th> <th></th>
<th><%= MaterialRelease.human_attribute_name(:name) %></th> <th><%= MaterialRelease.human_attribute_name(:name) %></th>
<th><%= t(".table_headers.owner_info") %> <th><%= t(".table_headers.owner_info") %>
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>

View File

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

View File

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

View File

@@ -55,7 +55,7 @@ Rails.application.routes.draw do
resources :appearance_releases, except: [:show], concerns: [:contractable, :notable] resources :appearance_releases, except: [:show], concerns: [:contractable, :notable]
resources :appearance_release_imports, only: [:create] resources :appearance_release_imports, only: [:create]
resources :location_releases, except: [:show], concerns: [:contractable, :notable, :photoable] resources :location_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :material_releases, except: [:show], concerns: [:contractable, :notable, :file_uploadable] resources :material_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :music_releases, except: [:show], concerns: [:contractable, :notable] resources :music_releases, except: [:show], concerns: [:contractable, :notable]
resources :talent_releases, except: [:show], concerns: [:contractable, :notable, :photoable] resources :talent_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :medical_releases, except: [:show], concerns: [:contractable, :notable, :photoable] resources :medical_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
@@ -101,9 +101,7 @@ Rails.application.routes.draw do
delete :destroy_file delete :destroy_file
end end
resource :zoom_meeting, only: [:show] resource :zoom_meeting, only: [:show]
resources :broadcast_recordings, only: [:destroy, :edit, :update] do resources :broadcast_recordings, only: :destroy
resources :broadcast_recording_starrings, only: :create
end
end end
resources :directories, except: [:index] do resources :directories, except: [:index] do
member do member do

View File

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

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

View File

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

View File

@@ -541,10 +541,7 @@ CREATE TABLE public.broadcast_recordings (
created_at timestamp(6) without time zone NOT NULL, created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL, updated_at timestamp(6) without time zone NOT NULL,
duration double precision, duration double precision,
hidden boolean DEFAULT false, hidden boolean DEFAULT false
name character varying,
description text,
starred boolean DEFAULT false
); );
@@ -4028,8 +4025,6 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200807190607'), ('20200807190607'),
('20200811102720'), ('20200811102720'),
('20200812060406'), ('20200812060406'),
('20200819070738'), ('20200819070738');
('20200820082501'),
('20200824171649');

View File

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

View File

@@ -1,48 +0,0 @@
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,66 +9,16 @@ RSpec.describe BroadcastRecordingsController, type: :controller do
before do before do
sign_in user sign_in user
stub_mux_live_stream
end
describe "#edit" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recording) { create(:broadcast_recording, broadcast: broadcast) }
before 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 end
describe "#destroy" do describe "#destroy" do
let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") } let(:broadcast) { create(:broadcast, project: project, name: "New Broadcast") }
let(:recording) { create(:broadcast_recording, broadcast: broadcast) } let(:recording) { create(:broadcast_recording, broadcast: broadcast) }
before do
stub_mux_live_stream
end
it "hides the broadcast recording" do it "hides the broadcast recording" do
expect(recording.hidden).to be false expect(recording.hidden).to be false

View File

@@ -150,6 +150,13 @@ RSpec.describe BroadcastsController, type: :controller do
expect(assigns(:broadcast)).to eq(broadcast) expect(assigns(:broadcast)).to eq(broadcast)
end 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 it "displays zoom meeting button" do
get :show, params: { project_id: project.id, id: broadcast.id } get :show, params: { project_id: project.id, id: broadcast.id }
@@ -167,7 +174,7 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with just the current broadcast" do it "renders the view dropdown with just the current broadcast" do
get :show, params: { project_id: project, id: broadcast } get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Another Broadcast") expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Another Broadcast")
end end
end end
@@ -178,12 +185,32 @@ RSpec.describe BroadcastsController, type: :controller do
get :show, params: { project_id: project, id: broadcast, multi_view_ids: [broadcast.id, other_broadcast.id] } get :show, params: { project_id: project, id: broadcast, multi_view_ids: [broadcast.id, other_broadcast.id] }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Another Broadcast") 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") expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Some Other Broadcast")
end end
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 context "when virtual director video embed is available" do
let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast", let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast",
director_mode_video_embed: "<iframe>video player</iframe>") } director_mode_video_embed: "<iframe>video player</iframe>") }
@@ -191,8 +218,9 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with a director mode enable option" do it "renders the view dropdown with a director mode enable option" do
get :show, params: { project_id: project, id: broadcast } get :show, params: { project_id: project, id: broadcast }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".custom-control-label", text: "Director Mode") 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")
end end
context "when director mode is enabled" do context "when director mode is enabled" do
@@ -205,8 +233,9 @@ RSpec.describe BroadcastsController, type: :controller do
it "renders the view dropdown with a director mode disable option" do it "renders the view dropdown with a director mode disable option" do
get :show, params: { project_id: project, id: broadcast, director_mode: true } get :show, params: { project_id: project, id: broadcast, director_mode: true }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".custom-control-label", text: "Director Mode") 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")
end end
end end
end end

View File

@@ -68,7 +68,13 @@ RSpec.describe PhotosController, type: :controller do
it_behaves_like "a photoable releases controller" it_behaves_like "a photoable releases controller"
end end
context "for material releases" do
subject { create(:material_release, project: project) }
it_behaves_like "a photoable releases controller"
end
private private
def release_params 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 it "renders the view dropdown with just the current broadcast" do
get :show, params: { token: broadcast.token } get :show, params: { token: broadcast.token }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Broadcast") expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Broadcast")
end end
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] } get :show, params: { token: broadcast.token, multi_view_tokens: [broadcast.token, other_broadcast.token] }
expect(response.body).to have_content broadcast.name expect(response.body).to have_content "Switch View"
expect(response.body).to have_selector(".dropdown-menu .dropdown-item.active", text: "Broadcast") 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") expect(response.body).to have_selector(".dropdown-menu a.dropdown-item", text: "Some Other Broadcast")
end end
@@ -66,7 +66,8 @@ RSpec.describe Public::BroadcastsController, type: :controller do
it "renders the view dropdown with a message" do it "renders the view dropdown with a message" do
get :show, params: { token: broadcast.token } get :show, params: { token: broadcast.token }
expect(response.body).to have_content broadcast.name 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
end end
@@ -76,7 +77,8 @@ RSpec.describe Public::BroadcastsController, type: :controller do
get :show, params: { token: broadcast.token } get :show, params: { token: broadcast.token }
expect(response.body).to have_content broadcast.name 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
end end

View File

@@ -10,10 +10,10 @@ describe Public::MaterialReleasesController do
it "allows photos param" do it "allows photos param" do
contract_template = create(:contract_template, project: project) 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_files } 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 }
expect(response).to be_successful expect(response).to be_successful
expect(MaterialRelease.last.files.attached?).to eq true expect(MaterialRelease.last.photos.attached?).to eq true
end end
it "displays validation errors" do it "displays validation errors" do
@@ -63,8 +63,8 @@ describe Public::MaterialReleasesController do
attributes_for(:material_release, :native).except(:signature).merge(signature_param) attributes_for(:material_release, :native).except(:signature).merge(signature_param)
end end
def material_release_params_with_files def material_release_params_with_photos
attributes_for(:material_release, :native, :with_file).except(:signature).merge(signature_param) attributes_for(:material_release, :native, :with_photo).except(:signature).merge(signature_param)
end end

View File

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

View File

@@ -42,12 +42,6 @@ FactoryBot.define do
end end
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 trait :non_native do
contract do contract do

View File

@@ -56,32 +56,14 @@ feature 'User managing broadcasts' do
visit project_broadcast_path(project, broadcast) visit project_broadcast_path(project, broadcast)
expect(page).to have_content('Live stream is waiting to begin.') expect(page).to have_content('Live stream is waiting to begin.')
expect(page).to have_content('Share URL') expect(page).to have_content('Copy URL')
click_on "Files" within '#files' do
expect(page).to have_content('contract.pdf') 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 end
scenario 'loads full broadcast asset url if available' do click_on 'Previous Sessions'
broadcast = create(:broadcast, :with_stream, :with_files, project: project, streamer_status: :recording, status: :active, full_live_stream_playback_uid: '') expect(page).to have_content(recording.download_file_name)
visit project_broadcast_path(project, broadcast)
expect(page.body).to match broadcast.stream_playback_url
end
end end
scenario 'Clicking Reset URL regenerates broadcast token' do scenario 'Clicking Reset URL regenerates broadcast token' do
@@ -91,19 +73,93 @@ feature 'User managing broadcasts' do
visit project_broadcast_path(project, broadcast) visit project_broadcast_path(project, broadcast)
expect(page).to have_content reset_url expect(page).to have_content reset_url
expect(page).to have_xpath "//input[@readonly][@value='#{broadcast_url(old_token)}']"
click_link reset_url click_link reset_url
expect(Broadcast.last.token).not_to eq old_token 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 expect(page).to have_content token_reset_notice
end 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 scenario 'form will not submit if user clicks Add files without selected files', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project) broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast) visit project_broadcast_path(project, broadcast)
expect(page).to have_content('Live stream is waiting to begin.') expect(page).to have_content('Live stream is waiting to begin.')
click_on "Files"
expect(page).to have_content add_file_button expect(page).to have_content add_file_button
click_on add_file_button click_on add_file_button
@@ -113,7 +169,7 @@ feature 'User managing broadcasts' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project) broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast) visit project_broadcast_path(project, broadcast)
click_on "Files"
expect(page).to have_content delete_file_button, count: 3 expect(page).to have_content delete_file_button, count: 3
accept_alert do accept_alert do
@@ -133,11 +189,9 @@ feature 'User managing broadcasts' do
new_window = window_opened_by { click_link 'Multi-View' } new_window = window_opened_by { click_link 'Multi-View' }
within_window new_window do within_window new_window do
click_on "Files" expect(page).to have_content switch_view_dropdown
expect(page).to have_content broadcast_one.name
expect(page).to have_content broadcast_two.name click_on switch_view_dropdown
click_on broadcast_one.name
expect(page).to have_link('Broadcast 1') expect(page).to have_link('Broadcast 1')
expect(page).to have_link('Broadcast 2') expect(page).to have_link('Broadcast 2')
@@ -151,6 +205,24 @@ feature 'User managing broadcasts' do
end end
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 context 'When the user is associate' do
let(:current_user) { create(:user, :associate) } let(:current_user) { create(:user, :associate) }
@@ -168,6 +240,17 @@ feature 'User managing broadcasts' do
expect(page).to have_content delete_file_button, count: 0 expect(page).to have_content delete_file_button, count: 0
end 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 end
context 'When the user is account manager' do context 'When the user is account manager' do
@@ -184,7 +267,7 @@ feature 'User managing broadcasts' do
broadcast = create(:broadcast, :with_stream, :with_files, project: project) broadcast = create(:broadcast, :with_stream, :with_files, project: project)
visit project_broadcast_path(project, broadcast) visit project_broadcast_path(project, broadcast)
click_on "Files"
expect(page).to have_content delete_file_button, count: 3 expect(page).to have_content delete_file_button, count: 3
accept_alert do accept_alert do
@@ -194,7 +277,26 @@ feature 'User managing broadcasts' do
expect(page).to have_content delete_file_button, count: 2 expect(page).to have_content delete_file_button, count: 2
expect(Broadcast.find(broadcast.id).files.count).to eq 2 expect(Broadcast.find(broadcast.id).files.count).to eq 2
end 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
end end
private private
@@ -218,6 +320,10 @@ feature 'User managing broadcasts' do
all('input[type="checkbox"]')[1].click all('input[type="checkbox"]')[1].click
end end
def switch_view_dropdown
'Switch View'
end
def schedule_demo def schedule_demo
t 'broadcasts.splash.actions.book_demo' t 'broadcasts.splash.actions.book_demo'
end end

View File

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

View File

@@ -19,7 +19,7 @@ describe GenerateContractsZipJob do
describe ".perform_later" do describe ".perform_later" do
it "enqueues a background job for generating zip file" do it "enqueues a background job for generating zip file" do
expect { 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 }.to have_enqueued_job
end end
end end
@@ -28,7 +28,7 @@ describe GenerateContractsZipJob do
shared_examples "generates ZIP containig CSV file with all releases data" 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 it "generates ZIP containing CSV file with all releases data for all release types" do
lowercase_plural = subject.constantize.model_name.plural 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 generated_zip = download.file.blob.download
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv" csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
@@ -50,111 +50,8 @@ describe GenerateContractsZipJob do
end end
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
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
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 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.project).to eq project
expect(download.release_type).to eq "AppearanceRelease" expect(download.release_type).to eq "AppearanceRelease"
@@ -172,12 +69,9 @@ describe GenerateContractsZipJob do
context "generates ZIP for appearance releases" do context "generates ZIP for appearance releases" do
let(:release) { create(:appearance_release_with_contract_template, :native, project: project, person_name: "John Doe") } let(:release) { create(:appearance_release_with_contract_template, :native, project: project, person_name: "John Doe") }
let(:incomplete_release) { create(:appearance_release_with_contract_template, project: project, person_name: "Jane Doe") }
let(:complete_release) { create(:appearance_release_with_contract_template, :non_native, project: project, person_name: "Brad Doe") }
subject { 'AppearanceRelease' } subject { 'AppearanceRelease' }
it_behaves_like "generates ZIP containig CSV file with all releases data" it_behaves_like "generates ZIP containig CSV file with all releases data"
it_behaves_like "generates ZIP containig CSV file with specific releases data"
end end
context "generates ZIP for location releases" do context "generates ZIP for location releases" do
@@ -231,7 +125,7 @@ describe GenerateContractsZipJob do
end end
it "updates status to 'failure' and sends user a notification" do 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(download.status).to eq "failure"
expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure")) expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))

View File

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

View File

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