diff --git a/Gemfile b/Gemfile
index 7c011f9..4b30193 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,7 +4,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "2.6.3"
# Bundle edge Rails instead: gem "rails", github: "rails/rails"
-gem "rails", "~> 6.0.0"
+gem "rails", "~> 6.0.3.1"
# Use postgresql as the database for Active Record
gem "pg", "~> 0.18"
# Use Puma as the app server
diff --git a/Gemfile.lock b/Gemfile.lock
index b1f67d7..25f6e5e 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -44,71 +44,71 @@ GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.0.3)
- actioncable (6.0.0)
- actionpack (= 6.0.0)
+ actioncable (6.0.3.2)
+ actionpack (= 6.0.3.2)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.0)
- actionpack (= 6.0.0)
- activejob (= 6.0.0)
- activerecord (= 6.0.0)
- activestorage (= 6.0.0)
- activesupport (= 6.0.0)
+ actionmailbox (6.0.3.2)
+ actionpack (= 6.0.3.2)
+ activejob (= 6.0.3.2)
+ activerecord (= 6.0.3.2)
+ activestorage (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
mail (>= 2.7.1)
- actionmailer (6.0.0)
- actionpack (= 6.0.0)
- actionview (= 6.0.0)
- activejob (= 6.0.0)
+ actionmailer (6.0.3.2)
+ actionpack (= 6.0.3.2)
+ actionview (= 6.0.3.2)
+ activejob (= 6.0.3.2)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.0)
- actionview (= 6.0.0)
- activesupport (= 6.0.0)
- rack (~> 2.0)
+ actionpack (6.0.3.2)
+ actionview (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
+ rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.0)
- actionpack (= 6.0.0)
- activerecord (= 6.0.0)
- activestorage (= 6.0.0)
- activesupport (= 6.0.0)
+ actiontext (6.0.3.2)
+ actionpack (= 6.0.3.2)
+ activerecord (= 6.0.3.2)
+ activestorage (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
nokogiri (>= 1.8.5)
- actionview (6.0.0)
- activesupport (= 6.0.0)
+ actionview (6.0.3.2)
+ activesupport (= 6.0.3.2)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_storage_base64 (1.0.0)
rails (~> 6.0)
- activejob (6.0.0)
- activesupport (= 6.0.0)
+ activejob (6.0.3.2)
+ activesupport (= 6.0.3.2)
globalid (>= 0.3.6)
- activemodel (6.0.0)
- activesupport (= 6.0.0)
+ activemodel (6.0.3.2)
+ activesupport (= 6.0.3.2)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
- activerecord (6.0.0)
- activemodel (= 6.0.0)
- activesupport (= 6.0.0)
+ activerecord (6.0.3.2)
+ activemodel (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
activeresource (5.1.0)
activemodel (>= 5.0, < 7)
activemodel-serializers-xml (~> 1.0)
activesupport (>= 5.0, < 7)
- activestorage (6.0.0)
- actionpack (= 6.0.0)
- activejob (= 6.0.0)
- activerecord (= 6.0.0)
+ activestorage (6.0.3.2)
+ actionpack (= 6.0.3.2)
+ activejob (= 6.0.3.2)
+ activerecord (= 6.0.3.2)
marcel (~> 0.3.1)
- activesupport (6.0.0)
+ activesupport (6.0.3.2)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
- zeitwerk (~> 2.1, >= 2.1.8)
+ zeitwerk (~> 2.2, >= 2.2.2)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
afm (0.2.2)
@@ -181,7 +181,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.1.5)
+ concurrent-ruby (1.1.6)
connection_pool (2.2.2)
countries (2.1.4)
i18n_data (~> 0.8.0)
@@ -230,7 +230,7 @@ GEM
hubspot-ruby (0.9.0)
activesupport (>= 3.0.0)
httparty (>= 0.10.0)
- i18n (1.8.2)
+ i18n (1.8.3)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
i18n_yaml_sorter (0.2.0)
@@ -270,22 +270,22 @@ GEM
ruby_dep (~> 1.2)
loaf (0.8.1)
rails (>= 3.2)
- loofah (2.4.0)
+ loofah (2.6.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
- method_source (0.9.2)
+ method_source (1.0.0)
mime-types (3.3)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.0904)
- mimemagic (0.3.3)
+ mimemagic (0.3.5)
mini_magick (4.9.5)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
- minitest (5.14.0)
+ minitest (5.14.1)
monetize (1.9.2)
money (~> 6.12)
money (6.13.4)
@@ -298,8 +298,8 @@ GEM
msgpack (1.3.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
- nio4r (2.5.1)
- nokogiri (1.10.7)
+ nio4r (2.5.2)
+ nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
oath (1.1.0)
bcrypt
@@ -337,20 +337,20 @@ GEM
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
- rails (6.0.0)
- actioncable (= 6.0.0)
- actionmailbox (= 6.0.0)
- actionmailer (= 6.0.0)
- actionpack (= 6.0.0)
- actiontext (= 6.0.0)
- actionview (= 6.0.0)
- activejob (= 6.0.0)
- activemodel (= 6.0.0)
- activerecord (= 6.0.0)
- activestorage (= 6.0.0)
- activesupport (= 6.0.0)
+ rails (6.0.3.2)
+ actioncable (= 6.0.3.2)
+ actionmailbox (= 6.0.3.2)
+ actionmailer (= 6.0.3.2)
+ actionpack (= 6.0.3.2)
+ actiontext (= 6.0.3.2)
+ actionview (= 6.0.3.2)
+ activejob (= 6.0.3.2)
+ activemodel (= 6.0.3.2)
+ activerecord (= 6.0.3.2)
+ activestorage (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
bundler (>= 1.3.0)
- railties (= 6.0.0)
+ railties (= 6.0.3.2)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x)
@@ -363,9 +363,9 @@ GEM
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
- railties (6.0.0)
- actionpack (= 6.0.0)
- activesupport (= 6.0.0)
+ railties (6.0.3.2)
+ actionpack (= 6.0.3.2)
+ activesupport (= 6.0.3.2)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
@@ -469,7 +469,7 @@ GEM
turbolinks-source (5.2.0)
typhoeus (1.3.1)
ethon (>= 0.9.0)
- tzinfo (1.2.6)
+ tzinfo (1.2.7)
thread_safe (~> 0.1)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
@@ -494,9 +494,9 @@ GEM
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
- websocket-driver (0.7.1)
+ websocket-driver (0.7.2)
websocket-extensions (>= 0.1.0)
- websocket-extensions (0.1.4)
+ websocket-extensions (0.1.5)
will_paginate (3.2.1)
will_paginate-bootstrap4 (0.2.2)
will_paginate (~> 3.0, >= 3.0.0)
@@ -504,7 +504,7 @@ GEM
wkhtmltopdf-heroku (2.12.5.0)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.2.2)
+ zeitwerk (2.3.1)
PLATFORMS
ruby
@@ -561,7 +561,7 @@ DEPENDENCIES
rack!
rack-contrib (~> 2.0.1)
rack-cors
- rails (~> 6.0.0)
+ rails (~> 6.0.3.1)
rails-controller-testing (~> 1.0.4)
rails-data-migrations (~> 1.2.0)
redcarpet (~> 3.4.0)
diff --git a/README.md b/README.md
index 201510c..4aa07ef 100644
--- a/README.md
+++ b/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
diff --git a/app/assets/javascripts/channels/broadcasts.coffee b/app/assets/javascripts/channels/broadcasts.coffee
index 9d49aaf..9ed744f 100644
--- a/app/assets/javascripts/channels/broadcasts.coffee
+++ b/app/assets/javascripts/channels/broadcasts.coffee
@@ -1,22 +1,23 @@
$(document).on "turbolinks:load", ->
- # 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 },
+ subscribeToBroadcast = (broadcastToken) -> 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" then @refreshBroadcastVideo(data)
- when "stream_recording_ready" then @showBroadcastRecordings(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
@@ -37,3 +38,12 @@ $(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
diff --git a/app/assets/javascripts/channels/projects.coffee b/app/assets/javascripts/channels/projects.coffee
index c0e4037..41061c9 100644
--- a/app/assets/javascripts/channels/projects.coffee
+++ b/app/assets/javascripts/channels/projects.coffee
@@ -16,6 +16,7 @@ $(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
diff --git a/app/assets/javascripts/collapse_select.js b/app/assets/javascripts/collapse_select.js
index d3d19e4..06ef0fa 100644
--- a/app/assets/javascripts/collapse_select.js
+++ b/app/assets/javascripts/collapse_select.js
@@ -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");
+});
\ No newline at end of file
diff --git a/app/assets/javascripts/multi_view_broadcasts.js b/app/assets/javascripts/multi_view_broadcasts.js
index 27325ab..f313ab8 100644
--- a/app/assets/javascripts/multi_view_broadcasts.js
+++ b/app/assets/javascripts/multi_view_broadcasts.js
@@ -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');
diff --git a/app/assets/javascripts/photo_preview.js b/app/assets/javascripts/photo_preview.js
index 3f0cbb8..741db37 100644
--- a/app/assets/javascripts/photo_preview.js
+++ b/app/assets/javascripts/photo_preview.js
@@ -51,10 +51,8 @@ $(document).on("turbolinks:load", function() {
$("[data-behavior=guardian-photo-preview]").each(function(index, element) {
App.PhotoPreview.init(element);
});
- $("[data-behavior=take-person-photo]").click(function(e) {
- $("[data-ujs-target=person-photo-input]").trigger("click");
- });
- $("[data-behavior=take-guardian-photo]").click(function(e) {
- $("[data-ujs-target=guardian-photo-input]").trigger("click");
+ $("[data-behavior=trigger-click]").click(function(e) {
+ const target = $(this).data("target");
+ $(target).trigger("click");
});
});
diff --git a/app/assets/javascripts/play_previous_recordings.js b/app/assets/javascripts/play_previous_recordings.js
deleted file mode 100644
index f2d1212..0000000
--- a/app/assets/javascripts/play_previous_recordings.js
+++ /dev/null
@@ -1,24 +0,0 @@
-$(document).on("click", "[data-behavior=play_recording]", function() {
- if ($(this).hasClass('active')){
- return false;
- }
-
- var playback_url = $(this).attr("data-playback-url")
- $("#broadcast_video").empty();
-
- new Clappr.Player({
- parentId: '#broadcast_video',
- source: playback_url,
- width: '100%',
- height: '100%',
- autoPlay: true
- });
-
- $(".dropdown-menu").children().removeClass('active');
- $(".dropdown-menu").children().children('i').remove();
- $(this).siblings().removeClass('active');
- $(this).siblings().children("i").remove();
- $(this).addClass('active');
- $(this).prepend(' ');
-});
-
diff --git a/app/assets/javascripts/play_previous_recordings.js.erb b/app/assets/javascripts/play_previous_recordings.js.erb
new file mode 100644
index 0000000..c3c7b49
--- /dev/null
+++ b/app/assets/javascripts/play_previous_recordings.js.erb
@@ -0,0 +1,26 @@
+$(document).on("click", "[data-behavior=play_recording]", function() {
+ if ($(this).hasClass('active')){
+ return false;
+ }
+
+ console.warn('Play prev : ', playback_url);
+
+ var playback_url = $(this).attr("data-playback-url")
+ $("#broadcast_video").empty();
+
+ new Clappr.Player({
+ <%= "baseUrl: 'http://cdn.clappr.io/latest'," if Rails.env.test? %>
+ parentId: '#broadcast_video',
+ source: playback_url,
+ width: '100%',
+ height: '100%',
+ autoPlay: true
+ });
+
+ $(".dropdown-menu").children().removeClass('active');
+ $(".dropdown-menu").children().children('i').remove();
+ $(this).siblings().removeClass('active');
+ $(this).siblings().children("i").remove();
+ $(this).addClass('active');
+ $(this).prepend(' ');
+});
\ No newline at end of file
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index ffbf3b1..b14620f 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -6,6 +6,11 @@
@import "dropzone/dist/dropzone";
@import 'bootstrap-datepicker';
+// Global styles
+label {
+ text-transform: capitalize;
+}
+
// Wordmarks
.suite-wordmark {
font-weight: normal;
diff --git a/app/assets/stylesheets/contract_pdf.scss b/app/assets/stylesheets/contract_pdf.scss
index 59c6abc..8c2571f 100644
--- a/app/assets/stylesheets/contract_pdf.scss
+++ b/app/assets/stylesheets/contract_pdf.scss
@@ -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%;
}
diff --git a/app/channels/broadcasts_channel.rb b/app/channels/broadcasts_channel.rb
index 36d1d95..dd3d941 100644
--- a/app/channels/broadcasts_channel.rb
+++ b/app/channels/broadcasts_channel.rb
@@ -28,10 +28,21 @@ 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
diff --git a/app/channels/projects_channel.rb b/app/channels/projects_channel.rb
index 9b2ebbd..68ee885 100644
--- a/app/channels/projects_channel.rb
+++ b/app/channels/projects_channel.rb
@@ -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,4 +25,12 @@ 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
diff --git a/app/controllers/acquired_media_releases_controller.rb b/app/controllers/acquired_media_releases_controller.rb
index 8d572ab..9c1858e 100644
--- a/app/controllers/acquired_media_releases_controller.rb
+++ b/app/controllers/acquired_media_releases_controller.rb
@@ -61,7 +61,8 @@ class AcquiredMediaReleasesController < ApplicationController
:name,
:territory,
:term,
- :person_name,
+ :person_first_name,
+ :person_last_name,
:person_phone,
:person_email,
:person_company,
diff --git a/app/controllers/api/broadcasts_controller.rb b/app/controllers/api/broadcasts_controller.rb
index b3ed0a9..25cadfa 100644
--- a/app/controllers/api/broadcasts_controller.rb
+++ b/app/controllers/api/broadcasts_controller.rb
@@ -24,8 +24,12 @@ class Api::BroadcastsController < Api::ApiController
def update
file_params.each do |file|
- file[:io] = StringIO.new(Base64.decode64(file[:io]))
- @broadcast.files.attach(io: file[:io], filename: file[:filename])
+ if file.is_a?(String)
+ @broadcast.files.attach(file)
+ else
+ file[:io] = StringIO.new(Base64.decode64(file[:io]))
+ @broadcast.files.attach(file.to_h.symbolize_keys)
+ end
end
@broadcast.save!
diff --git a/app/controllers/api/direct_uploads_controller.rb b/app/controllers/api/direct_uploads_controller.rb
new file mode 100644
index 0000000..ac25b25
--- /dev/null
+++ b/app/controllers/api/direct_uploads_controller.rb
@@ -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
diff --git a/app/controllers/appearance_release_imports_controller.rb b/app/controllers/appearance_release_imports_controller.rb
index 40a0857..b80a7d2 100644
--- a/app/controllers/appearance_release_imports_controller.rb
+++ b/app/controllers/appearance_release_imports_controller.rb
@@ -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 += '
'
- @failed_files.each { |file_name| alert_message += "- #{file_name}
" }
- alert_message += '
'
- 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
diff --git a/app/controllers/appearance_releases_controller.rb b/app/controllers/appearance_releases_controller.rb
index e63ec5a..16440ac 100644
--- a/app/controllers/appearance_releases_controller.rb
+++ b/app/controllers/appearance_releases_controller.rb
@@ -77,9 +77,43 @@ class AppearanceReleasesController < ApplicationController
results
end
+ def person_params
+ %i[
+ person_first_name
+ person_last_name
+ person_phone
+ person_email
+ person_photo
+ person_address_street1
+ ]
+ end
+
+ def guardian_params
+ %i[
+ guardian_first_name
+ guardian_last_name
+ guardian_phone
+ guardian_email
+ guardian_photo
+ guardian_address_street1
+ ]
+ end
+
+ def second_guardian_params
+ %i[
+ guardian_2_first_name
+ guardian_2_last_name
+ guardian_2_phone
+ guardian_2_email
+ guardian_2_photo
+ guardian_2_address_street1
+ ]
+ end
+
def appearance_release_params
- 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,
+ params.require(:appearance_release).permit(person_params,
+ guardian_params, second_guardian_params,
+ :contract, :minor,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text, :person_date_of_birth,
diff --git a/app/controllers/broadcasts_controller.rb b/app/controllers/broadcasts_controller.rb
index 3ae5e41..c83338a 100644
--- a/app/controllers/broadcasts_controller.rb
+++ b/app/controllers/broadcasts_controller.rb
@@ -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,18 +24,21 @@ class BroadcastsController < ApplicationController
end
end
- def update
- @broadcast.update(broadcast_params)
- @files = @broadcast.files.order("created_at DESC").paginate(page: 1)
- 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[: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)
+
+ pagination_content = ApplicationController.render html: helpers.will_paginate(@files, params: { active_tab: params[:active_tab], page: params[:page], active_files_tab: params[:active_files_tab] })
+ BroadcastsChannel.broadcast_file_upload_updates(@broadcast, @files, pagination_content)
+ end
+
def destroy
if @broadcast.destroy
redirect_to [@project, :broadcasts], alert: t(".alert")
@@ -68,7 +71,10 @@ 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 { |b| MultiViewBroadcast.new(b, params[:multi_view_ids]) }
+ @multi_view_broadcasts = authorized_broadcasts.map do |b|
+ files_page = params[:files_page] if params[:active_files_tab] == b.token
+ MultiViewBroadcast.new(b, params[:multi_view_ids], files_page)
+ end
end
def filtered_broadcasts
@@ -87,20 +93,29 @@ class BroadcastsController < ApplicationController
class MultiViewBroadcast
include Rails.application.routes.url_helpers
-
+
delegate_missing_to :@broadcast
-
- def initialize(broadcast, multi_view_ids)
+
+ def initialize(broadcast, multi_view_ids, paginate_page)
@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
diff --git a/app/controllers/concerns/medical_release_context.rb b/app/controllers/concerns/medical_release_context.rb
new file mode 100644
index 0000000..6b15cd4
--- /dev/null
+++ b/app/controllers/concerns/medical_release_context.rb
@@ -0,0 +1,13 @@
+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
diff --git a/app/controllers/concerns/misc_release_context.rb b/app/controllers/concerns/misc_release_context.rb
new file mode 100644
index 0000000..75c8b6a
--- /dev/null
+++ b/app/controllers/concerns/misc_release_context.rb
@@ -0,0 +1,13 @@
+module MiscReleaseContext
+ extend ActiveSupport::Concern
+
+ def misc_releases
+ policy_scope(MiscRelease)
+ end
+
+ def set_misc_release
+ misc_release_id = params[:misc_release_id] || params[:id]
+
+ @misc_release = authorize misc_releases.find(misc_release_id)
+ end
+end
diff --git a/app/controllers/contract_templates_controller.rb b/app/controllers/contract_templates_controller.rb
index f5698c0..5f3fbc6 100644
--- a/app/controllers/contract_templates_controller.rb
+++ b/app/controllers/contract_templates_controller.rb
@@ -61,7 +61,15 @@ 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,
+ :question_11_text, :question_12_text,
+ :question_13_text, :question_14_text,
+ :question_15_text)
end
def download_attributes
diff --git a/app/controllers/contracts_controller.rb b/app/controllers/contracts_controller.rb
index 73997e1..6f943ec 100644
--- a/app/controllers/contracts_controller.rb
+++ b/app/controllers/contracts_controller.rb
@@ -48,8 +48,10 @@ class ContractsController < ApplicationController
# Native release contracts must be generated on-the-fly; non-native releases have a contract attachment
if releasable.native?
send_file contract.to_pdf, download_attributes
- else
+ elsif policy(contract).show?
redirect_to releasable.contract.service_url
+ else
+ raise Pundit::NotAuthorizedError
end
end
end
diff --git a/app/controllers/location_releases_controller.rb b/app/controllers/location_releases_controller.rb
index 5ece1f0..898032a 100644
--- a/app/controllers/location_releases_controller.rb
+++ b/app/controllers/location_releases_controller.rb
@@ -68,7 +68,8 @@ class LocationReleasesController < ApplicationController
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text,
- :filming_started_on, :filming_ended_on
+ :filming_started_on, :filming_ended_on,
+ :filming_hours
)
end
diff --git a/app/controllers/medical_releases_controller.rb b/app/controllers/medical_releases_controller.rb
new file mode 100644
index 0000000..9c48ce0
--- /dev/null
+++ b/app/controllers/medical_releases_controller.rb
@@ -0,0 +1,40 @@
+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
diff --git a/app/controllers/misc_releases_controller.rb b/app/controllers/misc_releases_controller.rb
new file mode 100644
index 0000000..1541725
--- /dev/null
+++ b/app/controllers/misc_releases_controller.rb
@@ -0,0 +1,40 @@
+class MiscReleasesController < ApplicationController
+ include ProjectContext, MiscReleaseContext
+
+ before_action :set_project, only: [:index]
+ before_action :set_misc_release, only: [:destroy]
+
+ include ProjectLayout
+
+ def index
+ @misc_releases = filtered_misc_releases.order_by_recent.paginate(page: params[:page])
+ end
+
+ def destroy
+ @project = @misc_release.project
+
+ if @misc_release.destroy
+ redirect_to [@project, :misc_releases], alert: t(".alert")
+ end
+ end
+
+ private
+
+ def misc_releases
+ if @project
+ policy_scope(@project.misc_releases)
+ else
+ policy_scope(MiscRelease)
+ end
+ end
+
+ def filtered_misc_releases
+ results = misc_releases
+
+ if params[:query].present?
+ results = results.search(params[:query])
+ end
+
+ results
+ end
+end
diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb
index bca7a3b..b956781 100644
--- a/app/controllers/password_resets_controller.rb
+++ b/app/controllers/password_resets_controller.rb
@@ -18,6 +18,7 @@ class PasswordResetsController < ApplicationController
end
def edit
+ redirect_to new_session_path, notice: t(".notice") if @user.nil?
end
def update
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 2b13b11..c02708d 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -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 video_analysis)
+ %i(appearance_release location_release material_release acquired_media_release music_release talent_release medical_release misc_release video_analysis)
end
def project_params_with_current_account
diff --git a/app/controllers/public/acquired_media_releases_controller.rb b/app/controllers/public/acquired_media_releases_controller.rb
index 1d6bd11..5288601 100644
--- a/app/controllers/public/acquired_media_releases_controller.rb
+++ b/app/controllers/public/acquired_media_releases_controller.rb
@@ -45,6 +45,9 @@ 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,
diff --git a/app/controllers/public/appearance_releases_controller.rb b/app/controllers/public/appearance_releases_controller.rb
index c1a0955..17d5464 100644
--- a/app/controllers/public/appearance_releases_controller.rb
+++ b/app/controllers/public/appearance_releases_controller.rb
@@ -39,11 +39,60 @@ 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 guardian_params
+ %i[
+ guardian_first_name
+ guardian_last_name
+ guardian_phone
+ guardian_email
+ guardian_photo
+ guardian_address_street1
+ guardian_address_street2
+ guardian_address_city
+ guardian_address_state
+ guardian_address_zip
+ guardian_address_country
+ ]
+ end
+
+ def second_guardian_params
+ %i[
+ guardian_2_first_name
+ guardian_2_last_name
+ guardian_2_phone
+ guardian_2_email
+ guardian_2_photo
+ guardian_2_address_street1
+ guardian_2_address_street2
+ guardian_2_address_city
+ guardian_2_address_state
+ guardian_2_address_zip
+ guardian_2_address_country
+ ]
+ end
+
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,
- :signature_base64, :person_date_of_birth,
- :locale, :contract_template,)
+ params.require(:appearance_release).permit(person_params, guardian_params,
+ second_guardian_params,
+ :minor, :signature_base64,
+ :person_date_of_birth,
+ :locale, :contract_template)
end
def appearance_release_params_with_locale
diff --git a/app/controllers/public/broadcasts_controller.rb b/app/controllers/public/broadcasts_controller.rb
index 314e6c3..bad8a1c 100644
--- a/app/controllers/public/broadcasts_controller.rb
+++ b/app/controllers/public/broadcasts_controller.rb
@@ -6,14 +6,17 @@ 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[:page])
-
+ @files = @broadcast.files.order("created_at DESC").paginate(page: params[:files_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
@@ -26,29 +29,45 @@ class Public::BroadcastsController < Public::BaseController
Broadcast.
where(token: params[:multi_view_tokens]).
order_by_recent.
- map { |b| MultiViewBroadcast.new(b, params[:multi_view_tokens]) }
+ map do |b|
+ files_page = params[:files_page] if params[:active_files_tab] == b.token
+ MultiViewBroadcast.new(b, params[:multi_view_tokens], files_page)
+ end
end
def set_broadcast
@broadcast = Broadcast.find_by_token(params[:token])
+
+ unless @broadcast.present?
+ redirect_to [:new, :session], alert: t(".alert")
+ end
end
class MultiViewBroadcast
include Rails.application.routes.url_helpers
-
+
delegate_missing_to :@broadcast
-
- def initialize(broadcast, multi_view_tokens)
+
+ def initialize(broadcast, multi_view_tokens, paginate_page)
@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
diff --git a/app/controllers/public/location_releases_controller.rb b/app/controllers/public/location_releases_controller.rb
index 563e188..536406d 100644
--- a/app/controllers/public/location_releases_controller.rb
+++ b/app/controllers/public/location_releases_controller.rb
@@ -63,7 +63,9 @@ class Public::LocationReleasesController < Public::BaseController
:person_address_zip,
:person_address_country,
:signature_base64,
- :locale, :contract_template, :filming_started_on, :filming_ended_on
+ :locale, :contract_template, :filming_started_on, :filming_ended_on,
+ :filming_hours,
+ photos: []
)
end
diff --git a/app/controllers/public/material_releases_controller.rb b/app/controllers/public/material_releases_controller.rb
index f8e4846..5aef717 100644
--- a/app/controllers/public/material_releases_controller.rb
+++ b/app/controllers/public/material_releases_controller.rb
@@ -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
+ :locale, :contract_template, :description, photos: []
)
end
diff --git a/app/controllers/public/medical_releases_controller.rb b/app/controllers/public/medical_releases_controller.rb
new file mode 100644
index 0000000..084298c
--- /dev/null
+++ b/app/controllers/public/medical_releases_controller.rb
@@ -0,0 +1,123 @@
+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,
+ guardian_params,
+ second_guardian_params,
+ :minor,
+ :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,
+ :question_11_answer, :question_12_answer,
+ :question_13_answer, :question_14_answer,
+ :question_15_answer, photos: [],
+ )
+ end
+
+ def person_params
+ %i[
+ 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 guardian_params
+ %i[
+ guardian_first_name
+ guardian_last_name
+ guardian_phone
+ guardian_email
+ guardian_photo
+ guardian_address_street1
+ guardian_address_street2
+ guardian_address_city
+ guardian_address_state
+ guardian_address_zip
+ guardian_address_country
+ ]
+ end
+
+ def second_guardian_params
+ %i[
+ guardian_2_first_name
+ guardian_2_last_name
+ guardian_2_phone
+ guardian_2_email
+ guardian_2_photo
+ guardian_2_address_street1
+ guardian_2_address_street2
+ guardian_2_address_city
+ guardian_2_address_state
+ guardian_2_address_zip
+ guardian_2_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
diff --git a/app/controllers/public/misc_releases_controller.rb b/app/controllers/public/misc_releases_controller.rb
new file mode 100644
index 0000000..61e4933
--- /dev/null
+++ b/app/controllers/public/misc_releases_controller.rb
@@ -0,0 +1,99 @@
+class Public::MiscReleasesController < Public::BaseController
+ before_action :set_account, :set_project, :set_contract_template
+
+ def new
+ @misc_release = build_misc_release
+ end
+
+ def create
+ @misc_release = build_misc_release(misc_release_params_with_locale_and_contract_template)
+
+ if @misc_release.save(context: :native)
+ if @misc_release.contract_template.present?
+ AttachContractToReleasableJob.perform_later(@misc_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 misc_releases
+ policy_scope(@project.misc_releases)
+ end
+
+ def build_misc_release(params = {})
+ authorize misc_releases.build(params)
+ end
+
+ def misc_release_params
+ params
+ .require(:misc_release)
+ .permit(
+ person_params,
+ guardian_params,
+ :signature_base64,
+ :locale,
+ :contract_template,
+ 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 guardian_params
+ [
+ :guardian_first_name,
+ :guardian_last_name,
+ :guardian_phone,
+ :guardian_email,
+ :minor,
+ :guardian_address_street1,
+ :guardian_address_street2,
+ :guardian_address_city,
+ :guardian_address_state,
+ :guardian_address_zip,
+ :guardian_address_country,
+ :guardian_photo
+ ]
+ end
+
+ def misc_release_params_with_locale
+ misc_release_params.merge(locale: I18n.locale)
+ end
+
+ def misc_release_params_with_locale_and_contract_template
+ misc_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: MiscRelease.to_s, account: @account, user_agent: request.user_agent, user_ip: request.remote_ip)
+ end
+end
diff --git a/app/controllers/public/talent_releases_controller.rb b/app/controllers/public/talent_releases_controller.rb
index 44d2f33..4c6fd3e 100644
--- a/app/controllers/public/talent_releases_controller.rb
+++ b/app/controllers/public/talent_releases_controller.rb
@@ -45,42 +45,59 @@ class Public::TalentReleasesController < Public::BaseController
.permit(
person_params,
guardian_params,
+ second_guardian_params,
:signature_base64,
:locale,
:contract_template,
- photos: [],
+ 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,
+ %i[
+ 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 guardian_params
- [
- :guardian_first_name,
- :guardian_last_name,
- :guardian_phone,
- :guardian_email,
- :minor,
- :guardian_address_street1,
- :guardian_address_street2,
- :guardian_address_city,
- :guardian_address_state,
- :guardian_address_zip,
- :guardian_address_country,
- :guardian_photo,
+ %i[
+ guardian_first_name
+ guardian_last_name
+ guardian_phone
+ guardian_email
+ minor
+ guardian_address_street1
+ guardian_address_street2
+ guardian_address_city
+ guardian_address_state
+ guardian_address_zip
+ guardian_address_country
+ guardian_photo
+ ]
+ end
+
+ def second_guardian_params
+ %i[
+ guardian_2_first_name
+ guardian_2_last_name
+ guardian_2_phone
+ guardian_2_email
+ guardian_2_address_street1
+ guardian_2_address_street2
+ guardian_2_address_city
+ guardian_2_address_state
+ guardian_2_address_zip
+ guardian_2_address_country
+ guardian_2_photo
]
end
diff --git a/app/controllers/release_template_imports_controller.rb b/app/controllers/release_template_imports_controller.rb
index 9efb566..56c33cf 100644
--- a/app/controllers/release_template_imports_controller.rb
+++ b/app/controllers/release_template_imports_controller.rb
@@ -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)
diff --git a/app/controllers/talent_releases_controller.rb b/app/controllers/talent_releases_controller.rb
index c937db9..e2255c2 100644
--- a/app/controllers/talent_releases_controller.rb
+++ b/app/controllers/talent_releases_controller.rb
@@ -61,15 +61,67 @@ class TalentReleasesController < ApplicationController
end
end
+ def person_params
+ %i[
+ 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 guardian_params
+ %i[
+ guardian_first_name
+ guardian_last_name
+ guardian_phone
+ guardian_email
+ minor
+ guardian_address_street1
+ guardian_address_street2
+ guardian_address_city
+ guardian_address_state
+ guardian_address_zip
+ guardian_address_country
+ guardian_photo
+ ]
+ end
+
+ def second_guardian_params
+ %i[
+ guardian_2_first_name
+ guardian_2_last_name
+ guardian_2_phone
+ guardian_2_email
+ guardian_2_address_street1
+ guardian_2_address_street2
+ guardian_2_address_city
+ guardian_2_address_state
+ guardian_2_address_zip
+ guardian_2_address_country
+ guardian_2_photo
+ ]
+ end
+
def talent_release_params
- params.require(:talent_release).permit(
- :person_first_name, :person_last_name, :person_phone, :guardian_photo, :person_email,
- :person_address_street1, :person_address_street2, :person_address_city, :person_address_state, :person_address_zip, :person_address_country,
- :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_email, :minor,
- :guardian_address_street1, :guardian_address_street2, :guardian_address_city, :guardian_address_state, :guardian_address_zip, :guardian_address_country,
- :contract, { photos: [] },
- :applicable_medium_id, :applicable_medium_text, :territory_id, :territory_text, :term_id, :term_text, :restriction_id, :restriction_text
- )
+ params.require(:talent_release).permit(person_params,
+ guardian_params,
+ second_guardian_params,
+ :contract, { photos: [] },
+ :applicable_medium_id,
+ :applicable_medium_text,
+ :territory_id,
+ :territory_text,
+ :term_id,
+ :term_text,
+ :restriction_id,
+ :restriction_text)
end
def build_talent_release(attrs = {})
diff --git a/app/controllers/zoom_notifications_controller.rb b/app/controllers/zoom_notifications_controller.rb
index 0550250..827af74 100644
--- a/app/controllers/zoom_notifications_controller.rb
+++ b/app/controllers/zoom_notifications_controller.rb
@@ -5,7 +5,7 @@ class ZoomNotificationsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :authorize_zoom
- before_action :set_zoom_meeting, only: :create
+ before_action :set_zoom_meeting, only: [:create], if: :meeting_event?
def create
case notification_event
@@ -13,8 +13,17 @@ 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_type
+ Rails.logger.info notification_event
Rails.logger.info notification
end
@@ -23,16 +32,24 @@ class ZoomNotificationsController < ApplicationController
private
+ def notification
+ params.to_unsafe_h
+ end
+
def notification_event
- params.dig(:event)
+ notification.dig(:event)
end
def notification_meeting_id
- params.dig(:payload, :object, :id)
+ notification.dig(:payload, :object, :id)
end
def notification_host_id
- params.dig(:payload, :object, :host_id)
+ notification.dig(:payload, :object, :host_id)
+ end
+
+ def meeting_event?
+ notification_event.split(".").first.to_s.in? %w(meeting recording)
end
def set_zoom_meeting
diff --git a/app/helpers/contact_info_helper.rb b/app/helpers/contact_info_helper.rb
index 77e4def..b79dd07 100644
--- a/app/helpers/contact_info_helper.rb
+++ b/app/helpers/contact_info_helper.rb
@@ -41,7 +41,7 @@ module ContactInfoHelper
end
def email_abbr(email)
- content_tag(:abbr, "E: ", title: "Email") + email
+ content_tag(:abbr, "E: ", title: "Email") + mail_to(email)
end
def phone_abbr(phone)
diff --git a/app/helpers/dropzone_helper.rb b/app/helpers/dropzone_helper.rb
index 60d2d4d..321bac3 100644
--- a/app/helpers/dropzone_helper.rb
+++ b/app/helpers/dropzone_helper.rb
@@ -2,9 +2,13 @@ module DropzoneHelper
def dropzone_placeholder_message_for(releasable)
case releasable.model_name.param_key
when "acquired_media_release"
- "To Add Photos & Videos to the release:
Drag & Drop Files
or
Click or Tap here to browse photos and connect to Camera"
+ '(Optional) To add the licensed photos or videos ("Property") to this release:
Drag & Drop Files
or
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:
Drag & Drop Files
or
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:
Drag & Drop Files
or
Click or Tap here to browse files"
when "task_request"
diff --git a/app/jobs/attach_recording_to_zoom_meeting_job.rb b/app/jobs/attach_recording_to_zoom_meeting_job.rb
new file mode 100644
index 0000000..57bc321
--- /dev/null
+++ b/app/jobs/attach_recording_to_zoom_meeting_job.rb
@@ -0,0 +1,25 @@
+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
diff --git a/app/jobs/match_appearance_releases_job.rb b/app/jobs/match_appearance_releases_job.rb
new file mode 100644
index 0000000..5136170
--- /dev/null
+++ b/app/jobs/match_appearance_releases_job.rb
@@ -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
diff --git a/app/models/account.rb b/app/models/account.rb
index d9bd775..826eb1c 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -55,6 +55,10 @@ class Account < ApplicationRecord
User.joins(:project_memberships).where(project_memberships: { project: projects }),
Broadcast.where(project: projects),
TaskRequest.where(project: projects),
+ ZoomMeeting.where(project: projects),
+ MedicalRelease.where(project: projects),
+ MiscRelease.where(project: projects),
+ MatchingRequest.where(project: projects),
self
])).sum(:byte_size).to_f
end
diff --git a/app/models/acquired_media_release.rb b/app/models/acquired_media_release.rb
index 1638efd..6a12d35 100644
--- a/app/models/acquired_media_release.rb
+++ b/app/models/acquired_media_release.rb
@@ -43,7 +43,8 @@ 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 = ["Artwork", "Film Footage", "Video Footage", "Still Photograph"].freeze
+ CATEGORIES = ["Film Footage", "Video Footage", "Still Photograph"].freeze
def minor?
false
diff --git a/app/models/appearance_release.rb b/app/models/appearance_release.rb
index 59d1f22..9a750a7 100644
--- a/app/models/appearance_release.rb
+++ b/app/models/appearance_release.rb
@@ -12,10 +12,46 @@ class AppearanceRelease < ApplicationRecord
include Taggable
include PersonName
include GuardianPhotoable
+ include SecondGuardianPhotoable
include GuardianName
+ include SecondGuardianName
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]
+ ]
+
+ composed_of :guardian_address,
+ class_name: 'Address',
+ mapping: [
+ %w[guardian_address_street1 street1],
+ %w[guardian_address_street2 street2],
+ %w[guardian_address_city city],
+ %w[guardian_address_state state],
+ %w[guardian_address_zip zip],
+ %w[guardian_address_country country]
+ ]
+
+ composed_of :guardian_2_address,
+ class_name: 'Address',
+ mapping: [
+ %w[guardian_2_address_street1 street1],
+ %w[guardian_2_address_street2 street2],
+ %w[guardian_2_address_city city],
+ %w[guardian_2_address_state state],
+ %w[guardian_2_address_zip zip],
+ %w[guardian_2_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
@@ -39,6 +75,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
@@ -70,7 +107,18 @@ 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 person_email person_phone]
+ 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
+ ]
# All releases must respond to the following messages
def name
@@ -97,6 +145,10 @@ class AppearanceRelease < ApplicationRecord
true
end
+ def second_guardian_present?
+ self.guardian_2_first_name.present?
+ 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
diff --git a/app/models/blank_contract.rb b/app/models/blank_contract.rb
index ee36282..cde5d8a 100644
--- a/app/models/blank_contract.rb
+++ b/app/models/blank_contract.rb
@@ -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
diff --git a/app/models/broadcast.rb b/app/models/broadcast.rb
index a74f105..564fd41 100644
--- a/app/models/broadcast.rb
+++ b/app/models/broadcast.rb
@@ -7,8 +7,6 @@ class Broadcast < ApplicationRecord
has_secure_token
- scope :order_by_recent, -> { order(created_at: :desc) }
-
validates :name, presence: true
enum status: [:created, :active, :idle]
diff --git a/app/models/broadcast_recording.rb b/app/models/broadcast_recording.rb
index 179ea49..fe4cd9c 100644
--- a/app/models/broadcast_recording.rb
+++ b/app/models/broadcast_recording.rb
@@ -1,8 +1,6 @@
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
diff --git a/app/models/concerns/attachable.rb b/app/models/concerns/attachable.rb
new file mode 100644
index 0000000..7d4860a
--- /dev/null
+++ b/app/models/concerns/attachable.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Attachable
+ extend ActiveSupport::Concern
+
+ included do
+ has_many_attached :attachments
+ end
+end
diff --git a/app/models/concerns/releasable.rb b/app/models/concerns/releasable.rb
index 3d024e4..08ccf4a 100644
--- a/app/models/concerns/releasable.rb
+++ b/app/models/concerns/releasable.rb
@@ -6,8 +6,6 @@ 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
diff --git a/app/models/concerns/second_guardian_name.rb b/app/models/concerns/second_guardian_name.rb
new file mode 100644
index 0000000..8e4e04d
--- /dev/null
+++ b/app/models/concerns/second_guardian_name.rb
@@ -0,0 +1,20 @@
+module SecondGuardianName
+ extend ActiveSupport::Concern
+
+ included do
+ def guardian_2_name
+ "#{guardian_2_first_name} #{guardian_2_last_name}".titleize
+ end
+
+ def guardian_2_name=(value)
+ if value.include?(' ')
+ split = value.split(" ", 2)
+ self.guardian_2_first_name = split.first
+ self.guardian_2_last_name = split.last
+ else
+ self.guardian_2_first_name = value
+ self.guardian_2_last_name = "(Not Given)"
+ end
+ end
+ end
+end
diff --git a/app/models/concerns/second_guardian_photoable.rb b/app/models/concerns/second_guardian_photoable.rb
new file mode 100644
index 0000000..5e21240
--- /dev/null
+++ b/app/models/concerns/second_guardian_photoable.rb
@@ -0,0 +1,9 @@
+module SecondGuardianPhotoable
+ extend ActiveSupport::Concern
+
+ included do
+ has_one_attached :guardian_2_photo
+
+ validates :guardian_2_photo, content_type: ["image/png", "image/jpeg"]
+ end
+end
diff --git a/app/models/contract.rb b/app/models/contract.rb
index 534c264..1c475e3 100644
--- a/app/models/contract.rb
+++ b/app/models/contract.rb
@@ -29,6 +29,10 @@ class Contract
}
end
+ def medical_release?
+ @releasable.instance_of?(MedicalRelease)
+ end
+
private
def contract_template
diff --git a/app/models/contract_template.rb b/app/models/contract_template.rb
index 6e91a5e..6b213a6 100644
--- a/app/models/contract_template.rb
+++ b/app/models/contract_template.rb
@@ -13,6 +13,8 @@ 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
+ has_many :misc_releases, dependent: :restrict_with_error
monetize :fee_cents
has_rich_text :body
@@ -50,6 +52,10 @@ class ContractTemplate < ApplicationRecord
parent.present?
end
+ def archived?
+ archived_at.present?
+ end
+
def archive
update(archived_at: Time.zone.now)
end
diff --git a/app/models/headshot_collection.rb b/app/models/headshot_collection.rb
index 6a5c94f..34afdcf 100644
--- a/app/models/headshot_collection.rb
+++ b/app/models/headshot_collection.rb
@@ -5,7 +5,7 @@ class HeadshotCollection
def self.for_project(project)
appearance_releases_with_photo = project.appearance_releases.with_person_photo
- new(project.id, appearance_releases_with_photo + project.talent_releases)
+ new(project.headshot_collection_uid, appearance_releases_with_photo + project.talent_releases)
end
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
diff --git a/app/models/matching_request.rb b/app/models/matching_request.rb
new file mode 100644
index 0000000..c719d57
--- /dev/null
+++ b/app/models/matching_request.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class MatchingRequest < ApplicationRecord
+ include Attachable
+
+ belongs_to :project
+end
diff --git a/app/models/medical_release.rb b/app/models/medical_release.rb
new file mode 100644
index 0000000..62f08b9
--- /dev/null
+++ b/app/models/medical_release.rb
@@ -0,0 +1,79 @@
+class MedicalRelease < ApplicationRecord
+ include Contractable
+ include Notable
+ include Photoable
+ include Releasable
+ include Searchable
+ include Signable
+ include Syncable
+ include PersonName
+ include GuardianPhotoable
+ include SecondGuardianPhotoable
+ include GuardianName
+ include SecondGuardianName
+
+ NUMBER_OF_CUSTOM_FIELDS = 15
+
+ 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 being signed by a minor
+ with_options if: :minor? do
+ validates :guardian_email, email: true, allow_blank: true
+ validates :guardian_2_email, email: true, allow_blank: true
+ end
+
+ # 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 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
diff --git a/app/models/misc_release.rb b/app/models/misc_release.rb
new file mode 100644
index 0000000..54887d3
--- /dev/null
+++ b/app/models/misc_release.rb
@@ -0,0 +1,86 @@
+class MiscRelease < ApplicationRecord
+ include Contractable
+ include Notable
+ include Photoable
+ include Releasable
+ include Searchable
+ include Signable
+ include Syncable
+ include PersonName
+ include GuardianName
+ include GuardianPhotoable
+
+ 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)
+ ]
+
+ composed_of :guardian_address,
+ class_name: "Address",
+ mapping: [
+ %w(guardian_address_street1 street1),
+ %w(guardian_address_street2 street2),
+ %w(guardian_address_city city),
+ %w(guardian_address_state state),
+ %w(guardian_address_zip zip),
+ %w(guardian_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
+
+ with_options if: :minor? do
+ validates :guardian_first_name, :guardian_last_name, presence: true
+ validates :guardian_phone, presence: 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
+ guardian_address_street1 guardian_address_street2 guardian_address_city guardian_address_state guardian_address_zip guardian_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 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
diff --git a/app/models/note.rb b/app/models/note.rb
index 927c2a9..062b329 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -4,6 +4,4 @@ class Note < ApplicationRecord
belongs_to :notable, polymorphic: true
validates :content, presence: true
-
- scope :order_by_recent, -> { order(created_at: :desc) }
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 1d9e43e..b720b32 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -3,8 +3,8 @@ class Project < ApplicationRecord
include Filterable
include Syncable
- SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material)
- AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music)
+ SIGNABLE_RELEASE_TYPES = %w(talent appearance acquired_media location material medical misc)
+ AVAILABLE_RELEASE_TYPES = %w(appearance location material acquired_media talent music medical misc)
belongs_to :account
has_many :acquired_media_releases, dependent: :destroy
@@ -13,6 +13,8 @@ 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 :misc_releases, dependent: :destroy
has_many :videos, dependent: :destroy
has_many :imports, dependent: :destroy
has_many :contract_templates, dependent: :destroy
@@ -34,6 +36,8 @@ class Project < ApplicationRecord
material_release: false,
music_release: false,
talent_release: false,
+ medical_release: false,
+ misc_release: false,
video_analysis: false,
}
end
@@ -66,6 +70,8 @@ class Project < ApplicationRecord
material_release: true,
music_release: true,
talent_release: true,
+ medical_release: true,
+ misc_release: true,
video_analysis: true,
}
when "nat_geo"
@@ -77,6 +83,8 @@ class Project < ApplicationRecord
material_release: true,
music_release: true,
talent_release: true,
+ medical_release: true,
+ misc_release: true,
video_analysis: true,
}
else
@@ -118,7 +126,7 @@ class Project < ApplicationRecord
current_zoom_meeting = zoom_meetings.active.first
unless current_zoom_meeting.present?
- zoom_user = ZoomUser.free.first || ZoomUser.create
+ zoom_user = ZoomUser.for_new_meeting
current_zoom_meeting = ZoomMeeting.create(zoom_user: zoom_user, project: self)
end
diff --git a/app/models/qr_code.rb b/app/models/qr_code.rb
index 637fc6c..a38e0df 100644
--- a/app/models/qr_code.rb
+++ b/app/models/qr_code.rb
@@ -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
diff --git a/app/models/releasable_param.rb b/app/models/releasable_param.rb
index a8cff38..4c2b7c9 100644
--- a/app/models/releasable_param.rb
+++ b/app/models/releasable_param.rb
@@ -1,5 +1,5 @@
class ReleasableParam
- TYPES = %w(talent appearance location material acquired_media music)
+ TYPES = %w(talent appearance location material acquired_media music medical misc)
def initialize(params)
@params = params
diff --git a/app/models/sample_appearance_release.rb b/app/models/sample_appearance_release.rb
index e2e0a20..c1d7170 100644
--- a/app/models/sample_appearance_release.rb
+++ b/app/models/sample_appearance_release.rb
@@ -8,7 +8,12 @@ class SampleAppearanceRelease < AppearanceRelease
def default_attrs
{
- person_address: "Street Address, City, State Zipcode",
+ 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_first_name: "Some",
person_last_name: "Person",
person_phone: "555-555-5555",
diff --git a/app/models/talent_release.rb b/app/models/talent_release.rb
index 830c56f..8ca4dbe 100644
--- a/app/models/talent_release.rb
+++ b/app/models/talent_release.rb
@@ -11,7 +11,9 @@ class TalentRelease < ApplicationRecord
include Taggable
include PersonName
include GuardianPhotoable
+ include SecondGuardianPhotoable
include GuardianName
+ include SecondGuardianName
composed_of :person_address,
class_name: "Address",
@@ -35,6 +37,17 @@ class TalentRelease < ApplicationRecord
%w(guardian_address_country country)
]
+ composed_of :guardian_2_address,
+ class_name: "Address",
+ mapping: [
+ %w(guardian_2_address_street1 street1),
+ %w(guardian_2_address_street2 street2),
+ %w(guardian_2_address_city city),
+ %w(guardian_2_address_state state),
+ %w(guardian_2_address_zip zip),
+ %w(guardian_2_address_country country)
+ ]
+
def self.face_photo_acceptable_content_types
["image/png", "image/jpeg"]
end
@@ -58,6 +71,7 @@ class TalentRelease < 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, :guardian_2_email, email: true, allow_blank: true
validates :guardian_phone, presence: true
end
@@ -84,6 +98,10 @@ class TalentRelease < ApplicationRecord
false
end
+ def second_guardian_present?
+ guardian_2_first_name.present?
+ 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
diff --git a/app/models/zoom_meeting.rb b/app/models/zoom_meeting.rb
index deb3730..13e1e45 100644
--- a/app/models/zoom_meeting.rb
+++ b/app/models/zoom_meeting.rb
@@ -1,9 +1,10 @@
-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? }
diff --git a/app/models/zoom_user.rb b/app/models/zoom_user.rb
index 823d6e9..95ca0eb 100644
--- a/app/models/zoom_user.rb
+++ b/app/models/zoom_user.rb
@@ -1,18 +1,27 @@
+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
- self.api_id = gateway.create_host(api_email)
+ retries ||= 0
+ self.api_id = gateway.create_host(self.class.generate_api_email)
+ self.account_number = ZoomGateway.ACCOUNT_NUMBER
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
@@ -21,9 +30,22 @@ class ZoomUser < ApplicationRecord
save
end
+ def current_account?
+ account_number == ZoomGateway.ACCOUNT_NUMBER
+ end
+
+ # Static methods
class << self
- def api_email(id)
- "host#{id}@directme"
+ 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
end
end
diff --git a/app/policies/acquired_media_release_policy.rb b/app/policies/acquired_media_release_policy.rb
index e947756..f2e5108 100644
--- a/app/policies/acquired_media_release_policy.rb
+++ b/app/policies/acquired_media_release_policy.rb
@@ -12,7 +12,7 @@ class AcquiredMediaReleasePolicy < ApplicationPolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def tag_multiple?
diff --git a/app/policies/appearance_release_policy.rb b/app/policies/appearance_release_policy.rb
index 1cec72f..b49287b 100644
--- a/app/policies/appearance_release_policy.rb
+++ b/app/policies/appearance_release_policy.rb
@@ -16,7 +16,7 @@ class AppearanceReleasePolicy < ReleasePolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def tag_multiple?
diff --git a/app/policies/contract_policy.rb b/app/policies/contract_policy.rb
index c6a9b9e..f904cc5 100644
--- a/app/policies/contract_policy.rb
+++ b/app/policies/contract_policy.rb
@@ -1,5 +1,9 @@
class ContractPolicy < ApplicationPolicy
def show?
- user.manager? || user.account_manager?
+ if record.respond_to?(:medical_release?) && record.medical_release?
+ user.account_manager?
+ else
+ user.manager? || user.account_manager?
+ end
end
end
diff --git a/app/policies/contract_template_policy.rb b/app/policies/contract_template_policy.rb
index 5c05abf..e6bb8d1 100644
--- a/app/policies/contract_template_policy.rb
+++ b/app/policies/contract_template_policy.rb
@@ -3,10 +3,8 @@ class ContractTemplatePolicy < ApplicationPolicy
def resolve
if user.account_manager?
scope.left_outer_joins(:project).where(projects: {account: user.account})
- elsif user.manager?
- scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
else
- scope.none
+ scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
end
end
end
@@ -14,8 +12,9 @@ class ContractTemplatePolicy < ApplicationPolicy
def create?
user.manager? || user.account_manager?
end
+
def show?
- create?
+ true
end
def destroy?
diff --git a/app/policies/location_release_policy.rb b/app/policies/location_release_policy.rb
index e372806..66e2114 100644
--- a/app/policies/location_release_policy.rb
+++ b/app/policies/location_release_policy.rb
@@ -16,7 +16,7 @@ class LocationReleasePolicy < ReleasePolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def edit_photos?
diff --git a/app/policies/material_release_policy.rb b/app/policies/material_release_policy.rb
index 6934bb1..4c834f7 100644
--- a/app/policies/material_release_policy.rb
+++ b/app/policies/material_release_policy.rb
@@ -16,7 +16,7 @@ class MaterialReleasePolicy < ReleasePolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def edit_photos?
diff --git a/app/policies/medical_release_policy.rb b/app/policies/medical_release_policy.rb
new file mode 100644
index 0000000..8866337
--- /dev/null
+++ b/app/policies/medical_release_policy.rb
@@ -0,0 +1,41 @@
+class MedicalReleasePolicy < ReleasePolicy
+ def create?
+ true
+ end
+
+ def show?
+ true
+ end
+
+ def update?
+ !record.native?
+ end
+
+ def destroy?
+ user.manager? || user.account_manager?
+ end
+
+ def edit_photos?
+ true
+ end
+
+ def index?
+ true
+ end
+
+ def update_photos?
+ edit_photos?
+ end
+
+ def tag_multiple?
+ true
+ end
+
+ def download_single?
+ user.account_manager?
+ end
+
+ def download_multiple?
+ download_single?
+ end
+end
diff --git a/app/policies/misc_release_policy.rb b/app/policies/misc_release_policy.rb
new file mode 100644
index 0000000..06bae3b
--- /dev/null
+++ b/app/policies/misc_release_policy.rb
@@ -0,0 +1,41 @@
+class MiscReleasePolicy < ReleasePolicy
+ def create?
+ true
+ end
+
+ def show?
+ true
+ end
+
+ def update?
+ !record.native?
+ end
+
+ def destroy?
+ user.manager? || user.account_manager?
+ end
+
+ def edit_photos?
+ true
+ end
+
+ def index?
+ true
+ end
+
+ def update_photos?
+ edit_photos?
+ end
+
+ def tag_multiple?
+ true
+ end
+
+ def download_single?
+ true
+ end
+
+ def download_multiple?
+ download_single?
+ end
+end
diff --git a/app/policies/music_release_policy.rb b/app/policies/music_release_policy.rb
index 89ce948..14d0224 100644
--- a/app/policies/music_release_policy.rb
+++ b/app/policies/music_release_policy.rb
@@ -12,7 +12,7 @@ class MusicReleasePolicy < ReleasePolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def tag_multiple?
diff --git a/app/policies/talent_release_policy.rb b/app/policies/talent_release_policy.rb
index 2cfe659..5d3a308 100644
--- a/app/policies/talent_release_policy.rb
+++ b/app/policies/talent_release_policy.rb
@@ -12,7 +12,7 @@ class TalentReleasePolicy < ReleasePolicy
end
def destroy?
- true
+ user.manager? || user.account_manager?
end
def edit_photos?
diff --git a/app/views/acquired_media_releases/_form.html.erb b/app/views/acquired_media_releases/_form.html.erb
index 049c736..4f54715 100644
--- a/app/views/acquired_media_releases/_form.html.erb
+++ b/app/views/acquired_media_releases/_form.html.erb
@@ -4,7 +4,7 @@
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
- <%= form.form_group :categories, label: { text: "Categories" } do %>
+ <%= form.form_group :categories, label: { text: "Licensed property type" } do %>
<% AcquiredMediaRelease::CATEGORIES.each do |category| %>
<%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %>
diff --git a/app/views/appearance_releases/_appearance_release.html.erb b/app/views/appearance_releases/_appearance_release.html.erb
index b73f3b7..9779356 100644
--- a/app/views/appearance_releases/_appearance_release.html.erb
+++ b/app/views/appearance_releases/_appearance_release.html.erb
@@ -2,7 +2,7 @@
<%= check_box_tag "appearance_release_ids[]", appearance_release.id, false %> |
<% if appearance_release.photo.attached? %>
- <%= image_tag medium_variant(appearance_release.photo), class: "img-fluid" %>
+ <%= image_tag medium_variant(appearance_release.photo) %>
<% else %>
<%= fa_icon("warning", text: t(".no_photos"), class: "text-danger") %>
<% end %>
@@ -11,10 +11,11 @@
<%= appearance_release.name %>
|
- <%= number_to_phone appearance_release.person_phone %>
- |
-
- <%= mail_to appearance_release.person_email %>
+ <%= contact_info(
+ address: appearance_release.person_address,
+ phone: appearance_release.person_phone,
+ email: appearance_release.person_email
+ ) %>
|
<%= notes_preview appearance_release.notes.order_by_recent %>
diff --git a/app/views/appearance_releases/_form.html.erb b/app/views/appearance_releases/_form.html.erb
index fd392a8..3e9e915 100644
--- a/app/views/appearance_releases/_form.html.erb
+++ b/app/views/appearance_releases/_form.html.erb
@@ -13,18 +13,29 @@
<%= 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" %>
+ <%= form.text_field :person_address_street1, wrapper_class: "col-sm-6" %>
!appearance_release.minor?) %>" data-ujs-target="guardian-fields">
-
- <%= form.text_field :guardian_first_name, required: appearance_release.minor?, wrapper_class: "col-sm-3" %>
- <%= 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" %>
-
-
- <%= form.text_field :guardian_address, wrapper_class: "col-sm-6" %>
-
+ <%= card_field_set_tag t(".guardian_info.heading") do %>
+
+ <%= form.text_field :guardian_first_name, required: appearance_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= 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" %>
+ <%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_address_street1, wrapper_class: "col-sm-6" %>
+
+ <% end %>
+
+ <%= card_field_set_tag t(".guardian_2_info.heading") do %>
+
+ <%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_2_address_street1, wrapper_class: "col-sm-6" %>
+
+ <% end %>
<% end %>
@@ -52,27 +63,43 @@
<% end %>
<%= form.hidden_field :person_photo, value: form.object.person_photo.signed_id if appearance_release.person_photo.attached?%>
- <%= form.file_field :person_photo, wrapper_class: "required", hide_label: true, required: !appearance_release.person_photo.attached?, data: { ujs_target: "person-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %>
+ <%= form.file_field :person_photo, hide_label: true, data: { ujs_target: "person-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %>
!appearance_release.minor?) %>" data-ujs-target="guardian-fields">
<%= t(".photos.guardian_photo.heading") %>
-
+
<% if appearance_release.guardian_photo.attached? %>
<%= javascript_tag nonce: true do %>
- App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(appearance_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ App.PhotoPreview.set("#guardian-photo-preview", "<%= url_for(appearance_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if appearance_release.guardian_photo.attached?%>
<%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %>
+
+ <%= t(".photos.guardian_2_photo.heading") %>
+
+ <% if appearance_release.guardian_2_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("#guardian-2-photo-preview", "<%= url_for(appearance_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if appearance_release.guardian_2_photo.attached?%>
+ <%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, help: "PNG or JPG only", accept: appearance_release.class.face_photo_acceptable_content_types.join(",") %>
+
<% end %>
diff --git a/app/views/appearance_releases/index.html.erb b/app/views/appearance_releases/index.html.erb
index 5515977..f496ca2 100644
--- a/app/views/appearance_releases/index.html.erb
+++ b/app/views/appearance_releases/index.html.erb
@@ -46,8 +46,7 @@
<%= check_box_tag "appearance_release_ids[]", false, false %> |
|
<%= AppearanceRelease.human_attribute_name(:person_name) %> |
- <%= AppearanceRelease.human_attribute_name(:person_phone) %> |
- <%= AppearanceRelease.human_attribute_name(:person_email) %> |
+ <%= AppearanceRelease.human_attribute_name(:contact_info) %> |
<%= t(".table_headers.notes") %> |
<%= t(".table_headers.tags") %> |
<%= t(".table_headers.signed_at") %> |
diff --git a/app/views/blank_contracts/pdf.html.erb b/app/views/blank_contracts/pdf.html.erb
index e70dbc3..87cc5f1 100644
--- a/app/views/blank_contracts/pdf.html.erb
+++ b/app/views/blank_contracts/pdf.html.erb
@@ -2,6 +2,10 @@
<% has_logo = local_assigns[:logo] %>
+
+ | |
+ <%= t '.do_not_copy_warning' %> |
+
|
<% if has_logo %>
@@ -11,17 +15,9 @@
<% end %>
|
-
+
|
-
- | |
- <%= serial_numbers[copy_index] %> |
-
-
- | |
- <%= t '.do_not_copy_warning' %> |
-
<% if contract_template.body.present? %>
diff --git a/app/views/broadcasts/_file.html.erb b/app/views/broadcasts/_file.html.erb
index ede860f..b0c90a8 100644
--- a/app/views/broadcasts/_file.html.erb
+++ b/app/views/broadcasts/_file.html.erb
@@ -1,4 +1,4 @@
-
+
<% 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 %>
diff --git a/app/views/broadcasts/_file_form.html.erb b/app/views/broadcasts/_file_form.html.erb
index 21a333d..7ab4f5b 100644
--- a/app/views/broadcasts/_file_form.html.erb
+++ b/app/views/broadcasts/_file_form.html.erb
@@ -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" %>
+ <%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, required: true, wrapper_class: "w-65 mr-2", id: "broadcast_files_#{token}" %>
<%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %>
<% end %>
diff --git a/app/views/broadcasts/_files_section.html.erb b/app/views/broadcasts/_files_section.html.erb
new file mode 100644
index 0000000..86865c8
--- /dev/null
+++ b/app/views/broadcasts/_files_section.html.erb
@@ -0,0 +1,21 @@
+
+ <% 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 %>
+
+
+
+ <% if files.present? %>
+ <%= render partial: "broadcasts/file", collection: files %>
+ <% else %>
+ -
+ Files will appear here.
+
+ <% end %>
+
+
+
diff --git a/app/views/broadcasts/show.html.erb b/app/views/broadcasts/show.html.erb
index c136236..4d6e507 100644
--- a/app/views/broadcasts/show.html.erb
+++ b/app/views/broadcasts/show.html.erb
@@ -3,7 +3,13 @@
<% end %>
<% if @broadcast %>
-
+
+ <% 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 %>
+
+ <% end %>
<% end %>
<% end %>
@@ -24,12 +30,10 @@
<%= @broadcast.name %>
-
+ <%= link_to "Switch View", "#", class: "btn btn-light border dropdown-toggle", role: "button", id: "dropdownMenuLink", data: { toggle: "dropdown" }, aria: { haspopup: "true", expanded: "false" } %>
- params[:active_tab] == 'files') %>" id="files">
-
- <% 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 %>
-
- <%= fa_icon("warning", text: "You may need to refresh the page to see new files uploaded by other team members") %>
-
-
- <% if @files.present? %>
- <%= render partial: "broadcasts/file", collection: @files %>
- <% else %>
- -
- Files will appear here.
-
- <% end %>
-
-
-
-
params[:active_tab] == 'recordings') %>" id="recordings">
<%= render partial: 'broadcasts/broadcast_recordings', locals: { recordings: @recordings, broadcast: @broadcast } %>
@@ -150,5 +127,36 @@
+
+
+
+
+
+
+ <% if @multi_view_broadcasts.present? %>
+ <% @multi_view_broadcasts.each_with_index do |mvb, index| %>
+ (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 } %>
+
+ <% end %>
+ <% else %>
+
+ <%= render partial: 'broadcasts/files_section', locals: { broadcast: @broadcast, files: @files } %>
+
+ <% end %>
+
+
+
-
+
diff --git a/app/views/broadcasts/update.js.erb b/app/views/broadcasts/update.js.erb
index 8345207..a46716a 100644
--- a/app/views/broadcasts/update.js.erb
+++ b/app/views/broadcasts/update.js.erb
@@ -1,5 +1,9 @@
-$("#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) %>");
+$("#broadcast_file_form_<%= @broadcast.token %>").html("<%= j render(partial: "broadcasts/file_form", locals: { model: [@project, @broadcast], token: @broadcast.token }) %>");
-bsCustomFileInput.init();
\ No newline at end of file
+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();
diff --git a/app/views/contract_templates/_form.html.erb b/app/views/contract_templates/_form.html.erb
index 0917df1..821fddf 100644
--- a/app/views/contract_templates/_form.html.erb
+++ b/app/views/contract_templates/_form.html.erb
@@ -2,21 +2,20 @@
<%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %>
<%= 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 misc medical), "#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" %>
-
<% end %>
+ <%= field_set_tag content_tag(:span, t(".custom_fields.heading"), class: "h6 text-muted text-uppercase"), id: "custom_fields", style: "display: none;" do %>
+ <%= fa_icon("info-circle", text: t(".custom_fields.instructions")) %>
+ <%= render "shared/custom_fields", form: form %>
+
+ <% end %>
+
<%= link_to t("shared.cancel"), [project, :contract_templates], class: "col-3 text-reset" %>
diff --git a/app/views/contracts/_medical_questionnaire.html.erb b/app/views/contracts/_medical_questionnaire.html.erb
new file mode 100644
index 0000000..e6e20c8
--- /dev/null
+++ b/app/views/contracts/_medical_questionnaire.html.erb
@@ -0,0 +1,8 @@
+ <%= t ".heading" %>
+
+<% (1..MedicalRelease::NUMBER_OF_CUSTOM_FIELDS).each do |n| %>
+ <% if contract_template.public_send("question_#{n}_text").present? %>
+ <%= contract_template.public_send("question_#{n}_text") %>
+ <%= releasable.public_send("question_#{n}_answer") %>
+ <% end %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/contracts/_photos.html.erb b/app/views/contracts/_photos.html.erb
index 6f429f7..242881c 100644
--- a/app/views/contracts/_photos.html.erb
+++ b/app/views/contracts/_photos.html.erb
@@ -5,6 +5,9 @@
<% if release.respond_to? :guardian_photo %>
<% @total_photos_count += release.guardian_photo.attached? ? 1 : 0 %>
<% end %>
+<% if release.respond_to? :guardian_2_photo %>
+ <% @total_photos_count += release.guardian_2_photo.attached? ? 1 : 0 %>
+<% end %>
<%= t '.heading', count: @total_photos_count %>
diff --git a/app/views/contracts/_signature_page.html.erb b/app/views/contracts/_signature_page.html.erb
index e6ad5d6..1f6265b 100644
--- a/app/views/contracts/_signature_page.html.erb
+++ b/app/views/contracts/_signature_page.html.erb
@@ -29,6 +29,7 @@
<% 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) %>
@@ -55,7 +56,23 @@
<%= 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: ":" %>
+ <% if releasable.respond_to?(:second_guardian_present?) && releasable.second_guardian_present? %>
+
+
+ Second guardian Information
+
+ <% # Second guardian information %>
+
+ <%= description_list_pair_for releasable, :guardian_2_name, append: ":" %>
+ <%= description_list_pair_for releasable, :guardian_2_address, append: ":" %>
+ <%= description_list_pair_for releasable, :guardian_2_phone, append: ":" %>
+ <%= description_list_pair_for releasable, :guardian_2_email, append: ":" %>
+
+
+ <% end %>
+
<% end %>
diff --git a/app/views/contracts/pdf.html.erb b/app/views/contracts/pdf.html.erb
index b38fde7..142d51e 100644
--- a/app/views/contracts/pdf.html.erb
+++ b/app/views/contracts/pdf.html.erb
@@ -15,6 +15,13 @@
Guardian Clause
<%= contract_template.guardian_clause %>
<% end %>
+
+<% if releasable.model_name == "MedicalRelease" %>
+
+ <%= render "contracts/medical_questionnaire", releasable: releasable, contract_template: contract_template, preview: preview %>
+
+<% end %>
+
<%= render "contracts/signature_page", releasable: releasable, contract_template: contract_template, preview: preview %>
diff --git a/app/views/location_releases/_form.html.erb b/app/views/location_releases/_form.html.erb
index 33aeb45..a0d1290 100644
--- a/app/views/location_releases/_form.html.erb
+++ b/app/views/location_releases/_form.html.erb
@@ -11,14 +11,10 @@
<%= field_set_tag content_tag(:span, t(".signer_details.heading"), class: "h6 text-muted text-uppercase") do %>
- <%= form.text_field :person_first_name, wrapper_class: "col-sm-3" %>
- <%= form.text_field :person_last_name, wrapper_class: "col-sm-3" %>
+ <%= 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" %>
-
-
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
-
-
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
@@ -38,6 +34,7 @@
<%= 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" %>
<% end %>
diff --git a/app/views/material_releases/_form.html.erb b/app/views/material_releases/_form.html.erb
index 8a336ca..2256596 100644
--- a/app/views/material_releases/_form.html.erb
+++ b/app/views/material_releases/_form.html.erb
@@ -13,14 +13,10 @@
<%= field_set_tag content_tag(:span, t(".signer_details.heading"), class: "h6 text-muted text-uppercase") do %>
- <%= form.text_field :person_first_name, wrapper_class: "col-sm-3" %>
- <%= form.text_field :person_last_name, wrapper_class: "col-sm-3" %>
+ <%= 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" %>
-
-
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
-
-
<%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
<%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
diff --git a/app/views/medical_releases/_medical_release.html.erb b/app/views/medical_releases/_medical_release.html.erb
new file mode 100644
index 0000000..29c4b73
--- /dev/null
+++ b/app/views/medical_releases/_medical_release.html.erb
@@ -0,0 +1,49 @@
+
+ | <%= check_box_tag "medical_release_ids[]", medical_release.id, false %> |
+
+ <% if medical_release.photo.attached? %>
+ <%= image_tag medium_variant(medical_release.photo), class: "img-fluid" %>
+ <% end %>
+ |
+
+ <%= medical_release.name %>
+ |
+
+ <%= contact_info(
+ address: medical_release.person_address,
+ phone: medical_release.person_phone,
+ email: medical_release.person_email
+ ) %>
+ |
+
+ <%= notes_preview medical_release.notes.order_by_recent %>
+ |
+ ">
+ <%= tags_preview medical_release, medical_release.tags %>
+ |
+
+
+ <%= medical_release.signed_on %>
+ |
+
+
+
+
+ <%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
+
+
+ |
+
diff --git a/app/views/medical_releases/index.html.erb b/app/views/medical_releases/index.html.erb
new file mode 100644
index 0000000..e056d0f
--- /dev/null
+++ b/app/views/medical_releases/index.html.erb
@@ -0,0 +1,48 @@
+
+
+
+ <% 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 %>
+
+
+
+
+
+
+
+
+ | <%= check_box_tag "medical_release_ids[]", false, false %> |
+ |
+ <%= MedicalRelease.human_attribute_name(:person_name) %> |
+ <%= MedicalRelease.human_attribute_name(:contact_info) %> |
+ <%= t(".table_headers.notes") %> |
+ <%= t(".table_headers.tags") %> |
+ <%= t(".table_headers.signed_at") %> |
+ |
+
+
+
+ <% if @medical_releases.any? %>
+ <%= render @medical_releases %>
+ <% else %>
+
+ | <%= t(".empty") %> |
+
+ <% end %>
+
+
+
+
+
diff --git a/app/views/medical_releases/index.js.erb b/app/views/medical_releases/index.js.erb
new file mode 100644
index 0000000..e720a01
--- /dev/null
+++ b/app/views/medical_releases/index.js.erb
@@ -0,0 +1,3 @@
+$("#medical_releases").html("<%= j render(@medical_releases) %>");
+$("form input[type='search']").val("<%= params[:query] %>");
+$("#medical_releases_pagination").html("<%= j will_paginate(@medical_releases) %>");
diff --git a/app/views/misc_releases/_misc_release.html.erb b/app/views/misc_releases/_misc_release.html.erb
new file mode 100644
index 0000000..ae53b18
--- /dev/null
+++ b/app/views/misc_releases/_misc_release.html.erb
@@ -0,0 +1,48 @@
+
+ | <%= check_box_tag "misc_release_ids[]", misc_release.id, false %> |
+
+ <% if misc_release.photo.attached? %>
+ <%= image_tag medium_variant(misc_release.photo), class: "img-fluid" %>
+ <% end %>
+ |
+
+ <%= misc_release.name %>
+ |
+
+ <%= contact_info(
+ address: misc_release.person_address,
+ phone: misc_release.person_phone,
+ email: misc_release.person_email
+ ) %>
+ |
+
+ <%= notes_preview misc_release.notes.order_by_recent %>
+ |
+ ">
+ <%= tags_preview misc_release, misc_release.tags %>
+ |
+
+
+ <%= misc_release.signed_on %>
+ |
+
+
+
+ <%= button_tag t(".actions.manage"), class: "btn btn-light btn-sm dropdown-toggle border", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false } %>
+
+
+ |
+
diff --git a/app/views/misc_releases/index.html.erb b/app/views/misc_releases/index.html.erb
new file mode 100644
index 0000000..0217277
--- /dev/null
+++ b/app/views/misc_releases/index.html.erb
@@ -0,0 +1,48 @@
+
+
+
+ <% if @misc_releases.any? && policy(MiscRelease).tag_multiple? %>
+ <%= button_to_bulk_tagging(@project) %>
+ <% end %>
+
+ <% if @misc_releases.any? && policy(MiscRelease).download_multiple? %>
+ <%= link_to "Download All", [@project, :contract_downloads, release_type: @misc_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, :misc_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 %>
+
+
+
+
+
+
+
+
+ | <%= check_box_tag "misc_release_ids[]", false, false %> |
+ |
+ <%= MiscRelease.human_attribute_name(:person_name) %> |
+ <%= MiscRelease.human_attribute_name(:contact_info) %> |
+ <%= t(".table_headers.notes") %> |
+ <%= t(".table_headers.tags") %> |
+ <%= t(".table_headers.signed_at") %> |
+ |
+
+
+
+ <% if @misc_releases.any? %>
+ <%= render @misc_releases %>
+ <% else %>
+
+ | <%= t(".empty") %> |
+
+ <% end %>
+
+
+
+
+
diff --git a/app/views/misc_releases/index.js.erb b/app/views/misc_releases/index.js.erb
new file mode 100644
index 0000000..24f3ccf
--- /dev/null
+++ b/app/views/misc_releases/index.js.erb
@@ -0,0 +1,3 @@
+$("#misc_releases").html("<%= j render(@misc_releases) %>");
+$("form input[type='search']").val("<%= params[:query] %>");
+$("#misc_releases_pagination").html("<%= j will_paginate(@misc_releases) %>");
diff --git a/app/views/projects/_form.html.erb b/app/views/projects/_form.html.erb
index a8a91d7..677a545 100644
--- a/app/views/projects/_form.html.erb
+++ b/app/views/projects/_form.html.erb
@@ -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" %>
<%= form.text_field :client_name, placeholder: true %>
<%= form.form_group do %>
diff --git a/app/views/public/acquired_media_releases/new.html.erb b/app/views/public/acquired_media_releases/new.html.erb
index 2380db0..0f034f1 100644
--- a/app/views/public/acquired_media_releases/new.html.erb
+++ b/app/views/public/acquired_media_releases/new.html.erb
@@ -15,12 +15,12 @@
<%= card_field_set_tag t(".acquired_media_info.heading") do %>
- <%= form.text_field :name, required: true, wrapper_class: "col-12", label: 'Licensor ("Owner")' %>
+ <%= form.text_field :name, required: true, wrapper_class: "col-12" %>
- <%= form.text_area :description, wrapper_class: "col-12" %>
+ <%= form.text_area :description, required: true, wrapper_class: "col-12" %>
- <%= form.form_group :categories, label: { text: "Categories" } do %>
+ <%= form.form_group :categories, label: { text: "Licensed property type" } do %>
<% AcquiredMediaRelease::CATEGORIES.each do |category| %>
<%= form.check_box :categories, { multiple: true, label: category }, category, false %>
<% end %>
@@ -31,20 +31,19 @@
<%= card_field_set_tag t(".personal_info.heading") do %>
- <%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
- <%= form.text_field :person_phone, wrapper_class: "col-sm-6", label: 'Phone' %>
- <%= form.text_field :person_fax, wrapper_class: "col-sm-6", label: 'Fax' %>
+ <%= 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.text_field :person_title, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.phone_field :person_phone, required: true, wrapper_class: "col-sm-6", label: 'Phone' %>
+ <%= form.email_field :person_email, required: true, wrapper_class: "col-sm-6", label: 'Email' %>
+ <%= form.text_field :person_fax, required: true, wrapper_class: "col-sm-6", label: 'Fax' %>
- <%= render "shared/address_fields", form: form, subject: "person" %>
+ <%= render "shared/address_fields", form: form, required: true, subject: "person" %>
<% end %>
<%= card_field_set_tag t(".files.heading") do %>
-
- <%= fa_icon "warning" %>
- For optimal accuracy, please ensure video file names and photo file names match the source file name in the editing sequence.
-
<%= render "shared/file_infos_dropzone", form: form, releasable: @acquired_media_release %>
<% end %>
diff --git a/app/views/public/appearance_releases/new.html.erb b/app/views/public/appearance_releases/new.html.erb
index 9055980..c88d7d6 100644
--- a/app/views/public/appearance_releases/new.html.erb
+++ b/app/views/public/appearance_releases/new.html.erb
@@ -30,13 +30,13 @@
<%= 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.phone_field :person_phone, required: true, wrapper_class: "col-sm-6" %>
- <%= 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" %>
+ <%= form.email_field :person_email, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.date_field :person_date_of_birth, required: true, wrapper_class: "col-sm-6", placeholder: Date.current %>
+ <%= render "shared/address_fields", form: form, subject: "person", required: true %>
<% end %>
<%= card_field_set_tag t(".photo.heading") do %>
@@ -57,7 +57,7 @@
<%= 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" }, accept: @appearance_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
- <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-person-photo" } %>
+ <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=person-photo-input]" } %>
<%= fa_icon "arrow-up", text: t(".photo.camera_instructions_html") %>
@@ -74,11 +74,10 @@
<%= form.text_field :guardian_first_name, required: @appearance_release.minor?, wrapper_class: "col-sm-3" %>
<%= 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" %>
-
-
- <%= form.text_field :guardian_address, wrapper_class: "col-sm-6" %>
+ <%= form.phone_field :guardian_phone, required: @appearance_release.minor?, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_email, required: @appearance_release.minor?, wrapper_class: "col-sm-6" %>
+ <%= render "shared/address_fields", form: form, subject: "guardian", required: @appearance_release.minor? %>
<% end %>
@@ -99,9 +98,50 @@
<% end %>
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if @appearance_release.guardian_photo.attached? %>
- <%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @appearance_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+ <%= form.file_field :guardian_photo, required: @appearance_release.minor?, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @appearance_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
- <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-guardian-photo" } %>
+ <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-photo-input]" } %>
+
+
+ <%= fa_icon "arrow-up", text: t(".photo.camera_instructions_html") %>
+ <%= t ".photo.warning" %>
+
+
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_2_info.heading") do %>
+
+ <%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian_2" %>
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_2_photo.heading") do %>
+ <%= t ".guardian_2_photo.instructions" %>
+
+
+
+ <%= t ".photo.no_photo" %>
+
+
+
+ <% if @appearance_release.guardian_2_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@appearance_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if @appearance_release.guardian_2_photo.attached? %>
+ <%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, accept: @appearance_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+
+ <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-2-photo-input]" } %>
<%= fa_icon "arrow-up", text: t(".photo.camera_instructions_html") %>
diff --git a/app/views/public/broadcasts/_file_form.html.erb b/app/views/public/broadcasts/_file_form.html.erb
index 3935c63..369bbf4 100644
--- a/app/views/public/broadcasts/_file_form.html.erb
+++ b/app/views/public/broadcasts/_file_form.html.erb
@@ -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" %>
+ <%= form.file_field :files, direct_upload: true, multiple: true, accept: "*", hide_label: true, required: true, wrapper_class: "w-65 mr-2", id: "broadcast_files_#{token}" %>
<%= form.button fa_icon("upload", text: "Add File"), class: "btn btn-primary", type: :submit, data: { disable_with: fa_icon("spinner", text: "Adding File") } %>
<% end %>
\ No newline at end of file
diff --git a/app/views/public/broadcasts/update.js.erb b/app/views/public/broadcasts/update.js.erb
index fa75fc2..4e4a2e8 100644
--- a/app/views/public/broadcasts/update.js.erb
+++ b/app/views/public/broadcasts/update.js.erb
@@ -1,5 +1,9 @@
-$("#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) %>");
+$("#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) %>");
+}
bsCustomFileInput.init();
\ No newline at end of file
diff --git a/app/views/public/location_releases/new.html.erb b/app/views/public/location_releases/new.html.erb
index 2e3625e..c688ecc 100644
--- a/app/views/public/location_releases/new.html.erb
+++ b/app/views/public/location_releases/new.html.erb
@@ -17,25 +17,21 @@
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
- <%= render "shared/address_fields", form: form, subject: "" %>
+ <%= render "shared/address_fields", form: form, required: true, subject: "" %>
<% end %>
<%= card_field_set_tag t(".contact_info.heading") do %>
- <%= 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" %>
+ <%= 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, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.email_field :person_email, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :person_company, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :person_title, required: true, wrapper_class: "col-sm-6" %>
-
- <%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
-
-
- <%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
- <%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
-
- <%= render "shared/address_fields", form: form, subject: "person" %>
+ <%= render "shared/address_fields", form: form, required: true, subject: "person" %>
<% end %>
@@ -43,11 +39,16 @@
<%= card_field_set_tag t(".filming_info.heading") do %>
- <%= 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_started_on, required: true, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
+ <%= form.text_field :filming_ended_on, required: true, wrapper_class: "col-sm-6", class: "datepicker-control", readonly: true %>
+ <%= form.text_field :filming_hours, required: true, wrapper_class: "col-sm-12" %>
<% 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 %>
diff --git a/app/views/public/material_releases/new.html.erb b/app/views/public/material_releases/new.html.erb
index 9396ddd..565ac57 100644
--- a/app/views/public/material_releases/new.html.erb
+++ b/app/views/public/material_releases/new.html.erb
@@ -18,24 +18,24 @@
<%= form.text_field :name, required: true, wrapper_class: "col-12" %>
- <%= form.text_area :description, placeholder: true, wrapper_class: "col-sm-12", rows: 6 %>
+ <%= form.text_area :description, required: true, placeholder: true, wrapper_class: "col-sm-12", rows: 6 %>
<% end %>
<%= card_field_set_tag t(".contact_info.heading") do %>
- <%= 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" %>
+ <%= 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, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.email_field :person_email, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :person_company, required: true, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :person_title, required: true, wrapper_class: "col-sm-6" %>
-
- <%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
-
-
- <%= form.text_field :person_company, wrapper_class: "col-sm-6" %>
- <%= form.text_field :person_title, wrapper_class: "col-sm-6" %>
-
- <%= render "shared/address_fields", form: form, subject: "person" %>
+ <%= render "shared/address_fields", form: form, subject: "person", required: true %>
+ <% end %>
+
+ <%= card_field_set_tag t(".photo.heading") do %>
+ <%= render "shared/photos_dropzone_fields", form: form, release: @material_release %>
<% end %>
diff --git a/app/views/public/medical_releases/create.html.erb b/app/views/public/medical_releases/create.html.erb
new file mode 100644
index 0000000..e9384ee
--- /dev/null
+++ b/app/views/public/medical_releases/create.html.erb
@@ -0,0 +1 @@
+ Your release was successfully submitted. Thank you.
diff --git a/app/views/public/medical_releases/new.html.erb b/app/views/public/medical_releases/new.html.erb
new file mode 100644
index 0000000..7f4dd2f
--- /dev/null
+++ b/app/views/public/medical_releases/new.html.erb
@@ -0,0 +1,158 @@
+
+
+ <%= errors_summary_for @medical_release %>
+ <%= bootstrap_form_with model: [@account, @project, @contract_template, @medical_release], local: true, validation_context: :native do |form| %>
+ <%= t ".instructions_html", name: @project.name %>
+ <%= card_field_set_tag t(".legal.heading") do %>
+ <%= @contract_template.body %>
+ <% if @contract_template.fee? %>
+
+ Fee <%= number_to_currency @contract_template.fee %>
+
+ <% end %>
+ <% end %>
+
+
+
+ <% unless @contract_template.guardian_clause.blank? %>
+ <%= form.form_group :minor do %>
+ <%= form.check_box :minor, label: t("helpers.label.medical_release.minor"), data: { target: "[data-ujs-target=guardian-fields]", toggle: "collapse" } %>
+ <% end %>
+
+ <%= card_field_set_tag t(".guardian_clause.heading") do %>
+ <%= @contract_template.guardian_clause %>
+ <% end %>
+
+ <% end %>
+
+ <% if (1..MedicalRelease::NUMBER_OF_CUSTOM_FIELDS).map {|n| @contract_template.public_send("question_#{n}_text").presence }.compact.any? %>
+ <%= card_field_set_tag t(".questionnaire.heading") do %>
+ <% (1..MedicalRelease::NUMBER_OF_CUSTOM_FIELDS).each do |n| %>
+ <% if @contract_template.public_send("question_#{n}_text").present? %>
+
+ <%= form.text_area "question_#{n}_answer", wrapper_class: "col-sm-12", label: @contract_template.public_send("question_#{n}_text") %>
+
+ <% end %>
+ <% end %>
+ <% end %>
+
+ <% end %>
+
+ <%= card_field_set_tag t(".personal_info.heading") do %>
+ <%= t ".personal_info.instructions" %>
+
+ <%= 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" %>
+
+ <%= 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: @medical_release %>
+ <% end %>
+
+ <% unless @contract_template.guardian_clause.blank? %>
+ !@medical_release.minor?) %>" data-ujs-target="guardian-fields">
+ <%= card_field_set_tag t(".guardian_info.heading") do %>
+
+ <%= form.text_field :guardian_first_name, required: @medical_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_last_name, required: @medical_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_phone, required: @medical_release.minor?, wrapper_class: "col-sm-6" %>
+
+
+ <%= form.text_field :guardian_email, required: @medical_release.minor?, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian", required: @medical_release.minor? %>
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_photo.heading") do %>
+ <%= t ".guardian_photo.instructions" %>
+
+
+
+ <%= t ".photo.no_photo" %>
+
+
+
+ <% if @medical_release.guardian_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@medical_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if @medical_release.guardian_photo.attached? %>
+ <%= form.file_field :guardian_photo, required: @medical_release.minor?, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @medical_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+
+ <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-guardian-photo" } %>
+
+
+ <%= fa_icon "arrow-up", text: t(".photo.camera_instructions_html") %>
+ <%= t ".photo.warning" %>
+
+
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_2_info.heading") do %>
+
+ <%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
+
+
+ <%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian_2" %>
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_2_photo.heading") do %>
+ <%= t ".guardian_2_photo.instructions" %>
+
+
+
+ <%= t ".photo.no_photo" %>
+
+
+
+ <% if @medical_release.guardian_2_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@medical_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if @medical_release.guardian_2_photo.attached? %>
+ <%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, accept: @medical_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+
+ <%= button_tag t(".photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-guardian-2-photo" } %>
+
+
+ <%= fa_icon "arrow-up", text: t(".photo.camera_instructions_html") %>
+ <%= t ".photo.warning" %>
+
+
+ <% end %>
+
+
+
+
+ <% end %>
+
+ <%= card_field_set_tag t(".signature.heading") do %>
+ <%= render "shared/signature_fields", form: form %>
+ <% end %>
+
+
+ <%= form.button t("shared.submit_release_short"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/public/misc_releases/create.html.erb b/app/views/public/misc_releases/create.html.erb
new file mode 100644
index 0000000..6eda1cb
--- /dev/null
+++ b/app/views/public/misc_releases/create.html.erb
@@ -0,0 +1 @@
+ Your release was successfully submitted. Thank you.
\ No newline at end of file
diff --git a/app/views/public/misc_releases/new.html.erb b/app/views/public/misc_releases/new.html.erb
new file mode 100644
index 0000000..35672ce
--- /dev/null
+++ b/app/views/public/misc_releases/new.html.erb
@@ -0,0 +1,97 @@
+
+
+ <%= errors_summary_for @misc_release %>
+ <%= bootstrap_form_with model: [@account, @project, @contract_template, @misc_release], local: true, validation_context: :native do |form| %>
+ <%= t ".instructions_html", name: @project.name %>
+ <%= card_field_set_tag t(".legal.heading") do %>
+ <%= @contract_template.body %>
+ <% end %>
+
+
+
+ <% unless @contract_template.guardian_clause.blank? %>
+ <%= form.form_group :minor do %>
+ <%= form.check_box :minor, label: t("helpers.label.appearance_release.minor"), data: { target: "[data-ujs-target=guardian-fields]", toggle: "collapse" } %>
+ <% end %>
+
+ <%= card_field_set_tag t(".guardian_clause.heading") do %>
+ <%= @contract_template.guardian_clause %>
+ <% end %>
+
+ <% end %>
+
+ <%= card_field_set_tag t(".personal_info.heading") do %>
+ <%= t ".personal_info.instructions" %>
+
+ <%= 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" %>
+
+ <%= 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: @misc_release %>
+ <% end %>
+
+ <% unless @contract_template.guardian_clause.blank? %>
+ !@misc_release.minor?) %>" data-ujs-target="guardian-fields">
+ <%= card_field_set_tag t(".guardian_info.heading") do %>
+
+ <%= form.text_field :guardian_first_name, required: @misc_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_last_name, required: @misc_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
+
+
+ <%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian" %>
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_photo.heading") do %>
+ <%= t ".guardian_photo.instructions" %>
+
+
+
+ <%= t ".guardian_photo.no_photo" %>
+
+
+
+ <% if @misc_release.guardian_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@misc_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if @misc_release.guardian_photo.attached? %>
+ <%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @misc_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+
+ <%= button_tag t(".guardian_photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-guardian-photo" } %>
+
+
+ <%= fa_icon "arrow-up", text: t(".guardian_photo.camera_instructions_html") %>
+ <%= t ".guardian_photo.warning" %>
+
+
+ <% end %>
+
+
+ <% end %>
+
+ <%= card_field_set_tag t(".signature.heading") do %>
+ <%= render "shared/signature_fields", form: form %>
+ <% end %>
+
+
+ <%= form.button t("shared.submit_release_long"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
+
+ <% end %>
+
+
diff --git a/app/views/public/talent_releases/new.html.erb b/app/views/public/talent_releases/new.html.erb
index 17c5239..01f4e72 100644
--- a/app/views/public/talent_releases/new.html.erb
+++ b/app/views/public/talent_releases/new.html.erb
@@ -31,8 +31,6 @@
<%= 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" %>
<%= render "shared/address_fields", form: form, subject: "person" %>
@@ -51,8 +49,6 @@
<%= form.text_field :guardian_first_name, required: @talent_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.text_field :guardian_last_name, required: @talent_release.minor?, wrapper_class: "col-sm-3" %>
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
-
-
<%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
<%= render "shared/address_fields", form: form, subject: "guardian" %>
@@ -78,7 +74,7 @@
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if @talent_release.guardian_photo.attached? %>
<%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, accept: @talent_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
- <%= button_tag t(".guardian_photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "take-guardian-photo" } %>
+ <%= button_tag t(".guardian_photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-photo-input]" } %>
<%= fa_icon "arrow-up", text: t(".guardian_photo.camera_instructions_html") %>
@@ -87,6 +83,48 @@
<% end %>
+
+
+ <%= card_field_set_tag t(".guardian_2_info.heading") do %>
+
+ <%= form.text_field :guardian_2_first_name, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_2_last_name, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian_2" %>
+ <% end %>
+
+
+
+ <%= card_field_set_tag t(".guardian_2_photo.heading") do %>
+ <%= t ".guardian_2_photo.instructions" %>
+
+
+
+ <%= t ".guardian_2_photo.no_photo" %>
+
+
+
+ <% if @talent_release.guardian_2_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(@talent_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if @talent_release.guardian_2_photo.attached? %>
+ <%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, accept: @talent_release.class.face_photo_acceptable_content_types.join(","), direct_upload: true %>
+
+ <%= button_tag t(".guardian_2_photo.take_photo"), type: "button", class: "btn btn-lg btn-primary take-photo-button", data: { behavior: "trigger-click", target: "[data-ujs-target=guardian-2-photo-input]" } %>
+
+
+ <%= fa_icon "arrow-up", text: t(".guardian_2_photo.camera_instructions_html") %>
+ <%= t ".guardian_2_photo.warning" %>
+
+
+ <% end %>
+
+
diff --git a/app/views/shared/_address_fields.html.erb b/app/views/shared/_address_fields.html.erb
index 56c08ee..51cda48 100644
--- a/app/views/shared/_address_fields.html.erb
+++ b/app/views/shared/_address_fields.html.erb
@@ -1,16 +1,17 @@
<% field_name_prefix = subject.present? ? "#{subject}_" : "" %>
+<% required = required || false %>
- <%= form.text_field "#{field_name_prefix}address_street1", wrapper_class: "col-sm-6" %>
+ <%= form.text_field "#{field_name_prefix}address_street1", required: required, wrapper_class: "col-sm-6" %>
<%= form.text_field "#{field_name_prefix}address_street2", wrapper_class: "col-sm-6" %>
- <%= form.text_field "#{field_name_prefix}address_city", wrapper_class: "col-sm-6" %>
- <%= form.text_field "#{field_name_prefix}address_state", wrapper_class: "col-sm-3" %>
- <%= form.text_field "#{field_name_prefix}address_zip", wrapper_class: "col-sm-3" %>
+ <%= form.text_field "#{field_name_prefix}address_city", required: required, wrapper_class: "col-sm-6" %>
+ <%= form.text_field "#{field_name_prefix}address_state", required: required, wrapper_class: "col-sm-3" %>
+ <%= form.text_field "#{field_name_prefix}address_zip", required: required, wrapper_class: "col-sm-3" %>
<%= form.form_group "#{field_name_prefix}address_country" do %>
<%= form.label "#{field_name_prefix}address_country" %>
- <%= form.country_select "#{field_name_prefix}address_country", { priority: %w(US CA), prompt: true }, class: "form-control custom-select" %>
+ <%= form.country_select "#{field_name_prefix}address_country", { selected: 'US', priority: %w(US CA), prompt: true }, class: "form-control custom-select" %>
<% end %>
diff --git a/app/views/shared/_custom_fields.html.erb b/app/views/shared/_custom_fields.html.erb
new file mode 100644
index 0000000..bdf2f9b
--- /dev/null
+++ b/app/views/shared/_custom_fields.html.erb
@@ -0,0 +1,5 @@
+<% (1..MedicalRelease::NUMBER_OF_CUSTOM_FIELDS).each do |n| %>
+
+ <%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %>
+
+<% end%>
diff --git a/app/views/talent_releases/_form.html.erb b/app/views/talent_releases/_form.html.erb
index 76fbff9..2c2caa7 100644
--- a/app/views/talent_releases/_form.html.erb
+++ b/app/views/talent_releases/_form.html.erb
@@ -9,22 +9,30 @@
<%= form.text_field :person_first_name, required: true, wrapper_class: "col-sm-3" %>
<%= form.text_field :person_last_name, required: true, wrapper_class: "col-sm-3" %>
<%= form.phone_field :person_phone, wrapper_class: "col-sm-6" %>
-
-
<%= form.email_field :person_email, wrapper_class: "col-sm-6" %>
<%= render "shared/address_fields", form: form, subject: "person" %>
!talent_release.minor?) %>" data-ujs-target="guardian-fields">
-
- <%= form.text_field :guardian_first_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
- <%= form.text_field :guardian_last_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
- <%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
-
-
- <%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
-
- <%= render "shared/address_fields", form: form, subject: "guardian" %>
+ <%= card_field_set_tag t(".guardian_info.heading") do %>
+
+ <%= form.text_field :guardian_first_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_last_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian" %>
+ <% end %>
+
+ <%= card_field_set_tag t(".guardian_2_info.heading") do %>
+
+ <%= form.text_field :guardian_2_first_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.text_field :guardian_2_last_name, required: talent_release.minor?, wrapper_class: "col-sm-3" %>
+ <%= form.phone_field :guardian_2_phone, wrapper_class: "col-sm-6" %>
+ <%= form.text_field :guardian_2_email, wrapper_class: "col-sm-6" %>
+
+ <%= render "shared/address_fields", form: form, subject: "guardian_2" %>
+ <% end %>
<% end %>
@@ -44,20 +52,36 @@
<%= t(".photos.guardian_photo.heading") %>
-
+
<% if talent_release.guardian_photo.attached? %>
<%= javascript_tag nonce: true do %>
- App.PhotoPreview.set("[data-behavior=guardian-photo-preview]", "<%= url_for(talent_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ App.PhotoPreview.set("#guardian-photo-preview", "<%= url_for(talent_release.guardian_photo.variant(auto_orient: true, resize: '200x200')) %>");
<% end %>
<% end %>
<%= form.hidden_field :guardian_photo, value: form.object.guardian_photo.signed_id if talent_release.guardian_photo.attached?%>
<%= form.file_field :guardian_photo, hide_label: true, data: { ujs_target: "guardian-photo-input" }, help: "PNG or JPG only", accept: talent_release.class.face_photo_acceptable_content_types.join(",") %>
+
+ <%= t(".photos.guardian_2_photo.heading") %>
+
+ <% if talent_release.guardian_2_photo.attached? %>
+ <%= javascript_tag nonce: true do %>
+ App.PhotoPreview.set("#guardian-2-photo-preview", "<%= url_for(talent_release.guardian_2_photo.variant(auto_orient: true, resize: '200x200')) %>");
+ <% end %>
+ <% end %>
+
+ <%= form.hidden_field :guardian_2_photo, value: form.object.guardian_2_photo.signed_id if talent_release.guardian_2_photo.attached?%>
+ <%= form.file_field :guardian_2_photo, hide_label: true, data: { ujs_target: "guardian-2-photo-input" }, help: "PNG or JPG only", accept: talent_release.class.face_photo_acceptable_content_types.join(",") %>
+
diff --git a/config/initializers/zoom.rb b/config/initializers/zoom.rb
index a07b9a1..b51101e 100644
--- a/config/initializers/zoom.rb
+++ b/config/initializers/zoom.rb
@@ -1,4 +1,6 @@
require 'zoom'
+require 'zoom_gateway'
+
unless Rails.env.test?
Zoom.configure do |c|
c.api_key = ENV['ZOOM_API_KEY']
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b49020c..cc28c89 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -60,6 +60,10 @@ en:
activerecord:
attributes:
appearance_release:
+ guardian_2_address: Guardian 2 address
+ guardian_2_email: Guardian 2 email
+ guardian_2_name: Guardian 2 name
+ guardian_2_phone: Guardian 2 phone
person_address: Address
person_email: Email
person_name: Name
@@ -119,15 +123,22 @@ 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
form:
contract_and_rights:
heading: 2 of 3 Contract & Exploitable Rights
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires)
+ guardian_info:
+ heading: Guardian Information
person_details:
heading: 1 of 3 Person Details
photos:
+ guardian_2_photo:
+ heading: Second Guardian Photo
guardian_photo:
heading: Guardian Photo
heading: 3 of 3 Photo
@@ -148,6 +159,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
@@ -219,12 +232,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
@@ -237,7 +253,10 @@ en:
new:
heading: New Release Template
contracts:
+ medical_questionnaire:
+ heading: Medical Questionnaire
photos:
+ guardian_2_photo_heading: Second guardian photo
guardian_photo_heading: Guardian photo
heading:
one: Photo
@@ -307,6 +326,9 @@ en:
help:
task_request:
time_allowed: Minimum of 2 hours, no partial hours allowed
+ contract_template:
+ fee: Leave at $0.00 for no-fee
+ guardian_clause: Leave blank if not required for this contract
video:
audio_only_edl_file: If you do not upload an Audio Only EDL, the software will not generate a BiG Music Cue Sheet.
edl_file: Please follow our directions on exporting the All Tracks EDL. Failure to do so could result in inaccurate and incomplete reporting.
@@ -314,6 +336,8 @@ en:
graphics_only_edl_file: If you do not upload a Graphics Only EDL, the software will not generate a Graphics Cue List.
label:
acquired_media_release:
+ description: Description of property
+ name: Name of property
person_address: Address
person_address_city: City
person_address_country: Country
@@ -323,29 +347,62 @@ en:
person_address_zip: Zip code
person_company: Company
person_email: Email address
+ person_first_name: Licensor/Owner first name
+ person_last_name: Licensor/Owner last name
person_name: Name
person_phone: Phone number
person_title: Title
appearance_release:
+ guardian_2_address_city: Guardian 2 city
+ guardian_2_address_country: Guardian 2 country
+ guardian_2_address_state: Guardian 2 state
+ guardian_2_address_street1: Guardian 2 address
+ guardian_2_address_street2: Guardian 2 address (Line 2)
+ guardian_2_address_zip: Guardian 2 zip code
+ guardian_2_email: Guardian 2 email
+ guardian_2_first_name: Guardian 2 first name
+ guardian_2_last_name: Guardian 2 last name
+ guardian_2_phone: Guardian 2 phone
+ guardian_address_city: Guardian city
+ guardian_address_country: Guardian country
+ guardian_address_state: Guardian state
+ guardian_address_street1: Guardian address
+ guardian_address_street2: Guardian address (Line 2)
+ guardian_address_zip: Guardian zip code
minor: Is the person a minor?
- person_address: Address
+ person_address_city: City
+ person_address_country: Country
+ person_address_state: State
+ person_address_street1: Address
+ person_address_street2: Address (Line 2)
+ person_address_zip: Zip code
+ 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:
address_city: City
address_country: Country
address_state: State
- address_street1: Address
+ address_street1: Address of Property
address_street2: Address (Line 2)
address_zip: Zip code
+ filming_ended_on: Filming end date
+ filming_started_on: Filming start date
+ name: Name of property
person_address_city: City
person_address_country: Country
person_address_state: State
person_address_street1: Address
person_address_street2: Address (Line 2)
person_address_zip: Zip code
+ person_first_name: Owner first name
+ person_last_name: Owner last name
material_release:
+ description: Description of licensed material
+ name: Name of licensed material
person_address: Address
person_address_city: City
person_address_country: Country
@@ -355,9 +412,45 @@ en:
person_address_zip: Zip code
person_company: Company
person_email: Email address
+ person_first_name: Licensor/Owner first name
+ person_last_name: Licensor/Owner last name
person_name: Name
person_phone: Phone number
person_title: Title
+ medical_release:
+ guardian_2_address_city: Guardian 2 city
+ guardian_2_address_country: Guardian 2 country
+ guardian_2_address_state: Guardian 2 state
+ guardian_2_address_street1: Guardian 2 address
+ guardian_2_address_street2: Guardian 2 address (Line 2)
+ guardian_2_address_zip: Guardian 2 zip code
+ guardian_2_email: Guardian 2 email
+ guardian_2_first_name: Guardian 2 first name
+ guardian_2_last_name: Guardian 2 last name
+ guardian_2_phone: Guardian 2 phone
+ guardian_address_city: Guardian city
+ guardian_address_country: Guardian country
+ guardian_address_state: Guardian state
+ guardian_address_street1: Guardian address
+ guardian_address_street2: Guardian address (Line 2)
+ guardian_address_zip: Guardian zip code
+ guardian_email: Guardian email
+ guardian_first_name: Guardian first name
+ guardian_last_name: Guardian last name
+ guardian_phone: Guardian phone
+ minor: Is the person a minor?
+ person_address_city: City
+ person_address_country: Country
+ person_address_state: State
+ person_address_street1: Address
+ person_address_street2: Address (Line 2)
+ person_address_zip: Zip code
+ 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
music_release:
person_address: Address
person_address_city: City
@@ -374,6 +467,16 @@ en:
project:
predefined_client_name: Client
talent_release:
+ guardian_2_address_city: Guardian 2 city
+ guardian_2_address_country: Guardian 2 country
+ guardian_2_address_state: Guardian 2 state
+ guardian_2_address_street1: Guardian 2 address
+ guardian_2_address_street2: Guardian 2 address (Line 2)
+ guardian_2_address_zip: Guardian 2 zip code
+ guardian_2_email: Guardian 2 email
+ guardian_2_first_name: Guardian 2 first name
+ guardian_2_last_name: Guardian 2 last name
+ guardian_2_phone: Guardian 2 phone
guardian_address_city: City
guardian_address_country: Guardian country
guardian_address_state: State
@@ -551,9 +654,10 @@ en:
location_details:
heading: 1 of 4 Location Details
photos:
+ dropzone_label: Tap to take a photo of the Property (optional)
heading: 4 of 4 Photos
signer_details:
- heading: 2 of 4 Signer Details
+ heading: 2 of 4 Owner Details
index:
actions:
new: Import Release
@@ -585,9 +689,10 @@ en:
material_details:
heading: 1 of 3 Material Details
photos:
+ dropzone_label: Tap to take a photo of Licensed Material (optional)
heading: 4 of 4 Photos
signer_details:
- heading: 2 of 4 Signer Details
+ heading: 2 of 4 Licensor/Owner Details
index:
actions:
new: Import Release
@@ -605,6 +710,34 @@ en:
heading: Import Material Release (Products / Logos)
update:
notice: The material release has been updated
+ medical_releases:
+ destroy:
+ alert: The medical release has been deleted
+ index:
+ actions:
+ search: Search
+ empty: Medical releases will appear here
+ table_headers:
+ notes: Notes
+ signed_at: Date Signed
+ tags: Tags
+ medical_release:
+ actions:
+ manage: Manage
+ misc_releases:
+ destroy:
+ alert: The misc release has been deleted
+ index:
+ actions:
+ search: Search
+ empty: Misc Releases will appear here
+ table_headers:
+ notes: Notes
+ signed_at: Date Signed
+ tags: Tags
+ misc_release:
+ actions:
+ manage: Manage
music_releases:
create:
notice: The music release has been created
@@ -648,6 +781,7 @@ en:
create:
notice: Check your email for password reset instructions
edit:
+ notice: This password reset URL has expired or is invalid. Try again by clicking "Forgot your password?" below
submit: Save New Password
title: Password Reset
new:
@@ -709,6 +843,8 @@ en:
label: Which release categories do you require for this project?
location_release: Location Releases
material_release: Material Releases (Products / Logos)
+ medical_release: Medical Releases
+ misc_release: Misc Releases
music_release: Music Releases (Original Music)
talent_release: Talent Releases
index:
@@ -735,6 +871,8 @@ en:
downloads: Downloads
location_release: Location Releases (%{count})
material_release: Material Releases (%{count})
+ medical_release: Medical Releases (%{count})
+ misc_release: Misc Releases (%{count})
music_release: Music Releases (%{count})
report: Reports
talent_release: Talent Releases (%{count})
@@ -750,9 +888,7 @@ en:
legal:
heading: Legal
personal_info:
- heading: Person Details
- personal_info:
- heading: Signer's Contact Information
+ heading: Licensor/Owner Contact Information
signature:
heading: Signature
appearance_releases:
@@ -760,6 +896,12 @@ en:
notice: Your release has been signed. Thank you!
new:
cancel: Cancel
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires)
+ guardian_2_photo:
+ heading: Second Guardian Photo
+ instructions: >
+ Lastly, it's time for second 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!
guardian_clause:
heading: Guardian Clause
guardian_info:
@@ -769,35 +911,40 @@ 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 %{name}. 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 %{name}. 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 Take Photo 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.
signature:
heading: Sign Below
+ broadcasts:
+ show:
+ alert: That broadcast is no longer available
location_releases:
create:
notice: Your release has been signed. Thank you!
new:
cancel: Cancel
contact_info:
- heading: Signer Information
+ heading: Owner Contact Information
filming_info:
heading: Filming Information
legal:
heading: Legal
location_info:
heading: Location Information
+ photos:
+ heading: Photos
signature:
heading: Sign Below
material_releases:
@@ -806,18 +953,94 @@ en:
new:
cancel: Cancel
contact_info:
- heading: Signer's Contact Information
+ heading: Licensor/Owner Contact Information
legal:
heading: Legal
+ photo:
+ heading: Photos
release_info:
heading: Release Information
signature:
heading: Sign Below
+ medical_releases:
+ create:
+ notice: Your release has been signed. Thank you!
+ new:
+ cancel: Cancel
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires)
+ guardian_2_photo:
+ heading: Second Guardian Photo
+ instructions: >
+ Lastly, it's time for second 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!
+ guardian_clause:
+ heading: Guardian Clause
+ guardian_info:
+ heading: Guardian Information
+ guardian_photo:
+ heading: Guardian Photo
+ 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: >
+ Below is the medical release form. After scrolling down and reading the medical release form, please enter your personal information, take a photo, and press the "Submit Release" button.
+ legal:
+ heading: Legal
+ personal_info:
+ heading: Personal Information
+ instructions: Now, enter your personal information.
+ photo:
+ camera_instructions_html: Click Take Photo to Turn ON Camera
+ heading: Photos
+ no_photo: No photo yet
+ take_photo: Take Photo
+ warning: If your photo appears sideways, it will be autocorrected when you submit your release.
+ questionnaire:
+ heading: Questionnaire
+ signature:
+ heading: Signature
+ misc_releases:
+ create:
+ notice: Your release has been signed. Thank you!
+ new:
+ cancel: Cancel
+ guardian_clause:
+ heading: Guardian Clause
+ guardian_info:
+ heading: Guardian Information
+ guardian_photo:
+ camera_instructions_html: Click Take Photo to Turn ON Camera
+ heading: Guardian Photo
+ 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!
+ no_photo: No photo yet
+ take_photo: Take Photo
+ warning: If your photo appears sideways, it will be autocorrected when you submit your release.
+ instructions_html: >
+ Below is the misc release form. After scrolling down and reading the misc release form, please enter your personal information, take a photo, and press the "Submit Release" button.
+ legal:
+ heading: Legal
+ personal_info:
+ heading: Personal Information
+ instructions: Now, enter your personal information.
+ photo:
+ heading: Photos
+ signature:
+ heading: Signature
talent_releases:
create:
notice: Your release has been signed. Thank you!
new:
cancel: Cancel
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires)
+ guardian_2_photo:
+ camera_instructions_html: Click Take Photo to Turn ON Camera
+ heading: Second Guardian Photo
+ instructions: >
+ Lastly, it's time for second 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!
+ no_photo: No photo yet
+ take_photo: Take Photo
+ warning: If your photo appears sideways, it will be autocorrected when you submit your release.
guardian_clause:
heading: Guardian Clause
guardian_info:
@@ -900,6 +1123,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:
@@ -918,7 +1142,13 @@ en:
form:
contract_and_rights:
heading: 2 of 3 Contract & Exploitable Rights
+ guardian_2_info:
+ heading: Guardian Information (if company requires)
+ guardian_info:
+ heading: Guardian Information
photos:
+ guardian_2_photo:
+ heading: Second Guardian Photo
guardian_photo:
heading: Guardian Photo
heading: 3 of 3 Photos
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 30e4aa8..3384431 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -25,9 +25,16 @@ 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:
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires) (ES)
+ guardian_info:
+ heading: Guardian Information (ES)
photos:
+ guardian_2_photo:
+ heading: Second Guardian Photo (ES)
guardian_photo:
heading: Guardian Photo (ES)
person_photo:
@@ -37,6 +44,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,8 +61,18 @@ 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_2_photo_heading: Second guardian photo (ES)
guardian_photo_heading: Guardian photo (ES)
heading:
one: Photo (ES)
@@ -101,16 +120,73 @@ es:
errors_helper:
failure_message: "Los siguientes errores han impedido que se presente este %{model_name}:"
helpers:
+ help:
+ contract_template:
+ fee: Leave at $0.00 for no-fee (ES)
+ guardian_clause: Leave blank if not required for this contract (ES)
label:
appearance_release:
- guardian_address: Dirección del tutor legal
+ guardian_2_address_city: Guardian 2 city (ES)
+ guardian_2_address_country: Guardian 2 country (ES)
+ guardian_2_address_state: Guardian 2 state (ES)
+ guardian_2_address_street1: Guardian 2 address (ES)
+ guardian_2_address_street2: Guardian 2 address (Line 2) (ES)
+ guardian_2_address_zip: Guardian 2 zip code (ES)
+ guardian_2_email: Guardian 2 email (ES)
+ guardian_2_first_name: Guardian 2 first name (ES)
+ guardian_2_last_name: Guardian 2 last name (ES)
+ guardian_2_phone: Guardian 2 phone (ES)
+ guardian_address_city: Guardian city (ES)
+ guardian_address_country: Guardian country (ES)
+ guardian_address_state: Guardian state (ES)
+ guardian_address_street1: Dirección del tutor legal
+ guardian_address_street2: Dirección del tutor legal (Línea 2)
+ guardian_address_zip: Guardian zip code (ES)
guardian_name: Nómbre del tutor legal
guardian_phone: Número de teléfono del tutor legal
minor: El firmante es un menor
- person_address: Dirección
+ person_address_city: City (ES)
+ person_address_country: Country (ES)
+ person_address_state: State (ES)
+ person_address_street1: Address (ES)
+ person_address_street2: Address (Line 2) (ES)
person_email: Dirección de correo electrónico
person_name: Nómbre
person_phone: Número de teléfono
+ medical_release:
+ guardian_2_address_city: Guardian 2 city (ES)
+ guardian_2_address_country: Guardian 2 country (ES)
+ guardian_2_address_state: Guardian 2 state (ES)
+ guardian_2_address_street1: Guardian 2 address (ES)
+ guardian_2_address_street2: Guardian 2 address (Line 2) (ES)
+ guardian_2_address_zip: Guardian 2 zip code (ES)
+ guardian_2_email: Guardian 2 email (ES)
+ guardian_2_first_name: ""
+ guardian_2_last_name: ""
+ guardian_2_phone: ""
+ guardian_address_city: Guardian City (ES)
+ guardian_address_country: Guardian country (ES)
+ guardian_address_state: Guardian State (ES)
+ guardian_address_street1: Guardian address (ES)
+ guardian_address_street2: Guardian address (line 2) (ES)
+ guardian_address_zip: Guardian ZIP (ES)
+ guardian_email: Guardian email (ES)
+ guardian_first_name: Guardian First name (ES)
+ guardian_last_name: Guardian Last name (ES)
+ guardian_phone: Guardian Phone (ES)
+ minor: El firmante es un menor
+ person_address_city: Person City (ES)
+ person_address_country: Country (ES)
+ person_address_state: Person State (ES)
+ person_address_street1: Person Address (ES)
+ person_address_street2: Person Address (line 2) (ES)
+ person_address_zip: Person ZIP (ES)
+ person_date_of_birth: Date of birth (ES)
+ person_email: Email address (ES)
+ person_first_name: First name (ES)
+ person_last_name: Last name (ES)
+ person_name: Name (ES)
+ person_phone: Phone number (ES)
project:
client_name: Nómbre del cliente del proyecto
description: Descripción del proyecto
@@ -118,6 +194,36 @@ es:
name: Nómbre del proyecto de vídeo
producer_address: Dirección del productor
producer_name: Nómbre del productor
+ talen_release:
+ guardian_2_address_city: Guardian 2 city (ES)
+ guardian_2_address_country: Guardian 2 country (ES)
+ guardian_2_address_state: Guardian 2 state (ES)
+ guardian_2_address_street1: Guardian 2 address (ES)
+ guardian_2_address_street2: Guardian 2 address (Line 2) (ES)
+ guardian_2_address_zip: Guardian 2 zip code (ES)
+ guardian_2_email: Guardian 2 email (ES)
+ guardian_2_first_name: Guardian 2 first name (ES)
+ guardian_2_last_name: Guardian 2 last name (ES)
+ guardian_2_phone: Guardian 2 phone (ES)
+ guardian_address_city: City (ES)
+ guardian_address_country: Guardian country (ES)
+ guardian_address_state: State (ES)
+ guardian_address_street1: Guardian address (ES)
+ guardian_address_street2: Guardian address (Line 2) (ES)
+ guardian_address_zip: Zip code (ES)
+ guardian_email: Guardian email address (ES)
+ guardian_name: Guardian name (ES)
+ guardian_phone: Guardian phone number (ES)
+ minor: Is the person a minor? (ES)
+ person_address_city: City (ES)
+ person_address_country: Country (ES)
+ person_address_state: State (ES)
+ person_address_street1: Address (ES)
+ person_address_street2: Address (Line 2) (ES)
+ person_address_zip: Zip code (ES)
+ person_email: Email address (ES)
+ person_name: Name (ES)
+ person_phone: Phone number (ES)
placeholder:
appearance_release:
person_address: Calle, Número de apartamento, Ciudad, Estado, Código Postal
@@ -132,12 +238,26 @@ es:
update: Save Changes (ES)
create: 'Crear %{model}'
update: 'Actualizar %{model}'
+ location_releases:
+ form:
+ photos:
+ dropzone_label: Tap to take a photo of the Property (optional) (ES)
+ material_releases:
+ form:
+ photos:
+ dropzone_label: Tap to take a photo of Licensed Material (optional) (ES)
public:
appearance_releases:
create:
notice: La autorización está firmada. ¡Gracias!
new:
cancel: Cancelar
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires) (ES)
+ guardian_2_photo:
+ heading: Second Guardian Photo (ES)
+ instructions: >
+ (ES) Lastly, it's time for second 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! (ES)
guardian_clause:
heading: Guardian Clause (ES)
guardian_photo:
@@ -160,10 +280,50 @@ es:
clear: Despejar
heading: Firma
instructions: 'Firma Abajo:'
- talent_releases:
+ location_releases:
new:
+ photos:
+ heading: Photos (ES)
+ material_releases:
+ new:
+ photo:
+ heading: Photos (ES)
+ medical_releases:
+ new:
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires) (ES)
+ guardian_2_photo:
+ heading: Second Guardian Photo (ES)
+ instructions: >
+ (ES) Lastly, it's time for second 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! (ES)
guardian_clause:
heading: Guardian Clause (ES)
+ guardian_info:
+ heading: Gurdian Information (ES)
+ guardian_photo:
+ heading: Guardian Photo (ES)
+ instructions: >
+ (ES) 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! (ES)
+ photo:
+ camera_instructions_html: Haga clic en Take Photo para encender la cámara
+ no_photo: No hay foto todavía
+ take_photo: Take Photo (ES)
+ warning: Si su foto aparece de lado, se corregirá automáticamente cuando actualizar la autorización
+ talent_releases:
+ new:
+ guardian_2_info:
+ heading: Second Guardian Information (if company requires) (ES)
+ guardian_2_photo:
+ camera_instructions_html: ""
+ heading: Second Guardian Photo (ES)
+ instructions: ""
+ no_photo: ""
+ take_photo: ""
+ warning: ""
+ guardian_clause:
+ heading: Guardian Clause (ES)
+ guardian_info:
+ heading: ""
guardian_photo:
camera_instructions_html: (ES) Click Take Photo to Turn ON Camera (ES)
heading: Guardian Photo (ES)
@@ -171,6 +331,8 @@ es:
no_photo: No hay foto todavía
take_photo: Take Photo (ES)
warning: (ES) If your photo appears sideways, it will be autocorrected when you submit your release. (ES)
+ photo:
+ heading: Photos (ES)
teams:
show:
choose_project: ¿Qué proyecto de la lista de abajo asistirá?
@@ -179,7 +341,13 @@ es:
print: Print (ES)
talent_releases:
form:
+ guardian_2_info:
+ heading: Guardian Information (if company requires) (ES)
+ guardian_info:
+ heading: Guardian Information (ES)
photos:
+ guardian_2_photo:
+ heading: Second Guardian Photo (ES)
guardian_photo:
heading: Guardian Photo (ES)
task_requests:
diff --git a/config/routes.rb b/config/routes.rb
index 665311d..d43bfb9 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -54,6 +54,8 @@ Rails.application.routes.draw do
resources :material_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :music_releases, except: [:show], concerns: [:contractable, :notable]
resources :talent_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
+ resources :medical_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
+ resources :misc_releases, except: [:show], concerns: [:contractable, :notable, :photoable]
resources :contract_templates, only: [:index, :new, :create, :destroy] do
resource :qr_codes, only: [:show], controller: "contract_templates/qr_codes"
resource :blank_contracts, only: [:show, :new, :create], controller: "contract_templates/blank_contracts"
@@ -124,6 +126,8 @@ Rails.application.routes.draw do
resources :acquired_media_releases, only: [:new, :create]
resources :location_releases, only: [:new, :create]
resources :material_releases, only: [:new, :create]
+ resources :medical_releases, only: [:new, :create]
+ resources :misc_releases, only: [:new, :create]
end
end
end
@@ -133,7 +137,7 @@ Rails.application.routes.draw do
end
RELEASES = [:acquired_media_releases, :appearance_releases, :talent_releases, :material_releases, :location_releases]
- ALL_RELEASES = RELEASES + [:music_releases]
+ ALL_RELEASES = RELEASES + [:music_releases, :medical_releases, :misc_releases]
ALL_RELEASES.each do |release|
resources release, only: [], concerns: :taggable
@@ -168,6 +172,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
diff --git a/db/data_migrations/20200526114957_assign_account_number_and_type_to_zoom_users.rb b/db/data_migrations/20200526114957_assign_account_number_and_type_to_zoom_users.rb
new file mode 100644
index 0000000..16b2aee
--- /dev/null
+++ b/db/data_migrations/20200526114957_assign_account_number_and_type_to_zoom_users.rb
@@ -0,0 +1,7 @@
+class AssignAccountNumberAndTypeToZoomUsers < ActiveRecord::DataMigration
+ def up
+ ZoomUser.find_each do |zu|
+ zu.update account_number: ENV.fetch('ZOOM_ACCOUNT_NUMBER'), tier: (ENV['ZOOM_USER_TYPE'] == 'pro' ? 1 : 0)
+ end
+ end
+end
\ No newline at end of file
diff --git a/db/data_migrations/20200623111803_change_existing_zoom_user_settings.rb b/db/data_migrations/20200623111803_change_existing_zoom_user_settings.rb
new file mode 100644
index 0000000..adbacee
--- /dev/null
+++ b/db/data_migrations/20200623111803_change_existing_zoom_user_settings.rb
@@ -0,0 +1,9 @@
+class ChangeExistingZoomUserSettings < ActiveRecord::DataMigration
+ def up
+ gateway = ZoomGateway.new
+
+ ZoomUser.find_each do |zu|
+ gateway.update_user_settings zu.api_id
+ end
+ end
+end
diff --git a/db/migrate/20200430151828_create_matching_requests.rb b/db/migrate/20200430151828_create_matching_requests.rb
new file mode 100644
index 0000000..cc4e4cb
--- /dev/null
+++ b/db/migrate/20200430151828_create_matching_requests.rb
@@ -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
diff --git a/db/migrate/20200430190412_add_identifier_to_appearance_releases.rb b/db/migrate/20200430190412_add_identifier_to_appearance_releases.rb
new file mode 100644
index 0000000..a1ff2fa
--- /dev/null
+++ b/db/migrate/20200430190412_add_identifier_to_appearance_releases.rb
@@ -0,0 +1,5 @@
+class AddIdentifierToAppearanceReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :appearance_releases, :identifier, :string, default: nil
+ end
+end
diff --git a/db/migrate/20200526113516_add_account_number_and_type_to_zoom_users.rb b/db/migrate/20200526113516_add_account_number_and_type_to_zoom_users.rb
new file mode 100644
index 0000000..8bc0afa
--- /dev/null
+++ b/db/migrate/20200526113516_add_account_number_and_type_to_zoom_users.rb
@@ -0,0 +1,6 @@
+class AddAccountNumberAndTypeToZoomUsers < ActiveRecord::Migration[6.0]
+ def change
+ add_column :zoom_users, :account_number, :string
+ add_column :zoom_users, :tier, :integer, default: 0
+ end
+end
diff --git a/db/migrate/20200603090419_add_filming_hours_to_location_releases.rb b/db/migrate/20200603090419_add_filming_hours_to_location_releases.rb
new file mode 100644
index 0000000..f462e35
--- /dev/null
+++ b/db/migrate/20200603090419_add_filming_hours_to_location_releases.rb
@@ -0,0 +1,5 @@
+class AddFilmingHoursToLocationReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :location_releases, :filming_hours, :text
+ end
+end
diff --git a/db/migrate/20200606044747_create_medical_releases.rb b/db/migrate/20200606044747_create_medical_releases.rb
new file mode 100644
index 0000000..950292d
--- /dev/null
+++ b/db/migrate/20200606044747_create_medical_releases.rb
@@ -0,0 +1,23 @@
+class CreateMedicalReleases < ActiveRecord::Migration[6.0]
+ def change
+ create_table :medical_releases do |t|
+ t.belongs_to :project, foreign_key: true
+ t.belongs_to :contract_template, foreign_key: true
+ t.string :person_first_name
+ t.string :person_last_name
+ t.string :person_address_street1
+ t.string :person_address_street2
+ t.string :person_address_city
+ t.string :person_address_state
+ t.string :person_address_zip
+ t.string :person_address_country
+ t.string :person_phone
+ t.string :person_email
+ t.string :locale
+ t.text :notes
+ t.datetime :signed_at
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20200610085411_add_question_fields_to_contract_templates.rb b/db/migrate/20200610085411_add_question_fields_to_contract_templates.rb
new file mode 100644
index 0000000..0187af8
--- /dev/null
+++ b/db/migrate/20200610085411_add_question_fields_to_contract_templates.rb
@@ -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
diff --git a/db/migrate/20200610140459_add_answer_fields_to_medical_releases.rb b/db/migrate/20200610140459_add_answer_fields_to_medical_releases.rb
new file mode 100644
index 0000000..3e78fb5
--- /dev/null
+++ b/db/migrate/20200610140459_add_answer_fields_to_medical_releases.rb
@@ -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
diff --git a/db/migrate/20200612121539_add_guardian_email_to_appearance_releases.rb b/db/migrate/20200612121539_add_guardian_email_to_appearance_releases.rb
new file mode 100644
index 0000000..dfa06d1
--- /dev/null
+++ b/db/migrate/20200612121539_add_guardian_email_to_appearance_releases.rb
@@ -0,0 +1,5 @@
+class AddGuardianEmailToAppearanceReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :appearance_releases, :guardian_email, :string
+ end
+end
diff --git a/db/migrate/20200615131722_remove_broadcast_id_from_zoom_meetings.rb b/db/migrate/20200615131722_remove_broadcast_id_from_zoom_meetings.rb
new file mode 100644
index 0000000..e88c9e9
--- /dev/null
+++ b/db/migrate/20200615131722_remove_broadcast_id_from_zoom_meetings.rb
@@ -0,0 +1,5 @@
+class RemoveBroadcastIdFromZoomMeetings < ActiveRecord::Migration[6.0]
+ def change
+ remove_column :zoom_meetings, :broadcast_id
+ end
+end
diff --git a/db/migrate/20200615133602_destructure_person_address_column_in_appearance_releases.rb b/db/migrate/20200615133602_destructure_person_address_column_in_appearance_releases.rb
new file mode 100644
index 0000000..ba88cc4
--- /dev/null
+++ b/db/migrate/20200615133602_destructure_person_address_column_in_appearance_releases.rb
@@ -0,0 +1,10 @@
+class DestructurePersonAddressColumnInAppearanceReleases < ActiveRecord::Migration[6.0]
+ def change
+ rename_column :appearance_releases, :person_address, :person_address_street1
+ add_column :appearance_releases, :person_address_street2, :string
+ add_column :appearance_releases, :person_address_city, :string
+ add_column :appearance_releases, :person_address_state, :string
+ add_column :appearance_releases, :person_address_zip, :string
+ add_column :appearance_releases, :person_address_country, :string
+ end
+end
diff --git a/db/migrate/20200616124214_destructure_guardian_address_column_in_appearance_releases.rb b/db/migrate/20200616124214_destructure_guardian_address_column_in_appearance_releases.rb
new file mode 100644
index 0000000..9cb94da
--- /dev/null
+++ b/db/migrate/20200616124214_destructure_guardian_address_column_in_appearance_releases.rb
@@ -0,0 +1,10 @@
+class DestructureGuardianAddressColumnInAppearanceReleases < ActiveRecord::Migration[6.0]
+ def change
+ rename_column :appearance_releases, :guardian_address, :guardian_address_street1
+ add_column :appearance_releases, :guardian_address_street2, :string
+ add_column :appearance_releases, :guardian_address_city, :string
+ add_column :appearance_releases, :guardian_address_state, :string
+ add_column :appearance_releases, :guardian_address_zip, :string
+ add_column :appearance_releases, :guardian_address_country, :string
+ end
+end
diff --git a/db/migrate/20200619081446_add_more_questions_and_answers_to_medical_releases.rb b/db/migrate/20200619081446_add_more_questions_and_answers_to_medical_releases.rb
new file mode 100644
index 0000000..3696559
--- /dev/null
+++ b/db/migrate/20200619081446_add_more_questions_and_answers_to_medical_releases.rb
@@ -0,0 +1,15 @@
+class AddMoreQuestionsAndAnswersToMedicalReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :contract_templates, :question_11_text, :text
+ add_column :contract_templates, :question_12_text, :text
+ add_column :contract_templates, :question_13_text, :text
+ add_column :contract_templates, :question_14_text, :text
+ add_column :contract_templates, :question_15_text, :text
+
+ add_column :medical_releases, :question_11_answer, :text
+ add_column :medical_releases, :question_12_answer, :text
+ add_column :medical_releases, :question_13_answer, :text
+ add_column :medical_releases, :question_14_answer, :text
+ add_column :medical_releases, :question_15_answer, :text
+ end
+end
diff --git a/db/migrate/20200619085823_create_misc_releases.rb b/db/migrate/20200619085823_create_misc_releases.rb
new file mode 100644
index 0000000..9bf0f52
--- /dev/null
+++ b/db/migrate/20200619085823_create_misc_releases.rb
@@ -0,0 +1,34 @@
+class CreateMiscReleases < ActiveRecord::Migration[6.0]
+ def change
+ create_table :misc_releases do |t|
+ t.belongs_to :project, foreign_key: true
+ t.belongs_to :contract_template, foreign_key: true
+ t.string :person_first_name
+ t.string :person_last_name
+ t.string :person_address_street1
+ t.string :person_address_street2
+ t.string :person_address_city
+ t.string :person_address_state
+ t.string :person_address_zip
+ t.string :person_address_country
+ t.string :person_phone
+ t.string :person_email
+ t.string :guardian_first_name
+ t.string :guardian_last_name
+ t.string :guardian_address_street1
+ t.string :guardian_address_street2
+ t.string :guardian_address_city
+ t.string :guardian_address_state
+ t.string :guardian_address_zip
+ t.string :guardian_address_country
+ t.string :guardian_phone
+ t.string :guardian_email
+ t.string :locale
+ t.text :notes
+ t.datetime :signed_at
+ t.boolean :minor, default: false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20200619134853_add_second_guardian_fields_to_appearance_releases.rb b/db/migrate/20200619134853_add_second_guardian_fields_to_appearance_releases.rb
new file mode 100644
index 0000000..a067b44
--- /dev/null
+++ b/db/migrate/20200619134853_add_second_guardian_fields_to_appearance_releases.rb
@@ -0,0 +1,14 @@
+class AddSecondGuardianFieldsToAppearanceReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :appearance_releases, :guardian_2_first_name, :string
+ add_column :appearance_releases, :guardian_2_last_name, :string
+ add_column :appearance_releases, :guardian_2_email, :string
+ add_column :appearance_releases, :guardian_2_phone, :string
+ add_column :appearance_releases, :guardian_2_address_street1, :string
+ add_column :appearance_releases, :guardian_2_address_street2, :string
+ add_column :appearance_releases, :guardian_2_address_city, :string
+ add_column :appearance_releases, :guardian_2_address_state, :string
+ add_column :appearance_releases, :guardian_2_address_zip, :string
+ add_column :appearance_releases, :guardian_2_address_country, :string
+ end
+end
diff --git a/db/migrate/20200622180507_add_guardians_fields_to_medical_releases.rb b/db/migrate/20200622180507_add_guardians_fields_to_medical_releases.rb
new file mode 100644
index 0000000..a4d3314
--- /dev/null
+++ b/db/migrate/20200622180507_add_guardians_fields_to_medical_releases.rb
@@ -0,0 +1,25 @@
+class AddGuardiansFieldsToMedicalReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :medical_releases, :minor, :boolean, default: false
+ add_column :medical_releases, :guardian_first_name, :string
+ add_column :medical_releases, :guardian_last_name, :string
+ add_column :medical_releases, :guardian_email, :string
+ add_column :medical_releases, :guardian_phone, :string
+ add_column :medical_releases, :guardian_address_street1, :string
+ add_column :medical_releases, :guardian_address_street2, :string
+ add_column :medical_releases, :guardian_address_city, :string
+ add_column :medical_releases, :guardian_address_state, :string
+ add_column :medical_releases, :guardian_address_zip, :string
+ add_column :medical_releases, :guardian_address_country, :string
+ add_column :medical_releases, :guardian_2_first_name, :string
+ add_column :medical_releases, :guardian_2_last_name, :string
+ add_column :medical_releases, :guardian_2_email, :string
+ add_column :medical_releases, :guardian_2_phone, :string
+ add_column :medical_releases, :guardian_2_address_street1, :string
+ add_column :medical_releases, :guardian_2_address_street2, :string
+ add_column :medical_releases, :guardian_2_address_city, :string
+ add_column :medical_releases, :guardian_2_address_state, :string
+ add_column :medical_releases, :guardian_2_address_zip, :string
+ add_column :medical_releases, :guardian_2_address_country, :string
+ end
+end
diff --git a/db/migrate/20200625144713_add_second_guardian_fields_to_talent_releases.rb b/db/migrate/20200625144713_add_second_guardian_fields_to_talent_releases.rb
new file mode 100644
index 0000000..543c5c1
--- /dev/null
+++ b/db/migrate/20200625144713_add_second_guardian_fields_to_talent_releases.rb
@@ -0,0 +1,14 @@
+class AddSecondGuardianFieldsToTalentReleases < ActiveRecord::Migration[6.0]
+ def change
+ add_column :talent_releases, :guardian_2_first_name, :string
+ add_column :talent_releases, :guardian_2_last_name, :string
+ add_column :talent_releases, :guardian_2_email, :string
+ add_column :talent_releases, :guardian_2_phone, :string
+ add_column :talent_releases, :guardian_2_address_street1, :string
+ add_column :talent_releases, :guardian_2_address_street2, :string
+ add_column :talent_releases, :guardian_2_address_city, :string
+ add_column :talent_releases, :guardian_2_address_state, :string
+ add_column :talent_releases, :guardian_2_address_zip, :string
+ add_column :talent_releases, :guardian_2_address_country, :string
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index e1fe1e4..c4de3ba 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9,6 +9,20 @@ 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: -
--
@@ -43,14 +57,14 @@ COMMENT ON EXTENSION pg_trgm IS 'text similarity measurement and index searching
CREATE FUNCTION public.pg_search_dmetaphone(text) RETURNS text
LANGUAGE sql IMMUTABLE STRICT
- AS $_$
- SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ')
+ AS $_$
+ SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ')
$_$;
SET default_tablespace = '';
-SET default_table_access_method = heap;
+SET default_with_oids = false;
--
-- Name: account_auths; Type: TABLE; Schema: public; Owner: -
@@ -290,13 +304,13 @@ ALTER SEQUENCE public.active_storage_blobs_id_seq OWNED BY public.active_storage
CREATE TABLE public.appearance_releases (
id bigint NOT NULL,
person_name_old character varying,
- person_address character varying,
+ person_address_street1 character varying,
person_phone character varying,
project_id bigint,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
minor boolean DEFAULT false,
- guardian_address character varying,
+ guardian_address_street1 character varying,
guardian_name_old character varying,
guardian_phone character varying,
person_email character varying,
@@ -316,7 +330,29 @@ 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,
+ guardian_email character varying,
+ identifier character varying,
+ person_address_street2 character varying,
+ person_address_city character varying,
+ person_address_state character varying,
+ person_address_zip character varying,
+ person_address_country character varying,
+ guardian_address_street2 character varying,
+ guardian_address_city character varying,
+ guardian_address_state character varying,
+ guardian_address_zip character varying,
+ guardian_address_country character varying,
+ guardian_2_first_name character varying,
+ guardian_2_last_name character varying,
+ guardian_2_email character varying,
+ guardian_2_phone character varying,
+ guardian_2_address_street1 character varying,
+ guardian_2_address_street2 character varying,
+ guardian_2_address_city character varying,
+ guardian_2_address_state character varying,
+ guardian_2_address_zip character varying,
+ guardian_2_address_country character varying
);
@@ -592,7 +628,22 @@ 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,
+ question_11_text text,
+ question_12_text text,
+ question_13_text text,
+ question_14_text text,
+ question_15_text text
);
@@ -846,7 +897,8 @@ CREATE TABLE public.location_releases (
filming_started_on date,
filming_ended_on date,
person_first_name character varying,
- person_last_name character varying
+ person_last_name character varying,
+ filming_hours text
);
@@ -869,6 +921,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: -
--
@@ -927,6 +1010,143 @@ CREATE SEQUENCE public.material_releases_id_seq
ALTER SEQUENCE public.material_releases_id_seq OWNED BY public.material_releases.id;
+--
+-- Name: medical_releases; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.medical_releases (
+ id bigint NOT NULL,
+ project_id bigint,
+ contract_template_id bigint,
+ person_first_name character varying,
+ person_last_name character varying,
+ person_address_street1 character varying,
+ person_address_street2 character varying,
+ person_address_city character varying,
+ person_address_state character varying,
+ person_address_zip character varying,
+ person_address_country character varying,
+ person_phone character varying,
+ person_email character varying,
+ locale character varying,
+ 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,
+ 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,
+ question_11_answer text,
+ question_12_answer text,
+ question_13_answer text,
+ question_14_answer text,
+ question_15_answer text,
+ minor boolean DEFAULT false,
+ guardian_first_name character varying,
+ guardian_last_name character varying,
+ guardian_email character varying,
+ guardian_phone character varying,
+ guardian_address_street1 character varying,
+ guardian_address_street2 character varying,
+ guardian_address_city character varying,
+ guardian_address_state character varying,
+ guardian_address_zip character varying,
+ guardian_address_country character varying,
+ guardian_2_first_name character varying,
+ guardian_2_last_name character varying,
+ guardian_2_email character varying,
+ guardian_2_phone character varying,
+ guardian_2_address_street1 character varying,
+ guardian_2_address_street2 character varying,
+ guardian_2_address_city character varying,
+ guardian_2_address_state character varying,
+ guardian_2_address_zip character varying,
+ guardian_2_address_country character varying
+);
+
+
+--
+-- Name: medical_releases_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.medical_releases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: medical_releases_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.medical_releases_id_seq OWNED BY public.medical_releases.id;
+
+
+--
+-- Name: misc_releases; Type: TABLE; Schema: public; Owner: -
+--
+
+CREATE TABLE public.misc_releases (
+ id bigint NOT NULL,
+ project_id bigint,
+ contract_template_id bigint,
+ person_first_name character varying,
+ person_last_name character varying,
+ person_address_street1 character varying,
+ person_address_street2 character varying,
+ person_address_city character varying,
+ person_address_state character varying,
+ person_address_zip character varying,
+ person_address_country character varying,
+ person_phone character varying,
+ person_email character varying,
+ guardian_first_name character varying,
+ guardian_last_name character varying,
+ guardian_address_street1 character varying,
+ guardian_address_street2 character varying,
+ guardian_address_city character varying,
+ guardian_address_state character varying,
+ guardian_address_zip character varying,
+ guardian_address_country character varying,
+ guardian_phone character varying,
+ guardian_email character varying,
+ locale character varying,
+ notes text,
+ signed_at timestamp without time zone,
+ minor boolean DEFAULT false,
+ created_at timestamp(6) without time zone NOT NULL,
+ updated_at timestamp(6) without time zone NOT NULL
+);
+
+
+--
+-- Name: misc_releases_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE public.misc_releases_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+
+--
+-- Name: misc_releases_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE public.misc_releases_id_seq OWNED BY public.misc_releases.id;
+
+
--
-- Name: music_releases; Type: TABLE; Schema: public; Owner: -
--
@@ -1303,7 +1523,17 @@ CREATE TABLE public.talent_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,
+ guardian_2_first_name character varying,
+ guardian_2_last_name character varying,
+ guardian_2_email character varying,
+ guardian_2_phone character varying,
+ guardian_2_address_street1 character varying,
+ guardian_2_address_street2 character varying,
+ guardian_2_address_city character varying,
+ guardian_2_address_state character varying,
+ guardian_2_address_zip character varying,
+ guardian_2_address_country character varying
);
@@ -1596,7 +1826,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,
status integer DEFAULT 0,
zoom_user_id bigint,
project_id bigint
@@ -1630,7 +1859,9 @@ CREATE TABLE public.zoom_users (
id bigint NOT NULL,
api_id character varying,
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,
+ account_number character varying,
+ tier integer DEFAULT 0
);
@@ -1793,6 +2024,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: -
--
@@ -1800,6 +2038,20 @@ ALTER TABLE ONLY public.location_releases ALTER COLUMN id SET DEFAULT nextval('p
ALTER TABLE ONLY public.material_releases ALTER COLUMN id SET DEFAULT nextval('public.material_releases_id_seq'::regclass);
+--
+-- Name: medical_releases id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.medical_releases ALTER COLUMN id SET DEFAULT nextval('public.medical_releases_id_seq'::regclass);
+
+
+--
+-- Name: misc_releases id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.misc_releases ALTER COLUMN id SET DEFAULT nextval('public.misc_releases_id_seq'::regclass);
+
+
--
-- Name: music_releases id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -2109,6 +2361,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: -
--
@@ -2117,6 +2377,22 @@ ALTER TABLE ONLY public.material_releases
ADD CONSTRAINT material_releases_pkey PRIMARY KEY (id);
+--
+-- Name: medical_releases medical_releases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.medical_releases
+ ADD CONSTRAINT medical_releases_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: misc_releases misc_releases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.misc_releases
+ ADD CONSTRAINT misc_releases_pkey PRIMARY KEY (id);
+
+
--
-- Name: music_releases music_releases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -2578,6 +2854,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: -
--
@@ -2620,6 +2903,34 @@ CREATE INDEX index_material_releases_on_term_id ON public.material_releases USIN
CREATE INDEX index_material_releases_on_territory_id ON public.material_releases USING btree (territory_id);
+--
+-- Name: index_medical_releases_on_contract_template_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_medical_releases_on_contract_template_id ON public.medical_releases USING btree (contract_template_id);
+
+
+--
+-- Name: index_medical_releases_on_project_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_medical_releases_on_project_id ON public.medical_releases USING btree (project_id);
+
+
+--
+-- Name: index_misc_releases_on_contract_template_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_misc_releases_on_contract_template_id ON public.misc_releases USING btree (contract_template_id);
+
+
+--
+-- Name: index_misc_releases_on_project_id; Type: INDEX; Schema: public; Owner: -
+--
+
+CREATE INDEX index_misc_releases_on_project_id ON public.misc_releases USING btree (project_id);
+
+
--
-- Name: index_music_releases_on_applicable_medium_id; Type: INDEX; Schema: public; Owner: -
--
@@ -2900,13 +3211,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: -
--
@@ -2935,6 +3239,14 @@ CREATE UNIQUE INDEX taggings_idx ON public.taggings USING btree (tag_id, taggabl
CREATE INDEX taggings_idy ON public.taggings USING btree (taggable_id, taggable_type, tagger_id, context);
+--
+-- Name: misc_releases fk_rails_0222652fcd; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.misc_releases
+ ADD CONSTRAINT fk_rails_0222652fcd FOREIGN KEY (project_id) REFERENCES public.projects(id);
+
+
--
-- Name: unreleased_appearances fk_rails_0393a349dd; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -3063,6 +3375,14 @@ ALTER TABLE ONLY public.video_release_confirmations
ADD CONSTRAINT fk_rails_2787252ceb FOREIGN KEY (file_info_id) REFERENCES public.file_infos(id);
+--
+-- Name: medical_releases fk_rails_325442c794; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.medical_releases
+ ADD CONSTRAINT fk_rails_325442c794 FOREIGN KEY (contract_template_id) REFERENCES public.contract_templates(id);
+
+
--
-- Name: music_releases fk_rails_3a2b4033ad; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -3207,6 +3527,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: -
--
@@ -3240,11 +3568,11 @@ ALTER TABLE ONLY public.music_releases
--
--- Name: zoom_meetings fk_rails_8d814ea729; Type: FK CONSTRAINT; Schema: public; Owner: -
+-- Name: medical_releases fk_rails_98aa92daa9; 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);
+ALTER TABLE ONLY public.medical_releases
+ ADD CONSTRAINT fk_rails_98aa92daa9 FOREIGN KEY (project_id) REFERENCES public.projects(id);
--
@@ -3327,6 +3655,14 @@ ALTER TABLE ONLY public.active_storage_attachments
ADD CONSTRAINT fk_rails_c3b3935057 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id);
+--
+-- Name: misc_releases fk_rails_c664291b9b; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY public.misc_releases
+ ADD CONSTRAINT fk_rails_c664291b9b FOREIGN KEY (contract_template_id) REFERENCES public.contract_templates(id);
+
+
--
-- Name: location_releases fk_rails_c7458d662e; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -3558,10 +3894,26 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200424161117'),
('20200427073429'),
('20200428091105'),
+('20200430151828'),
+('20200430190412'),
('20200507110804'),
('20200512161738'),
('20200518200245'),
('20200519191908'),
-('20200610143327');
+('20200526113516'),
+('20200603090419'),
+('20200606044747'),
+('20200610085411'),
+('20200610140459'),
+('20200610143327'),
+('20200612121539'),
+('20200615131722'),
+('20200615133602'),
+('20200616124214'),
+('20200619081446'),
+('20200619085823'),
+('20200619134853'),
+('20200622180507'),
+('20200625144713');
diff --git a/lib/brayniac_ai.rb b/lib/brayniac_ai.rb
index ce9bc72..a6a7143 100644
--- a/lib/brayniac_ai.rb
+++ b/lib/brayniac_ai.rb
@@ -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"
diff --git a/lib/brayniac_ai/qr_matching.rb b/lib/brayniac_ai/qr_matching.rb
new file mode 100644
index 0000000..4328870
--- /dev/null
+++ b/lib/brayniac_ai/qr_matching.rb
@@ -0,0 +1,4 @@
+module BrayniacAI
+ class QrMatching < Base
+ end
+end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index dbeedb6..432f383 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -33,6 +33,8 @@ if Rails.env.development? || Rails.env.test? || Rails.env.review?
material_release: true,
music_release: true,
talent_release: true,
+ medical_release: true,
+ misc_release: true,
video_analysis: true,
})
diff --git a/lib/tasks/zoom.rake b/lib/tasks/zoom.rake
index 3ac0868..06e2902 100644
--- a/lib/tasks/zoom.rake
+++ b/lib/tasks/zoom.rake
@@ -1,4 +1,3 @@
-require 'zoom_gateway'
namespace :zoom do
desc "Setup necessary zoom roles and users"
task :setup => :environment do
@@ -17,4 +16,30 @@ namespace :zoom do
Rails.logger.info "Created role #{ZoomGateway.HOST_ROLE}."
end
end
+
+
+ desc "Synchronize ActiveRecord users with current account state"
+ task :sync => :environment do
+ zoom = Zoom.new
+
+ roles = zoom.roles_list["roles"]
+ ActiveRecord::Base.transaction do
+ ZoomUser.tiers.keys.each do |tier|
+ full_role_name = ZoomGateway.host_role_name(tier)
+ role_id = roles.select { |r| r["name"] == full_role_name }.first["id"]
+ user_ids = zoom.roles_members(role_id: role_id).dig("members").pluck("id")
+
+ # Invalid db users (not existing on the given Zoom account, but existing in the app db)
+ ZoomUser.current_account.public_send(tier).where.not(api_id: user_ids).each do |zu|
+ zu.api_id = nil
+ zu.destroy
+ end
+
+ # Missing zoom users (existing in given Zoom account, but not existing in the app db)
+ (user_ids - ZoomUser.current_account.public_send(tier).pluck(:api_id)).each do |api_user_id|
+ ZoomUser.current_account.public_send(tier).create(api_id: api_user_id)
+ end
+ end
+ end
+ end
end
\ No newline at end of file
diff --git a/lib/zoom_gateway.rb b/lib/zoom_gateway.rb
index 0e947fc..60e8798 100644
--- a/lib/zoom_gateway.rb
+++ b/lib/zoom_gateway.rb
@@ -1,8 +1,13 @@
+# frozen_string_literal: true
+
+require './lib/zoom_wrapper_monkeypatch'
+
class ZoomGateway
class AuthenticationError < StandardError; end
class MeetingExpired < StandardError; end
class UserNotFound < StandardError; end
class TooManyHosts < StandardError; end
+ class UserAlreadyExists < StandardError; end
class << self
def USER_TYPE_NAME
@@ -20,12 +25,24 @@ class ZoomGateway
end
def HOST_ROLE
- "#{self.USER_TYPE_NAME}-directme-host"
+ self.host_role_name(self.USER_TYPE_NAME)
+ end
+
+ def ACCOUNT_NUMBER
+ ENV['ZOOM_ACCOUNT_NUMBER']
+ end
+
+ def enable_recordings?
+ ENV['ZOOM_ENABLE_RECORDINGS'] == 'true'
end
def apply_limits?
self.USER_TYPE_NAME == 'pro'
end
+
+ def host_role_name(user_type_name)
+ "#{user_type_name}-directme-host"
+ end
end
def initialize
@@ -33,12 +50,14 @@ class ZoomGateway
end
def create_meeting(host_id, **kwargs)
+ recording_type = self.class.enable_recordings? ? 'cloud' : 'none'
meeting = @client.meeting_create({ user_id: host_id,
topic: kwargs[:topic],
type: 1, # Instant meeting
settings: {
host_video: true,
- participant_video: true
+ participant_video: true,
+ auto_recording: recording_type,
} })
meeting["id"]
end
@@ -50,6 +69,23 @@ class ZoomGateway
parse_zoom_error(e)
end
+ # Update user with custom settings
+ def update_user_settings(user_id)
+ custom_defaults = {
+ id: user_id,
+ in_meeting: {
+ auto_saving_chat: true,
+ co_host: true,
+ non_verbal_feedback: true,
+ breakout_room: true,
+ group_hd: true,
+ far_end_camera_control: true,
+ allow_live_streaming: true
+ }
+ }
+ @client.user_settings_update custom_defaults
+ end
+
def create_host(host_email)
# Find role
host_role = @client.roles_list["roles"].try(:select) { |r| r["name"] == self.class.HOST_ROLE }.try(:first)
@@ -67,6 +103,8 @@ class ZoomGateway
type: self.class.USER_TYPE
})
+ update_user_settings(host_user["id"])
+
# Assign role to user
@client.roles_assign role_id: host_role["id"], members: [{id: host_user["id"]}]
@@ -78,6 +116,10 @@ class ZoomGateway
@client.user_delete(id: host_id)
end
+ def delete_recording(meeting_id, recording_id)
+ @client.recording_delete(meeting_id: meeting_id, recording_id: recording_id)
+ end
+
private
def parse_zoom_error(error)
@@ -87,6 +129,8 @@ class ZoomGateway
raise UserNotFound, error.message
elsif error.status_code == 3001
raise MeetingExpired, error.message
+ elsif error.status_code == 1005
+ raise UserAlreadyExists, error.message
else
raise error
end
diff --git a/lib/zoom_wrapper_monkeypatch.rb b/lib/zoom_wrapper_monkeypatch.rb
new file mode 100644
index 0000000..bb9e0dc
--- /dev/null
+++ b/lib/zoom_wrapper_monkeypatch.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Zoom
+ module Actions
+ module User
+ def user_settings_update(*args)
+ params = Zoom::Params.new(Utils.extract_options!(args))
+ permitted_in_meeting_params = %i[
+ auto_saving_chat
+ co_host
+ non_verbal_feedback
+ breakout_room
+ group_hd
+ far_end_camera_control
+ allow_live_streaming
+ ]
+ permitted_params = { in_meeting: permitted_in_meeting_params }
+ params.require(:id).permit permitted_params
+ request_body = params.except(:id).to_json
+ resp = self.class.patch("/users/#{params[:id]}/settings", body: request_body, headers: request_headers)
+ Utils.parse_response resp
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/spec/channels/broadcasts_channel_spec.rb b/spec/channels/broadcasts_channel_spec.rb
index 9622ed2..2149998 100644
--- a/spec/channels/broadcasts_channel_spec.rb
+++ b/spec/channels/broadcasts_channel_spec.rb
@@ -50,4 +50,21 @@ RSpec.describe BroadcastsChannel, type: :channel do
})
end
end
+
+
+ describe ".broadcast_file_upload_updates" do
+ it 'broadcasts to the channel with the right data' do
+ broadcast = create(:broadcast, :with_stream, :with_files, skip_create_callback: true)
+ files_content = ApplicationController.render partial: "broadcasts/file", collection: broadcast.files
+
+ expect {
+ BroadcastsChannel.broadcast_file_upload_updates(broadcast, broadcast.files, "pagination_content")
+ }.to have_broadcasted_to(broadcast).with({
+ event: 'file_upload_update',
+ broadcast_token: broadcast.token,
+ files_content: files_content,
+ pagination_content: "pagination_content"
+ })
+ end
+ end
end
diff --git a/spec/channels/projects_channel_spec.rb b/spec/channels/projects_channel_spec.rb
index 92dbfc1..9a8aea5 100644
--- a/spec/channels/projects_channel_spec.rb
+++ b/spec/channels/projects_channel_spec.rb
@@ -24,4 +24,20 @@ RSpec.describe ProjectsChannel, type: :channel do
}.to have_broadcasted_to(project).with(event: "video_status_update", content: content)
end
end
+
+ describe ".conference_recording_ready" do
+ it "broadcasts to the project channel" do
+ recording_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
+ zoom_meeting = create(:zoom_meeting, project: project, recording: recording_file)
+ video_url = 'http://url.to.video/video.mp4'
+ allow(zoom_meeting.recording).to receive(:service_url).and_return(video_url)
+
+ expect {
+ ProjectsChannel.conference_recording_ready(project, zoom_meeting.recording)
+ }.to have_broadcasted_to(project).with { |data|
+ expect(data['content']).to include(video_url)
+ expect(data['event']).to eq('conference_recording_ready')
+ }
+ end
+ end
end
diff --git a/spec/controllers/api/broadcasts_controller_spec.rb b/spec/controllers/api/broadcasts_controller_spec.rb
index 56bae48..ee5e3af 100644
--- a/spec/controllers/api/broadcasts_controller_spec.rb
+++ b/spec/controllers/api/broadcasts_controller_spec.rb
@@ -128,6 +128,26 @@ RSpec.describe Api::BroadcastsController, type: :controller do
expect(included.first.dig("id")).to eq broadcast.files.first.id.to_s
expect(included.first.dig("type")).to eq 'active_storage_attachment'
end
+
+ context "when files param contains a signed_id string" do
+ it "adds that file to the broadcast" do
+ project = create(:project, name: 'first', account_id: current_user.primary_account.id)
+ broadcast = create(:broadcast, :with_stream, skip_create_callback: true, project: project, status: 'created')
+ blob = ActiveStorage::Blob.create_after_upload!(io: StringIO.new("Hello"), filename: "hello.txt", content_type: "text/plain")
+
+ sign_in_to_api(current_user)
+ patch :update, params: { project_id: project, id: broadcast, broadcast: { files: [blob.signed_id] } }
+
+ relationships = JSON.parse(response.body).dig('data', 'relationships')
+ included = JSON.parse(response.body).dig('included')
+
+ expect(relationships.keys).to include('files')
+ expect(included.size).to eq 1
+ expect(included.first.dig("id")).to eq broadcast.files.first.id.to_s
+ expect(included.first.dig("type")).to eq 'active_storage_attachment'
+ expect(included.first.dig("attributes", "filename")).to eq 'hello.txt'
+ end
+ end
end
after do
diff --git a/spec/controllers/api/direct_uploads_controller_spec.rb b/spec/controllers/api/direct_uploads_controller_spec.rb
new file mode 100644
index 0000000..9f83ff7
--- /dev/null
+++ b/spec/controllers/api/direct_uploads_controller_spec.rb
@@ -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
diff --git a/spec/controllers/appearance_releases_controller_spec.rb b/spec/controllers/appearance_releases_controller_spec.rb
index f926def..53e2be6 100644
--- a/spec/controllers/appearance_releases_controller_spec.rb
+++ b/spec/controllers/appearance_releases_controller_spec.rb
@@ -26,8 +26,7 @@ RSpec.describe AppearanceReleasesController, tye: :controller do
get :index, params: { project_id: project }
expect(response.body).to have_content "John Doe"
- expect(response.body).to have_content "555-123-4567"
- expect(response.body).to have_content "jane.doe@test.com"
+ expect(response.body).to have_content "P: 5551234567E: jane.doe@test.com"
expect(response.body).to have_content "Some notes here"
expect(response.body).to have_button "Import Release"
expect(response.body).to have_content "Manage"
@@ -264,7 +263,12 @@ 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)
+ .except(:guardian_address_street2).except(:guardian_address_city)
+ .except(:guardian_address_state).except(:guardian_address_zip)
+ .except(:guardian_address_country)
+ .merge(contract_param, exploitable_rights_params)
end
def exploitable_rights_params
diff --git a/spec/controllers/broadcasts_controller_spec.rb b/spec/controllers/broadcasts_controller_spec.rb
index c1c65f6..08b686a 100644
--- a/spec/controllers/broadcasts_controller_spec.rb
+++ b/spec/controllers/broadcasts_controller_spec.rb
@@ -111,17 +111,6 @@ RSpec.describe BroadcastsController, type: :controller do
end
end
- describe "#update" do
- let!(:broadcast) { create(:broadcast, :with_stream, skip_create_callback: true, project: project ) }
-
- it "uploads files to broadcast" do
- patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
-
- expect(broadcast.files.count).to eq(1)
- expect(broadcast.files.first.filename).to eq("contract.pdf")
- end
- end
-
describe "#show" do
let(:broadcast) { create(:broadcast, project: project, name: "Another Broadcast") }
@@ -198,6 +187,25 @@ RSpec.describe BroadcastsController, type: :controller do
end
end
+ describe "#update" do
+ let!(:broadcast) { create(:broadcast, :with_stream, skip_create_callback: true, project: project ) }
+
+ it "uploads files to broadcast" do
+ patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
+
+ expect(broadcast.files.count).to eq(1)
+ expect(broadcast.files.first.filename).to eq("contract.pdf")
+ end
+
+ it "sends an update to the broadcasts channel" do
+ allow(BroadcastsChannel).to receive(:broadcast_file_upload_updates)
+
+ patch :update, params: { project_id: project.id, id: broadcast.id, broadcast: file_params }, xhr: true
+
+ expect(BroadcastsChannel).to have_received(:broadcast_file_upload_updates)
+ end
+ end
+
describe "#destroy" do
let!(:broadcast_2) { create(:broadcast, :with_stream, skip_create_callback: true, project: project, name: "Another Broadcast") }
diff --git a/spec/controllers/contracts_controller_spec.rb b/spec/controllers/contracts_controller_spec.rb
index 5456dcf..6d6976a 100644
--- a/spec/controllers/contracts_controller_spec.rb
+++ b/spec/controllers/contracts_controller_spec.rb
@@ -63,4 +63,55 @@ RSpec.describe ContractsController, type: :controller do
it_behaves_like "a contracts controller"
end
+
+ context "for medical releases" do
+ let(:native_releasable) { create(:medical_release_with_contract_template, :native) }
+ let(:non_native_releasable) { create(:medical_release_with_contract_template, :non_native) }
+
+ describe "#show when user is account manager" do
+ it_behaves_like "a contracts controller"
+ end
+
+ shared_examples "a medical contracts controller for non-authorized users" do
+ describe "#show" do
+ context "for a native release" do
+ it "responds with not authorized error" do
+ pdf_body = Tempfile.new
+ allow_any_instance_of(Contract).to receive(:to_pdf).and_return(pdf_body)
+
+ expect {
+ get :show, params: { format: :pdf, "#{native_releasable.model_name.singular}_id" => native_releasable }
+ }.to raise_exception(Pundit::NotAuthorizedError)
+ end
+ end
+
+ context "for a non-native release" do
+ it "responds with the attached contract" do
+ contract = double(:contract, service_url: "http://example.org/contract.pdf")
+ allow_any_instance_of(non_native_releasable.class).to receive(:contract).and_return(contract)
+
+ expect {
+ get :show, params: { format: :pdf, "#{non_native_releasable.model_name.singular}_id" => non_native_releasable }
+ }.to raise_exception(Pundit::NotAuthorizedError)
+ end
+ end
+ end
+ end
+
+ describe "#show when user is project manager" do
+ let(:manager_user) { create(:user, :manager) }
+ before do
+ sign_in manager_user
+ end
+ it_behaves_like "a medical contracts controller for non-authorized users"
+ end
+
+ describe "#show when user is associate" do
+ let(:associate_user) { create(:user, :associate) }
+ before do
+ sign_in associate_user
+ end
+ it_behaves_like "a medical contracts controller for non-authorized users"
+ end
+ end
end
diff --git a/spec/controllers/medical_releases_controller_spec.rb b/spec/controllers/medical_releases_controller_spec.rb
new file mode 100644
index 0000000..e7dfa51
--- /dev/null
+++ b/spec/controllers/medical_releases_controller_spec.rb
@@ -0,0 +1,91 @@
+require "rails_helper"
+
+RSpec.describe MedicalReleasesController, type: :controller do
+ render_views
+
+ let(:user) { create(:user) }
+ let(:account) { user.primary_account }
+ let(:project) { create(:project, account: user.primary_account) }
+
+ before do
+ sign_in user
+ end
+
+ describe "#index" do
+ it "responds successfully" do
+ get :index, params: { project_id: project }
+
+ expect(response).to be_successful
+ end
+
+ it "renders content" do
+ release = create(:medical_release, project: project,
+ person_first_name: "My",
+ person_last_name: "Release",
+ person_phone: "5551234567",
+ person_email: "jane.doe@test.com")
+ create(:note, notable: release, content: "Some notes here")
+
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_content "My Release"
+ expect(response.body).to have_content "Some notes here"
+ expect(response.body).to have_content "Manage"
+ end
+
+ context "when there are no medical releases" do
+ it "renders an empty message" do
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_content("Medical releases will appear here")
+ end
+ end
+
+ context "when there are many records" do
+ it "paginates the table" do
+ create_list(:medical_release, 20, project: project)
+
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_link("2", href: project_medical_releases_path(project, page: 2))
+ end
+ end
+
+ context "for xhr request" do
+ it "filters the releases by a query param" do
+ medical_releases = [
+ create(:medical_release, person_name: "Adam Sandler", project: project),
+ create(:medical_release, person_name: "Zoe Perry", project: project),
+ ]
+
+ get :index, params: { project_id: project, query: "Zoe" }, xhr: true
+
+ expect(response.body).not_to have_content("Adam Sandler")
+ expect(response.body).to have_content("Zoe Perry")
+ end
+ end
+ end
+
+ describe "#destroy" do
+ let!(:medical_release) { create(:medical_release, project: project) }
+
+ it "responds with redirect" do
+ delete :destroy, params: { project_id: project, id: medical_release }
+
+ expect(response).to be_redirect
+ expect(response).to redirect_to [project, :medical_releases]
+ end
+
+ it "sets the flash" do
+ delete :destroy, params: { project_id: project, id: medical_release }
+
+ expect(flash.alert).not_to be_nil
+ end
+
+ it "destroys the record" do
+ expect {
+ delete :destroy, params: { project_id: project, id: medical_release }
+ }.to change(MedicalRelease, :count).by(-1)
+ end
+ end
+end
diff --git a/spec/controllers/misc_releases_controller_spec.rb b/spec/controllers/misc_releases_controller_spec.rb
new file mode 100644
index 0000000..43f8957
--- /dev/null
+++ b/spec/controllers/misc_releases_controller_spec.rb
@@ -0,0 +1,116 @@
+require "rails_helper"
+
+RSpec.describe MiscReleasesController, type: :controller do
+ render_views
+
+ let(:user) { create(:user) }
+ let(:account) { user.primary_account }
+ let(:project) { create(:project, account: user.primary_account) }
+
+ before do
+ sign_in user
+ end
+
+ describe "#index" do
+ it "responds successfully" do
+ get :index, params: { project_id: project }
+
+ expect(response).to be_successful
+ end
+
+ it "renders content" do
+ release = create(:misc_release, project: project,
+ person_first_name: "My",
+ person_last_name: "Release",
+ person_phone: "5551234567",
+ person_email: "jane.doe@test.com")
+ create(:note, notable: release, content: "Some notes here")
+
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_content "My Release"
+ expect(response.body).to have_content "P: 5551234567"
+ expect(response.body).to have_content "jane.doe@test.com"
+ expect(response.body).to have_content "Some notes here"
+ expect(response.body).to have_content "Manage"
+ end
+
+ context "when there are no misc releases" do
+ it "renders an empty message" do
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_content("Misc Releases will appear here")
+ end
+ end
+
+ context "when there are many records" do
+ it "paginates the table" do
+ create_list(:misc_release, 20, project: project)
+
+ get :index, params: { project_id: project }
+
+ expect(response.body).to have_link("2", href: project_misc_releases_path(project, page: 2))
+ end
+ end
+
+ context "for xhr request" do
+ it "filters the releases by a query param" do
+ misc_releases = [
+ create(:misc_release, person_name: "Adam Sandler", project: project),
+ create(:misc_release, person_name: "Zoe Perry", project: project),
+ ]
+
+ get :index, params: { project_id: project, query: "Zoe" }, xhr: true
+
+ expect(response.body).not_to have_content("Adam Sandler")
+ expect(response.body).to have_content("Zoe Perry")
+ end
+ end
+ end
+
+ describe "#destroy" do
+ let!(:misc_release) { create(:misc_release, project: project) }
+
+ it "responds with redirect" do
+ delete :destroy, params: { project_id: project, id: misc_release }
+
+ expect(response).to be_redirect
+ expect(response).to redirect_to [project, :misc_releases]
+ end
+
+ it "sets the flash" do
+ delete :destroy, params: { project_id: project, id: misc_release }
+
+ expect(flash.alert).not_to be_nil
+ end
+
+ it "destroys the record" do
+ expect {
+ delete :destroy, params: { project_id: project, id: misc_release }
+ }.to change(MiscRelease, :count).by(-1)
+ end
+ end
+
+ private
+
+ def misc_release_params
+ attributes_for(:misc_release).merge(exploitable_rights_params)
+ end
+
+ def minor_misc_release_params
+ attributes_for(:misc_release, :minor_with_guardian_photo).merge(exploitable_rights_params)
+ end
+
+ def exploitable_rights_params
+ {
+ applicable_medium_id: ApplicableMedium.last.id,
+ applicable_medium_text: "applicable_media",
+ territory_id: Territory.last.id,
+ territory_text: "territory",
+ term_id: Term.last.id,
+ term_text: "term",
+ restriction_id: Restriction.last.id,
+ restriction_text: "restrictions",
+ }
+ end
+end
diff --git a/spec/controllers/password_resets_controller_spec.rb b/spec/controllers/password_resets_controller_spec.rb
index 48ebc3f..b664891 100644
--- a/spec/controllers/password_resets_controller_spec.rb
+++ b/spec/controllers/password_resets_controller_spec.rb
@@ -56,6 +56,16 @@ RSpec.describe PasswordResetsController, type: :controller do
expect(response.body).to have_content("Password Reset")
expect(response.body).to have_selector("input[name='password_reset[password]']")
end
+
+ context "when reset token is invalid" do
+ it "redirects to the sign in page" do
+ get :edit, params: { id: "bad token" }
+
+ expect(response).to be_redirect
+ expect(response).to redirect_to(new_session_path)
+ expect(flash.notice).to be_present
+ end
+ end
end
describe "#update" do
diff --git a/spec/controllers/public/appearance_releases_controller_spec.rb b/spec/controllers/public/appearance_releases_controller_spec.rb
index 3130922..7b2ecf2 100644
--- a/spec/controllers/public/appearance_releases_controller_spec.rb
+++ b/spec/controllers/public/appearance_releases_controller_spec.rb
@@ -31,7 +31,7 @@ describe Public::AppearanceReleasesController do
contract_template = create(:contract_template, project: project)
sign_in(user)
- post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, appearance_release: { person_address: "Albuquerque" } }
+ post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, appearance_release: { person_email: "email@email.com" } }
body = CGI.unescape_html(response.body)
expect(body).to match /Person first name can't be blank/
expect(body).to match /Person last name can't be blank/
@@ -120,7 +120,19 @@ describe Public::AppearanceReleasesController do
def minor_appearance_release_params(with_guardian_photo = true)
minor_type = with_guardian_photo ? :minor_with_guardian_photo : :minor
- attributes_for(:appearance_release, minor_type).merge(signature_param)
+ attributes_for(:appearance_release, minor_type)
+ .merge(signature_param, guardian_address_params)
+ end
+
+ def guardian_address_params
+ {
+ guardian_address_street1: "St1",
+ guardian_address_street2: "St2",
+ guardian_address_city: "City",
+ guardian_address_state: "State",
+ guardian_address_zip: "ZIP",
+ guardian_address_country: "Country"
+ }
end
def signature_param
diff --git a/spec/controllers/public/broadcasts_controller_spec.rb b/spec/controllers/public/broadcasts_controller_spec.rb
index ad10b87..8850bd7 100644
--- a/spec/controllers/public/broadcasts_controller_spec.rb
+++ b/spec/controllers/public/broadcasts_controller_spec.rb
@@ -92,6 +92,14 @@ RSpec.describe Public::BroadcastsController, type: :controller do
expect(broadcast.files.count).to eq(1)
expect(broadcast.files.first.filename).to eq("contract.pdf")
end
+
+ it "sends an update to the broadcasts channel" do
+ allow(BroadcastsChannel).to receive(:broadcast_file_upload_updates)
+
+ patch :update, params: { token: broadcast.token, broadcast: file_params }, xhr: true
+
+ expect(BroadcastsChannel).to have_received(:broadcast_file_upload_updates)
+ end
end
after do
diff --git a/spec/controllers/public/location_releases_controller_spec.rb b/spec/controllers/public/location_releases_controller_spec.rb
index 6a6a261..af10c12 100644
--- a/spec/controllers/public/location_releases_controller_spec.rb
+++ b/spec/controllers/public/location_releases_controller_spec.rb
@@ -7,6 +7,15 @@ describe Public::LocationReleasesController do
render_views
describe "#create" do
+ it "allows photos param" do
+ contract_template = create(:contract_template, project: project)
+
+ post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, location_release: location_release_params_with_photos }
+
+ expect(response).to be_successful
+ expect(LocationRelease.last.photos.attached?).to eq true
+ end
+
it "logs analytics" do
contract_template = create(:contract_template, project: project)
@@ -67,6 +76,10 @@ describe Public::LocationReleasesController do
attributes_for(:location_release, :native).except(:signature).merge(signature_param).merge(person_address_params)
end
+ def location_release_params_with_photos
+ attributes_for(:location_release, :native, :with_photo).except(:signature).merge(signature_param)
+ end
+
def person_address_params
{
person_address_street1: "123 Broadway",
diff --git a/spec/controllers/public/material_releases_controller_spec.rb b/spec/controllers/public/material_releases_controller_spec.rb
index 1ada22f..6ab78be 100644
--- a/spec/controllers/public/material_releases_controller_spec.rb
+++ b/spec/controllers/public/material_releases_controller_spec.rb
@@ -7,6 +7,15 @@ describe Public::MaterialReleasesController do
render_views
describe "#create" do
+ it "allows photos param" do
+ contract_template = create(:contract_template, project: project)
+
+ post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, material_release: material_release_params_with_photos }
+
+ expect(response).to be_successful
+ expect(MaterialRelease.last.photos.attached?).to eq true
+ end
+
it "logs analytics" do
contract_template = create(:contract_template, project: project)
@@ -65,6 +74,11 @@ describe Public::MaterialReleasesController do
attributes_for(:material_release, :native).except(:signature).merge(signature_param)
end
+ def material_release_params_with_photos
+ attributes_for(:material_release, :native, :with_photo).except(:signature).merge(signature_param)
+ end
+
+
def signature_param
file = file_fixture("signature.png")
data_uri = Base64Image.from_image(file).data_uri
diff --git a/spec/controllers/public/medical_releases_controller_spec.rb b/spec/controllers/public/medical_releases_controller_spec.rb
new file mode 100644
index 0000000..794bdb2
--- /dev/null
+++ b/spec/controllers/public/medical_releases_controller_spec.rb
@@ -0,0 +1,71 @@
+require "rails_helper"
+
+RSpec.describe Public::MedicalReleasesController, type: :controller do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, account: user.primary_account) }
+
+ render_views
+
+ describe "#create" do
+ it "logs analytics" do
+ contract_template = create(:contract_template, project: project)
+
+ expect {
+ post :create, params: { account_id: project.account.to_param, project_id: project, contract_template_id: contract_template, medical_release: medical_release_params }
+ }.to(
+ have_enqueued_job(TrackAnalyticsJob)
+ .with(nil, nil, :track_create_native_release, release_type: "MedicalRelease", account: project.account, user_agent: "Rails Testing", user_ip: "0.0.0.0")
+ )
+ end
+
+ it "displays validation errors" do
+ contract_template = create(:contract_template, project: project)
+ sign_in(user)
+
+ post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, medical_release: { person_address_city: "Albuquerque" } }
+ body = CGI.unescape_html(response.body)
+ expect(body).to match /Person first name can't be blank/
+ expect(body).to match /Person last name can't be blank/
+ expect(body).to match />can't be blank
+ end
+
+ it "responds with success " do
+ contract_template = create(:contract_template, project: project)
+
+ post :create, params: { account_id: user.primary_account.to_param, project_id: project, contract_template_id: contract_template, medical_release: medical_release_params }
+
+ expect(response).to be_successful
+ end
+
+ it "runs attach contract to releasable job" do
+ contract_template = create(:contract_template, project: project)
+
+ expect {
+ post :create, params: { account_id: project.account.to_param, project_id: project, contract_template_id: contract_template, medical_release: medical_release_params }
+ }.to(
+ have_enqueued_job(AttachContractToReleasableJob)
+ .with(MedicalRelease.last)
+ )
+ end
+ end
+
+ private
+
+ def medical_release_params
+ attributes_for(:medical_release, :native).except(:signature).merge(signature_param, photos_param)
+ end
+
+ def photos_param
+ path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
+ photo = Rack::Test::UploadedFile.new(path, "image/png")
+
+ { photos: [photo] }
+ end
+
+ def signature_param
+ file = file_fixture("signature.png")
+ data_uri = Base64Image.from_image(file).data_uri
+
+ { signature_base64: data_uri }
+ end
+end
diff --git a/spec/controllers/public/zoom_meetings_controller_spec.rb b/spec/controllers/public/zoom_meetings_controller_spec.rb
index d19c387..61f5a1c 100644
--- a/spec/controllers/public/zoom_meetings_controller_spec.rb
+++ b/spec/controllers/public/zoom_meetings_controller_spec.rb
@@ -1,5 +1,4 @@
require 'rails_helper'
-require 'zoom_gateway'
RSpec.describe Public::ZoomMeetingsController, type: :controller do
let(:user) { create(:user) }
diff --git a/spec/controllers/zoom_meetings_controller_spec.rb b/spec/controllers/zoom_meetings_controller_spec.rb
index 2048f4d..ca1ab04 100644
--- a/spec/controllers/zoom_meetings_controller_spec.rb
+++ b/spec/controllers/zoom_meetings_controller_spec.rb
@@ -1,5 +1,4 @@
require 'rails_helper'
-require 'zoom_gateway'
RSpec.describe ZoomMeetingsController, type: :controller do
let(:user) { create(:user) }
diff --git a/spec/controllers/zoom_notifications_controller_spec..rb b/spec/controllers/zoom_notifications_controller_spec..rb
deleted file mode 100644
index c8d48ea..0000000
--- a/spec/controllers/zoom_notifications_controller_spec..rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require "rails_helper"
-
-RSpec.describe ZoomNotificationsController, type: :controller do
- render_views
-
- let!(:zoom_meeting) { create(:zoom_meeting, api_meeting_id: 'meeting_id') }
-
- let(:started_status) { {event: 'meeting.started', payload: {object: {id: 'meeting_id' }}} }
- let(:ended_status) { {event: 'meeting.ended', payload: {object: {id: 'meeting_id' }}} }
- let(:wrong_meeting_id) { {payload: {object: {id: 'wrong_id' }}} }
-
- let(:authorization_header) { {'Authorization' => 'xxx-xxx-xxx'} }
- let(:wrong_authorization_header) { {'Authorization' => 'yyy-yyy-yyy'} }
-
- before do
- allow(ENV).to receive(:[]).with('ZOOM_VERIFICATION_TOKEN').and_return('xxx-xxx-xxx')
- end
-
- describe '#create' do
- context 'with no authorization key' do
- it 'raises 403 response' do
- post :create, params: started_status
- expect(response).to have_http_status(403)
- end
- end
-
- context 'with wrong authorization key' do
- it 'raises 403 response' do
- request.headers.merge!(wrong_authorization_header)
- post :create, params: started_status
- expect(response).to have_http_status(403)
- end
- end
-
- context 'authorized' do
- before do
- request.headers.merge!(authorization_header)
- end
-
- context 'with wrong meeting id' do
- it 'raises RecordNotFound' do
- expect {
- post :create, params: wrong_meeting_id
- }.to raise_error(ActiveRecord::RecordNotFound)
- end
- end
-
- context 'with right meeting id' do
- it 'responds with 200' do
- post :create, params: started_status
-
- expect(response).to have_http_status(200)
- end
-
- it 'assigns the zoom meeting' do
- post :create, params: started_status
-
- expect(assigns(:zoom_meeting)).to eq(zoom_meeting)
- end
-
- it 'updates the zoom_meeting when started status is received in notification' do
- post :create, params: started_status
-
- expect(zoom_meeting.reload).to be_started
- end
-
- it 'updates the zoom_meeting when ended status is received in notification' do
- post :create, params: ended_status
-
- expect(zoom_meeting.reload).to be_ended
- end
- end
- end
- end
-end
diff --git a/spec/controllers/zoom_notifications_controller_spec.rb b/spec/controllers/zoom_notifications_controller_spec.rb
new file mode 100644
index 0000000..01eb0cb
--- /dev/null
+++ b/spec/controllers/zoom_notifications_controller_spec.rb
@@ -0,0 +1,101 @@
+require "rails_helper"
+
+RSpec.describe ZoomNotificationsController, type: :controller do
+ render_views
+
+ let!(:zoom_meeting) { create(:zoom_meeting, api_meeting_id: 'meeting_id') }
+
+ let(:started_status) { {event: 'meeting.started', payload: {object: {id: 'meeting_id' }}} }
+ let(:ended_status) { {event: 'meeting.ended', payload: {object: {id: 'meeting_id' }}} }
+ let(:wrong_meeting_id) { {event: 'meeting.started', payload: {object: {id: 'wrong_id' }}} }
+
+ let(:recording_complete) { {event: 'recording.completed', payload: {object: {id: 'meeting_id', recording_files: [Object.new]}}} }
+
+ let(:authorization_header) { {'Authorization' => 'xxx-xxx-xxx'} }
+ let(:wrong_authorization_header) { {'Authorization' => 'yyy-yyy-yyy'} }
+
+ before do
+ allow(ENV).to receive(:[]).with('ZOOM_VERIFICATION_TOKEN').and_return('xxx-xxx-xxx')
+ end
+
+ describe '#create' do
+ context 'with no authorization key' do
+ it 'raises 403 response' do
+ post :create, params: started_status
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context 'with wrong authorization key' do
+ it 'raises 403 response' do
+ request.headers.merge!(wrong_authorization_header)
+ post :create, params: started_status
+ expect(response).to have_http_status(403)
+ end
+ end
+
+ context 'authorized' do
+ before do
+ request.headers.merge!(authorization_header)
+ end
+
+ context 'user hooks' do
+ before(:each) { ZoomUser.create api_id: 'zoom_user_id' }
+
+ it 'deletes the user from db if user.deleted is passed with existing user id' do
+ expect {
+ post :create, params: {event: 'user.deleted', payload: {object: {id: 'zoom_user_id'}}}
+ }.to change { ZoomUser.count }.by(-1)
+ end
+
+ it 'does not do anything if user.deleted is passed with non-existing user' do
+ expect {
+ post :create, params: {event: 'user.deleted', payload: {object: {id: 'wrong-user-id'}}}
+ }.not_to change { ZoomUser.count }
+ end
+ end
+
+ context 'meeting hooks' do
+ context 'with wrong meeting id' do
+ it 'raises RecordNotFound' do
+ expect {
+ post :create, params: wrong_meeting_id
+ }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
+ context 'with right meeting id' do
+ it 'responds with 200' do
+ post :create, params: started_status
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'assigns the zoom meeting' do
+ post :create, params: started_status
+
+ expect(assigns(:zoom_meeting)).to eq(zoom_meeting)
+ end
+
+ it 'updates the zoom_meeting when started status is received in notification' do
+ post :create, params: started_status
+
+ expect(zoom_meeting.reload).to be_started
+ end
+
+ it 'updates the zoom_meeting when ended status is received in notification' do
+ post :create, params: ended_status
+
+ expect(zoom_meeting.reload).to be_ended
+ end
+
+ it 'updates the recording when recording complete notification is received' do
+ expect(AttachRecordingToZoomMeetingJob).to receive(:perform_later)
+
+ post :create, params: recording_complete
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/factories/appearance_releases.rb b/spec/factories/appearance_releases.rb
index fa39d2c..c656d74 100644
--- a/spec/factories/appearance_releases.rb
+++ b/spec/factories/appearance_releases.rb
@@ -11,7 +11,12 @@ FactoryBot.define do
end
trait :native do
- person_address "100 Test Lane, New York, NY 10001"
+ person_address_street1 "St1"
+ person_address_street2 "St2"
+ person_address_city "City"
+ person_address_state "State"
+ person_address_zip "ZIP"
+ person_address_country "Country"
person_phone "123-555-6789"
signature do
@@ -31,16 +36,28 @@ FactoryBot.define do
minor true
guardian_first_name "Jamie"
guardian_last_name "Doe"
- guardian_address "100 Test Lane, New York, 10001"
+ guardian_address_street1 "St1"
+ guardian_address_street2 "St2"
+ guardian_address_city "City"
+ guardian_address_state "State"
+ guardian_address_zip "ZIP"
+ guardian_address_country "Country"
guardian_phone "123-555-1234"
+ guardian_email "guardian@galaxy.all"
end
trait :minor_with_guardian_photo do
minor true
guardian_first_name "Jamie"
guardian_last_name "Doe"
- guardian_address "100 Test Lane, New York, 10001"
guardian_phone "123-555-1234"
+ guardian_email "guardian@galaxy.all"
+ guardian_address_street1 "St1"
+ guardian_address_street2 "St2"
+ guardian_address_city "City"
+ guardian_address_state "State"
+ guardian_address_zip "ZIP"
+ guardian_address_country "Country"
guardian_photo do
path = Rails.root.join("spec", "fixtures", "files", "pratt.jpg")
Rack::Test::UploadedFile.new(path, "image/jpeg")
@@ -65,5 +82,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
diff --git a/spec/factories/contract_templates.rb b/spec/factories/contract_templates.rb
index 782bea9..8d90846 100644
--- a/spec/factories/contract_templates.rb
+++ b/spec/factories/contract_templates.rb
@@ -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
@@ -16,10 +20,18 @@ FactoryBot.define do
release_type "talent"
end
+ factory :medical_release_contract_template do
+ release_type "medical"
+ end
+
factory :material_release_contract_template do
release_type "material"
end
+ factory :misc_release_contract_template do
+ release_type "misc"
+ end
+
factory :location_release_contract_template do
release_type "location"
end
diff --git a/spec/factories/location_releases.rb b/spec/factories/location_releases.rb
index 3431b77..727ea50 100644
--- a/spec/factories/location_releases.rb
+++ b/spec/factories/location_releases.rb
@@ -15,6 +15,13 @@ FactoryBot.define do
end
end
+ trait :with_photo do
+ photos do
+ path = Rails.root.join("spec", "fixtures", "files", "location_photo.png")
+ [Rack::Test::UploadedFile.new(path, "image/png")]
+ end
+ end
+
trait :non_native do
contract do
path = Rails.root.join("spec", "fixtures", "files", "contract.pdf")
diff --git a/spec/factories/material_releases.rb b/spec/factories/material_releases.rb
index 9f6339a..d4ac6d5 100644
--- a/spec/factories/material_releases.rb
+++ b/spec/factories/material_releases.rb
@@ -15,6 +15,14 @@ FactoryBot.define do
end
end
+ trait :with_photo do
+ photos do
+ path = Rails.root.join("spec", "fixtures", "files", "material_photo.png")
+ [Rack::Test::UploadedFile.new(path, "image/png")]
+ end
+ end
+
+
trait :non_native do
contract do
path = Rails.root.join("spec", "fixtures", "files", "contract.pdf")
diff --git a/spec/factories/medical_releases.rb b/spec/factories/medical_releases.rb
new file mode 100644
index 0000000..7109fac
--- /dev/null
+++ b/spec/factories/medical_releases.rb
@@ -0,0 +1,47 @@
+FactoryBot.define do
+ factory :medical_release do
+ association :project
+
+ person_first_name "Jane"
+ person_last_name "Doe"
+
+ photos [Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "person_photo.png"), "image/png")]
+
+ trait :native do
+ person_phone "123-555-6789"
+
+ signature do
+ path = Rails.root.join("spec", "fixtures", "files", "signature.png")
+ Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+
+ trait :non_native do
+ contract do
+ path = Rails.root.join("spec", "fixtures", "files", "contract.pdf")
+ Rack::Test::UploadedFile.new(path, "application/pdf")
+ end
+ end
+
+ factory :medical_release_with_contract_template do
+ after(:build) do |medical_release, _|
+ medical_release.contract_template = build(:medical_release_contract_template)
+ end
+ end
+
+ factory :medical_release_with_contract_template_and_photos do
+ after(:build) do |medical_release, _|
+ medical_release.contract_template = build(:medical_release_contract_template)
+ path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
+ medical_release.photos.attach Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+
+ factory :medical_release_with_photo do
+ after(:build) do |medical_release, _|
+ path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
+ medical_release.photos.attach Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+ end
+end
diff --git a/spec/factories/misc_releases.rb b/spec/factories/misc_releases.rb
new file mode 100644
index 0000000..42096e8
--- /dev/null
+++ b/spec/factories/misc_releases.rb
@@ -0,0 +1,58 @@
+FactoryBot.define do
+ factory :misc_release do
+ association :project
+
+ person_first_name "Jane"
+ person_last_name "Doe"
+
+ photos [Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "person_photo.png"), "image/png")]
+
+ trait :native do
+ person_phone "123-555-6789"
+
+ signature do
+ path = Rails.root.join("spec", "fixtures", "files", "signature.png")
+ Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+
+ trait :minor do
+ minor true
+ guardian_first_name "Jamie"
+ guardian_last_name "Doe"
+ guardian_phone "123-555-1234"
+ end
+
+ trait :minor_with_guardian_photo do
+ minor true
+ guardian_first_name "Jamie"
+ guardian_last_name "Doe"
+ guardian_phone "123-555-1234"
+ guardian_photo do
+ path = Rails.root.join("spec", "fixtures", "files", "pratt.jpg")
+ Rack::Test::UploadedFile.new(path, "image/jpeg")
+ end
+ end
+
+ factory :misc_release_with_contract_template do
+ after(:build) do |misc_release, _|
+ misc_release.contract_template = build(:misc_release_contract_template)
+ end
+ end
+
+ factory :misc_release_with_contract_template_and_photos do
+ after(:build) do |misc_release, _|
+ misc_release.contract_template = build(:misc_release_contract_template)
+ path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
+ misc_release.photos.attach Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+
+ factory :misc_release_with_photo do
+ after(:build) do |misc_release, _|
+ path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
+ misc_release.photos.attach Rack::Test::UploadedFile.new(path, "image/png")
+ end
+ end
+ end
+end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index c720785..dcbe930 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -16,6 +16,7 @@ FactoryBot.define do
appearance_release: true,
location_release: true,
material_release: true,
+ medical_release: true,
music_release: true,
talent_release: true,
video_analysis: true,
diff --git a/spec/factories/zoom_users.rb b/spec/factories/zoom_users.rb
index 188b749..e3d569a 100644
--- a/spec/factories/zoom_users.rb
+++ b/spec/factories/zoom_users.rb
@@ -1,5 +1,8 @@
FactoryBot.define do
factory :zoom_user do
+ account_number ZoomGateway.ACCOUNT_NUMBER
+ trait ZoomGateway.USER_TYPE_NAME
+
trait :with_api_id do
api_id "api_user_id"
end
diff --git a/spec/features/user_creates_note_spec.rb b/spec/features/user_creates_note_spec.rb
index 9ab6ffa..0aed700 100644
--- a/spec/features/user_creates_note_spec.rb
+++ b/spec/features/user_creates_note_spec.rb
@@ -103,4 +103,16 @@ feature "User creates notes" do
it_behaves_like "a notable collection UI"
end
+
+ context "for medical releases" do
+ subject! { create(:medical_release, project: project, notes: []) }
+
+ it_behaves_like "a notable collection UI"
+ end
+
+ context "for misc releases" do
+ subject! { create(:misc_release, project: project, notes: []) }
+
+ it_behaves_like "a notable collection UI"
+ end
end
diff --git a/spec/features/user_creates_tags_spec.rb b/spec/features/user_creates_tags_spec.rb
index 028ee2c..2d02dc6 100644
--- a/spec/features/user_creates_tags_spec.rb
+++ b/spec/features/user_creates_tags_spec.rb
@@ -86,4 +86,16 @@ feature "User creates tags" do
it_behaves_like "a taggable collection UI"
end
+
+ context "for medical releases" do
+ subject! { create(:medical_release, project: project, tags: []) }
+
+ it_behaves_like "a taggable collection UI"
+ end
+
+ context "for misc releases" do
+ subject! { create(:misc_release, project: project, tags: []) }
+
+ it_behaves_like "a taggable collection UI"
+ end
end
diff --git a/spec/features/user_manages_contract_templates_spec.rb b/spec/features/user_manages_contract_templates_spec.rb
index 1af8733..094c8bd 100644
--- a/spec/features/user_manages_contract_templates_spec.rb
+++ b/spec/features/user_manages_contract_templates_spec.rb
@@ -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)
@@ -27,6 +28,18 @@ RSpec.feature 'User manages contract templates', type: :feature do
expect(page).to have_content('The release template has been created')
end
+ scenario 'medical release template has a guardian clause field' do
+ visit new_project_contract_template_path(project)
+
+ fill_in 'Name', with: 'My Release Template'
+ select 'Medical Release', from: 'Release type'
+ fill_hidden guardian_clause_field, with: 'Guardian clause text'
+ click_on 'Create Release Template'
+
+ expect(page).to have_content('The release template has been created')
+ expect(ContractTemplate.last.guardian_clause.body.to_s).to match /Guardian clause text/
+ end
+
scenario 'preview new talent release template without guardian clause' do
visit new_project_contract_template_path(project)
select 'Talent Release', from: 'Release type'
@@ -191,6 +204,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 +226,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 +246,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
diff --git a/spec/features/user_managing_acquired_media_releases_spec.rb b/spec/features/user_managing_acquired_media_releases_spec.rb
index b5832b3..267b955 100644
--- a/spec/features/user_managing_acquired_media_releases_spec.rb
+++ b/spec/features/user_managing_acquired_media_releases_spec.rb
@@ -5,6 +5,13 @@ feature "User managing acquired_media releases" do
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
context "when signed out" do
+ scenario "United States is default country" do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_acquired_media_release_path(project.account, project, contract_template)
+ expect(country_field_value).to eq "US"
+ end
+
scenario "creating a release", js: true do
contract_template = create(:contract_template, project: project)
@@ -13,13 +20,24 @@ feature "User managing acquired_media releases" do
by "filling out the form" do
fill_in acquired_media_name_field, with: "Jane Doe"
acquired_media_category_fields
+ fill_in acquried_media_description_field, with: "Description"
+ fill_in acquried_media_owner_first_name, with: "Jane"
+ fill_in acquried_media_owner_last_name, with: "Doe"
+ fill_in acquired_media_person_title, with: "Ms."
+ fill_in acquired_media_person_phone, with: "555-5555-5555"
+ fill_in acquired_media_person_email, with: "person@example.com"
+ fill_in acquired_media_person_fax, with: "FAX"
+ fill_in acquired_media_person_address_street_1, with: "Street 1"
+ fill_in acquired_media_person_address_city, with: "City"
+ fill_in acquired_media_person_address_state, with: "State"
+ fill_in acquired_media_release_person_address_zip, with: "ZIP"
draw_signature file_fixture("signature.png"), "acquired_media_release_signature_base64"
end
click_button "I have read and agree to the above"
- expect(AcquiredMediaRelease.last.categories).to include("Artwork")
+ expect(AcquiredMediaRelease.last.categories).to include("Video Footage")
expect(AcquiredMediaRelease.last.categories).to include("Still Photograph")
expect(page).to have_content("Your release was successfully submitted. Thank you.")
end
@@ -205,12 +223,60 @@ feature "User managing acquired_media releases" do
private
+ def country_field_value
+ find_field("acquired_media_release[person_address_country]").value
+ end
+
def acquired_media_name_field
"acquired_media_release[name]"
end
+ def acquried_media_description_field
+ "acquired_media_release[description]"
+ end
+
+ def acquried_media_owner_first_name
+ "acquired_media_release[person_first_name]"
+ end
+
+ def acquried_media_owner_last_name
+ "acquired_media_release[person_last_name]"
+ end
+
+ def acquired_media_person_title
+ "acquired_media_release[person_title]"
+ end
+
+ def acquired_media_person_phone
+ "acquired_media_release[person_phone]"
+ end
+
+ def acquired_media_person_email
+ "acquired_media_release[person_email]"
+ end
+
+ def acquired_media_person_fax
+ "acquired_media_release[person_fax]"
+ end
+
+ def acquired_media_person_address_street_1
+ "acquired_media_release[person_address_street1]"
+ end
+
+ def acquired_media_person_address_city
+ "acquired_media_release[person_address_city]"
+ end
+
+ def acquired_media_person_address_state
+ "acquired_media_release[person_address_state]"
+ end
+
+ def acquired_media_release_person_address_zip
+ "acquired_media_release[person_address_zip]"
+ end
+
def acquired_media_category_fields
- find(:css, "#acquired_media_release_categories_artwork").set(true)
+ find(:css, "#acquired_media_release_categories_video_footage").set(true)
find(:css, "#acquired_media_release_categories_still_photograph").set(true)
end
diff --git a/spec/features/user_managing_appearance_releases_spec.rb b/spec/features/user_managing_appearance_releases_spec.rb
index 28eeb2b..9335a0f 100644
--- a/spec/features/user_managing_appearance_releases_spec.rb
+++ b/spec/features/user_managing_appearance_releases_spec.rb
@@ -19,13 +19,13 @@ feature 'User managing appearance releases' do
fill_in person_first_name_field, with: 'Jane'
fill_in person_last_name_field, with: 'Doe'
- fill_in person_address_field, with: '123 Test Lane, New York, NY 10000'
+ fill_in_person_address_fields
fill_in person_phone_field, with: '555-555-5555'
fill_in person_email_field, with: 'jane.doe@test.com'
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,23 +45,88 @@ 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'
fill_in guardian_phone_field, with: '001101'
fill_in person_first_name_field, with: 'Jane'
fill_in person_last_name_field, with: 'Doe'
- fill_in person_address_field, with: '123 Test Lane, New York, NY 10000'
+ fill_in_person_address_fields
fill_in person_phone_field, with: '555-555-5555'
fill_in person_email_field, with: 'jane.doe@test.com'
fill_in person_date_of_birth, with: '01/01/1999'
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'
+ fill_in_guardian_address_fields
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
+ click_button submit_release_button
expect(page).to have_content(successful_submission_message)
end
+
+ scenario 'creating a release for a minor with two guardians', js: true do
+ allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: true))
+
+ project = create(:project, members: current_user, account: current_user.primary_account)
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_appearance_release_path(project.account, project, contract_template)
+
+ expect(page).to have_photo_button
+ expect(page).not_to have_content('SECOND GUARDIAN INFORMATION')
+ expect(page).not_to have_content('SECOND GUARDIAN PHOTO')
+
+ 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'
+
+ expect(page).to have_content 'SECOND GUARDIAN INFORMATION'
+ expect(page).to have_content 'SECOND GUARDIAN PHOTO'
+ expect(page).to have_content 'Guardian 2 Email'
+ expect(page).to have_content 'Guardian 2 Phone'
+ expect(page).to have_content 'Guardian 2 Address'
+
+ fill_in guardian_first_name_field, with: 'Guardian'
+ fill_in guardian_last_name_field, with: 'Name'
+ fill_in guardian_phone_field, with: '001101'
+ fill_in person_first_name_field, with: 'Jane'
+ fill_in person_last_name_field, with: 'Doe'
+ fill_in_person_address_fields
+ fill_in person_phone_field, with: '555-555-5555'
+ fill_in person_email_field, with: 'jane.doe@test.com'
+ fill_in person_date_of_birth, with: '01/01/1999'
+ 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'
+
+ 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'
+ fill_in_guardian_address_fields
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
+
+ fill_in guardian_2_first_name_field, with: 'Second'
+ fill_in guardian_2_last_name_field, with: 'Guardian'
+ fill_in guardian_2_phone_field, with: '999'
+
+ click_button submit_release_button
+
+ expect(page).to have_content(successful_submission_message)
+ expect(AppearanceRelease.last.guardian_2_first_name).to eq 'Second'
+ end
end
context 'when signed in' do
@@ -129,49 +194,48 @@ feature 'User managing appearance releases' do
expect(page).to have_content 'New Jane'
end
+ scenario 'user can enter information for second guardian when editing non native release for minor', js: true do
+ appearance_release = create(:appearance_release, :non_native, :minor, project: project)
+
+ visit edit_appearance_release_path(appearance_release)
+
+ expect(page).to have_content guardian_2_first_name_field.titleize
+ expect(page).to have_content guardian_2_photo_heading
+
+ fill_in guardian_first_name_field, with: 'Guardian'
+ fill_in guardian_last_name_field, with: 'Name'
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+
+ fill_in guardian_2_first_name_field, with: 'Second'
+ fill_in guardian_2_last_name_field, with: 'guardian'
+ attach_file guardian_2_photo_field, file_fixture('person_photo.png'), visible: :all
+
+ click_button submit_update_button
+
+ expect(page).to have_content successful_update_message
+ expect(AppearanceRelease.last.guardian_2_photo.attached?).to eq true
+ 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 +313,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 +327,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 +344,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 +491,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
@@ -458,6 +531,18 @@ feature 'User managing appearance releases' do
'appearance_release_minor'
end
+ def guardian_2_first_name_field
+ 'Guardian 2 first name'
+ end
+
+ def guardian_2_last_name_field
+ 'Guardian 2 last name'
+ end
+
+ def guardian_2_phone_field
+ 'Guardian 2 phone'
+ end
+
def guardian_first_name_field
'Guardian first name'
end
@@ -470,24 +555,74 @@ feature 'User managing appearance releases' do
'Guardian phone'
end
+ def guardian_email_field
+ 'Guardian email'
+ end
+
+ def guardian_address_street1_field
+ t('helpers.label.appearance_release.guardian_address_street1')
+ end
+
+ def guardian_address_city_field
+ t('helpers.label.appearance_release.guardian_address_city')
+ end
+
+ def guardian_address_state_field
+ t('helpers.label.appearance_release.guardian_address_state')
+ end
+
+ def guardian_address_zip_field
+ t('helpers.label.appearance_release.guardian_address_zip')
+ end
+
def guardian_photo_field
'appearance_release[guardian_photo]'
end
+ def guardian_2_photo_field
+ 'appearance_release[guardian_2_photo]'
+ end
+
def person_name_field
t('helpers.label.appearance_release.person_name')
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
- t('helpers.label.appearance_release.person_address')
+ def fill_in_person_address_fields
+ fill_in person_address_street1_field, with: "123 Test Lane"
+ fill_in person_address_city_field, with: "New York"
+ fill_in person_address_state_field, with: "NY"
+ fill_in person_address_zip_field, with: '1000'
+ end
+
+ def fill_in_guardian_address_fields
+ fill_in guardian_address_street1_field, with: "124 Test Lane"
+ fill_in guardian_address_city_field, with: "New York"
+ fill_in guardian_address_state_field, with: "NY"
+ fill_in guardian_address_zip_field, with: '1000'
+ end
+
+ def person_address_street1_field
+ t('helpers.label.appearance_release.person_address_street1')
+ end
+
+ def person_address_city_field
+ t('helpers.label.appearance_release.person_address_city')
+ end
+
+ def person_address_state_field
+ t('helpers.label.appearance_release.person_address_state')
+ end
+
+ def person_address_zip_field
+ t('helpers.label.appearance_release.person_address_zip')
end
def person_email_field
@@ -518,6 +653,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
@@ -549,4 +688,12 @@ feature 'User managing appearance releases' do
def successful_destroy_message
'The release has been deleted'
end
+
+ def guardian_photo_heading
+ t 'appearance_releases.form.photos.guardian_photo.heading'
+ end
+
+ def guardian_2_photo_heading
+ t 'appearance_releases.form.photos.guardian_2_photo.heading'
+ end
end
diff --git a/spec/features/user_managing_broadcasts_spec.rb b/spec/features/user_managing_broadcasts_spec.rb
index 5414351..318697b 100644
--- a/spec/features/user_managing_broadcasts_spec.rb
+++ b/spec/features/user_managing_broadcasts_spec.rb
@@ -1,83 +1,154 @@
-require "rails_helper"
+# frozen_string_literal: true
-feature "User managing broadcasts" do
+require 'rails_helper'
+
+feature 'User managing broadcasts' do
let(:current_user) { create(:user, :manager) }
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
- context "managing broadcasts" do
+ context 'managing broadcasts' do
before do
sign_in current_user
- allow(MuxLiveStream).to receive(:new).and_return(double(id: "id", key: "key", playback_id: "playback_id"))
+ allow(MuxLiveStream).to receive(:new).and_return(double(id: 'id', key: 'key', playback_id: 'playback_id'))
end
- scenario "creating and deleting a broadcast", js: true do
+ scenario 'creating and deleting a broadcast', js: true do
visit new_project_broadcast_path(project)
- by "filling out the form" do
- fill_in broadcast_name_field, with: "My Broadcast"
+ by 'filling out the form' do
+ fill_in broadcast_name_field, with: 'My Broadcast'
end
- click_button "Create Live Stream"
- expect(page).to have_content("A live stream has been created")
- click_on "Manage"
- expect(page).to have_link("Copy Stream URL", exact: true)
- expect(page).to have_link("Copy Stream Key", exact: true)
- expect(page).to have_link("View", exact: true)
- expect(page).to have_link("Delete", exact: true)
+ click_button 'Create Live Stream'
+ expect(page).to have_content('A live stream has been created')
+ click_on 'Manage'
+ expect(page).to have_link('Copy Stream URL', exact: true)
+ expect(page).to have_link('Copy Stream Key', exact: true)
+ expect(page).to have_link('View', exact: true)
+ expect(page).to have_link('Delete', exact: true)
- it_also "Deletes the broadcast" do
+ it_also 'Deletes the broadcast' do
allow_any_instance_of(Broadcast).to receive(:destroy_mux_live_stream).and_return(true)
accept_alert do
- click_link "Delete"
+ click_link 'Delete'
end
-
- expect(page).to have_content("A live stream has been deleted")
- expect(page).not_to have_content("My Broadcast")
+
+ expect(page).to have_content('A live stream has been deleted')
+ expect(page).not_to have_content('My Broadcast')
end
end
- scenario "visit show page of broadcast", js: true do
+ scenario 'visit show page of broadcast', js: true do
broadcast = create(:broadcast, :with_stream, :with_files, project: project)
recording = create(:broadcast_recording, broadcast: broadcast)
-
+
visit project_broadcast_path(project, broadcast)
- expect(page).to have_content("Live stream is waiting to begin.")
- expect(page).to have_content("Copy URL")
-
- click_on "Files"
- expect(page).to have_content("contract.pdf")
+ expect(page).to have_content('Live stream is waiting to begin.')
+ expect(page).to have_content('Copy URL')
- click_on "Previous Sessions"
+ within '#files' do
+ expect(page).to have_content('contract.pdf')
+ end
+
+ click_on 'Previous Sessions'
expect(page).to have_content(recording.download_file_name)
end
- scenario "visit multi-view broadcast page", js: true do
- broadcasts = create_list(:broadcast, 4, :with_stream, project: project)
-
+ scenario 'user can go back and forth between live session and previous sessions', js: true do
+ broadcast = create(:broadcast, :with_stream, :with_files, project: project)
+ recording = create(:broadcast_recording, broadcast: broadcast)
+
+ visit project_broadcast_path(project, broadcast)
+
+ expect(page).to have_content broadcast.name.titleize, count: 1
+ expect(page).to have_content recording.download_file_name, count: 0
+
+ click_on switch_view_dropdown
+ expect(page).to have_content broadcast.name.titleize, count: 2
+ expect(page).to have_content recording.download_file_name, count: 1
+
+ live_stream_nav_item = page.find('.dropdown-item', text: broadcast.name.titleize)
+ recording_nav_item = page.find('.dropdown-item', text: recording.download_file_name)
+
+ expect(live_stream_nav_item[:class].include?('active')).to eq true
+ expect(recording_nav_item[:class].include?('active')).to eq false
+
+ click_on recording.download_file_name
+
+ expect(page).to have_content broadcast.name.titleize, count: 1
+ expect(page).to have_content recording.download_file_name, count: 0
+ expect(live_stream_nav_item[:class].include?('active')).to eq false
+ expect(recording_nav_item[:class].include?('active')).to eq true
+
+ click_on switch_view_dropdown
+ click_on broadcast.name.titleize
+
+ expect(page).to have_content broadcast.name.titleize, count: 1
+ expect(page).to have_content recording.download_file_name, count: 0
+
+ # Page is reloaded, we need to get dropdown items again
+ live_stream_nav_item = page.find('.dropdown-item', text: broadcast.name.titleize, visible: :all)
+ recording_nav_item = page.find('.dropdown-item', text: recording.download_file_name, visible: :all)
+
+ expect(live_stream_nav_item[:class].include?('active')).to eq true
+ expect(recording_nav_item[:class].include?('active')).to eq false
+ end
+
+ scenario 'form will not submit if user clicks Add files without selected files', js: true do
+ broadcast = create(:broadcast, :with_stream, :with_files, project: project)
+
+ visit project_broadcast_path(project, broadcast)
+
+ expect(page).to have_content('Live stream is waiting to begin.')
+ expect(page).to have_content add_file_button
+
+ click_on add_file_button
+ end
+
+ scenario 'visit multi-view broadcast page', js: true do
+ broadcast_one = create(:broadcast, :with_stream, :with_files, name: 'Broadcast 1', project: project)
+ broadcast_two = create(:broadcast, :with_stream, :with_files, name: 'Broadcast 2', project: project)
+
visit project_broadcasts_path(project)
click_checkboxes
-
- new_window = window_opened_by { click_link "Multi-View" }
- within_window new_window do
- expect(page).to have_content("Switch View")
- click_on "Switch View"
- expect(page).to have_link(broadcasts.first.name)
- expect(page).to have_link(broadcasts.second.name)
- end
+ new_window = window_opened_by { click_link 'Multi-View' }
+ within_window new_window do
+ expect(page).to have_content switch_view_dropdown
+
+ click_on switch_view_dropdown
+ expect(page).to have_link('Broadcast 1')
+ expect(page).to have_link('Broadcast 2')
+
+ within '#files' do
+ click_on 'Broadcast 1'
+ expect(page).to have_content('contract.pdf')
+
+ click_on 'Broadcast 2'
+ expect(page).to have_content('contract.pdf')
+ end
+ end
end
end
private
+ def add_file_button
+ 'Add File'
+ end
+
def broadcast_name_field
- "broadcast[name]"
+ 'broadcast[name]'
end
def click_checkboxes
+ all('input[type="checkbox"]')[0].click
all('input[type="checkbox"]')[1].click
- all('input[type="checkbox"]')[2].click
+ end
+
+ def switch_view_dropdown
+ 'Switch View'
end
end
diff --git a/spec/features/user_managing_location_releases_spec.rb b/spec/features/user_managing_location_releases_spec.rb
index 8a2c916..d10bb8e 100644
--- a/spec/features/user_managing_location_releases_spec.rb
+++ b/spec/features/user_managing_location_releases_spec.rb
@@ -5,25 +5,72 @@ feature "User managing location releases" do
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
context "when signed out" do
- scenario "creating a release", js: true do
+ scenario "United States is default country" do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_location_release_path(project.account, project, contract_template)
+ expect(country_field_value).to eq "US"
+ end
+
+ scenario "creating a release without photos", js: true do
contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_location_release_path(project.account, project, contract_template)
by "filling out the form" do
fill_in location_name_field, with: "Benny's Burritos"
+ fill_in location_address_street_1, with: "Location's street address"
+ fill_in location_address_city, with: "Location's city"
+ fill_in location_address_state, with: "Location's state"
+ fill_in location_address_zip, with: "Location's zip"
fill_in person_first_name_field, with: "Jane"
fill_in person_last_name_field, with: "Doe"
fill_in person_phone_field, with: "555-555-5555"
fill_in person_email_field, with: "jane.doe@test.com"
+ fill_in person_company_field, with: "BIG"
+ fill_in person_title_field, with: "Ms."
fill_in person_address_street1_field, with: "100 Broadway"
+ fill_in person_address_city, with: "Person's City"
+ fill_in person_address_state, with: "Person's State"
+ fill_in person_address_zip, with: "Person's Zip"
+ fill_in filming_hours_field, with: "04:00 - 22:00"
draw_signature file_fixture("signature.png"), "location_release_signature_base64"
end
- click_button "I have read and agree to the above"
+ click_button submit_release_button
expect(page).to have_content("Your release was successfully submitted. Thank you.")
end
+
+ scenario "creating a release with photos", js: true do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_location_release_path(project.account, project, contract_template)
+
+ fill_in location_name_field, with: "Benny's Burritos"
+ fill_in location_address_street_1, with: "Location's street address"
+ fill_in location_address_city, with: "Location's city"
+ fill_in location_address_state, with: "Location's state"
+ fill_in location_address_zip, with: "Location's zip"
+ fill_in person_first_name_field, with: "Jane"
+ fill_in person_last_name_field, with: "Doe"
+ fill_in person_phone_field, with: "555-555-5555"
+ fill_in person_email_field, with: "jane.doe@test.com"
+ fill_in person_company_field, with: "BIG"
+ fill_in person_title_field, with: "Ms."
+ fill_in person_address_street1_field, with: "100 Broadway"
+ fill_in person_address_city, with: "Person's City"
+ fill_in person_address_state, with: "Person's State"
+ fill_in person_address_zip, with: "Person's Zip"
+ fill_in filming_hours_field, with: "04:00 - 22:00"
+ draw_signature file_fixture("signature.png"), "location_release_signature_base64"
+
+ drop_file Rails.root.join(file_fixture("location_photo.png")), type: :dropzone
+ click_button submit_release_button
+
+ expect(page).to have_content("Your release was successfully submitted. Thank you.")
+ expect(LocationRelease.last.photos.attached?).to eq true
+ end
end
context "when signed in" do
@@ -51,6 +98,7 @@ feature "User managing location releases" do
by "filling out the remaining information" do
fill_in_release_fields name: "Test Location Release"
+ fill_in filming_hours_field, with: "04:00 - 22:00"
click_button create_release_button
expect(page).to have_content(create_release_notice)
expect(page).to have_photo("location_photo.png")
@@ -136,6 +184,7 @@ feature "User managing location releases" do
:native,
project: project,
name: "Benny's Burritos",
+ filming_hours: "06:00 - 20:00",
tag_list: "Restaurant",
notes: [
build(:note,
@@ -172,6 +221,8 @@ feature "User managing location releases" do
expect(pdf_body).to have_content("Restaurant")
expect(pdf_body).to have_content photos_heading.upcase
expect(pdf_body).to have_content("location_photo.png")
+ expect(pdf_body).to have_content("Filming Hours")
+ expect(pdf_body).to have_content("06:00 - 20:00")
end
context "when the user is associate" do
@@ -190,6 +241,10 @@ feature "User managing location releases" do
private
+ def country_field_value
+ find_field("location_release[person_address_country]").value
+ end
+
def photos_heading(photos_count = 1)
t 'contracts.photos.heading', count: photos_count
end
@@ -198,6 +253,22 @@ feature "User managing location releases" do
"location_release[name]"
end
+ def location_address_street_1
+ "location_release[address_street1]"
+ end
+
+ def location_address_city
+ "location_release[address_city]"
+ end
+
+ def location_address_state
+ "location_release[address_state]"
+ end
+
+ def location_address_zip
+ "location_release[address_zip]"
+ end
+
def contract_field
"location_release[contract]"
end
@@ -210,18 +281,42 @@ feature "User managing location releases" do
"location_release[person_last_name]"
end
- def person_email_field
- "location_release[person_email]"
- end
-
def person_address_street1_field
"location_release[person_address_street1]"
end
+ def person_address_city
+ "location_release[person_address_city]"
+ end
+
+ def person_address_state
+ "location_release[person_address_state]"
+ end
+
+ def person_address_zip
+ "location_release[person_address_zip]"
+ end
+
def person_phone_field
"location_release[person_phone]"
end
+ def person_email_field
+ "location_release[person_email]"
+ end
+
+ def person_company_field
+ "location_release[person_company]"
+ end
+
+ def person_title_field
+ "location_release[person_title]"
+ end
+
+ def filming_hours_field
+ "location_release[filming_hours]"
+ end
+
def have_photo(filename, attr: "src")
have_selector("img[#{attr}*='#{filename}']")
end
@@ -246,6 +341,10 @@ feature "User managing location releases" do
t "helpers.submit.location_release.create"
end
+ def submit_release_button
+ t("shared.submit_release_long")
+ end
+
def create_release_notice
t "location_releases.create.notice"
end
diff --git a/spec/features/user_managing_material_releases_spec.rb b/spec/features/user_managing_material_releases_spec.rb
index 6a6e486..1f966b2 100644
--- a/spec/features/user_managing_material_releases_spec.rb
+++ b/spec/features/user_managing_material_releases_spec.rb
@@ -5,21 +5,84 @@ feature "User managing material releases" do
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
context "when signed out" do
- scenario "creating a release", js: true do
+ scenario "United States is default country" do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_material_release_path(project.account, project, contract_template)
+ expect(country_field_value).to eq "US"
+ end
+
+ scenario "creating a release without photos", js: true do
contract_template = create(:contract_template, project: project)
visit new_account_project_contract_template_material_release_path(project.account, project, contract_template)
- by "filling out the form" do
- fill_in material_name_field, with: "Pepsi Logo"
- fill_in person_first_name_field, with: "Jane"
- fill_in person_last_name_field, with: "Doe"
- draw_signature file_fixture("signature.png"), "material_release_signature_base64"
- end
+ fill_all_fields
+ draw_signature file_fixture("signature.png"), "material_release_signature_base64"
- click_button "I have read and agree to the above"
+ click_button submit_release_button
- expect(page).to have_content("Your release was successfully submitted. Thank you.")
+ expect(page).to have_content success_submit_message
+ end
+
+ scenario "creating a release with photos", js: true do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_material_release_path(project.account, project, contract_template)
+
+ fill_all_fields
+ draw_signature file_fixture("signature.png"), "material_release_signature_base64"
+ drop_file Rails.root.join(file_fixture("material_photo.png")), type: :dropzone
+
+ click_button submit_release_button
+
+ expect(page).to have_content success_submit_message
+ expect(MaterialRelease.last.photos.attached?).to eq true
+ end
+
+ scenario "creating release is possible only after filling all fields", js: true do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_material_release_path(project.account, project, contract_template)
+
+ fill_in material_name_field, with: "Pepsi Logo"
+ expect_failed_client_side_validation
+
+ fill_in material_description_field, with: "Description text"
+ expect_failed_client_side_validation
+
+ fill_in person_first_name_field, with: "Jane"
+ expect_failed_client_side_validation
+
+ fill_in person_last_name_field, with: "Doe"
+ expect_failed_client_side_validation
+
+ fill_in person_phone_field, with: "2229929229"
+ expect_failed_client_side_validation
+
+ fill_in person_email_field, with: "mail@mail.com"
+ expect_failed_client_side_validation
+
+ fill_in person_company_field, with: "Company"
+ expect_failed_client_side_validation
+
+ fill_in person_title_field, with: "Mr."
+ expect_failed_client_side_validation
+
+ fill_in person_address_street1_field, with: "Street 1 address"
+ expect_failed_client_side_validation
+
+ fill_in person_city_field, with: "City"
+ expect_failed_client_side_validation
+
+ fill_in person_state_field, with: "State"
+ expect_failed_client_side_validation
+
+ fill_in person_zip_field, with: "ZIP"
+ draw_signature file_fixture("signature.png"), "material_release_signature_base64"
+
+ click_button submit_release_button
+ expect(page).to have_content success_submit_message
end
end
@@ -180,6 +243,10 @@ feature "User managing material releases" do
private
+ def country_field_value
+ find_field("material_release[person_address_country]").value
+ end
+
def photos_heading(photos_count = 1)
t 'contracts.photos.heading', count: photos_count
end
@@ -188,6 +255,10 @@ feature "User managing material releases" do
"material_release[name]"
end
+ def material_description_field
+ "material_release[description]"
+ end
+
def person_first_name_field
"material_release[person_first_name]"
end
@@ -196,6 +267,38 @@ feature "User managing material releases" do
"material_release[person_last_name]"
end
+ def person_phone_field
+ "material_release[person_phone]"
+ end
+
+ def person_email_field
+ "material_release[person_email]"
+ end
+
+ def person_company_field
+ "material_release[person_company]"
+ end
+
+ def person_title_field
+ "material_release[person_title]"
+ end
+
+ def person_address_street1_field
+ "material_release[person_address_street1]"
+ end
+
+ def person_city_field
+ "material_release[person_address_city]"
+ end
+
+ def person_state_field
+ "material_release[person_address_state]"
+ end
+
+ def person_zip_field
+ "material_release[person_address_zip]"
+ end
+
def have_photo(filename)
have_selector("img[src*='#{filename}']")
end
@@ -224,6 +327,10 @@ feature "User managing material releases" do
t "helpers.submit.material_release.create"
end
+ def submit_release_button
+ t 'shared.submit_release_long'
+ end
+
def create_release_notice
t "material_releases.create.notice"
end
@@ -250,4 +357,29 @@ feature "User managing material releases" do
select "Other", from: "Restriction"
fill_in "Describe other restrictions", with: "Test"
end
+
+ def fill_all_fields
+ fill_in material_name_field, with: "Pepsi Logo"
+ fill_in material_description_field, with: "Description text"
+ fill_in person_first_name_field, with: "Jane"
+ fill_in person_last_name_field, with: "Doe"
+ fill_in person_phone_field, with: "2229929229"
+ fill_in person_email_field, with: "mail@mail.com"
+ fill_in person_company_field, with: "Company"
+ fill_in person_title_field, with: "Mr."
+ fill_in person_address_street1_field, with: "Street 1 address"
+ fill_in person_city_field, with: "City"
+ fill_in person_state_field, with: "State"
+ fill_in person_zip_field, with: "ZIP"
+ end
+
+ def success_submit_message
+ 'Your release was successfully submitted. Thank you.'
+ end
+
+ def expect_failed_client_side_validation
+ draw_signature file_fixture("signature.png"), "material_release_signature_base64"
+ click_button submit_release_button
+ expect(page).not_to have_content success_submit_message
+ end
end
diff --git a/spec/features/user_managing_medical_releases_spec.rb b/spec/features/user_managing_medical_releases_spec.rb
new file mode 100644
index 0000000..59510fb
--- /dev/null
+++ b/spec/features/user_managing_medical_releases_spec.rb
@@ -0,0 +1,399 @@
+require "rails_helper"
+
+feature "User managing medical releases" do
+ let(:current_user) { create(:user) }
+ let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
+
+ context "when signed out" do
+ scenario 'creating a release for an adult', js: true do
+ allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: true))
+
+ project = create(:project, members: current_user, account: current_user.primary_account)
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_medical_release_path(project.account, project, contract_template)
+
+ fill_in person_first_name_field, with: 'Jane'
+ fill_in person_last_name_field, with: 'Doe'
+ fill_in_person_address_fields
+ fill_in person_phone_field, with: '555-555-5555'
+ fill_in person_email_field, with: 'jane.doe@test.com'
+ drop_file Rails.root.join(file_fixture("person_photo.png")), type: :dropzone
+ draw_signature file_fixture("signature.png"), "medical_release_signature_base64"
+
+ expect do
+ click_button submit_release_button
+ end.to change(MedicalRelease, :count).by(1)
+
+ expect(page).to have_content(successful_submission_message)
+ end
+
+ scenario 'creating a release for a minor', js: true do
+ allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: true))
+
+ project = create(:project, members: current_user, account: current_user.primary_account)
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_medical_release_path(project.account, project, contract_template)
+
+ expect(page).not_to have_content guardian_information_heading.upcase
+ expect(page).not_to have_content guardian_photo_heading.upcase
+
+ page.check person_is_minor_checkbox
+ expect(page).to have_content guardian_information_heading.upcase
+ expect(page).to have_content guardian_photo_heading.upcase
+ expect(page).to have_content guardian_email_field.titleize
+
+ fill_in guardian_first_name_field, with: 'Guardian'
+ fill_in guardian_last_name_field, with: 'Name'
+ fill_in guardian_phone_field, with: '001101'
+ fill_in person_first_name_field, with: 'Jane'
+ fill_in person_last_name_field, with: 'Doe'
+ fill_in_person_address_fields
+ fill_in person_phone_field, with: '555-555-5555'
+ fill_in person_email_field, with: 'jane.doe@test.com'
+ drop_file Rails.root.join(file_fixture("person_photo.png")), type: :dropzone
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'medical_release_signature_base64'
+
+ fill_in guardian_email_field, with: 'invalid@email'
+ click_button submit_release_button
+ expect(page).to have_content email_validation_error_for('Guardian')
+
+ fill_in guardian_email_field, with: 'valid@email.com'
+ fill_in_guardian_address_fields
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'medical_release_signature_base64'
+ click_button submit_release_button
+
+ expect(page).to have_content(successful_submission_message)
+ end
+
+ scenario 'creating a release for a minor with two guardians', js: true do
+ allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: true))
+
+ project = create(:project, members: current_user, account: current_user.primary_account)
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_medical_release_path(project.account, project, contract_template)
+
+ expect(page).not_to have_content guardian_2_information_heading.upcase
+ expect(page).not_to have_content guardian_2_photo_heading.upcase
+
+ page.check person_is_minor_checkbox
+ expect(page).to have_content guardian_information_heading.upcase
+ expect(page).to have_content guardian_photo_heading.upcase
+ expect(page).to have_content guardian_email_field.titleize
+
+ expect(page).to have_content guardian_2_information_heading.upcase
+ expect(page).to have_content guardian_2_photo_heading.upcase
+ expect(page).to have_content guardian_2_email_field.titleize
+ expect(page).to have_content guardian_2_phone_field.titleize
+ expect(page).to have_content guardian_2_address_street1_field.titleize
+
+ fill_in guardian_first_name_field, with: 'Guardian'
+ fill_in guardian_last_name_field, with: 'Name'
+ fill_in guardian_phone_field, with: '001101'
+ fill_in person_first_name_field, with: 'Jane'
+ fill_in person_last_name_field, with: 'Doe'
+ fill_in_person_address_fields
+ fill_in person_phone_field, with: '555-555-5555'
+ fill_in person_email_field, with: 'jane.doe@test.com'
+ drop_file Rails.root.join(file_fixture("person_photo.png")), type: :dropzone
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'medical_release_signature_base64'
+
+ fill_in guardian_email_field, with: 'invalid@email'
+ click_button submit_release_button
+ expect(page).to have_content email_validation_error_for('Guardian')
+
+ fill_in guardian_email_field, with: 'valid@email.com'
+ fill_in_guardian_address_fields
+ attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
+ draw_signature file_fixture('signature.png'), 'medical_release_signature_base64'
+
+ fill_in guardian_2_first_name_field, with: 'Second'
+ fill_in guardian_2_last_name_field, with: 'Guardian'
+ fill_in guardian_2_phone_field, with: '999'
+
+ click_button submit_release_button
+
+ expect(page).to have_content(successful_submission_message)
+ expect(MedicalRelease.last.guardian_2_first_name).to eq 'Second'
+ end
+ end
+
+ context "when signed in as account manager" do
+ before do
+ sign_in current_user
+ end
+
+ scenario "Download All is visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).to have_content download_all_button
+ end
+
+ scenario "Download action in Manage menu is visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).to have_link("Download", exact: true, count: 2)
+ end
+
+ scenario "Downloading PDF of native medical release is possible" do
+ native_release = create(:medical_release_with_contract_template, :native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ click_link *view_release_pdf_link_for(native_release)
+ expect(content_type).to eq('application/pdf')
+ end
+ end
+
+ context "when the user is manager(project manager)" do
+ let(:current_user) { create(:user, :manager) }
+
+ before do
+ sign_in current_user
+ end
+
+ scenario "Download All is not visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).not_to have_content download_all_button
+ end
+
+ scenario "Download action in Manage menu is not visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).to have_link("Download", exact: true, count: 0)
+ end
+
+ scenario "Downloading PDF of native medical release is not possible" do
+ native_release = create(:medical_release_with_contract_template, :native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ link = medical_release_contracts_path(native_release, format: 'pdf')
+ expect { visit link }.to raise_exception Pundit::NotAuthorizedError
+ end
+
+ scenario "Downloading PDF of non native medical release is not possible" do
+ non_native_release = create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ link = medical_release_contracts_path(non_native_release, format: 'pdf')
+ expect { visit link }.to raise_exception Pundit::NotAuthorizedError
+ end
+ end
+
+ context "when the user is associate" do
+ let(:current_user) { create(:user, :associate) }
+
+ before do
+ sign_in current_user
+ end
+
+ scenario "Download All is not visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).not_to have_content download_all_button
+ end
+
+ scenario "Download action in Manage menu is not visible" do
+ create(:medical_release_with_contract_template, :native, project: project)
+ create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ expect(page).to have_link("Download", exact: true, count: 0)
+ end
+
+ scenario "Downloading PDF of native medical release is not possible" do
+ native_release = create(:medical_release_with_contract_template, :native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ link = medical_release_contracts_path(native_release, format: 'pdf')
+ expect { visit link }.to raise_exception Pundit::NotAuthorizedError
+ end
+
+ scenario "Downloading PDF of non native medical release is not possible" do
+ non_native_release = create(:medical_release_with_contract_template, :non_native, project: project)
+
+ visit project_medical_releases_path(project)
+
+ link = medical_release_contracts_path(non_native_release, format: 'pdf')
+ expect { visit link }.to raise_exception Pundit::NotAuthorizedError
+ end
+ end
+
+ private
+
+ def download_all_button
+ 'Download All'
+ end
+
+ def download_action
+ 'Download'
+ end
+
+ def manage_button
+ t 'medical_releases.medical_release.actions.manage'
+ end
+
+ def view_release_pdf_link_for(release)
+ ['Download', href: medical_release_contracts_path(release, format: 'pdf')]
+ end
+
+ def person_first_name_field
+ "medical_release[person_first_name]"
+ end
+
+ def person_last_name_field
+ "medical_release[person_last_name]"
+ end
+
+ def person_email_field
+ "medical_release[person_email]"
+ end
+
+ def person_phone_field
+ "medical_release[person_phone]"
+ end
+
+ def submit_release_button
+ t 'shared.submit_release_short'
+ end
+
+ def successful_submission_message
+ "Your release was successfully submitted. Thank you."
+ end
+
+ def fill_in_person_address_fields
+ fill_in person_address_street1_field, with: "123 Test Lane"
+ fill_in person_address_city_field, with: "New York"
+ fill_in person_address_state_field, with: "NY"
+ fill_in person_address_zip_field, with: '1000'
+ end
+
+ def fill_in_guardian_address_fields
+ fill_in guardian_address_street1_field, with: "124 Test Lane"
+ fill_in guardian_address_city_field, with: "New York"
+ fill_in guardian_address_state_field, with: "NY"
+ fill_in guardian_address_zip_field, with: '1000'
+ end
+
+ def person_address_street1_field
+ t('helpers.label.medical_release.person_address_street1')
+ end
+
+ def person_address_city_field
+ t('helpers.label.medical_release.person_address_city')
+ end
+
+ def person_address_state_field
+ t('helpers.label.medical_release.person_address_state')
+ end
+
+ def person_address_zip_field
+ t('helpers.label.medical_release.person_address_zip')
+ end
+
+
+ def guardian_first_name_field
+ t('helpers.label.medical_release.guardian_first_name')
+ end
+
+ def guardian_last_name_field
+ t('helpers.label.medical_release.guardian_last_name')
+ end
+
+ def guardian_phone_field
+ t('helpers.label.medical_release.guardian_phone')
+ end
+
+ def guardian_email_field
+ t('helpers.label.medical_release.guardian_email')
+ end
+
+ def guardian_address_street1_field
+ t('helpers.label.medical_release.guardian_address_street1')
+ end
+
+ def guardian_address_city_field
+ t('helpers.label.medical_release.guardian_address_city')
+ end
+
+ def guardian_address_state_field
+ t('helpers.label.medical_release.guardian_address_state')
+ end
+
+ def guardian_address_zip_field
+ t('helpers.label.medical_release.guardian_address_zip')
+ end
+
+ def guardian_photo_field
+ 'medical_release[guardian_photo]'
+ end
+
+ def person_is_minor_checkbox
+ 'medical_release_minor'
+ end
+
+ def guardian_2_first_name_field
+ t('helpers.label.medical_release.guardian_2_first_name')
+ end
+
+ def guardian_2_last_name_field
+ t('helpers.label.medical_release.guardian_2_last_name')
+ end
+
+ def guardian_2_phone_field
+ t('helpers.label.medical_release.guardian_2_phone')
+ end
+
+ def guardian_2_email_field
+ t('helpers.label.medical_release.guardian_2_email')
+ end
+
+ def guardian_2_address_street1_field
+ t('helpers.label.medical_release.guardian_2_address_street1')
+ end
+
+ def email_validation_error_for(prefix)
+ "#{prefix} email is not an email"
+ end
+
+ def guardian_photo_heading
+ t 'public.medical_releases.new.guardian_photo.heading'
+ end
+
+ def guardian_information_heading
+ t 'public.medical_releases.new.guardian_info.heading'
+ end
+
+ def guardian_2_photo_heading
+ t 'public.medical_releases.new.guardian_2_photo.heading'
+ end
+
+ def guardian_2_information_heading
+ t 'public.medical_releases.new.guardian_2_info.heading'
+ end
+end
diff --git a/spec/features/user_managing_misc_releases_spec.rb b/spec/features/user_managing_misc_releases_spec.rb
new file mode 100644
index 0000000..d2ae17e
--- /dev/null
+++ b/spec/features/user_managing_misc_releases_spec.rb
@@ -0,0 +1,55 @@
+require "rails_helper"
+
+feature "User managing misc releases" do
+ let(:current_user) { create(:user) }
+ let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
+
+ context "when signed in as account manager" do
+ before do
+ sign_in current_user
+ end
+
+ scenario "Download All is visible" do
+ create(:misc_release_with_contract_template, :native, project: project)
+
+ visit project_misc_releases_path(project)
+
+ expect(page).to have_content download_all_button
+ end
+
+ scenario "Downloading PDF of native misc release is possible" do
+ native_release = create(:misc_release_with_contract_template, :native, project: project)
+
+ visit project_misc_releases_path(project)
+
+ click_link *view_release_pdf_link_for(native_release)
+ expect(content_type).to eq('application/pdf')
+ end
+ end
+
+ context "when the user is manager(project manager)" do
+ let(:current_user) { create(:user, :manager) }
+
+ before do
+ sign_in current_user
+ end
+
+ scenario "Download action in Manage menu is not visible" do
+ create(:misc_release_with_contract_template, :native, project: project)
+
+ visit project_misc_releases_path(project)
+
+ expect(page).to have_link("Download", exact: true, count: 0)
+ end
+ end
+
+ private
+
+ def download_all_button
+ 'Download All'
+ end
+
+ def view_release_pdf_link_for(release)
+ ['Download', href: misc_release_contracts_path(release, format: 'pdf')]
+ end
+end
diff --git a/spec/features/user_managing_talent_releases_spec.rb b/spec/features/user_managing_talent_releases_spec.rb
index 512cc85..6362a58 100644
--- a/spec/features/user_managing_talent_releases_spec.rb
+++ b/spec/features/user_managing_talent_releases_spec.rb
@@ -5,6 +5,13 @@ feature "User managing talent releases" do
let(:project) { create(:project, members: current_user, account: current_user.primary_account) }
context "when signed out" do
+ scenario "United States is default country" do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_talent_release_path(project.account, project, contract_template)
+ expect(country_field_value).to eq "US"
+ end
+
scenario "creating a release for an adult", js: true do
contract_template = create(:contract_template, project: project)
@@ -55,6 +62,47 @@ feature "User managing talent releases" do
expect(page).to have_content("Your release was successfully submitted. Thank you.")
end
+
+ scenario "creating a release for a minor with two guardians", js: true do
+ contract_template = create(:contract_template, project: project)
+
+ visit new_account_project_contract_template_talent_release_path(project.account, project, contract_template)
+
+ expect(page).not_to have_content guardian_information_heading.upcase
+ expect(page).not_to have_content guardian_2_information_heading.upcase
+ expect(page).not_to have_content guardian_photo_heading.upcase
+ expect(page).not_to have_content guardian_2_photo_heading.upcase
+
+ page.check person_is_minor_checkbox
+ expect(page).to have_content guardian_information_heading.upcase
+ expect(page).to have_content guardian_2_information_heading.upcase
+ expect(page).to have_content guardian_photo_heading.upcase
+ expect(page).to have_content guardian_2_photo_heading.upcase
+
+ fill_in person_first_name_field, with: "Jane"
+ fill_in person_last_name_field, with: "Doe"
+ fill_in person_address_field, with: "123 Test Lane, New York, NY 10000"
+ fill_in person_phone_field, with: "555-555-5555"
+ fill_in person_email_field, with: "jane.doe@test.com"
+
+ fill_in guardian_first_name_field, with: "Guardian"
+ fill_in guardian_last_name_field, with: "Name"
+ fill_in guardian_phone_field, with: "001101"
+
+ fill_in guardian_2_first_name_field, with: "Second"
+ fill_in guardian_2_last_name_field, with: "Guardian"
+
+ drop_file Rails.root.join(file_fixture("person_photo.png")), type: :dropzone
+ attach_file guardian_photo_field, file_fixture("hemsworth.jpeg"), visible: :all
+ attach_file guardian_2_photo_field, file_fixture("person_photo.png"), visible: :all
+ draw_signature file_fixture("signature.png"), "talent_release_signature_base64"
+
+ click_button submit_button
+
+ expect(page).to have_content success_submit_message
+ expect(TalentRelease.last.guardian_2_photo.attached?).to eq true
+ expect(TalentRelease.last.guardian_2_name).to eq "Second Guardian"
+ end
end
context "when signed in" do
@@ -118,6 +166,43 @@ feature "User managing talent releases" do
expect(page).to have_photo("person_photo.png")
end
+ scenario "creating a release for minor with two guardians", js: true do
+ visit new_project_talent_release_path(project)
+
+ expect(page).not_to have_content guardian_photo_heading
+ expect(page).not_to have_content guardian_2_photo_heading
+
+ page.check person_is_minor_checkbox
+
+ expect(page).to have_content guardian_photo_heading
+ expect(page).to have_content guardian_2_photo_heading
+
+ fill_in person_first_name_field, with: "John"
+ fill_in person_last_name_field, with: "Doe"
+
+ fill_in guardian_first_name_field, with: "Guardian"
+ fill_in guardian_last_name_field, with: "Name"
+ fill_in guardian_phone_field, with: "01010"
+
+ fill_in guardian_2_first_name_field, with: "Second"
+ fill_in guardian_2_last_name_field, with: "Guardian"
+
+ fill_in_exploitable_rights
+
+ attach_file contract_field, Rails.root.join(file_fixture("contract.pdf")), visible: false
+ drop_file Rails.root.join(file_fixture("person_photo.png")), type: :dropzone
+ attach_file guardian_photo_field, Rails.root.join(file_fixture("hemsworth.jpeg")), visible: false
+ attach_file guardian_2_photo_field, Rails.root.join(file_fixture("pratt.jpg")), visible: false
+
+ click_button create_release_button
+
+ expect(page).to have_content create_release_notice
+ expect(page).to have_photo("person_photo.png")
+
+ expect(TalentRelease.last.guardian_2_photo.attached?).to eq true
+ expect(TalentRelease.last.guardian_2_name).to eq "Second Guardian"
+ end
+
scenario "updating an existing release" do
talent_release = create(:talent_release, project: project)
@@ -274,6 +359,10 @@ feature "User managing talent releases" do
private
+ def country_field_value
+ find_field("talent_release[person_address_country]").value
+ end
+
def photos_heading(photos_count = 1)
t 'contracts.photos.heading', count: photos_count
end
@@ -290,6 +379,14 @@ feature "User managing talent releases" do
"Guardian last name"
end
+ def guardian_2_first_name_field
+ "talent_release[guardian_2_first_name]"
+ end
+
+ def guardian_2_last_name_field
+ "talent_release[guardian_2_last_name]"
+ end
+
def guardian_phone_field
"Guardian phone"
end
@@ -298,6 +395,10 @@ feature "User managing talent releases" do
"talent_release[guardian_photo]"
end
+ def guardian_2_photo_field
+ "talent_release[guardian_2_photo]"
+ end
+
def have_photo_button
have_selector(".take-photo-button")
end
@@ -376,4 +477,32 @@ feature "User managing talent releases" do
select "Other", from: "Restriction"
fill_in "Describe other restrictions", with: "Test"
end
+
+ def guardian_information_heading
+ t 'public.talent_releases.new.guardian_info.heading'
+ end
+
+ def guardian_2_information_heading
+ t 'public.talent_releases.new.guardian_2_info.heading'
+ end
+
+ def guardian_photo_heading
+ t 'public.talent_releases.new.guardian_photo.heading'
+ end
+
+ def guardian_2_photo_heading
+ t 'public.talent_releases.new.guardian_2_photo.heading'
+ end
+
+ def submit_button
+ t 'shared.submit_release_long'
+ end
+
+ def success_submit_message
+ "Your release was successfully submitted. Thank you."
+ end
+
+ def contract_field
+ "talent_release[contract]"
+ end
end
diff --git a/spec/features/user_performs_video_analysis_spec.rb b/spec/features/user_performs_video_analysis_spec.rb
index 50dbd70..5b69f08 100644
--- a/spec/features/user_performs_video_analysis_spec.rb
+++ b/spec/features/user_performs_video_analysis_spec.rb
@@ -521,8 +521,8 @@ feature "User performs video analysis" do
new_path = polymorphic_path([:new, video, release, :video_release_confirmation])
first("form[action='#{new_path}']").click_button
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -572,8 +572,8 @@ feature "User performs video analysis" do
new_path = polymorphic_path([:new, video, release, :video_release_confirmation])
first("form[action='#{new_path}']").click_button
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -748,8 +748,8 @@ feature "User performs video analysis" do
open_graphics_element_modal(video)
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -796,8 +796,8 @@ feature "User performs video analysis" do
open_graphics_element_modal(video)
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -1188,8 +1188,8 @@ feature "User performs video analysis" do
open_audio_confirmation_modal
expect(page).to have_field("Origin", with: "Original Music")
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
expect(page).to have_field("Source EDL", with: "Audio")
click_on "Show/Hide EDL Events"
@@ -1219,10 +1219,10 @@ feature "User performs video analysis" do
expect(page).to have_field("Source EDL", with: "All Tracks")
expect(page).to have_field("Channel", with: "A1")
expect(page).to have_field("Origin", with: "Library Music")
- expect(page).to have_field("Timecode in", with: "01:00:00:00")
+ expect(page).to have_field("Timecode In", with: "01:00:00:00")
expect(page).to have_field("Timecode out", with: "01:00:02:00")
expect(page).to have_field("Duration", with: "00:00:02")
- expect(page).to have_field("Source file name", with: "source_file_name.wav")
+ expect(page).to have_field("Source File Name", with: "source_file_name.wav")
expect(page).to have_field("Clip name", with: "clip_name")
expect(page).to have_field("Description", with: "description")
@@ -1323,8 +1323,8 @@ feature "User performs video analysis" do
open_unreleased_modal(video)
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -1371,8 +1371,8 @@ feature "User performs video analysis" do
open_unreleased_modal(video)
- expect(page).to have_content "Timecode in"
- expect(page).to have_content "Source file name"
+ expect(page).to have_content "Timecode In"
+ expect(page).to have_content "Source File Name"
click_on "Show/Hide EDL Events"
within "#edl_events" do
@@ -1445,7 +1445,7 @@ feature "User performs video analysis" do
first("#suggested_matches form[action='#{new_path}']").click_button
- expect(page).to have_content "Timecode in"
+ expect(page).to have_content "Timecode In"
within "form[action='#{create_path}']" do
click_button "Confirm Release"
@@ -1462,7 +1462,7 @@ feature "User performs video analysis" do
$("#audio_matches .releasable-match button")[0].click()
JS
- expect(page).to have_content "Timecode in"
+ expect(page).to have_content "Timecode In"
end
def select_option(select_id, text)
@@ -1486,7 +1486,7 @@ feature "User performs video analysis" do
JS
expect(page).to have_field("Origin", with: "Library Music")
- expect(page).to have_content "Timecode in"
+ expect(page).to have_content "Timecode In"
within "form[action='#{create_path}']" do
expect(page).to have_selector("#matched_file_name", text: "library_file_name")
@@ -1518,7 +1518,7 @@ feature "User performs video analysis" do
first("form[action='#{new_path}']", text: text).click_button
- expect(page).to have_content "Timecode in"
+ expect(page).to have_content "Timecode In"
within "form[action='#{create_path}']" do
click_button "Confirm Release"
@@ -1536,7 +1536,7 @@ feature "User performs video analysis" do
first("#music_releases form[action='#{new_path}']", text: text).click_button
expect(page).to have_field("Origin", with: "Original Music")
- expect(page).to have_content "Timecode in"
+ expect(page).to have_content "Timecode In"
within "form[action='#{create_path}']" do
select "Vocal", from: "Music type"
diff --git a/spec/jobs/attach_recording_to_zoom_meeting_job_spec.rb b/spec/jobs/attach_recording_to_zoom_meeting_job_spec.rb
new file mode 100644
index 0000000..727bd51
--- /dev/null
+++ b/spec/jobs/attach_recording_to_zoom_meeting_job_spec.rb
@@ -0,0 +1,45 @@
+require "rails_helper"
+
+describe AttachRecordingToZoomMeetingJob do
+ let(:project) { create(:project) }
+ let(:zoom_meeting) { create(:zoom_meeting, project: project) }
+ let(:recording_hash) { {'id' => 'recording-id', 'download_url' => 'http://download.url', 'recording_start' => '2020-05-22 16:33:50 UTC', 'recording_end' => '2020-05-22 17:34:06 UTC'} }
+ let(:download_token) { 'download_token' }
+
+ before :each do
+ allow_any_instance_of(ZoomGateway).to receive(:delete_recording)
+ end
+
+ describe ".perform_now" do
+ it "downloads the video" do
+ allow(zoom_meeting.recording).to receive(:attach)
+
+ expect(URI).to receive(:open).with("http://download.url?access_token=download_token")
+ AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
+ end
+
+ it "deletes the recording through the API" do
+ stub_uri_open
+ allow(zoom_meeting.recording).to receive(:attach).and_return(true)
+
+ expect_any_instance_of(ZoomGateway).to receive(:delete_recording).with(zoom_meeting.api_meeting_id, 'recording-id')
+ AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
+ end
+
+ it "attaches downloaded video to recording" do
+ allow(zoom_meeting.recording).to receive(:attach)
+ stub_uri_open
+
+ AttachRecordingToZoomMeetingJob.perform_now zoom_meeting, recording_hash, download_token
+ expect(zoom_meeting.recording).to have_received(:attach).with(hash_including(content_type: 'video/mp4'))
+ end
+ end
+
+ private
+
+ def stub_uri_open
+ url = "http://download.url?access_token=download_token"
+ file = double(:file, read: 'stubbed read')
+ allow(URI).to receive(:open).with(url).and_return(file)
+ end
+end
diff --git a/spec/jobs/match_appearance_releases_job_spec.rb b/spec/jobs/match_appearance_releases_job_spec.rb
new file mode 100644
index 0000000..bd35985
--- /dev/null
+++ b/spec/jobs/match_appearance_releases_job_spec.rb
@@ -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
\ No newline at end of file
diff --git a/spec/lib/zoom_gateway_spec.rb b/spec/lib/zoom_gateway_spec.rb
index 0809f37..dc41514 100644
--- a/spec/lib/zoom_gateway_spec.rb
+++ b/spec/lib/zoom_gateway_spec.rb
@@ -1,16 +1,16 @@
require 'rails_helper'
-require 'zoom_gateway'
RSpec.describe ZoomGateway do
let(:roles_list_response) { {"roles" => [{"name" => 'pro-directme-host', "id" => "host_role_id"}, {"name" => 'basic-directme-host', "id" => "host_role_id"}]} }
let(:host_user_hash) { {"email" => "user1@directme", "id" => "host_user_id"} }
let(:roles_members_response) { {"members" => [host_user_hash]} }
let(:user_create_response) { {"id" => "new_host_id"} }
+ let(:user_settings_update_response) { "User settings updated" }
let(:roles_assign_response) { {"ids" => ["new_host_id"]} }
let(:meeting_hash) { {"id" => "meeting_id", "start_url" => "https://start_url", "join_url" => "https://join_url"} }
let(:gateway) { ZoomGateway.new }
- describe "constants" do
+ describe "pseudo-constants" do
context '.USER_TYPE_NAME' do
it 'defaults to "basic"' do
expect(ZoomGateway.USER_TYPE_NAME).to eq('basic')
@@ -64,6 +64,36 @@ RSpec.describe ZoomGateway do
expect(ZoomGateway.HOST_ROLE).to eq('pro-directme-host')
end
end
+
+ context '.ACCOUNT_NUMBER' do
+ it 'depends on ENV["ZOOM_ACCOUNT_NUMBER"]' do
+ stub_env_variable('ZOOM_ACCOUNT_NUMBER', 'xxx-yyy-zzz')
+ expect(ZoomGateway.ACCOUNT_NUMBER).to eq('xxx-yyy-zzz')
+ end
+ end
+ end
+
+ describe 'static methods' do
+ context '.enable_recordings?' do
+ it 'is truthy when ZOOM_ENABLE_RECORDINGS is set to true' do
+ stub_env_variable('ZOOM_ENABLE_RECORDINGS', 'true')
+ expect(ZoomGateway.enable_recordings?).to be_truthy
+ end
+
+ it 'is falsey otherwise' do
+ stub_env_variable('ZOOM_ENABLE_RECORDINGS', '1')
+ expect(ZoomGateway.enable_recordings?).to be_falsey
+
+ stub_env_variable('ZOOM_ENABLE_RECORDINGS', 'false')
+ expect(ZoomGateway.enable_recordings?).to be_falsey
+ end
+ end
+
+ context '.host_role_name' do
+ it 'returns given name with -directme-host prefix' do
+ expect(ZoomGateway.host_role_name('prefix')).to eq('prefix-directme-host')
+ end
+ end
end
describe ".find_meeting" do
@@ -92,7 +122,9 @@ RSpec.describe ZoomGateway do
it "returns new host id" do
allow_any_instance_of(Zoom.new.class).to receive(:user_create).and_return(user_create_response)
allow_any_instance_of(Zoom.new.class).to receive(:roles_assign).and_return(roles_assign_response)
+ allow_any_instance_of(Zoom.new.class).to receive(:user_settings_update).and_return(user_settings_update_response)
+ expect_any_instance_of(Zoom.new.class).to receive(:user_settings_update)
expect(gateway.create_host("host-email@address")).to eq("new_host_id")
end
@@ -102,20 +134,18 @@ RSpec.describe ZoomGateway do
end
it 'raises an exception' do
- allow(ENV).to receive(:[]).and_call_original
- allow(ENV).to receive(:[]).with('ZOOM_USER_TYPE').and_return('pro')
- allow(ENV).to receive(:[]).with('ZOOM_PRO_USERS_LIMIT').and_return('2')
+ stub_env_variables(ZOOM_USER_TYPE: 'pro', ZOOM_PRO_USERS_LIMIT: 2)
expect { gateway.create_host('host-email@address') }.to raise_error(ZoomGateway::TooManyHosts)
end
end
end
- private
-
- def stub_env_variable(name, value)
- allow(ENV).to receive(:[]).and_call_original
- allow(ENV).to receive(:[]).with(name.to_s).and_return(value.to_s)
+ describe '.delete_recording' do
+ it 'calls api client to delete recording' do
+ expect_any_instance_of(Zoom.new.class).to receive(:recording_delete)
+ gateway.delete_recording('meeting-id', 'recording-id')
+ end
end
end
diff --git a/spec/lib/zoom_wrapper_monkeypatch_spec.rb b/spec/lib/zoom_wrapper_monkeypatch_spec.rb
new file mode 100644
index 0000000..7f653e6
--- /dev/null
+++ b/spec/lib/zoom_wrapper_monkeypatch_spec.rb
@@ -0,0 +1,60 @@
+require 'rails_helper'
+
+RSpec.describe Zoom::Actions::User do
+ let(:wrapper) { Zoom.new }
+
+ describe '.update_user_settings' do
+ it 'raises exception if id param is missing' do
+ params = {
+ in_meeting: {
+ not_allowed_param: 1
+ }
+ }
+
+ expect do
+ wrapper.user_settings_update(params)
+ end.to raise_exception(Zoom::ParameterMissing)
+ end
+
+ it 'raises exception if not allowed param is present' do
+ params = {
+ id: 'dw3-3sd33',
+ in_meeting: {
+ not_allowed_param: 1
+ }
+ }
+
+ expect do
+ wrapper.user_settings_update(params)
+ end.to raise_exception(Zoom::ParameterNotPermitted)
+ end
+
+ it 'sends PATCH request to the Zoom API endpoint' do
+ params = {
+ id: 'zoom-120-id',
+ in_meeting: {
+ auto_saving_chat: true,
+ co_host: true,
+ non_verbal_feedback: true,
+ breakout_room: true,
+ group_hd: true,
+ far_end_camera_control: true,
+ allow_live_streaming: true
+ }
+ }
+
+ allow(Zoom::Utils).to receive(:parse_response).and_return 'Success!'
+
+ path = "/users/#{params[:id]}/settings"
+ body_params = { body: params.except(:id).to_json }
+ allow(wrapper.class)
+ .to receive(:patch)
+ .with(path, hash_including(body_params))
+ .and_return({})
+
+ mock_response = wrapper.user_settings_update params
+ expect(mock_response).to eq 'Success!'
+ end
+ end
+
+end
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
index 5915227..97468b7 100644
--- a/spec/models/account_spec.rb
+++ b/spec/models/account_spec.rb
@@ -66,14 +66,16 @@ RSpec.describe Account do
end
describe "#storage_total" do
- it "sums videos, release photos, contracts, signatures" do
+ it "sums videos, release photos, contracts, signatures, recordings" do
video_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
+ recording_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "video_file.mp4"), "video/mp4")
photo_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "person_photo.png"), "image/png")
contract_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "contract.pdf"), "application/pdf")
signature_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "signature.png"), "image/png")
edl_file = Rack::Test::UploadedFile.new(Rails.root.join("spec", "fixtures", "files", "sample-edl.edl"), "application/octet-stream")
expect(video_file.size).to eq 1_055_736
+ expect(recording_file.size).to eq 1_055_736
expect(edl_file.size).to eq 440
expect(photo_file.size).to eq 910
expect(contract_file.size).to eq 12
@@ -89,8 +91,9 @@ RSpec.describe Account do
acquired_media_release = create(:acquired_media_release, project: project, contract: contract_file)
import = create(:import, project: project, file: contract_file)
music_release = create(:music_release, project: project, contract: contract_file)
+ zoom_meeting = create(:zoom_meeting, project: project, recording: recording_file)
- expect(account.storage_total).to eq 1_069_936
+ expect(account.storage_total).to eq 2_125_672
end
it "sums only for projects tied to account" do
@@ -127,7 +130,12 @@ RSpec.describe Account do
User,
Broadcast,
TaskRequest,
- Account
+ Account,
+ ZoomMeeting,
+ MedicalRelease,
+ MiscRelease,
+ MatchingRequest,
+ ActionMailbox::InboundEmail # This is Rails model, we are not using it and it is NOT added to the Account#storage_total calculation
]
Rails.application.eager_load!
ActiveRecord::Base.descendants.each do |model|
diff --git a/spec/models/app_host_spec.rb b/spec/models/app_host_spec.rb
index 851d2d6..b3753cd 100644
--- a/spec/models/app_host_spec.rb
+++ b/spec/models/app_host_spec.rb
@@ -147,10 +147,4 @@ describe AppHost do
expect(app_domain.protocol).to eq :http
end
end
-
- private
-
- def stub_env(key, value)
- allow(ENV).to receive(:fetch).with(key).and_return(value)
- end
end
diff --git a/spec/models/blank_contract_spec.rb b/spec/models/blank_contract_spec.rb
index d3c2d20..9b7e421 100644
--- a/spec/models/blank_contract_spec.rb
+++ b/spec/models/blank_contract_spec.rb
@@ -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
diff --git a/spec/models/contract_template_preview_spec.rb b/spec/models/contract_template_preview_spec.rb
index 7cdf8ec..dee4dea 100644
--- a/spec/models/contract_template_preview_spec.rb
+++ b/spec/models/contract_template_preview_spec.rb
@@ -50,11 +50,19 @@ describe ContractTemplatePreview do
'id' => nil,
'person_first_name' => 'Dummy',
'person_last_name' => 'Person',
- 'person_address' => 'Street 1, Street 2, City, State 12345, Country',
+ 'person_address_street1' => 'Street 1',
+ 'person_address_street2' => 'Street 2',
+ 'person_address_city' => 'City',
+ 'person_address_state' => 'State',
+ 'person_address_zip' => '12345',
'person_phone' => '00 111 222 333 4444',
'updated_at' => nil,
'minor' => true,
- 'guardian_address' => 'Street 3, Street 4, City-2, State-2 112233, Country-2',
+ 'guardian_address_street1' => 'Street 3',
+ 'guardian_address_street2' => 'Street 4',
+ 'guardian_address_city' => 'City-2',
+ 'guardian_address_state' => 'State-2',
+ 'guardian_address_zip' => '112233',
"guardian_first_name" => nil,
"guardian_last_name" => nil,
"guardian_name_old" => nil,
diff --git a/spec/models/contract_template_spec.rb b/spec/models/contract_template_spec.rb
index 0d9e4dc..834ac9a 100644
--- a/spec/models/contract_template_spec.rb
+++ b/spec/models/contract_template_spec.rb
@@ -13,6 +13,8 @@ describe ContractTemplate do
it { is_expected.to have_many(:appearance_releases).dependent(:restrict_with_error) }
it { is_expected.to have_many(:location_releases).dependent(:restrict_with_error) }
it { is_expected.to have_many(:material_releases).dependent(:restrict_with_error) }
+ it { is_expected.to have_many(:medical_releases).dependent(:restrict_with_error) }
+ it { is_expected.to have_many(:misc_releases).dependent(:restrict_with_error) }
end
describe 'validations' do
diff --git a/spec/models/excel_reports/video_reports/nat_geo_legal_binder_logs/appearance_release_log_sheet_spec.rb b/spec/models/excel_reports/video_reports/nat_geo_legal_binder_logs/appearance_release_log_sheet_spec.rb
index ce1ff5f..9b1490e 100644
--- a/spec/models/excel_reports/video_reports/nat_geo_legal_binder_logs/appearance_release_log_sheet_spec.rb
+++ b/spec/models/excel_reports/video_reports/nat_geo_legal_binder_logs/appearance_release_log_sheet_spec.rb
@@ -29,7 +29,7 @@ module ExcelReports
restriction: Restriction.last,
person_first_name: "John",
person_last_name: "Doe",
- person_address: "123 Main Street, New York, NY 10000")
+ person_address_street1: "123 Main Street, New York, NY 10000")
)
)
allow(sheet).to receive(:add_row)
diff --git a/spec/models/headshot_collection_spec.rb b/spec/models/headshot_collection_spec.rb
index e33912f..374fb91 100644
--- a/spec/models/headshot_collection_spec.rb
+++ b/spec/models/headshot_collection_spec.rb
@@ -6,6 +6,7 @@ describe HeadshotCollection do
project = create(:project,
appearance_releases: create_list(:appearance_release, 1),
talent_releases: create_list(:talent_release, 1),
+ headshot_collection_uid: "123abc"
)
collection = HeadshotCollection.for_project(project)
@@ -14,7 +15,7 @@ describe HeadshotCollection do
expect(collection).to be_a(HeadshotCollection)
expect(collection.releasables).to include(project.appearance_releases.first)
expect(collection.releasables).to include(project.talent_releases.first)
- expect(collection.collection_uid).to eq(project.id)
+ expect(collection.collection_uid).to eq(project.headshot_collection_uid)
end
context "when a release has no headshot photo attachment" do
@@ -85,6 +86,29 @@ describe HeadshotCollection do
expect(mapping["appearance_release_#{releases.first.id}"]).to include("123")
expect(mapping["talent_release_#{releases.last.id}"]).to include("456")
end
+
+ context "when collection uid is blank" do
+ it "is not included in the hash" do
+ releases = []
+ collection = HeadshotCollection.new(nil, releases)
+
+ hash = collection.to_hash
+
+ expect(hash.keys).not_to include(:collection_uid)
+ end
+ end
+
+ 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
diff --git a/spec/models/medical_release_spec.rb b/spec/models/medical_release_spec.rb
new file mode 100644
index 0000000..917c3ef
--- /dev/null
+++ b/spec/models/medical_release_spec.rb
@@ -0,0 +1,53 @@
+require "rails_helper"
+
+RSpec.describe MedicalRelease do
+ it_behaves_like "a contractable"
+ it_behaves_like "a notable"
+ it_behaves_like "a photoable"
+ it_behaves_like "a releasable"
+
+ describe "validations" do
+ it { is_expected.to validate_presence_of(:person_first_name) }
+ it { is_expected.to validate_presence_of(:person_last_name) }
+
+ context "for #person_email" do
+ it { is_expected.to allow_value("test@test.com", nil).for(:person_email) }
+ it { is_expected.not_to allow_values("foo", "test@foo", "N/A").for(:person_email) }
+ end
+
+ context "for native releases" do
+ it { is_expected.to validate_attachment_of(:signature).on(:native) }
+ end
+
+ context "for non-native releases" do
+ it { is_expected.to validate_attachment_of(:contract).on(:non_native) }
+ end
+ end
+
+ describe "attachments" do
+ it { is_expected.to respond_to(:signature) }
+ end
+
+ describe "#uses_edl?" do
+ it { is_expected.not_to be_uses_edl }
+ end
+
+ describe "#contract_file_name" do
+ it "includes project name, signed at date, release type, release number and person name" do
+ release = create(:medical_release_with_contract_template, id: 100, signed_at: Date.new(2020, 2, 10), person_first_name: "John", person_last_name: "Doe")
+
+ expect(release.contract_file_name).to eq("my-video-project_medical_2020.02.10_1_doe-john")
+ end
+
+ context "when signed at is nil" do
+ it "uses the created at date" do
+ release = create(:medical_release_with_contract_template,
+ signed_at: nil,
+ created_at: DateTime.new(2020, 2, 10, 12, 0, 0),
+ person_first_name: "John", person_last_name: "Doe")
+
+ expect(release.contract_file_name).to eq("my-video-project_medical_2020.02.10_1_doe-john")
+ end
+ end
+ end
+end
diff --git a/spec/models/misc_release_spec.rb b/spec/models/misc_release_spec.rb
new file mode 100644
index 0000000..ce68b16
--- /dev/null
+++ b/spec/models/misc_release_spec.rb
@@ -0,0 +1,53 @@
+require 'rails_helper'
+
+RSpec.describe MiscRelease, type: :model do
+ it_behaves_like "a contractable"
+ it_behaves_like "a notable"
+ it_behaves_like "a photoable"
+ it_behaves_like "a releasable"
+
+ describe "validations" do
+ it { is_expected.to validate_presence_of(:person_first_name) }
+ it { is_expected.to validate_presence_of(:person_last_name) }
+
+ context "for #person_email" do
+ it { is_expected.to allow_value("test@test.com", nil).for(:person_email) }
+ it { is_expected.not_to allow_values("foo", "test@foo", "N/A").for(:person_email) }
+ end
+
+ context "for native releases" do
+ it { is_expected.to validate_attachment_of(:signature).on(:native) }
+ end
+
+ context "for non-native releases" do
+ it { is_expected.to validate_attachment_of(:contract).on(:non_native) }
+ end
+ end
+
+ describe "attachments" do
+ it { is_expected.to respond_to(:signature) }
+ end
+
+ describe "#uses_edl?" do
+ it { is_expected.not_to be_uses_edl }
+ end
+
+ describe "#contract_file_name" do
+ it "includes project name, signed at date, release type, release number and person name" do
+ release = create(:misc_release_with_contract_template, id: 100, signed_at: Date.new(2020, 2, 10), person_first_name: "John", person_last_name: "Doe")
+
+ expect(release.contract_file_name).to eq("my-video-project_misc_2020.02.10_1_doe-john")
+ end
+
+ context "when signed at is nil" do
+ it "uses the created at date" do
+ release = create(:misc_release_with_contract_template,
+ signed_at: nil,
+ created_at: DateTime.new(2020, 2, 10, 12, 0, 0),
+ person_first_name: "John", person_last_name: "Doe")
+
+ expect(release.contract_file_name).to eq("my-video-project_misc_2020.02.10_1_doe-john")
+ end
+ end
+ end
+end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e5e437c..4210321 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1,5 +1,4 @@
require "rails_helper"
-require "zoom_gateway"
RSpec.describe Project, type: :model do
describe "associations" do
@@ -10,6 +9,8 @@ RSpec.describe Project, type: :model do
it { is_expected.to have_many(:material_releases).dependent(:destroy) }
it { is_expected.to have_many(:music_releases).dependent(:destroy) }
it { is_expected.to have_many(:talent_releases).dependent(:destroy) }
+ it { is_expected.to have_many(:medical_releases).dependent(:destroy) }
+ it { is_expected.to have_many(:misc_releases).dependent(:destroy) }
it { is_expected.to have_many(:videos).dependent(:destroy) }
it { is_expected.to have_many(:contract_templates).dependent(:destroy) }
it { is_expected.to have_many(:project_memberships).dependent(:destroy) }
@@ -79,7 +80,7 @@ RSpec.describe Project, type: :model do
context 'there is no meeting' do
context 'there is a free user available' do
- let!(:free_zoom_user) { create(:zoom_user, api_id: 'user_id') }
+ let!(:free_zoom_user) { create(:zoom_user, :with_api_id) }
before do
allow_any_instance_of(ZoomGateway).to receive(:create_meeting).and_return('new-meeting-id')
diff --git a/spec/models/zoom_meeting_spec.rb b/spec/models/zoom_meeting_spec.rb
index b761ab0..7b573db 100644
--- a/spec/models/zoom_meeting_spec.rb
+++ b/spec/models/zoom_meeting_spec.rb
@@ -1,5 +1,4 @@
require 'rails_helper'
-require 'zoom_gateway'
RSpec.describe ZoomMeeting, type: :model do
let(:zoom_meeting) { build(:zoom_meeting, api_meeting_id: nil) }
@@ -16,6 +15,17 @@ RSpec.describe ZoomMeeting, type: :model do
end
+ describe "attachments" do
+ it { is_expected.to respond_to(:recording) }
+ end
+
+ describe "validations" do
+ context '#recording' do
+ it { is_expected.to allow_content_type("video/mp4").for(:recording) }
+ it { is_expected.not_to allow_content_types("image/png").for(:recording) }
+ end
+ end
+
describe 'associations' do
it { is_expected.to belong_to(:zoom_user) }
it { is_expected.to belong_to(:project).optional(true) }
diff --git a/spec/models/zoom_user_spec.rb b/spec/models/zoom_user_spec.rb
index c53f78b..15732ae 100644
--- a/spec/models/zoom_user_spec.rb
+++ b/spec/models/zoom_user_spec.rb
@@ -5,6 +5,10 @@ RSpec.describe ZoomUser, type: :model do
it { is_expected.to have_many(:zoom_meetings).dependent(:nullify) }
end
+ describe "enums" do
+ it { is_expected.to define_enum_for(:tier).with_values([:basic, :pro]) }
+ end
+
describe 'callbacks' do
let(:zoom_user) { build(:zoom_user) }
@@ -22,10 +26,120 @@ RSpec.describe ZoomUser, type: :model do
zoom_user.save
expect(zoom_user.api_id).to eq "retrieved_api_id"
end
+
+ it 'assigns current account number' do
+ allow_any_instance_of(ZoomGateway).to receive(:create_host).and_return("retrieved_api_id")
+ ENV['ZOOM_ACCOUNT_NUMBER'] = 'xxx-yyy-zzz'
+
+ zoom_user.save
+ expect(zoom_user.account_number).to eq 'xxx-yyy-zzz'
+ end
end
context '#before_destroy' do
pending 'aborts if there is api_id assigned'
end
end
+
+ describe 'scopes' do
+ context '.current_account' do
+ before do
+ create_list(:zoom_user, 10, :with_api_id, account_number: 'first-account-id')
+ create_list(:zoom_user, 25, :with_api_id, account_number: 'second-account-id')
+ end
+
+ it 'only returns users from currently set account' do
+ ENV['ZOOM_ACCOUNT_NUMBER'] = 'first-account-id'
+ expect(ZoomUser.current_account.count).to eq 10
+ expect(ZoomUser.current_account.pluck(:account_number).uniq.count).to eq 1
+ expect(ZoomUser.current_account.pluck(:account_number).uniq.first).to eq 'first-account-id'
+ end
+ end
+
+ context '.free' do
+ let(:free_user) { create(:zoom_user, :with_api_id) }
+ let(:busy_user) { create(:zoom_user, :with_api_id) }
+ let(:second_busy_user) { create(:zoom_user, :with_api_id) }
+ let!(:meeting_started) { create(:zoom_meeting, zoom_user: busy_user, status: :started) }
+ let!(:meeting_created) { create(:zoom_meeting, zoom_user: second_busy_user, status: :created) }
+
+ it 'returns only the users without started / created meetings' do
+ users = ZoomUser.free
+
+ expect(users).to include(free_user)
+ expect(users).not_to include(busy_user)
+ expect(users).not_to include(second_busy_user)
+ end
+ end
+ end
+
+
+ describe '.current_account?' do
+ let(:zoom_user) { create(:zoom_user, :with_api_id, account_number: 'xxx-xxx-xxx') }
+
+ it 'returns true if it belongs to currently set account' do
+ ENV['ZOOM_ACCOUNT_NUMBER'] = 'xxx-xxx-xxx'
+ expect(zoom_user.current_account?).to be_truthy
+ end
+
+ it 'returns false if it doesn\'t belong to currently set account' do
+ ENV['ZOOM_ACCOUNT_NUMBER'] = 'yyy-yyy-yyy'
+ expect(zoom_user.current_account?).to be_falsey
+ end
+ end
+
+
+ context 'static methods' do
+ describe '.generate_api_email' do
+ it 'contains @' do
+ expect(ZoomUser.generate_api_email).to include('@')
+ end
+ end
+
+ describe '.for_new_meeting' do
+ let(:a_basic) { create(:zoom_user, :with_api_id, account_number: 'aaa', tier: :basic) }
+ let(:b_basic) { create(:zoom_user, :with_api_id, account_number: 'bbb', tier: :basic) }
+ let(:a_pro) { create(:zoom_user, :with_api_id, account_number: 'aaa', tier: :pro) }
+ let(:b_pro) { create(:zoom_user, :with_api_id, account_number: 'bbb', tier: :pro) }
+
+ it 'picks free user of requested type from current account' do
+ [a_basic, a_pro, b_basic, b_pro]
+
+ stub_env_variables(ZOOM_USER_TYPE: 'basic', ZOOM_ACCOUNT_NUMBER: 'aaa')
+ expect(ZoomUser.for_new_meeting).to eq(a_basic)
+
+ stub_env_variables(ZOOM_USER_TYPE: 'pro', ZOOM_ACCOUNT_NUMBER: 'aaa')
+ expect(ZoomUser.for_new_meeting).to eq(a_pro)
+
+ stub_env_variables(ZOOM_USER_TYPE: 'basic', ZOOM_ACCOUNT_NUMBER: 'bbb')
+ expect(ZoomUser.for_new_meeting).to eq(b_basic)
+
+ stub_env_variables(ZOOM_USER_TYPE: 'pro', ZOOM_ACCOUNT_NUMBER: 'bbb')
+ expect(ZoomUser.for_new_meeting).to eq(b_pro)
+ end
+
+ context 'no free user' do
+ before do
+ allow_any_instance_of(ZoomGateway).to receive(:create_host).and_return('host-id')
+ end
+
+ it 'creates new user if there is no requested user free available under account' do
+ [a_basic, a_pro, b_basic]
+ stub_env_variables(ZOOM_USER_TYPE: 'pro', ZOOM_ACCOUNT_NUMBER: 'bbb')
+
+ expect_any_instance_of(ZoomGateway).to receive(:create_host)
+ ZoomUser.for_new_meeting
+ end
+
+ it 'creates new user if requested user is busy' do
+ [a_basic, a_pro, b_basic, b_pro]
+ stub_env_variables(ZOOM_USER_TYPE: 'pro', ZOOM_ACCOUNT_NUMBER: 'aaa')
+ create(:zoom_meeting, zoom_user: a_pro, status: :started)
+
+ expect_any_instance_of(ZoomGateway).to receive(:create_host)
+ ZoomUser.for_new_meeting
+ end
+ end
+ end
+ end
end
diff --git a/spec/policies/acquired_media_release_policy_spec.rb b/spec/policies/acquired_media_release_policy_spec.rb
index ad580fc..3f366a5 100644
--- a/spec/policies/acquired_media_release_policy_spec.rb
+++ b/spec/policies/acquired_media_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
describe AcquiredMediaReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -24,6 +25,14 @@ describe AcquiredMediaReleasePolicy do
end
permissions :destroy? do
- it { is_expected.to permit(:destroy) }
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
end
end
diff --git a/spec/policies/appearance_release_policy_spec.rb b/spec/policies/appearance_release_policy_spec.rb
index 64920a4..a9f474c 100644
--- a/spec/policies/appearance_release_policy_spec.rb
+++ b/spec/policies/appearance_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
describe AppearanceReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -24,6 +25,14 @@ describe AppearanceReleasePolicy do
end
permissions :destroy? do
- it { is_expected.to permit(:destroy) }
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
end
end
diff --git a/spec/policies/contract_template_policy_spec.rb b/spec/policies/contract_template_policy_spec.rb
index 703d70e..241ca38 100644
--- a/spec/policies/contract_template_policy_spec.rb
+++ b/spec/policies/contract_template_policy_spec.rb
@@ -15,6 +15,10 @@ describe ContractTemplatePolicy do
it { is_expected.not_to permit(user_context, :create) }
end
+ permissions :show? do
+ it { is_expected.to permit(user_context, :show) }
+ end
+
permissions :destroy? do
it { is_expected.not_to permit(user_context, contract_template) }
@@ -33,6 +37,32 @@ describe ContractTemplatePolicy do
it { is_expected.to permit(user_context, :create) }
end
+ permissions :show? do
+ it { is_expected.to permit(user_context, :show) }
+ end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, contract_template) }
+
+ context "when there are associated releases" do
+ let(:contract_template) { create(:contract_template, appearance_releases: build_list(:appearance_release, 1)) }
+
+ it { is_expected.to permit(user_context, contract_template) }
+ end
+ end
+ end
+
+ context "for an account manager" do
+ let(:user) { create(:user, :account_manager) }
+
+ permissions :create? do
+ it { is_expected.to permit(user_context, :create) }
+ end
+
+ permissions :show? do
+ it { is_expected.to permit(user_context, :show) }
+ end
+
permissions :destroy? do
it { is_expected.to permit(user_context, contract_template) }
@@ -79,7 +109,7 @@ describe ContractTemplatePolicy do
context "for associate" do
let(:user) { create(:user, :associate, primary_account: account) }
- it { is_expected.not_to include(member_project.contract_templates.first) }
+ it { is_expected.to include(member_project.contract_templates.first) }
it { is_expected.not_to include(non_member_project.contract_templates.first) }
it { is_expected.not_to include(outside_project.contract_templates.first) }
end
diff --git a/spec/policies/location_release_policy_spec.rb b/spec/policies/location_release_policy_spec.rb
index d98916f..cc5a84a 100644
--- a/spec/policies/location_release_policy_spec.rb
+++ b/spec/policies/location_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
describe LocationReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -23,10 +24,6 @@ describe LocationReleasePolicy do
end
end
- permissions :destroy? do
- it { is_expected.to permit(:destroy) }
- end
-
permissions :edit_photos? do
it { is_expected.to permit(:edit_photos) }
end
@@ -34,4 +31,16 @@ describe LocationReleasePolicy do
permissions :update_photos? do
it { is_expected.to permit(:update_photos) }
end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
+ end
end
diff --git a/spec/policies/material_release_policy_spec.rb b/spec/policies/material_release_policy_spec.rb
index 85042a9..f3e675a 100644
--- a/spec/policies/material_release_policy_spec.rb
+++ b/spec/policies/material_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
describe MaterialReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -23,10 +24,6 @@ describe MaterialReleasePolicy do
end
end
- permissions :destroy? do
- it { is_expected.to permit(:destroy) }
- end
-
permissions :edit_photos? do
it { is_expected.to permit(:edit_photos) }
end
@@ -34,4 +31,16 @@ describe MaterialReleasePolicy do
permissions :update_photos? do
it { is_expected.to permit(:update_photos) }
end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
+ end
end
diff --git a/spec/policies/medical_release_policy_spec.rb b/spec/policies/medical_release_policy_spec.rb
new file mode 100644
index 0000000..4f7e1ff
--- /dev/null
+++ b/spec/policies/medical_release_policy_spec.rb
@@ -0,0 +1,46 @@
+require "rails_helper"
+
+describe MedicalReleasePolicy do
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
+
+ subject { described_class }
+
+ permissions :create? do
+ it { is_expected.to permit(:create) }
+ end
+
+ permissions :show? do
+ it { is_expected.to permit(:show) }
+ end
+
+ permissions :update? do
+ context "for a native release" do
+ it { is_expected.not_to permit(user_context, build(:medical_release, :native)) }
+ end
+
+ context "for a non-native release" do
+ it { is_expected.to permit(user_context, build(:medical_release, :non_native)) }
+ end
+ end
+
+ permissions :edit_photos? do
+ it { is_expected.to permit(:edit_photos) }
+ end
+
+ permissions :update_photos? do
+ it { is_expected.to permit(:update_photos) }
+ end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
+ end
+end
diff --git a/spec/policies/misc_release_policy_spec.rb b/spec/policies/misc_release_policy_spec.rb
new file mode 100644
index 0000000..2b2a9f7
--- /dev/null
+++ b/spec/policies/misc_release_policy_spec.rb
@@ -0,0 +1,42 @@
+require "rails_helper"
+
+describe MiscReleasePolicy do
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
+
+ subject { described_class }
+
+ permissions :create? do
+ it { is_expected.to permit(:create) }
+ end
+
+ permissions :show? do
+ it { is_expected.to permit(:show) }
+ end
+
+ permissions :update? do
+ context "for a native release" do
+ it { is_expected.not_to permit(user_context, build(:misc_release, :native)) }
+ end
+ end
+
+ permissions :edit_photos? do
+ it { is_expected.to permit(:edit_photos) }
+ end
+
+ permissions :update_photos? do
+ it { is_expected.to permit(:update_photos) }
+ end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
+ end
+end
diff --git a/spec/policies/music_release_policy_spec.rb b/spec/policies/music_release_policy_spec.rb
index e84b556..d03c13d 100644
--- a/spec/policies/music_release_policy_spec.rb
+++ b/spec/policies/music_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
RSpec.describe MusicReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -18,6 +19,14 @@ RSpec.describe MusicReleasePolicy do
end
permissions :destroy? do
- it { is_expected.to permit(:destroy) }
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
end
end
diff --git a/spec/policies/talent_release_policy_spec.rb b/spec/policies/talent_release_policy_spec.rb
index 22f025e..9dc2e86 100644
--- a/spec/policies/talent_release_policy_spec.rb
+++ b/spec/policies/talent_release_policy_spec.rb
@@ -1,7 +1,8 @@
require "rails_helper"
describe TalentReleasePolicy do
- let(:user_context) { build(:user_context) }
+ let(:user) { create(:user, :manager) }
+ let(:user_context) { build(:user_context, user: user, account: user.primary_account) }
subject { described_class }
@@ -23,10 +24,6 @@ describe TalentReleasePolicy do
end
end
- permissions :destroy? do
- it { is_expected.to permit(:destroy) }
- end
-
permissions :edit_photos? do
it { is_expected.to permit(:edit_photos) }
end
@@ -34,4 +31,16 @@ describe TalentReleasePolicy do
permissions :update_photos? do
it { is_expected.to permit(:update_photos) }
end
+
+ permissions :destroy? do
+ it { is_expected.to permit(user_context, :destroy) }
+ end
+
+ context "for an associate" do
+ let(:user) { create(:user, :associate) }
+
+ permissions :destroy? do
+ it { is_expected.not_to permit(user_context, :destroy) }
+ end
+ end
end
diff --git a/spec/support/env_helper.rb b/spec/support/env_helper.rb
new file mode 100644
index 0000000..257a1ca
--- /dev/null
+++ b/spec/support/env_helper.rb
@@ -0,0 +1,16 @@
+module EnvHelper
+ def stub_env_variables(vars)
+ allow(ENV).to receive(:[]).and_call_original
+ vars.each do |variable, value|
+ allow(ENV).to receive(:[]).with(variable.to_s).and_return(value)
+ end
+ end
+
+ def stub_env_variable(key, value)
+ stub_env_variables({key => value})
+ end
+end
+
+RSpec.configure do |config|
+ config.include EnvHelper
+end
|