Compare commits
5 Commits
make-all-f
...
import-arc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94b417d4c4 | ||
|
|
a7b90c223b | ||
|
|
9a540efc74 | ||
|
|
028e946fcf | ||
|
|
fbf3173747 |
16
README.md
16
README.md
@@ -95,14 +95,28 @@ rake i18n:sort
|
||||
```
|
||||
|
||||
## Zoom.us integration
|
||||
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.
|
||||
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.
|
||||
|
||||
#### 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
|
||||
|
||||
|
||||
@@ -8,11 +8,16 @@ $(document).on "turbolinks:load", ->
|
||||
# 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" then @refreshBroadcastVideo(data)
|
||||
when "stream_recording_ready" then @showBroadcastRecordings(data)
|
||||
when "file_upload_update" then @refreshBroadcastFilesTab(data)
|
||||
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)
|
||||
|
||||
refreshBroadcastVideo: (data) ->
|
||||
$("#broadcast_updates").html data.status_content
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
$(document).on("change", "[data-toggle=collapse-select]", function(event) {
|
||||
const select = event.target;
|
||||
const target = select.dataset.target;
|
||||
const showValues = JSON.parse(select.dataset.showValues);
|
||||
|
||||
if (showValues.indexOf(select.value) > -1) {
|
||||
$(target).show("fast");
|
||||
} else {
|
||||
$(target).hide("fast");
|
||||
}
|
||||
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");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("turbolinks:load", function() {
|
||||
$("[data-toggle=collapse-select]").trigger("change");
|
||||
});
|
||||
@@ -31,7 +31,7 @@ u {
|
||||
}
|
||||
|
||||
.page {
|
||||
page-break-before: always;
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
.logo {
|
||||
@@ -44,6 +44,14 @@ u {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.qr-code {
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
.do-not-copy-warning {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.heading-table td {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
50
app/controllers/api/direct_uploads_controller.rb
Normal file
50
app/controllers/api/direct_uploads_controller.rb
Normal file
@@ -0,0 +1,50 @@
|
||||
# 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
|
||||
@@ -3,7 +3,6 @@
|
||||
class AppearanceReleaseImportsController < ApplicationController
|
||||
include AppearanceReleaseContext
|
||||
include ProjectContext
|
||||
include CreateReleasableJobs
|
||||
|
||||
before_action :set_project, only: [:create]
|
||||
|
||||
@@ -11,24 +10,16 @@ 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
|
||||
attachments.each do |attachment|
|
||||
create_imported_appearance_release attachment
|
||||
end
|
||||
MatchAppearanceReleasesJob.perform_later(@project, attachments)
|
||||
notice_message = t 'appearance_releases.create.matching_started'
|
||||
redirect_to [@project, :appearance_releases], notice: notice_message
|
||||
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
|
||||
@@ -45,45 +36,7 @@ class AppearanceReleaseImportsController < ApplicationController
|
||||
params.require(:attachments)
|
||||
end
|
||||
|
||||
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
|
||||
def acceptable_extensions
|
||||
AppearanceRelease.acceptable_import_file_extensions
|
||||
end
|
||||
end
|
||||
|
||||
@@ -78,7 +78,7 @@ 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, :minor,
|
||||
params.require(:appearance_release).permit(:contract, :guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :guardian_email, :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,
|
||||
|
||||
@@ -61,7 +61,12 @@ class ContractTemplatesController < ApplicationController
|
||||
:applicable_medium_id, :applicable_medium_text,
|
||||
:territory_id, :territory_text,
|
||||
:term_id, :term_text,
|
||||
:restriction_id, :restriction_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)
|
||||
end
|
||||
|
||||
def download_attributes
|
||||
|
||||
@@ -41,7 +41,7 @@ class Public::AppearanceReleasesController < Public::BaseController
|
||||
|
||||
def appearance_release_params
|
||||
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,
|
||||
:guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_email, :guardian_photo, :minor,
|
||||
:signature_base64, :person_date_of_birth,
|
||||
:locale, :contract_template,)
|
||||
end
|
||||
|
||||
@@ -48,6 +48,11 @@ class Public::MedicalReleasesController < Public::BaseController
|
||||
: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
|
||||
|
||||
@@ -11,7 +11,9 @@ class ReleaseTemplateImportsController < ApplicationController
|
||||
|
||||
templates = []
|
||||
filtered_contract_templates.each do |contract_template|
|
||||
next if contract_template.duplicated? || contract_template.project == @project
|
||||
next if contract_template.duplicated? ||
|
||||
contract_template.archived? ||
|
||||
contract_template.project == @project
|
||||
|
||||
already_imported = contract_template.duplicates.non_archived.pluck(:project_id).include?(@project.id)
|
||||
templates << OpenStruct.new(template: contract_template, already_imported?: already_imported)
|
||||
|
||||
100
app/jobs/match_appearance_releases_job.rb
Normal file
100
app/jobs/match_appearance_releases_job.rb
Normal file
@@ -0,0 +1,100 @@
|
||||
# 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
|
||||
@@ -56,6 +56,7 @@ class Account < ApplicationRecord
|
||||
Broadcast.where(project: projects),
|
||||
ZoomMeeting.where(project: projects),
|
||||
MedicalRelease.where(project: projects),
|
||||
MatchingRequest.where(project: projects),
|
||||
self
|
||||
])).sum(:byte_size).to_f
|
||||
end
|
||||
|
||||
@@ -39,6 +39,7 @@ 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
|
||||
|
||||
@@ -8,7 +8,7 @@ class BlankContract
|
||||
end
|
||||
|
||||
def to_pdf
|
||||
kit = PDFKit.new(as_html)
|
||||
kit = PDFKit.new(as_html, margin_right: 1, margin_left: 1, margin_top: 10, margin_bottom: 1)
|
||||
kit.to_file("tmp/#{filename}")
|
||||
end
|
||||
|
||||
|
||||
9
app/models/concerns/attachable.rb
Normal file
9
app/models/concerns/attachable.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Attachable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
has_many_attached :attachments
|
||||
end
|
||||
end
|
||||
@@ -51,6 +51,10 @@ class ContractTemplate < ApplicationRecord
|
||||
parent.present?
|
||||
end
|
||||
|
||||
def archived?
|
||||
archived_at.present?
|
||||
end
|
||||
|
||||
def archive
|
||||
update(archived_at: Time.zone.now)
|
||||
end
|
||||
|
||||
@@ -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 { |_, v| v.blank? }
|
||||
}.reject { |k, v| v.blank? && k != :ids_to_images }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
7
app/models/matching_request.rb
Normal file
7
app/models/matching_request.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class MatchingRequest < ApplicationRecord
|
||||
include Attachable
|
||||
|
||||
belongs_to :project
|
||||
end
|
||||
@@ -24,7 +24,7 @@ class QrCode
|
||||
end
|
||||
end
|
||||
|
||||
def to_base64_png(width = 100, height = 100)
|
||||
def to_base64_png(width = 200, height = 200)
|
||||
_qr_code.as_png.resize(width, height).to_data_url
|
||||
end
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
<div class="page">
|
||||
<% has_logo = local_assigns[:logo] %>
|
||||
<table class="heading-table">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="do-not-copy-warning"><strong><%= t '.do_not_copy_warning' %></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<% if has_logo %>
|
||||
@@ -11,17 +15,9 @@
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<img src="<%= qr_codes[copy_index] %>" />
|
||||
<img class="qr-code" src="<%= qr_codes[copy_index] %>" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td class="serial-number"><%= serial_numbers[copy_index] %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><strong><%= t '.do_not_copy_warning' %></strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<% if contract_template.body.present? %>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<meta name="project-id" content="<%= @project.id %>">
|
||||
<% end %>
|
||||
<% if @broadcast %>
|
||||
<meta name="broadcast-token" content="<%= @broadcast.token %>">
|
||||
<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" content="<%= multi_view_broadcast.token %>">
|
||||
<meta name="broadcast-token" current="false" content="<%= multi_view_broadcast.token %>">
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -2,21 +2,20 @@
|
||||
<%= 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: "#guardian_clause", show_values: %w(appearance talent) }, 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_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" %>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-row" id="fee_field">
|
||||
<%= 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")do %>
|
||||
<%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase"), id: "exploitable_rights_fields" 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 %>
|
||||
@@ -28,6 +27,12 @@
|
||||
</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">
|
||||
|
||||
@@ -39,6 +39,15 @@
|
||||
<% 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>
|
||||
@@ -56,6 +65,7 @@
|
||||
<%= 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>
|
||||
|
||||
|
||||
@@ -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: "#other_client", show_values: [: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_show_values_mapping: { "#other_client": [: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 %>
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
<%= 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>
|
||||
|
||||
@@ -13,6 +13,19 @@
|
||||
<% 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>
|
||||
@@ -36,7 +49,7 @@
|
||||
<% end %>
|
||||
|
||||
<div class="mt-5">
|
||||
<%= form.button t("shared.submit_release_long"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
|
||||
<%= 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>
|
||||
|
||||
5
app/views/shared/_custom_fields.html.erb
Normal file
5
app/views/shared/_custom_fields.html.erb
Normal file
@@ -0,0 +1,5 @@
|
||||
<% (1..10).each do |n| %>
|
||||
<div class="form-row">
|
||||
<%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %>
|
||||
</div>
|
||||
<% end%>
|
||||
@@ -112,6 +112,7 @@ en:
|
||||
no_photos: Needs Photo
|
||||
create:
|
||||
failed_import: Failed to create appearance release for files listed below
|
||||
matching_started: Matching started
|
||||
no_attachments: Failed to import - no attachments
|
||||
edit:
|
||||
heading: Edit Appearance Release
|
||||
@@ -141,6 +142,8 @@ en:
|
||||
shared:
|
||||
imported_appearance_release_contract_name: Imported Contract
|
||||
imported_appearance_release_headshot_name: Imported Headshot
|
||||
incomplete_match: Incomplete Match
|
||||
matched_import: Complete Match
|
||||
type_filter_actions:
|
||||
all_releases: All Releases
|
||||
complete_releases: Complete Releases
|
||||
@@ -212,12 +215,15 @@ en:
|
||||
archived_failure: Failed to archive the release template
|
||||
archived_notice: The release template has been archived
|
||||
form:
|
||||
custom_fields:
|
||||
heading: Medical Questionnaire
|
||||
instructions: Please list the questions you wish the signer to answer. Any unused question fields will be hidden.
|
||||
exploitable_rights:
|
||||
heading: 2 of 3 Exploitable Rights
|
||||
heading: Exploitable Rights
|
||||
legal:
|
||||
heading: 3 of 3 Legal
|
||||
heading: Legal
|
||||
release_info:
|
||||
heading: 1 of 3 Release Info
|
||||
heading: Release Info
|
||||
index:
|
||||
actions:
|
||||
import: Import Release Template
|
||||
@@ -324,7 +330,10 @@ en:
|
||||
appearance_release:
|
||||
minor: Is the person a minor?
|
||||
person_address: Address
|
||||
person_date_of_birth: Date of birth
|
||||
person_email: Email address
|
||||
person_first_name: First name
|
||||
person_last_name: Last name
|
||||
person_name: Name
|
||||
person_phone: Phone number
|
||||
location_release:
|
||||
@@ -789,17 +798,17 @@ en:
|
||||
instructions: >
|
||||
Lastly, it's time for guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
|
||||
instructions_html: >
|
||||
Congrats in appearing on <em>%{name}</em>. Below is the appearance release form. After scrolling down and reading the appearance release form, please enter your personal information, take a selfie photo, and press the "Submit Release" button.
|
||||
Congrats on appearing in <em>%{name}</em>. After scrolling down and reading the appearance release form, please enter your personal information, take a selfie photo and press the "Submit Release" button. If the person appearing on camera is a minor, you will enter their personal information first, select the button noting this person is a minor, and then enter your own personal info under "Guardian Information" at the bottom.
|
||||
legal:
|
||||
heading: Legal
|
||||
personal_info:
|
||||
heading: Personal Information
|
||||
instructions: Now, enter your personal information.
|
||||
instructions: Enter the personal information for the person appearing on camera.
|
||||
photo:
|
||||
camera_instructions_html: Click <em>Take Photo</em> to Turn ON Camera
|
||||
heading: Take a Photo
|
||||
heading: Photo of Person Appearing on Camera
|
||||
instructions: >
|
||||
Lastly, it's time for you to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
|
||||
'Before you take your selfie photo, remove your hat and sunglasses (regular eyewear is okay). Make sure you are the only person in the frame, look straight at the camera and snap the photo. NOTE: If you are a Guardian, you must take the photo of the minor. Minor photo is required only for record keeping purposes to maintain proof of parental consent and to identify minor within the Program.'
|
||||
no_photo: No photo yet
|
||||
take_photo: Take Photo
|
||||
warning: If your photo appears sideways, it will be autocorrected when you submit your release.
|
||||
@@ -851,6 +860,8 @@ en:
|
||||
instructions: Now, enter your personal information.
|
||||
photo:
|
||||
heading: Photos
|
||||
questionnaire:
|
||||
heading: Questionnaire
|
||||
signature:
|
||||
heading: Signature
|
||||
talent_releases:
|
||||
@@ -940,6 +951,7 @@ en:
|
||||
search: Search
|
||||
submit_release: Submit Release
|
||||
submit_release_long: I have read and agree to the above
|
||||
submit_release_short: Submit
|
||||
suite: Suite
|
||||
tag_multiple_releases: Add Tag
|
||||
tag_multiple_releases_form:
|
||||
|
||||
@@ -25,6 +25,7 @@ es:
|
||||
appearance_releases:
|
||||
create:
|
||||
failed_import: Failed to create appearance release for files listed below (ES)
|
||||
matching_started: Matching started (ES)
|
||||
no_attachments: Failed to import - no attachments (ES)
|
||||
form:
|
||||
photos:
|
||||
@@ -37,6 +38,8 @@ es:
|
||||
shared:
|
||||
imported_appearance_release_contract_name: Contrato Importado
|
||||
imported_appearance_release_headshot_name: Retrato Importado
|
||||
incomplete_match: Incomplete Match (ES)
|
||||
matched_import: Complete Match (ES)
|
||||
type_filter_actions:
|
||||
all_releases: All Releases (ES)
|
||||
complete_releases: Complete Releases (ES)
|
||||
@@ -52,6 +55,15 @@ es:
|
||||
blank_contracts:
|
||||
create:
|
||||
number_of_copies_invalid_notice: Please enter valid number greater than 0 (ES)
|
||||
form:
|
||||
custom_fields:
|
||||
heading: Medical Questionnaire (ES)
|
||||
exploitable_rights:
|
||||
heading: Exploitable Rights (ES)
|
||||
legal:
|
||||
heading: Legal (ES)
|
||||
release_info:
|
||||
heading: Release Info (ES)
|
||||
contracts:
|
||||
photos:
|
||||
guardian_photo_heading: Guardian photo (ES)
|
||||
|
||||
@@ -163,6 +163,7 @@ Rails.application.routes.draw do
|
||||
resources :appearance_releases, only: [:show] do
|
||||
resources :notes, controller: "notes", only: [:create, :index]
|
||||
end
|
||||
resources :direct_uploads, only: [:create]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
9
db/migrate/20200430151828_create_matching_requests.rb
Normal file
9
db/migrate/20200430151828_create_matching_requests.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class CreateMatchingRequests < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
create_table :matching_requests do |t|
|
||||
t.belongs_to :project, foreign_key: true
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddIdentifierToAppearanceReleases < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :appearance_releases, :identifier, :string, default: nil
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
class AddQuestionFieldsToContractTemplates < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :contract_templates, :question_1_text, :text
|
||||
add_column :contract_templates, :question_2_text, :text
|
||||
add_column :contract_templates, :question_3_text, :text
|
||||
add_column :contract_templates, :question_4_text, :text
|
||||
add_column :contract_templates, :question_5_text, :text
|
||||
add_column :contract_templates, :question_6_text, :text
|
||||
add_column :contract_templates, :question_7_text, :text
|
||||
add_column :contract_templates, :question_8_text, :text
|
||||
add_column :contract_templates, :question_9_text, :text
|
||||
add_column :contract_templates, :question_10_text, :text
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,14 @@
|
||||
class AddAnswerFieldsToMedicalReleases < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :medical_releases, :question_1_answer, :text
|
||||
add_column :medical_releases, :question_2_answer, :text
|
||||
add_column :medical_releases, :question_3_answer, :text
|
||||
add_column :medical_releases, :question_4_answer, :text
|
||||
add_column :medical_releases, :question_5_answer, :text
|
||||
add_column :medical_releases, :question_6_answer, :text
|
||||
add_column :medical_releases, :question_7_answer, :text
|
||||
add_column :medical_releases, :question_8_answer, :text
|
||||
add_column :medical_releases, :question_9_answer, :text
|
||||
add_column :medical_releases, :question_10_answer, :text
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddGuardianEmailToAppearanceReleases < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :appearance_releases, :guardian_email, :string
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class RemoveBroadcastIdFromZoomMeetings < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
remove_column :zoom_meetings, :broadcast_id
|
||||
end
|
||||
end
|
||||
127
db/structure.sql
127
db/structure.sql
@@ -9,20 +9,6 @@ SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||||
|
||||
|
||||
--
|
||||
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
|
||||
|
||||
|
||||
--
|
||||
-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: -
|
||||
--
|
||||
@@ -330,7 +316,9 @@ CREATE TABLE public.appearance_releases (
|
||||
person_first_name character varying,
|
||||
person_last_name character varying,
|
||||
guardian_first_name character varying,
|
||||
guardian_last_name character varying
|
||||
guardian_last_name character varying,
|
||||
identifier character varying,
|
||||
guardian_email character varying
|
||||
);
|
||||
|
||||
|
||||
@@ -606,7 +594,17 @@ CREATE TABLE public.contract_templates (
|
||||
term_text character varying,
|
||||
restriction_id bigint,
|
||||
restriction_text character varying,
|
||||
archived_at timestamp without time zone
|
||||
archived_at timestamp without time zone,
|
||||
question_1_text text,
|
||||
question_2_text text,
|
||||
question_3_text text,
|
||||
question_4_text text,
|
||||
question_5_text text,
|
||||
question_6_text text,
|
||||
question_7_text text,
|
||||
question_8_text text,
|
||||
question_9_text text,
|
||||
question_10_text text
|
||||
);
|
||||
|
||||
|
||||
@@ -875,6 +873,37 @@ CREATE SEQUENCE public.location_releases_id_seq
|
||||
ALTER SEQUENCE public.location_releases_id_seq OWNED BY public.location_releases.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.matching_requests (
|
||||
id bigint NOT NULL,
|
||||
project_id bigint,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.matching_requests_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.matching_requests_id_seq OWNED BY public.matching_requests.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: material_releases; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -955,7 +984,17 @@ CREATE TABLE public.medical_releases (
|
||||
notes text,
|
||||
signed_at timestamp without time zone,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
question_1_answer text,
|
||||
question_2_answer text,
|
||||
question_3_answer text,
|
||||
question_4_answer text,
|
||||
question_5_answer text,
|
||||
question_6_answer text,
|
||||
question_7_answer text,
|
||||
question_8_answer text,
|
||||
question_9_answer text,
|
||||
question_10_answer text
|
||||
);
|
||||
|
||||
|
||||
@@ -1612,7 +1651,6 @@ CREATE TABLE public.zoom_meetings (
|
||||
api_meeting_id character varying,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
broadcast_id bigint,
|
||||
zoom_user_id bigint,
|
||||
project_id bigint,
|
||||
status integer DEFAULT 0
|
||||
@@ -1811,6 +1849,13 @@ ALTER TABLE ONLY public.imports ALTER COLUMN id SET DEFAULT nextval('public.impo
|
||||
ALTER TABLE ONLY public.location_releases ALTER COLUMN id SET DEFAULT nextval('public.location_releases_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.matching_requests ALTER COLUMN id SET DEFAULT nextval('public.matching_requests_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: material_releases id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2119,6 +2164,14 @@ ALTER TABLE ONLY public.location_releases
|
||||
ADD CONSTRAINT location_releases_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests matching_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.matching_requests
|
||||
ADD CONSTRAINT matching_requests_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: material_releases material_releases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2588,6 +2641,13 @@ CREATE INDEX index_location_releases_on_term_id ON public.location_releases USIN
|
||||
CREATE INDEX index_location_releases_on_territory_id ON public.location_releases USING btree (territory_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_matching_requests_on_project_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_matching_requests_on_project_id ON public.matching_requests USING btree (project_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_material_releases_on_applicable_medium_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2917,13 +2977,6 @@ CREATE INDEX index_videos_on_audio_analysis_uid ON public.videos USING btree (au
|
||||
CREATE INDEX index_videos_on_project_id ON public.videos USING btree (project_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_zoom_meetings_on_broadcast_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_zoom_meetings_on_broadcast_id ON public.zoom_meetings USING btree (broadcast_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_zoom_meetings_on_project_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3232,6 +3285,14 @@ ALTER TABLE ONLY public.material_releases
|
||||
ADD CONSTRAINT fk_rails_6b945b36b9 FOREIGN KEY (contract_template_id) REFERENCES public.contract_templates(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: matching_requests fk_rails_71d16e64c8; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.matching_requests
|
||||
ADD CONSTRAINT fk_rails_71d16e64c8 FOREIGN KEY (project_id) REFERENCES public.projects(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: appearance_releases fk_rails_7a58302526; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3264,14 +3325,6 @@ ALTER TABLE ONLY public.music_releases
|
||||
ADD CONSTRAINT fk_rails_890d967673 FOREIGN KEY (territory_id) REFERENCES public.territories(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: zoom_meetings fk_rails_8d814ea729; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.zoom_meetings
|
||||
ADD CONSTRAINT fk_rails_8d814ea729 FOREIGN KEY (broadcast_id) REFERENCES public.broadcasts(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: medical_releases fk_rails_98aa92daa9; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -3591,10 +3644,16 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20200424161117'),
|
||||
('20200427073429'),
|
||||
('20200428091105'),
|
||||
('20200430151828'),
|
||||
('20200430190412'),
|
||||
('20200507110804'),
|
||||
('20200512161738'),
|
||||
('20200526113516'),
|
||||
('20200603090419'),
|
||||
('20200606044747');
|
||||
('20200606044747'),
|
||||
('20200610085411'),
|
||||
('20200610140459'),
|
||||
('20200612121539'),
|
||||
('20200615131722');
|
||||
|
||||
|
||||
|
||||
@@ -10,5 +10,6 @@ require_relative "./brayniac_ai/edl_parse"
|
||||
require_relative "./brayniac_ai/edl_parse_result"
|
||||
require_relative "./brayniac_ai/facial_recognition"
|
||||
require_relative "./brayniac_ai/facial_recognition_result"
|
||||
require_relative "./brayniac_ai/qr_matching"
|
||||
require_relative "./brayniac_ai/tag"
|
||||
require_relative "./brayniac_ai/validation"
|
||||
|
||||
4
lib/brayniac_ai/qr_matching.rb
Normal file
4
lib/brayniac_ai/qr_matching.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module BrayniacAI
|
||||
class QrMatching < Base
|
||||
end
|
||||
end
|
||||
36
spec/controllers/api/direct_uploads_controller_spec.rb
Normal file
36
spec/controllers/api/direct_uploads_controller_spec.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::DirectUploadsController, type: :controller do
|
||||
let(:current_user) { create(:user) }
|
||||
let(:project) { create(:project, account: current_user.primary_account) }
|
||||
|
||||
before do
|
||||
sign_in_to_api(current_user)
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
it 'returns data for a direct upload' do
|
||||
post :create, params: { direct_upload: direct_upload_params }
|
||||
|
||||
expect(response).to be_successful
|
||||
expect(response_body_data_attributes).to include('id', 'key', 'signed_id', 'url', 'headers')
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def direct_upload_params
|
||||
file = file_fixture("video_file.mp4")
|
||||
checksum = Digest::MD5.base64digest(StringIO.new(file.read).to_s)
|
||||
|
||||
{ filename: file.basename.to_s, content_type: "video/mp4", byte_size: file.size, checksum: checksum }
|
||||
end
|
||||
|
||||
def response_body_data
|
||||
JSON.parse(response.body).dig('data')
|
||||
end
|
||||
|
||||
def response_body_data_attributes
|
||||
response_body_data.dig('attributes')
|
||||
end
|
||||
end
|
||||
@@ -263,7 +263,9 @@ RSpec.describe AppearanceReleasesController, tye: :controller do
|
||||
end
|
||||
|
||||
def minor_appearance_release_params
|
||||
attributes_for(:appearance_release, :non_native, :minor_with_guardian_photo).except(:contract).merge(contract_param, exploitable_rights_params)
|
||||
attributes_for(:appearance_release, :non_native, :minor_with_guardian_photo)
|
||||
.except(:contract)
|
||||
.merge(contract_param, exploitable_rights_params)
|
||||
end
|
||||
|
||||
def exploitable_rights_params
|
||||
|
||||
@@ -33,6 +33,7 @@ FactoryBot.define do
|
||||
guardian_last_name "Doe"
|
||||
guardian_address "100 Test Lane, New York, 10001"
|
||||
guardian_phone "123-555-1234"
|
||||
guardian_email "guardian@galaxy.all"
|
||||
end
|
||||
|
||||
trait :minor_with_guardian_photo do
|
||||
@@ -41,6 +42,7 @@ FactoryBot.define do
|
||||
guardian_last_name "Doe"
|
||||
guardian_address "100 Test Lane, New York, 10001"
|
||||
guardian_phone "123-555-1234"
|
||||
guardian_email "guardian@galaxy.all"
|
||||
guardian_photo do
|
||||
path = Rails.root.join("spec", "fixtures", "files", "pratt.jpg")
|
||||
Rack::Test::UploadedFile.new(path, "image/jpeg")
|
||||
@@ -65,5 +67,24 @@ FactoryBot.define do
|
||||
appearance_release.contract_template = build(:appearance_release_contract_template)
|
||||
end
|
||||
end
|
||||
|
||||
factory :appearance_release_import do
|
||||
person_photo nil
|
||||
|
||||
trait :with_headshot do
|
||||
person_photo do
|
||||
path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
|
||||
Rack::Test::UploadedFile.new(path, "image/png")
|
||||
end
|
||||
end
|
||||
|
||||
trait :with_contract do
|
||||
contract do
|
||||
path = Rails.root.join("spec", "fixtures", "files", "AppearanceRelease.pdf")
|
||||
Rack::Test::UploadedFile.new(path, "application/pdf")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,10 @@ FactoryBot.define do
|
||||
guardian_clause "Is the signer a minor?"
|
||||
fee "$0.00"
|
||||
|
||||
trait :archived do
|
||||
archived_at Time.zone.now
|
||||
end
|
||||
|
||||
factory :appearance_release_contract_template do
|
||||
release_type "appearance"
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ require 'rails_helper'
|
||||
RSpec.feature 'User manages contract templates', type: :feature do
|
||||
let(:current_user) { create(:user, :manager) }
|
||||
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
|
||||
let(:project2) { create(:project, members: current_user, account: current_user.primary_account, name: 'New project') }
|
||||
|
||||
before do
|
||||
sign_in(current_user)
|
||||
@@ -191,6 +192,21 @@ RSpec.feature 'User manages contract templates', type: :feature do
|
||||
expect(page).not_to have_content('Test template')
|
||||
end
|
||||
|
||||
scenario 'archived contract templates from other projects are not shown when importing contract templates' do
|
||||
create(:contract_template, :archived, project: project2, name: 'Archived template')
|
||||
create(:contract_template, project: project2, name: 'Active template')
|
||||
create(:contract_template, project: project)
|
||||
|
||||
visit project_contract_templates_path(project)
|
||||
expect(page).to have_content('Test template')
|
||||
|
||||
click_on import_template_button
|
||||
|
||||
expect(page).not_to have_content('Test template')
|
||||
expect(page).not_to have_content('Archived template')
|
||||
expect(page).to have_content('Active template')
|
||||
end
|
||||
|
||||
context 'When the user is associate' do
|
||||
let(:current_user) { create(:user, :associate) }
|
||||
|
||||
@@ -198,7 +214,7 @@ RSpec.feature 'User manages contract templates', type: :feature do
|
||||
visit project_contract_templates_path(project)
|
||||
|
||||
expect(page).not_to have_content('Create New Release Template')
|
||||
expect(page).not_to have_content('Import Release Template')
|
||||
expect(page).not_to have_content(import_template_button)
|
||||
expect(page).not_to have_content('Delete')
|
||||
end
|
||||
end
|
||||
@@ -218,6 +234,14 @@ RSpec.feature 'User manages contract templates', type: :feature do
|
||||
|
||||
private
|
||||
|
||||
def import_template_button
|
||||
t 'contract_templates.index.actions.import'
|
||||
end
|
||||
|
||||
def import_selected_templates_button
|
||||
t 'release_template_imports.new.actions.import'
|
||||
end
|
||||
|
||||
def preview_heading
|
||||
t 'blank_contracts.new.preview_heading'
|
||||
end
|
||||
|
||||
@@ -25,7 +25,7 @@ feature 'User managing appearance releases' do
|
||||
fill_in person_date_of_birth, with: '01/01/1999'
|
||||
attach_file person_photo_field, file_fixture('person_photo.png'), visible: :all
|
||||
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
|
||||
click_button 'I have read and agree to the above'
|
||||
click_button submit_release_button
|
||||
|
||||
expect(page).to have_content(successful_submission_message)
|
||||
end
|
||||
@@ -45,6 +45,7 @@ feature 'User managing appearance releases' do
|
||||
page.check person_is_minor_checkbox
|
||||
expect(page).to have_content('GUARDIAN INFORMATION')
|
||||
expect(page).to have_content('GUARDIAN PHOTO')
|
||||
expect(page).to have_content 'Guardian Email'
|
||||
|
||||
fill_in guardian_first_name_field, with: 'Guardian'
|
||||
fill_in guardian_last_name_field, with: 'Name'
|
||||
@@ -58,7 +59,14 @@ feature 'User managing appearance releases' do
|
||||
attach_file person_photo_field, file_fixture('person_photo.png'), visible: :all
|
||||
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
|
||||
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
|
||||
click_button 'I have read and agree to the above'
|
||||
|
||||
fill_in guardian_email_field, with: 'invalid@email'
|
||||
click_button submit_release_button
|
||||
expect(page).to have_content('Guardian email is not an email')
|
||||
|
||||
fill_in guardian_email_field, with: 'valid@email.com'
|
||||
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
|
||||
click_button submit_release_button
|
||||
|
||||
expect(page).to have_content(successful_submission_message)
|
||||
end
|
||||
@@ -130,48 +138,25 @@ feature 'User managing appearance releases' do
|
||||
end
|
||||
|
||||
scenario 'progress bar shows when user imports a release', js: true do
|
||||
skip "TODO"
|
||||
visit project_appearance_releases_path(project)
|
||||
|
||||
expect(page).not_to have_css('#upload-progress-container')
|
||||
large_pdf_file = build_large_pdf_file
|
||||
attach_file import_appearance_release_field, Rails.root.join(large_pdf_file.path), visible: false
|
||||
expect(page).to have_css('#upload-progress-container')
|
||||
expect(page).to have_content submit_create_button, wait: 30
|
||||
click_button submit_create_button
|
||||
expect(page).to have_content matching_started
|
||||
end
|
||||
|
||||
scenario 'MatchAppearanceReleasesJob is started when import is finished', js: true do
|
||||
visit project_appearance_releases_path(project)
|
||||
|
||||
attach_file import_appearance_release_field, Rails.root.join(file_fixture('person_photo.png')), visible: false
|
||||
expect(page).to have_content importing_label
|
||||
allow(MatchAppearanceReleasesJob).to receive(:perform_later).with(project, anything)
|
||||
click_button submit_create_button
|
||||
expect(page).to have_css('.progress')
|
||||
end
|
||||
|
||||
scenario 'importing a releases works when image is selected', js: true do
|
||||
expect(page).to have_content matching_started
|
||||
visit project_appearance_releases_path(project)
|
||||
|
||||
expect(page).to have_content submit_create_button
|
||||
expect(page).to have_content no_appearance_releases
|
||||
attach_file import_appearance_release_field, Rails.root.join(file_fixture('person_photo.png')), visible: false
|
||||
expect(page).to have_content importing_label
|
||||
click_button submit_create_button
|
||||
expect(page).not_to have_content no_appearance_releases
|
||||
expect(page).to have_content /Imported Headshot\s+\d{7}/
|
||||
end
|
||||
|
||||
scenario 'importing a releases works when pdf is selected', js: true do
|
||||
visit project_appearance_releases_path(project)
|
||||
|
||||
expect(page).to have_content submit_create_button
|
||||
expect(page).to have_content no_appearance_releases
|
||||
attach_file import_appearance_release_field, Rails.root.join(file_fixture('contract.pdf')), visible: false
|
||||
expect(page).to have_content importing_label
|
||||
click_button submit_create_button
|
||||
expect(page).not_to have_content no_appearance_releases
|
||||
expect(page).to have_content /Imported Contract\s+\d{7}/
|
||||
end
|
||||
|
||||
scenario 'importing a releases fails when file other than image or pdf is selected', js: true do
|
||||
visit project_appearance_releases_path(project)
|
||||
|
||||
expect(page).to have_content submit_create_button
|
||||
expect(page).to have_content no_appearance_releases
|
||||
attach_file import_appearance_release_field, Rails.root.join(file_fixture('audio.mp3')), visible: false
|
||||
expect(page).to have_content importing_label
|
||||
click_button submit_create_button
|
||||
expect(page).to have_content failed_to_import_notice
|
||||
expect(page).to have_content no_appearance_releases
|
||||
end
|
||||
|
||||
@@ -249,6 +234,7 @@ feature 'User managing appearance releases' do
|
||||
expect(pdf_body).to have_content('TAGS')
|
||||
expect(pdf_body).to have_content('Woman')
|
||||
expect(pdf_body).to have_content('Brunette')
|
||||
expect(pdf_body).not_to have_content('Guardian Email')
|
||||
end
|
||||
|
||||
scenario 'viewing contract PDF for a minor without guardian photo' do
|
||||
@@ -262,8 +248,10 @@ feature 'User managing appearance releases' do
|
||||
expect(pdf_filename).to include(appearance_release.filename_suffix.parameterize)
|
||||
expect(pdf_body).to have_content(appearance_release.name)
|
||||
expect(pdf_body).to have_content(appearance_release.guardian_name)
|
||||
expect(pdf_body).to have_content(appearance_release.guardian_email)
|
||||
expect(pdf_body).to have_content photos_heading.upcase
|
||||
expect(pdf_body).to have_content(appearance_release.photo.filename.to_s)
|
||||
expect(pdf_body).to have_content('Guardian Email')
|
||||
end
|
||||
|
||||
scenario 'viewing contract PDF for a minor with guardian photo' do
|
||||
@@ -277,9 +265,11 @@ feature 'User managing appearance releases' do
|
||||
expect(pdf_filename).to include(appearance_release.filename_suffix.parameterize)
|
||||
expect(pdf_body).to have_content(appearance_release.name)
|
||||
expect(pdf_body).to have_content(appearance_release.guardian_name)
|
||||
expect(pdf_body).to have_content(appearance_release.guardian_email)
|
||||
expect(pdf_body).to have_content photos_heading(2).upcase
|
||||
expect(pdf_body).to have_content(appearance_release.photo.filename.to_s)
|
||||
expect(pdf_body).to have_content(appearance_release.guardian_photo.filename.to_s)
|
||||
expect(pdf_body).to have_content('Guardian Email')
|
||||
end
|
||||
|
||||
scenario 'deleting a release', js: true do
|
||||
@@ -422,6 +412,10 @@ feature 'User managing appearance releases' do
|
||||
tempfile
|
||||
end
|
||||
|
||||
def matching_started
|
||||
t 'appearance_releases.create.matching_started'
|
||||
end
|
||||
|
||||
def filter_type_all
|
||||
t 'appearance_releases.type_filter_actions.all_releases'
|
||||
end
|
||||
@@ -470,6 +464,10 @@ feature 'User managing appearance releases' do
|
||||
'Guardian phone'
|
||||
end
|
||||
|
||||
def guardian_email_field
|
||||
'Guardian email'
|
||||
end
|
||||
|
||||
def guardian_photo_field
|
||||
'appearance_release[guardian_photo]'
|
||||
end
|
||||
@@ -479,11 +477,11 @@ feature 'User managing appearance releases' do
|
||||
end
|
||||
|
||||
def person_first_name_field
|
||||
'Person first name'
|
||||
t('helpers.label.appearance_release.person_first_name')
|
||||
end
|
||||
|
||||
def person_last_name_field
|
||||
'Person last name'
|
||||
t('helpers.label.appearance_release.person_last_name')
|
||||
end
|
||||
|
||||
def person_address_field
|
||||
@@ -518,6 +516,10 @@ feature 'User managing appearance releases' do
|
||||
'Import Release'
|
||||
end
|
||||
|
||||
def submit_release_button
|
||||
'I have read and agree to the above'
|
||||
end
|
||||
|
||||
def submit_update_button
|
||||
'Save Changes'
|
||||
end
|
||||
|
||||
216
spec/jobs/match_appearance_releases_job_spec.rb
Normal file
216
spec/jobs/match_appearance_releases_job_spec.rb
Normal file
@@ -0,0 +1,216 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe MatchAppearanceReleasesJob do
|
||||
let(:project) { create(:project) }
|
||||
let(:dummy_appearance_release) { create(:appearance_release_import, :with_headshot, :with_contract) }
|
||||
let(:dummy_matching_request) { instance_double(MatchingRequest, id: 999) }
|
||||
|
||||
before :all do
|
||||
ENV["AWS_BUCKET"] = ""
|
||||
end
|
||||
|
||||
describe ".perform_now" do
|
||||
it "returns if no attachment is sent" do
|
||||
expect(MatchingRequest).not_to receive(:create)
|
||||
attachments = []
|
||||
MatchAppearanceReleasesJob.perform_now project, attachments
|
||||
end
|
||||
|
||||
it "returns if no valid attachment is sent" do
|
||||
expect(MatchingRequest).not_to receive(:create)
|
||||
dummy_video = create(:video)
|
||||
attachments = [dummy_video.file.blob.signed_id]
|
||||
MatchAppearanceReleasesJob.perform_now project, attachments
|
||||
end
|
||||
|
||||
it "does not create new appearance release if BrayniacAI returns empty matches array" do
|
||||
signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
|
||||
keys = [dummy_appearance_release.person_photo.key]
|
||||
payload = {
|
||||
project: project,
|
||||
attachments: signed_ids
|
||||
}
|
||||
qr_matching_payload = {
|
||||
bucket: '',
|
||||
files: keys,
|
||||
request_id: dummy_matching_request.id
|
||||
}
|
||||
qr_matching_mock_response = double(
|
||||
request_id: dummy_matching_request.id,
|
||||
matches: []
|
||||
)
|
||||
|
||||
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
|
||||
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
|
||||
expect(dummy_matching_request).to receive(:destroy)
|
||||
|
||||
MatchAppearanceReleasesJob.perform_now project, signed_ids
|
||||
|
||||
expect(AppearanceRelease.last).to eq dummy_appearance_release
|
||||
end
|
||||
|
||||
it "creates new incomplete appearance release if BrayniacAI returns single headshot match" do
|
||||
signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
|
||||
keys = [dummy_appearance_release.person_photo.key]
|
||||
payload = {
|
||||
project: project,
|
||||
attachments: signed_ids
|
||||
}
|
||||
qr_matching_payload = {
|
||||
bucket: '',
|
||||
files: keys,
|
||||
request_id: dummy_matching_request.id
|
||||
}
|
||||
mock_match = double(
|
||||
headshots: keys,
|
||||
contracts: [],
|
||||
unknowns: [],
|
||||
identifier: 'some/identifier/123'
|
||||
)
|
||||
matches = [mock_match]
|
||||
qr_matching_mock_response = double(
|
||||
request_id: dummy_matching_request.id,
|
||||
matches: matches
|
||||
)
|
||||
|
||||
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
|
||||
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
|
||||
expect(dummy_matching_request).to receive(:destroy)
|
||||
|
||||
MatchAppearanceReleasesJob.perform_now project, signed_ids
|
||||
|
||||
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
|
||||
expect(AppearanceRelease.last.person_photo).to be_attached
|
||||
expect(AppearanceRelease.last.contract).not_to be_attached
|
||||
end
|
||||
|
||||
it "creates new incomplete appearance release if BrayniacAI returns single contract match" do
|
||||
signed_ids = [dummy_appearance_release.contract.blob.signed_id]
|
||||
keys = [dummy_appearance_release.contract.key]
|
||||
payload = {
|
||||
project: project,
|
||||
attachments: signed_ids
|
||||
}
|
||||
qr_matching_payload = {
|
||||
bucket: '',
|
||||
files: keys,
|
||||
request_id: dummy_matching_request.id
|
||||
}
|
||||
mock_match = double(
|
||||
headshots: [],
|
||||
contracts: keys,
|
||||
unknowns: [],
|
||||
identifier: 'some/identifier/123'
|
||||
)
|
||||
matches = [mock_match]
|
||||
qr_matching_mock_response = double(
|
||||
request_id: dummy_matching_request.id,
|
||||
matches: matches
|
||||
)
|
||||
|
||||
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
|
||||
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
|
||||
expect(dummy_matching_request).to receive(:destroy)
|
||||
|
||||
MatchAppearanceReleasesJob.perform_now project, signed_ids
|
||||
|
||||
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
|
||||
expect(AppearanceRelease.last.person_photo.attached?).to eq false
|
||||
expect(AppearanceRelease.last.contract.attached?).to eq true
|
||||
end
|
||||
|
||||
it "creates new complete appearance release if BrayniacAI returns match for headshot and contract" do
|
||||
signed_ids = [
|
||||
dummy_appearance_release.person_photo.blob.signed_id,
|
||||
dummy_appearance_release.contract.blob.signed_id
|
||||
]
|
||||
keys = [
|
||||
dummy_appearance_release.person_photo.key,
|
||||
dummy_appearance_release.contract.key
|
||||
]
|
||||
payload = {
|
||||
project: project,
|
||||
attachments: signed_ids
|
||||
}
|
||||
qr_matching_payload = {
|
||||
bucket: '',
|
||||
files: keys,
|
||||
request_id: dummy_matching_request.id
|
||||
}
|
||||
mock_match = double(
|
||||
headshots: [keys[0]],
|
||||
contracts: [keys[1]],
|
||||
unknowns: [],
|
||||
identifier: 'some/identifier/123'
|
||||
)
|
||||
matches = [mock_match]
|
||||
qr_matching_mock_response = double(
|
||||
request_id: dummy_matching_request.id,
|
||||
matches: matches
|
||||
)
|
||||
|
||||
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
|
||||
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
|
||||
expect(dummy_matching_request).to receive(:destroy)
|
||||
|
||||
MatchAppearanceReleasesJob.perform_now project, signed_ids
|
||||
|
||||
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
|
||||
expect(AppearanceRelease.last.person_photo.attached?).to eq true
|
||||
expect(AppearanceRelease.last.contract.attached?).to eq true
|
||||
end
|
||||
|
||||
it "creates two new incomplete appearance releases if BrayniacAI returns two matches for headshot and contract" do
|
||||
signed_ids = [
|
||||
dummy_appearance_release.person_photo.blob.signed_id,
|
||||
dummy_appearance_release.contract.blob.signed_id
|
||||
]
|
||||
keys = [
|
||||
dummy_appearance_release.person_photo.key,
|
||||
dummy_appearance_release.contract.key
|
||||
]
|
||||
payload = {
|
||||
project: project,
|
||||
attachments: signed_ids
|
||||
}
|
||||
qr_matching_payload = {
|
||||
bucket: '',
|
||||
files: keys,
|
||||
request_id: dummy_matching_request.id
|
||||
}
|
||||
mock_match1 = double(
|
||||
headshots: [keys[0]],
|
||||
contracts: [],
|
||||
unknowns: [],
|
||||
identifier: 'some/identifier/123'
|
||||
)
|
||||
mock_match2 = double(
|
||||
headshots: [],
|
||||
contracts: [keys[1]],
|
||||
unknowns: [],
|
||||
identifier: 'some/identifier/789'
|
||||
)
|
||||
matches = [mock_match1, mock_match2]
|
||||
qr_matching_mock_response = double(
|
||||
request_id: dummy_matching_request.id,
|
||||
matches: matches
|
||||
)
|
||||
|
||||
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
|
||||
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
|
||||
expect(dummy_matching_request).to receive(:destroy)
|
||||
|
||||
MatchAppearanceReleasesJob.perform_now project, signed_ids
|
||||
|
||||
releases = AppearanceRelease.last(2)
|
||||
|
||||
expect(releases[0].identifier).to eq mock_match1.identifier
|
||||
expect(releases[0].person_photo.attached?).to eq true
|
||||
expect(releases[0].contract.attached?).to eq false
|
||||
|
||||
expect(releases[1].identifier).to eq mock_match2.identifier
|
||||
expect(releases[1].person_photo.attached?).to eq false
|
||||
expect(releases[1].contract.attached?).to eq true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -131,7 +131,8 @@ RSpec.describe Account do
|
||||
Broadcast,
|
||||
Account,
|
||||
ZoomMeeting,
|
||||
MedicalRelease
|
||||
MedicalRelease,
|
||||
MatchingRequest
|
||||
]
|
||||
Rails.application.eager_load!
|
||||
ActiveRecord::Base.descendants.each do |model|
|
||||
|
||||
@@ -42,7 +42,6 @@ describe BlankContract do
|
||||
material_release = create(:material_release_with_contract_template, project: project, person_name: 'Jane Doe')
|
||||
result = render_contract_html_for(material_release)
|
||||
|
||||
expect(result).to include 'serial-number'
|
||||
expect(result).to include 'DO NOT COPY'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,6 +97,18 @@ describe HeadshotCollection do
|
||||
expect(hash.keys).not_to include(:collection_uid)
|
||||
end
|
||||
end
|
||||
|
||||
context "when there are no releasables" do
|
||||
it "includes a blank hash value for the ids_to_images key" do
|
||||
releases = []
|
||||
collection = HeadshotCollection.new(nil, releases)
|
||||
|
||||
hash = collection.to_hash
|
||||
|
||||
expect(hash.keys).to include(:ids_to_images)
|
||||
expect(hash[:ids_to_images]).to eq(Hash.new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
Reference in New Issue
Block a user