diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 000000000..0b4648363
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,79 @@
+{
+ "enabledPlugins": {
+ "dependency-track@skillwire": true
+ },
+ "permissions": {
+ "allow": [
+ "WebSearch",
+ "Bash(rg:*)",
+ "Bash(ls:*)",
+ "Bash(bundle exec rspec:*)",
+ "Bash(bundle exec rake lint)",
+ "Bash(bundle exec rake parallel:spec)",
+ "Bash(bundle exec rake parallel:setup)",
+ "Bash(bundle exec rubocop:*)",
+ "Bash(bundle exec erb_lint:*)",
+ "Bash(bundle exec rails:*)",
+ "Bash(bundle exec rake db:migrate)",
+ "Bash(bundle exec rake db:migrate:status)",
+ "Bash(bundle install)",
+ "Bash(yarn install)",
+ "Bash(yarn standard:*)",
+ "Bash(yarn prettier:*)",
+ "Bash(yarn stylelint:*)",
+ "Bash(yarn build:*)",
+ "Bash(git fetch)",
+ "Bash(git pull)",
+ "Bash(git status)",
+ "Bash(git diff:*)",
+ "Bash(git log:*)",
+ "Bash(git show:*)",
+ "Bash(git branch:*)",
+ "Bash(git checkout:*)",
+ "Bash(git add:*)",
+ "Bash(git commit:*)",
+ "Edit(app/**)",
+ "Edit(config/**)",
+ "Edit(db/migrate/**)",
+ "Edit(lib/**)",
+ "Edit(spec/**)",
+ "Edit(docs/**)"
+ ],
+ "deny": [
+ "Read(.env*)",
+ "Read(config/master.key)",
+ "Edit(.env*)",
+ "Edit(config/master.key)",
+ "Edit(config/credentials.yml.enc)",
+ "Edit(db/schema.rb)",
+ "Edit(db/structure.sql)",
+ "Edit(Gemfile.lock)",
+ "Edit(yarn.lock)",
+ "Edit(AGENTS.md)",
+ "Edit(AI_CONTEXT.md)",
+ "Edit(WORKFLOW_AI.md)",
+ "Bash(curl:*)",
+ "Bash(wget:*)",
+ "Bash(sudo:*)",
+ "Bash(rm -rf:*)",
+ "Bash(chmod:*)",
+ "Bash(chown:*)",
+ "Bash(echo:*)",
+ "Bash(cat:*)",
+ "Bash(tail:*)",
+ "Bash(head:*)",
+ "Bash(gh:*)",
+ "Bash(git add .)",
+ "Bash(git add --all)",
+ "Bash(git add -A)",
+ "Bash(git push --force)",
+ "Bash(git push --force-with-lease)",
+ "Bash(git reset --hard)",
+ "Bash(bundle exec rake db:drop)",
+ "Bash(bundle exec rake db:reset)"
+ ]
+ },
+ "env": {
+ "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
+ }
+}
diff --git a/.github/workflows/production_pipeline.yml b/.github/workflows/production_pipeline.yml
index 45a31167f..6fc1c3b96 100644
--- a/.github/workflows/production_pipeline.yml
+++ b/.github/workflows/production_pipeline.yml
@@ -20,3 +20,14 @@ jobs:
release_tag: ${{ needs.test.outputs.releasetag }}
permissions:
id-token: write
+
+ sbom:
+ name: Upload SBOM
+ needs: [aws_deploy]
+ permissions:
+ contents: read
+ uses: ./.github/workflows/upload-sbom.yml
+ with:
+ projectversion: prod
+ secrets:
+ DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index fde032a69..b4d4f697d 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -38,7 +38,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -59,7 +58,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
# This is temporary to fix flaky parallel tests due to `secret_key_base` being read before it's set
- name: Create local secret
@@ -102,7 +101,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -122,7 +120,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -160,7 +158,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -180,7 +177,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -218,7 +215,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -239,7 +235,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create local secret
run: |
@@ -281,7 +277,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -302,7 +297,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create local secret
run: |
@@ -344,7 +339,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -365,7 +359,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -396,7 +390,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Install packages and symlink local dependencies
run: |
diff --git a/.github/workflows/staging_pipeline.yml b/.github/workflows/staging_pipeline.yml
index a2e777db0..9187142d3 100644
--- a/.github/workflows/staging_pipeline.yml
+++ b/.github/workflows/staging_pipeline.yml
@@ -32,6 +32,15 @@ jobs:
permissions:
id-token: write
+ sbom:
+ name: Upload SBOM
+ needs: [aws_deploy]
+ uses: ./.github/workflows/upload-sbom.yml
+ with:
+ projectversion: staging
+ secrets:
+ DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}
+
performance:
needs: [aws_deploy]
runs-on: ubuntu-latest
diff --git a/.github/workflows/upload-sbom.yml b/.github/workflows/upload-sbom.yml
new file mode 100644
index 000000000..da41affce
--- /dev/null
+++ b/.github/workflows/upload-sbom.yml
@@ -0,0 +1,55 @@
+name: Upload SBOM
+
+# Generates a CycloneDX SBOM with Syft (auto-detects both the Ruby gems in
+# Gemfile.lock and the Node packages in yarn.lock) and uploads it to
+# Dependency-Track. Called from the staging and production pipelines after a
+# successful deploy.
+
+on:
+ workflow_call:
+ inputs:
+ projectversion:
+ required: true
+ type: string
+ secrets:
+ DTRACK_API_KEY:
+ required: true
+
+permissions:
+ contents: read
+
+jobs:
+ sbom:
+ name: Generate and upload SBOM
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - run: |
+ echo "SYFT_VERSION=v1.45.0" >> "$GITHUB_ENV"
+ echo "SYFT_SCRIPT_SHA=9673f867e50398b5d25ec97ff051a451c46d262c" >> "$GITHUB_ENV"
+
+ - uses: actions/cache@v4
+ with:
+ path: /usr/local/bin/syft
+ key: syft-${{ env.SYFT_VERSION }}
+
+ - name: Install Syft
+ run: |
+ [ -f /usr/local/bin/syft ] || \
+ curl -sSfL "https://raw.githubusercontent.com/anchore/syft/${SYFT_SCRIPT_SHA}/install.sh" | sh -s -- -b /usr/local/bin "$SYFT_VERSION"
+
+ - run: syft . -o cyclonedx-xml=bom.xml
+
+ - name: Upload SBOM to Dependency-Track
+ env:
+ DTRACK_API_KEY: ${{ secrets.DTRACK_API_KEY }}
+ SBOM_VERSION: ${{ inputs.projectversion }}
+ run: |
+ curl -sSf -X POST "https://api-deps.softwire.com/api/v1/bom" \
+ -H "X-Api-Key: $DTRACK_API_KEY" \
+ -F "autoCreate=true" \
+ -F "projectName=CORE" \
+ -F "projectVersion=$SBOM_VERSION" \
+ -F "parentName=Support" \
+ -F "bom=@bom.xml"
diff --git a/.nvmrc b/.nvmrc
index 209e3ef4b..a45fd52cc 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-20
+24
diff --git a/.ruby-version b/.ruby-version
index f9892605c..7bcbb3808 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-3.4.4
+3.4.9
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 000000000..841257b42
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,105 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project
+
+CORE — a Ruby on Rails app (the "Submit social housing lettings and sales data" service) that collects lettings and sales of social housing data in England for MHCLG. Data providers (Local Authorities and Private Registered Providers) submit logs; the data is exported nightly to CDS (Consolidated Data Store) via XML to S3.
+
+Stack: Ruby 3.4.9, Rails 7.2, PostgreSQL, Sidekiq + Redis, Webpack/Propshaft, Stimulus, ViewComponent, GOV.UK Design System (govuk-frontend, govuk-components, govuk_design_system_formbuilder), Devise + 2FA, Pundit, PaperTrail.
+
+Full domain/architecture docs live in `docs/` (rendered at https://communitiesuk.github.io/submit-social-housing-lettings-and-sales-data) and are the authoritative reference — especially `docs/index.md` (domain overview), `docs/form/*` (form architecture), `docs/bulk_upload.md`, `docs/exports.md`, `docs/csv_downloads.md`, and the ADRs in `docs/adr/`.
+
+## Commands
+
+Run app (Rails + Sidekiq's redis + JS watch via Foreman):
+
+```bash
+./bin/dev
+```
+
+Rails server alone: `bundle exec rails s` (port 3000). JS watch alone: `yarn build --mode=development --watch`. First-time asset build: `yarn build --mode=development`.
+
+Tests:
+
+```bash
+bundle exec rspec # full suite
+bundle exec rspec ./spec/path/to/file.rb # single file
+bundle exec rspec ./spec/path/to/file.rb:42 # single example by line
+bundle exec rake parallel:setup # one-time setup
+RAILS_ENV=test bundle exec rake parallel:spec # parallel run
+```
+
+If you change the schema, run `bundle exec rake db:migrate RAILS_ENV=test` before running specs.
+
+Lint (everything): `bundle exec rake lint`. Individual linters:
+
+```bash
+bundle exec rubocop # -a safe autocorrect, -A all
+bundle exec erb_lint --lint-all
+yarn standard # --fix to autocorrect
+yarn stylelint app/frontend/styles
+yarn prettier . --check # --write to autocorrect
+```
+
+Database: `bundle exec rake db:create db:migrate db:seed`. Seeded users use the password from `REVIEW_APP_USER_PASSWORD` in `.env` (default `password`).
+
+## Architecture
+
+### The form system (core abstraction)
+
+Form data collection runs on annual windows (1 April → 1 April + 3-month late-submission tail). Two forms may be active simultaneously during the April–June/July **crossover period**.
+
+`FormHandler` (singleton, `app/models/form_handler.rb`) holds every active form: `current/previous/next/archived` × `lettings/sales`. Each `Form` is built from Ruby classes (not JSON — historical JSON definitions in `config/forms/` are legacy; new forms are defined in code under `app/models/form/lettings/{sections,subsections,pages,questions}` and `app/models/form/sales/...`).
+
+Hierarchy: `Form` → `Section` → `Subsection` → `Page` → `Question`. Pages route via `depends_on` conditions (with chained method calls e.g. `{ "owning_organisation.provider_type": "local_authority" }`) or custom `routed_to?` methods. Questions can be `conditional_for` (inline conditional on the same page), `derived` (computed, not cleared when unrouted), or `inferred` (cleared when their source changes). See `docs/form/builder.md` for the full DSL.
+
+Key consequence: **every question id must match an ActiveRecord column on `LettingsLog` / `SalesLog`**. Checkbox questions need one column per answer option. Adding a question is a migration + form class change in lock-step.
+
+`Form::DEADLINES` in `app/models/form.rb` is the source of truth for collection year cutoffs (new_logs_end_date, submission_deadline, edit_end_date). Add a year here when introducing a new collection window.
+
+### Logs
+
+`LettingsLog` and `SalesLog` (both inherit shared behaviour from `Log`) are the primary records. Sales splits into discounted ownership, shared-ownership initial, and staircasing (post-2024); pre-2025 also included outright sales. Lettings splits into general needs and supported housing (which belongs to a `Scheme` with one or more `Location`s).
+
+Validations live in `app/models/validations/` (lettings) and `app/models/validations/sales/` and are mixed into the log models. Soft validations show interruption pages instead of hard errors.
+
+### Organisations & permissions
+
+Three user roles outside of MHCLG: **data providers**, **data coordinators** (org admins, can also complete logs), plus an optional **data protection officer (DPO)** flag on a user. Internal roles: **support** (full admin) and **statisticians**. Orgs form parent/child stock-owning/managing relationships (many-to-many), and a user's access to a log depends on whether their org owns or manages it. Pundit policies in `app/policies/` enforce this — always check the policy when adding controller actions.
+
+### Bulk upload
+
+Users upload a CSV per log-type per year; the file is saved to S3 and `ProcessBulkUploadJob` runs `BulkUpload::Processor`, which picks year- and type-specific `CsvParser`, `RowParser`, `Validator`, and `LogCreator` classes from `app/services/bulk_upload/`. Outcomes: clean upload, partial upload (requires user approval after error email), or rejected (template/critical errors). See `docs/bulk_upload.md`.
+
+### Exports to CDS
+
+`Exports::ExportService` orchestrates a nightly Sidekiq cron job that writes XML + manifests to S3 for ingestion by the Consolidated Data Store. Year-specific collections (lettings logs) can produce up to three concurrent collections during crossover. Field-level mapping lives in `lettings_log_export_service.rb`, `organisation_export_service.rb`, `user_export_service.rb`, gated by `EXPORT_FIELDS` constants in the matching `*_export_constants.rb` files (with `POST__EXPORT_FIELDS` for year-gated additions). Partial vs full export semantics are documented in `docs/exports.md`.
+
+### CSV downloads
+
+User-facing CSV downloads are also async via Sidekiq, delivered as S3 presigned URLs by email. Logs CSVs come in **labels** (human-readable) and **codes** (numeric, aligned with bulk upload / CDS) variants. Column selection lives in `lettings_log_attributes` / `sales_log_attributes` / `scheme_attributes` / `location_attributes` and (for users) `User.download_attributes`. Header descriptions live in the `csv_variable_definitions` table and are edited via `/admin`.
+
+### Rake tasks
+
+`lib/tasks/` holds many one-off and operational rake tasks (data corrections, migrations, exports, form-definition dumps). For ad-hoc production runs, tasks are executed as ECS Fargate tasks against `core-$env-ad-hoc` — see `docs/rake.md`.
+
+### Feature toggles
+
+`app/services/feature_toggle.rb` — simple class methods, no external flag service.
+
+### Frontend conventions
+
+- Service-specific components live in `app/components/` (ViewComponent), with `app-*` BEM class names to avoid clashing with the `govuk-*` Design System.
+- Stimulus controllers: register in `app/frontend/controllers/index.js` (kebab-case) and define in `app/frontend/controllers/` (underscore_case).
+- Webpack bundles JS/CSS via `jsbundling-rails` + `cssbundling-rails`; Propshaft serves the bundled assets. Babel transpiles to ES5 for IE compatibility (polyfills in `app/frontend/application.js`).
+
+## Testing notes
+
+- Prefer request specs over feature specs (faster, still cover route + controller + model + view). Use feature specs only when JavaScript or interaction-specific assertions are needed.
+- FactoryBot factories have deep callback chains: creating a `lettings_log`/`sales_log` also creates a `User`, `Organisation`, often a `DataProtectionConfirmation`, and an `OrganisationRentPeriod` (lettings only, if `period` is set). See `docs/testing.md` for the full breakdown — be aware that tests appearing to "just create a log" may be persisting several other records.
+- Capybara runs headless by default and uses Gecko driver for `js: true` specs (toggle in `spec/rails_helper.rb`).
+
+## Commit & PR conventions
+
+Commits and PRs are prefixed with the Jira ticket id (e.g. `CLDC-4300: ...`) — see `git log` for examples. Pre-commit hooks (Overcommit) run RuboCop and schema-up-to-date checks; do not skip them.
diff --git a/Dockerfile b/Dockerfile
index 88a7e6a79..ce24943c2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,10 @@
-FROM ruby:3.4.4-alpine3.20 as base
+FROM ruby:3.4.9-alpine3.23 as base
WORKDIR /app
+# Upgrade base packages to pick up latest security patches
+RUN apk upgrade --no-cache
+
# Add the timezone as it's not configured by default in Alpine
RUN apk add --update --no-cache tzdata && \
cp /usr/share/zoneinfo/Europe/London /etc/localtime && \
@@ -10,7 +13,7 @@ RUN apk add --update --no-cache tzdata && \
# build-base: compilation tools for bundle
# yarn: node package manager
# postgresql-dev: postgres driver and libraries
-RUN apk add --no-cache build-base=0.5-r3 busybox=1.36.1-r29 nodejs=20.15.1-r0 yarn=1.22.22-r0 bash=5.2.26-r0 libpq-dev yaml-dev linux-headers
+RUN apk add --no-cache build-base busybox nodejs yarn bash libpq-dev yaml-dev linux-headers
# Bundler version should be the same version as what the Gemfile.lock was bundled with
RUN gem install bundler:2.6.4 --no-document
@@ -40,14 +43,14 @@ RUN bundle config set without ""
RUN bundle install --jobs=4 --no-binstubs --no-cache
# Install gecko driver for Capybara tests
-RUN apk add firefox
+RUN apk add firefox=145.0-r0
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux64.tar.gz \
&& tar -xvzf geckodriver-v0.31.0-linux64.tar.gz \
&& rm geckodriver-v0.31.0-linux64.tar.gz \
&& chmod +x geckodriver \
&& mv geckodriver /usr/local/bin/
-CMD bundle exec rake parallel:setup && bundle exec rake parallel:spec
+CMD ["sh", "-c", "bundle exec rake parallel:setup && bundle exec rake parallel:spec"]
FROM base as development
@@ -61,7 +64,7 @@ RUN bundle install --jobs=4 --no-binstubs --no-cache
USER nonroot
-CMD bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0
+CMD ["sh", "-c", "bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0"]
FROM base as production
@@ -75,4 +78,4 @@ RUN chown -R nonroot performance_test
USER nonroot
-CMD bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0
+CMD ["sh", "-c", "bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0"]
diff --git a/Gemfile b/Gemfile
index 2b3897121..172a13e9f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,14 +3,14 @@
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
-ruby "3.4.4"
+ruby "3.4.9"
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
-gem "rails", "~> 7.2.2"
+gem "rails", "~> 8.1.3"
# Use postgresql as the database for Active Record
gem "pg", "~> 1.1"
# Use Puma as the app server
-gem "puma", "~> 6.4"
+gem "puma", "~> 7.2.1"
# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
gem "propshaft"
# Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]
@@ -18,7 +18,7 @@ gem "jsbundling-rails"
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", ">= 1.4.4", require: false
# GOV UK frontend components
-gem "govuk-components", "~> 5.7"
+gem "govuk-components", "~> 6.2"
# GOV UK component form builder DSL
gem "govuk_design_system_formbuilder", "~> 5.7"
# Convert Markdown into GOV.UK frontend-styled HTML
@@ -40,11 +40,11 @@ gem "devise_two_factor_authentication"
gem "uk_postcode"
# Get rich data from postcode lookups. Wraps postcodes.io
# Use Ruby objects to build reusable markup. A React inspired evolution of the presenter pattern
-gem "view_component", "~> 3.9"
+gem "view_component", "~> 4.9"
# Use the AWS S3 SDK as storage mechanism
gem "aws-sdk-s3"
# Track changes to models for auditing or versioning.
-gem "paper_trail", "~> 15.2"
+gem "paper_trail", "~> 17.0"
# Store active record objects in version whodunnits
gem "paper_trail-globalid"
@@ -67,7 +67,7 @@ gem "faker"
gem "method_source", "~> 1.1"
gem "rails_admin", "~> 3.1"
gem "ruby-openai"
-gem "sidekiq"
+gem "sidekiq", "~> 7.2.4"
gem "sidekiq-cron"
gem "unread"
@@ -75,9 +75,6 @@ gem "unread"
gem "nokogiri", "~> 1.19.1"
gem "thor", "~> 1.4.0"
-# Pinning until activesupport is updated to v8.1.2
-gem "connection_pool", "~> 2.5"
-
group :development, :test do
# Check gems for known vulnerabilities
gem "bundler-audit"
@@ -119,7 +116,7 @@ end
gem "cssbundling-rails"
gem "tzinfo-data", platforms: %i[mingw mswin x64_mingw jruby]
-gem "excon", "~> 0.111.0"
+gem "excon", ">= 1.5.0"
-# faraday is a transitive dependency, but we need to force the version to 2.14.1 to avoid a vulnerability.
-gem "faraday", ">= 2.14.1"
+# faraday is a transitive dependency, but we need to force the version to 2.14.3 to avoid a vulnerability.
+gem "faraday", ">= 2.14.3"
diff --git a/Gemfile.lock b/Gemfile.lock
index 52368da38..542b392a0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,85 +1,86 @@
GEM
remote: https://rubygems.org/
specs:
- actioncable (7.2.3.1)
- actionpack (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ action_text-trix (2.1.19)
+ railties
+ actioncable (8.1.3.1)
+ actionpack (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
- actionmailbox (7.2.3.1)
- actionpack (= 7.2.3.1)
- activejob (= 7.2.3.1)
- activerecord (= 7.2.3.1)
- activestorage (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ actionmailbox (8.1.3.1)
+ actionpack (= 8.1.3.1)
+ activejob (= 8.1.3.1)
+ activerecord (= 8.1.3.1)
+ activestorage (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
mail (>= 2.8.0)
- actionmailer (7.2.3.1)
- actionpack (= 7.2.3.1)
- actionview (= 7.2.3.1)
- activejob (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ actionmailer (8.1.3.1)
+ actionpack (= 8.1.3.1)
+ actionview (= 8.1.3.1)
+ activejob (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
mail (>= 2.8.0)
rails-dom-testing (~> 2.2)
- actionpack (7.2.3.1)
- actionview (= 7.2.3.1)
- activesupport (= 7.2.3.1)
- cgi
+ actionpack (8.1.3.1)
+ actionview (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
nokogiri (>= 1.8.5)
- racc
- rack (>= 2.2.4, < 3.3)
+ rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
useragent (~> 0.16)
- actiontext (7.2.3.1)
- actionpack (= 7.2.3.1)
- activerecord (= 7.2.3.1)
- activestorage (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ actiontext (8.1.3.1)
+ action_text-trix (~> 2.1.15)
+ actionpack (= 8.1.3.1)
+ activerecord (= 8.1.3.1)
+ activestorage (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (7.2.3.1)
- activesupport (= 7.2.3.1)
+ actionview (8.1.3.1)
+ activesupport (= 8.1.3.1)
builder (~> 3.1)
- cgi
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
- activejob (7.2.3.1)
- activesupport (= 7.2.3.1)
+ activejob (8.1.3.1)
+ activesupport (= 8.1.3.1)
globalid (>= 0.3.6)
- activemodel (7.2.3.1)
- activesupport (= 7.2.3.1)
+ activemodel (8.1.3.1)
+ activesupport (= 8.1.3.1)
activemodel-serializers-xml (1.0.3)
activemodel (>= 5.0.0.a)
activesupport (>= 5.0.0.a)
builder (~> 3.1)
- activerecord (7.2.3.1)
- activemodel (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ activerecord (8.1.3.1)
+ activemodel (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
timeout (>= 0.4.0)
- activestorage (7.2.3.1)
- actionpack (= 7.2.3.1)
- activejob (= 7.2.3.1)
- activerecord (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ activestorage (8.1.3.1)
+ actionpack (= 8.1.3.1)
+ activejob (= 8.1.3.1)
+ activerecord (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
marcel (~> 1.0)
- activesupport (7.2.3.1)
+ activesupport (8.1.3.1)
base64
- benchmark (>= 0.3)
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
+ json
logger (>= 1.4.2)
- minitest (>= 5.1, < 6)
+ minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
- addressable (2.8.6)
- public_suffix (>= 2.0.2, < 6.0)
+ uri (>= 0.13.1)
+ addressable (2.9.0)
+ public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
auto_strip_attributes (2.6.0)
activerecord (>= 4.0)
@@ -115,7 +116,6 @@ GEM
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.3.0)
bcrypt (3.1.22)
- benchmark (0.5.0)
better_html (2.2.0)
actionview (>= 7.0)
activesupport (>= 7.0)
@@ -123,7 +123,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
- bigdecimal (4.0.1)
+ bigdecimal (4.1.2)
bindex (0.8.1)
bootsnap (1.18.3)
msgpack (~> 1.2)
@@ -149,24 +149,26 @@ GEM
capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4)
launchy
- cgi (0.5.1)
childprocess (5.0.0)
coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
- concurrent-ruby (1.3.6)
- connection_pool (2.5.3)
+ concurrent-ruby (1.3.8)
+ connection_pool (2.5.5)
crack (1.0.0)
bigdecimal
rexml
- crass (1.0.6)
+ crass (1.0.7)
+ cronex (0.15.0)
+ tzinfo
+ unicode (>= 0.4.4.5)
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
csv (3.3.2)
date (3.5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
- devise (5.0.3)
+ devise (5.0.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 7.0)
@@ -187,7 +189,7 @@ GEM
drb (2.2.3)
dumb_delegator (1.0.0)
encryptor (3.0.0)
- erb (6.0.2)
+ erb (6.0.4)
erb_lint (0.9.0)
activesupport
better_html (>= 2.0.1)
@@ -196,10 +198,11 @@ GEM
rubocop (>= 1)
smart_properties
erubi (1.13.1)
- et-orbi (1.2.11)
+ et-orbi (1.4.0)
tzinfo
event_stream_parser (1.0.0)
- excon (0.111.0)
+ excon (1.5.0)
+ logger
factory_bot (6.5.0)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.4)
@@ -207,24 +210,24 @@ GEM
railties (>= 5.0.0)
faker (3.2.3)
i18n (>= 1.8.11, < 2)
- faraday (2.14.1)
+ faraday (2.14.3)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-multipart (1.0.4)
multipart-post (~> 2)
- faraday-net_http (3.1.0)
- net-http
+ faraday-net_http (3.4.3)
+ net-http (~> 0.5)
ffi (1.16.3)
- fugit (1.11.1)
- et-orbi (~> 1, >= 1.2.11)
+ fugit (1.12.2)
+ et-orbi (~> 1.4)
raabro (~> 1.4)
- globalid (1.2.1)
+ globalid (1.4.0)
activesupport (>= 6.1)
- govuk-components (5.7.0)
+ govuk-components (6.4.0)
html-attributes-utils (~> 1.0.0, >= 1.0.0)
pagy (>= 6, < 10)
- view_component (>= 3.9, < 3.17)
+ view_component (>= 4.9, < 4.13)
govuk_design_system_formbuilder (5.7.1)
actionview (>= 6.1)
activemodel (>= 6.1)
@@ -236,12 +239,12 @@ GEM
hashdiff (1.1.0)
html-attributes-utils (1.0.2)
activesupport (>= 6.1.4.4)
- i18n (1.14.8)
+ i18n (1.15.2)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
iniparse (1.5.0)
io-console (0.8.2)
- irb (1.17.0)
+ irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
@@ -249,10 +252,10 @@ GEM
jmespath (1.6.2)
jsbundling-rails (1.3.0)
railties (>= 6.0.0)
- json (2.19.2)
+ json (2.20.0)
json-schema (4.1.1)
addressable (>= 2.8)
- jwt (2.8.0)
+ jwt (3.2.0)
base64
kaminari (1.2.2)
activesupport (>= 4.1.0)
@@ -274,7 +277,7 @@ GEM
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0)
- loofah (2.25.1)
+ loofah (2.25.2)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@@ -282,17 +285,17 @@ GEM
net-imap
net-pop
net-smtp
- marcel (1.0.4)
+ marcel (1.2.1)
matrix (0.4.2)
method_source (1.1.0)
mini_mime (1.1.5)
minitest (5.27.0)
- msgpack (1.7.2)
+ msgpack (1.8.3)
multipart-post (2.4.1)
nested_form (0.3.2)
- net-http (0.4.1)
- uri
- net-imap (0.5.7)
+ net-http (0.9.1)
+ uri (>= 0.11.1)
+ net-imap (0.6.4.1)
date
net-protocol
net-pop (0.1.2)
@@ -301,25 +304,25 @@ GEM
timeout
net-smtp (0.5.1)
net-protocol
- nio4r (2.7.4)
- nokogiri (1.19.1-arm64-darwin)
+ nio4r (2.7.5)
+ nokogiri (1.19.4-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-darwin)
+ nokogiri (1.19.4-x86_64-darwin)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-linux-gnu)
+ nokogiri (1.19.4-x86_64-linux-gnu)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-linux-musl)
+ nokogiri (1.19.4-x86_64-linux-musl)
racc (~> 1.4)
- notifications-ruby-client (6.0.0)
- jwt (>= 1.5, < 3)
+ notifications-ruby-client (6.4.0)
+ jwt (>= 1.5, < 4)
orm_adapter (0.5.0)
overcommit (0.63.0)
childprocess (>= 0.6.3, < 6)
iniparse (~> 1.4)
rexml (~> 3.2)
- pagy (9.3.2)
- paper_trail (15.2.0)
- activerecord (>= 6.1)
+ pagy (9.4.0)
+ paper_trail (17.0.0)
+ activerecord (>= 7.1)
request_store (~> 1.4)
paper_trail-globalid (0.2.0)
globalid
@@ -350,45 +353,45 @@ GEM
psych (5.3.1)
date
stringio
- public_suffix (5.0.4)
- puma (6.5.0)
+ public_suffix (7.0.5)
+ puma (7.2.1)
nio4r (~> 2.0)
pundit (2.3.1)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
- rack (3.1.20)
+ rack (3.1.21)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-mini-profiler (3.3.1)
rack (>= 1.2.0)
- rack-session (2.1.1)
+ rack-session (2.1.2)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.3.1)
rack (>= 3)
- rails (7.2.3.1)
- actioncable (= 7.2.3.1)
- actionmailbox (= 7.2.3.1)
- actionmailer (= 7.2.3.1)
- actionpack (= 7.2.3.1)
- actiontext (= 7.2.3.1)
- actionview (= 7.2.3.1)
- activejob (= 7.2.3.1)
- activemodel (= 7.2.3.1)
- activerecord (= 7.2.3.1)
- activestorage (= 7.2.3.1)
- activesupport (= 7.2.3.1)
+ rails (8.1.3.1)
+ actioncable (= 8.1.3.1)
+ actionmailbox (= 8.1.3.1)
+ actionmailer (= 8.1.3.1)
+ actionpack (= 8.1.3.1)
+ actiontext (= 8.1.3.1)
+ actionview (= 8.1.3.1)
+ activejob (= 8.1.3.1)
+ activemodel (= 8.1.3.1)
+ activerecord (= 8.1.3.1)
+ activestorage (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
bundler (>= 1.15.0)
- railties (= 7.2.3.1)
+ railties (= 8.1.3.1)
rails-dom-testing (2.3.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
- rails-html-sanitizer (1.7.0)
- loofah (~> 2.25)
+ rails-html-sanitizer (1.7.1)
+ loofah (~> 2.25, >= 2.25.2)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails_admin (3.3.0)
activemodel-serializers-xml (>= 1.0)
@@ -397,10 +400,9 @@ GEM
nested_form (~> 0.3)
rails (>= 6.0, < 9)
turbo-rails (>= 1.0, < 3)
- railties (7.2.3.1)
- actionpack (= 7.2.3.1)
- activesupport (= 7.2.3.1)
- cgi
+ railties (8.1.3.1)
+ actionpack (= 8.1.3.1)
+ activesupport (= 8.1.3.1)
irb (~> 1.13)
rackup (>= 1.0.0)
rake (>= 12.2)
@@ -408,7 +410,7 @@ GEM
tsort (>= 0.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
- rake (13.3.1)
+ rake (13.4.2)
randexp (0.1.7)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
@@ -419,7 +421,7 @@ GEM
tsort
redcarpet (3.6.0)
redis (4.8.1)
- redis-client (0.22.1)
+ redis-client (0.29.0)
connection_pool
regexp_parser (2.11.3)
reline (0.6.3)
@@ -514,10 +516,11 @@ GEM
connection_pool (>= 2.3.0)
rack (>= 2.2.4)
redis-client (>= 0.19.0)
- sidekiq-cron (1.12.0)
- fugit (~> 1.8)
+ sidekiq-cron (2.4.0)
+ cronex (>= 0.13.0)
+ fugit (~> 1.8, >= 1.11.1)
globalid (>= 1.0.1)
- sidekiq (>= 6)
+ sidekiq (>= 6.5.0)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
@@ -531,7 +534,7 @@ GEM
thor (1.4.0)
thread_safe (0.3.6)
timecop (0.9.8)
- timeout (0.4.3)
+ timeout (0.6.1)
tsort (0.2.0)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
@@ -539,17 +542,18 @@ GEM
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uk_postcode (2.1.8)
+ unicode (0.4.4.5)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
unread (0.14.0)
activerecord (>= 6.1)
- uri (1.0.4)
+ uri (1.1.1)
useragent (0.16.11)
- view_component (3.10.0)
- activesupport (>= 5.2.0, < 8.0)
- concurrent-ruby (~> 1.0)
- method_source (~> 1.0)
+ view_component (4.12.0)
+ actionview (>= 7.1.0)
+ activesupport (>= 7.1.0)
+ concurrent-ruby (~> 1)
virtus (2.0.0)
axiom-types (~> 0.1)
coercible (~> 1.0)
@@ -566,13 +570,13 @@ GEM
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
websocket (1.2.10)
- websocket-driver (0.7.7)
+ websocket-driver (0.8.2)
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.7.5)
+ zeitwerk (2.8.2)
PLATFORMS
arm64-darwin
@@ -590,17 +594,16 @@ DEPENDENCIES
capybara
capybara-lockstep
capybara-screenshot
- connection_pool (~> 2.5)
cssbundling-rails
devise
devise_two_factor_authentication
dotenv-rails
erb_lint
- excon (~> 0.111.0)
+ excon (>= 1.5.0)
factory_bot_rails
faker
- faraday (>= 2.14.1)
- govuk-components (~> 5.7)
+ faraday (>= 2.14.3)
+ govuk-components (~> 6.2)
govuk_design_system_formbuilder (~> 5.7)
govuk_markdown
jsbundling-rails
@@ -610,19 +613,19 @@ DEPENDENCIES
nokogiri (~> 1.19.1)
notifications-ruby-client
overcommit (>= 0.37.0)
- paper_trail (~> 15.2)
+ paper_trail (~> 17.0)
paper_trail-globalid
parallel_tests
pg (~> 1.1)
possessive
propshaft
pry-byebug
- puma (~> 6.4)
+ puma (~> 7.2.1)
pundit
rack (~> 3.1.20)
rack-attack
rack-mini-profiler (~> 3.3.0)
- rails (~> 7.2.2)
+ rails (~> 8.1.3)
rails_admin (~> 3.1)
redcarpet (~> 3.6)
redis (~> 4.8)
@@ -635,7 +638,7 @@ DEPENDENCIES
selenium-webdriver (~> 4.43)
sentry-rails
sentry-ruby
- sidekiq
+ sidekiq (~> 7.2.4)
sidekiq-cron
simplecov
stimulus-rails
@@ -644,12 +647,12 @@ DEPENDENCIES
tzinfo-data
uk_postcode
unread
- view_component (~> 3.9)
+ view_component (~> 4.9)
web-console (>= 4.1.0)
webmock
RUBY VERSION
- ruby 3.4.4p0
+ ruby 3.4.9p82
BUNDLED WITH
2.6.4
diff --git a/app/components/bulk_upload_error_row_component.html.erb b/app/components/bulk_upload_error_row_component.html.erb
index 8cfdb674e..4ce6e4f5c 100644
--- a/app/components/bulk_upload_error_row_component.html.erb
+++ b/app/components/bulk_upload_error_row_component.html.erb
@@ -13,7 +13,7 @@
<% if critical_errors.any? %>
Critical errors
These errors must be fixed to complete your logs.
- <%= govuk_table(html_attributes: { class: potential_errors.any? ? "" : "no-bottom-border" }) do |table| %>
+ <%= helpers.govuk_table(html_attributes: { class: potential_errors.any? ? "" : "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
@@ -39,7 +39,7 @@
<% if potential_errors.any? %>
Confirmation needed
Potential data discrepancies exist in the following cells.
Please resolve all critical errors and review the cells with data discrepancies before re-uploading the file. Bulk confirmation of potential discrepancies is accessible only after all critical errors have been resolved.
- <%= govuk_table(html_attributes: { class: "no-bottom-border" }) do |table| %>
+ <%= helpers.govuk_table(html_attributes: { class: "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
diff --git a/app/components/bulk_upload_error_row_component.rb b/app/components/bulk_upload_error_row_component.rb
index 1cb4de9d8..569f71b85 100644
--- a/app/components/bulk_upload_error_row_component.rb
+++ b/app/components/bulk_upload_error_row_component.rb
@@ -2,9 +2,8 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
attr_reader :bulk_upload_errors
def initialize(bulk_upload_errors:)
+ super()
@bulk_upload_errors = bulk_upload_errors
-
- super
end
def row
@@ -18,7 +17,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def tenant_code_html
return if tenant_code.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Tenant code: #{tenant_code}"
end
end
@@ -30,7 +29,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def purchaser_code_html
return if purchaser_code.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Purchaser code: #{purchaser_code}"
end
end
@@ -42,7 +41,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def property_ref_html
return if property_ref.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Property reference: #{property_ref}"
end
end
diff --git a/app/components/bulk_upload_error_summary_table_component.html.erb b/app/components/bulk_upload_error_summary_table_component.html.erb
index f9b42f34d..58489612a 100644
--- a/app/components/bulk_upload_error_summary_table_component.html.erb
+++ b/app/components/bulk_upload_error_summary_table_component.html.erb
@@ -3,7 +3,7 @@
<% sorted_errors.each do |error| %>
- <%= govuk_table do |table| %>
+ <%= helpers.govuk_table do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(text: question_for_field(error[0][1].to_sym), header: true) %>
@@ -13,7 +13,7 @@
<%= table.with_body do |body| %>
<% body.with_row do |row| %>
<% row.with_cell(text: error[0][2].html_safe) %>
- <% row.with_cell(text: pluralize(error[1], "error"), numeric: true) %>
+ <% row.with_cell(text: helpers.pluralize(error[1], "error"), numeric: true) %>
<% end %>
<% end %>
<% end %>
diff --git a/app/components/bulk_upload_error_summary_table_component.rb b/app/components/bulk_upload_error_summary_table_component.rb
index d15d5280e..db69fd9ec 100644
--- a/app/components/bulk_upload_error_summary_table_component.rb
+++ b/app/components/bulk_upload_error_summary_table_component.rb
@@ -6,9 +6,8 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
delegate :question_for_field, to: :row_parser_class
def initialize(bulk_upload:)
+ super()
@bulk_upload = bulk_upload
-
- super
end
def sorted_errors
diff --git a/app/components/bulk_upload_summary_component.rb b/app/components/bulk_upload_summary_component.rb
index fa4cad414..2df854536 100644
--- a/app/components/bulk_upload_summary_component.rb
+++ b/app/components/bulk_upload_summary_component.rb
@@ -2,9 +2,9 @@ class BulkUploadSummaryComponent < ViewComponent::Base
attr_reader :bulk_upload
def initialize(bulk_upload:)
+ super()
@bulk_upload = bulk_upload
@bulk_upload_errors = bulk_upload.bulk_upload_errors
- super
end
def upload_status
@@ -27,9 +27,9 @@ class BulkUploadSummaryComponent < ViewComponent::Base
return if count.nil? || count <= 0
text = count > 1 ? (plural_text || singular_text.pluralize(count)) : singular_text
- content_tag(:p, class: "govuk-!-font-size-16 govuk-!-margin-bottom-1") do
- concat(content_tag(:strong, count))
- concat(" #{text}")
+ helpers.content_tag(:p, class: "govuk-!-font-size-16 govuk-!-margin-bottom-1") do
+ helpers.concat(helpers.content_tag(:strong, count))
+ helpers.concat(" #{text}")
end
end
@@ -44,11 +44,11 @@ class BulkUploadSummaryComponent < ViewComponent::Base
end
def download_lettings_file_link(bulk_upload)
- govuk_link_to "Download file", download_lettings_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
+ helpers.govuk_link_to "Download file", download_lettings_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
end
def download_sales_file_link(bulk_upload)
- govuk_link_to "Download file", download_sales_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
+ helpers.govuk_link_to "Download file", download_sales_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
end
def view_error_report_link(bulk_upload)
@@ -61,12 +61,12 @@ class BulkUploadSummaryComponent < ViewComponent::Base
"bulk_upload_#{bulk_upload.log_type}_result_path"
end
- govuk_link_to "View error report", send(path, bulk_upload), class: "govuk-link"
+ helpers.govuk_link_to "View error report", helpers.send(path, bulk_upload), class: "govuk-link"
end
def view_logs_link(bulk_upload)
return unless bulk_upload.status.to_s == "logs_uploaded_with_errors"
- govuk_link_to "View logs with errors", send("#{bulk_upload.log_type}_logs_path", bulk_upload_id: [bulk_upload.id]), class: "govuk-link"
+ helpers.govuk_link_to "View logs with errors", helpers.send("#{bulk_upload.log_type}_logs_path", bulk_upload_id: [bulk_upload.id]), class: "govuk-link"
end
end
diff --git a/app/components/check_answers_summary_list_card_component.html.erb b/app/components/check_answers_summary_list_card_component.html.erb
index 8b0c7d9b0..c9c974938 100644
--- a/app/components/check_answers_summary_list_card_component.html.erb
+++ b/app/components/check_answers_summary_list_card_component.html.erb
@@ -7,12 +7,12 @@
<% end %>
- <%= govuk_summary_list do |summary_list| %>
+ <%= helpers.govuk_summary_list do |summary_list| %>
<% applicable_questions.each do |question| %>
<% summary_list.with_row do |row| %>
<% row.with_key { get_question_label(question) } %>
<% row.with_value do %>
- <%= simple_format(
+ <%= helpers.simple_format(
get_answer_label(question),
wrapper_tag: "span",
class: "govuk-!-margin-right-4",
@@ -21,7 +21,7 @@
<% extra_value = question.get_extra_check_answer_value(log) %>
<% if extra_value && question.answer_label(log).present? %>
- <%= simple_format(
+ <%= helpers.simple_format(
extra_value,
wrapper_tag: "span",
class: "govuk-!-font-weight-regular app-!-colour-muted",
diff --git a/app/components/check_answers_summary_list_card_component.rb b/app/components/check_answers_summary_list_card_component.rb
index 1dc345f01..89345a0eb 100644
--- a/app/components/check_answers_summary_list_card_component.rb
+++ b/app/components/check_answers_summary_list_card_component.rb
@@ -2,12 +2,11 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
attr_reader :questions, :log, :user
def initialize(questions:, log:, user:, correcting_hard_validation: false)
+ super()
@questions = questions
@log = log
@user = user
@correcting_hard_validation = correcting_hard_validation
-
- super
end
def applicable_questions
@@ -34,16 +33,16 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
def action_href(question, log)
referrer = question.displayed_as_answered?(log) ? "check_answers" : "check_answers_new_answer"
- send("#{log.log_type}_#{question.page.id}_path", log, referrer:)
+ helpers.send("#{log.log_type}_#{question.page.id}_path", log, referrer:)
end
def correct_validation_action_href(question, log, _related_question_ids, correcting_hard_validation)
return action_href(question, log) unless correcting_hard_validation
if question.displayed_as_answered?(log)
- send("#{log.log_type}_confirm_clear_answer_path", log, question_id: question.id)
+ helpers.send("#{log.log_type}_confirm_clear_answer_path", log, question_id: question.id)
else
- send("#{log.log_type}_#{question.page.id}_path", log, referrer: "check_errors", related_question_ids: request.query_parameters["related_question_ids"], original_page_id: request.query_parameters["original_page_id"])
+ helpers.send("#{log.log_type}_#{question.page.id}_path", log, referrer: "check_errors", related_question_ids: request.query_parameters["related_question_ids"], original_page_id: request.query_parameters["original_page_id"])
end
end
@@ -56,7 +55,7 @@ private
"govuk-link govuk-link--no-visited-state"
end
- govuk_link_to question.check_answer_prompt, correct_validation_action_href(question, log, nil, @correcting_hard_validation), class: link_class
+ helpers.govuk_link_to question.check_answer_prompt, correct_validation_action_href(question, log, nil, @correcting_hard_validation), class: link_class
end
def number_of_buyers
diff --git a/app/components/create_log_actions_component.html.erb b/app/components/create_log_actions_component.html.erb
index 130072ec0..c8f557bce 100644
--- a/app/components/create_log_actions_component.html.erb
+++ b/app/components/create_log_actions_component.html.erb
@@ -1,11 +1,11 @@
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_sales_results/summary.html.erb b/app/views/bulk_upload_sales_results/summary.html.erb
index ed2ec14b3..fc9f39d82 100644
--- a/app/views/bulk_upload_sales_results/summary.html.erb
+++ b/app/views/bulk_upload_sales_results/summary.html.erb
@@ -1,3 +1,7 @@
+<% content_for :before_content do %>
+ <%= govuk_back_link(href: :back) %>
+<% end %>
+
<%= render partial: "bulk_upload_shared/moved_user_banner" %>
@@ -34,4 +38,6 @@
<% end %>
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_sales_resume/confirm.html.erb b/app/views/bulk_upload_sales_resume/confirm.html.erb
index b47619053..1259d8bf9 100644
--- a/app/views/bulk_upload_sales_resume/confirm.html.erb
+++ b/app/views/bulk_upload_sales_resume/confirm.html.erb
@@ -9,7 +9,7 @@
<%= logs_and_errors_warning(@bulk_upload) %>
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<% if unique_answers_to_be_cleared(@bulk_upload).present? %>
diff --git a/app/views/bulk_upload_sales_resume/fix_choice.html.erb b/app/views/bulk_upload_sales_resume/fix_choice.html.erb
index b376ee62d..8a2887678 100644
--- a/app/views/bulk_upload_sales_resume/fix_choice.html.erb
+++ b/app/views/bulk_upload_sales_resume/fix_choice.html.erb
@@ -19,7 +19,7 @@
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<%= govuk_details(summary_text: "How to choose between fixing errors on the CORE site or in the CSV") do %>
diff --git a/app/views/form/guidance/_building_height_class.html.erb b/app/views/form/guidance/_building_height_class.html.erb
new file mode 100644
index 000000000..f538ae151
--- /dev/null
+++ b/app/views/form/guidance/_building_height_class.html.erb
@@ -0,0 +1,5 @@
+
+ <%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.building_height_class.title")) do %>
+ <%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.building_height_class.content").html_safe %>
+ <% end %>
+
diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb
index bf455a6cd..7e35f28c2 100644
--- a/app/views/layouts/_footer.html.erb
+++ b/app/views/layouts/_footer.html.erb
@@ -1,42 +1,44 @@
-<%= govuk_footer do |footer| %>
- <%= footer.with_meta do %>
-