Compare commits

..

5 Commits

100 changed files with 503 additions and 1533 deletions

View File

@@ -1,13 +1,8 @@
$(document).on "turbolinks:load", -> $(document).on "turbolinks:load", ->
# Only connect if a broadcast-token meta tag is present subscribeToBroadcast = (broadcastToken) -> App.cable.subscriptions.create { channel: "BroadcastsChannel", token: broadcastToken },
broadcast_meta = document.querySelector("meta[name=broadcast-token]")
return unless broadcast_meta
broadcastToken = broadcast_meta.getAttribute("content")
App.public = App.cable.subscriptions.create { channel: "BroadcastsChannel", token: broadcastToken },
connected: -> connected: ->
# Called when the subscription is ready for use on the server # Called when the subscription is ready for use on the server
console.info "Subscribed to channel for broadcast:#{broadcastToken}"
disconnected: -> disconnected: ->
# Called when the subscription has been terminated by the server # Called when the subscription has been terminated by the server
@@ -17,6 +12,7 @@ $(document).on "turbolinks:load", ->
switch data.event switch data.event
when "broadcast_stream_update" then @refreshBroadcastVideo(data) when "broadcast_stream_update" then @refreshBroadcastVideo(data)
when "stream_recording_ready" then @showBroadcastRecordings(data) when "stream_recording_ready" then @showBroadcastRecordings(data)
when "file_upload_update" then @refreshBroadcastFilesTab(data)
refreshBroadcastVideo: (data) -> refreshBroadcastVideo: (data) ->
$("#broadcast_updates").html data.status_content $("#broadcast_updates").html data.status_content
@@ -37,3 +33,12 @@ $(document).on "turbolinks:load", ->
$(".flash-message").html data.flash_content $(".flash-message").html data.flash_content
$("#broadcast_recordings").html data.recordings_content $("#broadcast_recordings").html data.recordings_content
$("#broadcast_recordings_nav").html data.recordings_nav_content $("#broadcast_recordings_nav").html data.recordings_nav_content
refreshBroadcastFilesTab: (data) ->
$("#broadcast_file_list_#{data.broadcast_token}").html data.files_content
$("#broadcast_files_pagination_#{data.broadcast_token}").html data.pagination_content
# Create a channel subscription for every broadcast included in the meta tags
get_token = (meta) -> meta.getAttribute("content")
broadcast_tokens = (get_token broadcast_meta for broadcast_meta in document.querySelectorAll("meta[name=broadcast-token]"))
subscribeToBroadcast token for token in broadcast_tokens

View File

@@ -16,6 +16,7 @@ $(document).on "turbolinks:load", ->
switch data.event switch data.event
when "video_status_update" then @showVideoStatusUpdate(data.content) when "video_status_update" then @showVideoStatusUpdate(data.content)
when "download_status_update" then @showDownloadStatusUpdate(data.content) when "download_status_update" then @showDownloadStatusUpdate(data.content)
when "conference_recording_ready" then @showDownloadStatusUpdate(data.content)
showVideoStatusUpdate: (content) -> showVideoStatusUpdate: (content) ->
$("[data-ujs-target='video-analysis-msg']").replaceWith content $("[data-ujs-target='video-analysis-msg']").replaceWith content

View File

@@ -14,7 +14,6 @@ $red: #F9002B;
$green: #51B61B; $green: #51B61B;
$teal: #32C498; $teal: #32C498;
$purple: #5139EE; $purple: #5139EE;
$yellow: #F9BE1B;
$dark: $gray-900; $dark: $gray-900;
$success: $teal; $success: $teal;
$link-color: $body-color; $link-color: $body-color;

View File

@@ -32,14 +32,14 @@
&.release-me { &.release-me {
span:last-child { span:last-child {
background-color: $teal; background-color: $teal;
color: $white; color: $body-color;
} }
} }
&.direct-me { &.direct-me {
span:last-child { span:last-child {
background-color: $green; background-color: $green;
color: $white; color: $body-color;
} }
} }
@@ -53,14 +53,7 @@
&.deliver-me { &.deliver-me {
span:last-child { span:last-child {
background-color: $purple; background-color: $purple;
color: $white; color: white;
}
}
&.task-me {
span:last-child {
background-color: $yellow;
color: $white;
} }
} }

View File

@@ -34,4 +34,15 @@ class BroadcastsChannel < ApplicationCable::Channel
recordings_content: recordings_content, recordings_content: recordings_content,
recordings_nav_content: recordings_nav_content recordings_nav_content: recordings_nav_content
end end
def self.broadcast_file_upload_updates(broadcast, files, pagination_content)
files_content = ApplicationController.render partial: "broadcasts/file", collection: files
broadcast_to broadcast, {
event: :file_upload_update,
broadcast_token: broadcast.token,
files_content: files_content,
pagination_content: pagination_content
}
end
end end

View File

@@ -25,4 +25,12 @@ class ProjectsChannel < ApplicationCable::Channel
content = ApplicationController.render partial: "application/flash", locals: { flash: flash } content = ApplicationController.render partial: "application/flash", locals: { flash: flash }
broadcast_to download.project, event: :download_status_update, content: content broadcast_to download.project, event: :download_status_update, content: content
end end
def self.conference_recording_ready(project, recording)
link = ApplicationController.helpers.link_to('Download here.', recording.service_url, target: '_blank', class: 'alert-link')
notification = "A recording of your video conference is now available. #{link}"
flash = OpenStruct.new(notice: notification)
content = ApplicationController.render partial: 'application/flash', locals: { flash: flash }
broadcast_to project, event: :conference_recording_ready, content: content
end
end end

View File

@@ -1,36 +0,0 @@
class Admin::TaskRequestsController < Admin::ApplicationController
before_action :set_task_request, only: [:edit, :update, :show]
def index
@task_requests = task_requests.order_by_recent.paginate(page: params[:page])
end
def edit
end
def show
@files = @task_request.files.paginate(page: params[:page])
end
def update
if @task_request.update(task_request_params)
redirect_to [:admin, :task_requests], notice: t(".notice")
else
render :edit
end
end
private
def task_request_params
params.require(:task_request).permit(:status, :deliverable_url)
end
def task_requests
policy_scope TaskRequest
end
def set_task_request
@task_request = authorize policy_scope(TaskRequest).find(params[:id])
end
end

View File

@@ -24,18 +24,21 @@ class BroadcastsController < ApplicationController
end end
end end
def update
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
end
def show def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting] @conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application' render layout: 'application'
end end
def update
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab], page: params[:page], active_files_tab: params[:active_files_tab] })
BroadcastsChannel.broadcast_file_upload_updates(@broadcast, @files, pagination_content)
end
def destroy def destroy
if @broadcast.destroy if @broadcast.destroy
redirect_to [@project, :broadcasts], alert: t(".alert") redirect_to [@project, :broadcasts], alert: t(".alert")
@@ -68,7 +71,10 @@ class BroadcastsController < ApplicationController
def set_multi_view_broadcasts def set_multi_view_broadcasts
authorized_broadcasts = authorize policy_scope(Broadcast).where(id: params[:multi_view_ids]).order_by_recent authorized_broadcasts = authorize policy_scope(Broadcast).where(id: params[:multi_view_ids]).order_by_recent
@multi_view_broadcasts = authorized_broadcasts.map { |b| MultiViewBroadcast.new(b, params[:multi_view_ids]) } @multi_view_broadcasts = authorized_broadcasts.map do |b|
files_page = params[:files_page] if params[:active_files_tab] == b.token
MultiViewBroadcast.new(b, params[:multi_view_ids], files_page)
end
end end
def filtered_broadcasts def filtered_broadcasts
@@ -90,17 +96,26 @@ class BroadcastsController < ApplicationController
delegate_missing_to :@broadcast delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_ids) def initialize(broadcast, multi_view_ids, paginate_page)
@broadcast = broadcast @broadcast = broadcast
@multi_view_ids = multi_view_ids @multi_view_ids = multi_view_ids
@paginate_page = paginate_page
end end
def url def url
project_broadcast_path(@broadcast.project, @broadcast, multi_view_ids: @multi_view_ids, locale: I18n.locale) project_broadcast_path(@broadcast.project, @broadcast, multi_view_ids: @multi_view_ids, locale: I18n.locale)
end end
def files
@broadcast.files.order("created_at DESC").paginate(page: @paginate_page)
end
def uid def uid
id id
end end
def self.model_name
Broadcast.model_name
end
end end
end end

View File

@@ -68,7 +68,8 @@ class LocationReleasesController < ApplicationController
:territory_id, :territory_text, :territory_id, :territory_text,
:term_id, :term_text, :term_id, :term_text,
:restriction_id, :restriction_text, :restriction_id, :restriction_text,
:filming_started_on, :filming_ended_on :filming_started_on, :filming_ended_on,
:filming_hours
) )
end end

View File

@@ -18,6 +18,7 @@ class PasswordResetsController < ApplicationController
end end
def edit def edit
redirect_to new_session_path, notice: t(".notice") if @user.nil?
end end
def update def update

View File

@@ -6,7 +6,7 @@ class Public::BroadcastsController < Public::BaseController
@conference_url = broadcast_zoom_meeting_url(@broadcast.token) @conference_url = broadcast_zoom_meeting_url(@broadcast.token)
@multi_view_broadcasts = multi_view_broadcasts @multi_view_broadcasts = multi_view_broadcasts
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page]) @recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page]) @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render 'broadcasts/show' render 'broadcasts/show'
end end
@@ -14,6 +14,9 @@ class Public::BroadcastsController < Public::BaseController
def update def update
@broadcast.update(broadcast_params) @broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1) @files = @broadcast.files.order("created_at DESC").paginate(page: 1)
pagination_content = ApplicationController.render html: helpers.will_paginate(@files,params: { active_tab: params[:active_tab], page: params[:page], active_files_tab: params[:active_files_tab] })
BroadcastsChannel.broadcast_file_upload_updates(@broadcast, @files, pagination_content)
end end
private private
@@ -26,7 +29,10 @@ class Public::BroadcastsController < Public::BaseController
Broadcast. Broadcast.
where(token: params[:multi_view_tokens]). where(token: params[:multi_view_tokens]).
order_by_recent. order_by_recent.
map { |b| MultiViewBroadcast.new(b, params[:multi_view_tokens]) } map do |b|
files_page = params[:files_page] if params[:active_files_tab] == b.token
MultiViewBroadcast.new(b, params[:multi_view_tokens], files_page)
end
end end
def set_broadcast def set_broadcast
@@ -38,17 +44,26 @@ class Public::BroadcastsController < Public::BaseController
delegate_missing_to :@broadcast delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_tokens) def initialize(broadcast, multi_view_tokens, paginate_page)
@broadcast = broadcast @broadcast = broadcast
@multi_view_tokens = multi_view_tokens @multi_view_tokens = multi_view_tokens
@paginate_page = paginate_page
end end
def url def url
broadcast_url(uid, multi_view_tokens: @multi_view_tokens, host: AppHost.new.domain_with_port, locale: I18n.locale) broadcast_url(uid, multi_view_tokens: @multi_view_tokens, host: AppHost.new.domain_with_port, locale: I18n.locale)
end end
def files
@broadcast.files.order("created_at DESC").paginate(page: @paginate_page)
end
def uid def uid
token token
end end
def self.model_name
Broadcast.model_name
end
end end
end end

View File

@@ -63,7 +63,8 @@ class Public::LocationReleasesController < Public::BaseController
:person_address_zip, :person_address_zip,
:person_address_country, :person_address_country,
:signature_base64, :signature_base64,
:locale, :contract_template, :filming_started_on, :filming_ended_on :locale, :contract_template, :filming_started_on, :filming_ended_on,
:filming_hours
) )
end end

View File

@@ -1,76 +0,0 @@
class TaskRequestsController < ApplicationController
layout "project"
before_action :set_project
before_action :build_task_request, only: [:new, :create]
before_action :set_task_request, only: [:show, :edit, :update, :cancel]
def index
@task_requests = task_requests.order_by_recent.paginate(page: params[:page])
end
def new
end
def create
@task_request.attributes = task_request_params_with_email
if @task_request.save
log_create_analytics
taskme_url = url_for([:admin, @task_request])
SubmitHubspotTaskRequestFormJob.perform_later(@task_request.user_email, taskme_url)
else
render :new
end
end
def show
@files = @task_request.files.paginate(page: params[:page])
end
def edit
end
def update
if @task_request.update(task_request_params)
redirect_to [@project, :task_requests], notice: t(".notice")
else
render :edit
end
end
def cancel
@task_request.cancelled!
redirect_to [@project, :task_requests], notice: t(".notice")
end
private
def task_request_params
params.require(:task_request).permit(:description, :deadline, :time_allowed, :additional_notes, files: [])
end
def task_request_params_with_email
task_request_params.merge(user_email: Current.user.email)
end
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def set_task_request
@task_request = authorize policy_scope(TaskRequest).find(params[:id])
end
def task_requests
authorize policy_scope(@project.task_requests)
end
def build_task_request
@task_request = authorize @project.task_requests.build
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_task_request, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

@@ -1,19 +0,0 @@
class TasksController < ApplicationController
before_action :set_project
include ProjectLayout
def index
@tasks = task_requests.completed.order_by_recent.paginate(page: params[:page])
end
private
def set_project
@project = policy_scope(Project).find(params[:project_id])
end
def task_requests
authorize policy_scope(@project.task_requests)
end
end

View File

@@ -13,8 +13,11 @@ class ZoomNotificationsController < ApplicationController
@zoom_meeting.started! @zoom_meeting.started!
when 'meeting.ended' when 'meeting.ended'
@zoom_meeting.ended! @zoom_meeting.ended!
when 'recording.completed'
recording = notification.dig(:payload, :object, :recording_files).first
AttachRecordingToZoomMeetingJob.perform_later(@zoom_meeting, recording, notification['download_token'])
else else
Rails.logger.info notification_type Rails.logger.info notification_event
Rails.logger.info notification Rails.logger.info notification
end end
@@ -23,16 +26,20 @@ class ZoomNotificationsController < ApplicationController
private private
def notification
params.to_unsafe_h
end
def notification_event def notification_event
params.dig(:event) notification.dig(:event)
end end
def notification_meeting_id def notification_meeting_id
params.dig(:payload, :object, :id) notification.dig(:payload, :object, :id)
end end
def notification_host_id def notification_host_id
params.dig(:payload, :object, :host_id) notification.dig(:payload, :object, :host_id)
end end
def set_zoom_meeting def set_zoom_meeting

View File

@@ -41,7 +41,7 @@ module ContactInfoHelper
end end
def email_abbr(email) def email_abbr(email)
content_tag(:abbr, "E: ", title: "Email") + email content_tag(:abbr, "E: ", title: "Email") + mail_to(email)
end end
def phone_abbr(phone) def phone_abbr(phone)

View File

@@ -7,8 +7,8 @@ module DescriptionListHelper
safe_join(tags) safe_join(tags)
end end
def description_list_pair_for(record, attribute, append: nil, custom_label: nil) def description_list_pair_for(record, attribute, append: nil)
term = custom_label.nil? ? translation_for(record, attribute) : custom_label term = translation_for(record, attribute)
definition = record.send(attribute) definition = record.send(attribute)
description_list_pair(term, definition, append: append) description_list_pair(term, definition, append: append)

View File

@@ -7,8 +7,6 @@ module DropzoneHelper
"To Add Audio Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files" "To Add Audio Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "directory" when "directory"
"To Add Files to the Folder:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files" "To Add Files to the Folder:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "task_request"
"To Add Files for the Task:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
else else
"To Add Photos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera" "To Add Photos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera"
end end

View File

@@ -1,6 +1,5 @@
$(document).on("turbolinks:load", () => { $(document).on("turbolinks:load", () => {
$('.datepicker-control').datepicker({ $('.datepicker-control').datepicker({
format: "yyyy-mm-dd", format: "yyyy-mm-dd"
todayHighlight: true
}); });
}); });

View File

@@ -0,0 +1,26 @@
require 'zoom_gateway'
class AttachRecordingToZoomMeetingJob < ApplicationJob
queue_as :default
def perform(zoom_meeting, recording_hash, download_token)
download_url = "#{recording_hash['download_url']}?access_token=#{download_token}"
file = URI.open(download_url)
if zoom_meeting.recording.attach(io: file, filename: file_name(zoom_meeting, recording_hash), content_type: 'video/mp4')
# Temorarily disabling notifications
# if zoom_meeting.project.present?
# ProjectsChannel.conference_recording_ready(zoom_meeting.project, zoom_meeting.recording)
# end
gateway = ZoomGateway.new
gateway.delete_recording(zoom_meeting.api_meeting_id, recording_hash['id'])
end
end
private
def file_name(zoom_meeting, recording_hash)
start = recording_hash['recording_start'].to_datetime
prefix = zoom_meeting.project.present? ? "#{zoom_meeting.project.name}_" : ''
"#{prefix}video_conference_date#{start.strftime("%Y-%m-%d")}_Time_#{start.strftime("%T")}.mp4"
end
end

View File

@@ -1,18 +0,0 @@
class SubmitHubspotTaskRequestFormJob < ApplicationJob
queue_as :default
def perform(user_email, taskme_url)
hubspot_task_request_form_guid = ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"]
return unless hubspot_task_request_form_guid.present?
submission_params = {
email: user_email,
taskme_url: taskme_url
}
form = Hubspot::Form.new("guid" => hubspot_task_request_form_guid)
is_form_sumitted = form.submit(submission_params)
raise StandardError.new "Failed to submit the task request hubspot form data: #{is_form_sumitted}" unless is_form_sumitted
end
end

View File

@@ -54,7 +54,7 @@ class Account < ApplicationRecord
Download.where(project: projects), Download.where(project: projects),
User.joins(:project_memberships).where(project_memberships: { project: projects }), User.joins(:project_memberships).where(project_memberships: { project: projects }),
Broadcast.where(project: projects), Broadcast.where(project: projects),
TaskRequest.where(project: projects), ZoomMeeting.where(project: projects),
self self
])).sum(:byte_size).to_f ])).sum(:byte_size).to_f
end end
@@ -79,10 +79,6 @@ class Account < ApplicationRecord
plan_uid.to_s == "me_suite" || plan_uid.to_s == "releaseme" plan_uid.to_s == "me_suite" || plan_uid.to_s == "releaseme"
end end
def taskme_enabled?
plan_uid.to_s == "me_suite" || plan_uid.to_s == "taskme"
end
def plan_name def plan_name
case plan_uid.to_s case plan_uid.to_s
when "deliverme" when "deliverme"
@@ -91,8 +87,6 @@ class Account < ApplicationRecord
"DirectME" "DirectME"
when "releaseme" when "releaseme"
"ReleaseME" "ReleaseME"
when "taskme"
"TaskME"
when "me_suite" when "me_suite"
"ME Suite" "ME Suite"
end end

View File

@@ -7,8 +7,6 @@ class Broadcast < ApplicationRecord
has_secure_token has_secure_token
scope :order_by_recent, -> { order(created_at: :desc) }
validates :name, presence: true validates :name, presence: true
enum status: [:created, :active, :idle] enum status: [:created, :active, :idle]

View File

@@ -1,8 +1,6 @@
class BroadcastRecording < ApplicationRecord class BroadcastRecording < ApplicationRecord
belongs_to :broadcast belongs_to :broadcast
scope :order_by_recent, -> { order(created_at: :desc) }
delegate :name, to: :broadcast, prefix: :broadcast delegate :name, to: :broadcast, prefix: :broadcast
validates :asset_uid, uniqueness: true validates :asset_uid, uniqueness: true

View File

@@ -6,8 +6,6 @@ module Releasable
included do included do
belongs_to :project, touch: true belongs_to :project, touch: true
belongs_to :contract_template, optional: true belongs_to :contract_template, optional: true
scope :order_by_recent, -> { order(created_at: :desc) }
end end
def release_number def release_number

View File

@@ -5,7 +5,7 @@ class HeadshotCollection
def self.for_project(project) def self.for_project(project)
appearance_releases_with_photo = project.appearance_releases.with_person_photo appearance_releases_with_photo = project.appearance_releases.with_person_photo
new(project.id, appearance_releases_with_photo + project.talent_releases) new(project.headshot_collection_uid, appearance_releases_with_photo + project.talent_releases)
end end
def initialize(collection_uid, releasables) def initialize(collection_uid, releasables)
@@ -23,7 +23,7 @@ class HeadshotCollection
collection_uid: collection_uid.to_s, collection_uid: collection_uid.to_s,
bucket_name: aws_bucket_name, bucket_name: aws_bucket_name,
ids_to_images: map_ids_to_images, ids_to_images: map_ids_to_images,
} }.reject { |_, v| v.blank? }
end end
private private

View File

@@ -4,6 +4,4 @@ class Note < ApplicationRecord
belongs_to :notable, polymorphic: true belongs_to :notable, polymorphic: true
validates :content, presence: true validates :content, presence: true
scope :order_by_recent, -> { order(created_at: :desc) }
end end

View File

@@ -22,7 +22,6 @@ class Project < ApplicationRecord
has_many :downloads, dependent: :destroy has_many :downloads, dependent: :destroy
has_many :broadcasts, dependent: :destroy has_many :broadcasts, dependent: :destroy
has_many :zoom_meetings, dependent: :destroy has_many :zoom_meetings, dependent: :destroy
has_many :task_requests, dependent: :destroy
accepts_nested_attributes_for :project_memberships accepts_nested_attributes_for :project_memberships

View File

@@ -1,8 +0,0 @@
class TaskRequest < ApplicationRecord
belongs_to :project
has_many_attached :files
enum status: [:pending, :completed, :cancelled]
scope :order_by_recent, -> { order(created_at: :desc) }
end

View File

@@ -4,6 +4,9 @@ class ZoomMeeting < ApplicationRecord
belongs_to :project, optional: true belongs_to :project, optional: true
belongs_to :zoom_user belongs_to :zoom_user
has_one_attached :recording
validates :recording, content_type: ['video/mp4']
enum status: [:created, :started, :ended] enum status: [:created, :started, :ended]
after_create :create_api_meeting, if: -> { api_meeting_id.nil? } after_create :create_api_meeting, if: -> { api_meeting_id.nil? }

View File

@@ -1,3 +1,4 @@
require 'zoom_gateway'
class ZoomUser < ApplicationRecord class ZoomUser < ApplicationRecord
has_many :zoom_meetings, dependent: :nullify has_many :zoom_meetings, dependent: :nullify

View File

@@ -3,10 +3,8 @@ class ContractTemplatePolicy < ApplicationPolicy
def resolve def resolve
if user.account_manager? if user.account_manager?
scope.left_outer_joins(:project).where(projects: {account: user.account}) scope.left_outer_joins(:project).where(projects: {account: user.account})
elsif user.manager?
scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
else else
scope.none scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
end end
end end
end end
@@ -14,8 +12,9 @@ class ContractTemplatePolicy < ApplicationPolicy
def create? def create?
user.manager? || user.account_manager? user.manager? || user.account_manager?
end end
def show? def show?
create? true
end end
def destroy? def destroy?

View File

@@ -36,8 +36,4 @@ class ProjectPolicy < ApplicationPolicy
def show_downloads? def show_downloads?
show? show?
end end
def show_task_results?
show?
end
end end

View File

@@ -1,29 +0,0 @@
class TaskRequestPolicy < ApplicationPolicy
def index?
true
end
def show?
true
end
def create?
true
end
def destroy?
true
end
def update?
true
end
def cancel?
true
end
def open_deliverable?
true
end
end

View File

@@ -152,24 +152,6 @@ class Analytics
end end
end end
def track_create_task_request(user_agent:, user_ip:)
if analytics_enabled?
identify
track(
{
user_id: user.id,
event: "Task request created",
properties: {
account: account.try(:name),
account_id: account.try(:id),
user_agent: user_agent,
ip: user_ip,
},
}
)
end
end
private private
attr_reader :user, :account, :backend attr_reader :user, :account, :backend

View File

@@ -7,9 +7,6 @@
<li class="nav-item"> <li class="nav-item">
<%= link_to fa_icon("users fw", text: "Users"), [:admin, :users], class: class_string("nav-link", "active" => controller_name == "users") %> <%= link_to fa_icon("users fw", text: "Users"), [:admin, :users], class: class_string("nav-link", "active" => controller_name == "users") %>
</li> </li>
<li class="nav-item">
<%= link_to fa_icon("tasks fw", text: "Task Requests"), [:admin, :task_requests], class: class_string("nav-link", "active" => controller_name == "task_requests") %>
</li>
<li class="nav-item"> <li class="nav-item">
<%= link_to fa_icon("bug fw", text: "Errors"), "https://sentry.io/bigmedia/", class: "nav-link", target: :_blank %> <%= link_to fa_icon("bug fw", text: "Errors"), "https://sentry.io/bigmedia/", class: "nav-link", target: :_blank %>
</li> </li>

View File

@@ -1,13 +0,0 @@
<%= errors_summary_for task_request %>
<%= bootstrap_form_with model: model, local: true do |form| %>
<%= form.select :status, options_for_select(TaskRequest.statuses.except(:cancelled).keys, task_request.status), {}, class: "form-control custom-select" %>
<%= form.text_field :deliverable_url %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [:admin, :task_requests], class: "col-3 text-reset" %>
<div class="col-9">
<%= form.submit class: class_string("btn btn-block", ["btn-success", "btn-primary"] => task_request.new_record?), data: { disable_with: t("shared.disable_with") } %>
</div>
</div>
<% end %>

View File

@@ -1,32 +0,0 @@
<tr id="<%= dom_id(task_request) %>">
<td>
<%= task_request.id %>
</td>
<td>
<%= task_request.project.account.name %>
</td>
<td>
<%= task_request.project.name %>
</td>
<td>
<%= task_request.created_at.strftime("%D") %>
</td>
<td>
<%= task_request.deadline.try(:strftime, '%D') %>
</td>
<td>
<%= task_request.time_allowed %>
</td>
<td>
<%= task_request.status.titleize %>
</td>
<td class="text-right">
<div class="btn-group">
<%= button_tag "Manage", class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
<div class="dropdown-menu dropdown-menu-right">
<%= link_to fa_icon("tasks", text: "View"), [:admin, task_request], class: "dropdown-item", target: '_blank' %>
<%= link_to fa_icon("pencil", text: "Edit"), [:edit, :admin, task_request], class: "dropdown-item" %>
</div>
</div>
</td>
</tr>

View File

@@ -1,6 +0,0 @@
<div class="card shadow-sm">
<%= card_header text: "Edit Task Request", close_action_path: [:admin, :task_requests] %>
<div class="card-body">
<%= render "form", model: [:admin, @task_request], task_request: @task_request %>
</div>
</div>

View File

@@ -1,25 +0,0 @@
<div class="border bg-white rounded shadow-sm pb-3 table-responsive">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Task ID</th>
<th>Account Name</th>
<th>Project Name</th>
<th>Created On</th>
<th>Deadline</th>
<th>Time Allowed</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody id="users">
<% if @task_requests.any? %>
<%= render @task_requests %>
<% else %>
<tr>
<td colspan="20" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
</div>

View File

@@ -1,49 +0,0 @@
<div class="card shadow-sm">
<%= card_header text: "Task Details", close_action_path: [:admin, :task_requests] %>
<div class="card-body">
<div class="row">
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request.project.account, :name, custom_label: "Account Name", append: ":" %>
<%= description_list_pair_for @task_request.project, :name, custom_label: "Project Name", append: ":" %>
<%= description_list_pair_for @task_request, :created_at, append: ":" %>
<%= description_list_pair_for @task_request, :user_email, append: ":" %>
<%= description_list_pair_for @task_request, :status, append: ":" %>
</dl>
</div>
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :deadline, append: ":" %>
<%= description_list_pair_for @task_request, :time_allowed, append: ":" %>
<%= description_list_pair_for @task_request, :description, append: ":" %>
<%= description_list_pair_for @task_request, :additional_notes, append: ":" %>
</dl>
</div>
<div class="col-md-12">
<h2 class="h6 mt-3">Files:</h2>
<div class="pt-2 mx-n3">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Filename</th>
<th></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @files.any? %>
<%= render partial: "task_requests/file", collection: @files %>
<% else %>
<tr>
<td colspan="12" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="mt-4" id="task_requests_pagiantion">
<%= will_paginate @files %>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<td data-behavior="select"><%= check_box_tag "appearance_release_ids[]", appearance_release.id, false %></td> <td data-behavior="select"><%= check_box_tag "appearance_release_ids[]", appearance_release.id, false %></td>
<td> <td>
<% if appearance_release.photo.attached? %> <% if appearance_release.photo.attached? %>
<%= image_tag medium_variant(appearance_release.photo), class: "img-fluid" %> <%= image_tag medium_variant(appearance_release.photo) %>
<% else %> <% else %>
<%= fa_icon("warning", text: t(".no_photos"), class: "text-danger") %> <%= fa_icon("warning", text: t(".no_photos"), class: "text-danger") %>
<% end %> <% end %>
@@ -11,10 +11,11 @@
<%= appearance_release.name %> <%= appearance_release.name %>
</td> </td>
<td> <td>
<%= number_to_phone appearance_release.person_phone %> <%= contact_info(
</td> address: appearance_release.person_address,
<td> phone: appearance_release.person_phone,
<%= mail_to appearance_release.person_email %> email: appearance_release.person_email
) %>
</td> </td>
<td> <td>
<%= notes_preview appearance_release.notes.order_by_recent %> <%= notes_preview appearance_release.notes.order_by_recent %>

View File

@@ -52,7 +52,7 @@
<% end %> <% end %>
<div class="d-inline-block"> <div class="d-inline-block">
<%= form.hidden_field :person_photo, value: form.object.person_photo.signed_id if appearance_release.person_photo.attached?%> <%= form.hidden_field :person_photo, value: form.object.person_photo.signed_id if appearance_release.person_photo.attached?%>
<%= form.file_field :person_photo, wrapper_class: "required", hide_label: true, required: !appearance_release.person_photo.attached?, data: { ujs_target: "person-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %> <%= form.file_field :person_photo, hide_label: true, data: { ujs_target: "person-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %>
</div> </div>
</div> </div>

View File

@@ -46,8 +46,7 @@
<th data-behavior="all-selectable"><%= check_box_tag "appearance_release_ids[]", false, false %></th> <th data-behavior="all-selectable"><%= check_box_tag "appearance_release_ids[]", false, false %></th>
<th></th> <th></th>
<th><%= AppearanceRelease.human_attribute_name(:person_name) %></th> <th><%= AppearanceRelease.human_attribute_name(:person_name) %></th>
<th><%= AppearanceRelease.human_attribute_name(:person_phone) %></th> <th><%= AppearanceRelease.human_attribute_name(:contact_info) %></th>
<th><%= AppearanceRelease.human_attribute_name(:person_email) %></th>
<th><%= t(".table_headers.notes") %></th> <th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th> <th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th> <th><%= t(".table_headers.signed_at") %></th>

View File

@@ -11,12 +11,6 @@
<hr class="divider-light mx-n4"> <hr class="divider-light mx-n4">
<nav> <nav>
<ul class="nav nav-pills nav-pills-dark flex-column"> <ul class="nav nav-pills nav-pills-dark flex-column">
<li class="nav-item">
<%= link_to [project, :task_requests], class: class_string("nav-link", "active" => controller_name == "task_requests") do %>
<%= lock_icon_for(Current.account, :taskme) %>
<%= product_wordmark :task_me, class: class_string("d-inline-block", "disabled" => !Current.account.taskme_enabled?) %>
<% end %>
</li>
<li class="nav-item"> <li class="nav-item">
<%= link_to [project, :contract_templates], class: class_string("nav-link", "active" => %w(contract_templates release_template_imports).include?(controller_name)) do %> <%= link_to [project, :contract_templates], class: class_string("nav-link", "active" => %w(contract_templates release_template_imports).include?(controller_name)) do %>
<%= lock_icon_for Current.account, :releaseme %> <%= lock_icon_for Current.account, :releaseme %>

View File

@@ -1,4 +1,4 @@
<li class="my-2"> <li class="my-2" id="<%= dom_id(file) %>">
<% if file.variable? %> <% if file.variable? %>
<%= link_to image_tag(file.variant(resize_and_pad: [300, 300, background: "#F7F8F9"]), class: "bg-light img-thumbnail img-fluid"), file, target: "_blank" %> <%= link_to image_tag(file.variant(resize_and_pad: [300, 300, background: "#F7F8F9"]), class: "bg-light img-thumbnail img-fluid"), file, target: "_blank" %>
<% else %> <% else %>

View File

@@ -1,4 +1,4 @@
<%= bootstrap_form_for model, layout: :inline, remote: true do |form| %> <%= bootstrap_form_for model, layout: :inline, remote: true do |form| %>
<%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, wrapper_class: "w-65 mr-2" %> <%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, wrapper_class: "w-65 mr-2", id: "broadcast_files_#{token}" %>
<%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %> <%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %>
<% end %> <% end %>

View File

@@ -0,0 +1,21 @@
<div class="text-center pb-2" id="broadcast_file_form_<%= broadcast.token %>">
<% if controller.class.module_parent.to_s == "Public" %>
<%= render partial: "public/broadcasts/file_form", locals: { model: [broadcast], token: broadcast.token } %>
<% else %>
<%= render partial: "broadcasts/file_form", locals: { model: [broadcast.project, broadcast], token: broadcast.token } %>
<% end %>
</div>
<div class="overflow-auto mh-30">
<ul class="list-unstyled d-flex flex-column align-items-center text-center" id="broadcast_file_list_<%= broadcast.token %>">
<% if files.present? %>
<%= render partial: "broadcasts/file", collection: files %>
<% else %>
<li class="my-3">
Files will appear here.
</li>
<% end %>
</ul>
<div class="d-flex mt-2 justify-content-center" id="broadcast_files_pagination_<%= broadcast.token %>">
<%= will_paginate(files, param_name: 'files_page', params: { active_files_tab: broadcast.token }) if files.present? %>
</div>
</div>

View File

@@ -5,6 +5,12 @@
<% if @broadcast %> <% if @broadcast %>
<meta name="broadcast-token" content="<%= @broadcast.token %>"> <meta name="broadcast-token" content="<%= @broadcast.token %>">
<% end %> <% end %>
<% # Subscribe to Action Cable for every broadcast including those in multi-view %>
<% @multi_view_broadcasts.each do |multi_view_broadcast| %>
<% if multi_view_broadcast.token != @broadcast.token %>
<meta name="broadcast-token" content="<%= multi_view_broadcast.token %>">
<% end %>
<% end %>
<% end %> <% end %>
<% content_for :header do %> <% content_for :header do %>
@@ -24,9 +30,7 @@
<div class="d-flex justify-content-between align-items-center"> <div class="d-flex justify-content-between align-items-center">
<h1 class="h3 m-0"><%= @broadcast.name %></h1> <h1 class="h3 m-0"><%= @broadcast.name %></h1>
<div class="dropdown"> <div class="dropdown">
<a class="btn btn-light border dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <%= link_to "Switch View", "#", class: "btn btn-light border dropdown-toggle", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } %>
Switch View
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink"> <div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5> <h5 class="dropdown-header">Live Streams</h5>
<span class="dropdown-item active"><%= fa_icon("check", text: @broadcast.name.titleize) %></span> <span class="dropdown-item active"><%= fa_icon("check", text: @broadcast.name.titleize) %></span>
@@ -72,13 +76,10 @@
<div class="card-header"> <div class="card-header">
<ul class="nav nav-tabs card-header-tabs"> <ul class="nav nav-tabs card-header-tabs">
<li class="nav-item"> <li class="nav-item">
<a class="<%= class_string("nav-link", "active" => !params[:active_tab].present?) %>" href="#home" data-toggle="tab">Home</a> <%= link_to "Home", "#home", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="<%= class_string("nav-link", "active" => params[:active_tab] == "files") %>" href="#files" data-toggle="tab">Files</a> <%= link_to "Previous Sessions", "#recordings", class: class_string("nav-link", "active" => params[:active_tab] == "recordings"), data: { toggle: "tab" } %>
</li>
<li class="nav-item">
<a class="<%= class_string("nav-link", "active" => params[:active_tab] == "recordings") %>" href="#recordings" data-toggle="tab">Previous Sessions</a>
</li> </li>
</ul> </ul>
</div> </div>
@@ -118,30 +119,6 @@
<p class="card-text">If you want to join the ZOOM meeting dedicated to this broadcast, follow the link below.</p> <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' %> <%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary btn-block', target: '_blank' %>
</div> </div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'files') %>" id="files">
<div class="text-center pb-2" id="broadcast_file_form">
<% if controller.class.module_parent.to_s == "Public" %>
<%= render partial: "public/broadcasts/file_form", locals: { model: [@broadcast], token: @broadcast.token } %>
<% else %>
<%= render partial: "broadcasts/file_form", locals: { model: [@project, @broadcast] } %>
<% end %>
</div>
<p class="alert alert-info mt-2"><%= fa_icon("warning", text: "You may need to refresh the page to see new files uploaded by other team members") %></p>
<div class="overflow-auto mh-30">
<ul class="list-unstyled d-flex flex-column align-items-center text-center" id="broadcast_file_list">
<% if @files.present? %>
<%= render partial: "broadcasts/file", collection: @files %>
<% else %>
<li class="my-3">
Files will appear here.
</li>
<% end %>
</ul>
<div class="d-flex mt-2 justify-content-center" id="broadcast_files_pagination">
<%= will_paginate(@files, params: { active_tab: 'files' }) if @files.present? %>
</div>
</div>
</div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings"> <div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == 'recordings') %>" id="recordings">
<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 } %>
@@ -150,5 +127,36 @@
</div> </div>
</div> </div>
</div> </div>
<!-- files section -->
<div id="files" class="card shadow-sm mb-3">
<div class="card-header">
<h2 class="h5">Files</h2>
<% if @multi_view_broadcasts %>
<ul class="nav nav-tabs card-header-tabs">
<% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<li class="nav-item">
<%= link_to mvb.name, "#files_broadcast_#{mvb.token}", class: class_string("nav-link", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))), data: { toggle: "tab" } %>
</li>
<% end %>
</ul>
<% end %>
</div>
<div class="card-body p-3">
<div class="tab-content">
<% if @multi_view_broadcasts.present? %>
<% @multi_view_broadcasts.each_with_index do |mvb, index| %>
<div class="<%= class_string("tab-pane fade show", "active" => (params[:active_files_tab] == mvb.token || (params[:active_files_tab].nil? && index == 0))) %>" id="files_broadcast_<%= mvb.token %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: mvb, files: mvb.files } %>
</div>
<% end %>
<% else %>
<div class="tab-pane fade show active" id="files_broadcast_<%= @broadcast.id %>">
<%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
</div>
<% end %>
</div>
</div>
</div>
</div> </div>
<div> <div>

View File

@@ -1,5 +1,9 @@
$("#broadcast_file_form").html("<%= j render(partial: "broadcasts/file_form", locals: { model: [@project, @broadcast] }) %>"); $("#broadcast_file_form_<%= @broadcast.token %>").html("<%= j render(partial: "broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>");
$("#broadcast_file_list").html("<%= j render(partial: "broadcasts/file", collection: @files) %>");
$("#broadcast_files_pagination").html("<%= j will_paginate(@files) %>"); var file_id = "#<%= dom_id(@files.first) %>"
if ($("#broadcast_file_list_<%= @broadcast.token %>").has(file_id).length == 0) {
$("#broadcast_file_list_<%= @broadcast.token %>").html("<%= j render(partial: "broadcasts/file", collection: @files) %>");
$("#broadcast_files_pagination_<%= @broadcast.token %>").html("<%= j will_paginate(@files, param_name: 'files_page', params: { active_files_tab: @broadcast.token }) %>");
}
bsCustomFileInput.init(); bsCustomFileInput.init();

View File

@@ -29,6 +29,7 @@
<% if releasable.model_name == "LocationRelease" %> <% if releasable.model_name == "LocationRelease" %>
<%= description_list_pair "Filming Started On:", releasable&.filming_started_on&.strftime("%D") %> <%= description_list_pair "Filming Started On:", releasable&.filming_started_on&.strftime("%D") %>
<%= description_list_pair "Filming Ended On:", releasable&.filming_ended_on&.strftime("%D") %> <%= description_list_pair "Filming Ended On:", releasable&.filming_ended_on&.strftime("%D") %>
<%= description_list_pair "Filming Hours:", releasable&.filming_hours %>
<% end %> <% end %>
<% if contract_template.fee? %> <% if contract_template.fee? %>
<%= description_list_pair "Fee:", number_to_currency(contract_template.fee) %> <%= description_list_pair "Fee:", number_to_currency(contract_template.fee) %>

View File

@@ -38,6 +38,7 @@
<div class="form-row"> <div class="form-row">
<%= form.text_field :filming_started_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %> <%= form.text_field :filming_started_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
<%= form.text_field :filming_ended_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %> <%= form.text_field :filming_ended_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
<%= form.text_field :filming_hours, wrapper_class: "col-sm-12" %>
</div> </div>
<% end %> <% end %>

View File

@@ -16,11 +16,6 @@
<%= link_to t("projects.show.downloads"), [@project, :downloads], class: "text-decoration-none text-reset stretched-link" %> <%= link_to t("projects.show.downloads"), [@project, :downloads], class: "text-decoration-none text-reset stretched-link" %>
<% end %> <% end %>
<% end %> <% end %>
<% if policy(Project).show_task_results? %>
<%= render "folder_card" do %>
<%= link_to t("projects.show.tasks"), [@project, :tasks], class: "text-decoration-none text-reset stretched-link" %>
<% end %>
<% end %>
</div> </div>
<hr/> <hr/>

View File

@@ -1,4 +1,4 @@
<%= bootstrap_form_for model, url: broadcast_url(token: token), layout: :inline, remote: true do |form| %> <%= bootstrap_form_for model, url: broadcast_url(token: token), layout: :inline, remote: true do |form| %>
<%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, wrapper_class: "w-65 mr-2" %> <%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, wrapper_class: "w-65 mr-2", id: "broadcast_files_#{token}" %>
<%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %> <%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %>
<% end %> <% end %>

View File

@@ -1,5 +1,9 @@
$("#broadcast_file_form").html("<%= j render(partial: "public/broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>"); $("#broadcast_file_form_<%= @broadcast.token %>").html("<%= j render(partial: "public/broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>");
$("#broadcast_file_list").html("<%= j render(partial: "broadcasts/file", collection: @files) %>");
$("#broadcast_files_pagination").html("<%= j will_paginate(@files) %>"); var file_id = "#<%= dom_id(@files.first) %>"
if ($("#broadcast_file_list_<%= @broadcast.token %>").has(file_id).length == 0) {
$("#broadcast_file_list_<%= @broadcast.token %>").html("<%= j render(partial: "broadcasts/file", collection: @files) %>");
$("#broadcast_files_pagination_<%= @broadcast.token %>").html("<%= j will_paginate(@files) %>");
}
bsCustomFileInput.init(); bsCustomFileInput.init();

View File

@@ -45,6 +45,7 @@
<div class="form-row"> <div class="form-row">
<%= form.text_field :filming_started_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %> <%= form.text_field :filming_started_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
<%= form.text_field :filming_ended_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %> <%= form.text_field :filming_ended_on, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
<%= form.text_field :filming_hours, wrapper_class: "col-sm-12" %>
</div> </div>
<% end %> <% end %>

View File

@@ -1,6 +0,0 @@
<tr>
<td><%= file.filename %></td>
<td class="text-right">
<%= link_to fa_icon("download"), file, target: "_blank" %>
</td>
</tr>

View File

@@ -1,39 +0,0 @@
<%= errors_summary_for task_request %>
<%= bootstrap_form_with model: model, url: [@project, @task_request, show_chat: true], local: true do |form| %>
<div class="alert alert-notice text-center pl-0 text-md-left mt-4">
<%= fa_icon "info-circle" %>
<strong><%= t '.info_message' %></strong>
</div>
<%= form.text_area :description, label: t('.labels.description') %>
<%= form.text_field :deadline, class: "datepicker-control", label: t('.labels.deadline') %>
<%= form.text_field :time_allowed, label: t('.labels.time_allowed') %>
<%= form.text_area :additional_notes, label: t('.labels.additional_notes') %>
<%= field_set_tag content_tag(:span, t('.labels.files'), class: "h6 text-muted text-uppercase") do %>
<div class="field d-none">
<%= form.label :files %>
<%= form.file_field :files, disable: true, direct_upload: true, multiple: true, id: "task_request_files", hide_label: true %>
<% task_request.files.each do |file| %>
<% unless file.persisted? %>
<%= hidden_field_tag "#{task_request.model_name.param_key}[files][]", file.signed_id %>
<% end %>
<% end %>
</div>
<div class="dropzone field border-dashed"
data-accepted-files="audio/*,image/*,video/*,application/*"
data-behavior="dropzone"
data-file-input-id="task_request_files"
data-existing-files="<%= mock_photos_json(task_request.files) %>"
data-placeholder="<%= dropzone_placeholder_message_for(task_request) %>"
data-submit-button="#submit_folder"></div>
<% end %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [project, :task_requests], class: "col-3 text-reset" %>
<div class="col-9">
<%= form.submit class: class_string("btn btn-block", ["btn-success", "btn-primary"] => task_request.new_record?), data: { disable_with: t("shared.disable_with") } %>
</div>
</div>
<% end %>

View File

@@ -1,45 +0,0 @@
<tr>
<td>
<%= task_request.created_at.strftime('%D') %>
</td>
<td>
<%= task_request.deadline.try(:strftime, '%D') %>
</td>
<td>
<%= truncate(task_request.description) {
link_to t('.actions.read_more'),
'#',
class: 'alert-link',
data: {
toggle: "popover",
content: task_request.description,
trigger: "hover"
}
} %>
</td>
<td>
<%= task_request.time_allowed %>
</td>
<td>
<%= task_request.status.titleize %>
</td>
<td class="text-right">
<div class="btn-group">
<%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
<div class="dropdown-menu dropdown-menu-right">
<% if policy(task_request).show? %>
<%= link_to fa_icon("tasks fw", text: "View"), [task_request.project, task_request], class: "dropdown-item", target: '_blank' %>
<% end %>
<% if policy(task_request).edit? %>
<%= link_to fa_icon("pencil fw", text: "Edit"), [:edit, task_request.project, task_request], class: "dropdown-item" %>
<% end %>
<% if policy(task_request).open_deliverable? && task_request.status == "completed" %>
<%= link_to fa_icon("external-link fw", text: t(".actions.open_deliverable")), task_request.deliverable_url, class: "dropdown-item", target: '_blank' %>
<% end %>
<% if policy(task_request).cancel? && !task_request.cancelled? %>
<%= link_to fa_icon("ban fw", text: "Cancel"), [:cancel, task_request.project, task_request], class: "dropdown-item", method: :post %>
<% end %>
</div>
</div>
</td>
</tr>

View File

@@ -1,9 +0,0 @@
<% if params[:show_chat] %>
<%= javascript_include_tag "https://js.hs-scripts.com/7344617.js", defer: "defer", async: true, id: "hs-script-loader" %>
<%= javascript_tag nonce: true do %>
$(document).ready(function(){
window.HubSpotConversations.widget.open();
});
<% end %>
<% end %>
<p class="alert alert-success p-3 lead text-center"><%= t '.success_message' %></p>

View File

@@ -1,6 +0,0 @@
<div class="card shadow-sm">
<%= card_header text: t(".heading"), close_action_path: [@project, :task_requests] %>
<div class="card-body">
<%= render "form", model: [@project, @task_request], task_request: @task_request, project: @project %>
</div>
</div>

View File

@@ -1,39 +0,0 @@
<%= product_wordmark :task_me, class: "small mb-3" %>
<div class="row">
<div class="col-md-12">
<div class="d-md-flex d-sm-flex flex-sm-column flex-md-row flex-md-wrap mb-3">
<% if policy(TaskRequest).new? %>
<%= link_to fa_icon("plus", text: t(".actions.new")), [:new, @project, :task_request], class: "btn btn-primary mb-2" %>
<% end %>
</div>
</div>
</div>
<div class="border bg-white rounded shadow-sm pb-3 table-responsive">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th><%= t(".table_headers.task_request_created_on") %></th>
<th><%= t(".table_headers.task_request_deadline") %></th>
<th><%= t(".table_headers.task_request_description") %></th>
<th><%= t(".table_headers.task_request_time_allowed") %></th>
<th><%= t(".table_headers.task_request_status") %></th>
<th></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @task_requests.any? %>
<%= render @task_requests %>
<% else %>
<tr>
<td colspan="20" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div id="task_requests_pagination" class="mt-3">
<%= will_paginate @task_requests %>
</div>

View File

@@ -1,6 +0,0 @@
<div class="card shadow-sm">
<%= card_header text: t(".heading"), close_action_path: [@project, :task_requests] %>
<div class="card-body">
<%= render "form", model: [@project, @task_request], task_request: @task_request, project: @project %>
</div>
</div>

View File

@@ -1,46 +0,0 @@
<div class="card shadow-sm">
<%= card_header text: "Task Details", close_action_path: [@project, :task_requests] %>
<div class="card-body">
<div class="row">
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :description, append: ":" %>
<%= description_list_pair_for @task_request, :created_at, append: ":" %>
<%= description_list_pair_for @task_request, :status, append: ":" %>
</dl>
</div>
<div class="col-md-6 col-sm-12">
<dl>
<%= description_list_pair_for @task_request, :deadline, append: ":" %>
<%= description_list_pair_for @task_request, :time_allowed, append: ":" %>
<%= description_list_pair_for @task_request, :additional_notes, append: ":" %>
</dl>
</div>
<div class="col-md-12">
<h2 class="h6 mt-3">Files:</h2>
<div class="pt-2 mx-n3">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th>Filename</th>
<th></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @files.any? %>
<%= render partial: "file", collection: @files %>
<% else %>
<tr>
<td colspan="12" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
<div class="mt-4" id="task_requests_pagiantion">
<%= will_paginate @files %>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,17 +0,0 @@
<tr>
<td>
<%= task.created_at.strftime('%D') %>
</td>
<td>
<%= task.deadline.try(:strftime, '%D') %>
</td>
<td>
<%= task.time_allowed %>
</td>
<td>
<%= task.status.titleize %>
</td>
<td>
<%= link_to "View Deliverable", task.deliverable_url, target: "_blank" %>
</td>
</tr>

View File

@@ -1,26 +0,0 @@
<div class="border bg-white rounded shadow-sm pb-3 table-responsive">
<table class="table table-striped tr-px-4 align-all-middle">
<thead class="thead-light">
<tr>
<th><%= t(".table_headers.task_request_created_on") %></th>
<th><%= t(".table_headers.task_request_deadline") %></th>
<th><%= t(".table_headers.task_request_time_allowed") %></th>
<th><%= t(".table_headers.task_request_status") %></th>
<th><%= t(".table_headers.task_request_results") %></th>
</tr>
</thead>
<tbody id="task_requests">
<% if @tasks.any? %>
<%= render partial: "task", collection: @tasks %>
<% else %>
<tr>
<td colspan="5" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div id="task_requests_pagination" class="mt-3">
<%= will_paginate @tasks %>
</div>

View File

@@ -93,13 +93,6 @@ en:
application: application:
header: header:
sign_out: Sign Out sign_out: Sign Out
task_requests:
index:
empty: Task requests will appear here
show:
empty: Attached files will appear here.
update:
notice: The task request has been updated successfully
users: users:
create: create:
notice: The user was created notice: The user was created
@@ -646,6 +639,7 @@ en:
create: create:
notice: Check your email for password reset instructions notice: Check your email for password reset instructions
edit: edit:
notice: This password reset URL has expired or is invalid. Try again by clicking "Forgot your password?" below
submit: Save New Password submit: Save New Password
title: Password Reset title: Password Reset
new: new:
@@ -736,7 +730,6 @@ en:
music_release: Music Releases (%{count}) music_release: Music Releases (%{count})
report: Reports report: Reports
talent_release: Talent Releases (%{count}) talent_release: Talent Releases (%{count})
tasks: Tasks
public: public:
acquired_media_releases: acquired_media_releases:
new: new:
@@ -902,7 +895,6 @@ en:
tag_multiple_releases: Add Tag tag_multiple_releases: Add Tag
tag_multiple_releases_form: tag_multiple_releases_form:
submit: Add submit: Add
task_me: Task
tags: tags:
form: form:
submit: Add submit: Add
@@ -938,54 +930,6 @@ en:
manage: Manage manage: Manage
update: update:
notice: The talent release has been updated notice: The talent release has been updated
task_requests:
cancel:
notice: Task has been cancelled successfully.
create:
notice: Task request created succussfully.
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds.
edit:
heading:
Edit Task Request
form:
info_message: After submitting this task request, you'll be connected via chat with a ME Suite representative.
labels:
additional_notes: Please add any additional notes we should be aware of regarding this task.
deadline: What is the deadline for this task?
description: Please describe the task.
files: Please attach any files related to this task
time_allowed: How many hours would like spend on this task?
index:
actions:
new: Create Task Request
empty: Task requests will appear here.
table_headers:
task_request_created_on: Created On
task_request_deadline: Deadline
task_request_description: Description
task_request_results: Task Results
task_request_status: Status
task_request_time_allowed: Time Allowed
new:
heading: New Task Request
show:
empty: Attached files will appear here.
task_request:
actions:
manage: Manage
open_deliverable: Open Deliverable
read_more: read more
update:
notice: Task request updated successfully.
tasks:
index:
empty: Tasks will appear here.
table_headers:
task_request_created_on: Created On
task_request_deadline: Deadline
task_request_results: Task Results
task_request_status: Status
task_request_time_allowed: Time Allowed
user_mailer: user_mailer:
existing_account: existing_account:
subject: You've been added as a ME Suite Account Manager subject: You've been added as a ME Suite Account Manager

View File

@@ -182,16 +182,3 @@ es:
photos: photos:
guardian_photo: guardian_photo:
heading: Guardian Photo (ES) heading: Guardian Photo (ES)
task_requests:
create:
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds. (ES)
form:
info_message: After submitting this task request, you'll be connected via chat with a ME Suite representative. (ES)
index:
table_headers:
task_request_description: Description (ES)
task_request:
actions:
manage: Manage (ES)
open_deliverable: Open Deliverable (ES)
read_more: read more (ES)

View File

@@ -31,7 +31,6 @@ Rails.application.routes.draw do
resources :users, only: [:index, :new, :create, :edit, :update, :destroy] do resources :users, only: [:index, :new, :create, :edit, :update, :destroy] do
resource :masquerade, only: :create resource :masquerade, only: :create
end end
resources :task_requests, only: [:index, :edit, :update, :show]
root to: "accounts#index", as: :signed_in_root root to: "accounts#index", as: :signed_in_root
end end
@@ -98,12 +97,6 @@ Rails.application.routes.draw do
delete :destroy_file delete :destroy_file
end end
end end
resources :task_requests, except: :destroy do
member do
post :cancel
end
end
resources :tasks, only: :index
end end
resource :profile, only: [:show, :update] resource :profile, only: [:show, :update]
resources :videos, only: [] do resources :videos, only: [] do

View File

@@ -1,14 +0,0 @@
class CreateTaskRequests < ActiveRecord::Migration[6.0]
def change
create_table :task_requests do |t|
t.references :project
t.text :description
t.datetime :deadline
t.string :time_allowed
t.text :additional_notes
t.integer :status, default: 0
t.timestamps
end
end
end

View File

@@ -1,5 +0,0 @@
class AddDeliverableUrlToTaskRequests < ActiveRecord::Migration[6.0]
def change
add_column :task_requests, :deliverable_url, :string
end
end

View File

@@ -0,0 +1,5 @@
class AddFilmingHoursToLocationReleases < ActiveRecord::Migration[6.0]
def change
add_column :location_releases, :filming_hours, :text
end
end

View File

@@ -1,5 +0,0 @@
class AddUserEmailToTaskRequests < ActiveRecord::Migration[6.0]
def change
add_column :task_requests, :user_email, :string
end
end

View File

@@ -50,7 +50,7 @@ $_$;
SET default_tablespace = ''; SET default_tablespace = '';
SET default_with_oids = false; SET default_table_access_method = heap;
-- --
-- Name: account_auths; Type: TABLE; Schema: public; Owner: - -- Name: account_auths; Type: TABLE; Schema: public; Owner: -
@@ -615,6 +615,15 @@ CREATE SEQUENCE public.contract_templates_id_seq
ALTER SEQUENCE public.contract_templates_id_seq OWNED BY public.contract_templates.id; ALTER SEQUENCE public.contract_templates_id_seq OWNED BY public.contract_templates.id;
--
-- Name: data_migrations; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.data_migrations (
version character varying NOT NULL
);
-- --
-- Name: directories; Type: TABLE; Schema: public; Owner: - -- Name: directories; Type: TABLE; Schema: public; Owner: -
-- --
@@ -1172,7 +1181,6 @@ CREATE TABLE public.settings (
-- --
CREATE SEQUENCE public.settings_id_seq CREATE SEQUENCE public.settings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1208,7 +1216,6 @@ CREATE TABLE public.taggings (
-- --
CREATE SEQUENCE public.taggings_id_seq CREATE SEQUENCE public.taggings_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1239,7 +1246,6 @@ CREATE TABLE public.tags (
-- --
CREATE SEQUENCE public.tags_id_seq CREATE SEQUENCE public.tags_id_seq
AS integer
START WITH 1 START WITH 1
INCREMENT BY 1 INCREMENT BY 1
NO MINVALUE NO MINVALUE
@@ -1320,44 +1326,6 @@ CREATE SEQUENCE public.talent_releases_id_seq
ALTER SEQUENCE public.talent_releases_id_seq OWNED BY public.talent_releases.id; ALTER SEQUENCE public.talent_releases_id_seq OWNED BY public.talent_releases.id;
--
-- Name: task_requests; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.task_requests (
id bigint NOT NULL,
project_id bigint,
description text,
deadline timestamp without time zone,
time_allowed character varying,
additional_notes text,
status integer DEFAULT 0,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
deliverable_url character varying,
user_email character varying
);
--
-- Name: task_requests_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.task_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: task_requests_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.task_requests_id_seq OWNED BY public.task_requests.id;
-- --
-- Name: terms; Type: TABLE; Schema: public; Owner: - -- Name: terms; Type: TABLE; Schema: public; Owner: -
-- --
@@ -1864,13 +1832,6 @@ ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id
ALTER TABLE ONLY public.talent_releases ALTER COLUMN id SET DEFAULT nextval('public.talent_releases_id_seq'::regclass); ALTER TABLE ONLY public.talent_releases ALTER COLUMN id SET DEFAULT nextval('public.talent_releases_id_seq'::regclass);
--
-- Name: task_requests id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.task_requests ALTER COLUMN id SET DEFAULT nextval('public.task_requests_id_seq'::regclass);
-- --
-- Name: terms id; Type: DEFAULT; Schema: public; Owner: - -- Name: terms id; Type: DEFAULT; Schema: public; Owner: -
-- --
@@ -2047,6 +2008,14 @@ ALTER TABLE ONLY public.contract_templates
ADD CONSTRAINT contract_templates_pkey PRIMARY KEY (id); ADD CONSTRAINT contract_templates_pkey PRIMARY KEY (id);
--
-- Name: data_migrations data_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.data_migrations
ADD CONSTRAINT data_migrations_pkey PRIMARY KEY (version);
-- --
-- Name: directories directories_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: directories directories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@@ -2191,14 +2160,6 @@ ALTER TABLE ONLY public.talent_releases
ADD CONSTRAINT talent_releases_pkey PRIMARY KEY (id); ADD CONSTRAINT talent_releases_pkey PRIMARY KEY (id);
--
-- Name: task_requests task_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.task_requests
ADD CONSTRAINT task_requests_pkey PRIMARY KEY (id);
-- --
-- Name: terms terms_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: terms terms_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@@ -2802,13 +2763,6 @@ CREATE INDEX index_talent_releases_on_term_id ON public.talent_releases USING bt
CREATE INDEX index_talent_releases_on_territory_id ON public.talent_releases USING btree (territory_id); CREATE INDEX index_talent_releases_on_territory_id ON public.talent_releases USING btree (territory_id);
--
-- Name: index_task_requests_on_project_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_task_requests_on_project_id ON public.task_requests USING btree (project_id);
-- --
-- Name: index_unreleased_appearances_on_video_id; Type: INDEX; Schema: public; Owner: - -- Name: index_unreleased_appearances_on_video_id; Type: INDEX; Schema: public; Owner: -
-- --
@@ -3545,9 +3499,6 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200427073429'), ('20200427073429'),
('20200428091105'), ('20200428091105'),
('20200507110804'), ('20200507110804'),
('20200512161738'), ('20200512161738');
('20200518200245'),
('20200519191908'),
('20200610143327');

View File

@@ -23,6 +23,10 @@ class ZoomGateway
"#{self.USER_TYPE_NAME}-directme-host" "#{self.USER_TYPE_NAME}-directme-host"
end end
def enable_recordings?
ENV['ZOOM_ENABLE_RECORDINGS'] == '1'
end
def apply_limits? def apply_limits?
self.USER_TYPE_NAME == 'pro' self.USER_TYPE_NAME == 'pro'
end end
@@ -33,12 +37,14 @@ class ZoomGateway
end end
def create_meeting(host_id, **kwargs) def create_meeting(host_id, **kwargs)
recording_type = self.class.enable_recordings? ? 'cloud' : 'none'
meeting = @client.meeting_create({ user_id: host_id, meeting = @client.meeting_create({ user_id: host_id,
topic: kwargs[:topic], topic: kwargs[:topic],
type: 1, # Instant meeting type: 1, # Instant meeting
settings: { settings: {
host_video: true, host_video: true,
participant_video: true participant_video: true,
auto_recording: recording_type,
} }) } })
meeting["id"] meeting["id"]
end end
@@ -78,6 +84,10 @@ class ZoomGateway
@client.user_delete(id: host_id) @client.user_delete(id: host_id)
end end
def delete_recording(meeting_id, recording_id)
@client.recording_delete(meeting_id: meeting_id, recording_id: recording_id)
end
private private
def parse_zoom_error(error) def parse_zoom_error(error)

View File

@@ -50,4 +50,21 @@ RSpec.describe BroadcastsChannel, type: :channel do
}) })
end end
end end
describe ".broadcast_file_upload_updates" do
it 'broadcasts to the channel with the right data' do
broadcast = create(:broadcast, :with_stream, :with_files, skip_create_callback: true)
files_content = ApplicationController.render partial: "broadcasts/file", collection: broadcast.files
expect {
BroadcastsChannel.broadcast_file_upload_updates(broadcast, broadcast.files, "pagination_content")
}.to have_broadcasted_to(broadcast).with({
event: 'file_upload_update',
broadcast_token: broadcast.token,
files_content: files_content,
pagination_content: "pagination_content"
})
end
end
end end

View File

@@ -24,4 +24,20 @@ RSpec.describe ProjectsChannel, type: :channel do
}.to have_broadcasted_to(project).with(event: "video_status_update", content: content) }.to have_broadcasted_to(project).with(event: "video_status_update", content: content)
end end
end end
describe ".conference_recording_ready" do
it "broadcasts to the project channel" do
recording_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
zoom_meeting = create(:zoom_meeting, project: project, recording: recording_file)
video_url = 'http://url.to.video/video.mp4'
allow(zoom_meeting.recording).to receive(:service_url).and_return(video_url)
expect {
ProjectsChannel.conference_recording_ready(project, zoom_meeting.recording)
}.to have_broadcasted_to(project).with { |data|
expect(data['content']).to include(video_url)
expect(data['event']).to eq('conference_recording_ready')
}
end
end
end end

View File

@@ -1,68 +0,0 @@
require "rails_helper"
RSpec.describe Admin::TaskRequestsController, type: :controller do
render_views
let!(:current_user) { create(:user, :admin) }
before do
sign_in(current_user)
end
describe "#index" do
it "returns a successful response" do
get :index
expect(response).to be_successful
end
end
describe "#edit" do
let(:task_request) { create(:task_request) }
it "returns a successful response" do
get :edit, params: { id: task_request }
expect(response).to be_successful
end
it "assigns task request" do
get :edit, params: { id: task_request }
expect(assigns(:task_request)).to eq task_request
end
end
describe "#update" do
let(:task_request) { create(:task_request) }
it "redirects to task requests page" do
patch :update, params: { id: task_request, task_request: update_params }
expect(response).to be_redirect
expect(response).to redirect_to admin_task_requests_path
end
it "sets a flash notice" do
patch :update, params: { id: task_request, task_request: update_params }
expect(flash.notice).to eq "The task request has been updated successfully"
end
it "updates task request" do
patch :update, params: { id: task_request, task_request: update_params }
expect(task_request.reload.status).to eq("completed")
expect(task_request.reload.deliverable_url).to eq("example.com/deliverables")
end
end
private
def update_params
{
status: "completed",
deliverable_url: "example.com/deliverables"
}
end
end

View File

@@ -26,8 +26,7 @@ RSpec.describe AppearanceReleasesController, tye: :controller do
get :index, params: { project_id: project } get :index, params: { project_id: project }
expect(response.body).to have_content "John Doe" expect(response.body).to have_content "John Doe"
expect(response.body).to have_content "555-123-4567" expect(response.body).to have_content "P: 5551234567E: jane.doe@test.com"
expect(response.body).to have_content "jane.doe@test.com"
expect(response.body).to have_content "Some notes here" expect(response.body).to have_content "Some notes here"
expect(response.body).to have_button "Import Release" expect(response.body).to have_button "Import Release"
expect(response.body).to have_content "Manage" expect(response.body).to have_content "Manage"

View File

@@ -111,17 +111,6 @@ RSpec.describe BroadcastsController, type: :controller do
end end
end end
describe "#update" do
let!(:broadcast) { create(:broadcast, :with_stream, skip_create_callback: true, project: project ) }
it "uploads files to broadcast" do
patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
expect(broadcast.files.count).to eq(1)
expect(broadcast.files.first.filename).to eq("contract.pdf")
end
end
describe "#show" do describe "#show" do
let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast") } let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast") }
@@ -198,6 +187,25 @@ RSpec.describe BroadcastsController, type: :controller do
end end
end end
describe "#update" do
let!(:broadcast) { create(:broadcast, :with_stream, skip_create_callback: true, project: project ) }
it "uploads files to broadcast" do
patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
expect(broadcast.files.count).to eq(1)
expect(broadcast.files.first.filename).to eq("contract.pdf")
end
it "sends an update to the broadcasts channel" do
allow(BroadcastsChannel).to receive(:broadcast_file_upload_updates)
patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
expect(BroadcastsChannel).to have_received(:broadcast_file_upload_updates)
end
end
describe "#destroy" do describe "#destroy" do
let!(:broadcast_2) { create(:broadcast, :with_stream, skip_create_callback: true, project: project, name: "Another Broadcast") } let!(:broadcast_2) { create(:broadcast, :with_stream, skip_create_callback: true, project: project, name: "Another Broadcast") }

View File

@@ -56,6 +56,16 @@ RSpec.describe PasswordResetsController, type: :controller do
expect(response.body).to have_content("Password Reset") expect(response.body).to have_content("Password Reset")
expect(response.body).to have_selector("input[name='password_reset[password]']") expect(response.body).to have_selector("input[name='password_reset[password]']")
end end
context "when reset token is invalid" do
it "redirects to the sign in page" do
get :edit, params: { id: "bad token" }
expect(response).to be_redirect
expect(response).to redirect_to(new_session_path)
expect(flash.notice).to be_present
end
end
end end
describe "#update" do describe "#update" do

View File

@@ -92,6 +92,14 @@ RSpec.describe Public::BroadcastsController, type: :controller do
expect(broadcast.files.count).to eq(1) expect(broadcast.files.count).to eq(1)
expect(broadcast.files.first.filename).to eq("contract.pdf") expect(broadcast.files.first.filename).to eq("contract.pdf")
end end
it "sends an update to the broadcasts channel" do
allow(BroadcastsChannel).to receive(:broadcast_file_upload_updates)
patch :update, params: { token: broadcast.token, broadcast: file_params }, xhr: true
expect(BroadcastsChannel).to have_received(:broadcast_file_upload_updates)
end
end end
after do after do

View File

@@ -1,129 +0,0 @@
require 'rails_helper'
RSpec.describe TaskRequestsController, 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
end
describe "#index" do
it "responds successfully" do
get :index, params: { project_id: project }
expect(response).to be_successful
end
it "renders content" do
create(:task_request, project: project, description: "Another Request")
get :index, params: { project_id: project }
expect(response.body).to have_link "Create Task Request"
expect(response.body).to have_content "Pending"
end
context "when there are many records" do
it "paginates the table" do
create_list(:task_request, 20, project: project)
get :index, params: { project_id: project }
expect(response.body).to have_link("2", href: project_task_requests_path(project, page: 2))
end
end
end
describe "#new" do
it "responds successfully" do
get :new, params: { project_id: project }
expect(response).to be_successful
expect(assigns(:task_request)).to be_a_new(TaskRequest)
expect(response).to render_template(:new)
end
end
describe "#create" do
it "does create a new record" do
expect {
post :create, params: { project_id: project.id, task_request: task_request_params }
}.to change(TaskRequest, :count)
end
it "logs an event" do
expect {
post :create, params: { project_id: project.id, task_request: task_request_params }
}.to have_enqueued_job(TrackAnalyticsJob).with(user, account, :track_create_task_request, user_agent: "Rails Testing", user_ip: "0.0.0.0")
end
it "submits data to hubspot form" do
expect {
post :create, params: { project_id: project.id, task_request: task_request_params }
}.to have_enqueued_job(SubmitHubspotTaskRequestFormJob)
end
end
describe "#update" do
let!(:task_request) { create(:task_request, project: project, description: "My description" ) }
it "updates task request" do
patch :update, params: { project_id: project.id, id: task_request.id, task_request: update_params }
expect(task_request.reload.description).to eq("This is updated description")
end
end
describe "#show" do
let!(:task_request) { create(:task_request, project: project, description: "Task Request") }
it "responds successfully" do
get :show, params: { project_id: project.id, id: task_request.id }
expect(response).to be_successful
expect(assigns(:task_request)).to eq(task_request)
end
it "renders content" do
get :show, params: { project_id: project.id, id: task_request.id }
expect(response.body).to have_content "Task Request"
expect(response.body).to have_content "pending"
end
end
describe "#cancel" do
let!(:task_request) { create(:task_request, project: project, description: "Task to be cancelled") }
it "responds with redirect" do
post :cancel, params: { project_id: project.id, id: task_request.id }
expect(response).to be_redirect
expect(response).to redirect_to(project_task_requests_path(project))
expect(flash.notice).not_to be_nil
end
it "updates the status to 'cancelled'" do
expect {
post :cancel, params: { project_id: project.id, id: task_request.id }
}.to change { task_request.reload.status }.from("pending").to("cancelled")
end
end
private
def task_request_params
attributes = attributes_for(:task_request).except(:status, :user_email)
files = 2.times.map { Rack::Test::UploadedFile.new(file_fixture("location_photo.png"), "image/png") }
attributes.merge({ files: files })
end
def update_params
{ description: "This is updated description" }
end
end

View File

@@ -1,40 +0,0 @@
require 'rails_helper'
RSpec.describe TasksController, 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
end
describe "#index" do
it "responds successfully" do
get :index, params: { project_id: project }
expect(response).to be_successful
end
it "renders content" do
create(:task_request, :completed, project: project, description: "Another Request")
get :index, params: { project_id: project }
expect(response.body).to have_content "Completed"
expect(response.body).to have_link "View Deliverable"
end
context "when there are many records" do
it "paginates the table" do
create_list(:task_request, 20, :completed, project: project)
get :index, params: { project_id: project }
expect(response.body).to have_link("2", href: project_tasks_path(project, page: 2))
end
end
end
end

View File

@@ -69,6 +69,13 @@ RSpec.describe ZoomNotificationsController, type: :controller do
expect(zoom_meeting.reload).to be_ended expect(zoom_meeting.reload).to be_ended
end end
it 'updates the recording when recording complete notification is received' do
expect {
post :create, params: recording_complete
}.to change { zoom_meeting.recording }
end
end end
end end
end end

View File

@@ -1,20 +0,0 @@
FactoryBot.define do
factory :task_request do
association :project
user_email 'test@email.com'
deadline { 10.days.from_now }
time_allowed "10 days"
description "Task request"
additional_notes "Additional notes"
status 0
trait :completed do
deliverable_url "example.com/deliverables"
status 1
end
trait :with_files do
files { [Rack::Test::UploadedFile.new('spec/fixtures/files/contract.pdf', 'application/pdf')] }
end
end
end

View File

@@ -1,108 +0,0 @@
require "rails_helper"
feature "Admin managing task requests" do
let(:current_user) { create(:user, admin: true, email: "user@test.com") }
let(:project) { create(:project, account: current_user.primary_account, name: "Test Project") }
before do
sign_in current_user
end
scenario "admin should see View action for task request in Manage dropdown", js: true do
create(:task_request)
visit admin_task_requests_path
click_on 'Manage'
expect(page).to have_content 'View'
end
scenario "admin can open detail view of task request", js: true do
task_request = create(:task_request, :with_files)
visit admin_task_requests_path
click_on 'Manage'
click_link 'View'
switch_to_window(windows.last)
expect(page).to have_content 'Account Name'
expect(page).to have_content task_request.project.account.name
expect(page).to have_content 'Project Name'
expect(page).to have_content task_request.project.name
expect(page).to have_content 'Description'
expect(page).to have_content task_request.description
expect(page).to have_content 'Created At'
expect(page).to have_content task_request.created_at
expect(page).to have_content 'User Email'
expect(page).to have_content task_request.user_email
expect(page).to have_content 'Deadline'
expect(page).to have_content task_request.deadline
expect(page).to have_content 'Time Allowed'
expect(page).to have_content task_request.time_allowed
expect(page).to have_content 'Additional Notes'
expect(page).to have_content task_request.additional_notes
expect(page).to have_content 'Status'
expect(page).to have_content task_request.status
expect(page).to have_content 'Files'
task_request.files.each do |file|
expect(page).to have_content file.blob.filename
end
end
scenario "no files attached label is shown if there are no files attached to the task request", js:true do
create(:task_request)
visit admin_task_requests_path
click_on 'Manage'
click_link 'View'
switch_to_window(windows.last)
expect(page).to have_content 'Attached files will appear here.'
end
scenario "task requests table is visible" do
visit admin_task_requests_path
expect(page).to have_content "Task ID"
expect(page).to have_content "Account Name"
expect(page).to have_content "Project Name"
expect(page).to have_content "Created On"
expect(page).to have_content "Deadline"
expect(page).to have_content "Time Allowed"
expect(page).to have_content "Status"
end
scenario "sees list of task requests" do
visit admin_task_requests_path
expect(page).to have_content no_task_requests_label
task_request = create(:task_request)
visit admin_task_requests_path
expect(page).not_to have_content no_task_requests_label
expect(page).to have_content task_request.id
expect(page).to have_content task_request.project.account.name
expect(page).to have_content task_request.project.name
expect(page).to have_content task_request.created_at.try(:strftime, '%D')
expect(page).to have_content task_request.deadline.try(:strftime, '%D')
expect(page).to have_content task_request.time_allowed
expect(page).to have_content task_request.status.capitalize
end
private
def no_task_requests_label
"Task requests will appear here"
end
end

View File

@@ -1,92 +0,0 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.feature 'User creates task request', type: :feature do
let(:current_user) { create(:user, :manager) }
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
before do
sign_in(current_user)
end
scenario 'creating a new task request' do
visit new_project_task_request_path(project)
fill_in description_field, with: 'Description of the task'
fill_in deadline_field, with: '2020-06-24'
fill_in time_allowed_field, with: '30'
fill_in additional_notes_field, with: 'Additional note about the task'
click_on 'Create Task request'
expect(page).to have_content task_created_message
end
scenario 'user can view task request details' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-07-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit project_task_request_path(project, TaskRequest.first)
expect(page).to have_content('Description of the task')
expect(page).to have_content('2020-07-23')
expect(page).to have_content('10')
expect(page).to have_content('Additional note about the task')
end
scenario 'user can update existing task request' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-08-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit edit_project_task_request_path(project, TaskRequest.first)
fill_in deadline_field, with: '2020-07-01'
fill_in time_allowed_field, with: '13'
click_on 'Update Task request'
expect(page).to have_content('13')
expect(page).to have_content('07/01/20')
end
scenario 'user can cancel a task request' do
create(:task_request, project: project, description: 'Description of the task', deadline: '2020-08-23', time_allowed: '10', additional_notes: 'Additional note about the task')
visit project_task_requests_path(project)
click_on 'Manage'
click_link 'Cancel'
expect(page).to have_content('Cancelled')
end
scenario 'user can view completed tasks' do
create_list(:task_request, 5, project: project, status: 'completed')
create_list(:task_request, 5, project: project, status: 'pending')
visit project_tasks_path(project)
expect(page).to have_content('Completed')
expect(page).not_to have_content('Pending')
end
private
def description_field
t "task_requests.form.labels.description"
end
def deadline_field
t "task_requests.form.labels.deadline"
end
def time_allowed_field
t "task_requests.form.labels.time_allowed"
end
def additional_notes_field
t "task_requests.form.labels.additional_notes"
end
def task_created_message
t 'task_requests.create.success_message'
end
end

View File

@@ -46,15 +46,17 @@ feature "User managing broadcasts" do
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("Copy 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")
end
click_on "Previous Sessions" click_on "Previous Sessions"
expect(page).to have_content(recording.download_file_name) expect(page).to have_content(recording.download_file_name)
end end
scenario "visit multi-view broadcast page", js: true do scenario "visit multi-view broadcast page", js: true do
broadcasts = create_list(:broadcast, 4, :with_stream, project: project) broadcast_one = create(:broadcast, :with_stream, :with_files, name: "Broadcast 1", project: project)
broadcast_two = create(:broadcast, :with_stream, :with_files, name: "Broadcast 2", project: project)
visit project_broadcasts_path(project) visit project_broadcasts_path(project)
click_checkboxes click_checkboxes
@@ -64,8 +66,16 @@ feature "User managing broadcasts" do
expect(page).to have_content("Switch View") expect(page).to have_content("Switch View")
click_on "Switch View" click_on "Switch View"
expect(page).to have_link(broadcasts.first.name) expect(page).to have_link("Broadcast 1")
expect(page).to have_link(broadcasts.second.name) expect(page).to have_link("Broadcast 2")
within "#files" do
click_on "Broadcast 1"
expect(page).to have_content("contract.pdf")
click_on "Broadcast 2"
expect(page).to have_content("contract.pdf")
end
end end
end end
end end
@@ -77,7 +87,7 @@ feature "User managing broadcasts" do
end end
def click_checkboxes def click_checkboxes
all('input[type="checkbox"]')[0].click
all('input[type="checkbox"]')[1].click all('input[type="checkbox"]')[1].click
all('input[type="checkbox"]')[2].click
end end
end end

View File

@@ -17,6 +17,7 @@ feature "User managing location releases" do
fill_in person_phone_field, with: "555-555-5555" fill_in person_phone_field, with: "555-555-5555"
fill_in person_email_field, with: "jane.doe@test.com" fill_in person_email_field, with: "jane.doe@test.com"
fill_in person_address_street1_field, with: "100 Broadway" fill_in person_address_street1_field, with: "100 Broadway"
fill_in filming_hours_field, with: "04:00 - 22:00"
draw_signature file_fixture("signature.png"), "location_release_signature_base64" draw_signature file_fixture("signature.png"), "location_release_signature_base64"
end end
@@ -51,6 +52,7 @@ feature "User managing location releases" do
by "filling out the remaining information" do by "filling out the remaining information" do
fill_in_release_fields name: "Test Location Release" fill_in_release_fields name: "Test Location Release"
fill_in filming_hours_field, with: "04:00 - 22:00"
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_photo("location_photo.png") expect(page).to have_photo("location_photo.png")
@@ -136,6 +138,7 @@ feature "User managing location releases" do
:native, :native,
project: project, project: project,
name: "Benny's Burritos", name: "Benny's Burritos",
filming_hours: "06:00 - 20:00",
tag_list: "Restaurant", tag_list: "Restaurant",
notes: [ notes: [
build(:note, build(:note,
@@ -172,6 +175,8 @@ feature "User managing location releases" do
expect(pdf_body).to have_content("Restaurant") expect(pdf_body).to have_content("Restaurant")
expect(pdf_body).to have_content photos_heading.upcase expect(pdf_body).to have_content photos_heading.upcase
expect(pdf_body).to have_content("location_photo.png") expect(pdf_body).to have_content("location_photo.png")
expect(pdf_body).to have_content("Filming Hours")
expect(pdf_body).to have_content("06:00 - 20:00")
end end
context "when the user is associate" do context "when the user is associate" do
@@ -222,6 +227,10 @@ feature "User managing location releases" do
"location_release[person_phone]" "location_release[person_phone]"
end end
def filming_hours_field
"location_release[filming_hours]"
end
def have_photo(filename, attr: "src") def have_photo(filename, attr: "src")
have_selector("img[#{attr}*='#{filename}']") have_selector("img[#{attr}*='#{filename}']")
end end

View File

@@ -1,116 +0,0 @@
require "rails_helper"
feature "User managing task requests" do
let(:current_user) { create(:user) }
let(:project) { create(:project, account: current_user.primary_account) }
before :each do
sign_in current_user
end
scenario "task requests table is visible" do
visit project_task_requests_path(project)
expect(page).to have_content "Created On"
expect(page).to have_content "Deadline"
expect(page).to have_content description_column
expect(page).to have_content "Time Allowed"
expect(page).to have_content "Status"
end
scenario "sees list of task requests" do
visit project_task_requests_path(project)
expect(page).to have_content no_task_requests_label
task_request = create(:task_request, project: project)
visit project_task_requests_path(project)
expect(page).not_to have_content no_task_requests_label
expect(page).to have_content task_request.created_at.try(:strftime, '%D')
expect(page).to have_content task_request.deadline.try(:strftime, '%D')
expect(page).to have_content task_request.time_allowed
expect(page).to have_content task_request.status.capitalize
end
scenario "full description is shown if description text is not truncated" do
visit project_task_requests_path(project)
task_request = create(:task_request, project: project, description: 'Short Desc')
visit project_task_requests_path(project)
expect(page).to have_content task_request.description
end
scenario "truncated description is shown if description text is too long" do
visit project_task_requests_path(project)
task_request = create(:task_request,
project: project,
description: long_description_text)
visit project_task_requests_path(project)
expect(page).not_to have_content task_request.description
truncated_text = "#{task_request.description[0..26]}...read more"
expect(page).to have_content truncated_text
end
scenario "full description is shown when user hovers over read more link in description colum", js: true do
visit project_task_requests_path(project)
task_request = create(:task_request,
project: project,
description: long_description_text)
visit project_task_requests_path(project)
page.execute_script '$("a[data-toggle=popover]").trigger("mouseover")'
expect(page).to have_content task_request.description
end
scenario "user does not see open deliverable action in manage dropdown if task status is not completed" do
task_request = create(:task_request, project: project)
visit project_task_requests_path(project)
click_on manage_button
expect(page).not_to have_content open_deliverable_action_label
end
scenario "user can click deliverable action in manage dropdown if task status is completed", js: true do
create(:task_request, project: project, status: "completed", deliverable_url: "/")
visit project_task_requests_path(project)
click_on manage_button
expect(page).to have_content open_deliverable_action_label
click_link open_deliverable_action_label
switch_to_window(windows.last)
expect(page).to have_content add_new_project_label
end
private
def no_task_requests_label
"Task requests will appear here"
end
def manage_button
t "task_requests.task_request.actions.manage"
end
def open_deliverable_action_label
t "task_requests.task_request.actions.open_deliverable"
end
def add_new_project_label
t "projects.index.actions.new"
end
def description_column
t 'task_requests.index.table_headers.task_request_description'
end
def long_description_text
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
end
end

View File

@@ -0,0 +1,45 @@
require "rails_helper"
describe AttachRecordingToZoomMeetingJob do
let(:project) { create(:project) }
let(:zoom_meeting) { create(:zoom_meeting, project: project) }
let(:recording_hash) { {'id' => 'recording-id', 'download_url' => 'http://download.url', 'recording_start' => '2020-05-22 16:33:50 UTC', 'recording_end' => '2020-05-22 17:34:06 UTC'} }
let(:download_token) { 'download_token' }
before :each do
allow_any_instance_of(ZoomGateway).to receive(:delete_recording)
end
describe ".perform_now" do
it "downloads the video" do
allow(zoom_meeting.recording).to receive(:attach)
expect(URI).to receive(:open).with("http://download.url?access_token=download_token")
AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
end
it "deletes the recording through the API" do
stub_uri_open
allow(zoom_meeting.recording).to receive(:attach).and_return(true)
expect_any_instance_of(ZoomGateway).to receive(:delete_recording).with(zoom_meeting.api_meeting_id, 'recording-id')
AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
end
it "attaches downloaded video to recording" do
allow(zoom_meeting.recording).to receive(:attach)
stub_uri_open
AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
expect(zoom_meeting.recording).to have_received(:attach).with(hash_including(content_type: 'video/mp4'))
end
end
private
def stub_uri_open
url = "http://download.url?access_token=download_token"
file = double(:file, read: 'stubbed read')
allow(URI).to receive(:open).with(url).and_return(file)
end
end

View File

@@ -1,36 +0,0 @@
require 'rails_helper'
RSpec.describe SubmitHubspotTaskRequestFormJob, type: :job do
describe '#perform_now' do
before do
ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"] = "hubspot_task_request_form_guid"
end
it 'submits to the Hubspot API with the right params' do
form = double(:form)
allow(Hubspot::Form).to receive(:new).and_return(form)
allow(form).to receive(:submit).and_return(true)
SubmitHubspotTaskRequestFormJob.perform_now("email@test.com", "https://example.com/admin/task_requests/1")
expect(Hubspot::Form).to have_received(:new).with("guid" => "hubspot_task_request_form_guid")
expect(form).to have_received(:submit).with(
email: "email@test.com",
taskme_url: "https://example.com/admin/task_requests/1"
)
end
context 'when HUBSPOT_TASK_REQUEST_FORM_GUID is not available' do
it 'does not submit to the API' do
ENV["HUBSPOT_TASK_REQUEST_FORM_GUID"] = nil
form = double(:form)
allow(Hubspot::Form).to receive(:new).and_return(form)
allow(form).to receive(:submit)
SubmitHubspotTaskRequestFormJob.perform_now("email@test.com", "https://example.com/admin/task_requests/1")
expect(form).not_to have_received(:submit)
end
end
end
end

View File

@@ -64,6 +64,21 @@ RSpec.describe ZoomGateway do
expect(ZoomGateway.HOST_ROLE).to eq('pro-directme-host') expect(ZoomGateway.HOST_ROLE).to eq('pro-directme-host')
end end
end end
context '.enable_recordings?' do
it 'is truthy when ZOOM_ENABLE_RECORDINGS is set to 1' do
stub_env_variable('ZOOM_ENABLE_RECORDINGS', '1')
expect(ZoomGateway.enable_recordings?).to be_truthy
end
it 'is falsey otherwise' do
stub_env_variable('ZOOM_ENABLE_RECORDINGS', '0')
expect(ZoomGateway.enable_recordings?).to be_falsey
stub_env_variable('ZOOM_ENABLE_RECORDINGS', '2')
expect(ZoomGateway.enable_recordings?).to be_falsey
end
end
end end
describe ".find_meeting" do describe ".find_meeting" do
@@ -111,6 +126,13 @@ RSpec.describe ZoomGateway do
end end
end end
describe '.delete_recording' do
it 'calls api client to delete recording' do
expect_any_instance_of(Zoom.new.class).to receive(:recording_delete)
gateway.delete_recording('meeting-id', 'recording-id')
end
end
private private
def stub_env_variable(name, value) def stub_env_variable(name, value)

View File

@@ -66,14 +66,16 @@ RSpec.describe Account do
end end
describe "#storage_total" do describe "#storage_total" do
it "sums videos, release photos, contracts, signatures" do it "sums videos, release photos, contracts, signatures, recordings" do
video_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4") video_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
recording_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
photo_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "person_photo.png"), "image/png") photo_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "person_photo.png"), "image/png")
contract_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "contract.pdf"), "application/pdf") contract_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "contract.pdf"), "application/pdf")
signature_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "signature.png"), "image/png") signature_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "signature.png"), "image/png")
edl_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "sample-edl.edl"), "application/octet-stream") edl_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "sample-edl.edl"), "application/octet-stream")
expect(video_file.size).to eq 1_055_736 expect(video_file.size).to eq 1_055_736
expect(recording_file.size).to eq 1_055_736
expect(edl_file.size).to eq 440 expect(edl_file.size).to eq 440
expect(photo_file.size).to eq 910 expect(photo_file.size).to eq 910
expect(contract_file.size).to eq 12 expect(contract_file.size).to eq 12
@@ -89,8 +91,9 @@ RSpec.describe Account do
acquired_media_release = create(:acquired_media_release, project: project, contract: contract_file) acquired_media_release = create(:acquired_media_release, project: project, contract: contract_file)
import = create(:import, project: project, file: contract_file) import = create(:import, project: project, file: contract_file)
music_release = create(:music_release, project: project, contract: contract_file) music_release = create(:music_release, project: project, contract: contract_file)
zoom_meeting = create(:zoom_meeting, project: project, recording: recording_file)
expect(account.storage_total).to eq 1_069_936 expect(account.storage_total).to eq 2_125_672
end end
it "sums only for projects tied to account" do it "sums only for projects tied to account" do
@@ -126,8 +129,8 @@ RSpec.describe Account do
Download, Download,
User, User,
Broadcast, Broadcast,
TaskRequest, Account,
Account ZoomMeeting
] ]
Rails.application.eager_load! Rails.application.eager_load!
ActiveRecord::Base.descendants.each do |model| ActiveRecord::Base.descendants.each do |model|

View File

@@ -6,6 +6,7 @@ describe HeadshotCollection do
project = create(:project, project = create(:project,
appearance_releases: create_list(:appearance_release, 1), appearance_releases: create_list(:appearance_release, 1),
talent_releases: create_list(:talent_release, 1), talent_releases: create_list(:talent_release, 1),
headshot_collection_uid: "123abc"
) )
collection = HeadshotCollection.for_project(project) collection = HeadshotCollection.for_project(project)
@@ -14,7 +15,7 @@ describe HeadshotCollection do
expect(collection).to be_a(HeadshotCollection) expect(collection).to be_a(HeadshotCollection)
expect(collection.releasables).to include(project.appearance_releases.first) expect(collection.releasables).to include(project.appearance_releases.first)
expect(collection.releasables).to include(project.talent_releases.first) expect(collection.releasables).to include(project.talent_releases.first)
expect(collection.collection_uid).to eq(project.id) expect(collection.collection_uid).to eq(project.headshot_collection_uid)
end end
context "when a release has no headshot photo attachment" do context "when a release has no headshot photo attachment" do
@@ -85,6 +86,17 @@ describe HeadshotCollection do
expect(mapping["appearance_release_#{releases.first.id}"]).to include("123") expect(mapping["appearance_release_#{releases.first.id}"]).to include("123")
expect(mapping["talent_release_#{releases.last.id}"]).to include("456") expect(mapping["talent_release_#{releases.last.id}"]).to include("456")
end end
context "when collection uid is blank" do
it "is not included in the hash" do
releases = []
collection = HeadshotCollection.new(nil, releases)
hash = collection.to_hash
expect(hash.keys).not_to include(:collection_uid)
end
end
end end
private private

View File

@@ -1,16 +0,0 @@
require 'rails_helper'
RSpec.describe TaskRequest, type: :model do
describe "associations" do
it { is_expected.to belong_to(:project) }
end
describe "enums" do
it { is_expected.to define_enum_for(:status).with_values([:pending, :completed, :cancelled]) }
end
describe "#order_by_recent" do
subject { described_class }
it { is_expected.to respond_to(:order_by_recent) }
end
end

View File

@@ -16,6 +16,17 @@ RSpec.describe ZoomMeeting, type: :model do
end end
describe "attachments" do
it { is_expected.to respond_to(:recording) }
end
describe "validations" do
context '#recording' do
it { is_expected.to allow_content_type("video/mp4").for(:recording) }
it { is_expected.not_to allow_content_types("image/png").for(:recording) }
end
end
describe 'associations' do describe 'associations' do
it { is_expected.to belong_to(:zoom_user) } it { is_expected.to belong_to(:zoom_user) }
it { is_expected.to belong_to(:project).optional(true) } it { is_expected.to belong_to(:project).optional(true) }

View File

@@ -15,6 +15,10 @@ describe ContractTemplatePolicy do
it { is_expected.not_to permit(user_context, :create) } it { is_expected.not_to permit(user_context, :create) }
end end
permissions :show? do
it { is_expected.to permit(user_context, :show) }
end
permissions :destroy? do permissions :destroy? do
it { is_expected.not_to permit(user_context, contract_template) } it { is_expected.not_to permit(user_context, contract_template) }
@@ -33,6 +37,32 @@ describe ContractTemplatePolicy do
it { is_expected.to permit(user_context, :create) } it { is_expected.to permit(user_context, :create) }
end end
permissions :show? do
it { is_expected.to permit(user_context, :show) }
end
permissions :destroy? do
it { is_expected.to permit(user_context, contract_template) }
context "when there are associated releases" do
let(:contract_template) { create(:contract_template, appearance_releases: build_list(:appearance_release, 1)) }
it { is_expected.to permit(user_context, contract_template) }
end
end
end
context "for an account manager" do
let(:user) { create(:user, :account_manager) }
permissions :create? do
it { is_expected.to permit(user_context, :create) }
end
permissions :show? do
it { is_expected.to permit(user_context, :show) }
end
permissions :destroy? do permissions :destroy? do
it { is_expected.to permit(user_context, contract_template) } it { is_expected.to permit(user_context, contract_template) }
@@ -79,7 +109,7 @@ describe ContractTemplatePolicy do
context "for associate" do context "for associate" do
let(:user) { create(:user, :associate, primary_account: account) } let(:user) { create(:user, :associate, primary_account: account) }
it { is_expected.not_to include(member_project.contract_templates.first) } it { is_expected.to include(member_project.contract_templates.first) }
it { is_expected.not_to include(non_member_project.contract_templates.first) } it { is_expected.not_to include(non_member_project.contract_templates.first) }
it { is_expected.not_to include(outside_project.contract_templates.first) } it { is_expected.not_to include(outside_project.contract_templates.first) }
end end