diff --git a/.gitignore b/.gitignore index 73ada7f4c7d..efcb4365403 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ .generators *.pyc *.rbc -*.sassc **.orig .bundle .byebug_history diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e171730e71a..6331a2e493b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,6 +5,7 @@ variables: GITLAB_CI: 'true' + FF_SCRIPT_SECTIONS: 'true' JUNIT_OUTPUT: 'true' ECR_REGISTRY: '${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com' IDP_CI_SHA: 'sha256:e846ed99aa3c8f9083731105b8ef25536c7ab3ed5e9f2b781b63431badcb091b' @@ -107,7 +108,7 @@ check_changelog: specs: stage: test - parallel: 11 + parallel: 22 cache: - <<: *ruby_cache - <<: *yarn_cache @@ -128,6 +129,7 @@ specs: services: - name: postgres:13.9 alias: db-postgres + command: ["--fsync=false", "--synchronous_commit=false", "--full_page_writes=false"] - name: redis:7.0 alias: db-redis artifacts: diff --git a/Gemfile b/Gemfile index 9cbb44f0a69..40a1feb67f2 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ gem 'aws-sdk-pinpoint' gem 'aws-sdk-pinpointsmsvoice' gem 'aws-sdk-ses', '~> 1.6' gem 'aws-sdk-sns' +gem 'aws-sdk-sqs' gem 'barby', '~> 0.6.8' gem 'base32-crockford' gem 'bootsnap', '~> 1.0', require: false @@ -33,8 +34,9 @@ gem 'jsbundling-rails', '~> 1.0.0' gem 'jwe' gem 'jwt' gem 'lograge', '>= 0.11.2' -gem 'lookbook', '~> 1.5.3', require: false +gem 'lookbook', '~> 2.0.0', require: false gem 'lru_redux' +gem 'mail' gem 'msgpack', '~> 1.6' gem 'maxminddb' gem 'multiset' @@ -44,6 +46,7 @@ gem 'pg' gem 'phonelib' gem 'premailer-rails', '>= 1.12.0' gem 'profanity_filter' +gem 'propshaft' gem 'rack', '>= 2.2.3.1' gem 'rack-attack', '>= 6.2.1' gem 'rack-cors', '>= 1.0.5', require: 'rack/cors' @@ -61,14 +64,13 @@ gem 'safe_target_blank', '>= 1.0.2' gem 'saml_idp', github: '18F/saml_idp', tag: '0.18.2-18f' gem 'scrypt' gem 'simple_form', '>= 5.0.2' -gem 'sprockets-rails' gem 'stringex', require: false gem 'strong_migrations', '>= 0.4.2' gem 'subprocess', require: false gem 'terminal-table', require: false gem 'uglifier', '~> 4.2' gem 'valid_email', '>= 0.1.3' -gem 'view_component', '~> 2.82.0' +gem 'view_component', '~> 3.0.0' gem 'webauthn', '~> 2.5.2' gem 'xmldsig', '~> 0.6' gem 'xmlenc', '~> 0.7', '>= 0.7.1' @@ -98,6 +100,7 @@ group :development, :test do gem 'erb_lint', '~> 0.3.0', require: false gem 'i18n-tasks', '~> 1.0' gem 'knapsack' + gem 'listen' gem 'nokogiri', '~> 1.14.0' gem 'pg_query', require: false gem 'pry-byebug' diff --git a/Gemfile.lock b/Gemfile.lock index ca2dafb71fd..1a366e8b663 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -164,6 +164,9 @@ GEM aws-sdk-sns (1.49.0) aws-sdk-core (~> 3, >= 3.122.0) aws-sigv4 (~> 1.1) + aws-sdk-sqs (1.53.0) + aws-sdk-core (~> 3, >= 3.165.0) + aws-sigv4 (~> 1.1) aws-sigv4 (1.5.2) aws-eventstream (~> 1, >= 1.0.2) axe-core-api (4.3.2) @@ -375,17 +378,16 @@ GEM loofah (2.20.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) - lookbook (1.5.3) - actioncable + lookbook (2.0.3) activemodel css_parser htmlbeautifier (~> 1.3) htmlentities (~> 4.3.4) - listen (~> 3.0) + marcel (~> 1.0) railties (>= 5.0) redcarpet (~> 3.5) rouge (>= 3.26, < 5.0) - view_component (> 2.0, < 4) + view_component (>= 2.0) yard (~> 0.9.25) zeitwerk (~> 2.5) lru_redux (1.1.0) @@ -451,6 +453,11 @@ GEM net-smtp premailer (~> 1.7, >= 1.7.9) profanity_filter (0.1.1) + propshaft (0.7.0) + actionpack (>= 7.0.0) + activesupport (>= 7.0.0) + rack + railties (>= 7.0.0) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) @@ -544,7 +551,7 @@ GEM retries (0.0.5) rexml (3.2.5) rotp (6.2.0) - rouge (4.1.0) + rouge (4.1.1) rqrcode (2.1.0) chunky_png (~> 1.0) rqrcode_core (~> 1.0) @@ -635,13 +642,6 @@ GEM simpleidn (0.2.1) unf (~> 0.1.4) smart_properties (1.17.0) - sprockets (4.0.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.4.2) - actionpack (>= 5.2) - activesupport (>= 5.2) - sprockets (>= 3.0.0) stringex (2.8.5) strong_migrations (0.8.0) activerecord (>= 5.2) @@ -669,7 +669,7 @@ GEM activemodel mail (>= 2.6.1) simpleidn - view_component (2.82.0) + view_component (3.0.0) activesupport (>= 5.2.0, < 8.0) concurrent-ruby (~> 1.0) method_source (~> 1.0) @@ -729,6 +729,7 @@ DEPENDENCIES aws-sdk-pinpointsmsvoice aws-sdk-ses (~> 1.6) aws-sdk-sns + aws-sdk-sqs axe-core-rspec (~> 4.2) barby (~> 0.6.8) base32-crockford @@ -766,9 +767,11 @@ DEPENDENCIES jwt knapsack letter_opener (~> 1.8) + listen lograge (>= 0.11.2) - lookbook (~> 1.5.3) + lookbook (~> 2.0.0) lru_redux + mail maxminddb msgpack (~> 1.6) multiset @@ -781,6 +784,7 @@ DEPENDENCIES phonelib premailer-rails (>= 1.12.0) profanity_filter + propshaft pry-byebug pry-doc pry-rails @@ -819,7 +823,6 @@ DEPENDENCIES simplecov (~> 0.21.0) simplecov-cobertura simplecov_json_formatter - sprockets-rails stringex strong_migrations (>= 0.4.2) subprocess @@ -827,7 +830,7 @@ DEPENDENCIES terminal-table uglifier (~> 4.2) valid_email (>= 0.1.3) - view_component (~> 2.82.0) + view_component (~> 3.0.0) webauthn (~> 2.5.2) webdrivers (~> 5.2.0) webmock diff --git a/Makefile b/Makefile index 151327b2445..08925bfd1fa 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ ARTIFACT_DESTINATION_FILE ?= ./tmp/idp.tar.gz brakeman \ build_artifact \ check \ + clobber_db \ + clobber_assets \ + clobber_logs \ docker_setup \ download_acuant_sdk \ fast_setup \ @@ -34,6 +37,7 @@ ARTIFACT_DESTINATION_FILE ?= ./tmp/idp.tar.gz optimize_assets \ optimize_svg \ run \ + tidy \ update \ urn \ README.md \ @@ -268,3 +272,24 @@ README.md: docs/ ## Generates README.md based on the contents of the docs direct download_acuant_sdk: ## Downloads the most recent Acuant SDK release from Github @scripts/download_acuant_sdk.sh + +clobber_db: ## Resets the database for make setup + bin/rake db:create + bin/rake db:environment:set + bin/rake db:reset + bin/rake db:environment:set + bin/rake dev:prime + +clobber_assets: ## Removes (clobbers) assets + bin/rake assets:clobber + RAILS_ENV=test bin/rake assets:clobber + +clobber_logs: ## Purges logs and tmp/ + rm -f log/* + rm -rf tmp/cache/* + rm -rf tmp/encrypted_doc_storage + rm -rf tmp/letter_opener + rm -rf tmp/mails + +tidy: clobber_assets clobber_logs ## Remove assets, logs, and unused gems, but leave DB alone + bundle clean diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js deleted file mode 100644 index 6b147d7d533..00000000000 --- a/app/assets/config/manifest.js +++ /dev/null @@ -1,10 +0,0 @@ -//= link_tree ../images -//= link_tree ../fonts - -//= link intl-tel-input/build/css/intlTelInput.css -//= link intl-tel-input/build/img/flags.png -//= link intl-tel-input/build/img/flags@2x.png - -//= link_tree ../../../node_modules/@18f/identity-design-system/dist/assets/img -//= link_tree ../../../node_modules/@18f/identity-design-system/dist/assets/fonts -//= link_tree ../builds diff --git a/app/assets/stylesheets/_uswds-core.scss b/app/assets/stylesheets/_uswds-core.scss index 1a1be05c817..656649b41b0 100644 --- a/app/assets/stylesheets/_uswds-core.scss +++ b/app/assets/stylesheets/_uswds-core.scss @@ -4,8 +4,8 @@ $render-font-face: false !default; @forward '@18f/identity-design-system/packages/uswds-core' with ( $theme-body-font-size: 'sm', - $theme-font-path: '.', - $theme-image-path: '@18f/identity-design-system/dist/assets/img', + $theme-font-path: '', + $theme-image-path: '', $theme-global-border-box-sizing: true, $theme-global-link-styles: true, $theme-grid-container-max-width: 'tablet-lg', diff --git a/app/assets/stylesheets/_uswds-form-controls.scss b/app/assets/stylesheets/_uswds-form-controls.scss new file mode 100644 index 00000000000..bcb8825cf56 --- /dev/null +++ b/app/assets/stylesheets/_uswds-form-controls.scss @@ -0,0 +1,13 @@ +@forward 'usa-checkbox'; +@forward 'usa-error-message'; +@forward 'usa-fieldset'; +@forward 'usa-file-input'; +@forward 'usa-form-group'; +@forward 'usa-hint'; +@forward 'usa-input'; +@forward 'usa-label'; +@forward 'usa-legend'; +@forward 'usa-memorable-date'; +@forward 'usa-radio'; +@forward 'usa-select'; +@forward 'usa-success-message'; diff --git a/app/assets/stylesheets/components/_alert.scss b/app/assets/stylesheets/components/_alert.scss index 506cafceb76..fc35acaffb5 100644 --- a/app/assets/stylesheets/components/_alert.scss +++ b/app/assets/stylesheets/components/_alert.scss @@ -6,7 +6,7 @@ font-weight: bold; &::before { - background-image: url('alert/info-white.svg'); + background-image: url('/alert/info-white.svg'); } } diff --git a/app/assets/stylesheets/components/_icon.scss b/app/assets/stylesheets/components/_icon.scss index 05b22f6a71d..708d8447270 100644 --- a/app/assets/stylesheets/components/_icon.scss +++ b/app/assets/stylesheets/components/_icon.scss @@ -28,7 +28,7 @@ $icon-min-padding: 2px; &-success { &::before { - background-image: url('alert/success.svg'); + background-image: url('/alert/success.svg'); content: ''; display: block; height: $h4; diff --git a/app/assets/stylesheets/components/_language-picker.scss b/app/assets/stylesheets/components/_language-picker.scss index e6d14f6823b..5910f030e92 100644 --- a/app/assets/stylesheets/components/_language-picker.scss +++ b/app/assets/stylesheets/components/_language-picker.scss @@ -66,10 +66,10 @@ } &::after { - background-image: url(@18f/identity-design-system/dist/assets/img/angle-arrow-up.svg); + background-image: url('/angle-arrow-up.svg'); @include at-media('tablet') { - background-image: url(@18f/identity-design-system/dist/assets/img/angle-arrow-up-white.svg); + background-image: url('/angle-arrow-up-white.svg'); } } } @@ -79,7 +79,7 @@ color: color('white'); &::after { - background-image: url(@18f/identity-design-system/dist/assets/img/angle-arrow-down-white.svg); + background-image: url('/angle-arrow-down-white.svg'); } } } diff --git a/app/assets/stylesheets/components/_list.scss b/app/assets/stylesheets/components/_list.scss index 5be58d778d2..389920d1e7b 100644 --- a/app/assets/stylesheets/components/_list.scss +++ b/app/assets/stylesheets/components/_list.scss @@ -3,7 +3,7 @@ padding: 1rem 1rem 1rem 0; &::before { - background-image: url('alert/success.svg'); + background-image: url('/alert/success.svg'); background-repeat: no-repeat; content: ''; display: inline-block; diff --git a/app/assets/stylesheets/components/_personal-key.scss b/app/assets/stylesheets/components/_personal-key.scss index 27d55bc560e..c475e8c922f 100644 --- a/app/assets/stylesheets/components/_personal-key.scss +++ b/app/assets/stylesheets/components/_personal-key.scss @@ -2,7 +2,7 @@ .personal-key-block { @include u-padding-y(2); - background-image: url('personal-key/pkey-block.svg'); + background-image: url('/personal-key/pkey-block.svg'); background-position: center; background-repeat: no-repeat; @@ -28,7 +28,7 @@ .bg-personal-key { height: 145px; - background-image: url('personal-key/shield.svg'); + background-image: url('/personal-key/shield.svg'); background-position: center; background-repeat: no-repeat; background-size: 145px 145px; diff --git a/app/assets/stylesheets/components/_phone-input.scss b/app/assets/stylesheets/components/_phone-input.scss index 07f0e973b95..b9a1deec9fd 100644 --- a/app/assets/stylesheets/components/_phone-input.scss +++ b/app/assets/stylesheets/components/_phone-input.scss @@ -8,11 +8,11 @@ lg-phone-input { } .iti__flag { - background-image: url('intl-tel-input/build/img/flags.png'); + background-image: url('/flags.png'); /* stylelint-disable-next-line media-feature-name-no-vendor-prefix */ @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { - background-image: url('intl-tel-input/build/img/flags@2x.png'); + background-image: url('/flags@2x.png'); } } diff --git a/app/assets/stylesheets/components/_spinner-button.scss b/app/assets/stylesheets/components/_spinner-button.scss index 5d931537a15..887f7eb13c3 100644 --- a/app/assets/stylesheets/components/_spinner-button.scss +++ b/app/assets/stylesheets/components/_spinner-button.scss @@ -1,44 +1,21 @@ @use 'uswds-core' as *; lg-spinner-button { - display: block; - - @include at-media('mobile-lg') { - display: inline-block; + .usa-button { + position: relative; } &:not(.spinner-button--spinner-active) .spinner-dots { display: none; } -} - -.spinner-button--spinner-active { - .spinner-button__content { - position: relative; - a, - button:not([type]), - [type='submit'], - [type='button'], - .usa-button:disabled.usa-button--active:not(.usa-button--unstyled, .usa-button--secondary, .usa-button--accent-cool, .usa-button--accent-warm, .usa-button--base, .usa-button--outline, .usa-button--inverse), - .usa-button--disabled.usa-button--active:not(.usa-button--unstyled, .usa-button--secondary, .usa-button--accent-cool, .usa-button--accent-warm, .usa-button--base, .usa-button--outline, .usa-button--inverse) { - color: transparent; - opacity: 1; - } + &:not(.spinner-button--outline) .spinner-dots { + color: color('white'); } +} - &:not(.spinner-button--outline) .spinner-button__content { - a, - button:not([type]), - [type='submit'], - [type='button'] { - background-color: color('primary-darker'); - } - - .spinner-dots { - color: color('white'); - } - } +.spinner-button--spinner-active .spinner-button__content { + opacity: 0; } .spinner-button__action-message { diff --git a/app/assets/stylesheets/components/_step-indicator.scss b/app/assets/stylesheets/components/_step-indicator.scss index 95a3835e984..b10b9cb5212 100644 --- a/app/assets/stylesheets/components/_step-indicator.scss +++ b/app/assets/stylesheets/components/_step-indicator.scss @@ -109,7 +109,7 @@ lg-step-indicator { .step-indicator__step--complete::before { background-color: color('white'); - background-image: url('alert/success.svg'); + background-image: url('/alert/success.svg'); } .step-indicator__step:not(:last-child)::after { diff --git a/app/components/button_component.html.erb b/app/components/button_component.html.erb index 4a8193d1c42..a3063a3e3c5 100644 --- a/app/components/button_component.html.erb +++ b/app/components/button_component.html.erb @@ -1,4 +1,4 @@ <%= action.call( **tag_options, class: css_class, - ) { safe_join([icon_content, content&.strip].compact) } %> + ) { safe_join([icon_content, content].compact) } %> diff --git a/app/components/button_component.rb b/app/components/button_component.rb index 188ad67148d..b2c60bd4a06 100644 --- a/app/components/button_component.rb +++ b/app/components/button_component.rb @@ -37,4 +37,18 @@ def css_class def icon_content render IconComponent.new(icon:) if icon end + + def content + original_content = super + if original_content.present? && icon.present? + # Content templates may include leading whitespace, which interferes with the layout when an + # icon is present. This can be solved in CSS using Flexbox, but doing so for all buttons may + # have unintended consequences. + trimmed_content = original_content.lstrip + trimmed_content = sanitize(trimmed_content) if original_content.html_safe? + trimmed_content + else + original_content + end + end end diff --git a/app/components/clipboard_button_component.rb b/app/components/clipboard_button_component.rb index 0d8612cc54d..38719624eff 100644 --- a/app/components/clipboard_button_component.rb +++ b/app/components/clipboard_button_component.rb @@ -1,22 +1,34 @@ -class ClipboardButtonComponent < ButtonComponent - attr_reader :clipboard_text, :tag_options - - def initialize(clipboard_text:, **tag_options) - super(**tag_options, type: :button, icon: :content_copy) +class ClipboardButtonComponent < BaseComponent + attr_reader :clipboard_text, :button_options + def initialize(clipboard_text:, **button_options) @clipboard_text = clipboard_text + @button_options = button_options end def call content_tag( :'lg-clipboard-button', - super, + button_content, 'clipboard-text': clipboard_text, 'tooltip-text': t('components.clipboard_button.tooltip'), + class: css_class, ) end def content t('components.clipboard_button.label') end + + def css_class + 'clipboard-button--unstyled' if button_options[:unstyled] + end + + def button_content + render ButtonComponent.new( + **button_options, + type: :button, + icon: :content_copy, + ).with_content(content) + end end diff --git a/app/components/clipboard_button_component.scss b/app/components/clipboard_button_component.scss index 25e92517298..0073a14d6a4 100644 --- a/app/components/clipboard_button_component.scss +++ b/app/components/clipboard_button_component.scss @@ -12,5 +12,9 @@ .usa-tooltip { @include at-media-max('mobile-lg') { display: block; + + .clipboard-button--unstyled & { + display: inline; + } } } diff --git a/app/components/icon_component.rb b/app/components/icon_component.rb index 7976d647003..f0c679a5955 100644 --- a/app/components/icon_component.rb +++ b/app/components/icon_component.rb @@ -1,6 +1,4 @@ class IconComponent < BaseComponent - include AssetHelper - # See: https://github.com/uswds/uswds/tree/develop/src/img/usa-icons ICONS = %i[ accessibility_new @@ -256,7 +254,7 @@ def initialize(icon:, **tag_options) end def icon_path - asset_path([design_system_asset_path('img/sprite.svg'), '#', icon].join, host: asset_host) + asset_path([asset_path('sprite.svg'), '#', icon].join, host: asset_host) end private diff --git a/app/components/javascript_required_component.html.erb b/app/components/javascript_required_component.html.erb index ece80238a07..514068d4efe 100644 --- a/app/components/javascript_required_component.html.erb +++ b/app/components/javascript_required_component.html.erb @@ -1,6 +1,6 @@