Compare commits

...

5 Commits

Author SHA1 Message Date
Bilal
79174d8f3b remove comment 2020-09-09 19:38:09 +03:00
Bilal
aa6c851807 add specs 2020-09-09 19:27:12 +03:00
Bilal
ab0b6f2c7d update broadcast layout 2020-09-09 18:40:38 +03:00
Senad Uka
3db230de9b Upstream sync 2020-09-09 05:33:57 +02:00
Senad Uka
e5ac3e9345 Upstream sync 2020-09-06 21:42:50 +02:00
34 changed files with 681 additions and 90 deletions

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,7 +1,6 @@
$(document).on("click", "[data-behavior=play_recording]", function() { $(document).on("click", "[data-behavior=play_recording]", function() {
if ($(this).hasClass('active')){ clearPlayingHighlight();
return false; $(this).parent().parent().addClass('playing-highlight');
}
$("#broadcast_video").data('videoType', 'recording'); $("#broadcast_video").data('videoType', 'recording');
@@ -16,13 +15,13 @@ $(document).on("click", "[data-behavior=play_recording]", function() {
height: '100%', height: '100%',
autoPlay: true 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'); }); $(document).on("click", "[data-behavior=play_stream]", function() {
// clearPlayingHighlight();
$("#broadcast_video").data('videoType', 'stream');
});
function clearPlayingHighlight() {
$(".playing-highlight").removeClass("playing-highlight");
}

View File

@@ -1,4 +1,30 @@
// Do not allow file attachments in rich text content // Do not allow file attachments in rich text content
addEventListener("trix-file-accept", function(event) { addEventListener("trix-file-accept", function(event) {
event.preventDefault(); event.preventDefault();
}) });
Trix.config.textAttributes.underline = {
style: { "textDecoration": "underline" },
inheritable: true,
parser: function (element) {
var style = window.getComputedStyle(element);
return style.textDecoration === "underline";
}
}
document.addEventListener('trix-initialize', function (e) {
const trix = e.target;
const toolBar = trix.toolbarElement;
// // Creation of the button
const button = document.createElement("button");
button.setAttribute("type", "button");
button.setAttribute("class", "trix-button trix-button--icon trix-button--icon-underline");
button.setAttribute("data-trix-attribute", "underline");
button.setAttribute("title", "underline");
button.setAttribute("tabindex", "-1");
button.innerText = "U";
// Attachment of the button to the toolBar
toolBar.querySelector('.trix-button-group--text-tools').appendChild(button);
});

View File

@@ -461,3 +461,37 @@ a[data-behavior=seekable-timecode] {
border-color: transparent; border-color: transparent;
border-bottom: 3px solid #ff0000; border-bottom: 3px solid #ff0000;
} }
//Trix underline style
trix-toolbar {
.trix-button--icon-underline::before {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z'/%3E%3C/svg%3E");
}
}
// Play button SVG
.play-btn {
width: 60%;
height: auto;
}
.play-btn-svg{
transition: 0.3s;
stroke:#fedfc2;
opacity: 0;
}
.play-btn:hover .play-btn-svg {
fill-opacity: 0;
opacity: 1;
}
// Play button in video thumbnail preview
.play-thumbnail { position: relative; }
.play-thumbnail img { display: block; }
.play-thumbnail .play-btn { position: absolute; bottom:5px; left:10px; }
// Active recording highlight
.playing-highlight {
background-color: rgba(182, 203, 205, 1);
}

View File

@@ -48,6 +48,10 @@ u {
margin-right: -30px; margin-right: -30px;
} }
.embed-person-photo {
text-align: right;
}
.do-not-copy-warning { .do-not-copy-warning {
padding-right: 15px; padding-right: 15px;
} }

View File

@@ -45,13 +45,14 @@ class Api::ReleasesController < Api::ApiController
if model_name == "acquired_media_release" if model_name == "acquired_media_release"
mapping = { mapping = {
"#{model_name.camelize}": SerializableAcquiredMediaRelease, "#{model_name.camelize}": SerializableAcquiredMediaRelease,
FileInfo: SerializableFileInfo FileInfo: SerializableFileInfo,
"ActiveStorage::Attachment".to_sym => ActiveStorage::SerializableAttachment,
} }
render jsonapi: release, render jsonapi: release,
status: status, status: status,
class: mapping, class: mapping,
include: [:file_infos] include: [:files, :file_infos]
else else
mapping = { mapping = {
"#{model_name.camelize}": show_serializable, "#{model_name.camelize}": show_serializable,

View File

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

View File

@@ -3,7 +3,7 @@ class ContractsController < ApplicationController
respond_to do |format| respond_to do |format|
format.pdf { send_contract_pdf } format.pdf { send_contract_pdf }
if Rails.env.development? if Rails.env.development? || Rails.env.test?
format.html { render_sample_html } format.html { render_sample_html }
end end
end end

View File

@@ -4,4 +4,16 @@ class PagesController < ApplicationController
skip_after_action :verify_authorized skip_after_action :verify_authorized
skip_after_action :verify_policy_scoped skip_after_action :verify_policy_scoped
skip_before_action :require_login 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 end

View File

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

View File

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

View File

@@ -12,10 +12,10 @@ class BroadcastRecordingPolicy < ApplicationPolicy
end end
def edit? def edit?
destroy? true
end end
def update? def update?
edit? true
end end
end end

View File

@@ -17,4 +17,14 @@ class SerializableAcquiredMediaRelease < JSONAPI::Serializable::Resource
{ count: @object.file_infos.size } { count: @object.file_infos.size }
end end
end end
has_many :files do
data do
@object.files
end
meta do
{ count: @object.files.size }
end
end
end end

View File

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

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

View File

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

View File

@@ -1,26 +1,30 @@
<% if recordings.present? %> <% if recordings.present? %>
<div class="list-group"> <ul class="list-unstyled">
<% recordings.each do |recording| %> <% recordings.each do |recording| %>
<div class="list-group-item list-group-item-action"> <li class="media pb-1 pt-1 pr-1">
<div class="d-flex align-items-start"> <% if policy(BroadcastRecording).update? %>
<% if (controller.class.module_parent.to_s != "Public" && policy(BroadcastRecording).update?) %> <%= link_to fa_icon("#{recording.starred ? 'star' : 'star-o'} fw"), [broadcast.project, broadcast, recording, :broadcast_recording_starrings], method: :post, class: "text-warning mr-3", remote: true %>
<%= 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 %>
<% end %>
<%= image_tag(recording.thumbnail_url, class: 'img-thumbnail img-fluid max-w-75') %> <div class="play-thumbnail">
<div class="ml-auto"> <%= image_tag(recording.thumbnail_url, class: 'mr-3', size: "75x64") %>
<% if (controller.class.module_parent.to_s != "Public" && policy(BroadcastRecording).edit?) %> <%= render "broadcasts/play_button", playback_url: recording.playback_url, data_id: dom_id(recording) %>
<%= 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>
<div class="d-flex flex-column align-items-start justify-content-start p-4">
<h5><%= recording.name %></h5> <div class="media-body">
<p><%= recording.description %></p> <h5 class="mt-0 mb-1"><%= recording.name %></h5>
<%= recording.description %>
</div> </div>
</div>
<% if policy(BroadcastRecording).edit? %>
<%= link_to fa_icon('edit'), [:edit, broadcast.project, broadcast, recording], class: "mr-3", remote: true %>
<% end %>
<%= link_to(fa_icon('download'), recording.download_url, target: "_blank") %>
</li>
<% end %> <% 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>

View File

@@ -1,12 +1,10 @@
<div class="list-group"> <div id="live-take" class="media p-1 playing-highlight">
<div class="list-group-item list-group-item-action flex-column align-items-start"> <img class="mr-5 ml-1 mt-1" src="https://via.placeholder.com/64" alt="Live stream thumbnail">
<div class="d-flex w-100 justify-content-between mb-1"> <div class="media-body">
<h5 class="mb-1"><%= broadcast.name %></h5> <h5 class="mt-0"><%= broadcast.name %></h5>
<small>Created - <%= time_ago_in_words(broadcast.created_at) + " ago" %></small> <small>Created - <%= time_ago_in_words(broadcast.created_at) + " ago" %></small>
</div>
<div id="broadcast_updates"> <div id="broadcast_updates">
<%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %> <%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %>
</div> </div>
</div> </div>
</div> </div>
<hr/>

View File

@@ -0,0 +1,5 @@
<div class="play-btn" data-behavior="play_recording" data-playback-url="<%= playback_url %>" data-id="<%= data_id %>">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 26">
<polygon class="play-btn-svg" points="9.33 6.69 9.33 19.39 19.3 13.04 9.33 6.69"/>
</svg>
</div>

View File

@@ -22,11 +22,16 @@
<div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark"> <div class="d-flex justify-content-start align-items-center flex-row p-3 mb-5 bg-dark">
<%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %> <%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %>
<div class="ml-4 dropdown"> <div class="ml-4 dropdown">
<%= 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 %> <% if @multi_view_broadcasts.present? %>
<i class="fa fa-video-camera text-primary" aria-hidden="true"></i><span class="ml-2" id="selected_stream"><%= @broadcast.name %></span> <%= 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 %> <% end %>
<div class="dropdown-menu bg-black" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu bg-black" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5>
<%= link_to fa_icon("check", text: @broadcast.name.titleize), "#", data: { behavior: "play_stream"}, class: "dropdown-item active" %> <%= 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 %>
@@ -120,6 +125,21 @@
<div id="live_take"> <div id="live_take">
<%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %> <%= render partial: 'broadcasts/live_take', locals: { broadcast: @broadcast } %>
</div> </div>
<% if params[:director_mode] %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(director_mode: true, token: @broadcast.token)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% else %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(director_mode: true, id: @broadcast.id)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% end %>
<hr/>
<% else %>
<% if controller.class.module_parent.to_s == "Public" %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(token: @broadcast.token).except(:director_mode)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% else %>
<%= link_to "Play #{@broadcast.name.titleize}", url_for(params.permit!.merge(id: @broadcast.id).except(:director_mode)), data: { behavior: "play_stream"}, class: "mt-2 btn btn-primary" %>
<% end %>
<hr/>
<% end %>
<div id="broadcast_recordings"> <div id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %> <%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
</div> </div>

View File

@@ -4,19 +4,31 @@
</div> </div>
<hr> <hr>
<% end %> <% end %>
<% if preview %>
<h1>PREVIEW ONLY</h1>
<% end %>
<% if contract_template.body.present? %>
<%= contract_template.body %>
<br/>
<% end %>
<% if releasable.minor? && contract_template.guardian_clause.present? %>
<p class="text-left"><strong>Guardian Clause</strong></p>
<%= contract_template.guardian_clause %>
<% end %>
<% if releasable.respond_to?(:question_1_answer) %> <div class="page">
<% if preview %>
<h1>PREVIEW ONLY</h1>
<% end %>
<% if releasable.model_name == "AppearanceRelease" && releasable.person_photo.attached? %>
<div class="embed-person-photo">
<%= image_tag releasable.photos.first.variant(auto_orient: true, resize: "200x200"), id: "top-person-photo" %>
</div>
<hr>
<% end %>
<% if contract_template.body.present? %>
<%= contract_template.body %>
<br/>
<% end %>
<% if releasable.minor? && contract_template.guardian_clause.present? %>
<p class="text-left"><strong>Guardian Clause</strong></p>
<%= contract_template.guardian_clause %>
<% end %>
</div>
<% if contract_template.present? && contract_template.has_questionnaire? %>
<div class="page"> <div class="page">
<%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %> <%= render "contracts/questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>
</div> </div>

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

@@ -9,12 +9,12 @@ Rails.application.config.content_security_policy do |policy|
policy.font_src :self, :https, :data policy.font_src :self, :https, :data
policy.img_src :self, :https, :data policy.img_src :self, :https, :data
policy.object_src :self 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.media_src :self, :https, AppHost.new.domain_with_port, "https://stream.mux.com", :data, :blob
# policy.style_src :self, :https, :unsafe_inline # policy.style_src :self, :https, :unsafe_inline
# If you are using webpack-dev-server then specify webpack-dev-server host # 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, "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 # Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint" # policy.report_uri "/csp-violation-report-endpoint"

View File

@@ -200,6 +200,7 @@ Rails.application.routes.draw do
get "cookies_disabled" => 'pages#show', id: "cookies_disabled", as: :cookies_disabled get "cookies_disabled" => 'pages#show', id: "cookies_disabled", as: :cookies_disabled
get "accountless_user" => 'pages#show', id: "accountless_user", as: :accountless_user 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] resource :session, only: [:new, :create]
resources :password_resets, only: [:new, :create, :edit, :update] resources :password_resets, only: [:new, :create, :edit, :update]

View File

@@ -30,6 +30,16 @@ RSpec.describe Api::AcquiredMediaReleasesController, type: :controller do
expect(response).to be_successful expect(response).to be_successful
end 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 end
describe '#create' do describe '#create' do

View File

@@ -14,6 +14,8 @@ RSpec.describe Api::ProfilesController, type: :controller do
expect(response).to be_successful expect(response).to be_successful
expect(response_body_data).to include('id' => current_user.to_param, 'type' => 'user') 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('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
end end

View File

@@ -19,6 +19,22 @@ FactoryBot.define do
amendment_clause "Amendment Legal Language" amendment_clause "Amendment Legal Language"
end end
trait :with_questionnaire_legal_text do
questionnaire_legal_text "Questionnaire Legal Text"
end
trait :with_one_question do
question_1_text "Is this a question?"
end
trait :with_exhibits do
exhibit_a_legal_text "Exhibit A legal text"
exhibit_b_legal_text "Exhibit B legal text"
exhibit_a_question_text "Exhibit A question text"
exhibit_b_question_text "Exhibit B question text"
end
factory :appearance_release_contract_template do factory :appearance_release_contract_template do
release_type "appearance" release_type "appearance"
end end

View File

@@ -386,6 +386,13 @@ RSpec.feature 'User manages contract templates', type: :feature do
expect(ct.signature_legal_text.id).not_to eq ContractTemplate.last.signature_legal_text.id expect(ct.signature_legal_text.id).not_to eq ContractTemplate.last.signature_legal_text.id
end end
scenario 'trix editor has underline button', js: true do
visit new_project_contract_template_path(project)
select 'Appearance Release', from: 'Release type'
expect(page).to have_selector("button[data-trix-attribute='underline']")
end
context 'When the user is associate' do context 'When the user is associate' do
let(:current_user) { create(:user, :associate) } let(:current_user) { create(:user, :associate) }

View File

@@ -544,7 +544,7 @@ feature 'User managing appearance releases' do
expect(pdf_body).to have_content('Guardian Email') expect(pdf_body).to have_content('Guardian Email')
end end
scenario "viewing the contract PDF when exhibit A is signed" do scenario "viewing the contract PDF when exhibit A is signed and without questionnaire" do
contract_template = create(:appearance_release_contract_template, project: project, exhibit_a_legal_text: "Exhibit A legal text", exhibit_a_question_text: "Exhibit A question text") contract_template = create(:appearance_release_contract_template, project: project, exhibit_a_legal_text: "Exhibit A legal text", exhibit_a_question_text: "Exhibit A question text")
appearance_release = create(:appearance_release, appearance_release = create(:appearance_release,
:amendment_signed, :amendment_signed,
@@ -566,10 +566,122 @@ feature 'User managing appearance releases' do
expect(pdf_body).to have_content("John Doe") expect(pdf_body).to have_content("John Doe")
expect(pdf_body).to have_content "Exhibit A" expect(pdf_body).to have_content exhibit_a_heading
expect(pdf_body).to have_content "Exhibit A legal text" expect(pdf_body).to have_content "Exhibit A legal text"
expect(pdf_body).to have_content "Exhibit A question text" expect(pdf_body).to have_content "Exhibit A question text"
expect(pdf_body).to have_content "Answer to exhibit A question" expect(pdf_body).to have_content "Answer to exhibit A question"
expect(pdf_body).not_to have_content questionnaire_heading
expect(pdf_body).not_to have_content exhibit_b_heading
end
scenario "viewing the contract PDF when exhibit B is signed and without questionnaire" do
contract_template = create(:appearance_release_contract_template, project: project, exhibit_b_legal_text: "Exhibit B legal text", exhibit_b_question_text: "Exhibit B question text")
appearance_release = create(:appearance_release,
:amendment_signed,
:native,
contract_template: contract_template,
project: project,
person_first_name: "John",
person_last_name: "Doe",
exhibit_b_answer: "Answer to exhibit B question"
)
sign_in(current_user)
visit project_appearance_releases_path(project)
click_link *view_release_pdf_link_for(appearance_release)
expect(content_type).to eq("application/pdf")
expect(content_disposition).to include("inline")
expect(pdf_filename).to include("doe-john")
expect(pdf_body).to have_content("John Doe")
expect(pdf_body).to have_content exhibit_b_heading
expect(pdf_body).to have_content "Exhibit B legal text"
expect(pdf_body).to have_content "Exhibit B question text"
expect(pdf_body).to have_content "Answer to exhibit B question"
expect(pdf_body).not_to have_content questionnaire_heading
expect(pdf_body).not_to have_content exhibit_a_heading
end
scenario "viewing the contract PDF with questionnaire and without exhibits" do
contract_template = create(:appearance_release_contract_template, :with_questionnaire_legal_text, :with_one_question, project: project)
appearance_release = create(:appearance_release,
:amendment_signed,
:native,
contract_template: contract_template,
project: project,
person_first_name: "John",
person_last_name: "Doe",
question_1_answer: "Yes"
)
sign_in(current_user)
visit project_appearance_releases_path(project)
click_link *view_release_pdf_link_for(appearance_release)
expect(content_type).to eq("application/pdf")
expect(content_disposition).to include("inline")
expect(pdf_filename).to include("doe-john")
expect(pdf_body).to have_content questionnaire_heading
expect(pdf_body).to have_content contract_template.question_1_text
expect(pdf_body).to have_content appearance_release.question_1_answer
expect(pdf_body).not_to have_content exhibit_a_heading
expect(pdf_body).not_to have_content exhibit_b_heading
end
scenario "viewing the contract PDF with questionnaire and with exhibits" do
contract_template = create(:appearance_release_contract_template,
:with_questionnaire_legal_text,
:with_one_question,
:with_exhibits,
project: project)
appearance_release = create(:appearance_release,
:amendment_signed,
:native,
contract_template: contract_template,
project: project,
person_first_name: "John",
person_last_name: "Doe",
question_1_answer: "Yes",
exhibit_a_answer: "Exhibit A answer",
exhibit_b_answer: "Exhibit B answer"
)
sign_in(current_user)
visit project_appearance_releases_path(project)
click_link *view_release_pdf_link_for(appearance_release)
expect(content_type).to eq("application/pdf")
expect(content_disposition).to include("inline")
expect(pdf_filename).to include("doe-john")
expect(pdf_body).to have_content questionnaire_heading
expect(pdf_body).to have_content contract_template.question_1_text
expect(pdf_body).to have_content appearance_release.question_1_answer
expect(pdf_body).to have_content exhibit_a_heading
expect(pdf_body).to have_content contract_template.exhibit_a_legal_text.to_plain_text
expect(pdf_body).to have_content contract_template.exhibit_a_question_text
expect(pdf_body).to have_content appearance_release.exhibit_a_answer
expect(pdf_body).to have_content exhibit_b_heading
expect(pdf_body).to have_content contract_template.exhibit_b_legal_text.to_plain_text
expect(pdf_body).to have_content contract_template.exhibit_b_question_text
expect(pdf_body).to have_content appearance_release.exhibit_b_answer
end
scenario "viewing the contract PDF - it shows person photo on first page if person photo is attached" do
appearance_release = create(:appearance_release_with_contract_template, :native, :minor_with_guardian_photo, project: project)
visit view_release_pdf_html_preview_link_for(appearance_release)
person_photo_url = url_for(appearance_release.person_photo.variant(auto_orient: true, resize: "200x200")).to_s
expect(page).to have_selector("#top-person-photo[src^='#{person_photo_url}']")
end end
scenario 'deleting a release', js: true do scenario 'deleting a release', js: true do
@@ -908,6 +1020,10 @@ feature 'User managing appearance releases' do
['Download', href: appearance_release_contracts_path(appearance_release, format: 'pdf')] ['Download', href: appearance_release_contracts_path(appearance_release, format: 'pdf')]
end end
def view_release_pdf_html_preview_link_for(appearance_release)
appearance_release_contracts_path(appearance_release)
end
def successful_submission_message def successful_submission_message
'Your release was successfully submitted. Thank you.' 'Your release was successfully submitted. Thank you.'
end end
@@ -987,4 +1103,16 @@ feature 'User managing appearance releases' do
def amendment_signature_label def amendment_signature_label
t 'contracts.amendment_page.description_labels.amendment_signature' t 'contracts.amendment_page.description_labels.amendment_signature'
end end
def questionnaire_heading
t 'contracts.questionnaire.heading.appearance_release'
end
def exhibit_a_heading
t 'contracts.exhibit_a_page.heading.appearance_release'
end
def exhibit_b_heading
t 'contracts.exhibit_b_page.heading.appearance_release'
end
end end

View File

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

View File

@@ -244,11 +244,32 @@ feature "User managing medical releases" do
expect(pdf_filename).to include("doe-john") expect(pdf_filename).to include("doe-john")
expect(pdf_body).to have_content("John Doe") expect(pdf_body).to have_content("John Doe")
expect(pdf_body).to have_content "MEDICAL QUESTIONNAIRE" expect(pdf_body).to have_content questionnaire_heading.upcase
expect(pdf_body).to have_content "Question 1 text" expect(pdf_body).to have_content "Question 1 text"
expect(pdf_body).to have_content "Question 1 answer" expect(pdf_body).to have_content "Question 1 answer"
expect(pdf_body).to have_content "Questionnaire legal text" expect(pdf_body).to have_content "Questionnaire legal text"
end end
scenario 'viewing contract PDF without medical questionnaire' do
contract_template = create(:medical_release_contract_template, project: project)
medical_release = create(:medical_release,
:native,
contract_template: contract_template,
project: project,
person_first_name: "John",
person_last_name: "Doe",
)
sign_in(current_user)
visit project_medical_releases_path(project)
click_link *view_release_pdf_link_for(medical_release)
expect(content_type).to eq("application/pdf")
expect(content_disposition).to include("inline")
expect(pdf_filename).to include("doe-john")
expect(pdf_body).not_to have_content questionnaire_heading.upcase
end
end end
context "when the user is manager(project manager)" do context "when the user is manager(project manager)" do
@@ -499,4 +520,8 @@ feature "User managing medical releases" do
def dummy_signature_legal_text def dummy_signature_legal_text
'Some signature legal language' 'Some signature legal language'
end end
def questionnaire_heading
t 'contracts.questionnaire.heading.medical_release'
end
end end

View File

@@ -80,7 +80,7 @@ feature "User managing misc releases" do
end end
scenario 'viewing the contract PDF' do scenario 'viewing the contract PDF with questionnaire' do
misc_release = create(:misc_release, misc_release = create(:misc_release,
:native, :native,
contract_template: build(:misc_release_contract_template, question_1_text: 'Q1'), contract_template: build(:misc_release_contract_template, question_1_text: 'Q1'),
@@ -121,10 +121,30 @@ feature "User managing misc releases" do
expect(pdf_body).to have_content('Woman') expect(pdf_body).to have_content('Woman')
expect(pdf_body).to have_content('Brunette') expect(pdf_body).to have_content('Brunette')
expect(pdf_body).not_to have_content('Guardian Email') expect(pdf_body).not_to have_content('Guardian Email')
expect(pdf_body).to have_content('QUESTIONNAIRE') expect(pdf_body).to have_content questionnaire_heading.upcase
expect(pdf_body).to have_content('Q1') expect(pdf_body).to have_content('Q1')
expect(pdf_body).to have_content('A1') expect(pdf_body).to have_content('A1')
end end
scenario 'viewing the contract PDF without questionnaire' do
misc_release = create(:misc_release,
:native,
contract_template: build(:misc_release_contract_template),
project: project,
person_first_name: 'Jane',
person_last_name: 'Doe'
)
sign_in(current_user)
visit project_misc_releases_path(project)
click_link *view_release_pdf_link_for(misc_release)
expect(content_type).to eq('application/pdf')
expect(content_disposition).to include('inline')
expect(pdf_filename).to include('doe-jane')
expect(pdf_body).not_to have_content questionnaire_heading.upcase
end
end end
context "when the user is manager(project manager)" do context "when the user is manager(project manager)" do
@@ -215,4 +235,8 @@ feature "User managing misc releases" do
def view_release_pdf_link_for(release) def view_release_pdf_link_for(release)
['Download', href: misc_release_contracts_path(release, format: 'pdf')] ['Download', href: misc_release_contracts_path(release, format: 'pdf')]
end end
def questionnaire_heading
t 'contracts.questionnaire.heading.misc_release'
end
end end

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,8 +50,111 @@ 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"
@@ -69,9 +172,12 @@ 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
@@ -125,7 +231,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"))