diff --git a/.ruby-version b/.ruby-version index 94ff29cc4..ef538c281 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.1.1 +3.1.2 diff --git a/Dockerfile b/Dockerfile index 4f9e69c34..65db290a7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build compilation image -FROM ruby:3.1.1-alpine as builder +FROM ruby:3.1.2-alpine as builder # The application runs from /app WORKDIR /app @@ -16,7 +16,7 @@ RUN apk add --no-cache build-base yarn postgresql-dev git # Install bundler to run bundle exec # This should be the same version as the Gemfile.lock -RUN gem install bundler:2.3.7 --no-document +RUN gem install bundler:2.3.14 --no-document # Install gems defined in Gemfile COPY .ruby-version Gemfile Gemfile.lock /app/ @@ -45,7 +45,7 @@ RUN rm -rf node_modules log tmp && \ find /usr/local/bundle/gems -name "*.html" -delete # Build runtime image -FROM ruby:3.1.1-alpine as production +FROM ruby:3.1.2-alpine as production # The application runs from /app WORKDIR /app diff --git a/Dockerfile_dev b/Dockerfile_dev index 26bfd366f..81a3101c9 100644 --- a/Dockerfile_dev +++ b/Dockerfile_dev @@ -1,5 +1,5 @@ # Build compilation image -FROM ruby:3.1.1-alpine +FROM ruby:3.1.2-alpine # The application runs from /app WORKDIR /app @@ -11,7 +11,7 @@ RUN apk add --no-cache build-base yarn postgresql-dev git bash # Install bundler to run bundle exec # This should be the same version as the Gemfile.lock -RUN gem install bundler:2.3.4 --no-document +RUN gem install bundler:2.3.14 --no-document # Install gems defined in Gemfile COPY .ruby-version Gemfile Gemfile.lock /app/ diff --git a/Gemfile b/Gemfile index 35abd8d23..10ce38f07 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" git_source(:github) { |repo| "https://github.com/#{repo}.git" } -ruby "3.1.1" +ruby "3.1.2" # Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main' gem "rails", "~> 7.0.2" @@ -27,8 +27,6 @@ gem "govuk_markdown" gem "notifications-ruby-client" # A modest javascript framework for the html you already have gem "stimulus-rails" -# Administration framework -gem "activeadmin" # Admin charts gem "chartkick" # Spreadsheet parsing @@ -89,6 +87,7 @@ group :test do gem "capybara", require: false gem "capybara-lockstep" gem "factory_bot_rails" + gem "faker" gem "rspec-rails", require: false gem "selenium-webdriver", require: false gem "simplecov", require: false diff --git a/Gemfile.lock b/Gemfile.lock index b412e0a82..71c6bd92f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,94 +24,82 @@ GIT GEM remote: https://rubygems.org/ specs: - actioncable (7.0.2.4) - actionpack (= 7.0.2.4) - activesupport (= 7.0.2.4) + actioncable (7.0.3) + actionpack (= 7.0.3) + activesupport (= 7.0.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (7.0.2.4) - actionpack (= 7.0.2.4) - activejob (= 7.0.2.4) - activerecord (= 7.0.2.4) - activestorage (= 7.0.2.4) - activesupport (= 7.0.2.4) + actionmailbox (7.0.3) + actionpack (= 7.0.3) + activejob (= 7.0.3) + activerecord (= 7.0.3) + activestorage (= 7.0.3) + activesupport (= 7.0.3) mail (>= 2.7.1) net-imap net-pop net-smtp - actionmailer (7.0.2.4) - actionpack (= 7.0.2.4) - actionview (= 7.0.2.4) - activejob (= 7.0.2.4) - activesupport (= 7.0.2.4) + actionmailer (7.0.3) + actionpack (= 7.0.3) + actionview (= 7.0.3) + activejob (= 7.0.3) + activesupport (= 7.0.3) mail (~> 2.5, >= 2.5.4) net-imap net-pop net-smtp rails-dom-testing (~> 2.0) - actionpack (7.0.2.4) - actionview (= 7.0.2.4) - activesupport (= 7.0.2.4) + actionpack (7.0.3) + actionview (= 7.0.3) + activesupport (= 7.0.3) rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (7.0.2.4) - actionpack (= 7.0.2.4) - activerecord (= 7.0.2.4) - activestorage (= 7.0.2.4) - activesupport (= 7.0.2.4) + actiontext (7.0.3) + actionpack (= 7.0.3) + activerecord (= 7.0.3) + activestorage (= 7.0.3) + activesupport (= 7.0.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (7.0.2.4) - activesupport (= 7.0.2.4) + actionview (7.0.3) + activesupport (= 7.0.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activeadmin (2.12.0) - arbre (~> 1.2, >= 1.2.1) - formtastic (>= 3.1, < 5.0) - formtastic_i18n (~> 0.4) - inherited_resources (~> 1.7) - jquery-rails (~> 4.2) - kaminari (~> 1.0, >= 1.2.1) - railties (>= 6.0, < 7.1) - ransack (>= 2.1.1, < 4) - activejob (7.0.2.4) - activesupport (= 7.0.2.4) + activejob (7.0.3) + activesupport (= 7.0.3) globalid (>= 0.3.6) - activemodel (7.0.2.4) - activesupport (= 7.0.2.4) - activerecord (7.0.2.4) - activemodel (= 7.0.2.4) - activesupport (= 7.0.2.4) - activestorage (7.0.2.4) - actionpack (= 7.0.2.4) - activejob (= 7.0.2.4) - activerecord (= 7.0.2.4) - activesupport (= 7.0.2.4) + activemodel (7.0.3) + activesupport (= 7.0.3) + activerecord (7.0.3) + activemodel (= 7.0.3) + activesupport (= 7.0.3) + activestorage (7.0.3) + actionpack (= 7.0.3) + activejob (= 7.0.3) + activerecord (= 7.0.3) + activesupport (= 7.0.3) marcel (~> 1.0) mini_mime (>= 1.1.0) - activesupport (7.0.2.4) + activesupport (7.0.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) - arbre (1.5.0) - activesupport (>= 3.0.0, < 7.1) - ruby2_keywords (>= 0.0.2, < 1.0) ast (2.4.2) aws-eventstream (1.2.0) - aws-partitions (1.584.0) - aws-sdk-core (3.130.2) + aws-partitions (1.592.0) + aws-sdk-core (3.131.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) - jmespath (~> 1.0) - aws-sdk-kms (1.56.0) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.57.0) aws-sdk-core (~> 3, >= 3.127.0) aws-sigv4 (~> 1.1) aws-sdk-s3 (1.114.0) @@ -120,7 +108,7 @@ GEM aws-sigv4 (~> 1.4) aws-sigv4 (1.5.0) aws-eventstream (~> 1, >= 1.0.2) - bcrypt (3.1.17) + bcrypt (3.1.18) better_html (1.0.16) actionview (>= 4.0) activesupport (>= 4.0) @@ -133,11 +121,11 @@ GEM bootsnap (1.11.1) msgpack (~> 1.2) builder (3.2.4) - bundler-audit (0.9.0.1) + bundler-audit (0.9.1) bundler (>= 1.2.0, < 3) thor (~> 1.0) byebug (11.1.3) - capybara (3.36.0) + capybara (3.37.1) addressable matrix mini_mime (>= 0.1.3) @@ -158,7 +146,6 @@ GEM crack (0.4.5) rexml crass (1.0.6) - deep_merge (1.2.2) diff-lcs (1.5.0) digest (3.1.0) docile (1.4.0) @@ -182,63 +169,40 @@ GEM factory_bot_rails (6.2.0) factory_bot (~> 6.2.0) railties (>= 5.0.0) + faker (2.21.0) + i18n (>= 1.8.11, < 2) ffi (1.15.5) - formtastic (4.0.0) - actionpack (>= 5.2.0) - formtastic_i18n (0.7.0) globalid (1.0.0) activesupport (>= 5.0) - govuk-components (3.0.3) + govuk-components (3.0.4) activemodel (>= 6.1) railties (>= 6.1) view_component (~> 2.49.1) - govuk_design_system_formbuilder (3.0.2) + govuk_design_system_formbuilder (3.0.3) actionview (>= 6.1) activemodel (>= 6.1) activesupport (>= 6.1) - deep_merge (~> 1.2.1) + html-attributes-utils (~> 0.9.0) govuk_markdown (1.0.0) activesupport redcarpet - has_scope (0.8.0) - actionpack (>= 5.2) - activesupport (>= 5.2) hashdiff (1.0.1) + html-attributes-utils (0.9.0) + activesupport (>= 6.1.4.4) html_tokenizer (0.0.7) i18n (1.10.0) concurrent-ruby (~> 1.0) - inherited_resources (1.13.1) - actionpack (>= 5.2, < 7.1) - has_scope (~> 0.6) - railties (>= 5.2, < 7.1) - responders (>= 2, < 4) iniparse (1.5.0) jmespath (1.6.1) - jquery-rails (4.4.0) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) jsbundling-rails (1.0.2) railties (>= 6.0.0) json-schema (3.0.0) addressable (>= 2.8) jwt (2.3.0) - kaminari (1.2.2) - activesupport (>= 4.1.0) - kaminari-actionview (= 1.2.2) - kaminari-activerecord (= 1.2.2) - kaminari-core (= 1.2.2) - kaminari-actionview (1.2.2) - actionview - kaminari-core (= 1.2.2) - kaminari-activerecord (1.2.2) - activerecord - kaminari-core (= 1.2.2) - kaminari-core (1.2.2) listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.17.0) + loofah (2.18.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) @@ -306,35 +270,35 @@ GEM puma (5.6.4) nio4r (~> 2.0) racc (1.6.0) - rack (2.2.3) + rack (2.2.3.1) rack-attack (6.6.1) rack (>= 1.0, < 3) rack-mini-profiler (2.3.4) rack (>= 1.2.0) rack-test (1.1.0) rack (>= 1.0, < 3) - rails (7.0.2.4) - actioncable (= 7.0.2.4) - actionmailbox (= 7.0.2.4) - actionmailer (= 7.0.2.4) - actionpack (= 7.0.2.4) - actiontext (= 7.0.2.4) - actionview (= 7.0.2.4) - activejob (= 7.0.2.4) - activemodel (= 7.0.2.4) - activerecord (= 7.0.2.4) - activestorage (= 7.0.2.4) - activesupport (= 7.0.2.4) + rails (7.0.3) + actioncable (= 7.0.3) + actionmailbox (= 7.0.3) + actionmailer (= 7.0.3) + actionpack (= 7.0.3) + actiontext (= 7.0.3) + actionview (= 7.0.3) + activejob (= 7.0.3) + activemodel (= 7.0.3) + activerecord (= 7.0.3) + activestorage (= 7.0.3) + activesupport (= 7.0.3) bundler (>= 1.15.0) - railties (= 7.0.2.4) + railties (= 7.0.3) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.4.2) loofah (~> 2.3) - railties (7.0.2.4) - actionpack (= 7.0.2.4) - activesupport (= 7.0.2.4) + railties (7.0.3) + actionpack (= 7.0.3) + activesupport (= 7.0.3) method_source rake (>= 12.2) thor (~> 1.0) @@ -342,16 +306,12 @@ GEM rainbow (3.1.1) rake (13.0.6) randexp (0.1.7) - ransack (3.1.0) - activerecord (>= 6.0.4) - activesupport (>= 6.0.4) - i18n rb-fsevent (0.11.1) rb-inotify (0.10.1) ffi (~> 1.0) redcarpet (3.5.1) redis (4.6.0) - regexp_parser (2.3.1) + regexp_parser (2.4.0) request_store (1.5.1) rack (>= 1.4) responders (3.0.1) @@ -396,7 +356,7 @@ GEM rubocop-rails (= 2.13.2) rubocop-rake (= 0.6.0) rubocop-rspec (= 2.7.0) - rubocop-performance (1.13.3) + rubocop-performance (1.14.0) rubocop (>= 1.7.0, < 2.0) rubocop-ast (>= 0.4.0) rubocop-rails (2.13.2) @@ -414,13 +374,13 @@ GEM childprocess (>= 0.5, < 5.0) rexml (~> 3.2, >= 3.2.5) rubyzip (>= 1.2.2) - sentry-rails (5.3.0) + sentry-rails (5.3.1) railties (>= 5.0) - sentry-ruby-core (~> 5.3.0) - sentry-ruby (5.3.0) + sentry-ruby-core (~> 5.3.1) + sentry-ruby (5.3.1) concurrent-ruby (~> 1.0, >= 1.0.2) - sentry-ruby-core (= 5.3.0) - sentry-ruby-core (5.3.0) + sentry-ruby-core (= 5.3.1) + sentry-ruby-core (5.3.1) concurrent-ruby simplecov (0.21.2) docile (~> 1.1) @@ -431,10 +391,10 @@ GEM smart_properties (1.17.0) stimulus-rails (1.0.4) railties (>= 6.0.0) - strscan (3.0.1) + strscan (3.0.3) thor (1.2.1) timecop (0.9.5) - timeout (0.2.0) + timeout (0.3.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) uk_postcode (2.1.7) @@ -468,7 +428,6 @@ PLATFORMS x86_64-linux DEPENDENCIES - activeadmin aws-sdk-s3 bootsnap (>= 1.4.4) bundler-audit @@ -480,6 +439,7 @@ DEPENDENCIES dotenv-rails erb_lint factory_bot_rails + faker govuk-components govuk_design_system_formbuilder govuk_markdown @@ -519,7 +479,7 @@ DEPENDENCIES webmock RUBY VERSION - ruby 3.1.1p18 + ruby 3.1.2p20 BUNDLED WITH - 2.3.12 + 2.3.14 diff --git a/app/admin/admin_users.rb b/app/admin/admin_users.rb deleted file mode 100644 index e161e0202..000000000 --- a/app/admin/admin_users.rb +++ /dev/null @@ -1,37 +0,0 @@ -ActiveAdmin.register AdminUser do - permit_params :email, :phone, :password, :password_confirmation - - controller do - def update_resource(object, attributes) - update_method = attributes.first[:password].present? ? :update : :update_without_password - object.send(update_method, *attributes) - end - end - - index do - selectable_column - id_column - column :email - column "Phone Number", :phone - column :current_sign_in_at - column :sign_in_count - column :created_at - actions - end - - filter :email - filter :phone - filter :current_sign_in_at - filter :sign_in_count - filter :created_at - - form do |f| - f.inputs do - f.input :email - f.input :phone - f.input :password - f.input :password_confirmation - end - f.actions - end -end diff --git a/app/admin/case_logs.rb b/app/admin/case_logs.rb deleted file mode 100644 index 389830a16..000000000 --- a/app/admin/case_logs.rb +++ /dev/null @@ -1,20 +0,0 @@ -ActiveAdmin.register CaseLog do - # See permitted parameters documentation: - # https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters - permit_params do - CaseLog.editable_fields - end - - index do - selectable_column - id_column - column :created_at - column :updated_at - column :status - column :tenant_code - column :postcode_full - column :owning_organisation - column :managing_organisation - actions - end -end diff --git a/app/admin/dashboard.rb b/app/admin/dashboard.rb deleted file mode 100644 index 579f6f487..000000000 --- a/app/admin/dashboard.rb +++ /dev/null @@ -1,32 +0,0 @@ -ActiveAdmin.register_page "Dashboard" do - menu priority: 1, label: proc { I18n.t("active_admin.dashboard") } - - content title: proc { I18n.t("active_admin.dashboard") } do - columns do - column do - panel "Recent logs" do - table_for CaseLog.order(updated_at: :desc).limit(10) do - column :id - column :created_at - column :updated_at - column :status - column :tenant_code - column :postcode_full - end - end - end - - column do - panel "Total logs in progress" do - para CaseLog.in_progress.size - end - panel "Total logs completed" do - para CaseLog.completed.size - end - panel "Total logs completed" do - pie_chart CaseLog.group(:status).size - end - end - end - end -end diff --git a/app/admin/organisations.rb b/app/admin/organisations.rb deleted file mode 100644 index a9e7fb17d..000000000 --- a/app/admin/organisations.rb +++ /dev/null @@ -1,31 +0,0 @@ -ActiveAdmin.register Organisation do - permit_params do - permitted = %i[name - phone - provider_type - address_line1 - address_line2 - postcode - local_authorities - holds_own_stock - other_stock_owners - managing_agents] - permitted - end - - index do - selectable_column - id_column - column :name - column "Org type", :provider_type - column "Address Line 1", :address_line1 - column "Address Line 2", :address_line2 - column :postcode - column "Phone Number", :phone - column :local_authorities - column :holds_own_stock - column :other_stock_owners - column :managing_agents - actions - end -end diff --git a/app/admin/users.rb b/app/admin/users.rb deleted file mode 100644 index 59a235b99..000000000 --- a/app/admin/users.rb +++ /dev/null @@ -1,42 +0,0 @@ -ActiveAdmin.register User do - permit_params :name, :email, :password, :password_confirmation, :organisation_id, :role - - controller do - def update_resource(object, attributes) - update_method = attributes.first[:password].present? ? :update : :update_without_password - object.send(update_method, *attributes) - end - end - - index do - selectable_column - id_column - column :name - column :email - column :organisation - column(:role) { |u| u.role.to_s.humanize } - column :current_sign_in_at - column :sign_in_count - column :created_at - actions - end - - filter :email - filter :name - filter :organisation - filter :current_sign_in_at - filter :sign_in_count - filter :created_at - - form do |f| - f.inputs do - f.input :name - f.input :email - f.input :password - f.input :password_confirmation - f.input :organisation - f.input :role - end - f.actions - end -end diff --git a/app/components/search_component.rb b/app/components/search_component.rb index 35eeefda7..676257263 100644 --- a/app/components/search_component.rb +++ b/app/components/search_component.rb @@ -11,8 +11,12 @@ class SearchComponent < ViewComponent::Base def path(current_user) if request.path.include?("users") user_path(current_user) + elsif request.path.include?("organisations") && request.path.include?("logs") + request.path elsif request.path.include?("organisations") organisations_path + elsif request.path.include?("logs") + case_logs_path end end diff --git a/app/concerns/.keep b/app/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/app/concerns/admin/paper_trail.rb b/app/concerns/admin/paper_trail.rb deleted file mode 100644 index 5558d465b..000000000 --- a/app/concerns/admin/paper_trail.rb +++ /dev/null @@ -1,15 +0,0 @@ -module Admin - module PaperTrail - extend ActiveSupport::Concern - - included do - before_action :set_paper_trail_whodunnit - end - - protected - - def user_for_paper_trail - current_admin_user - end - end -end diff --git a/app/controllers/auth/passwords_controller.rb b/app/controllers/auth/passwords_controller.rb index c26529157..e6b1f3a49 100644 --- a/app/controllers/auth/passwords_controller.rb +++ b/app/controllers/auth/passwords_controller.rb @@ -62,12 +62,8 @@ protected resource.need_two_factor_authentication?(request) ? :updated_2FA : :updated end - def resource_class_name - resource_class.name.underscore - end - def after_sending_reset_password_instructions_path_for(_resource) - account_password_reset_confirmation_path(email: params.dig(resource_class_name, "email")) + account_password_reset_confirmation_path(email: params.dig("user", "email")) end def after_resetting_password_path_for(resource) diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index ad65de5e0..1180a51de 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -2,13 +2,13 @@ class Auth::SessionsController < Devise::SessionsController include Helpers::Email def create - self.resource = resource_class.new - if params.dig(resource_class_name, "email").empty? + self.resource = User.new + if params.dig("user", "email").empty? resource.errors.add :email, "Enter an email address" - elsif !email_valid?(params.dig(resource_class_name, "email")) + elsif !email_valid?(params.dig("user", "email")) resource.errors.add :email, "Enter an email address in the correct format, like name@example.com" end - if params.dig(resource_class_name, "password").empty? + if params.dig("user", "password").empty? resource.errors.add :password, "Enter a password" end if resource.errors.present? @@ -20,19 +20,11 @@ class Auth::SessionsController < Devise::SessionsController private - def resource_class - request.path.include?("admin") ? AdminUser : User - end - - def resource_class_name - resource_class.name.underscore - end - def after_sign_in_path_for(resource) if resource.need_two_factor_authentication?(request) - send("#{resource_name}_two_factor_authentication_path") + user_two_factor_authentication_path else - params.dig(resource_class_name, "start").present? ? case_logs_path : super + params.dig("user", "start").present? ? case_logs_path : super end end end diff --git a/app/controllers/case_logs_controller.rb b/app/controllers/case_logs_controller.rb index 1217585f0..22e6cb599 100644 --- a/app/controllers/case_logs_controller.rb +++ b/app/controllers/case_logs_controller.rb @@ -1,6 +1,7 @@ class CaseLogsController < ApplicationController include Pagy::Backend include Modules::CaseLogsFilter + include Modules::SearchFilter skip_before_action :verify_authenticity_token, if: :json_api_request? before_action :authenticate, if: :json_api_request? @@ -10,12 +11,17 @@ class CaseLogsController < ApplicationController def index set_session_filters - @pagy, @case_logs = pagy(filtered_case_logs(current_user.case_logs)) + all_logs = current_user.case_logs + unpaginated_filtered_logs = filtered_case_logs(filtered_collection(all_logs, search_term)) + + @pagy, @case_logs = pagy(unpaginated_filtered_logs) + @searched = search_term.presence + @total_count = all_logs.size respond_to do |format| format.html format.csv do - send_data filtered_case_logs(current_user.case_logs).to_csv, filename: "logs-#{Time.zone.now}.csv" + send_data unpaginated_filtered_logs.to_csv, filename: "logs-#{Time.zone.now}.csv" end end end @@ -85,6 +91,10 @@ private API_ACTIONS = %w[create show update destroy].freeze + def search_term + params["search"] + end + def json_api_request? API_ACTIONS.include?(request["action"]) && request.format.json? end diff --git a/app/controllers/organisations_controller.rb b/app/controllers/organisations_controller.rb index 7b5eceac4..c1b37aab4 100644 --- a/app/controllers/organisations_controller.rb +++ b/app/controllers/organisations_controller.rb @@ -55,7 +55,12 @@ class OrganisationsController < ApplicationController set_session_filters(specific_org: true) organisation_logs = CaseLog.all.where(owning_organisation_id: @organisation.id) - @pagy, @case_logs = pagy(filtered_case_logs(organisation_logs)) + unpaginated_filtered_logs = filtered_case_logs(filtered_collection(organisation_logs, search_term)) + + @pagy, @case_logs = pagy(unpaginated_filtered_logs) + @searched = search_term.presence + @total_count = organisation_logs.size + render "logs", layout: "application" else redirect_to(case_logs_path) diff --git a/app/frontend/active_admin.js b/app/frontend/active_admin.js deleted file mode 100644 index 95c03bbb9..000000000 --- a/app/frontend/active_admin.js +++ /dev/null @@ -1,7 +0,0 @@ -// Load Active Admin's styles into Webpacker, -// see `active_admin.scss` for customization. -import "./styles/active_admin.scss"; - -import "@activeadmin/activeadmin"; - -import "chartkick/chart.js" diff --git a/app/frontend/styles/_table-group.scss b/app/frontend/styles/_table-group.scss index 71905dfec..c5ca328f3 100644 --- a/app/frontend/styles/_table-group.scss +++ b/app/frontend/styles/_table-group.scss @@ -2,7 +2,7 @@ overflow-x: auto; overflow-y: hidden; margin: govuk-spacing(-3) govuk-spacing(-3) govuk-spacing(3); - padding: 0 govuk-spacing(3); + padding: govuk-spacing(3) govuk-spacing(3); scrollbar-color: $govuk-text-colour govuk-colour("light-grey"); .govuk-table { diff --git a/app/frontend/styles/active_admin.scss b/app/frontend/styles/active_admin.scss deleted file mode 100644 index 66b7017f9..000000000 --- a/app/frontend/styles/active_admin.scss +++ /dev/null @@ -1,17 +0,0 @@ -// Sass variable overrides must be declared before loading up Active Admin's styles. -// -// To view the variables that Active Admin provides, take a look at -// `app/assets/stylesheets/active_admin/mixins/_variables.scss` in the -// Active Admin source. -// -// For example, to change the sidebar width: -// $sidebar-width: 242px; - -// Active Admin's got SASS! -@import "@activeadmin/activeadmin/src/scss/mixins"; -@import "@activeadmin/activeadmin/src/scss/base"; - -// Overriding any non-variable Sass must be done after the fact. -// For example, to change the default status-tag color: -// -// .status_tag { background: #6090DB; } diff --git a/app/helpers/organisation_helper.rb b/app/helpers/organisation_helper.rb index c600f61da..68fa98242 100644 --- a/app/helpers/organisation_helper.rb +++ b/app/helpers/organisation_helper.rb @@ -8,9 +8,4 @@ module OrganisationHelper current_organisation.name end end - - DISPLAY_PROVIDER_TYPE = { "LA": "Local authority", "PRP": "Private registered provider" }.freeze - def display_provider_type(provider_type) - DISPLAY_PROVIDER_TYPE[provider_type.to_sym] - end end diff --git a/app/models/admin_user.rb b/app/models/admin_user.rb deleted file mode 100644 index 7fe671e05..000000000 --- a/app/models/admin_user.rb +++ /dev/null @@ -1,36 +0,0 @@ -class AdminUser < ApplicationRecord - # Include default devise modules. Others available are: - # :confirmable, :timeoutable, :omniauthable - devise :two_factor_authenticatable, :database_authenticatable, :recoverable, - :rememberable, :validatable, :trackable, :lockable - - has_one_time_password(encrypted: true) - - has_paper_trail ignore: %w[last_sign_in_at - current_sign_in_at - current_sign_in_ip - last_sign_in_ip - failed_attempts - unlock_token - locked_at - reset_password_token - reset_password_sent_at - remember_created_at - sign_in_count - updated_at] - - validates :phone, presence: true, numericality: true - - MFA_TEMPLATE_ID = "6bdf5ee1-8e01-4be1-b1f9-747061d8a24c".freeze - RESET_PASSWORD_TEMPLATE_ID = "fbb2d415-b9b1-4507-ba0a-6e542fa3504d".freeze - - def send_two_factor_authentication_code(code) - template_id = MFA_TEMPLATE_ID - personalisation = { otp: code } - DeviseNotifyMailer.new.send_email(email, template_id, personalisation) - end - - def reset_password_notify_template - RESET_PASSWORD_TEMPLATE_ID - end -end diff --git a/app/models/case_log.rb b/app/models/case_log.rb index 2c09bd650..3823cfdeb 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -51,6 +51,17 @@ class CaseLog < ApplicationRecord end } + scope :filter_by_id, ->(id) { where(id:) } + scope :filter_by_tenant_code, ->(tenant_code) { where("tenant_code ILIKE ?", "%#{tenant_code}%") } + scope :filter_by_propcode, ->(propcode) { where("propcode ILIKE ?", "%#{propcode}%") } + scope :filter_by_postcode, ->(postcode_full) { where("postcode_full ILIKE ?", "%#{postcode_full.gsub(/\s+/, '')}%") } + scope :search_by, lambda { |param| + filter_by_id(param) + .or(filter_by_tenant_code(param)) + .or(filter_by_propcode(param)) + .or(filter_by_postcode(param)) + } + AUTOGENERATED_FIELDS = %w[id status created_at updated_at discarded_at].freeze OPTIONAL_FIELDS = %w[first_time_property_let_as_social_housing tenant_code propcode].freeze RENT_TYPE_MAPPING = { 0 => 1, 1 => 2, 2 => 2, 3 => 3, 4 => 3, 5 => 3 }.freeze diff --git a/app/models/organisation.rb b/app/models/organisation.rb index 6d22c303a..3d66b0a85 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -62,12 +62,18 @@ class Organisation < ApplicationRecord data_protection_confirmed? ? "Accepted" : "Not accepted" end + DISPLAY_PROVIDER_TYPE = { "LA": "Local authority", "PRP": "Private registered provider" }.freeze + + def display_provider_type + DISPLAY_PROVIDER_TYPE[provider_type.to_sym] + end + def display_attributes [ { name: "name", value: name, editable: true }, { name: "address", value: address_string, editable: true }, { name: "telephone_number", value: phone, editable: true }, - { name: "type", value: "Org type", editable: false }, + { name: "type", value: display_provider_type, editable: false }, { name: "local_authorities_operated_in", value: local_authority_names, editable: false, format: :bullet }, { name: "rent_periods", value: rent_period_labels, editable: false, format: :bullet }, { name: "holds_own_stock", value: holds_own_stock.to_s.humanize, editable: false }, diff --git a/app/models/user.rb b/app/models/user.rb index f6a20c722..6b4808b84 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -34,6 +34,7 @@ class User < ApplicationRecord scope :search_by_name, ->(name) { where("name ILIKE ?", "%#{name}%") } scope :search_by_email, ->(email) { where("email ILIKE ?", "%#{email}%") } + scope :filter_by_active, -> { where(active: true) } scope :search_by, ->(param) { search_by_name(param).or(search_by_email(param)) } def case_logs @@ -89,8 +90,10 @@ class User < ApplicationRecord old_user_id.present? end - def skip_confirmation! - !active? + def send_confirmation_instructions + return unless active? + + super end def need_two_factor_authentication?(_request) diff --git a/app/services/exports/case_log_export_service.rb b/app/services/exports/case_log_export_service.rb index 0f0d7dd84..078e4a879 100644 --- a/app/services/exports/case_log_export_service.rb +++ b/app/services/exports/case_log_export_service.rb @@ -179,7 +179,7 @@ module Exports # Mapping which would require a change in our data model attribute_hash["createddate"] = attribute_hash["created_at"] attribute_hash["uploaddate"] = attribute_hash["updated_at"] - attribute_hash["tenancycode"] = attribute_hash["tenancy_code"] + attribute_hash["tenancycode"] = attribute_hash["tenant_code"] attribute_hash["ppcodenk"] = attribute_hash["previous_postcode_known"] # Age refused diff --git a/app/services/imports/case_logs_field_import_service.rb b/app/services/imports/case_logs_field_import_service.rb new file mode 100644 index 000000000..d7be932bd --- /dev/null +++ b/app/services/imports/case_logs_field_import_service.rb @@ -0,0 +1,35 @@ +module Imports + class CaseLogsFieldImportService < ImportService + def update_field(field, folder) + case field + when "tenant_code" + import_from(folder, :update_tenant_code) + else + raise "Updating #{field} is not supported by the field import service" + end + end + + private + + def update_tenant_code(xml_doc) + old_id = field_value(xml_doc, "meta", "document-id") + record = CaseLog.find_by(old_id:) + + if record.present? + tenant_code = string_or_nil(xml_doc, "_2bTenCode") + if tenant_code.present? && record.tenant_code.blank? + record.update!(tenant_code:) + else + @logger.info("Case Log #{record.id} has a value for tenant_code, skipping update") + end + else + @logger.warn("Could not find record matching legacy ID #{old_id}") + end + end + + def string_or_nil(xml_doc, attribute) + str = field_value(xml_doc, "xmlns", attribute) + str.presence + end + end +end diff --git a/app/services/imports/case_logs_import_service.rb b/app/services/imports/case_logs_import_service.rb index 02cb2ca35..6b670ce81 100644 --- a/app/services/imports/case_logs_import_service.rb +++ b/app/services/imports/case_logs_import_service.rb @@ -2,6 +2,9 @@ module Imports class CaseLogsImportService < ImportService def create_logs(folder) import_from(folder, :create_log) + if @logs_with_discrepancies.count.positive? + @logger.warn("The following case logs had status discrepancies: [#{@logs_with_discrepancies.join(', ')}]") + end end private @@ -52,6 +55,7 @@ module Imports attributes["joint"] = unsafe_string_as_integer(xml_doc, "joint") attributes["startertenancy"] = unsafe_string_as_integer(xml_doc, "_2a") attributes["tenancy"] = unsafe_string_as_integer(xml_doc, "Q2b") + attributes["tenant_code"] = string_or_nil(xml_doc, "_2bTenCode") attributes["tenancyother"] = string_or_nil(xml_doc, "Q2ba") attributes["tenancylength"] = safe_string_as_integer(xml_doc, "_2cYears") attributes["needstype"] = needs_type(xml_doc) @@ -225,6 +229,8 @@ module Imports def check_status_completed(case_log, previous_status) if previous_status.include?("submitted") && case_log.status != "completed" @logger.warn "Case log #{case_log.id} is not completed" + @logger.warn "Case log with old id:#{case_log.old_id} is incomplete but status should be complete" + @logs_with_discrepancies << case_log.old_id end end diff --git a/app/services/imports/import_service.rb b/app/services/imports/import_service.rb index 664790055..e45498004 100644 --- a/app/services/imports/import_service.rb +++ b/app/services/imports/import_service.rb @@ -5,6 +5,7 @@ module Imports def initialize(storage_service, logger = Rails.logger) @storage_service = storage_service @logger = logger + @logs_with_discrepancies = [] end def import_from(folder, create_method) diff --git a/app/views/case_logs/_log_list.html.erb b/app/views/case_logs/_log_list.html.erb index 87c5c1ed7..130120de8 100644 --- a/app/views/case_logs/_log_list.html.erb +++ b/app/views/case_logs/_log_list.html.erb @@ -1,8 +1,12 @@
<%= govuk_table do |table| %> <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular], id: title.dasherize) do |caption| %> - + + <% if defined?(searched) && searched.present? %> + <%= pagy.count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total <%= title.downcase %>. <%= govuk_link_to("Clear search", request.path) %> + <% else %> <%= pagy.count %> total <%= title.downcase %> + <% end %> <%= govuk_link_to "Download (CSV)", "/logs.csv", type: "text/csv" %> <% end %> diff --git a/app/views/case_logs/index.html.erb b/app/views/case_logs/index.html.erb index 857b1dbd8..b18e22861 100644 --- a/app/views/case_logs/index.html.erb +++ b/app/views/case_logs/index.html.erb @@ -1,8 +1,17 @@ -<% content_for :title, "Logs" %> +<% item_label = @pagy.count > 1 ? "logs" : "log" %> + +<% if @searched.present? %> + <% title = "Your organisation (#{@pagy.count} #{item_label} matching ‘#{@searched}’ of #{@total_count} total logs)" %> +<% else %> + <% title = "Your organisation (Logs)" %> +<% end %> + +<% content_for :title, title %> + +<% content_for :tab_title do %> + <%= "Logs" %> +<% end %> -

- <%= content_for(:title) %> -

<%= govuk_button_to "Create a new lettings log", case_logs_path %> @@ -10,10 +19,10 @@
<%= render partial: "log_filters" %> - <% if @case_logs.present? %> -
- <%= render partial: "log_list", locals: { case_logs: @case_logs, title: "Logs", pagy: @pagy } %> - <%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %> -
- <% end %> +
+ <%= render SearchComponent.new(current_user:, search_label: "Search by log ID, tenant code, property reference or postcode", value: @searched) %> +
+ <%= render partial: "log_list", locals: { case_logs: @case_logs, title: "Logs", pagy: @pagy, searched: @searched, item_label:, total_count: @total_count } %> + <%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %> +
diff --git a/app/views/layouts/organisations.html.erb b/app/views/layouts/organisations.html.erb index 0feff9918..cb4d1c716 100644 --- a/app/views/layouts/organisations.html.erb +++ b/app/views/layouts/organisations.html.erb @@ -1,6 +1,9 @@ <% content_for :content do %>

- <%= organisation_header(request.path, current_user, @organisation) %> + <% if current_user.support? && request.path != "/organisations" %> + <%= @organisation.name %> + <% end %> + <%= content_for(:title) %>

<% items = tab_items(current_user) %> diff --git a/app/views/organisations/_organisation_list.html.erb b/app/views/organisations/_organisation_list.html.erb index 591cedba7..20e35b40c 100644 --- a/app/views/organisations/_organisation_list.html.erb +++ b/app/views/organisations/_organisation_list.html.erb @@ -1,35 +1,37 @@ -<%= govuk_table do |table| %> - <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> - <% if searched.present? %> - <%= pagy.count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total organisations. <%= govuk_link_to("Clear search", request.path) %> - <% else %> - <%= pagy.count %> total organisations. +
+ <%= govuk_table do |table| %> + <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> + <% if searched.present? %> + <%= pagy.count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total organisations. <%= govuk_link_to("Clear search", request.path) %> + <% else %> + <%= pagy.count %> total organisations. + <% end %> <% end %> - <% end %> - <%= table.head do |head| %> - <%= head.row do |row| %> - <% row.cell(header: true, text: "Name", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Registration number", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Type", html_attributes: { - scope: "col", - }) %> + <%= table.head do |head| %> + <%= head.row do |row| %> + <% row.cell(header: true, text: "Name", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Registration number", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Type", html_attributes: { + scope: "col", + }) %> + <% end %> <% end %> - <% end %> - <% @organisations.each do |organisation| %> - <%= table.body do |body| %> - <%= body.row do |row| %> - <% row.cell(header: true, html_attributes: { - scope: "row", - }) do %> - <%= govuk_link_to(organisation.name, "organisations/#{organisation.id}/logs") %> + <% @organisations.each do |organisation| %> + <%= table.body do |body| %> + <%= body.row do |row| %> + <% row.cell(header: true, html_attributes: { + scope: "row", + }) do %> + <%= govuk_link_to(organisation.name, "organisations/#{organisation.id}/logs") %> + <% end %> + <% row.cell(text: organisation.housing_registration_no) %> + <% row.cell(text: organisation.display_provider_type) %> <% end %> - <% row.cell(text: organisation.housing_registration_no) %> - <% row.cell(text: display_provider_type(organisation.provider_type)) %> <% end %> <% end %> <% end %> -<% end %> +
diff --git a/app/views/organisations/logs.html.erb b/app/views/organisations/logs.html.erb index a12287530..a5e62dbf8 100644 --- a/app/views/organisations/logs.html.erb +++ b/app/views/organisations/logs.html.erb @@ -1,9 +1,15 @@ -<% content_for :title, "Logs" %> +<% item_label = @pagy.count > 1 ? "logs" : "log" %> +<% if @searched.present? %> + <% title = "Your organisation (#{@pagy.count} #{item_label} matching ‘#{@searched}’ of #{@total_count} total logs)" %> +<% else %> + <% title = "Your organisation (Logs)" %> +<% end %> -

- <%= @organisation.name %> - <%= content_for(:title) %> -

+<% content_for :title, title %> + +<% content_for :tab_title do %> + <%= "Logs" %> +<% end %> <%= render SubNavigationComponent.new( items: secondary_items(request.path, @organisation.id), @@ -11,10 +17,10 @@
<%= render partial: "case_logs/log_filters" %> - <% if @case_logs.present? %> -
- <%= render partial: "case_logs/log_list", locals: { case_logs: @case_logs, title: "Logs", pagy: @pagy } %> - <%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %> -
- <% end %> +
+ <%= render SearchComponent.new(current_user:, search_label: "Search by log ID, tenant code, property reference or postcode", value: @searched) %> +
+ <%= render partial: "case_logs/log_list", locals: { case_logs: @case_logs, title: "Logs", pagy: @pagy, searched: @searched, item_label:, total_count: @total_count } %> + <%== render partial: "pagy/nav", locals: { pagy: @pagy, item_name: "logs" } %> +
diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb index ecd36da73..f4760a7c9 100644 --- a/app/views/organisations/show.html.erb +++ b/app/views/organisations/show.html.erb @@ -1,4 +1,4 @@ -<% content_for :title, "Your organisation (Details)" %> +<% content_for :title, current_user.support? ? "Details" : "Your organisation" %> <% content_for :tab_title do %> <%= "Details" %> diff --git a/app/views/users/_user_list.html.erb b/app/views/users/_user_list.html.erb index b0a9cb52b..7b9f0785d 100644 --- a/app/views/users/_user_list.html.erb +++ b/app/views/users/_user_list.html.erb @@ -1,54 +1,56 @@ -<%= govuk_table do |table| %> - <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> - - <% if searched.present? %> - <%= pagy.count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total users. <%= govuk_link_to("Clear search", request.path) %> - <% else %> - <%= pagy.count %> total users. +
+ <%= govuk_table do |table| %> + <%= table.caption(classes: %w[govuk-!-font-size-19 govuk-!-font-weight-regular]) do |caption| %> + + <% if searched.present? %> + <%= pagy.count %> <%= item_label %> found matching ‘<%= searched %>’ of <%= total_count %> total users. <%= govuk_link_to("Clear search", request.path) %> + <% else %> + <%= pagy.count %> total users. + <% end %> + + <% if current_user.support? %> + <% query = searched.present? ? "?search=#{searched}" : nil %> + <%= govuk_link_to "Download (CSV)", "/users.csv#{query}", type: "text/csv" %> <% end %> - - <% if current_user.support? %> - <% query = searched.present? ? "?search=#{searched}" : nil %> - <%= govuk_link_to "Download (CSV)", "/users.csv#{query}", type: "text/csv" %> <% end %> - <% end %> - <%= table.head do |head| %> - <%= head.row do |row| %> - <% row.cell(header: true, text: "Name and email adress", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Organisation and role", html_attributes: { - scope: "col", - }) %> - <% row.cell(header: true, text: "Last logged in", html_attributes: { - scope: "col", - }) %> + <%= table.head do |head| %> + <%= head.row do |row| %> + <% row.cell(header: true, text: "Name and email adress", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Organisation and role", html_attributes: { + scope: "col", + }) %> + <% row.cell(header: true, text: "Last logged in", html_attributes: { + scope: "col", + }) %> + <% end %> <% end %> - <% end %> - <% users.each do |user| %> - <%= table.body do |body| %> - <%= body.row do |row| %> - <% row.cell(header: true, html_attributes: { - scope: "row", - }) do %> - <%= simple_format(user_cell(user), {}, wrapper_tag: "span") %> - <% if user.is_data_protection_officer? || user.is_key_contact? %> -
+ <% users.each do |user| %> + <%= table.body do |body| %> + <%= body.row do |row| %> + <% row.cell(header: true, html_attributes: { + scope: "row", + }) do %> + <%= simple_format(user_cell(user), {}, wrapper_tag: "span") %> + <% if user.is_data_protection_officer? || user.is_key_contact? %> +
+ <% end %> + <%= user.is_data_protection_officer? ? govuk_tag( + classes: "app-tag--small", + colour: "turquoise", + text: "Data protection officer", + ) : "" %> + <%= user.is_key_contact? ? govuk_tag( + classes: "app-tag--small", + colour: "turquoise", + text: "Key contact", + ) : "" %> + <% end %> + <% row.cell(text: simple_format(org_cell(user), {}, wrapper_tag: "div")) %> + <% row.cell(text: user.active? ? user.last_sign_in_at&.to_formatted_s(:govuk_date) : "Deactivated") %> <% end %> - <%= user.is_data_protection_officer? ? govuk_tag( - classes: "app-tag--small", - colour: "turquoise", - text: "Data protection officer", - ) : "" %> - <%= user.is_key_contact? ? govuk_tag( - classes: "app-tag--small", - colour: "turquoise", - text: "Key contact", - ) : "" %> - <% end %> - <% row.cell(text: simple_format(org_cell(user), {}, wrapper_tag: "div")) %> - <% row.cell(text: user.active? ? user.last_sign_in_at&.to_formatted_s(:govuk_date) : "Deactivated") %> <% end %> <% end %> <% end %> -<% end %> +
diff --git a/config/environments/test.rb b/config/environments/test.rb index 31b83e22e..3de3bd7e9 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -60,4 +60,5 @@ Rails.application.configure do # Annotate rendered view with file names. # config.action_view.annotate_rendered_view_with_filenames = true + Faker::Config.locale = "en-GB" end diff --git a/config/initializers/active_admin.rb b/config/initializers/active_admin.rb deleted file mode 100644 index ec86c8caf..000000000 --- a/config/initializers/active_admin.rb +++ /dev/null @@ -1,339 +0,0 @@ -ActiveAdmin.setup do |config| - # == Site Title - # - # Set the title that is displayed on the main layout - # for each of the active admin pages. - # - config.site_title = "DLUHC CORE" - - # Set the link url for the title. For example, to take - # users to your main site. Defaults to no link. - # - # config.site_title_link = "/" - - # Set an optional image to be displayed for the header - # instead of a string (overrides :site_title) - # - # Note: Aim for an image that's 21px high so it fits in the header. - # - # config.site_title_image = "logo.png" - - # == Default Namespace - # - # Set the default namespace each administration resource - # will be added to. - # - # eg: - # config.default_namespace = :hello_world - # - # This will create resources in the HelloWorld module and - # will namespace routes to /hello_world/* - # - # To set no namespace by default, use: - # config.default_namespace = false - # - # Default: - # config.default_namespace = :admin - # - # You can customize the settings for each namespace by using - # a namespace block. For example, to change the site title - # within a namespace: - # - # config.namespace :admin do |admin| - # admin.site_title = "Custom Admin Title" - # end - # - # This will ONLY change the title for the admin section. Other - # namespaces will continue to use the main "site_title" configuration. - - # == User Authentication - # - # Active Admin will automatically call an authentication - # method in a before filter of all controller actions to - # ensure that there is a currently logged in admin user. - # - # This setting changes the method which Active Admin calls - # within the application controller. - config.authentication_method = :authenticate_admin_user! - - # == User Authorization - # - # Active Admin will automatically call an authorization - # method in a before filter of all controller actions to - # ensure that there is a user with proper rights. You can use - # CanCanAdapter or make your own. Please refer to documentation. - # config.authorization_adapter = ActiveAdmin::CanCanAdapter - - # In case you prefer Pundit over other solutions you can here pass - # the name of default policy class. This policy will be used in every - # case when Pundit is unable to find suitable policy. - # config.pundit_default_policy = "MyDefaultPunditPolicy" - - # If you wish to maintain a separate set of Pundit policies for admin - # resources, you may set a namespace here that Pundit will search - # within when looking for a resource's policy. - # config.pundit_policy_namespace = :admin - - # You can customize your CanCan Ability class name here. - # config.cancan_ability_class = "Ability" - - # You can specify a method to be called on unauthorized access. - # This is necessary in order to prevent a redirect loop which happens - # because, by default, user gets redirected to Dashboard. If user - # doesn't have access to Dashboard, he'll end up in a redirect loop. - # Method provided here should be defined in application_controller.rb. - # config.on_unauthorized_access = :access_denied - - # == Current User - # - # Active Admin will associate actions with the current - # user performing them. - # - # This setting changes the method which Active Admin calls - # (within the application controller) to return the currently logged in user. - config.current_user_method = :current_admin_user - - # == Logging Out - # - # Active Admin displays a logout link on each screen. These - # settings configure the location and method used for the link. - # - # This setting changes the path where the link points to. If it's - # a string, the strings is used as the path. If it's a Symbol, we - # will call the method to return the path. - # - # Default: - config.logout_link_path = :destroy_admin_user_session_path - - # This setting changes the http method used when rendering the - # link. For example :get, :delete, :put, etc.. - # - # Default: - # config.logout_link_method = :get - - # == Root - # - # Set the action to call for the root path. You can set different - # roots for each namespace. - # - # Default: - # config.root_to = 'dashboard#index' - - # == Admin Comments - # - # This allows your users to comment on any resource registered with Active Admin. - # - # You can completely disable comments: - config.comments = false - # - # You can change the name under which comments are registered: - # config.comments_registration_name = 'AdminComment' - # - # You can change the order for the comments and you can change the column - # to be used for ordering: - # config.comments_order = 'created_at ASC' - # - # You can disable the menu item for the comments index page: - # config.comments_menu = false - # - # You can customize the comment menu: - # config.comments_menu = { parent: 'Admin', priority: 1 } - - # == Batch Actions - # - # Enable and disable Batch Actions - # - config.batch_actions = true - - # == Controller Filters - # - # You can add before, after and around filters to all of your - # Active Admin resources and pages from here. - # - # config.before_action :do_something_awesome - - # == Attribute Filters - # - # You can exclude possibly sensitive model attributes from being displayed, - # added to forms, or exported by default by ActiveAdmin - # - config.filter_attributes = %i[encrypted_password password password_confirmation] - - # == Localize Date/Time Format - # - # Set the localize format to display dates and times. - # To understand how to localize your app with I18n, read more at - # https://guides.rubyonrails.org/i18n.html - # - # You can run `bin/rails runner 'puts I18n.t("date.formats")'` to see the - # available formats in your application. - # - config.localize_format = :long - - # == Setting a Favicon - # - # config.favicon = 'favicon.ico' - - # == Meta Tags - # - # Add additional meta tags to the head element of active admin pages. - # - # Add tags to all pages logged in users see: - # config.meta_tags = { author: 'My Company' } - - # By default, sign up/sign in/recover password pages are excluded - # from showing up in search engine results by adding a robots meta - # tag. You can reset the hash of meta tags included in logged out - # pages: - # config.meta_tags_for_logged_out_pages = {} - - # == Removing Breadcrumbs - # - # Breadcrumbs are enabled by default. You can customize them for individual - # resources or you can disable them globally from here. - # - # config.breadcrumb = false - - # == Create Another Checkbox - # - # Create another checkbox is disabled by default. You can customize it for individual - # resources or you can enable them globally from here. - # - # config.create_another = true - - # == Register Stylesheets & Javascripts - # - # We recommend using the built in Active Admin layout and loading - # up your own stylesheets / javascripts to customize the look - # and feel. - # - # To load a stylesheet: - # config.register_stylesheet 'my_stylesheet.css' - # - # You can provide an options hash for more control, which is passed along to stylesheet_link_tag(): - # config.register_stylesheet 'my_print_stylesheet.css', media: :print - # - # To load a javascript file: - # config.register_javascript 'my_javascript.js' - - # == CSV options - # - # Set the CSV builder separator - # config.csv_options = { col_sep: ';' } - # - # Force the use of quotes - # config.csv_options = { force_quotes: true } - - # == Menu System - # - # You can add a navigation menu to be used in your application, or configure a provided menu - # - # To change the default utility navigation to show a link to your website & a logout btn - # - # config.namespace :admin do |admin| - # admin.build_menu :utility_navigation do |menu| - # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } - # admin.add_logout_button_to_menu menu - # end - # end - # - # If you wanted to add a static menu item to the default menu provided: - # - # config.namespace :admin do |admin| - # admin.build_menu :default do |menu| - # menu.add label: "My Great Website", url: "http://www.mygreatwebsite.com", html_options: { target: :blank } - # end - # end - - # == Download Links - # - # You can disable download links on resource listing pages, - # or customize the formats shown per namespace/globally - # - # To disable/customize for the :admin namespace: - # - # config.namespace :admin do |admin| - # - # # Disable the links entirely - # admin.download_links = false - # - # # Only show XML & PDF options - # admin.download_links = [:xml, :pdf] - # - # # Enable/disable the links based on block - # # (for example, with cancan) - # admin.download_links = proc { can?(:view_download_links) } - # - # end - - # == Pagination - # - # Pagination is enabled by default for all resources. - # You can control the default per page count for all resources here. - # - # config.default_per_page = 30 - # - # You can control the max per page count too. - # - # config.max_per_page = 10_000 - - # == Filters - # - # By default the index screen includes a "Filters" sidebar on the right - # hand side with a filter for each attribute of the registered model. - # You can enable or disable them for all resources here. - # - # config.filters = true - # - # By default the filters include associations in a select, which means - # that every record will be loaded for each association (up - # to the value of config.maximum_association_filter_arity). - # You can enabled or disable the inclusion - # of those filters by default here. - # - # config.include_default_association_filters = true - - # config.maximum_association_filter_arity = 256 # default value of :unlimited will change to 256 in a future version - # config.filter_columns_for_large_association = [ - # :display_name, - # :full_name, - # :name, - # :username, - # :login, - # :title, - # :email, - # ] - # config.filter_method_for_large_association = '_starts_with' - - # == Head - # - # You can add your own content to the site head like analytics. Make sure - # you only pass content you trust. - # - # config.head = ''.html_safe - - # == Footer - # - # By default, the footer shows the current Active Admin version. You can - # override the content of the footer here. - # - # config.footer = 'my custom footer text' - - # == Sorting - # - # By default ActiveAdmin::OrderClause is used for sorting logic - # You can inherit it with own class and inject it for all resources - # - # config.order_clause = MyOrderClause - - # == Webpacker - # - # By default, Active Admin uses Sprocket's asset pipeline. - # You can switch to using Webpacker here. - # - # config.use_webpacker = true -end - -Rails.application.config.after_initialize do - ActiveAdmin::BaseController.include Admin::PaperTrail -end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 9e59169e6..83c73db72 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -152,7 +152,7 @@ Devise.setup do |config| # their account can't be confirmed with the token any more. # Default is nil, meaning there is no restriction on how long a user can take # before confirming their account. - config.confirm_within = 3.days + config.confirm_within = 5.days # If true, requires any email changes to be confirmed (exactly the same way as # initial account confirmation) to be applied. Requires additional unconfirmed_email diff --git a/config/routes.rb b/config/routes.rb index 1dd94e8bb..ccf9f101e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,28 +1,5 @@ # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html Rails.application.routes.draw do - devise_for :admin_users, { - path: :admin, - controllers: { - sessions: "auth/sessions", - passwords: "auth/passwords", - unlocks: "active_admin/devise/unlocks", - registrations: "active_admin/devise/registrations", - confirmations: "active_admin/devise/confirmations", - two_factor_authentication: "auth/two_factor_authentication", - }, - path_names: { - sign_in: "sign-in", - sign_out: "sign-out", - two_factor_authentication: "two-factor-authentication", - two_factor_authentication_resend_code: "resend-code", - }, - sign_out_via: %i[get], - } - - devise_scope :admin_user do - get "admin/two-factor-authentication/resend", to: "auth/two_factor_authentication#show_resend", as: "admin_user_two_factor_authentication_resend" - end - devise_for :users, { path: :account, controllers: { @@ -48,8 +25,6 @@ Rails.application.routes.draw do get "/health", to: ->(_) { [204, {}, [nil]] } - ActiveAdmin.routes(self) - root to: "start#index" get "/accessibility-statement", to: "content#accessibility_statement" diff --git a/db/migrate/20220525130518_drop_admin_users.rb b/db/migrate/20220525130518_drop_admin_users.rb new file mode 100644 index 000000000..bf96e23de --- /dev/null +++ b/db/migrate/20220525130518_drop_admin_users.rb @@ -0,0 +1,36 @@ +class DropAdminUsers < ActiveRecord::Migration[7.0] + def up + drop_table :admin_users + end + + def down + create_table "admin_users", force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" + t.datetime "reset_password_sent_at", precision: nil + t.datetime "remember_created_at", precision: nil + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "second_factor_attempts_count", default: 0 + t.string "encrypted_otp_secret_key" + t.string "encrypted_otp_secret_key_iv" + t.string "encrypted_otp_secret_key_salt" + t.string "direct_otp" + t.datetime "direct_otp_sent_at", precision: nil + t.datetime "totp_timestamp", precision: nil + t.string "phone" + t.string "name" + t.integer "sign_in_count", default: 0, null: false + t.datetime "current_sign_in_at", precision: nil + t.datetime "last_sign_in_at", precision: nil + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.integer "failed_attempts", default: 0 + t.string "unlock_token" + t.datetime "locked_at", precision: nil + t.index %w[encrypted_otp_secret_key], name: "index_admin_users_on_encrypted_otp_secret_key", unique: true + t.index %w[unlock_token], name: "index_admin_users_on_unlock_token", unique: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index a2b94061b..47c6a6883 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,39 +10,10 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_05_23_150557) do +ActiveRecord::Schema[7.0].define(version: 2022_05_25_130518) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "admin_users", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at", precision: nil - t.datetime "remember_created_at", precision: nil - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "second_factor_attempts_count", default: 0 - t.string "encrypted_otp_secret_key" - t.string "encrypted_otp_secret_key_iv" - t.string "encrypted_otp_secret_key_salt" - t.string "direct_otp" - t.datetime "direct_otp_sent_at", precision: nil - t.datetime "totp_timestamp", precision: nil - t.string "phone" - t.string "name" - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at", precision: nil - t.datetime "last_sign_in_at", precision: nil - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.integer "failed_attempts", default: 0 - t.string "unlock_token" - t.datetime "locked_at", precision: nil - t.index ["encrypted_otp_secret_key"], name: "index_admin_users_on_encrypted_otp_secret_key", unique: true - t.index ["unlock_token"], name: "index_admin_users_on_unlock_token", unique: true - end - create_table "case_logs", force: :cascade do |t| t.integer "status", default: 0 t.datetime "created_at", null: false diff --git a/lib/tasks/data_import_field.rake b/lib/tasks/data_import_field.rake new file mode 100644 index 000000000..45a53ec65 --- /dev/null +++ b/lib/tasks/data_import_field.rake @@ -0,0 +1,18 @@ +namespace :core do + desc "Update database field from data XMLs provided by Softwire" + task :data_import_field, %i[field path] => :environment do |_task, args| + field = args[:field] + path = args[:path] + raise "Usage: rake core:data_import_field['field','path/to/xml_files']" if path.blank? || field.blank? + + storage_service = StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) + + # We only allow a reduced list of known fields to be updatable + case field + when "tenant_code" + Imports::CaseLogsFieldImportService.new(storage_service).update_field(field, path) + else + raise "Field #{field} cannot be updated by data_import_field" + end + end +end diff --git a/package.json b/package.json index 9086ffff1..ef6f2bd7e 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "node": "^16.0.0" }, "dependencies": { - "@activeadmin/activeadmin": "^2.11.0", "@babel/core": "^7.17.7", "@babel/plugin-transform-runtime": "^7.17.0", "@babel/preset-env": "^7.16.11", diff --git a/spec/controllers/admin/admin_users_controller_spec.rb b/spec/controllers/admin/admin_users_controller_spec.rb deleted file mode 100644 index f1f2ebeab..000000000 --- a/spec/controllers/admin/admin_users_controller_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "rails_helper" -require_relative "../../support/devise" - -describe Admin::AdminUsersController, type: :controller do - render_views - let(:page) { Capybara::Node::Simple.new(response.body) } - let(:resource_title) { "Admin Users" } - let(:valid_session) { {} } - let(:signed_in_admin_user) { FactoryBot.create(:admin_user) } - - before do - sign_in signed_in_admin_user - end - - describe "Get admin users" do - before do - get :index, session: valid_session - end - - it "returns a table of admin users" do - expect(page).to have_content(resource_title) - expect(page).to have_table("index_table_admin_users") - expect(page).to have_link(AdminUser.first.id.to_s) - end - end - - describe "Create admin users" do - let(:params) { { admin_user: { email: "test2@example.com", password: "pAssword1", phone: "07566126368" } } } - - it "creates a new admin user" do - expect { post :create, session: valid_session, params: }.to change(AdminUser, :count).by(1) - end - - it "tracks who created the record" do - post(:create, session: valid_session, params:) - created_id = response.location.match(/[0-9]+/)[0] - whodunnit_actor = AdminUser.find_by(id: created_id).versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(signed_in_admin_user.id) - end - end - - describe "Update admin users" do - context "when viewing the form" do - before do - get :edit, session: valid_session, params: { id: AdminUser.first.id } - end - - it "shows the correct fields" do - expect(page).to have_field("admin_user_email") - expect(page).to have_field("admin_user_password") - expect(page).to have_field("admin_user_password_confirmation") - end - end - - context "when updating an admin user" do - let(:admin_user) { FactoryBot.create(:admin_user) } - let(:email) { "new_email@example.com" } - let(:params) { { id: admin_user.id, admin_user: { email: } } } - - before do - patch :update, session: valid_session, params: - end - - it "updates the user without needing to input a password" do - admin_user.reload - expect(admin_user.email).to eq(email) - end - - it "tracks who updated the record" do - admin_user.reload - whodunnit_actor = admin_user.versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(signed_in_admin_user.id) - end - end - end -end diff --git a/spec/controllers/admin/case_logs_controller_spec.rb b/spec/controllers/admin/case_logs_controller_spec.rb deleted file mode 100644 index a94e06585..000000000 --- a/spec/controllers/admin/case_logs_controller_spec.rb +++ /dev/null @@ -1,92 +0,0 @@ -require "rails_helper" -require_relative "../../support/devise" - -describe Admin::CaseLogsController, type: :controller do - before do - sign_in admin_user - end - - render_views - let(:page) { Capybara::Node::Simple.new(response.body) } - let(:resource_title) { "Logs" } - let(:valid_session) { {} } - let(:admin_user) { FactoryBot.create(:admin_user) } - let(:user) { FactoryBot.create(:user) } - - describe "Get case logs" do - let!(:case_log) { FactoryBot.create(:case_log, :in_progress) } - - before do - get :index, session: valid_session - end - - it "returns a table of case logs" do - expect(page).to have_content(resource_title) - expect(page).to have_table("index_table_case_logs") - expect(page).to have_link(case_log.id.to_s) - expect(page).to have_link(case_log.owning_organisation.name.to_s) - end - end - - describe "Create case logs" do - let(:owning_organisation) { FactoryBot.create(:organisation) } - let(:managing_organisation) { owning_organisation } - let(:params) do - { - "case_log": { - "owning_organisation_id": owning_organisation.id, - "managing_organisation_id": managing_organisation.id, - "created_by_id": user.id, - }, - } - end - - it "creates a new case log" do - expect { post :create, session: valid_session, params: }.to change(CaseLog, :count).by(1) - end - - it "tracks who created the record" do - post(:create, session: valid_session, params:) - created_id = response.location.match(/[0-9]+/)[0] - whodunnit_actor = CaseLog.find_by(id: created_id).versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - - describe "Update case log" do - let!(:case_log) { FactoryBot.create(:case_log, :in_progress) } - - context "when viewing the edit form" do - before do - get :edit, session: valid_session, params: { id: case_log.id } - end - - it "has the correct fields" do - expect(page).to have_field("case_log_age1") - expect(page).to have_field("case_log_tenant_code") - end - end - - context "when updating the case_log" do - let(:tenant_code) { "New tenant code by Admin" } - let(:params) { { id: case_log.id, case_log: { tenant_code: } } } - - before do - patch :update, session: valid_session, params: - end - - it "updates the case log" do - case_log.reload - expect(case_log.tenant_code).to eq(tenant_code) - end - - it "tracks who updated the record" do - case_log.reload - whodunnit_actor = case_log.versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - end -end diff --git a/spec/controllers/admin/dashboard_controller_spec.rb b/spec/controllers/admin/dashboard_controller_spec.rb deleted file mode 100644 index 141f53b88..000000000 --- a/spec/controllers/admin/dashboard_controller_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -require "rails_helper" -require_relative "../../support/devise" - -describe Admin::DashboardController, type: :controller do - before do - sign_in admin_user - end - - render_views - let(:page) { Capybara::Node::Simple.new(response.body) } - let(:resource_title) { "Dashboard" } - let(:valid_session) { {} } - let(:admin_user) { FactoryBot.create(:admin_user) } - - describe "Get case logs" do - before do - 2.times { |_| FactoryBot.create(:case_log, :in_progress) } - FactoryBot.create(:case_log, :completed) - get :index, session: valid_session - end - - it "returns a dashboard page" do - expect(page).to have_content(resource_title) - end - - it "returns a panel of recent case logs" do - expect(page).to have_xpath("//div[contains(@class, 'panel') and contains(//h3, 'Recent logs')]") - end - - it "returns a panel of in progress case logs" do - panel_xpath = "//div[@class='panel' and .//h3[contains(., 'Total logs in progress')]]" - panel_content_xpath = "#{panel_xpath}//div[@class='panel_contents' and .//p[contains(., 2)]]" - expect(page).to have_xpath(panel_xpath) - expect(page).to have_xpath(panel_content_xpath) - end - - it "returns a panel of completed case logs" do - panel_xpath = "//div[@class='panel' and .//h3[contains(., 'Total logs completed')]]" - panel_content_xpath = "#{panel_xpath}//div[@class='panel_contents' and .//p[contains(., 1)]]" - expect(page).to have_xpath(panel_xpath) - expect(page).to have_xpath(panel_content_xpath) - end - end -end diff --git a/spec/controllers/admin/organisations_controller_spec.rb b/spec/controllers/admin/organisations_controller_spec.rb deleted file mode 100644 index d66bc3c4c..000000000 --- a/spec/controllers/admin/organisations_controller_spec.rb +++ /dev/null @@ -1,78 +0,0 @@ -require "rails_helper" -require_relative "../../support/devise" - -describe Admin::OrganisationsController, type: :controller do - render_views - let(:page) { Capybara::Node::Simple.new(response.body) } - let(:resource_title) { "Organisations" } - let(:valid_session) { {} } - let!(:organisation) { FactoryBot.create(:organisation) } - let!(:admin_user) { FactoryBot.create(:admin_user) } - - before do - sign_in admin_user - end - - describe "Organisations" do - before do - get :index, session: valid_session - end - - it "returns a table of admin users" do - expect(page).to have_content(resource_title) - expect(page).to have_table("index_table_organisations") - expect(page).to have_link(organisation.id.to_s) - end - end - - describe "Create organisation" do - let(:params) { { organisation: { name: "DLUHC", provider_type: "LA" } } } - - it "creates a organisation" do - expect { post :create, session: valid_session, params: }.to change(Organisation, :count).by(1) - end - - it "tracks who created the record" do - post(:create, session: valid_session, params:) - created_id = response.location.match(/[0-9]+/)[0] - whodunnit_actor = Organisation.find_by(id: created_id).versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - - describe "Update organisation" do - context "when viewing the edit form" do - before do - get :edit, session: valid_session, params: { id: organisation.id } - end - - it "has the correct fields" do - expect(page).to have_field("organisation_name") - expect(page).to have_field("organisation_provider_type") - expect(page).to have_field("organisation_phone") - end - end - - context "when updating the organisation" do - let(:name) { "New Org Name by Admin" } - let(:params) { { id: organisation.id, organisation: { name: } } } - - before do - patch :update, session: valid_session, params: - end - - it "updates the organisation" do - organisation.reload - expect(organisation.name).to eq(name) - end - - it "tracks who updated the record" do - organisation.reload - whodunnit_actor = organisation.versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - end -end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb deleted file mode 100644 index 4ed4ab8ed..000000000 --- a/spec/controllers/admin/users_controller_spec.rb +++ /dev/null @@ -1,97 +0,0 @@ -require "rails_helper" -require_relative "../../support/devise" - -describe Admin::UsersController, type: :controller do - render_views - let!(:user) { FactoryBot.create(:user) } - let(:organisation) { FactoryBot.create(:organisation) } - let(:page) { Capybara::Node::Simple.new(response.body) } - let(:resource_title) { "Users" } - let(:valid_session) { {} } - let!(:admin_user) { FactoryBot.create(:admin_user) } - let(:notify_client) { instance_double(Notifications::Client) } - let(:devise_notify_mailer) { DeviseNotifyMailer.new } - - before do - allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) - allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) - allow(notify_client).to receive(:send_email).and_return(true) - sign_in admin_user - end - - describe "Get users" do - before do - get :index, session: valid_session - end - - it "returns a table of users" do - expect(page).to have_content(resource_title) - expect(page).to have_table("index_table_users") - expect(page).to have_link(user.id.to_s) - end - end - - describe "Create users" do - let(:params) do - { - user: { - email: "somethin5@example.com", - name: "Jane", - password: "pAssword1", - organisation_id: organisation.id, - role: "data_coordinator", - }, - } - end - - it "creates a new user" do - expect { post :create, session: valid_session, params: }.to change(User, :count).by(1) - end - - it "tracks who created the record" do - post(:create, session: valid_session, params:) - created_id = response.location.match(/[0-9]+/)[0] - whodunnit_actor = User.find_by(id: created_id).versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - - describe "Update users" do - context "when viewing the edit form" do - before do - get :edit, session: valid_session, params: { id: user.id } - end - - it "has the correct fields" do - expect(page).to have_field("user_email") - expect(page).to have_field("user_name") - expect(page).to have_field("user_organisation_id") - expect(page).to have_field("user_role") - expect(page).to have_field("user_password") - expect(page).to have_field("user_password_confirmation") - end - end - - context "when updating the user" do - let(:name) { "Pete" } - let(:params) { { id: user.id, user: { name: } } } - - before do - patch :update, session: valid_session, params: - end - - it "updates the user without needing to input a password" do - user.reload - expect(user.name).to eq(name) - end - - it "tracks who updated the record" do - user.reload - whodunnit_actor = user.versions.last.actor - expect(whodunnit_actor).to be_a(AdminUser) - expect(whodunnit_actor.id).to eq(admin_user.id) - end - end - end -end diff --git a/spec/factories/case_log.rb b/spec/factories/case_log.rb index 612ef9d8a..6a315a068 100644 --- a/spec/factories/case_log.rb +++ b/spec/factories/case_log.rb @@ -11,9 +11,9 @@ FactoryBot.define do end trait :in_progress do status { 1 } - tenant_code { "TH356" } - postcode_full { "PO5 3TE" } - ppostcode_full { "SW2 6HI" } + tenant_code { Faker::Name.initials(number: 10) } + postcode_full { Faker::Address.postcode } + ppostcode_full { Faker::Address.postcode } age1 { 17 } age2 { 19 } end @@ -24,7 +24,7 @@ FactoryBot.define do incfreq { 1 } end trait :conditional_section_complete do - tenant_code { "TH356" } + tenant_code { Faker::Name.initials(number: 10) } age1 { 34 } sex1 { "M" } ethnic { 2 } @@ -34,7 +34,7 @@ FactoryBot.define do end trait :completed do status { 2 } - tenant_code { "BZ737" } + tenant_code { Faker::Name.initials(number: 10) } age1 { 35 } sex1 { "F" } ethnic { 2 } @@ -52,11 +52,11 @@ FactoryBot.define do reservist { 0 } illness { 1 } preg_occ { 2 } - tenancy_code { "BZ757" } + tenancy_code { Faker::Name.initials(number: 10) } startertenancy { 0 } tenancylength { 5 } tenancy { 1 } - ppostcode_full { "SE2 6RT" } + ppostcode_full { Faker::Address.postcode } rsnvac { 6 } unittype_gn { 7 } beds { 3 } @@ -74,7 +74,7 @@ FactoryBot.define do tcharge { 325 } layear { 2 } waityear { 1 } - postcode_full { "NW1 5TY" } + postcode_full { Faker::Address.postcode } reasonpref { 1 } cbl { 1 } chr { 1 } @@ -112,7 +112,7 @@ FactoryBot.define do needstype { 1 } purchaser_code { 798_794 } reason { 4 } - propcode { "123" } + propcode { Faker::Name.initials(number: 10) } majorrepairs { 1 } la { "E09000003" } prevloc { "E07000105" } diff --git a/spec/features/admin_panel_spec.rb b/spec/features/admin_panel_spec.rb deleted file mode 100644 index 7c721deac..000000000 --- a/spec/features/admin_panel_spec.rb +++ /dev/null @@ -1,162 +0,0 @@ -require "rails_helper" - -RSpec.describe "Admin Panel" do - let!(:admin) { FactoryBot.create(:admin_user) } - let(:devise_notify_mailer) { DeviseNotifyMailer.new } - let(:notify_client) { instance_double(Notifications::Client) } - let(:mfa_template_id) { AdminUser::MFA_TEMPLATE_ID } - let(:otp) { "999111" } - - before do - allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) - allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) - allow(notify_client).to receive(:send_email).and_return(true) - end - - it "shows the admin sign in page" do - visit("/admin") - expect(page).to have_current_path("/admin/sign-in") - expect(page).to have_content("Sign in to your CORE administration account") - end - - context "with a valid 2FA code" do - before do - allow(SecureRandom).to receive(:random_number).and_return(otp) - visit("/admin") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - end - - it "authenticates successfully" do - expect(notify_client).to receive(:send_email).with( - { - email_address: admin.email, - template_id: mfa_template_id, - personalisation: { otp: }, - }, - ) - click_button("Sign in") - fill_in("code", with: otp) - click_button("Submit") - expect(page).to have_content("Dashboard") - expect(page).to have_content(I18n.t("devise.two_factor_authentication.success")) - end - - context "but it is more than 15 minutes old" do - it "does not authenticate successfully" do - click_button("Sign in") - admin.update!(direct_otp_sent_at: 16.minutes.ago) - fill_in("code", with: otp) - click_button("Submit") - expect(page).to have_content("Check your email") - expect(page).to have_http_status(:unprocessable_entity) - expect(page).to have_title("Error") - expect(page).to have_selector("#error-summary-title") - end - end - end - - context "with an invalid 2FA code" do - it "does not authenticate successfully" do - visit("/admin") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - fill_in("code", with: otp) - click_button("Submit") - expect(page).to have_content("Check your email") - expect(page).to have_http_status(:unprocessable_entity) - expect(page).to have_title("Error") - expect(page).to have_selector("#error-summary-title") - end - end - - context "when the 2FA code needs to be resent" do - before do - visit("/admin") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - end - - it "displays the resend view" do - click_link("Not received an email?") - expect(page).to have_button("Resend security code") - end - - it "send a new OTP code and redirects back to the 2FA view" do - click_link("Not received an email?") - expect { click_button("Resend security code") }.to(change { admin.reload.direct_otp }) - expect(page).to have_current_path("/admin/two-factor-authentication") - end - end - - context "when logging out and in again" do - before do - allow(SecureRandom).to receive(:random_number).and_return(otp) - end - - it "requires the 2FA code on each login" do - visit("/admin") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - fill_in("code", with: otp) - click_button("Submit") - click_link("Logout") - visit("/admin") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - expect(page).to have_content("Check your email") - end - end - - context "when the admin has forgotten their password" do - let!(:admin_user) { FactoryBot.create(:admin_user, last_sign_in_at: Time.zone.now) } - let(:reset_password_token) { "MCDH5y6Km-U7CFPgAMVS" } - - before do - allow(Devise.token_generator).to receive(:generate).and_return(reset_password_token) - end - - it " is redirected to the reset password page when they click the reset password link" do - visit("/admin") - click_link("reset your password") - expect(page).to have_current_path("/admin/password/new") - end - - it " is shown an error message if they submit without entering an email address" do - visit("/admin/password/new") - click_button("Send email") - expect(page).to have_selector("#error-summary-title") - expect(page).to have_selector("#user-email-field-error") - expect(page).to have_title("Error") - end - - it " is redirected to admin login page after reset email is sent" do - visit("/admin/password/new") - fill_in("admin_user[email]", with: admin_user.email) - click_button("Send email") - expect(page).to have_content("Check your email") - end - - it " is sent a reset password email via Notify" do - expect(notify_client).to receive(:send_email).with( - { - email_address: admin_user.email, - template_id: admin_user.reset_password_notify_template, - personalisation: { - name: admin_user.email, - email: admin_user.email, - organisation: "", - link: "http://localhost:3000/admin/password/edit?reset_password_token=#{reset_password_token}", - }, - }, - ) - visit("/admin/password/new") - fill_in("admin_user[email]", with: admin_user.email) - click_button("Send email") - end - end -end diff --git a/spec/features/auth/user_lockout_spec.rb b/spec/features/auth/user_lockout_spec.rb index c1ba131df..68cf78b2a 100644 --- a/spec/features/auth/user_lockout_spec.rb +++ b/spec/features/auth/user_lockout_spec.rb @@ -2,7 +2,6 @@ require "rails_helper" RSpec.describe "User Lockout" do let(:user) { FactoryBot.create(:user) } - let(:admin) { FactoryBot.create(:admin_user) } let(:max_login_attempts) { Devise.maximum_attempts } let(:max_2fa_attempts) { Devise.max_login_attempts } let(:notify_client) { instance_double(Notifications::Client) } @@ -26,53 +25,4 @@ RSpec.describe "User Lockout" do expect(page).to have_content(I18n.t("devise.failure.locked")) end end - - context "when login-in with the wrong admin password up to a maximum number of attempts" do - before do - visit("/admin/sign-in") - max_login_attempts.times do - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: "wrong_password") - click_button("Sign in") - end - end - - it "locks the admin account" do - visit("/admin/sign-in") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - expect(page).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("devise.failure.locked")) - end - end - - context "when login-in with the right admin password and incorrect 2FA token up to a maximum number of attempts" do - let(:devise_notify_mailer) { DeviseNotifyMailer.new } - - before do - allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) - allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) - allow(notify_client).to receive(:send_email).and_return(true) - - visit("/admin/sign-in") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - - max_2fa_attempts.times do - fill_in("code", with: "random") - click_button("Submit") - end - end - - it "locks the admin account" do - visit("/admin/sign-in") - fill_in("admin_user[email]", with: admin.email) - fill_in("admin_user[password]", with: admin.password) - click_button("Sign in") - expect(page).to have_http_status(:unprocessable_entity) - expect(page).to have_content(I18n.t("devise.two_factor_authentication.account_locked")) - end - end end diff --git a/spec/features/form/saving_data_spec.rb b/spec/features/form/saving_data_spec.rb index 9e8d09f58..863d906e7 100644 --- a/spec/features/form/saving_data_spec.rb +++ b/spec/features/form/saving_data_spec.rb @@ -73,7 +73,7 @@ RSpec.describe "Form Saving Data" do it "displays number answers in inputs if they are already saved" do visit("/logs/#{id}/property-postcode") - expect(page).to have_field("case-log-postcode-full-field", with: "PO53TE") + expect(page).to have_field("case-log-postcode-full-field", with: case_log.postcode_full) end it "displays text answers in inputs if they are already saved" do diff --git a/spec/features/log_spec.rb b/spec/features/log_spec.rb new file mode 100644 index 000000000..2e8812b63 --- /dev/null +++ b/spec/features/log_spec.rb @@ -0,0 +1,59 @@ +require "rails_helper" + +RSpec.describe "Log Features" do + context "when searching for specific logs" do + context "when I am logged in and there are logs in the database" do + let(:user) { FactoryBot.create(:user, last_sign_in_at: Time.zone.now) } + let!(:log_to_search) { FactoryBot.create(:case_log, owning_organisation: user.organisation) } + let!(:same_organisation_log) { FactoryBot.create(:case_log, owning_organisation: user.organisation) } + let!(:another_organisation_log) { FactoryBot.create(:case_log) } + + before do + visit("/logs") + fill_in("user[email]", with: user.email) + fill_in("user[password]", with: user.password) + click_button("Sign in") + end + + it "displays the logs belonging to the same organisation" do + expect(page).to have_link(log_to_search.id.to_s) + expect(page).to have_link(same_organisation_log.id.to_s) + expect(page).not_to have_link(another_organisation_log.id.to_s) + end + + context "when I search for a specific log" do + it "there is a search bar with a message and search button for logs" do + expect(page).to have_field("search") + expect(page).to have_content("Search by log ID, tenant code, property reference or postcode") + expect(page).to have_button("Search") + end + + context "when I fill in search information and press the search button" do + before do + fill_in("search", with: log_to_search.id) + click_button("Search") + end + + it "displays log matching the log ID" do + expect(page).to have_link(log_to_search.id.to_s) + expect(page).not_to have_link(same_organisation_log.id.to_s) + expect(page).not_to have_link(another_organisation_log.id.to_s) + end + + context "when I want to clear results" do + it "there is link to clear the search results" do + expect(page).to have_link("Clear search") + end + + it "displays the logs belonging to the same organisation after I clear the search results" do + click_link("Clear search") + expect(page).to have_link(log_to_search.id.to_s) + expect(page).to have_link(same_organisation_log.id.to_s) + expect(page).not_to have_link(another_organisation_log.id.to_s) + end + end + end + end + end + end +end diff --git a/spec/features/organisation_spec.rb b/spec/features/organisation_spec.rb index 75277a28a..8d00bf2dd 100644 --- a/spec/features/organisation_spec.rb +++ b/spec/features/organisation_spec.rb @@ -84,12 +84,13 @@ RSpec.describe "User Features" do context "when user is support user" do context "when viewing logs for specific organisation" do let(:user) { FactoryBot.create(:user, :support) } - let(:number_of_case_logs) { 4 } let(:first_log) { organisation.case_logs.first } let(:otp) { "999111" } + let!(:log_to_search) { FactoryBot.create(:case_log, owning_organisation: user.organisation, managing_organisation_id: organisation.id) } + let!(:other_logs) { FactoryBot.create_list(:case_log, 4, owning_organisation_id: organisation.id, managing_organisation_id: organisation.id) } + let(:number_of_case_logs) { CaseLog.count } before do - FactoryBot.create_list(:case_log, number_of_case_logs, owning_organisation_id: organisation.id, managing_organisation_id: organisation.id) first_log.update!(startdate: Time.utc(2022, 6, 2, 10, 36, 49)) allow(SecureRandom).to receive(:random_number).and_return(otp) click_link("Sign out") @@ -99,6 +100,48 @@ RSpec.describe "User Features" do visit("/organisations/#{org_id}/logs") end + context "when searching for specific logs" do + it "displays the logs belonging to the same organisation" do + expect(page).to have_content(log_to_search.id) + other_logs.each do |log| + expect(page).to have_content(log.id) + end + end + + context "when I search for a specific log" do + it "there is a search bar with a message and search button for logs" do + expect(page).to have_field("search") + expect(page).to have_content("Search by log ID, tenant code, property reference or postcode") + expect(page).to have_button("Search") + end + + context "when I fill in search information and press the search button" do + before do + fill_in("search", with: log_to_search.id) + click_button("Search") + end + + it "displays log matching the log ID" do + expect(page).to have_link(log_to_search.id.to_s) + other_logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + context "when I want to clear results" do + it "there is link to clear the search results" do + expect(page).to have_link("Clear search") + end + + it "displays the logs belonging to the same organisation after I clear the search result after I clear the search resultss" do + click_link("Clear search") + expect(page).to have_link(log_to_search.id.to_s) + end + end + end + end + end + it "can filter case logs" do expect(page).to have_content("#{number_of_case_logs} total logs") organisation.case_logs.map(&:id).each do |case_log_id| diff --git a/spec/fixtures/exports/case_logs.csv b/spec/fixtures/exports/case_logs.csv index af3c88a07..5d334bcfb 100644 --- a/spec/fixtures/exports/case_logs.csv +++ b/spec/fixtures/exports/case_logs.csv @@ -1,2 +1,2 @@ status,age1,sex1,ethnic,national,prevten,ecstat1,hhmemb,age2,sex2,ecstat2,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,leftreg,reservist,illness,preg_occ,startertenancy,tenancylength,tenancy,ppostcode_full,rsnvac,unittype_gn,beds,offered,wchair,earnings,incfreq,benefits,period,layear,waityear,postcode_full,reasonpref,cbl,chr,cap,reasonother,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,illness_type_1,illness_type_2,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,irproduct_other,reason,propcode,la,prevloc,hb,hbrentshortfall,mrcdate,incref,startdate,armedforces,unitletas,builtype,voiddate,renttype,needstype,lettype,totchild,totelder,totadult,nocharge,referral,brent,scharge,pscharge,supcharg,tcharge,tshortfall,chcharge,has_benefits,renewal,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat2,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,shelteredaccom,form,owningorgid,owningorgname,hcnum,maningorgid,maningorgname,manhcnum,createddate,uploaddate,tenancycode,ppcodenk -2,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,0,1,0,1,2,0,5,1,SE26RT,6,7,3,2,1,68,1,1,2,2,1,NW15TY,1,1,1,0,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05 10:36:49 UTC,0,2022-02-02 10:36:49 UTC,1,2,1,2019-11-03 00:00:00 UTC,2,1,7,0,0,2,0,,200.0,50.0,40.0,35.0,325.0,12.0,,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,0,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-02-08 16:52:15 UTC,2022-02-08 16:52:15 UTC,BZ757,1 +2,35,F,2,4,6,0,2,32,M,6,,,,,,,,,,,,,,,,,,,1,0,1,0,1,2,0,5,1,SE26RT,6,7,3,2,1,68,1,1,2,2,1,NW15TY,1,1,1,0,,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,,,4,123,E09000003,E07000105,6,1,2020-05-05 10:36:49 UTC,0,2022-02-02 10:36:49 UTC,1,2,1,2019-11-03 00:00:00 UTC,2,1,7,0,0,2,0,,200.0,50.0,40.0,35.0,325.0,12.0,,1,0,100.0,25.0,20.0,17.5,162.5,6.0,0,1,,2,P,,,,,,,,,,0,{id},{owning_org_id},DLUHC,1234,{managing_org_id},DLUHC,1234,2022-02-08 16:52:15 UTC,2022-02-08 16:52:15 UTC,BZ737,1 diff --git a/spec/fixtures/exports/case_logs.xml b/spec/fixtures/exports/case_logs.xml index 1b899d444..3e12ec610 100644 --- a/spec/fixtures/exports/case_logs.xml +++ b/spec/fixtures/exports/case_logs.xml @@ -139,7 +139,7 @@ 1234 2022-02-08 16:52:15 UTC 2022-02-08 16:52:15 UTC - BZ757 + BZ737 1 1 diff --git a/spec/fixtures/softwire_imports/case_logs/5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd.xml b/spec/fixtures/softwire_imports/case_logs/5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd.xml new file mode 100644 index 000000000..2531314dd --- /dev/null +++ b/spec/fixtures/softwire_imports/case_logs/5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd.xml @@ -0,0 +1,514 @@ + + + 2021-CORE-IR-GN + 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd + e29c492473446dca4d50224f2bb7cf965a261d6f + 7c5bd5fb549c09a2c55d7cb90d7ba84927e64618 + 7c5bd5fb549c09a2c55d7cb90d7ba84927e64618 + 2022-04-11T13:46:23.953121Z + 2022-04-11T13:46:23.953121Z + submitted-valid + 2021 + Manual Entry + + + + + Yes + 2 London Living Rent + + 2021-11-10 +
300072
+ 1 Private Registered Provider + + <_1btenagree>1 This Landlord + <_1bifanother/> + <_1bCOREcode/> + +
+ + <_2a>2 No + 2 Assured + + <_2bTenCode>TEN0021 + <_2cYears/> + + + 37 + + Female + 1) Full Time + 1 White: English/Scottish/Welsh/Northern Irish/British + 1 UK national resident in UK + 34 + + Female + Other + 1) Full Time + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 No + + + 2 No + + + 7 UC – without housing element (not in receipt of HB and tenants not eligible for housing support e.g. residential care home) + + + 3 None + + + + + + 8 (Non-violent) relationship breakdown with partner + + + + <_9b override-field="">2 No + + + + + Yes + + 1 Yes + + + + Yes + + + + + + + 28 Living with friends or family + Blackpool + E09000009 + FY1 1JD + + 1 Just moved to Local Authority area + 1 Just moved to Local Authority area + + + 1 Not homeless + 2 No + + + + + + + + 2 No + 2 No + 2 No + + + 10 Other social landlord + + + + 1 Weekly for 52 weeks + 100.00 + + + + 100.00 + + + 2021-04-15 + + 0 + PROPREF0042 + + + + 1 Flat / maisonette + 1 Purpose built + 2 No + 4 An Intermediate Rent basis + 10 Relet - tenant evicted due to arrears + + + Basingstoke & Deane + E07000084 + RG21 3HU + + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + <_100>0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + <_70>0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 37 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 37 + 0 + 37 + 2022-04-12Z + 2022-04-27Z + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 20 + 0 + 20 + C + 1 + 1 + 1 + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 2 + 2 Existing Tenant + 1 + 1 + 209 + 2 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 = 2 adults + 200.00 + 200.00 + 13 + + 200.00 + 1 Private Registered Provider + + + E12000008 + 1 + DLUHC + DLUHC + 655 + 655 + + 1 + + + + + + + + + + + + + 13 + + + 13 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 100.00 + 100.00 + + + + 0.00 + + + + 100.00 + 100.00 + + + + 0 + + + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 100.00 + 23.35 + + 0 + 0 + 0 + + + 0 + 0 + 23.35 + 0 + 0 + 0 + 0 + 0 + 0 + 10 + 11 + 2021 + 15 + 4 + 2021 + + + + FY1 + 1JD + + + +
diff --git a/spec/fixtures/softwire_imports/case_logs/893ufj2s-lq77-42m4-rty6-ej09gh585uy1.xml b/spec/fixtures/softwire_imports/case_logs/893ufj2s-lq77-42m4-rty6-ej09gh585uy1.xml new file mode 100644 index 000000000..f01bb1baa --- /dev/null +++ b/spec/fixtures/softwire_imports/case_logs/893ufj2s-lq77-42m4-rty6-ej09gh585uy1.xml @@ -0,0 +1,514 @@ + + + 2021-CORE-IR-GN + 893ufj2s-lq77-42m4-rty6-ej09gh585uy1 + e29c492473446dca4d50224f2bb7cf965a261d6f + 7c5bd5fb549c09a2c55d7cb90d7ba84927e64618 + 7c5bd5fb549c09a2c55d7cb90d7ba84927e64618 + 2022-04-11T13:46:23.953121Z + 2022-04-11T13:46:23.953121Z + submitted-valid + 2021 + Manual Entry + + + + + Yes + 2 London Living Rent + + 2021-11-10 +
300072
+ 1 Private Registered Provider + + <_1btenagree>1 This Landlord + <_1bifanother/> + <_1bCOREcode/> + +
+ + <_2a>2 No + 2 Assured + + <_2bTenCode>TEN0021 + <_2cYears/> + + + 37 + + Female + 1) Full Time + 1 White: English/Scottish/Welsh/Northern Irish/British + 1 UK national resident in UK + 34 + + Female + Other + 1) Full Time + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 No + + + 2 No + + + 7 UC – without housing element (not in receipt of HB and tenants not eligible for housing support e.g. residential care home) + + + 3 None + + + + + + 8 (Non-violent) relationship breakdown with partner + + + + <_9b override-field="">2 No + + + + + Yes + + 1 Yes + + + + Yes + + + + + + + 28 Living with friends or family + Blackpool + E09000009 + FY1 1JD + + 1 Just moved to Local Authority area + 1 Just moved to Local Authority area + + + 1 Not homeless + 2 No + + + + + + + + 2 No + 2 No + 2 No + + + 10 Other social landlord + + + + 1 Weekly for 52 weeks + 100.00 + + + + 100.00 + + + 2021-04-15 + + 0 + PROPREF0042 + + + + 1 Flat / maisonette + 1 Purpose built + 2 No + 4 An Intermediate Rent basis + 10 Relet - tenant evicted due to arrears + + + Basingstoke & Deane + E07000084 + RG21 3HU + + + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + <_100>0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + <_70>0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 37 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 37 + 0 + 37 + 2022-04-12Z + 2022-04-27Z + + + + + + + + + + + + + 0 + 0 + 0 + 0 + 20 + 0 + 20 + C + 1 + 1 + 1 + 1 + 4 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 2 + 2 Existing Tenant + 1 + 1 + 209 + 2 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 4 = 2 adults + 200.00 + 200.00 + 13 + + 200.00 + 1 Private Registered Provider + + + E12000008 + 1 + DLUHC + DLUHC + 655 + 655 + + 1 + + + + + + + + + + + + + 13 + + + 13 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + 100.00 + 100.00 + + + + 0.00 + + + + 100.00 + 100.00 + + + + 0 + + + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 100.00 + 23.35 + + 0 + 0 + 0 + + + 0 + 0 + 23.35 + 0 + 0 + 0 + 0 + 0 + 0 + 10 + 11 + 2021 + 15 + 4 + 2021 + + + + FY1 + 1JD + + + +
diff --git a/spec/lib/tasks/data_import_spec.rb b/spec/lib/tasks/data_import_spec.rb index 3d69913a9..d1023b100 100644 --- a/spec/lib/tasks/data_import_spec.rb +++ b/spec/lib/tasks/data_import_spec.rb @@ -4,13 +4,9 @@ require "rake" describe "rake core:data_import", type: :task do subject(:task) { Rake::Task["core:data_import"] } - let(:fixture_path) { "spec/fixtures/softwire_imports/organisations" } let(:instance_name) { "paas_import_instance" } - let(:type) { "organisation" } - let(:storage_service) { instance_double(StorageService) } let(:paas_config_service) { instance_double(PaasConfigurationService) } - let(:import_service) { instance_double(Imports::OrganisationImportService) } before do Rake.application.rake_require("tasks/data_import") @@ -24,6 +20,10 @@ describe "rake core:data_import", type: :task do end context "when importing organisation data" do + let(:type) { "organisation" } + let(:import_service) { instance_double(Imports::OrganisationImportService) } + let(:fixture_path) { "spec/fixtures/softwire_imports/organisations" } + before do allow(Imports::OrganisationImportService).to receive(:new).and_return(import_service) end @@ -40,6 +40,7 @@ describe "rake core:data_import", type: :task do context "when importing user data" do let(:type) { "user" } let(:import_service) { instance_double(Imports::UserImportService) } + let(:fixture_path) { "spec/fixtures/softwire_imports/users" } before do allow(Imports::UserImportService).to receive(:new).and_return(import_service) diff --git a/spec/lib/tasks/date_import_field_spec.rb b/spec/lib/tasks/date_import_field_spec.rb new file mode 100644 index 000000000..e86cecf1d --- /dev/null +++ b/spec/lib/tasks/date_import_field_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" +require "rake" + +describe "rake core:data_import_field", type: :task do + subject(:task) { Rake::Task["core:data_import_field"] } + + let(:instance_name) { "paas_import_instance" } + let(:storage_service) { instance_double(StorageService) } + let(:paas_config_service) { instance_double(PaasConfigurationService) } + + before do + Rake.application.rake_require("tasks/data_import_field") + Rake::Task.define_task(:environment) + task.reenable + + allow(StorageService).to receive(:new).and_return(storage_service) + allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service) + allow(ENV).to receive(:[]) + allow(ENV).to receive(:[]).with("IMPORT_PAAS_INSTANCE").and_return(instance_name) + end + + context "when importing a case log field" do + let(:import_service) { instance_double(Imports::CaseLogsFieldImportService) } + let(:fixture_path) { "spec/fixtures/softwire_imports/case_logs" } + + before do + allow(Imports::CaseLogsFieldImportService).to receive(:new).and_return(import_service) + allow(import_service).to receive(:update_field) + end + + context "and we update the tenant_code field" do + let(:field) { "tenant_code" } + + it "properly configures the storage service" do + expect(StorageService).to receive(:new).with(paas_config_service, instance_name) + task.invoke(field, fixture_path) + end + + it "calls the expected update method with parameters" do + expect(import_service).to receive(:update_field).with(field, fixture_path) + task.invoke(field, fixture_path) + end + end + + it "raises an exception if no parameters are provided" do + expect { task.invoke }.to raise_error(/Usage/) + end + + it "raises an exception if a single parameter is provided" do + expect { task.invoke("one_parameter") }.to raise_error(/Usage/) + end + + it "raises an exception if the field is not supported" do + expect { task.invoke("random_field", "my_path") }.to raise_error("Field random_field cannot be updated by data_import_field") + end + end +end diff --git a/spec/models/admin_user_spec.rb b/spec/models/admin_user_spec.rb deleted file mode 100644 index 5510325d1..000000000 --- a/spec/models/admin_user_spec.rb +++ /dev/null @@ -1,84 +0,0 @@ -require "rails_helper" - -RSpec.describe AdminUser, type: :model do - describe "#new" do - it "requires a phone number" do - expect { - described_class.create!( - email: "admin_test@example.com", - password: "password123", - ) - }.to raise_error(ActiveRecord::RecordInvalid) - end - - it "requires a numerical phone number" do - expect { - described_class.create!( - email: "admin_test@example.com", - password: "password123", - phone: "string", - ) - }.to raise_error(ActiveRecord::RecordInvalid) - end - - it "requires an email" do - expect { - described_class.create!( - password: "password123", - phone: "075752137", - ) - }.to raise_error(ActiveRecord::RecordInvalid) - end - - it "requires a password" do - expect { - described_class.create!( - email: "admin_test@example.com", - phone: "075752137", - ) - }.to raise_error(ActiveRecord::RecordInvalid) - end - - it "can be created" do - expect { - described_class.create!( - email: "admin_test@example.com", - password: "password123", - phone: "075752137", - ) - }.to change(described_class, :count).by(1) - end - end - - describe "paper trail" do - let(:admin_user) { FactoryBot.create(:admin_user) } - - it "creates a record of changes to a log" do - expect { admin_user.update!(phone: "09673867853") }.to change(admin_user.versions, :count).by(1) - end - - it "allows case logs to be restored to a previous version" do - admin_user.update!(phone: "09673867853") - expect(admin_user.paper_trail.previous_version.phone).to eq("07563867654") - end - - it "signing in does not create a new version" do - expect { - admin_user.update!( - last_sign_in_at: Time.zone.now, - current_sign_in_at: Time.zone.now, - current_sign_in_ip: "127.0.0.1", - last_sign_in_ip: "127.0.0.1", - failed_attempts: 3, - unlock_token: "dummy", - locked_at: Time.zone.now, - reset_password_token: "dummy", - reset_password_sent_at: Time.zone.now, - remember_created_at: Time.zone.now, - sign_in_count: 5, - updated_at: Time.zone.now, - ) - }.not_to change(admin_user.versions, :count) - end - end -end diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb index 33389c28d..96ee7824f 100644 --- a/spec/models/case_log_spec.rb +++ b/spec/models/case_log_spec.rb @@ -1871,6 +1871,102 @@ RSpec.describe CaseLog do FactoryBot.create(:case_log, startdate: Time.utc(2022, 6, 3)) end + context "when searching logs" do + let!(:case_log_to_search) { FactoryBot.create(:case_log, :completed) } + + before do + FactoryBot.create_list(:case_log, 5, :completed) + end + + describe "#filter_by_id" do + it "allows searching by a log ID" do + result = described_class.filter_by_id(case_log_to_search.id.to_s) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + end + + describe "#filter_by_tenant_code" do + it "allows searching by a Tenant Code" do + result = described_class.filter_by_tenant_code(case_log_to_search.tenant_code) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + context "when tenant_code has lower case letters" do + let(:matching_tenant_code_lower_case) { case_log_to_search.tenant_code.downcase } + + it "allows searching by a Tenant Code" do + result = described_class.filter_by_tenant_code(matching_tenant_code_lower_case) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + end + end + + describe "#filter_by_propcode" do + it "allows searching by a Property Reference" do + result = described_class.filter_by_propcode(case_log_to_search.propcode) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + context "when propcode has lower case letters" do + let(:matching_propcode_lower_case) { case_log_to_search.propcode.downcase } + + it "allows searching by a Property Reference" do + result = described_class.filter_by_propcode(matching_propcode_lower_case) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + end + end + + describe "#filter_by_postcode" do + it "allows searching by a Property Postcode" do + result = described_class.filter_by_postcode(case_log_to_search.postcode_full) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + end + + describe "#search_by" do + it "allows searching using ID" do + result = described_class.search_by(case_log_to_search.id.to_s) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + it "allows searching using tenancy code" do + result = described_class.search_by(case_log_to_search.tenant_code) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + it "allows searching by a Property Reference" do + result = described_class.search_by(case_log_to_search.propcode) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + it "allows searching by a Property Postcode" do + result = described_class.search_by(case_log_to_search.postcode_full) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + + context "when postcode has spaces and lower case letters" do + let(:matching_postcode_lower_case_with_spaces) { case_log_to_search.postcode_full.downcase.chars.insert(3, " ").join } + + it "allows searching by a Property Postcode" do + result = described_class.search_by(matching_postcode_lower_case_with_spaces) + expect(result.count).to eq(1) + expect(result.first.id).to eq case_log_to_search.id + end + end + end + end + context "when filtering by year" do it "allows filtering on a single year" do expect(described_class.filter_by_years(%w[2021]).count).to eq(2) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index df3f82911..646e65d2a 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -85,6 +85,18 @@ RSpec.describe User, type: :model do ) end + it "does not send a confirmation email to inactive users" do + expect(DeviseNotifyMailer).not_to receive(:confirmation_instructions) + described_class.create!( + name: "unconfirmed_user", + email: "unconfirmed_user@example.com", + password: "password123", + organisation: other_organisation, + role: "data_provider", + active: false, + ) + end + context "when the user is a data provider" do it "cannot assign roles" do expect(user.assignable_roles).to eq({}) diff --git a/spec/requests/auth/passwords_controller_spec.rb b/spec/requests/auth/passwords_controller_spec.rb index 0615e8257..888bb8c70 100644 --- a/spec/requests/auth/passwords_controller_spec.rb +++ b/spec/requests/auth/passwords_controller_spec.rb @@ -73,78 +73,6 @@ RSpec.describe Auth::PasswordsController, type: :request do end end - context "when an admin user" do - let(:admin_user) { FactoryBot.create(:admin_user) } - - describe "reset password" do - let(:new_value) { "new-password" } - - before do - allow(DeviseNotifyMailer).to receive(:notify_client).and_return(notify_client) - allow(notify_client).to receive(:send_email).and_return(true) - end - - it "renders the user edit password view" do - _raw, enc = Devise.token_generator.generate(AdminUser, :reset_password_token) - get "/admin/password/edit?reset_password_token=#{enc}" - expect(page).to have_css("h1", text: I18n.t("user.reset_password")) - end - - context "when passwords entered don't match" do - let(:raw) { admin_user.send_reset_password_instructions } - let(:params) do - { - id: admin_user.id, - admin_user: { - password: new_value, - password_confirmation: "something_else", - reset_password_token: raw, - }, - } - end - - it "shows an error" do - put "/admin/password", headers: headers, params: params - expect(response).to have_http_status(:unprocessable_entity) - expect(page).to have_content("doesn’t match new password") - end - end - - context "when passwords is reset" do - let(:raw) { admin_user.send_reset_password_instructions } - let(:params) do - { - id: admin_user.id, - admin_user: { - password: new_value, - password_confirmation: new_value, - reset_password_token: raw, - }, - } - end - - it "updates the password" do - expect { - put "/admin/password", headers: headers, params: params - admin_user.reload - }.to change(admin_user, :encrypted_password) - end - - it "sends you to the 2FA page and does not allow bypassing 2FA code" do - put "/admin/password", headers: headers, params: params - expect(response).to redirect_to("/admin/two-factor-authentication") - get "/admin/case_logs", headers: headers - expect(response).to redirect_to("/admin/two-factor-authentication") - end - - it "triggers an email" do - expect(notify_client).to receive(:send_email) - put "/admin/password", headers:, params: - end - end - end - end - context "when a customer support user" do let(:support_user) { FactoryBot.create(:user, :support) } diff --git a/spec/requests/case_logs_controller_spec.rb b/spec/requests/case_logs_controller_spec.rb index 51fe25fe3..ef78e0b5f 100644 --- a/spec/requests/case_logs_controller_spec.rb +++ b/spec/requests/case_logs_controller_spec.rb @@ -8,7 +8,7 @@ RSpec.describe CaseLogsController, type: :request do let(:api_password) { "test_password" } let(:basic_credentials) do ActionController::HttpAuthentication::Basic - .encode_credentials(api_username, api_password) + .encode_credentials(api_username, api_password) end let(:headers) do @@ -184,6 +184,17 @@ RSpec.describe CaseLogsController, type: :request do expect(page).to have_content("UA984") end + context "when there are no logs in the database" do + before do + CaseLog.destroy_all + end + + it "page has correct title" do + get "/logs", headers: headers, params: {} + expect(page).to have_title("Your organisation (Logs) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + end + context "when filtering" do context "with status filter" do let(:organisation_2) { FactoryBot.create(:organisation) } @@ -308,6 +319,113 @@ RSpec.describe CaseLogsController, type: :request do expect(page).not_to have_content("Managing organisation") end + context "when using a search query" do + let(:logs) { FactoryBot.create_list(:case_log, 3, :completed, owning_organisation: user.organisation) } + let(:log_to_search) { FactoryBot.create(:case_log, :completed, owning_organisation: user.organisation) } + let(:log_total_count) { CaseLog.where(owning_organisation: user.organisation).count } + + it "has search results in the title" do + get "/logs?search=#{log_to_search.id}", headers: headers, params: {} + expect(page).to have_title("Your organisation (1 log matching ‘#{log_to_search.id}’ of #{log_total_count} total logs) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + + it "shows case logs matching the id" do + get "/logs?search=#{log_to_search.id}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the tenant code" do + get "/logs?search=#{log_to_search.tenant_code}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the property reference" do + get "/logs?search=#{log_to_search.propcode}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the property postcode" do + get "/logs?search=#{log_to_search.postcode_full}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + context "when more than one results with matching postcode" do + let!(:matching_postcode_log) { FactoryBot.create(:case_log, :completed, owning_organisation: user.organisation, postcode_full: log_to_search.postcode_full) } + + it "displays all matching logs" do + get "/logs?search=#{log_to_search.postcode_full}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + expect(page).to have_link(matching_postcode_log.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + end + + context "when there are more than 1 page of search results" do + let(:postcode) { "XX11YY" } + let(:logs) { FactoryBot.create_list(:case_log, 30, :completed, owning_organisation: user.organisation, postcode_full: postcode) } + let(:log_total_count) { CaseLog.where(owning_organisation: user.organisation).count } + + it "has title with pagination details for page 1" do + get "/logs?search=#{logs[0].postcode_full}", headers: headers, params: {} + expect(page).to have_title("Your organisation (#{logs.count} logs matching ‘#{postcode}’ of #{log_total_count} total logs) (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + + it "has title with pagination details for page 2" do + get "/logs?search=#{logs[0].postcode_full}&page=2", headers: headers, params: {} + expect(page).to have_title("Your organisation (#{logs.count} logs matching ‘#{postcode}’ of #{log_total_count} total logs) (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + end + + context "when search query doesn't match any logs" do + it "doesn't display any logs" do + get "/logs?search=foobar", headers:, params: {} + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + expect(page).not_to have_link(log_to_search.id.to_s) + end + end + + context "when search query is empty" do + it "doesn't display any logs" do + get "/logs?search=", headers:, params: {} + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + expect(page).not_to have_link(log_to_search.id.to_s) + end + end + + context "when search and filter is present" do + let(:matching_postcode) { log_to_search.postcode_full } + let(:matching_status) { "in_progress" } + let!(:log_matching_filter_and_search) { FactoryBot.create(:case_log, :in_progress, owning_organisation: user.organisation, postcode_full: matching_postcode) } + + it "shows only logs matching both search and filters" do + get "/logs?search=#{matching_postcode}&status[]=#{matching_status}", headers: headers, params: {} + expect(page).to have_link(log_matching_filter_and_search.id.to_s) + expect(page).not_to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + end + end + context "when there are less than 20 logs" do before do get "/logs", headers:, params: {} @@ -348,7 +466,7 @@ RSpec.describe CaseLogsController, type: :request do end it "does not have pagination in the title" do - expect(page).to have_title("Logs") + expect(page).to have_title("Your organisation (Logs) - Submit social housing lettings and sales data (CORE) - GOV.UK") end it "shows the download csv link" do @@ -424,7 +542,7 @@ RSpec.describe CaseLogsController, type: :request do end it "has pagination in the title" do - expect(page).to have_title("Logs (page 1 of 2)") + expect(page).to have_title("Your organisation (Logs) (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") end end @@ -449,7 +567,7 @@ RSpec.describe CaseLogsController, type: :request do end it "has pagination in the title" do - expect(page).to have_title("Logs (page 2 of 2)") + expect(page).to have_title("Your organisation (Logs) (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") end end end @@ -638,6 +756,27 @@ RSpec.describe CaseLogsController, type: :request do csv = CSV.parse(response.body) expect(csv.count).to eq(2) end + + it "dowloads searched logs" do + get "/logs?search=#{case_log.id}", headers:, params: {} + csv = CSV.parse(response.body) + expect(csv.count).to eq(2) + end + + context "when both filter and search applied" do + let(:postcode) { "XX1 1TG" } + + before do + FactoryBot.create(:case_log, :in_progress, postcode_full: postcode, owning_organisation: organisation) + FactoryBot.create(:case_log, :completed, postcode_full: postcode, owning_organisation: organisation) + end + + it "dowloads logs matching both csv and filter logs" do + get "/logs?status[]=completed&search=#{postcode}", headers:, params: {} + csv = CSV.parse(response.body) + expect(csv.count).to eq(2) + end + end end context "when there are more than 20 logs" do diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb index 841439ea9..bab5ae6ed 100644 --- a/spec/requests/organisations_controller_spec.rb +++ b/spec/requests/organisations_controller_spec.rb @@ -379,10 +379,6 @@ RSpec.describe OrganisationsController, type: :request do get "/organisations/#{organisation.id}/logs", headers:, params: {} end - it "displays the name of the organisation in the header" do - expect(CGI.unescape_html(response.body)).to match("#{organisation.name}") - end - it "only shows logs for that organisation" do expect(page).to have_content("#{number_of_org1_case_logs} total logs") organisation.case_logs.map(&:id).each do |case_log_id| @@ -407,6 +403,113 @@ RSpec.describe OrganisationsController, type: :request do expect(page).to have_css(".app-sub-navigation") expect(page).to have_content("About this organisation") end + + context "when using a search query" do + let(:logs) { FactoryBot.create_list(:case_log, 3, :completed, owning_organisation: user.organisation) } + let(:log_to_search) { FactoryBot.create(:case_log, :completed, owning_organisation: user.organisation) } + let(:log_total_count) { CaseLog.where(owning_organisation: user.organisation).count } + + it "has search results in the title" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.id}", headers: headers, params: {} + expect(page).to have_title("Your organisation (1 log matching ‘#{log_to_search.id}’ of #{log_total_count} total logs) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + + it "shows case logs matching the id" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.id}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the tenant code" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.tenant_code}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the property reference" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.propcode}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + it "shows case logs matching the property postcode" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.postcode_full}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + + context "when more than one results with matching postcode" do + let!(:matching_postcode_log) { FactoryBot.create(:case_log, :completed, owning_organisation: user.organisation, postcode_full: log_to_search.postcode_full) } + + it "displays all matching logs" do + get "/organisations/#{organisation.id}/logs?search=#{log_to_search.postcode_full}", headers: headers, params: {} + expect(page).to have_link(log_to_search.id.to_s) + expect(page).to have_link(matching_postcode_log.id.to_s) + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + end + end + + context "when there are more than 1 page of search results" do + let(:postcode) { "XX11YY" } + let(:logs) { FactoryBot.create_list(:case_log, 30, :completed, owning_organisation: user.organisation, postcode_full: postcode) } + let(:log_total_count) { CaseLog.where(owning_organisation: user.organisation).count } + + it "has title with pagination details for page 1" do + get "/organisations/#{organisation.id}/logs?search=#{logs[0].postcode_full}", headers: headers, params: {} + expect(page).to have_title("Your organisation (#{logs.count} logs matching ‘#{postcode}’ of #{log_total_count} total logs) (page 1 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + + it "has title with pagination details for page 2" do + get "/organisations/#{organisation.id}/logs?search=#{logs[0].postcode_full}&page=2", headers: headers, params: {} + expect(page).to have_title("Your organisation (#{logs.count} logs matching ‘#{postcode}’ of #{log_total_count} total logs) (page 2 of 2) - Submit social housing lettings and sales data (CORE) - GOV.UK") + end + end + + context "when search query doesn't match any logs" do + it "doesn't display any logs" do + get "/organisations/#{organisation.id}/logs?search=foobar", headers:, params: {} + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + expect(page).not_to have_link(log_to_search.id.to_s) + end + end + + context "when search query is empty" do + it "doesn't display any logs" do + get "/organisations/#{organisation.id}/logs?search=", headers:, params: {} + logs.each do |log| + expect(page).not_to have_link(log.id.to_s) + end + expect(page).not_to have_link(log_to_search.id.to_s) + end + end + + context "when search and filter is present" do + let(:matching_postcode) { log_to_search.postcode_full } + let(:matching_status) { "in_progress" } + let!(:log_matching_filter_and_search) { FactoryBot.create(:case_log, :in_progress, owning_organisation: user.organisation, postcode_full: matching_postcode) } + + it "shows only logs matching both search and filters" do + get "/organisations/#{organisation.id}/logs?search=#{matching_postcode}&status[]=#{matching_status}", headers: headers, params: {} + expect(page).to have_content(log_matching_filter_and_search.id) + expect(page).not_to have_content(log_to_search.id) + logs.each do |log| + expect(page).not_to have_content(log.id) + end + end + end + end end context "when viewing a specific organisation details" do diff --git a/spec/requests/rack_attack_spec.rb b/spec/requests/rack_attack_spec.rb index a7d4bd34c..25ad55cac 100644 --- a/spec/requests/rack_attack_spec.rb +++ b/spec/requests/rack_attack_spec.rb @@ -12,11 +12,8 @@ describe "Rack::Attack" do let(:devise_notify_mailer) { DeviseNotifyMailer.new } let(:params) { { user: { email: } } } - let(:admin_params) { { admin_user: { email: admin_email } } } let(:user) { FactoryBot.create(:user) } - let(:admin_user) { FactoryBot.create(:admin_user) } let(:email) { user.email } - let(:admin_email) { admin_user.email } before do Rack::Attack.enabled = true @@ -40,15 +37,6 @@ describe "Rack::Attack" do last_response = response expect(last_response.status).to eq(200) end - - it "does not throttle for an admin user" do - under_limit.times do - post "/admin/password", params: admin_params - follow_redirect! - end - last_response = response - expect(last_response.status).to eq(200) - end end context "when the number of requests is at the throttle limit" do @@ -60,26 +48,6 @@ describe "Rack::Attack" do last_response = response expect(last_response.status).to eq(200) end - - it "does not throttle for an admin user" do - limit.times do - post "/admin/password", params: admin_params - follow_redirect! - end - last_response = response - expect(last_response.status).to eq(200) - end - - it "does not throttle if both endpoints are hit" do - limit.times do - post "/account/password", params: params - follow_redirect! - post "/admin/password", params: admin_params - follow_redirect! - end - last_response = response - expect(last_response.status).to eq(200) - end end context "when the number of requests is over the throttle limit" do @@ -91,15 +59,6 @@ describe "Rack::Attack" do last_response = response expect(last_response.status).to eq(429) end - - it "throttles for an admin user" do - over_limit.times do - post "/admin/password", params: admin_params - follow_redirect! - end - last_response = response - expect(last_response.status).to eq(429) - end end end end diff --git a/spec/services/exports/case_log_export_service_spec.rb b/spec/services/exports/case_log_export_service_spec.rb index 0e5f7095e..e172716d9 100644 --- a/spec/services/exports/case_log_export_service_spec.rb +++ b/spec/services/exports/case_log_export_service_spec.rb @@ -47,7 +47,7 @@ RSpec.describe Exports::CaseLogExportService do end context "and one case log is available for export" do - let!(:case_log) { FactoryBot.create(:case_log, :completed) } + let!(:case_log) { FactoryBot.create(:case_log, :completed, tenancy_code: "BZ757", propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenant_code: "BZ737") } let(:expected_data_filename) { "core_2021_2022_jan_mar_f0001_inc0001_pt001.xml" } it "generates a ZIP export file with the expected filename" do @@ -226,7 +226,7 @@ RSpec.describe Exports::CaseLogExportService do let(:csv_export_file) { File.open("spec/fixtures/exports/case_logs.csv", "r:UTF-8") } let(:expected_csv_filename) { "export_2022_05_01.csv" } - let(:case_log) { FactoryBot.create(:case_log, :completed) } + let(:case_log) { FactoryBot.create(:case_log, :completed, tenancy_code: "BZ757", propcode: "123", ppostcode_full: "SE2 6RT", postcode_full: "NW1 5TY", tenant_code: "BZ737") } it "generates an CSV export file with the expected content" do expected_content = replace_entity_ids(case_log, csv_export_file.read) diff --git a/spec/services/imports/case_logs_field_import_service_spec.rb b/spec/services/imports/case_logs_field_import_service_spec.rb new file mode 100644 index 000000000..c071b1ea7 --- /dev/null +++ b/spec/services/imports/case_logs_field_import_service_spec.rb @@ -0,0 +1,76 @@ +require "rails_helper" + +RSpec.describe Imports::CaseLogsFieldImportService do + subject(:import_service) { described_class.new(storage_service, logger) } + + let(:storage_service) { instance_double(StorageService) } + let(:logger) { instance_double(ActiveSupport::Logger) } + + let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") } + let(:fixture_directory) { "spec/fixtures/softwire_imports/case_logs" } + + def open_file(directory, filename) + File.open("#{directory}/#{filename}.xml") + end + + before do + # Owning and Managing organisations + FactoryBot.create(:organisation, old_visible_id: "1", provider_type: "PRP") + + # Created by users + FactoryBot.create(:user, old_user_id: "c3061a2e6ea0b702e6f6210d5c52d2a92612d2aa") + + # Stub the form handler to use the real form + allow(FormHandler.instance).to receive(:get_form).with("2021_2022").and_return(real_2021_2022_form) + + WebMock.stub_request(:get, /api.postcodes.io\/postcodes\/LS166FT/) + .to_return(status: 200, body: '{"status":200,"result":{"codes":{"admin_district":"E08000035"}}}', headers: {}) + end + + context "when updating a specific log value" do + let(:case_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } + let(:case_log_file) { open_file(fixture_directory, case_log_id) } + let(:case_log_xml) { Nokogiri::XML(case_log_file) } + let(:remote_folder) { "case_logs" } + let(:field) { "tenant_code" } + + before do + # Stub the S3 file listing and download + allow(storage_service).to receive(:list_files) + .and_return(["#{remote_folder}/#{case_log_id}.xml"]) + allow(storage_service).to receive(:get_file_io) + .with("#{remote_folder}/#{case_log_id}.xml") + .and_return(case_log_file) + end + + context "and the case log was previously imported" do + let(:case_log) { CaseLog.find_by(old_id: case_log_id) } + + before do + Imports::CaseLogsImportService.new(storage_service, logger).create_logs(fixture_directory) + case_log_file.rewind + end + + it "logs that the tenant_code already has a value and does not update the case_log" do + expect(logger).to receive(:info).with(/Case Log \d+ has a value for tenant_code, skipping update/) + expect { import_service.send(:update_field, field, remote_folder) } + .not_to(change { case_log.reload.tenant_code }) + end + end + + context "and the case log was previously imported with empty fields" do + let(:case_log) { CaseLog.find_by(old_id: case_log_id) } + + before do + Imports::CaseLogsImportService.new(storage_service, logger).create_logs(fixture_directory) + case_log_file.rewind + case_log.update!(tenant_code: nil) + end + + it "updates the case_log" do + expect { import_service.send(:update_field, field, remote_folder) } + .to(change { case_log.reload.tenant_code }) + end + end + end +end diff --git a/spec/services/imports/case_logs_import_service_spec.rb b/spec/services/imports/case_logs_import_service_spec.rb index 0f1ee40b6..797a42e16 100644 --- a/spec/services/imports/case_logs_import_service_spec.rb +++ b/spec/services/imports/case_logs_import_service_spec.rb @@ -30,7 +30,7 @@ RSpec.describe Imports::CaseLogsImportService do .to_return(status: 200, body: '{"status":200,"result":{"codes":{"admin_district":"E08000035"}}}', headers: {}) end - context "when importing users" do + context "when importing case logs" do let(:remote_folder) { "case_logs" } let(:case_log_id) { "0ead17cb-1668-442d-898c-0d52879ff592" } let(:case_log_id2) { "166fc004-392e-47a8-acb8-1c018734882b" } @@ -66,6 +66,39 @@ RSpec.describe Imports::CaseLogsImportService do expect { 2.times { case_log_service.create_logs(remote_folder) } } .to change(CaseLog, :count).by(3) end + + context "when there are status discrepancies" do + let(:case_log_id4) { "893ufj2s-lq77-42m4-rty6-ej09gh585uy1" } + let(:case_log_id5) { "5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd" } + let(:case_log_file) { open_file(fixture_directory, case_log_id4) } + let(:case_log_xml) { Nokogiri::XML(case_log_file) } + + before do + allow(storage_service).to receive(:get_file_io) + .with("#{remote_folder}/#{case_log_id4}.xml") + .and_return(open_file(fixture_directory, case_log_id4), open_file(fixture_directory, case_log_id4)) + allow(storage_service).to receive(:get_file_io) + .with("#{remote_folder}/#{case_log_id5}.xml") + .and_return(open_file(fixture_directory, case_log_id5), open_file(fixture_directory, case_log_id5)) + end + + it "the logger logs a warning with the case log's old id/filename" do + expect(logger).to receive(:warn).with(/is not completed/).once + expect(logger).to receive(:warn).with(/Case log with old id:#{case_log_id4} is incomplete but status should be complete/).once + + case_log_service.send(:create_log, case_log_xml) + end + + it "on completion the ids of all logs with status discrepancies are logged in a warning" do + allow(storage_service).to receive(:list_files) + .and_return(%W[#{remote_folder}/#{case_log_id4}.xml #{remote_folder}/#{case_log_id5}.xml]) + allow(logger).to receive(:warn).with(/is not completed/) + allow(logger).to receive(:warn).with(/is incomplete but status should be complete/) + expect(logger).to receive(:warn).with(/The following case logs had status discrepancies: \[893ufj2s-lq77-42m4-rty6-ej09gh585uy1, 5ybz29dj-l33t-k1l0-hj86-n4k4ma77xkcd\]/).once + + case_log_service.create_logs(remote_folder) + end + end end context "when importing a specific log" do @@ -78,6 +111,8 @@ RSpec.describe Imports::CaseLogsImportService do it "does not import the voiddate" do allow(logger).to receive(:warn).with(/is not completed/) + allow(logger).to receive(:warn).with(/Case log with old id:#{case_log_id} is incomplete but status should be complete/) + case_log_service.send(:create_log, case_log_xml) case_log = CaseLog.where(old_id: case_log_id).first diff --git a/spec/services/imports/organisation_la_import_service_spec.rb b/spec/services/imports/organisation_la_import_service_spec.rb index 8247c2b36..8d5784bb4 100644 --- a/spec/services/imports/organisation_la_import_service_spec.rb +++ b/spec/services/imports/organisation_la_import_service_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Imports::OrganisationLaImportService do let(:storage_service) { instance_double(StorageService) } let(:logger) { instance_double(ActiveSupport::Logger) } - context "when importing data protection confirmations" do + context "when importing organisation las" do subject(:import_service) { described_class.new(storage_service, logger) } before do diff --git a/spec/services/imports/organisation_rent_period_import_service_spec.rb b/spec/services/imports/organisation_rent_period_import_service_spec.rb index 39d2cf369..2921e5a4e 100644 --- a/spec/services/imports/organisation_rent_period_import_service_spec.rb +++ b/spec/services/imports/organisation_rent_period_import_service_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Imports::OrganisationRentPeriodImportService do let(:storage_service) { instance_double(StorageService) } let(:logger) { instance_double(ActiveSupport::Logger) } - context "when importing data protection confirmations" do + context "when importing organisation rent periods" do subject(:import_service) { described_class.new(storage_service, logger) } before do diff --git a/webpack.config.js b/webpack.config.js index 77eebab44..c22a0a141 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -13,10 +13,6 @@ module.exports = { entry: { application: [ "./app/frontend/application.js", - ], - active_admin: [ - './app/frontend/active_admin.js', - './app/frontend/styles/active_admin.scss' ] }, module: { @@ -68,12 +64,6 @@ module.exports = { { from: "app/frontend/vendor/outerHTML.js", to: "vendor" }, { from: "app/frontend/vendor/polyfill-output-value.js", to: "vendor" } ], - }), - new webpack.ProvidePlugin({ - $: 'jquery', - jQuery: 'jquery', - jquery: 'jquery', - 'window.jQuery': 'jquery' }) ] } diff --git a/yarn.lock b/yarn.lock index 3734c0edd..3cbc753f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,15 +2,6 @@ # yarn lockfile v1 -"@activeadmin/activeadmin@^2.11.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@activeadmin/activeadmin/-/activeadmin-2.12.0.tgz#f0f69fbc5828a538802512884304744e3d94a619" - integrity sha512-2paDrb1ZGy9T1W+LETV0nje/LmCqhqDZSEXtOKvRiC9zGMVh6IwjUD82C1ISfi5jg3VIrMihQ9tECIAS9d1f9w== - dependencies: - jquery "^3.4.1" - jquery-ui "^1.12.1" - jquery-ujs "^1.2.2" - "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -26,40 +17,40 @@ dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0", "@babel/compat-data@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.7.tgz#078d8b833fbbcc95286613be8c716cef2b519fa2" - integrity sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ== +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.17.10": + version "7.17.10" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" + integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== "@babel/core@^7.17.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.9.tgz#6bae81a06d95f4d0dec5bb9d74bbc1f58babdcfe" - integrity sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw== + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" + integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.9" - "@babel/helper-compilation-targets" "^7.17.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helpers" "^7.17.9" - "@babel/parser" "^7.17.9" + "@babel/generator" "^7.18.2" + "@babel/helper-compilation-targets" "^7.18.2" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helpers" "^7.18.2" + "@babel/parser" "^7.18.0" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.1" semver "^6.3.0" -"@babel/generator@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.9.tgz#f4af9fd38fa8de143c29fce3f71852406fc1e2fc" - integrity sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ== +"@babel/generator@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" + integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== dependencies: - "@babel/types" "^7.17.0" + "@babel/types" "^7.18.2" + "@jridgewell/gen-mapping" "^0.3.0" jsesc "^2.5.1" - source-map "^0.5.0" "@babel/helper-annotate-as-pure@^7.16.7": version "7.16.7" @@ -76,20 +67,20 @@ "@babel/helper-explode-assignable-expression" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz#a3c2924f5e5f0379b356d4cfb313d1414dc30e46" - integrity sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w== +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.10", "@babel/helper-compilation-targets@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" + integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== dependencies: - "@babel/compat-data" "^7.17.7" + "@babel/compat-data" "^7.17.10" "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" + browserslist "^4.20.2" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz#71835d7fb9f38bd9f1378e40a4c0902fdc2ea49d" - integrity sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ== +"@babel/helper-create-class-features-plugin@^7.17.12", "@babel/helper-create-class-features-plugin@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz#fac430912606331cb075ea8d82f9a4c145a4da19" + integrity sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" @@ -99,10 +90,10 @@ "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" -"@babel/helper-create-regexp-features-plugin@^7.16.7": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1" - integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA== +"@babel/helper-create-regexp-features-plugin@^7.16.7", "@babel/helper-create-regexp-features-plugin@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz#bb37ca467f9694bbe55b884ae7a5cc1e0084e4fd" + integrity sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" regexpu-core "^5.0.1" @@ -121,12 +112,10 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" +"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" + integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== "@babel/helper-explode-assignable-expression@^7.16.7": version "7.16.7" @@ -150,7 +139,7 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-member-expression-to-functions@^7.16.7", "@babel/helper-member-expression-to-functions@^7.17.7": +"@babel/helper-member-expression-to-functions@^7.17.7": version "7.17.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz#a34013b57d8542a8c4ff8ba3f747c02452a4d8c4" integrity sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw== @@ -164,10 +153,10 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-transforms@^7.16.7", "@babel/helper-module-transforms@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz#3943c7f777139e7954a5355c815263741a9c1cbd" - integrity sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw== +"@babel/helper-module-transforms@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" + integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== dependencies: "@babel/helper-environment-visitor" "^7.16.7" "@babel/helper-module-imports" "^7.16.7" @@ -175,8 +164,8 @@ "@babel/helper-split-export-declaration" "^7.16.7" "@babel/helper-validator-identifier" "^7.16.7" "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.18.0" + "@babel/types" "^7.18.0" "@babel/helper-optimise-call-expression@^7.16.7": version "7.16.7" @@ -185,10 +174,10 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" - integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" + integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== "@babel/helper-remap-async-to-generator@^7.16.8": version "7.16.8" @@ -200,22 +189,22 @@ "@babel/types" "^7.16.8" "@babel/helper-replace-supers@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" - integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz#41fdfcc9abaf900e18ba6e5931816d9062a7b2e0" + integrity sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q== dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-environment-visitor" "^7.18.2" + "@babel/helper-member-expression-to-functions" "^7.17.7" "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" -"@babel/helper-simple-access@^7.17.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz#aaa473de92b7987c6dfa7ce9a7d9674724823367" - integrity sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA== +"@babel/helper-simple-access@^7.17.7", "@babel/helper-simple-access@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" + integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== dependencies: - "@babel/types" "^7.17.0" + "@babel/types" "^7.18.2" "@babel/helper-skip-transparent-expression-wrappers@^7.16.0": version "7.16.0" @@ -251,69 +240,69 @@ "@babel/traverse" "^7.16.8" "@babel/types" "^7.16.8" -"@babel/helpers@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.9.tgz#b2af120821bfbe44f9907b1826e168e819375a1a" - integrity sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q== +"@babel/helpers@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" + integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== dependencies: "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/traverse" "^7.18.2" + "@babel/types" "^7.18.2" "@babel/highlight@^7.16.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.9.tgz#61b2ee7f32ea0454612def4fccdae0de232b73e3" - integrity sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg== + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" + integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== dependencies: "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.16.7", "@babel/parser@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.9.tgz#9c94189a6062f0291418ca021077983058e171ef" - integrity sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg== +"@babel/parser@^7.16.7", "@babel/parser@^7.18.0": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.3.tgz#39e99c7b0c4c56cef4d1eed8de9f506411c2ebc2" + integrity sha512-rL50YcEuHbbauAFAysNsJA4/f89fGTOBRNs9P81sniKnKAr4xULe5AecolcsKbi88xu0ByWYDj/S1AJ3FSFuSQ== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050" - integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.17.12.tgz#1dca338caaefca368639c9ffb095afbd4d420b1e" + integrity sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9" - integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz#0d498ec8f0374b1e2eb54b9cb2c4c78714c77753" + integrity sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.17.12" -"@babel/plugin-proposal-async-generator-functions@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8" - integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ== +"@babel/plugin-proposal-async-generator-functions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz#094a417e31ce7e692d84bab06c8e2a607cbeef03" + integrity sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" - integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== +"@babel/plugin-proposal-class-properties@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz#84f65c0cc247d46f40a6da99aadd6438315d80a4" + integrity sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-proposal-class-static-block@^7.16.7": - version "7.17.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c" - integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA== +"@babel/plugin-proposal-class-static-block@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz#7d02253156e3c3793bdb9f2faac3a1c05f0ba710" + integrity sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.17.6" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-dynamic-import@^7.16.7": @@ -324,36 +313,36 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163" - integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA== +"@babel/plugin-proposal-export-namespace-from@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz#b22864ccd662db9606edb2287ea5fd1709f05378" + integrity sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8" - integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ== +"@babel/plugin-proposal-json-strings@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz#f4642951792437233216d8c1af370bb0fbff4664" + integrity sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea" - integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg== +"@babel/plugin-proposal-logical-assignment-operators@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz#c64a1bcb2b0a6d0ed2ff674fd120f90ee4b88a23" + integrity sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99" - integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz#1e93079bbc2cbc756f6db6a1925157c4a92b94be" + integrity sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" "@babel/plugin-proposal-numeric-separator@^7.16.7": @@ -364,16 +353,16 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.16.7": - version "7.17.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390" - integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw== +"@babel/plugin-proposal-object-rest-spread@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz#79f2390c892ba2a68ec112eb0d895cfbd11155e8" + integrity sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw== dependencies: - "@babel/compat-data" "^7.17.0" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/compat-data" "^7.17.10" + "@babel/helper-compilation-targets" "^7.17.10" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.17.12" "@babel/plugin-proposal-optional-catch-binding@^7.16.7": version "7.16.7" @@ -383,40 +372,40 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a" - integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA== +"@babel/plugin-proposal-optional-chaining@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz#f96949e9bacace3a9066323a5cf90cfb9de67174" + integrity sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50" - integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw== +"@babel/plugin-proposal-private-methods@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz#c2ca3a80beb7539289938da005ad525a038a819c" + integrity sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.10" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-proposal-private-property-in-object@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce" - integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ== +"@babel/plugin-proposal-private-property-in-object@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz#b02efb7f106d544667d91ae97405a9fd8c93952d" + integrity sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-create-class-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-class-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2" - integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg== +"@babel/plugin-proposal-unicode-property-regex@^7.17.12", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz#3dbd7a67bd7f94c8238b394da112d86aaf32ad4d" + integrity sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -453,6 +442,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-import-assertions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz#58096a92b11b2e4e54b24c6a0cc0e5e607abcedd" + integrity sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw== + dependencies: + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -516,20 +512,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-arrow-functions@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" - integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== +"@babel/plugin-transform-arrow-functions@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz#dddd783b473b1b1537ef46423e3944ff24898c45" + integrity sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-async-to-generator@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808" - integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg== +"@babel/plugin-transform-async-to-generator@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz#dbe5511e6b01eee1496c944e35cdfe3f58050832" + integrity sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ== dependencies: "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-remap-async-to-generator" "^7.16.8" "@babel/plugin-transform-block-scoped-functions@^7.16.7": @@ -539,40 +535,40 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-block-scoping@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" - integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== +"@babel/plugin-transform-block-scoping@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.17.12.tgz#68fc3c4b3bb7dfd809d97b7ed19a584052a2725c" + integrity sha512-jw8XW/B1i7Lqwqj2CbrViPcZijSxfguBWZP2aN59NHgxUyO/OcO1mfdCxH13QhN5LbWhPkX+f+brKGhZTiqtZQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-classes@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" - integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== +"@babel/plugin-transform-classes@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.17.12.tgz#da889e89a4d38375eeb24985218edeab93af4f29" + integrity sha512-cvO7lc7pZat6BsvH6l/EGaI8zpl8paICaoGk+7x7guvtfak/TbIf66nYmJOH13EuG0H+Xx3M+9LQDtSvZFKXKw== dependencies: "@babel/helper-annotate-as-pure" "^7.16.7" "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" + "@babel/helper-function-name" "^7.17.9" "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" - integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== +"@babel/plugin-transform-computed-properties@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz#bca616a83679698f3258e892ed422546e531387f" + integrity sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-destructuring@^7.16.7": - version "7.17.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.7.tgz#49dc2675a7afa9a5e4c6bdee636061136c3408d1" - integrity sha512-XVh0r5yq9sLR4vZ6eVZe8FKfIcSgaTBxVBRSYokRj2qksf6QerYnTxz9/GTuKTH/n/HwLP7t6gtlybHetJ/6hQ== +"@babel/plugin-transform-destructuring@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz#dc4f92587e291b4daa78aa20cc2d7a63aa11e858" + integrity sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.16.7" @@ -582,12 +578,12 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-duplicate-keys@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9" - integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw== +"@babel/plugin-transform-duplicate-keys@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz#a09aa709a3310013f8e48e0e23bc7ace0f21477c" + integrity sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-exponentiation-operator@^7.16.7": version "7.16.7" @@ -597,12 +593,12 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-for-of@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" - integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== +"@babel/plugin-transform-for-of@^7.18.1": + version "7.18.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz#ed14b657e162b72afbbb2b4cdad277bf2bb32036" + integrity sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-function-name@^7.16.7": version "7.16.7" @@ -613,12 +609,12 @@ "@babel/helper-function-name" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" - integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== +"@babel/plugin-transform-literals@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz#97131fbc6bbb261487105b4b3edbf9ebf9c830ae" + integrity sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-member-expression-literals@^7.16.7": version "7.16.7" @@ -627,57 +623,58 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-modules-amd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186" - integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g== +"@babel/plugin-transform-modules-amd@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz#7ef1002e67e36da3155edc8bf1ac9398064c02ed" + integrity sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.16.8": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz#274be1a2087beec0254d4abd4d86e52442e1e5b6" - integrity sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw== +"@babel/plugin-transform-modules-commonjs@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz#1aa8efa2e2a6e818b6a7f2235fceaf09bdb31e9e" + integrity sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ== dependencies: - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-simple-access" "^7.18.2" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.16.7": - version "7.17.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.17.8.tgz#81fd834024fae14ea78fbe34168b042f38703859" - integrity sha512-39reIkMTUVagzgA5x88zDYXPCMT6lcaRKs1+S9K6NKBPErbgO/w/kP8GlNQTC87b412ZTlmNgr3k2JrWgHH+Bw== +"@babel/plugin-transform-modules-systemjs@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.0.tgz#50ecdb43de97c8483824402f7125edb94cddb09a" + integrity sha512-vwKpxdHnlM5tIrRt/eA0bzfbi7gUBLN08vLu38np1nZevlPySRe6yvuATJB5F/WPJ+ur4OXwpVYq9+BsxqAQuQ== dependencies: "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-module-transforms" "^7.17.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-identifier" "^7.16.7" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618" - integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ== +"@babel/plugin-transform-modules-umd@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz#56aac64a2c2a1922341129a4597d1fd5c3ff020f" + integrity sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA== dependencies: - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-module-transforms" "^7.18.0" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8": - version "7.16.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252" - integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz#9c4a5a5966e0434d515f2675c227fd8cc8606931" + integrity sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.7" + "@babel/helper-create-regexp-features-plugin" "^7.17.12" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-new-target@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244" - integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg== +"@babel/plugin-transform-new-target@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz#10842cd605a620944e81ea6060e9e65c265742e3" + integrity sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-object-super@^7.16.7": version "7.16.7" @@ -687,12 +684,12 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/helper-replace-supers" "^7.16.7" -"@babel/plugin-transform-parameters@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" - integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== +"@babel/plugin-transform-parameters@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz#eb467cd9586ff5ff115a9880d6fdbd4a846b7766" + integrity sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-property-literals@^7.16.7": version "7.16.7" @@ -701,27 +698,28 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-regenerator@^7.16.7": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz#0a33c3a61cf47f45ed3232903683a0afd2d3460c" - integrity sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ== +"@babel/plugin-transform-regenerator@^7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz#44274d655eb3f1af3f3a574ba819d3f48caf99d5" + integrity sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw== dependencies: + "@babel/helper-plugin-utils" "^7.17.12" regenerator-transform "^0.15.0" -"@babel/plugin-transform-reserved-words@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586" - integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg== +"@babel/plugin-transform-reserved-words@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz#7dbd349f3cdffba751e817cf40ca1386732f652f" + integrity sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-runtime@^7.17.0": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.17.0.tgz#0a2e08b5e2b2d95c4b1d3b3371a2180617455b70" - integrity sha512-fr7zPWnKXNc1xoHfrIU9mN/4XKX4VLZ45Q+oMhfsYIaHvg7mHgmhfOy/ckRWqDK7XF3QDigRpkh5DKq6+clE8A== + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz#04637de1e45ae8847ff14b9beead09c33d34374d" + integrity sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg== dependencies: "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" babel-plugin-polyfill-corejs2 "^0.3.0" babel-plugin-polyfill-corejs3 "^0.5.0" babel-plugin-polyfill-regenerator "^0.3.0" @@ -734,12 +732,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-spread@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" - integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== +"@babel/plugin-transform-spread@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz#c112cad3064299f03ea32afed1d659223935d1f5" + integrity sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-transform-sticky-regex@^7.16.7": @@ -749,19 +747,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-template-literals@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" - integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== +"@babel/plugin-transform-template-literals@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz#31ed6915721864847c48b656281d0098ea1add28" + integrity sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" -"@babel/plugin-transform-typeof-symbol@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e" - integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ== +"@babel/plugin-transform-typeof-symbol@^7.17.12": + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz#0f12f57ac35e98b35b4ed34829948d42bd0e6889" + integrity sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw== dependencies: - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/plugin-transform-unicode-escapes@^7.16.7": version "7.16.7" @@ -779,36 +777,37 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/preset-env@^7.16.11": - version "7.16.11" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" - integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.2.tgz#f47d3000a098617926e674c945d95a28cb90977a" + integrity sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q== dependencies: - "@babel/compat-data" "^7.16.8" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-plugin-utils" "^7.16.7" + "@babel/compat-data" "^7.17.10" + "@babel/helper-compilation-targets" "^7.18.2" + "@babel/helper-plugin-utils" "^7.17.12" "@babel/helper-validator-option" "^7.16.7" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-async-generator-functions" "^7.16.8" - "@babel/plugin-proposal-class-properties" "^7.16.7" - "@babel/plugin-proposal-class-static-block" "^7.16.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.17.12" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.17.12" + "@babel/plugin-proposal-async-generator-functions" "^7.17.12" + "@babel/plugin-proposal-class-properties" "^7.17.12" + "@babel/plugin-proposal-class-static-block" "^7.18.0" "@babel/plugin-proposal-dynamic-import" "^7.16.7" - "@babel/plugin-proposal-export-namespace-from" "^7.16.7" - "@babel/plugin-proposal-json-strings" "^7.16.7" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7" + "@babel/plugin-proposal-export-namespace-from" "^7.17.12" + "@babel/plugin-proposal-json-strings" "^7.17.12" + "@babel/plugin-proposal-logical-assignment-operators" "^7.17.12" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.17.12" "@babel/plugin-proposal-numeric-separator" "^7.16.7" - "@babel/plugin-proposal-object-rest-spread" "^7.16.7" + "@babel/plugin-proposal-object-rest-spread" "^7.18.0" "@babel/plugin-proposal-optional-catch-binding" "^7.16.7" - "@babel/plugin-proposal-optional-chaining" "^7.16.7" - "@babel/plugin-proposal-private-methods" "^7.16.11" - "@babel/plugin-proposal-private-property-in-object" "^7.16.7" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.7" + "@babel/plugin-proposal-optional-chaining" "^7.17.12" + "@babel/plugin-proposal-private-methods" "^7.17.12" + "@babel/plugin-proposal-private-property-in-object" "^7.17.12" + "@babel/plugin-proposal-unicode-property-regex" "^7.17.12" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.17.12" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -818,44 +817,44 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.16.7" - "@babel/plugin-transform-async-to-generator" "^7.16.8" + "@babel/plugin-transform-arrow-functions" "^7.17.12" + "@babel/plugin-transform-async-to-generator" "^7.17.12" "@babel/plugin-transform-block-scoped-functions" "^7.16.7" - "@babel/plugin-transform-block-scoping" "^7.16.7" - "@babel/plugin-transform-classes" "^7.16.7" - "@babel/plugin-transform-computed-properties" "^7.16.7" - "@babel/plugin-transform-destructuring" "^7.16.7" + "@babel/plugin-transform-block-scoping" "^7.17.12" + "@babel/plugin-transform-classes" "^7.17.12" + "@babel/plugin-transform-computed-properties" "^7.17.12" + "@babel/plugin-transform-destructuring" "^7.18.0" "@babel/plugin-transform-dotall-regex" "^7.16.7" - "@babel/plugin-transform-duplicate-keys" "^7.16.7" + "@babel/plugin-transform-duplicate-keys" "^7.17.12" "@babel/plugin-transform-exponentiation-operator" "^7.16.7" - "@babel/plugin-transform-for-of" "^7.16.7" + "@babel/plugin-transform-for-of" "^7.18.1" "@babel/plugin-transform-function-name" "^7.16.7" - "@babel/plugin-transform-literals" "^7.16.7" + "@babel/plugin-transform-literals" "^7.17.12" "@babel/plugin-transform-member-expression-literals" "^7.16.7" - "@babel/plugin-transform-modules-amd" "^7.16.7" - "@babel/plugin-transform-modules-commonjs" "^7.16.8" - "@babel/plugin-transform-modules-systemjs" "^7.16.7" - "@babel/plugin-transform-modules-umd" "^7.16.7" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8" - "@babel/plugin-transform-new-target" "^7.16.7" + "@babel/plugin-transform-modules-amd" "^7.18.0" + "@babel/plugin-transform-modules-commonjs" "^7.18.2" + "@babel/plugin-transform-modules-systemjs" "^7.18.0" + "@babel/plugin-transform-modules-umd" "^7.18.0" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.17.12" + "@babel/plugin-transform-new-target" "^7.17.12" "@babel/plugin-transform-object-super" "^7.16.7" - "@babel/plugin-transform-parameters" "^7.16.7" + "@babel/plugin-transform-parameters" "^7.17.12" "@babel/plugin-transform-property-literals" "^7.16.7" - "@babel/plugin-transform-regenerator" "^7.16.7" - "@babel/plugin-transform-reserved-words" "^7.16.7" + "@babel/plugin-transform-regenerator" "^7.18.0" + "@babel/plugin-transform-reserved-words" "^7.17.12" "@babel/plugin-transform-shorthand-properties" "^7.16.7" - "@babel/plugin-transform-spread" "^7.16.7" + "@babel/plugin-transform-spread" "^7.17.12" "@babel/plugin-transform-sticky-regex" "^7.16.7" - "@babel/plugin-transform-template-literals" "^7.16.7" - "@babel/plugin-transform-typeof-symbol" "^7.16.7" + "@babel/plugin-transform-template-literals" "^7.18.2" + "@babel/plugin-transform-typeof-symbol" "^7.17.12" "@babel/plugin-transform-unicode-escapes" "^7.16.7" "@babel/plugin-transform-unicode-regex" "^7.16.7" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.8" + "@babel/types" "^7.18.2" babel-plugin-polyfill-corejs2 "^0.3.0" babel-plugin-polyfill-corejs3 "^0.5.0" babel-plugin-polyfill-regenerator "^0.3.0" - core-js-compat "^3.20.2" + core-js-compat "^3.22.1" semver "^6.3.0" "@babel/preset-modules@^0.1.5": @@ -870,9 +869,9 @@ esutils "^2.0.2" "@babel/runtime@^7.12.5", "@babel/runtime@^7.8.4": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.9.tgz#d19fbf802d01a8cb6cf053a64e472d42c434ba72" - integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg== + version "7.18.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" + integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== dependencies: regenerator-runtime "^0.13.4" @@ -885,26 +884,26 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.3", "@babel/traverse@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.9.tgz#1f9b207435d9ae4a8ed6998b2b82300d83c37a0d" - integrity sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw== +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8" + integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA== dependencies: "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.9" - "@babel/helper-environment-visitor" "^7.16.7" + "@babel/generator" "^7.18.2" + "@babel/helper-environment-visitor" "^7.18.2" "@babel/helper-function-name" "^7.17.9" "@babel/helper-hoist-variables" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.9" - "@babel/types" "^7.17.0" + "@babel/parser" "^7.18.0" + "@babel/types" "^7.18.2" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.4.4": - version "7.17.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== +"@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.4.4": + version "7.18.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.2.tgz#191abfed79ebe6f4242f643a9a5cbaa36b10b091" + integrity sha512-0On6B8A4/+mFUto5WERt3EEuG1NznDirvwca1O8UwXQHVY8g3R7OzYgxXdOfMwLO08UrpUD/2+3Bclyq+/C94Q== dependencies: "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" @@ -920,32 +919,41 @@ integrity sha512-oHsJhgY2cip+K2ED7vKUNd2P+BEswVhrCYcJ802DSsblJFv7mPFVk3cQKvm2vHgHeDVdnj7oOKrBbzp1u8D+KA== "@jridgewell/gen-mapping@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.0.tgz#b30fd66b5426bb7f44bb6043ab127b20ee404063" - integrity sha512-YH+BnkvuCiPR+MUOY6JIArdTIGrRtsxnLaIxPRy4CpGJ/V6OO6Gq/1J+FJEc4j5e5h6Bcy3/K7prlMrm93BJoA== + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: - "@jridgewell/set-array" "1.0.0" + "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" + integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/resolve-uri@^3.0.3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz#4ac237f4dabc8dd93330386907b97591801f7352" - integrity sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw== + version "3.0.7" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" + integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== -"@jridgewell/set-array@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.0.0.tgz#6a8e62049ab198c5f7daf8047e71947ef46c11c8" - integrity sha512-LcqVnHCjOAj8BTCtjpwYZCMTn4yArusbdObCVRUYvBHhrR5fVLVyENG+UVWM4T4H/ufv7NiBLdprllxWs/5PaQ== +"@jridgewell/set-array@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" + integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== "@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + version "1.4.13" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" + integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== "@jridgewell/trace-mapping@^0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" - integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" + integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== dependencies: "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" @@ -990,9 +998,9 @@ "@types/estree" "*" "@types/eslint@*": - version "8.4.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" - integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + version "8.4.2" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.2.tgz#48f2ac58ab9c631cb68845c3d956b28f79fad575" + integrity sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA== dependencies: "@types/estree" "*" "@types/json-schema" "*" @@ -1013,9 +1021,9 @@ integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== "@types/node@*": - version "17.0.29" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.29.tgz#7f2e1159231d4a077bb660edab0fde373e375a3d" - integrity sha512-tx5jMmMFwx7wBwq/V7OohKDVb/JwJU5qCVkeLMh1//xycAJ/ESuw9aJ9SEtlCZDYi2pBfe4JkisSoAtbOsBNAA== + version "17.0.35" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.35.tgz#635b7586086d51fb40de0a2ec9d1014a5283ba4a" + integrity sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg== "@types/normalize-package-data@^2.4.0": version "2.4.1" @@ -1261,9 +1269,9 @@ ansi-styles@^4.0.0: color-convert "^2.0.1" ansis@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ansis/-/ansis-1.3.4.tgz#e94e32c6083c2eac9613ec6174c695a5bec9d9cb" - integrity sha512-BDXljGSG4gZXmWK64bQzXkI509i5fe8aAa9+eL29e3swaWUqxvxk/XlONjw9AUrNCpQWNdy++0GX7HAhWeR9BQ== + version "1.3.6" + resolved "https://registry.yarnpkg.com/ansis/-/ansis-1.3.6.tgz#5370d9cc7b20d054967cc003cf051c2acf395b2c" + integrity sha512-TMXlWGGK5cOYT//DNX8V4zGnr824j95Oh888GV2J3eVFwKnolgdym9jje9MNLa3a8YNl0MnyX7C5tVj8dw5amA== anymatch@~3.1.2: version "3.1.2" @@ -1301,7 +1309,7 @@ array-union@^3.0.1: arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== astral-regex@^2.0.0: version "2.0.0" @@ -1393,7 +1401,7 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.14.5, browserslist@^4.17.5, browserslist@^4.20.2: +browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.20.3: version "4.20.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf" integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg== @@ -1437,9 +1445,9 @@ camelcase@^5.3.1: integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001332: - version "1.0.30001332" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001332.tgz#39476d3aa8d83ea76359c70302eafdd4a1d727dd" - integrity sha512-10T30NYOEQtN6C11YGg411yebhvpnC6Z102+B95eAsN0oB6KUs01ivE8u+G6FMIRtIrVlYXhL+LUwQ3/hXwDWw== + version "1.0.30001343" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001343.tgz#8e1107e30d9a4d2f63782b48ae0a3ce34e2f9c2a" + integrity sha512-8KeCrAtPMabo/XW14B+R9sZYoClx1n0b+WYgwDKZPtWR3TcdvWzdSy7mPyFEmR5WU1St9v1PW6sdO5dkFOEzfA== chalk@^2.0.0: version "2.4.2" @@ -1451,9 +1459,9 @@ chalk@^2.0.0: supports-color "^5.3.0" chart.js@>=3.0.2, chart.js@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.7.1.tgz#0516f690c6a8680c6c707e31a4c1807a6f400ada" - integrity sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA== + version "3.8.0" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.8.0.tgz#c6c14c457b9dc3ce7f1514a59e9b262afd6f1a94" + integrity sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg== chartjs-adapter-date-fns@>=2.0.0: version "2.0.0" @@ -1461,9 +1469,9 @@ chartjs-adapter-date-fns@>=2.0.0: integrity sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw== chartkick@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/chartkick/-/chartkick-4.1.1.tgz#60d6e13a090c5334bd80ad8fb7da02aaf38fb936" - integrity sha512-+3+dIKZo8MzOiQFc4FZDZiRjDnrgVxgjk3tKXVclMcDF8yIJAEqSr5/l4pqpB2Rxye1s2Dg3j6bVA9eIeDbnCQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/chartkick/-/chartkick-4.2.0.tgz#106fc5ff7eef5343a9e6977f259a8a8a1ea57bf9" + integrity sha512-7yYZyxeFhOh/LA7gc1VwDFgc6t4ZM9RrbBjgb4dJoFukk2+94QkK0yulYI2OUH1cjcfrf1qmj04FkjZx7kZDeg== optionalDependencies: chart.js ">=3.0.2" chartjs-adapter-date-fns ">=2.0.0" @@ -1522,7 +1530,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -1552,7 +1560,7 @@ commander@^7.0.0: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" @@ -1578,18 +1586,18 @@ copy-webpack-plugin@^10.2.4: schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.20.2, core-js-compat@^3.21.0: - version "3.22.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.2.tgz#eec621eb276518efcf718d0a6d9d042c3d0cad48" - integrity sha512-Fns9lU06ZJ07pdfmPMu7OnkIKGPKDzXKIiuGlSvHHapwqMUF2QnnsWwtueFZtSyZEilP0o6iUeHQwpn7LxtLUw== +core-js-compat@^3.21.0, core-js-compat@^3.22.1: + version "3.22.7" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.7.tgz#8359eb66ecbf726dd0cfced8e48d5e73f3224239" + integrity sha512-uI9DAQKKiiE/mclIC5g4AjRpio27g+VMRhe6rQoz+q4Wm4L6A/fJhiLtBw+sfOpDG9wZ3O0pxIw7GbfOlBgjOA== dependencies: - browserslist "^4.20.2" + browserslist "^4.20.3" semver "7.0.0" core-js@^3.21.1, core-js@^3.4.0: - version "3.22.2" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.2.tgz#3ea0a245b0895fa39d1faa15fe75d91ade504a01" - integrity sha512-Z5I2vzDnEIqO2YhELVMFcL1An2CIsFe9Q7byZhs8c/QxummxZlAHw33TUHbIte987LkisOgL0LwQ1P9D6VISnA== + version "3.22.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.7.tgz#8d6c37f630f6139b8732d10f2c114c3f1d00024f" + integrity sha512-Jt8SReuDKVNZnZEzyEQT5eK6T2RRCXkfTq7Lo09kpm+fHjgGewSbNjV+Wt4yZMhPDdzz2x1ulI5z/w4nxpBseg== cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: version "7.0.1" @@ -1681,9 +1689,9 @@ dir-glob@^3.0.1: path-type "^4.0.0" electron-to-chromium@^1.4.118: - version "1.4.123" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.123.tgz#de88ea7fd29d7c868e63c88f129e91494bcf3266" - integrity sha512-0pHGE53WkYoFbsgwYcVKEpWa6jbzlvkohIEA2CUoZ9b5KC+w/zlMiQHvW/4IBcOh7YoEFqRNavgTk02TBoUTUw== + version "1.4.139" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.139.tgz#e634b69769ab4a54626bbd9e1475de872839c89a" + integrity sha512-lYxzcUCjWxxVug+A7UxBCUiVr13TCjfZFYJS9Lq1VpU/ErwV4a6zUQo9dfojuGpw/L/x9REGuBl6ICQPGgbs3g== element-closest@^2.0.2: version "2.0.2" @@ -1700,7 +1708,7 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== -enhanced-resolve@^5.9.2: +enhanced-resolve@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88" integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow== @@ -1946,14 +1954,14 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^7.1.3: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" @@ -2099,9 +2107,9 @@ ignore@^5.1.9, ignore@^5.2.0: integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== immutable@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" - integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef" + integrity sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ== import-fresh@^3.2.1: version "3.3.0" @@ -2249,23 +2257,6 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jquery-ui@^1.12.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.13.1.tgz#d0b7a42e73a04c31bb5706adf86f6f8942f64eaa" - integrity sha512-2VlU59N5P4HaumDK1Z3XEVjSvegFbEOQRgpHUBaB2Ak98Axl3hFhJ6RFcNQNuk9SfL6WxIbuLst8dW/U56NSiA== - dependencies: - jquery ">=1.8.0 <4.0.0" - -jquery-ujs@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.3.tgz#dcac6026ab7268e5ee41faf9d31c997cd4ddd603" - integrity sha512-59wvfx5vcCTHMeQT1/OwFiAj+UffLIwjRIoXdpO7Z7BCFGepzq9T9oLVeoItjTqjoXfUrHJvV7QU6pUR+UzOoA== - -"jquery@>=1.8.0 <4.0.0", jquery@^3.4.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" - integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2281,12 +2272,7 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -2316,10 +2302,10 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== -known-css-properties@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.24.0.tgz#19aefd85003ae5698a5560d2b55135bf5432155c" - integrity sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA== +known-css-properties@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776" + integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA== lines-and-columns@^1.1.6: version "1.2.4" @@ -2461,7 +2447,7 @@ mini-css-extract-plugin@^2.6.0: dependencies: schema-utils "^4.0.0" -minimatch@^3.0.4: +minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -2487,10 +2473,10 @@ mutation-observer-inner-html-shim@^1.0.0: resolved "https://registry.yarnpkg.com/mutation-observer-inner-html-shim/-/mutation-observer-inner-html-shim-1.0.1.tgz#84349f51dfc390d0af85011de8fa14e645fb400e" integrity sha512-YmJPDSUWJgBhwqRJP6AMvjdfDHU1gsrT5YdgpxMit2+x1khLYhdYq9fvp4clPsYecVT3JOprBf/KjEX7IqlU+g== -nanoid@^3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== neo-async@^2.6.2: version "2.6.2" @@ -2498,9 +2484,9 @@ neo-async@^2.6.2: integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-releases@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.3.tgz#225ee7488e4a5e636da8da52854844f9d716ca96" - integrity sha512-maHFz6OLqYxz+VQyCAtA3PTX4UP/53pa05fyDNc9CwjvJ0yEh6+xBwKsgCxMNhS8taUKBFYxfuiaD9U/55iFaw== + version "2.0.5" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" + integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== normalize-package-data@^2.5.0: version "2.5.0" @@ -2527,11 +2513,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-selector@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" - integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= - npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -2707,12 +2688,12 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.12, postcss@^8.4.7: - version "8.4.12" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.12.tgz#1e7de78733b28970fa4743f7da6f3763648b1905" - integrity sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg== +postcss@^8.4.14, postcss@^8.4.7: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== dependencies: - nanoid "^3.3.1" + nanoid "^3.3.4" picocolors "^1.0.0" source-map-js "^1.0.2" @@ -2901,9 +2882,9 @@ sass-loader@^12.6.0: neo-async "^2.6.2" sass@^1.49.9: - version "1.51.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.51.0.tgz#25ea36cf819581fe1fe8329e8c3a4eaaf70d2845" - integrity sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA== + version "1.52.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.52.1.tgz#554693da808543031f9423911d62c60a1acf7889" + integrity sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q== dependencies: chokidar ">=3.0.0 <4.0.0" immutable "^4.0.0" @@ -3022,11 +3003,6 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -3164,9 +3140,9 @@ stylelint-scss@^4.0.0: postcss-value-parser "^4.1.0" stylelint@^14.7.1: - version "14.8.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.8.0.tgz#506959bc1424610cdac9eaefca8fb2420292cf73" - integrity sha512-uIyIWMSBSVcj73Gn3nTvPyNsYdwTpxo1W6dWTIa1nm8JKgUi3FIobSXLgrRE6joLidoA0FdgAhCaqxwTF2ikrQ== + version "14.8.5" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.8.5.tgz#0fcbf5b6821283b5a249dde36d70f1158da0a2a3" + integrity sha512-e3t4H/hlWlspkcNUrkhf44RU3OpPTA7uBOoREGBzSwdEF+2g/+gbZq7WEpMP7BpopcSe/uLaTvDuL+URL7cdnQ== dependencies: balanced-match "^2.0.0" colord "^2.9.2" @@ -3186,14 +3162,13 @@ stylelint@^14.7.1: import-lazy "^4.0.0" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.24.0" + known-css-properties "^0.25.0" mathml-tag-names "^2.1.3" meow "^9.0.0" micromatch "^4.0.5" normalize-path "^3.0.0" - normalize-selector "^0.2.0" picocolors "^1.0.0" - postcss "^8.4.12" + postcss "^8.4.14" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^6.0.0" @@ -3277,9 +3252,9 @@ terser-webpack-plugin@^5.1.3: terser "^5.7.2" terser@^5.7.2: - version "5.13.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.13.0.tgz#d43fd71861df1b4df743980caa257c6fa03acc44" - integrity sha512-sgQ99P+fRBM1jAYzN9RTnD/xEWx/7LZgYTCRgmYriSq1wxxqiQPJgXkkLBBuwySDWJ2PP0PnVQyuf4xLUuH4Ng== + version "5.13.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.13.1.tgz#66332cdc5a01b04a224c9fad449fc1a18eaa1799" + integrity sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA== dependencies: acorn "^8.5.0" commander "^2.20.0" @@ -3430,9 +3405,9 @@ webpack-sources@^3.2.3: integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.70.0: - version "5.72.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.72.0.tgz#f8bc40d9c6bb489a4b7a8a685101d6022b8b6e28" - integrity sha512-qmSmbspI0Qo5ld49htys8GY9XhS9CGqFoHTsOVAnjBdg0Zn79y135R+k4IR4rKK6+eKaabMhJwiVB7xw0SJu5w== + version "5.72.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.72.1.tgz#3500fc834b4e9ba573b9f430b2c0a61e1bb57d13" + integrity sha512-dXG5zXCLspQR4krZVR6QgajnZOjW2K/djHvdcRaDQvsjV9z9vaW6+ja5dZOYbqBBjF6kGXka/2ZyxNdc+8Jung== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^0.0.51" @@ -3443,13 +3418,13 @@ webpack@^5.70.0: acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.9.2" + enhanced-resolve "^5.9.3" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" graceful-fs "^4.2.9" - json-parse-better-errors "^1.0.2" + json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2"