Compare commits

..

8 Commits

Author SHA1 Message Date
bilal
43e69d1e88 change text and spec 2020-06-22 19:22:23 +02:00
bilal
9f4cb16016 update notice text when creating task request 2020-06-19 12:36:16 +02:00
Senad Uka
3e917c29f0 task me sync 2020-06-19 12:32:50 +02:00
Senad Uka
8ad89371b8 Task mvp upstream sync 2020-06-15 11:02:00 +02:00
Senad Uka
9d7e2c044a Upstream sync task me 2020-06-09 06:34:58 +02:00
Senad Uka
88836e937e Task me sync 2020-06-03 07:24:01 +02:00
bilal
e3d4d22a34 Handle QrMatching response - mock 2020-06-02 22:23:19 +02:00
Senad Uka
3690268f83 Sync of the branch 2020-06-01 18:59:15 +02:00
188 changed files with 1783 additions and 2786 deletions

View File

@@ -95,28 +95,14 @@ rake i18n:sort
```
## Zoom.us integration
DirectMe app offers live broadcasting feature. Users are offered to paralelly connect to the Zoom meeting to have a video conference while the streaming happens. In order to use the Zoom functionality, the app needs to have the API and verification token keys provided along with the account number that is available after login into the Zoom account. You need to have Zoom PRO subscription in order to use this feature.
DirectMe app offers live broadcasting. Users are offered to paralelly connect to the Zoom meeting to have a video conference while the streaming happens. In order to use the Zoom functionality, the app needs to have the API keys provided. You need Zoom PRO account for this feature.
#### Zoom.us api keys
1. Log in to you zoom.us account
2. Go to https://marketplace.zoom.us/develop/create
3. Choose JWT application
4. Copy API Key and API Secret
5. Set up ZOOM_API_KEY and ZOOM_API_SECRET environment variables
#### Setup
There is some configuration that has to be done through the API on the Zoom account so that you can use the feature. Run `rails zoom:setup` rake task to do it.
#### Zoom.us webhooks
To ensure integrity in between different Zoom environments, the app uses Zoom webhooks. To set them up, go to https://marketplace.czoom.us -> Develop -> JWT app -> Feature -> Event Subscriptions and enable following hooks:
* Start Meeting
* End Meeting
* All Recordings have completed
* User has been created
* User had been deleted
#### Syncing app with Zoom account configuration
If you are setting up the app to use Zoom account that has been previously used with DirectME, it is a good idea to make sure that the db state reflects the account situation. To do that, run `rails zoom:sync` rake task.
## Working Locally

View File

@@ -1,23 +1,22 @@
$(document).on "turbolinks:load", ->
subscribeToBroadcast = (broadcastToken) -> App.cable.subscriptions.create { channel: "BroadcastsChannel", token: broadcastToken },
# Only connect if a broadcast-token meta tag is present
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: ->
# Called when the subscription is ready for use on the server
console.info "Subscribed to channel for broadcast:#{broadcastToken}"
disconnected: ->
# Called when the subscription has been terminated by the server
received: (data) ->
return unless document.querySelector("meta[name=broadcast-token][content='#{broadcastToken}']")
switch data.event
when "broadcast_stream_update"
return unless document.querySelector("meta[name=broadcast-token][current=true][content='#{broadcastToken}']")
@refreshBroadcastVideo(data)
when "stream_recording_ready"
return unless document.querySelector("meta[name=broadcast-token][current=true][content='#{broadcastToken}']")
@showBroadcastRecordings(data)
when "file_upload_update"
return unless document.querySelector("meta[name=broadcast-token][content='#{broadcastToken}']")
@refreshBroadcastFilesTab(data)
when "broadcast_stream_update" then @refreshBroadcastVideo(data)
when "stream_recording_ready" then @showBroadcastRecordings(data)
refreshBroadcastVideo: (data) ->
$("#broadcast_updates").html data.status_content
@@ -38,12 +37,3 @@ $(document).on "turbolinks:load", ->
$(".flash-message").html data.flash_content
$("#broadcast_recordings").html data.recordings_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,7 +16,6 @@ $(document).on "turbolinks:load", ->
switch data.event
when "video_status_update" then @showVideoStatusUpdate(data.content)
when "download_status_update" then @showDownloadStatusUpdate(data.content)
when "conference_recording_ready" then @showDownloadStatusUpdate(data.content)
showVideoStatusUpdate: (content) ->
$("[data-ujs-target='video-analysis-msg']").replaceWith content

View File

@@ -1,16 +1,11 @@
$(document).on("change", "[data-toggle=collapse-select]", function(event) {
const select = event.target;
const mappings = JSON.parse(select.dataset.targetShowValuesMapping);
$.each(mappings, function( key, value ) {
if (value.indexOf(select.value) > -1) {
$(key).show("fast");
} else {
$(key).hide("fast");
}
});
});
const target = select.dataset.target;
const showValues = JSON.parse(select.dataset.showValues);
$(document).on("turbolinks:load", function() {
$("[data-toggle=collapse-select]").trigger("change");
});
if (showValues.indexOf(select.value) > -1) {
$(target).show("fast");
} else {
$(target).hide("fast");
}
});

View File

@@ -39,7 +39,7 @@ function selectBroadcast(clicked_element, checkbox) {
if (broadcast_ids.length >= 2) {
multi_view_ids = $.param({multi_view_ids: broadcast_ids});
broadcast_url = "/en/projects/" + project_id + "/broadcasts/" + broadcast_ids[0] + "?" + multi_view_ids
$("#multi_view_broadcasts").attr("href", broadcast_url);
$("#multi_view_broadcasts").attr("target", "_blank");
$("#multi_view_broadcasts").removeClass('disabled');

View File

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

View File

@@ -6,11 +6,6 @@
@import "dropzone/dist/dropzone";
@import 'bootstrap-datepicker';
// Global styles
label {
text-transform: capitalize;
}
// Wordmarks
.suite-wordmark {
font-weight: normal;
@@ -37,14 +32,14 @@ label {
&.release-me {
span:last-child {
background-color: $teal;
color: $body-color;
color: $white;
}
}
&.direct-me {
span:last-child {
background-color: $green;
color: $body-color;
color: $white;
}
}
@@ -58,7 +53,14 @@ label {
&.deliver-me {
span:last-child {
background-color: $purple;
color: white;
color: $white;
}
}
&.task-me {
span:last-child {
background-color: $yellow;
color: $white;
}
}

View File

@@ -31,7 +31,7 @@ u {
}
.page {
page-break-before: always;
page-break-before: always;
}
.logo {
@@ -44,14 +44,6 @@ u {
text-align: right;
}
.qr-code {
margin-right: -30px;
}
.do-not-copy-warning {
padding-right: 15px;
}
.heading-table td {
width: 50%;
}

View File

@@ -28,21 +28,10 @@ class BroadcastsChannel < ApplicationCable::Channel
recordings_content = ApplicationController.render partial: "broadcasts/broadcast_recordings", locals: { recordings: recordings, broadcast: broadcast }
recordings_nav_content = ApplicationController.render partial: "broadcasts/broadcast_recording_nav", collection: recordings, as: :broadcast_recording
broadcast_to broadcast,
event: :stream_recording_ready,
flash_content: flash_content,
broadcast_to broadcast,
event: :stream_recording_ready,
flash_content: flash_content,
recordings_content: recordings_content,
recordings_nav_content: recordings_nav_content
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

View File

@@ -1,5 +1,5 @@
class ProjectsChannel < ApplicationCable::Channel
def subscribed
# TODO: How can we get the current account in this context
project = current_user.accessible_projects_for(current_user.primary_account).find(params[:id])
@@ -25,12 +25,4 @@ class ProjectsChannel < ApplicationCable::Channel
content = ApplicationController.render partial: "application/flash", locals: { flash: flash }
broadcast_to download.project, event: :download_status_update, content: content
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

View File

@@ -61,8 +61,7 @@ class AcquiredMediaReleasesController < ApplicationController
:name,
:territory,
:term,
:person_first_name,
:person_last_name,
:person_name,
:person_phone,
:person_email,
:person_company,

View File

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

@@ -1,50 +0,0 @@
# Duplicated from ActiveStorage::DirectUploadsController
# https://github.com/rails/rails/blob/v6.0.0/activestorage/app/controllers/active_storage/direct_uploads_controller.rb
class Api::DirectUploadsController < Api::ApiController
include ActiveStorage::SetCurrent
deserializable_resource :direct_upload, only: [:create]
def create
blob = ActiveStorage::Blob.create_before_direct_upload!(blob_params)
render jsonapi: DirectUpload.new(blob)
end
private
def blob_params
params.
require(:direct_upload).
permit(:type, :filename, :byte_size, :checksum, :content_type, :metadata).
except(:type).
to_h.symbolize_keys
end
class DeserializableDirectUpload < JSONAPI::Deserializable::Resource
attributes :filename, :byte_size, :checksum, :content_type, :metadata
end
class SerializableDirectUpload < JSONAPI::Serializable::Resource
type 'direct_upload'
attributes :id, :key, :signed_id, :url, :headers
end
class DirectUpload
delegate :id, :key, :signed_id, to: :blob
attr_reader :blob
def initialize(blob)
@blob = blob
end
def url
blob.service_url_for_direct_upload
end
def headers
blob.service_headers_for_direct_upload
end
end
end

View File

@@ -3,6 +3,7 @@
class AppearanceReleaseImportsController < ApplicationController
include AppearanceReleaseContext
include ProjectContext
include CreateReleasableJobs
before_action :set_project, only: [:create]
@@ -10,16 +11,24 @@ class AppearanceReleaseImportsController < ApplicationController
def create
authorize AppearanceRelease
@failed_files = []
attachments = appearance_release_params
if attachments.nil?
alert_message = t 'appearance_releases.create.no_attachments'
redirect_to [@project, :appearance_releases], alert: alert_message
else
MatchAppearanceReleasesJob.perform_later(@project, attachments)
notice_message = t 'appearance_releases.create.matching_started'
redirect_to [@project, :appearance_releases], notice: notice_message
attachments.each do |attachment|
create_imported_appearance_release attachment
end
end
unless @failed_files.empty?
alert_message = t 'appearance_releases.create.failed_import'
alert_message += '<br><ul>'
@failed_files.each { |file_name| alert_message += "<li>#{file_name}</li>" }
alert_message += '</ul>'
end
redirect_to [@project, :appearance_releases], alert: alert_message
end
private
@@ -36,7 +45,45 @@ class AppearanceReleaseImportsController < ApplicationController
params.require(:attachments)
end
def acceptable_extensions
AppearanceRelease.acceptable_import_file_extensions
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
def create_imported_appearance_release(attachment)
blob = ActiveStorage::Blob.find_signed(attachment)
return if blob.nil?
extension = blob.filename.extension_with_delimiter
unless AppearanceRelease.acceptable_import_file_extensions.include? extension
blob.purge
@failed_files << blob.filename
return
end
random_contract_no = AppearanceRelease.random_contract_number.to_s
appearance_release_params = {
person_last_name: random_contract_no
}
if blob.image?
appearance_release_params[:person_photo] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_headshot_name')
elsif extension == '.pdf'
appearance_release_params[:contract] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_contract_name')
end
appearance_release = build_appearance_release(appearance_release_params)
if appearance_release.save(context: :non_native)
log_create_analytics
after_create appearance_release
else
@failed_files << blob.filename
end
end
end

View File

@@ -78,8 +78,8 @@ class AppearanceReleasesController < ApplicationController
end
def appearance_release_params
params.require(:appearance_release).permit(:contract, :guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :guardian_email, :minor,
:person_address_street1, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
params.require(:appearance_release).permit(:contract, :guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text, :person_date_of_birth,

View File

@@ -1,6 +1,6 @@
class BroadcastsController < ApplicationController
layout "project"
before_action :set_project
before_action :build_broadcast, only: [:new, :create]
before_action :set_broadcast, only: [:show, :destroy, :update]
@@ -24,19 +24,16 @@ class BroadcastsController < ApplicationController
end
end
def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
render layout: 'application'
end
def update
@broadcast.update(broadcast_params)
@files = @broadcast.files.order("created_at DESC").paginate(page: 1)
end
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)
def show
@conference_url = url_for [@broadcast.project, @broadcast, :zoom_meeting]
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page])
render layout: 'application'
end
def destroy
@@ -71,10 +68,7 @@ class BroadcastsController < ApplicationController
def set_multi_view_broadcasts
authorized_broadcasts = authorize policy_scope(Broadcast).where(id: params[:multi_view_ids]).order_by_recent
@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
@multi_view_broadcasts = authorized_broadcasts.map { |b| MultiViewBroadcast.new(b, params[:multi_view_ids]) }
end
def filtered_broadcasts
@@ -93,29 +87,20 @@ class BroadcastsController < ApplicationController
class MultiViewBroadcast
include Rails.application.routes.url_helpers
delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_ids, paginate_page)
def initialize(broadcast, multi_view_ids)
@broadcast = broadcast
@multi_view_ids = multi_view_ids
@paginate_page = paginate_page
end
def url
project_broadcast_path(@broadcast.project, @broadcast, multi_view_ids: @multi_view_ids, locale: I18n.locale)
end
def files
@broadcast.files.order("created_at DESC").paginate(page: @paginate_page)
end
def uid
id
end
def self.model_name
Broadcast.model_name
end
end
end

View File

@@ -1,13 +0,0 @@
module MedicalReleaseContext
extend ActiveSupport::Concern
def medical_releases
policy_scope(MedicalRelease)
end
def set_medical_release
medical_release_id = params[:medical_release_id] || params[:id]
@medical_release = authorize medical_releases.find(medical_release_id)
end
end

View File

@@ -61,12 +61,7 @@ class ContractTemplatesController < ApplicationController
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
:question_1_text, :question_2_text,
:question_3_text, :question_4_text,
:question_5_text, :question_6_text,
:question_7_text, :question_8_text,
:question_9_text, :question_10_text)
:restriction_id, :restriction_text)
end
def download_attributes

View File

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

View File

@@ -1,40 +0,0 @@
class MedicalReleasesController < ApplicationController
include ProjectContext, MedicalReleaseContext
before_action :set_project, only: [:index]
before_action :set_medical_release, only: [:destroy]
include ProjectLayout
def index
@medical_releases = filtered_medical_releases.order_by_recent.paginate(page: params[:page])
end
def destroy
@project = @medical_release.project
if @medical_release.destroy
redirect_to [@project, :medical_releases], alert: t(".alert")
end
end
private
def medical_releases
if @project
policy_scope(@project.medical_releases)
else
policy_scope(MedicalRelease)
end
end
def filtered_medical_releases
results = medical_releases
if params[:query].present?
results = results.search(params[:query])
end
results
end
end

View File

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

View File

@@ -60,7 +60,7 @@ class ProjectsController < ApplicationController
end
def features_settings_params
%i(appearance_release location_release material_release acquired_media_release music_release talent_release medical_release video_analysis)
%i(appearance_release location_release material_release acquired_media_release music_release talent_release video_analysis)
end
def project_params_with_current_account

View File

@@ -45,9 +45,6 @@ class Public::AcquiredMediaReleasesController < Public::BaseController
params.require(:acquired_media_release).permit(
:name,
:description,
:person_first_name,
:person_last_name,
:person_email,
:person_title,
:person_phone,
:person_fax,

View File

@@ -39,25 +39,9 @@ class Public::AppearanceReleasesController < Public::BaseController
authorize appearance_releases.build(params)
end
def person_params
%i[
person_first_name
person_last_name
person_phone
person_email
person_photo
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
]
end
def appearance_release_params
params.require(:appearance_release).permit(person_params,
:guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_email, :guardian_photo, :minor,
params.require(:appearance_release).permit(:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
:signature_base64, :person_date_of_birth,
:locale, :contract_template,)
end

View File

@@ -6,17 +6,14 @@ class Public::BroadcastsController < Public::BaseController
@conference_url = broadcast_zoom_meeting_url(@broadcast.token)
@multi_view_broadcasts = multi_view_broadcasts
@recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_page])
@files = @broadcast.files.order("created_at DESC").paginate(page: params[:page])
render 'broadcasts/show'
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
private
@@ -29,10 +26,7 @@ class Public::BroadcastsController < Public::BaseController
Broadcast.
where(token: params[:multi_view_tokens]).
order_by_recent.
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
map { |b| MultiViewBroadcast.new(b, params[:multi_view_tokens]) }
end
def set_broadcast
@@ -41,29 +35,20 @@ class Public::BroadcastsController < Public::BaseController
class MultiViewBroadcast
include Rails.application.routes.url_helpers
delegate_missing_to :@broadcast
def initialize(broadcast, multi_view_tokens, paginate_page)
def initialize(broadcast, multi_view_tokens)
@broadcast = broadcast
@multi_view_tokens = multi_view_tokens
@paginate_page = paginate_page
end
def url
broadcast_url(uid, multi_view_tokens: @multi_view_tokens, host: AppHost.new.domain_with_port, locale: I18n.locale)
end
def files
@broadcast.files.order("created_at DESC").paginate(page: @paginate_page)
end
def uid
token
end
def self.model_name
Broadcast.model_name
end
end
end

View File

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

View File

@@ -45,7 +45,7 @@ class Public::MaterialReleasesController < Public::BaseController
:person_first_name, :person_last_name, :person_title, :person_company, :person_phone, :person_email,
:person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
:signature_base64,
:locale, :contract_template, :description, photos: []
:locale, :contract_template, :description
)
end

View File

@@ -1,86 +0,0 @@
class Public::MedicalReleasesController < Public::BaseController
before_action :set_account, :set_project, :set_contract_template
def new
@medical_release = build_medical_release
end
def create
@medical_release = build_medical_release(medical_release_params_with_locale_and_contract_template)
if @medical_release.save(context: :native)
if @medical_release.contract_template.present?
AttachContractToReleasableJob.perform_later(@medical_release)
end
log_create_analytics
else
render :new
end
end
private
def set_project
@project = @account.projects.find(params[:project_id])
end
def set_account
@account = Account.find_by(slug: params[:account_id])
end
def set_contract_template
@contract_template = @project.contract_templates.find(params[:contract_template_id])
end
def medical_releases
policy_scope(@project.medical_releases)
end
def build_medical_release(params = {})
authorize medical_releases.build(params)
end
def medical_release_params
params
.require(:medical_release)
.permit(
person_params,
:signature_base64,
:locale,
:contract_template,
:question_1_answer, :question_2_answer,
:question_3_answer, :question_4_answer,
:question_5_answer, :question_6_answer,
:question_7_answer, :question_8_answer,
:question_9_answer, :question_10_answer,
photos: [],
)
end
def person_params
[
:person_first_name,
:person_last_name,
:person_phone,
:person_email,
:person_address_street1,
:person_address_street2,
:person_address_city,
:person_address_state,
:person_address_zip,
:person_address_country,
]
end
def medical_release_params_with_locale
medical_release_params.merge(locale: I18n.locale)
end
def medical_release_params_with_locale_and_contract_template
medical_release_params_with_locale.merge(contract_template: @contract_template)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(nil, nil, :track_create_native_release, release_type: MedicalRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
end
end

View File

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

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

@@ -5,7 +5,7 @@ class ZoomNotificationsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_zoom
before_action :set_zoom_meeting, only: [:create], if: :meeting_event?
before_action :set_zoom_meeting, only: :create
def create
case notification_event
@@ -13,17 +13,8 @@ class ZoomNotificationsController < ApplicationController
@zoom_meeting.started!
when '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'])
when 'user.deleted'
zoom_user = ZoomUser.find_by(api_id: notification.dig(:payload, :object, :id))
if zoom_user.present?
zoom_user.api_id = nil
zoom_user.destroy
end
else
Rails.logger.info notification_event
Rails.logger.info notification_type
Rails.logger.info notification
end
@@ -32,24 +23,16 @@ class ZoomNotificationsController < ApplicationController
private
def notification
params.to_unsafe_h
end
def notification_event
notification.dig(:event)
params.dig(:event)
end
def notification_meeting_id
notification.dig(:payload, :object, :id)
params.dig(:payload, :object, :id)
end
def notification_host_id
notification.dig(:payload, :object, :host_id)
end
def meeting_event?
notification_event.split(".").first.to_s.in? %w(meeting recording)
params.dig(:payload, :object, :host_id)
end
def set_zoom_meeting

View File

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

View File

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

View File

@@ -3,14 +3,12 @@ module DropzoneHelper
case releasable.model_name.param_key
when "acquired_media_release"
"To Add Photos & Videos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera"
when "material_release"
t 'material_releases.form.photos.dropzone_label'
when "music_release"
"To Add Audio Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "location_release"
t 'location_releases.form.photos.dropzone_label'
when "directory"
"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
"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

View File

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

View File

@@ -1,25 +0,0 @@
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,100 +0,0 @@
# frozen_string_literal: true
class MatchAppearanceReleasesJob < ApplicationJob
queue_as :default
def perform(project, attachments)
filtered_attachments_object = filter_attachments attachments
return if filtered_attachments_object[:keys].blank?
matching_request = MatchingRequest.create project: project, attachments: filtered_attachments_object[:signed_ids]
payload = { request_id: matching_request.id, bucket: aws_bucket_name, files: filtered_attachments_object[:keys]}
response = BrayniacAI::QrMatching.create! payload
matches = response.matches || []
key_signed_id_hash = Hash[filtered_attachments_object[:keys].zip(filtered_attachments_object[:signed_ids])]
handle_matches matches, project, key_signed_id_hash
matching_request.destroy
end
private
def handle_matches(matches, project, key_signed_id_hash)
matches.each do |match|
contract_key = Array.wrap(match.contracts).first
headshot_key = Array.wrap(match.headshots).first
identifier = match.identifier
contract = key_signed_id_hash[contract_key]
headshot = key_signed_id_hash[headshot_key]
next if contract.nil? && headshot.nil?
identified_release = identifier.blank? ? nil : AppearanceRelease.find_by(identifier: identifier)
if identified_release.nil?
create_release project, contract, headshot, identifier
else
update_release identified_release, contract, headshot
end
end
end
def create_release(project, contract, headshot, identifier)
random_contract_no = AppearanceRelease.random_contract_number.to_s
is_incomplete = contract.nil? || headshot.nil?
params = {
project: project,
person_first_name: appearance_first_name(is_incomplete),
person_last_name: random_contract_no
}
params[:person_photo] = headshot unless headshot.nil?
params[:contract] = contract unless contract.nil?
params[:identifier] = identifier unless blank?
return if AppearanceRelease.create(params)
logger.error "Failed to create AppearanceRelease with params : \r\n#{params}"
end
def update_release(release, contract, headshot)
release.contract = contract unless contract.nil?
release.person_photo = headshot unless headshot.nil?
release.save
end
def appearance_first_name(incomplete)
if incomplete
I18n.t('appearance_releases.shared.incomplete_match')
else
I18n.t('appearance_releases.shared.matched_import')
end
end
def aws_bucket_name
ENV.fetch 'AWS_BUCKET'
end
def filter_attachments(attachments)
filtered_attachments_keys = []
filtered_attachments_signed_ids = []
attachments.each do |attachment|
blob = ActiveStorage::Blob.find_signed attachment
next if blob.nil?
extension = blob.filename.extension
next unless blob.image? || extension == 'pdf'
filtered_attachments_keys << blob.key
filtered_attachments_signed_ids << attachment
end
{
keys: filtered_attachments_keys,
signed_ids: filtered_attachments_signed_ids
}
end
end

View File

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

View File

@@ -43,8 +43,7 @@ class AcquiredMediaRelease < ApplicationRecord
person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country
]
# CATEGORIES = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze
CATEGORIES = ["Film Footage", "Video Footage", "Still Photograph"].freeze
CATEGORIES = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze
def minor?
false

View File

@@ -16,17 +16,6 @@ class AppearanceRelease < ApplicationRecord
has_one_attached :person_photo
composed_of :person_address,
class_name: 'Address',
mapping: [
%w[person_address_street1 street1],
%w[person_address_street2 street2],
%w[person_address_city city],
%w[person_address_state state],
%w[person_address_zip zip],
%w[person_address_country country]
]
# These validations apply to all releases
validates :person_email, email: true, allow_blank: true
validates :person_first_name, :person_last_name, presence: true
@@ -50,7 +39,6 @@ class AppearanceRelease < ApplicationRecord
# These validations apply to releases being signed by a minor
with_options if: :minor? do
validates :guardian_first_name, :guardian_last_name, presence: true
validates :guardian_email, email: true, allow_blank: true
end
validates :person_photo, content_type: face_photo_acceptable_content_types
@@ -82,18 +70,7 @@ class AppearanceRelease < ApplicationRecord
scope :having_no_person_photo, -> { left_joins(:person_photo_attachment).group(:id).having('COUNT(active_storage_attachments) = 0') }
scope :with_person_name, ->(name) { where('person_first_name ILIKE ? OR person_last_name ILIKE ?', "%#{name}%") }
searchable_on %i[
person_first_name
person_last_name
person_address_street1
person_address_street2
person_address_city
person_address_state
person_address_zip
person_address_country
person_email
person_phone
]
searchable_on %i[person_first_name person_last_name person_address person_email person_phone]
# All releases must respond to the following messages
def name

View File

@@ -8,7 +8,7 @@ class BlankContract
end
def to_pdf
kit = PDFKit.new(as_html, margin_right: 1, margin_left: 1, margin_top: 10, margin_bottom: 1)
kit = PDFKit.new(as_html)
kit.to_file("tmp/#{filename}")
end

View File

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

View File

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

View File

@@ -1,9 +0,0 @@
# frozen_string_literal: true
module Attachable
extend ActiveSupport::Concern
included do
has_many_attached :attachments
end
end

View File

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

View File

@@ -13,7 +13,6 @@ class ContractTemplate < ApplicationRecord
has_many :acquired_media_releases, dependent: :restrict_with_error
has_many :location_releases, dependent: :restrict_with_error
has_many :material_releases, dependent: :restrict_with_error
has_many :medical_releases, dependent: :restrict_with_error
monetize :fee_cents
has_rich_text :body

View File

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

View File

@@ -1,7 +0,0 @@
# frozen_string_literal: true
class MatchingRequest < ApplicationRecord
include Attachable
belongs_to :project
end

View File

@@ -1,71 +0,0 @@
class MedicalRelease < ApplicationRecord
include Contractable
include Notable
include Photoable
include Releasable
include Searchable
include Signable
include Syncable
include PersonName
composed_of :person_address,
class_name: "Address",
mapping: [
%w(person_address_street1 street1),
%w(person_address_street2 street2),
%w(person_address_city city),
%w(person_address_state state),
%w(person_address_zip zip),
%w(person_address_country country)
]
def self.face_photo_acceptable_content_types
["image/png", "image/jpeg"]
end
# These validations apply to all releases
validates :person_first_name, :person_last_name, presence: true
validates :person_email, email: true, allow_blank: true
acts_as_taggable_on :internal_tags, :tags
# These validations apply to releases created natively by the system (i.e. not imported from elsewhere)
with_options on: :native do
validates :signature, attached: true
end
# These validations apply to releases imported to the system from an outside source
with_options on: :non_native do
validates :contract, attached: true
end
searchable_on %i[
person_first_name person_last_name person_email person_phone
person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country
]
# All releases must respond to the following messages
def name
person_name
end
def filename_suffix
"#{person_last_name} #{person_first_name}"
end
def contact_person
@contact_person ||= Contact.new(person_name, person_address, person_email, person_phone)
end
def uses_edl?
false
end
def minor?
false
end
def contract_file_name
"#{project.name.parameterize}_#{contract_template.release_type}_#{(signed_at || created_at).strftime("%Y.%m.%d")}_#{release_number}_#{filename_suffix.parameterize}"
end
end

View File

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

View File

@@ -3,8 +3,8 @@ class Project < ApplicationRecord
include Filterable
include Syncable
SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical)
AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical)
SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material)
AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music)
belongs_to :account
has_many :acquired_media_releases, dependent: :destroy
@@ -13,7 +13,6 @@ class Project < ApplicationRecord
has_many :material_releases, dependent: :destroy
has_many :music_releases, dependent: :destroy
has_many :talent_releases, dependent: :destroy
has_many :medical_releases, dependent: :destroy
has_many :videos, dependent: :destroy
has_many :imports, dependent: :destroy
has_many :contract_templates, dependent: :destroy
@@ -23,6 +22,7 @@ class Project < ApplicationRecord
has_many :downloads, dependent: :destroy
has_many :broadcasts, dependent: :destroy
has_many :zoom_meetings, dependent: :destroy
has_many :task_requests, dependent: :destroy
accepts_nested_attributes_for :project_memberships
@@ -34,7 +34,6 @@ class Project < ApplicationRecord
material_release: false,
music_release: false,
talent_release: false,
medical_release: false,
video_analysis: false,
}
end
@@ -67,7 +66,6 @@ class Project < ApplicationRecord
material_release: true,
music_release: true,
talent_release: true,
medical_release: true,
video_analysis: true,
}
when "nat_geo"
@@ -79,7 +77,6 @@ class Project < ApplicationRecord
material_release: true,
music_release: true,
talent_release: true,
medical_release: true,
video_analysis: true,
}
else
@@ -121,7 +118,7 @@ class Project < ApplicationRecord
current_zoom_meeting = zoom_meetings.active.first
unless current_zoom_meeting.present?
zoom_user = ZoomUser.for_new_meeting
zoom_user = ZoomUser.free.first || ZoomUser.create
current_zoom_meeting = ZoomMeeting.create(zoom_user: zoom_user, project: self)
end

View File

@@ -24,7 +24,7 @@ class QrCode
end
end
def to_base64_png(width = 200, height = 200)
def to_base64_png(width = 100, height = 100)
_qr_code.as_png.resize(width, height).to_data_url
end

View File

@@ -1,5 +1,5 @@
class ReleasableParam
TYPES = %w(talent appearance location material acquired_media music medical)
TYPES = %w(talent appearance location material acquired_media music)
def initialize(params)
@params = params

View File

@@ -8,12 +8,7 @@ class SampleAppearanceRelease < AppearanceRelease
def default_attrs
{
person_address_street1: "Street Address",
person_address_street2: "St2",
person_address_city: "City",
person_address_state: "State",
person_address_zip: "ZIP",
person_address_country: "Country",
person_address: "Street Address, City, State Zipcode",
person_first_name: "Some",
person_last_name: "Person",
person_phone: "555-555-5555",

View File

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

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

View File

@@ -1,27 +1,18 @@
require 'securerandom'
class ZoomUser < ApplicationRecord
has_many :zoom_meetings, dependent: :nullify
enum tier: [:basic, :pro]
after_create :create_api_user, if: -> { api_id.nil? }
before_destroy :abort_destroy
scope :current_account, -> { where(account_number: ZoomGateway.ACCOUNT_NUMBER) }
scope :free, -> { where.not(id: ZoomMeeting.active.pluck(:zoom_user_id)) }
def api_email
self.class.api_email(self.id)
end
def create_api_user
retries ||= 0
self.api_id = gateway.create_host(self.class.generate_api_email)
self.account_number = ZoomGateway.ACCOUNT_NUMBER
self.api_id = gateway.create_host(api_email)
save
rescue ZoomGateway::UserAlreadyExists => e
retries += 1
if retries < 3
retry # new api email will be generated automatically
else
raise e
end
end
def delete_api_user
@@ -30,22 +21,9 @@ class ZoomUser < ApplicationRecord
save
end
def current_account?
account_number == ZoomGateway.ACCOUNT_NUMBER
end
# Static methods
class << self
def generate_api_email
"host#{SecureRandom.random_number(10000)}@directme"
end
def for_new_meeting
user = public_send(ZoomGateway.USER_TYPE_NAME).current_account.free.first
if user.nil?
user = public_send(ZoomGateway.USER_TYPE_NAME).current_account.create
end
user
def api_email(id)
"host#{id}@directme"
end
end

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
class MedicalReleasePolicy < ReleasePolicy
def create?
class TaskRequestPolicy < ApplicationPolicy
def index?
true
end
@@ -7,31 +7,23 @@ class MedicalReleasePolicy < ReleasePolicy
true
end
def update?
!record.native?
def create?
true
end
def destroy?
true
end
def edit_photos?
true
end
def index?
def update?
true
end
def update_photos?
edit_photos?
end
def tag_multiple?
def cancel?
true
end
def download_multiple?
def open_deliverable?
true
end
end

View File

@@ -151,6 +151,24 @@ class Analytics
)
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

View File

@@ -4,7 +4,7 @@
<div class="form-row">
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
</div>
<%= form.form_group :categories, label: { text: "Licensed property type" } do %>
<%= form.form_group :categories, label: { text: "Categories" } do %>
<% AcquiredMediaRelease::CATEGORIES.each do |category| %>
<%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %>

View File

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

View File

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

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

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

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

@@ -0,0 +1,49 @@
<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>
<% if appearance_release.photo.attached? %>
<%= image_tag medium_variant(appearance_release.photo) %>
<%= image_tag medium_variant(appearance_release.photo), class: "img-fluid" %>
<% else %>
<%= fa_icon("warning", text: t(".no_photos"), class: "text-danger") %>
<% end %>
@@ -11,11 +11,10 @@
<%= appearance_release.name %>
</td>
<td>
<%= contact_info(
address: appearance_release.person_address,
phone: appearance_release.person_phone,
email: appearance_release.person_email
) %>
<%= number_to_phone appearance_release.person_phone %>
</td>
<td>
<%= mail_to appearance_release.person_email %>
</td>
<td>
<%= notes_preview appearance_release.notes.order_by_recent %>

View File

@@ -13,7 +13,7 @@
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
<%= form.date_field :person_date_of_birth, wrapper_class: "col-sm-6", placeholder: Date.current %>
<%= form.text_field :person_address_street1, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_address, wrapper_class: "col-sm-6" %>
</div>
<div class="<%= class_string("collapse" => !appearance_release.minor?) %>" data-ujs-target="guardian-fields">
@@ -52,7 +52,7 @@
<% end %>
<div class="d-inline-block">
<%= form.hidden_field :person_photo, value: form.object.person_photo.signed_id if appearance_release.person_photo.attached?%>
<%= 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(",") %>
<%= 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(",") %>
</div>
</div>

View File

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

View File

@@ -11,6 +11,12 @@
<hr class="divider-light mx-n4">
<nav>
<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">
<%= 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 %>

View File

@@ -2,10 +2,6 @@
<div class="page">
<% has_logo = local_assigns[:logo] %>
<table class="heading-table">
<tr>
<td>&nbsp;</td>
<td class="do-not-copy-warning"><strong><%= t '.do_not_copy_warning' %></strong></td>
</tr>
<tr>
<td>
<% if has_logo %>
@@ -15,9 +11,17 @@
<% end %>
</td>
<td>
<img class="qr-code" src="<%= qr_codes[copy_index] %>" />
<img src="<%= qr_codes[copy_index] %>" />
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td class="serial-number"><%= serial_numbers[copy_index] %></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><strong><%= t '.do_not_copy_warning' %></strong></td>
</tr>
</table>
<hr>
<% if contract_template.body.present? %>

View File

@@ -1,4 +1,4 @@
<li class="my-2" id="<%= dom_id(file) %>">
<li class="my-2">
<% 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" %>
<% else %>

View File

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

View File

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

@@ -3,13 +3,7 @@
<meta name="project-id" content="<%= @project.id %>">
<% end %>
<% if @broadcast %>
<meta name="broadcast-token" current="true" content="<%= @broadcast.token %>">
<% 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" current="false" content="<%= multi_view_broadcast.token %>">
<% end %>
<meta name="broadcast-token" content="<%= @broadcast.token %>">
<% end %>
<% end %>
@@ -30,7 +24,9 @@
<div class="d-flex justify-content-between align-items-center">
<h1 class="h3 m-0"><%= @broadcast.name %></h1>
<div class="dropdown">
<%= link_to "Switch View", "#", class: "btn btn-light border dropdown-toggle", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } %>
<a class="btn btn-light border dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Switch View
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<h5 class="dropdown-header">Live Streams</h5>
<span class="dropdown-item active"><%= fa_icon("check", text: @broadcast.name.titleize) %></span>
@@ -76,10 +72,13 @@
<div class="card-header">
<ul class="nav nav-tabs card-header-tabs">
<li class="nav-item">
<%= link_to "Home", "#home", class: class_string("nav-link", "active" => !params[:active_tab].present?), data: { toggle: "tab" } %>
<a class="<%= class_string("nav-link", "active" => !params[:active_tab].present?) %>" href="#home" data-toggle="tab">Home</a>
</li>
<li class="nav-item">
<%= link_to "Previous Sessions", "#recordings", class: class_string("nav-link", "active" => params[:active_tab] == "recordings"), data: { toggle: "tab" } %>
<a class="<%= class_string("nav-link", "active" => params[:active_tab] == "files") %>" href="#files" data-toggle="tab">Files</a>
</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>
</ul>
</div>
@@ -119,6 +118,30 @@
<p class="card-text">If you want to join the ZOOM meeting dedicated to this broadcast, follow the link below.</p>
<%= link_to 'Video Conference', @conference_url, class: 'btn btn-primary btn-block', target: '_blank' %>
</div>
<div class="<%= class_string("tab-pane fade show", "active" => params[:active_tab] == '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 id="broadcast_recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
@@ -127,36 +150,5 @@
</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>

View File

@@ -1,9 +1,5 @@
$("#broadcast_file_form_<%= @broadcast.token %>").html("<%= j render(partial: "broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>");
$("#broadcast_file_form").html("<%= j render(partial: "broadcasts/file_form", locals: { model: [@project, @broadcast] }) %>");
$("#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

@@ -2,20 +2,21 @@
<%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row">
<%= form.text_field :name, wrapper_class: "col-sm-6" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(appearance talent), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical) } }, class: "form-control custom-select" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target: "#guardian_clause", show_values: %w(appearance talent) }, class: "form-control custom-select" %>
</div>
<div class="form-row" id="fee_field">
<div class="form-row">
<%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", help: "Leave at $0.00 for no-fee", wrapper_class: "col-sm-6" %>
</div>
<% end %>
<hr>
<%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase"), id: "exploitable_rights_fields" do %>
<%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase")do %>
<%= render "shared/exploitable_rights_fields", form: form %>
<hr>
<% end %>
<hr>
<%= field_set_tag content_tag(:span, t(".legal.heading"), class: "h6 text-muted text-uppercase") do %>
<%= form.form_group do %>
<%= form.rich_text_area :body %>
@@ -27,12 +28,6 @@
</div>
<% end %>
<%= field_set_tag content_tag(:span, t(".custom_fields.heading"), class: "h6 text-muted text-uppercase"), id: "custom_fields", style: "display: none;" do %>
<p class="alert alert-info"><%= fa_icon("info-circle", text: t(".custom_fields.instructions")) %></p>
<%= render "shared/custom_fields", form: form %>
<hr>
<% end %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [project, :contract_templates], class: "col-3 text-reset" %>
<div class="col-3">

View File

@@ -29,7 +29,6 @@
<% if releasable.model_name == "LocationRelease" %>
<%= 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 Hours:", releasable&.filming_hours %>
<% end %>
<% if contract_template.fee? %>
<%= description_list_pair "Fee:", number_to_currency(contract_template.fee) %>
@@ -39,15 +38,6 @@
<% end %>
</dl>
<% if releasable.model_name == "MedicalRelease" %>
<% (1..10).each do |n| %>
<% if contract_template.public_send("question_#{n}_text").present? %>
<p><strong><%= contract_template.public_send("question_#{n}_text") %></strong></p>
<p><%= releasable.public_send("question_#{n}_answer") %></p>
<% end %>
<% end %>
<% end %>
<% if releasable.minor? %>
<br/>
<p class="text-left"><strong>Guardian Information</strong></p>
@@ -65,7 +55,6 @@
<%= description_list_pair_for releasable, :guardian_name, append: ":" %>
<%= description_list_pair_for releasable, :guardian_address, append: ":" %>
<%= description_list_pair_for releasable, :guardian_phone, append: ":" %>
<%= description_list_pair_for releasable, :guardian_email, append: ":" %>
<%= description_list_pair_for releasable, :signed_on, append: ":" %>
</dl>

View File

@@ -11,10 +11,14 @@
<%= field_set_tag content_tag(:span, t(".signer_details.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row">
<%= form.text_field :person_first_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_first_name, wrapper_class: "col-sm-3" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-3" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
</div>
@@ -34,7 +38,6 @@
<div class="form-row">
<%= 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_hours, wrapper_class: "col-sm-12" %>
</div>
<% end %>

View File

@@ -13,10 +13,14 @@
<%= field_set_tag content_tag(:span, t(".signer_details.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row">
<%= form.text_field :person_first_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_first_name, wrapper_class: "col-sm-3" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-3" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
</div>

View File

@@ -1,49 +0,0 @@
<tr id="<%= dom_id(medical_release) %>">
<td data-behavior="select"><%= check_box_tag "medical_release_ids[]", medical_release.id, false %></td>
<td>
<% if medical_release.photo.attached? %>
<%= image_tag medium_variant(medical_release.photo), class: "img-fluid" %>
<% end %>
</td>
<td>
<%= medical_release.name %>
</td>
<td>
<%= contact_info(
address: medical_release.person_address,
phone: medical_release.person_phone,
email: medical_release.person_email
) %>
</td>
<td>
<%= notes_preview medical_release.notes.order_by_recent %>
</td>
<td id="<%= dom_id medical_release, "tags_preview" %>">
<%= tags_preview medical_release, medical_release.tags %>
</td>
<td>
<%= medical_release.signed_on %>
</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(Note).new? %>
<%= link_to fa_icon("sticky-note fw", text: "Notes"), [:new, medical_release, :note], class: "dropdown-item", remote: true %>
<% end %>
<% if policy(medical_release.tags).new? %>
<%= link_to fa_icon("tags fw", text: "Tags"), [:new, medical_release, :acts_as_taggable_on_tag], class: "dropdown-item", remote: true %>
<% end %>
<% if policy(Contract).show? && (medical_release.contract.attached? || medical_release.contract_template.present?) %>
<%= link_to fa_icon("download fw", text: "Download"), [medical_release, :contracts, format: "pdf"], class: "dropdown-item", target: "_blank" %>
<% end %>
<% if policy(medical_release).destroy? %>
<%= link_to fa_icon("trash fw", text: "Delete"), medical_release, class: "dropdown-item", method: :delete, data: { confirm: "Are you sure?" } %>
<% end %>
</div>
</div>
</td>
</tr>

View File

@@ -1,48 +0,0 @@
<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 @medical_releases.any? && policy(MedicalRelease).tag_multiple? %>
<%= button_to_bulk_tagging(@project) %>
<% end %>
<% if @medical_releases.any? && policy(MedicalRelease).download_multiple? %>
<%= link_to "Download All", [@project, :contract_downloads, release_type: @medical_releases.name], method: :post, remote: true, class: "btn btn-light border ml-auto mr-2 mb-2", data: {
disable_with: "Please wait..." } %>
<% end %>
<%= bootstrap_form_with url: [@project, :medical_releases], method: :get, remote: true, layout: :inline, id: "search" do |form| %>
<%= form.search_field :query, hide_label: true, placeholder: t(".actions.search"), class: "rounded-pill-right", value: params[:query], prepend: form.button(fa_icon("search"), class: "btn btn-light border mb-2 rounded-pill-left") %>
<% 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 data-behavior="all-selectable"><%= check_box_tag "medical_release_ids[]", false, false %></th>
<th></th>
<th><%= MedicalRelease.human_attribute_name(:person_name) %></th>
<th><%= MedicalRelease.human_attribute_name(:contact_info) %></th>
<th><%= t(".table_headers.notes") %></th>
<th><%= t(".table_headers.tags") %></th>
<th><%= t(".table_headers.signed_at") %></th>
<th></th>
</tr>
</thead>
<tbody id="medical_releases">
<% if @medical_releases.any? %>
<%= render @medical_releases %>
<% else %>
<tr>
<td colspan="12" class="py-4 text-center text-muted"><%= t(".empty") %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div id="medical_releases_pagination" class="mt-3">
<%= will_paginate @medical_releases %>
</div>

View File

@@ -1,3 +0,0 @@
$("#medical_releases").html("<%= j render(@medical_releases) %>");
$("form input[type='search']").val("<%= params[:query] %>");
$("#medical_releases_pagination").html("<%= j will_paginate(@medical_releases) %>");

View File

@@ -1,6 +1,6 @@
<%= bootstrap_form_with model: project, local: true do |form| %>
<%= form.text_field :name %>
<%= form.select :predefined_client_name, options_for_select(options_for_predefined_client_name_select, selected_project_client_value(project)), {}, data: { toggle: "collapse-select", target_show_values_mapping: { "#other_client": [:other] } }, class: "form-control custom-select" %>
<%= form.select :predefined_client_name, options_for_select(options_for_predefined_client_name_select, selected_project_client_value(project)), {}, data: { toggle: "collapse-select", target: "#other_client", show_values: [:other] }, class: "form-control custom-select" %>
<div id="other_client" style="<%='display: none' if selected_project_client_value(project) != 'other'%>">
<%= form.text_field :client_name, placeholder: true %>
<%= form.form_group do %>

View File

@@ -16,6 +16,11 @@
<%= link_to t("projects.show.downloads"), [@project, :downloads], class: "text-decoration-none text-reset stretched-link" %>
<% 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>
<hr/>

View File

@@ -15,12 +15,12 @@
<%= card_field_set_tag t(".acquired_media_info.heading") do %>
<div class="form-row">
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
<%= form.text_field :name, required: true, wrapper_class: "col-12", label: 'Licensor ("Owner")' %>
</div>
<div class="form-row">
<%= form.text_area :description, wrapper_class: "col-12" %>
</div>
<%= form.form_group :categories, label: { text: "Licensed property type" } do %>
<%= form.form_group :categories, label: { text: "Categories" } do %>
<% AcquiredMediaRelease::CATEGORIES.each do |category| %>
<%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %>
@@ -31,11 +31,8 @@
<%= card_field_set_tag t(".personal_info.heading") do %>
<div class="form-row">
<%= form.text_field :person_first_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6", label: 'Phone' %>
<%= form.email_field :person_email, wrapper_class: "col-sm-6", label: 'Email' %>
<%= form.text_field :person_phone, wrapper_class: "col-sm-6", label: 'Phone' %>
<%= form.text_field :person_fax, wrapper_class: "col-sm-6", label: 'Fax' %>
</div>
<%= render "shared/address_fields", form: form, subject: "person" %>

View File

@@ -35,8 +35,8 @@
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
<%= form.date_field :person_date_of_birth, wrapper_class: "col-sm-6", placeholder: Date.current %>
<%= form.text_field :person_address, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "person" %>
<% end %>
<%= card_field_set_tag t(".photo.heading") do %>
@@ -76,9 +76,6 @@
<%= form.text_field :guardian_last_name, required: @appearance_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :guardian_address, wrapper_class: "col-sm-6" %>
</div>

View File

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

View File

@@ -1,9 +1,5 @@
$("#broadcast_file_form_<%= @broadcast.token %>").html("<%= j render(partial: "public/broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>");
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) %>");
}
$("#broadcast_file_form").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) %>");
bsCustomFileInput.init();

View File

@@ -27,7 +27,11 @@
<%= form.text_field :person_first_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-6" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
</div>
@@ -41,14 +45,9 @@
<div class="form-row">
<%= 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_hours, wrapper_class: "col-sm-12" %>
</div>
<% end %>
<%= card_field_set_tag t(".photos.heading") do %>
<%= render "shared/photos_dropzone_fields", form: form, release: @location_release %>
<% end %>
<%= card_field_set_tag t(".signature.heading") do %>
<%= render "shared/signature_fields", form: form, instruction: 'An Authorized Signatory' %>
<% end %>

View File

@@ -27,17 +27,17 @@
<%= form.text_field :person_first_name, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, wrapper_class: "col-sm-6" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "person" %>
<% end %>
<%= card_field_set_tag t(".photo.heading") do %>
<%= render "shared/photos_dropzone_fields", form: form, release: @material_release %>
<% end %>
<hr>
<%= card_field_set_tag t(".signature.heading") do %>

View File

@@ -1 +0,0 @@
<p class="alert alert-success p-3 lead text-center">Your release was successfully submitted. Thank you.</p>

View File

@@ -1,56 +0,0 @@
<div class="card shadow-sm">
<div class="card-body">
<%= errors_summary_for @medical_release %>
<%= bootstrap_form_with model: [@account, @project, @contract_template, @medical_release], local: true, validation_context: :native do |form| %>
<div class="alert alert-warning font-weight-bold"><%= t ".instructions_html", name: @project.name %></div>
<%= card_field_set_tag t(".legal.heading") do %>
<p><%= @contract_template.body %></p>
<% if @contract_template.fee? %>
<p>
Fee <span class="font-weight-bold text-success"><%= number_to_currency @contract_template.fee %></span>
</p>
<% end %>
<% end %>
<hr>
<% if (1..10).map {|n| @contract_template.public_send("question_#{n}_text").presence }.compact.any? %>
<%= card_field_set_tag t(".questionnaire.heading") do %>
<% (1..10).each do |n| %>
<% if @contract_template.public_send("question_#{n}_text").present? %>
<div class="form-row">
<%= form.text_area "question_#{n}_answer", wrapper_class: "col-sm-12", label: @contract_template.public_send("question_#{n}_text") %>
</div>
<% end %>
<% end %>
<% end %>
<hr>
<% end %>
<%= card_field_set_tag t(".personal_info.heading") do %>
<div class="alert alert-warning font-weight-bold"><%= t ".personal_info.instructions" %></div>
<div class="form-row">
<%= form.text_field :person_first_name, required: true, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_last_name, required: true, wrapper_class: "col-sm-6" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "person" %>
<% end %>
<hr>
<%= card_field_set_tag t(".photo.heading") do %>
<%= render "shared/photos_dropzone_fields", form: form, release: @medical_release %>
<% end %>
<%= card_field_set_tag t(".signature.heading") do %>
<%= render "shared/signature_fields", form: form %>
<% end %>
<div class="mt-5">
<%= form.button t("shared.submit_release_short"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
</div>
<% end %>
</div>
</div>

View File

@@ -11,6 +11,6 @@
</div>
<%= form.form_group "#{field_name_prefix}address_country" do %>
<%= form.label "#{field_name_prefix}address_country" %>
<%= form.country_select "#{field_name_prefix}address_country", { selected: 'US', priority: %w(US CA), prompt: true }, class: "form-control custom-select" %>
<%= form.country_select "#{field_name_prefix}address_country", { priority: %w(US CA), prompt: true }, class: "form-control custom-select" %>
<% end %>

View File

@@ -1,5 +0,0 @@
<% (1..10).each do |n| %>
<div class="form-row">
<%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %>
</div>
<% end%>

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More