diff --git a/app/assets/images/ME_PRO_black.png b/app/assets/images/ME_PRO_black.png new file mode 100644 index 0000000..2fc7bd6 Binary files /dev/null and b/app/assets/images/ME_PRO_black.png differ diff --git a/app/assets/images/live_icon.png b/app/assets/images/live_icon.png new file mode 100644 index 0000000..26a6d22 Binary files /dev/null and b/app/assets/images/live_icon.png differ diff --git a/app/assets/javascripts/channels/broadcasts.coffee.erb b/app/assets/javascripts/channels/broadcasts.coffee.erb index 9765bc2..fddc672 100644 --- a/app/assets/javascripts/channels/broadcasts.coffee.erb +++ b/app/assets/javascripts/channels/broadcasts.coffee.erb @@ -24,7 +24,7 @@ $(document).on "turbolinks:load", -> stream_selected = $("#broadcast_video").data('videoType') == 'stream'; if data.streamer_status == 'recording' && data.status == 'active' && stream_selected $("#broadcast_video").html data.video_content - $("#live_take").html data.live_take_content + $("#recording_status").html data.recording_status_content new (Clappr.Player)( <%= "baseUrl: 'http://cdn.clappr.io/latest'," if Rails.env.test? %> @@ -37,7 +37,7 @@ $(document).on "turbolinks:load", -> hlsMinimumDvrSize: 1) if data.streamer_status == "idle" && data.status == "idle" $("#broadcast_video").html data.video_content - $("#live_take").html data.live_take_content + $("#recording_status").html data.recording_status_content showBroadcastRecordings: (data) -> $(".flash-message").html data.flash_content diff --git a/app/assets/javascripts/stream_player.js.erb b/app/assets/javascripts/stream_player.js.erb index af1aee9..b525d33 100644 --- a/app/assets/javascripts/stream_player.js.erb +++ b/app/assets/javascripts/stream_player.js.erb @@ -1,4 +1,7 @@ $(document).on("click", "[data-behavior=play_recording]", function() { + clearPlayingHighlight(); + $(this).parent().parent().addClass('playing-highlight'); + $("#broadcast_video").data('videoType', 'recording'); var playback_url = $(this).attr("data-playback-url") @@ -14,4 +17,11 @@ $(document).on("click", "[data-behavior=play_recording]", function() { }); }); -$(document).on("click", "[data-behavior=play_stream]", function() { $("#broadcast_video").data('videoType', 'stream'); }); \ No newline at end of file +$(document).on("click", "[data-behavior=play_stream]", function() { +// clearPlayingHighlight(); + $("#broadcast_video").data('videoType', 'stream'); +}); + +function clearPlayingHighlight() { + $(".playing-highlight").removeClass("playing-highlight"); +} \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 23289e9..5dc9303 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -467,4 +467,31 @@ 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"); } -} \ No newline at end of file +} + +// Play button SVG +.play-btn { + width: 60%; + height: auto; +} + +.play-btn-svg{ + transition: 0.3s; + stroke:#fedfc2; + opacity: 0; +} + +.play-btn:hover .play-btn-svg { + fill-opacity: 0; + opacity: 1; +} + +// Play button in video thumbnail preview +.play-thumbnail { position: relative; } +.play-thumbnail img { display: block; } +.play-thumbnail .play-btn { position: absolute; bottom:5px; left:10px; } + +// Active recording highlight +.playing-highlight { + background-color: scale-color($primary, $lightness: 80%); +} diff --git a/app/channels/broadcasts_channel.rb b/app/channels/broadcasts_channel.rb index 5109d93..918dfe3 100644 --- a/app/channels/broadcasts_channel.rb +++ b/app/channels/broadcasts_channel.rb @@ -11,7 +11,7 @@ class BroadcastsChannel < ApplicationCable::Channel def self.broadcast_stream_updates(broadcast) status_content = ApplicationController.render partial: "broadcasts/broadcast_status", locals: { broadcast: broadcast } video_content = ApplicationController.render partial: "broadcasts/video", locals: { broadcast: broadcast } - live_take = ApplicationController.render partial: "broadcasts/live_take", locals: { broadcast: broadcast } + recording_status_content = ApplicationController.render partial: "broadcasts/recording_status", locals: { broadcast: broadcast } broadcast_to broadcast, { event: :broadcast_stream_update, @@ -19,7 +19,7 @@ class BroadcastsChannel < ApplicationCable::Channel playback_url: broadcast.stream_playback_url, full_live_stream_playback_url: broadcast.full_live_stream_playback_url, video_content: video_content, - live_take_content: live_take, + recording_status_content: recording_status_content, status_content: status_content, streamer_status: broadcast.streamer_status } diff --git a/app/controllers/account_sessions_controller.rb b/app/controllers/account_sessions_controller.rb index dc9b4ca..3e83657 100644 --- a/app/controllers/account_sessions_controller.rb +++ b/app/controllers/account_sessions_controller.rb @@ -1,4 +1,5 @@ class AccountSessionsController < ApplicationController + skip_before_action :redirect_locked_accounts def update authorize :account_session, :update? session[:active_account] = account_session_params[:account_id] diff --git a/app/controllers/admin/account_locks_controller.rb b/app/controllers/admin/account_locks_controller.rb new file mode 100644 index 0000000..21aa3bd --- /dev/null +++ b/app/controllers/admin/account_locks_controller.rb @@ -0,0 +1,31 @@ +class Admin::AccountLocksController < Admin::ApplicationController + before_action :set_account + + def create + authorize :account_lock, :create? + @account.update(locked: true) + redirect_to admin_accounts_path, notice: 'Account locked' + end + + def destroy + authorize :account_lock, :destroy? + @account.update(locked: false) + redirect_to admin_accounts_path, notice: 'Account unlocked' + end + + private + + def set_account + if params[:account_id].present? + @account = Account.find_by(slug: params[:account_id]) + else + failure_redirect + end + rescue ActiveRecord::RecordNotFound + failure_redirect + end + + def failure_redirect + redirect_to admin_accounts_path, alert: 'Failed to find the account' + end +end \ No newline at end of file diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 6f6b302..ef1dce4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,6 +13,7 @@ class ApplicationController < ActionController::Base include SetCurrentRequestDetails before_action :redirect_accountless + before_action :redirect_locked_accounts private @@ -29,6 +30,12 @@ class ApplicationController < ActionController::Base end end + def redirect_locked_accounts + if Current.user && !Current.user.admin? && Current.account.present? && Current.account.locked? + redirect_to locked_account_path + end + end + def signed_in_as_admin? signed_in? && current_user.admin? end diff --git a/app/controllers/locked_accounts_controller.rb b/app/controllers/locked_accounts_controller.rb new file mode 100644 index 0000000..90a0618 --- /dev/null +++ b/app/controllers/locked_accounts_controller.rb @@ -0,0 +1,10 @@ +class LockedAccountsController < ApplicationController + skip_before_action :redirect_locked_accounts + skip_after_action :verify_policy_scoped + + def index + unless Current.account.locked? + redirect_to projects_path + end + end +end diff --git a/app/helpers/dropzone_helper.rb b/app/helpers/dropzone_helper.rb index 321bac3..0d1aa66 100644 --- a/app/helpers/dropzone_helper.rb +++ b/app/helpers/dropzone_helper.rb @@ -40,4 +40,13 @@ module DropzoneHelper { name: file_info.filename, size: file_info.byte_size, type: file_info.content_type } end.to_json end + + def dropzone_file_size_limit_for(releasable) + case releasable.model_name.param_key + when "material_release", "acquired_media_release" + 1000000 + else + 256 + end + end end diff --git a/app/javascript/packs/active_storage_dropzone.js b/app/javascript/packs/active_storage_dropzone.js index 74b7fbe..e57e99f 100644 --- a/app/javascript/packs/active_storage_dropzone.js +++ b/app/javascript/packs/active_storage_dropzone.js @@ -12,6 +12,7 @@ class ActiveStorageDropzone { var acceptedFiles = $(element).data("accepted-files") || "image/*"; var dictDefaultMessage = $(element).data("placeholder") || "Drop files here"; var submitButton = $($(element).data("submit-button")); + var maxFileSize = $(element).data("max-file-size"); var that = this; this.myDropzone = new this.DropzoneClass(element, { @@ -20,6 +21,7 @@ class ActiveStorageDropzone { acceptedFiles: acceptedFiles, parallelUploads: 30, dictDefaultMessage: dictDefaultMessage, + maxFilesize: maxFileSize, init: function () { this.on("sending", (file, xhr, formData) => { diff --git a/app/jobs/match_appearance_releases_job.rb b/app/jobs/match_appearance_releases_job.rb index 5136170..66c7ee0 100644 --- a/app/jobs/match_appearance_releases_job.rb +++ b/app/jobs/match_appearance_releases_job.rb @@ -15,6 +15,7 @@ class MatchAppearanceReleasesJob < ApplicationJob matches = response.matches || [] key_signed_id_hash = Hash[filtered_attachments_object[:keys].zip(filtered_attachments_object[:signed_ids])] handle_matches matches, project, key_signed_id_hash + handle_unmatches matches, project, key_signed_id_hash matching_request.destroy end @@ -40,6 +41,21 @@ class MatchAppearanceReleasesJob < ApplicationJob end end + def handle_unmatches(matches, project, key_signed_id_hash) + matched_keys = matches.flat_map { |match| match.contracts + match.headshots } + unmatches = key_signed_id_hash.find_all { |key, _| !key.in?(matched_keys) } + + unmatches.each do |key, signed_id| + blob = ActiveStorage::Blob.find_signed signed_id + + if blob.image? + create_release(project, nil, signed_id, nil) + else + create_release(project, signed_id, nil, nil) + end + end + end + def create_release(project, contract, headshot, identifier) random_contract_no = AppearanceRelease.random_contract_number.to_s is_incomplete = contract.nil? || headshot.nil? diff --git a/app/policies/account_lock_policy.rb b/app/policies/account_lock_policy.rb new file mode 100644 index 0000000..f14f1f6 --- /dev/null +++ b/app/policies/account_lock_policy.rb @@ -0,0 +1,9 @@ +class AccountLockPolicy < ApplicationPolicy + def create? + user.admin? + end + + def destroy? + user.admin? + end +end diff --git a/app/views/accounts/_form.html.erb b/app/views/accounts/_form.html.erb index b95def2..d696b97 100644 --- a/app/views/accounts/_form.html.erb +++ b/app/views/accounts/_form.html.erb @@ -6,7 +6,7 @@ <%= form.email_field :email, class: "form-group" %> <%= form.password_field :password %> <%= form.text_field :account_name, label: 'Account Name' %> - <%= form.select :interested_product_name, options_for_select(["I'm interested in all products", "DirectME", "ReleaseME", "CastME", "EditME", "DeliverME", "ExpenseME"]), { label: "What product are you most interested in?" }, { class: "form-control custom-select" } %> + <%= form.select :interested_product_name, options_for_select(["I'm interested in all products", "ME Suite PRO", "DirectME", "ReleaseME", "CastME", "EditME", "DeliverME", "ExpenseME"]), { label: "What product are you most interested in?" }, { class: "form-control custom-select" } %>
<%= form.submit "Start Free Trial", class: "btn btn-block btn-danger font-weight-bold" %>
diff --git a/app/views/accounts/new.html.erb b/app/views/accounts/new.html.erb index 31eea98..cbeca0e 100644 --- a/app/views/accounts/new.html.erb +++ b/app/views/accounts/new.html.erb @@ -4,6 +4,9 @@

Welcome To <%= suite_wordmark("d-inline-block") %>

Sign up for a 14 Day Free Trial which includes full access to the following products. No credit card required!

+
+
<%= image_tag "ME_PRO_black.png", width: "96.66%" %>
+
<%= image_tag "logo_directme.png", width: "90%" %>
<%= image_tag "logo_releaseme.png", width: "90%" %>
diff --git a/app/views/acquired_media_releases/index.html.erb b/app/views/acquired_media_releases/index.html.erb index edd521c..9218015 100644 --- a/app/views/acquired_media_releases/index.html.erb +++ b/app/views/acquired_media_releases/index.html.erb @@ -1,16 +1,19 @@
+ />
<% if policy(AcquiredMediaRelease).new? %> - <%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :acquired_media_release], class: "btn btn-primary mr-2 mb-2" %> +
+ <%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :acquired_media_release], class: "btn btn-primary mr-2 mb-2" %> +
<% end %> <% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).tag_multiple? %> <%= button_to_bulk_tagging(@project) %> <% end %> - + <% if @acquired_media_releases.any? && policy(AcquiredMediaRelease).download_multiple? %> - <%= link_to "Download All", [@project, :contract_downloads, release_type: @acquired_media_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: { + <%= button_to "Download", [@project, :contract_downloads, release_type: @acquired_media_releases.name], id: "download_releases", method: :post, remote: true, class: "btn btn-light border mr-2 mb-2", data: { disable_with: "Please wait..." } %> <% end %> diff --git a/app/views/acquired_media_releases/index.js.erb b/app/views/acquired_media_releases/index.js.erb index 4bc7e72..4ffebf9 100644 --- a/app/views/acquired_media_releases/index.js.erb +++ b/app/views/acquired_media_releases/index.js.erb @@ -1,3 +1,5 @@ $("#acquired_media_releases").html("<%= j render(@acquired_media_releases) %>"); $("form input[type='search']").val("<%= params[:query] %>"); $("#acquired_media_releases_pagination").html("<%= j will_paginate(@acquired_media_releases) %>"); +$("#selected_releases_form").attr('data-releasable-ids', JSON.stringify([])); +$("#total_entries").val(<%= @acquired_media_releases.total_entries %>); \ No newline at end of file diff --git a/app/views/admin/accounts/_account.html.erb b/app/views/admin/accounts/_account.html.erb index e418727..bc761b7 100644 --- a/app/views/admin/accounts/_account.html.erb +++ b/app/views/admin/accounts/_account.html.erb @@ -30,6 +30,11 @@ <%= link_to fa_icon("arrow-right", text: "Overview"), admin_account_path(account), class: "dropdown-item" %> <%= link_to fa_icon("pencil", text: "Edit"), edit_admin_account_path(account), class: "dropdown-item" %> <%= link_to fa_icon("arrow-right", text: "Account Managers"), account_auths_path({ account_id: account.id}), class: "dropdown-item" %> + <% if account.locked? %> + <%= link_to fa_icon("unlock", text: "Unlock Account"), [:admin, account, :lock], method: :delete, class: "dropdown-item" %> + <% else %> + <%= link_to fa_icon("lock", text: "Lock Account"), [:admin, account, :lock], method: :post, class: "dropdown-item" %> + <% end %>
diff --git a/app/views/broadcasts/_broadcast_recordings.html.erb b/app/views/broadcasts/_broadcast_recordings.html.erb index e764e6e..e4e6ec5 100644 --- a/app/views/broadcasts/_broadcast_recordings.html.erb +++ b/app/views/broadcasts/_broadcast_recordings.html.erb @@ -1,29 +1,31 @@ -<% if recordings.present? %> -
- <% recordings.each do |recording| %> -
-
- <% if policy(BroadcastRecording).update? %> - <%= link_to fa_icon("#{recording.starred ? 'star' : 'star-o'} fw"), [broadcast.project, broadcast, recording, :broadcast_recording_starrings], method: :post, class: "text-warning mr-3", remote: true %> - <% end %> - <%= image_tag(recording.thumbnail_url, class: 'img-thumbnail img-fluid max-w-75', data: { behavior: "play_recording", playback_url: recording.playback_url, id: dom_id(recording) }) %> -
- <% if policy(BroadcastRecording).edit? %> - <%= link_to fa_icon('edit'), [:edit, broadcast.project, broadcast, recording], remote: true %> - <% end %> - <%= link_to(fa_icon('download'), recording.download_url, target: "_blank") %> -
-
-
-
<%= recording.name %>
-

<%= recording.description %>

-
+
    + <% recordings.each do |recording| %> +
  • + <% if policy(BroadcastRecording).update? %> + <%= link_to fa_icon("#{recording.starred ? 'star' : 'star-o'} fw"), [broadcast.project, broadcast, recording, :broadcast_recording_starrings], method: :post, class: "text-warning mr-2", remote: true %> + <% end %> + +
    + <%= image_tag(recording.thumbnail_url, class: 'mr-2', size: "64x64") %> + <%= content_tag :div, class: "play-btn", data: { behavior: "play_recording", playback_url: recording.playback_url, id: dom_id(recording) } do %> + <%= render "broadcasts/play_button_svg" %> + <% end %>
    - <% end %> -
-
- <%= will_paginate(recordings, params: {controller: "broadcasts", action: "show", project_id: broadcast.project_id, id: broadcast.id, page: params[:page], active_tab: 'recordings'}) %> -
-<% else %> -

Recording of the live stream will appear here.

-<% end %> + +
+
<%= recording.name %>
+ <%= recording.description %> +
+ + <% 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") %> + + <% end %> + + +
+ <%= will_paginate(recordings, params: {controller: "broadcasts", action: "show", project_id: broadcast.project_id, id: broadcast.id, page: params[:page], active_tab: 'recordings'}) %> +
diff --git a/app/views/broadcasts/_broadcast_status.html.erb b/app/views/broadcasts/_broadcast_status.html.erb index 9e34bfa..20f60f1 100644 --- a/app/views/broadcasts/_broadcast_status.html.erb +++ b/app/views/broadcasts/_broadcast_status.html.erb @@ -1,13 +1,9 @@ <% if broadcast.streamer_connected? || (broadcast.streamer_recording? && !broadcast.active?) %>

Live stream has connected successfully and will be available soon.

-
Connected
<% elsif broadcast.streamer_recording? && broadcast.active? %>

Live stream has begun, click play to watch it.

-
Live
<% elsif broadcast.streamer_disconnected? %>

Live stream got disconnected.

-
Disconnected
<% elsif (broadcast.idle? && broadcast.streamer_idle?) || (broadcast.created? && broadcast.streamer_idle?) %>

Live stream is waiting to begin.

-
Idle
<% end %> diff --git a/app/views/broadcasts/_files_section.html.erb b/app/views/broadcasts/_files_section.html.erb index 86865c8..0790531 100644 --- a/app/views/broadcasts/_files_section.html.erb +++ b/app/views/broadcasts/_files_section.html.erb @@ -1,4 +1,4 @@ -
+
<% if controller.class.module_parent.to_s == "Public" %> <%= render partial: "public/broadcasts/file_form", locals: { model: [broadcast], token: broadcast.token } %> <% else %> diff --git a/app/views/broadcasts/_live_take.html.erb b/app/views/broadcasts/_live_take.html.erb index cb09912..1a795bf 100644 --- a/app/views/broadcasts/_live_take.html.erb +++ b/app/views/broadcasts/_live_take.html.erb @@ -1,12 +1,35 @@ -
-
-
-
<%= broadcast.name %>
- Created - <%= time_ago_in_words(broadcast.created_at) + " ago" %> -
-
+<% # TODO: Refactor this %> +<% if params[:director_mode] %> + <% if controller.class.module_parent.to_s == "Public" %> + <% live_take_url = url_for(params.permit!.merge(director_mode: true, token: broadcast.token)) %> + <% else %> + <% live_take_url = url_for(params.permit!.merge(director_mode: true, id: broadcast.id)) %> + <% end %> +
+<% else %> + <% if controller.class.module_parent.to_s == "Public" %> + <% live_take_url = url_for(params.permit!.merge(token: broadcast.token).except(:director_mode)) %> + <% else %> + <% live_take_url = url_for(params.permit!.merge(id: broadcast.id).except(:director_mode)) %> + <% end %> +<% end %> + +
+
+ <%= render 'broadcasts/recording_status', broadcast: broadcast %> +
+ +
+ <%= image_tag "live_icon.png", class: "mr-2", width: 64, alt: "Live stream thumbnail" %> + <%= link_to live_take_url, class: "play-btn", data: { behavior: "play_stream" } do %> + <%= render "broadcasts/play_button_svg" %> + <% end %> +
+ +
+
<%= broadcast.name %>
+ <%= render partial: 'broadcasts/broadcast_status', locals: { broadcast: broadcast } %> -
+
- diff --git a/app/views/broadcasts/_play_button_svg.html.erb b/app/views/broadcasts/_play_button_svg.html.erb new file mode 100644 index 0000000..6e9cce4 --- /dev/null +++ b/app/views/broadcasts/_play_button_svg.html.erb @@ -0,0 +1,3 @@ + + + diff --git a/app/views/broadcasts/_recording_status.html.erb b/app/views/broadcasts/_recording_status.html.erb new file mode 100644 index 0000000..4abe96c --- /dev/null +++ b/app/views/broadcasts/_recording_status.html.erb @@ -0,0 +1 @@ +<%= fa_icon "circle fw", class: class_string('mr-2', 'text-danger' => broadcast.streamer_recording? && broadcast.active?) %> diff --git a/app/views/broadcasts/show.html.erb b/app/views/broadcasts/show.html.erb index 8d79161..b987192 100644 --- a/app/views/broadcasts/show.html.erb +++ b/app/views/broadcasts/show.html.erb @@ -13,12 +13,18 @@ <% end %> <% end %> + + <% content_for :header do %>
<% end %>
-
+
<%= product_wordmark(:direct_me, class: 'navbar-brand text-white') %>
-
- <% unless controller.class.module_parent.to_s == "Public" %> - <% if @multi_view_broadcasts.present? %> - <% tokens = @multi_view_broadcasts.map(&:token) %> -
- - -