From 71ad502cc1f54d2c4dc02496e1fc6b8b59203470 Mon Sep 17 00:00:00 2001 From: Senad Uka Date: Tue, 30 Jun 2020 05:08:23 +0200 Subject: [PATCH] Taskme update --- Gemfile | 2 +- Gemfile.lock | 130 +++--- README.md | 16 +- .../javascripts/channels/broadcasts.coffee | 30 +- .../javascripts/channels/projects.coffee | 1 + app/assets/javascripts/collapse_select.js | 21 +- .../javascripts/multi_view_broadcasts.js | 2 +- app/assets/javascripts/photo_preview.js | 8 +- .../javascripts/play_previous_recordings.js | 24 -- .../play_previous_recordings.js.erb | 26 ++ app/assets/stylesheets/application.scss | 5 + app/assets/stylesheets/contract_pdf.scss | 10 +- app/channels/broadcasts_channel.rb | 17 +- app/channels/projects_channel.rb | 10 +- .../acquired_media_releases_controller.rb | 3 +- app/controllers/api/broadcasts_controller.rb | 8 +- .../api/direct_uploads_controller.rb | 50 +++ .../appearance_release_imports_controller.rb | 61 +-- .../appearance_releases_controller.rb | 38 +- app/controllers/broadcasts_controller.rb | 39 +- .../concerns/medical_release_context.rb | 13 + .../concerns/misc_release_context.rb | 13 + .../contract_templates_controller.rb | 10 +- app/controllers/contracts_controller.rb | 4 +- .../location_releases_controller.rb | 3 +- .../medical_releases_controller.rb | 40 ++ app/controllers/misc_releases_controller.rb | 40 ++ app/controllers/password_resets_controller.rb | 1 + app/controllers/projects_controller.rb | 2 +- .../acquired_media_releases_controller.rb | 3 + .../public/appearance_releases_controller.rb | 57 ++- .../public/broadcasts_controller.rb | 33 +- .../public/location_releases_controller.rb | 4 +- .../public/material_releases_controller.rb | 2 +- .../public/medical_releases_controller.rb | 123 ++++++ .../public/misc_releases_controller.rb | 99 +++++ .../public/talent_releases_controller.rb | 67 +-- .../release_template_imports_controller.rb | 4 +- app/controllers/talent_releases_controller.rb | 68 ++- .../zoom_notifications_controller.rb | 27 +- app/helpers/contact_info_helper.rb | 2 +- app/helpers/dropzone_helper.rb | 6 +- .../attach_recording_to_zoom_meeting_job.rb | 25 ++ app/jobs/match_appearance_releases_job.rb | 100 +++++ app/models/account.rb | 4 + app/models/acquired_media_release.rb | 3 +- app/models/appearance_release.rb | 54 ++- app/models/blank_contract.rb | 2 +- app/models/broadcast.rb | 2 - app/models/broadcast_recording.rb | 2 - app/models/concerns/attachable.rb | 9 + app/models/concerns/releasable.rb | 2 - app/models/concerns/second_guardian_name.rb | 20 + .../concerns/second_guardian_photoable.rb | 9 + app/models/contract.rb | 4 + app/models/contract_template.rb | 6 + app/models/headshot_collection.rb | 4 +- app/models/matching_request.rb | 7 + app/models/medical_release.rb | 79 ++++ app/models/misc_release.rb | 86 ++++ app/models/note.rb | 2 - app/models/project.rb | 14 +- app/models/qr_code.rb | 2 +- app/models/releasable_param.rb | 2 +- app/models/sample_appearance_release.rb | 7 +- app/models/talent_release.rb | 18 + app/models/zoom_meeting.rb | 5 +- app/models/zoom_user.rb | 36 +- app/policies/acquired_media_release_policy.rb | 2 +- app/policies/appearance_release_policy.rb | 2 +- app/policies/contract_policy.rb | 6 +- app/policies/contract_template_policy.rb | 7 +- app/policies/location_release_policy.rb | 2 +- app/policies/material_release_policy.rb | 2 +- app/policies/medical_release_policy.rb | 41 ++ app/policies/misc_release_policy.rb | 41 ++ app/policies/music_release_policy.rb | 2 +- app/policies/talent_release_policy.rb | 2 +- .../acquired_media_releases/_form.html.erb | 2 +- .../_appearance_release.html.erb | 11 +- app/views/appearance_releases/_form.html.erb | 51 ++- app/views/appearance_releases/index.html.erb | 3 +- app/views/blank_contracts/pdf.html.erb | 14 +- app/views/broadcasts/_file.html.erb | 2 +- app/views/broadcasts/_file_form.html.erb | 2 +- app/views/broadcasts/_files_section.html.erb | 21 + app/views/broadcasts/show.html.erb | 78 ++-- app/views/broadcasts/update.js.erb | 12 +- app/views/contract_templates/_form.html.erb | 17 +- .../contracts/_medical_questionnaire.html.erb | 8 + app/views/contracts/_photos.html.erb | 11 + app/views/contracts/_signature_page.html.erb | 17 + app/views/contracts/pdf.html.erb | 7 + app/views/location_releases/_form.html.erb | 9 +- app/views/material_releases/_form.html.erb | 8 +- .../_medical_release.html.erb | 49 +++ app/views/medical_releases/index.html.erb | 48 +++ app/views/medical_releases/index.js.erb | 3 + .../misc_releases/_misc_release.html.erb | 48 +++ app/views/misc_releases/index.html.erb | 48 +++ app/views/misc_releases/index.js.erb | 3 + app/views/projects/_form.html.erb | 2 +- .../acquired_media_releases/new.html.erb | 21 +- .../public/appearance_releases/new.html.erb | 62 ++- .../public/broadcasts/_file_form.html.erb | 2 +- app/views/public/broadcasts/update.js.erb | 10 +- .../public/location_releases/new.html.erb | 29 +- .../public/material_releases/new.html.erb | 24 +- .../public/medical_releases/create.html.erb | 1 + .../public/medical_releases/new.html.erb | 158 +++++++ .../public/misc_releases/create.html.erb | 1 + app/views/public/misc_releases/new.html.erb | 97 +++++ app/views/public/talent_releases/new.html.erb | 48 ++- app/views/shared/_address_fields.html.erb | 11 +- app/views/shared/_custom_fields.html.erb | 5 + app/views/talent_releases/_form.html.erb | 50 ++- config/initializers/zoom.rb | 2 + config/locales/en.yml | 262 +++++++++++- config/locales/es.yml | 174 +++++++- config/routes.rb | 7 +- ...n_account_number_and_type_to_zoom_users.rb | 7 + ...1803_change_existing_zoom_user_settings.rb | 9 + ...20200430151828_create_matching_requests.rb | 9 + ...2_add_identifier_to_appearance_releases.rb | 5 + ...d_account_number_and_type_to_zoom_users.rb | 6 + ..._add_filming_hours_to_location_releases.rb | 5 + .../20200606044747_create_medical_releases.rb | 23 + ...d_question_fields_to_contract_templates.rb | 14 + ...9_add_answer_fields_to_medical_releases.rb | 14 + ...d_guardian_email_to_appearance_releases.rb | 5 + ..._remove_broadcast_id_from_zoom_meetings.rb | 5 + ...n_address_column_in_appearance_releases.rb | 10 + ...n_address_column_in_appearance_releases.rb | 10 + ...estions_and_answers_to_medical_releases.rb | 15 + .../20200619085823_create_misc_releases.rb | 34 ++ ..._guardian_fields_to_appearance_releases.rb | 14 + ...dd_guardians_fields_to_medical_releases.rb | 25 ++ ...cond_guardian_fields_to_talent_releases.rb | 14 + db/structure.sql | 396 ++++++++++++++++- lib/brayniac_ai.rb | 1 + lib/brayniac_ai/qr_matching.rb | 4 + lib/tasks/dev.rake | 2 + lib/tasks/zoom.rake | 27 +- lib/zoom_gateway.rb | 48 ++- lib/zoom_wrapper_monkeypatch.rb | 25 ++ spec/channels/broadcasts_channel_spec.rb | 17 + spec/channels/projects_channel_spec.rb | 16 + .../api/broadcasts_controller_spec.rb | 20 + .../api/direct_uploads_controller_spec.rb | 36 ++ .../appearance_releases_controller_spec.rb | 10 +- .../controllers/broadcasts_controller_spec.rb | 30 +- spec/controllers/contracts_controller_spec.rb | 51 +++ .../medical_releases_controller_spec.rb | 91 ++++ .../misc_releases_controller_spec.rb | 116 +++++ .../password_resets_controller_spec.rb | 10 + .../appearance_releases_controller_spec.rb | 16 +- .../public/broadcasts_controller_spec.rb | 8 + .../location_releases_controller_spec.rb | 13 + .../material_releases_controller_spec.rb | 14 + .../medical_releases_controller_spec.rb | 71 ++++ .../public/zoom_meetings_controller_spec.rb | 1 - .../zoom_meetings_controller_spec.rb | 1 - .../zoom_notifications_controller_spec..rb | 75 ---- .../zoom_notifications_controller_spec.rb | 101 +++++ spec/factories/appearance_releases.rb | 42 +- spec/factories/contract_templates.rb | 12 + spec/factories/location_releases.rb | 7 + spec/factories/material_releases.rb | 8 + spec/factories/medical_releases.rb | 47 +++ spec/factories/misc_releases.rb | 58 +++ spec/factories/projects.rb | 1 + spec/factories/zoom_users.rb | 3 + spec/features/user_creates_note_spec.rb | 12 + spec/features/user_creates_tags_spec.rb | 12 + .../user_manages_contract_templates_spec.rb | 38 +- ...r_managing_acquired_media_releases_spec.rb | 70 ++- .../user_managing_appearance_releases_spec.rb | 237 +++++++++-- .../features/user_managing_broadcasts_spec.rb | 151 +++++-- .../user_managing_location_releases_spec.rb | 111 ++++- .../user_managing_material_releases_spec.rb | 150 ++++++- .../user_managing_medical_releases_spec.rb | 399 ++++++++++++++++++ .../user_managing_misc_releases_spec.rb | 55 +++ .../user_managing_talent_releases_spec.rb | 129 ++++++ .../user_performs_video_analysis_spec.rb | 42 +- ...tach_recording_to_zoom_meeting_job_spec.rb | 45 ++ .../match_appearance_releases_job_spec.rb | 216 ++++++++++ spec/lib/zoom_gateway_spec.rb | 50 ++- spec/lib/zoom_wrapper_monkeypatch_spec.rb | 60 +++ spec/models/account_spec.rb | 14 +- spec/models/app_host_spec.rb | 6 - spec/models/blank_contract_spec.rb | 1 - spec/models/contract_template_preview_spec.rb | 12 +- spec/models/contract_template_spec.rb | 2 + .../appearance_release_log_sheet_spec.rb | 2 +- spec/models/headshot_collection_spec.rb | 26 +- spec/models/medical_release_spec.rb | 53 +++ spec/models/misc_release_spec.rb | 53 +++ spec/models/project_spec.rb | 5 +- spec/models/zoom_meeting_spec.rb | 12 +- spec/models/zoom_user_spec.rb | 114 +++++ .../acquired_media_release_policy_spec.rb | 13 +- .../appearance_release_policy_spec.rb | 13 +- .../policies/contract_template_policy_spec.rb | 32 +- spec/policies/location_release_policy_spec.rb | 19 +- spec/policies/material_release_policy_spec.rb | 19 +- spec/policies/medical_release_policy_spec.rb | 46 ++ spec/policies/misc_release_policy_spec.rb | 42 ++ spec/policies/music_release_policy_spec.rb | 13 +- spec/policies/talent_release_policy_spec.rb | 19 +- spec/support/env_helper.rb | 16 + 210 files changed, 6316 insertions(+), 766 deletions(-) delete mode 100644 app/assets/javascripts/play_previous_recordings.js create mode 100644 app/assets/javascripts/play_previous_recordings.js.erb create mode 100644 app/controllers/api/direct_uploads_controller.rb create mode 100644 app/controllers/concerns/medical_release_context.rb create mode 100644 app/controllers/concerns/misc_release_context.rb create mode 100644 app/controllers/medical_releases_controller.rb create mode 100644 app/controllers/misc_releases_controller.rb create mode 100644 app/controllers/public/medical_releases_controller.rb create mode 100644 app/controllers/public/misc_releases_controller.rb create mode 100644 app/jobs/attach_recording_to_zoom_meeting_job.rb create mode 100644 app/jobs/match_appearance_releases_job.rb create mode 100644 app/models/concerns/attachable.rb create mode 100644 app/models/concerns/second_guardian_name.rb create mode 100644 app/models/concerns/second_guardian_photoable.rb create mode 100644 app/models/matching_request.rb create mode 100644 app/models/medical_release.rb create mode 100644 app/models/misc_release.rb create mode 100644 app/policies/medical_release_policy.rb create mode 100644 app/policies/misc_release_policy.rb create mode 100644 app/views/broadcasts/_files_section.html.erb create mode 100644 app/views/contracts/_medical_questionnaire.html.erb create mode 100644 app/views/medical_releases/_medical_release.html.erb create mode 100644 app/views/medical_releases/index.html.erb create mode 100644 app/views/medical_releases/index.js.erb create mode 100644 app/views/misc_releases/_misc_release.html.erb create mode 100644 app/views/misc_releases/index.html.erb create mode 100644 app/views/misc_releases/index.js.erb create mode 100644 app/views/public/medical_releases/create.html.erb create mode 100644 app/views/public/medical_releases/new.html.erb create mode 100644 app/views/public/misc_releases/create.html.erb create mode 100644 app/views/public/misc_releases/new.html.erb create mode 100644 app/views/shared/_custom_fields.html.erb create mode 100644 db/data_migrations/20200526114957_assign_account_number_and_type_to_zoom_users.rb create mode 100644 db/data_migrations/20200623111803_change_existing_zoom_user_settings.rb create mode 100644 db/migrate/20200430151828_create_matching_requests.rb create mode 100644 db/migrate/20200430190412_add_identifier_to_appearance_releases.rb create mode 100644 db/migrate/20200526113516_add_account_number_and_type_to_zoom_users.rb create mode 100644 db/migrate/20200603090419_add_filming_hours_to_location_releases.rb create mode 100644 db/migrate/20200606044747_create_medical_releases.rb create mode 100644 db/migrate/20200610085411_add_question_fields_to_contract_templates.rb create mode 100644 db/migrate/20200610140459_add_answer_fields_to_medical_releases.rb create mode 100644 db/migrate/20200612121539_add_guardian_email_to_appearance_releases.rb create mode 100644 db/migrate/20200615131722_remove_broadcast_id_from_zoom_meetings.rb create mode 100644 db/migrate/20200615133602_destructure_person_address_column_in_appearance_releases.rb create mode 100644 db/migrate/20200616124214_destructure_guardian_address_column_in_appearance_releases.rb create mode 100644 db/migrate/20200619081446_add_more_questions_and_answers_to_medical_releases.rb create mode 100644 db/migrate/20200619085823_create_misc_releases.rb create mode 100644 db/migrate/20200619134853_add_second_guardian_fields_to_appearance_releases.rb create mode 100644 db/migrate/20200622180507_add_guardians_fields_to_medical_releases.rb create mode 100644 db/migrate/20200625144713_add_second_guardian_fields_to_talent_releases.rb create mode 100644 lib/brayniac_ai/qr_matching.rb create mode 100644 lib/zoom_wrapper_monkeypatch.rb create mode 100644 spec/controllers/api/direct_uploads_controller_spec.rb create mode 100644 spec/controllers/medical_releases_controller_spec.rb create mode 100644 spec/controllers/misc_releases_controller_spec.rb create mode 100644 spec/controllers/public/medical_releases_controller_spec.rb delete mode 100644 spec/controllers/zoom_notifications_controller_spec..rb create mode 100644 spec/controllers/zoom_notifications_controller_spec.rb create mode 100644 spec/factories/medical_releases.rb create mode 100644 spec/factories/misc_releases.rb create mode 100644 spec/features/user_managing_medical_releases_spec.rb create mode 100644 spec/features/user_managing_misc_releases_spec.rb create mode 100644 spec/jobs/attach_recording_to_zoom_meeting_job_spec.rb create mode 100644 spec/jobs/match_appearance_releases_job_spec.rb create mode 100644 spec/lib/zoom_wrapper_monkeypatch_spec.rb create mode 100644 spec/models/medical_release_spec.rb create mode 100644 spec/models/misc_release_spec.rb create mode 100644 spec/policies/medical_release_policy_spec.rb create mode 100644 spec/policies/misc_release_policy_spec.rb create mode 100644 spec/support/env_helper.rb 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 += '
' - 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") %>

-
+
No photo yet
<% 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") %>

+
+
+ No photo yet +
+
+ <% 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 %> +
    +
    + <%= will_paginate(files, param_name: 'files_page', params: { active_files_tab: broadcast.token }) if files.present? %> +
    +
    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 %>

    + + +
    +
    +

    Files

    + <% if @multi_view_broadcasts %> + + <% end %> +
    +
    +
    + <% 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" %>
    -
    - <%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", help: "Leave at $0.00 for no-fee", wrapper_class: "col-sm-6" %> +
    + <%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", wrapper_class: "col-sm-6" %>
    <% end %>
    - <%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase")do %> + <%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase"), id: "exploitable_rights_fields" do %> <%= render "shared/exploitable_rights_fields", form: form %> +
    <% end %> -
    - <%= field_set_tag content_tag(:span, t(".legal.heading"), class: "h6 text-muted text-uppercase") do %> <%= form.form_group do %> <%= form.rich_text_area :body %> @@ -28,6 +27,12 @@
    <% 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 %>

      @@ -29,6 +32,14 @@ <%= release.guardian_photo.filename.to_s %> <% end %> + <% if release.respond_to?(:guardian_2_photo) && release.guardian_2_photo.attached? %> +
      +

      <%= t '.guardian_2_photo_heading' %>

      +
    • + <%= image_tag release.guardian_2_photo.variant(auto_orient: true, resize: "200x200") %>
      + <%= release.guardian_2_photo.filename.to_s %> +
    • + <% end %> <% end %>
    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 %> +
    +
    +
    + +
    + + + + + + + + + + + + + + + <% if @medical_releases.any? %> + <%= render @medical_releases %> + <% else %> + + + + <% 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") %>
    <%= t(".empty") %>
    +
    + +
    + <%= will_paginate @medical_releases %> +
    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 %> +
    +
    +
    + +
    + + + + + + + + + + + + + + + <% if @misc_releases.any? %> + <%= render @misc_releases %> + <% else %> + + + + <% 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") %>
    <%= t(".empty") %>
    +
    + +
    + <%= will_paginate @misc_releases %> +
    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") %>

    -
    +
    No photo yet
    <% 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") %>

    +
    +
    + No photo yet +
    +
    + <% 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 '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