diff --git a/.env.example b/.env.example
index 5796d781c..9eab453cf 100644
--- a/.env.example
+++ b/.env.example
@@ -14,7 +14,7 @@ SENDGRID_USERNAME=test_smtp_username
SENDGRID_PASSWORD=test_smtp_password
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
-AWS_REGION=xxx
+AWS_REGION=xxx
AWS_S3_BUCKET_NAME=xxx
DISPLAY_SOCIAL_MOBILITY_AWARD=true
PUSHER_SOCKET_HOST=localhost
@@ -24,4 +24,5 @@ PUSHER_APP_KEY=app_key
PUSHER_SECRET=secret
DEBOUNCE_API_KEY=test
GOV_UK_NOTIFY_API_KEY=key
-GOV_UK_NOTIFY_API_TEMPLATE_ID=id
\ No newline at end of file
+GOV_UK_NOTIFY_API_TEMPLATE_ID=id
+SESSION_TIMEOUT=1
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eea4c6fee..8db9f826c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: '16'
@@ -54,14 +54,13 @@ jobs:
env:
DISPLAY_SOCIAL_MOBILITY_AWARD: true
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/qae_test'
- BUNDLER_VERSION: 2.4.8
+ BUNDLER_VERSION: 2.4.19
DOCKER_TLS_CERTDIR: ''
run: |
sudo apt update
sudo apt-get -yqq install postgresql postgresql-client libpq-dev xvfb unzip libcurl4 libcurl3-gnutls libcurl4-openssl-dev
gem install bundler
gem update --system && gem update bundler
- bundle config path vendor/bundle
yarn install
bundle install --jobs 4 --retry 3
RAILS_ENV=test bundle exec rake db:create db:migrate
@@ -83,7 +82,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: '16'
@@ -124,7 +123,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: '16'
diff --git a/.github/workflows/deploy_development.yml b/.github/workflows/deploy_development.yml
index 08eef44d0..74bd31db8 100644
--- a/.github/workflows/deploy_development.yml
+++ b/.github/workflows/deploy_development.yml
@@ -16,7 +16,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: "16"
diff --git a/.github/workflows/deploy_production.yml b/.github/workflows/deploy_production.yml
index 6b52c737e..044f20bf3 100644
--- a/.github/workflows/deploy_production.yml
+++ b/.github/workflows/deploy_production.yml
@@ -17,7 +17,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: "16"
diff --git a/.github/workflows/deploy_staging.yml b/.github/workflows/deploy_staging.yml
index 94fb40315..e9eb9b1ed 100644
--- a/.github/workflows/deploy_staging.yml
+++ b/.github/workflows/deploy_staging.yml
@@ -17,7 +17,7 @@ jobs:
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
- ruby-version: 2.7.7
+ ruby-version: 3.2.2
- uses: actions/setup-node@v2-beta
with:
node-version: '16'
diff --git a/.ruby-version b/.ruby-version
index 1f7da99d4..be94e6f53 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.7.7
+3.2.2
diff --git a/.tool-versions b/.tool-versions
new file mode 100644
index 000000000..29d3872ec
--- /dev/null
+++ b/.tool-versions
@@ -0,0 +1,2 @@
+ruby 3.2.2
+nodejs 18.17.1
diff --git a/Dockerfile.local b/Dockerfile.local
index 7578b7fc8..c26f559c9 100644
--- a/Dockerfile.local
+++ b/Dockerfile.local
@@ -1,6 +1,6 @@
-ARG RUBY_VERSION=2.7.7
+ARG RUBY_VERSION=3.2.2
-FROM ruby:2.7.7
+FROM ruby:3.2.2
ENV HOME=/app
WORKDIR /app
@@ -18,7 +18,7 @@ COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle config set --local path 'vendor/bundle'
RUN bundle config set --local without 'development test'
-RUN gem install bundler:2.4.8 && bundle install --jobs 4 --retry 3
+RUN gem install bundler:2.4.19 && bundle install --jobs 4 --retry 3
COPY . /app
RUN yarn install
diff --git a/Gemfile b/Gemfile
index 61fe26583..1b99ba0a8 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,9 +2,9 @@ source 'https://rubygems.org'
git_source(:github) { |name| "https://github.com/#{name}.git" }
-ruby '~> 2.7.7'
+ruby '~> 3.2.2'
-gem 'rails', '6.1.7.3'
+gem 'rails', '7.0.5.1'
gem 'websocket-extensions', '~> 0.1.5'
# SSL redirect
@@ -14,12 +14,13 @@ gem 'rack-ssl-enforcer'
gem 'pg'
# Track Changes
-gem 'paper_trail', '~> 10.3'
+gem 'paper_trail', '~> 12.2.0'
+gem 'paper_trail-association_tracking'
# Assets & Templates
gem 'sprockets', '~> 3.7.2'
gem 'sprockets-rails', '>= 2.0.0'
-gem 'sassc-rails', '~> 2.0.0'
+gem 'sassc-rails', '~> 2.1.2'
gem 'slim-rails', '~> 3.2.0'
gem 'coffee-rails', '5.0'
gem 'jquery-rails', '4.4.0'
@@ -29,7 +30,7 @@ gem 'govuk-components'
gem 'uglifier', '>= 2.7.2'
gem 'js_cookie_rails', '2.1.4'
gem 'ckeditor'
-gem 'webpacker', '6.0.0.beta.7'
+gem 'webpacker', '6.0.0.rc.6'
# Autolinking in admin mass user mailer
gem 'rails_autolink'
@@ -37,7 +38,6 @@ gem 'rails_autolink'
# Decorators & Exposing named methods
gem 'draper', '~> 4.0'
gem 'decent_exposure'
-gem 'decent_decoration'
gem 'hashie', '~> 3.5'
@@ -48,7 +48,7 @@ gem 'responders', '~> 3.0'
gem 'rails-html-sanitizer', '~> 1.4.4'
# JSON
-gem 'json', '2.3.0'
+gem 'json'
gem 'jbuilder', '~> 2.10.1'
gem 'gon', '>= 6.4.0'
@@ -87,7 +87,6 @@ gem 'nokogiri'
# Uploads
gem 'carrierwave', '~> 1.3'
-gem 'fog', "1.42.1"
gem "fog-aws"
gem 'vigilion', '~> 1.0.4'
gem 'vigilion-rails', '~> 2.2.0'
@@ -126,7 +125,7 @@ gem 'nilify_blanks'
gem 'curb', '0.9.10'
# Web server
-gem 'puma', '~> 4.3.12'
+gem 'puma', '~> 6.3.1'
# Performance & Error reporting
gem 'appsignal'
@@ -144,6 +143,8 @@ gem 'shog'
gem 'rails-healthcheck'
+gem 'matrix'
+
# Used to convert HTML to text, with the exception of whitelisted attributes.
# This makes it easier for us to display HTML content within PDF documents.
gem 'sanitize'
@@ -179,7 +180,7 @@ end
group :test do
gem 'factory_bot_rails'
- gem 'capybara', '3.33'
+ gem 'capybara', '~> 3.39.0'
gem 'poltergeist'
gem 'database_cleaner-active_record'
gem 'launchy'
@@ -189,6 +190,6 @@ group :test do
gem 'codeclimate_circle_ci_coverage'
gem 'rspec_junit_formatter', '0.2.3'
gem 'timecop'
- gem 'webmock', '3.5.0'
+ gem 'webmock', '3.18.1'
gem 'rspec-sidekiq'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 1c637713a..1191e9fde 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -10,81 +10,83 @@ GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.0)
- CFPropertyList (2.3.6)
- actioncable (6.1.7.3)
- actionpack (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actioncable (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.1.7.3)
- actionpack (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionmailbox (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ activejob (= 7.0.5.1)
+ activerecord (= 7.0.5.1)
+ activestorage (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
mail (>= 2.7.1)
- actionmailer (6.1.7.3)
- actionpack (= 6.1.7.3)
- actionview (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ net-imap
+ net-pop
+ net-smtp
+ actionmailer (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ actionview (= 7.0.5.1)
+ activejob (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
mail (~> 2.5, >= 2.5.4)
+ net-imap
+ net-pop
+ net-smtp
rails-dom-testing (~> 2.0)
- actionpack (6.1.7.3)
- actionview (= 6.1.7.3)
- activesupport (= 6.1.7.3)
- rack (~> 2.0, >= 2.0.9)
+ actionpack (7.0.5.1)
+ actionview (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
+ rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.1.7.3)
- actionpack (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ actiontext (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ activerecord (= 7.0.5.1)
+ activestorage (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
+ globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
- actionview (6.1.7.3)
- activesupport (= 6.1.7.3)
+ actionview (7.0.5.1)
+ activesupport (= 7.0.5.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- active_hash (3.1.1)
+ active_hash (3.2.0)
activesupport (>= 5.0.0)
- activejob (6.1.7.3)
- activesupport (= 6.1.7.3)
+ activejob (7.0.5.1)
+ activesupport (= 7.0.5.1)
globalid (>= 0.3.6)
- activemodel (6.1.7.3)
- activesupport (= 6.1.7.3)
+ activemodel (7.0.5.1)
+ activesupport (= 7.0.5.1)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
builder (~> 3.1)
- activerecord (6.1.7.3)
- activemodel (= 6.1.7.3)
- activesupport (= 6.1.7.3)
- activestorage (6.1.7.3)
- actionpack (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ activerecord (7.0.5.1)
+ activemodel (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
+ activestorage (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ activejob (= 7.0.5.1)
+ activerecord (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
- activesupport (6.1.7.3)
+ activesupport (7.0.5.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
- zeitwerk (~> 2.3)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
afm (0.2.2)
- aliyun-sdk (0.8.0)
- nokogiri (~> 1.6)
- rest-client (~> 2.0)
amoeba (3.0.0)
activerecord (>= 3.2.6)
- appsignal (3.3.10)
+ appsignal (3.4.8)
rack
ast (2.4.2)
authy (3.0.1)
@@ -95,7 +97,7 @@ GEM
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
- bcrypt (3.1.18)
+ bcrypt (3.1.19)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootscale (0.7.0)
@@ -105,13 +107,14 @@ GEM
browser (2.4.0)
builder (3.2.4)
byebug (11.1.3)
- capybara (3.33.0)
+ capybara (3.39.2)
addressable
+ matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
- regexp_parser (~> 1.5)
+ regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
carrierwave (1.3.3)
activemodel (>= 4.0.0)
@@ -136,9 +139,9 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
- colorize (0.8.1)
+ colorize (1.1.0)
concurrent-ruby (1.2.2)
- connection_pool (2.4.0)
+ connection_pool (2.4.1)
countries (2.1.4)
i18n_data (~> 0.8.0)
money (~> 6.9)
@@ -161,8 +164,6 @@ GEM
database_cleaner-core (2.0.1)
date (3.3.3)
debug_inspector (1.1.0)
- decent_decoration (0.1.0)
- decent_exposure (~> 3.0)
decent_exposure (3.0.4)
activesupport (>= 4.0)
descendants_tracker (0.0.4)
@@ -194,15 +195,14 @@ GEM
activesupport (>= 5.0)
request_store (>= 1.0)
ruby2_keywords
- dry-inflector (1.0.0)
email_validator (2.2.4)
activemodel
- enumerize (2.6.1)
+ enumerize (2.7.0)
activesupport (>= 3.2)
erubi (1.12.0)
et-orbi (1.2.7)
tzinfo
- excon (0.99.0)
+ excon (0.100.0)
execjs (2.8.1)
factory_bot (6.2.1)
activesupport (>= 5.0.0)
@@ -237,165 +237,22 @@ GEM
faraday_middleware (1.2.0)
faraday (~> 1.0)
ffi (1.15.5)
- fission (0.5.0)
- CFPropertyList (~> 2.2)
- fog (1.42.1)
- fog-aliyun (>= 0.1.0)
- fog-atmos
- fog-aws (>= 0.6.0)
- fog-brightbox (~> 0.4)
- fog-cloudatcost (~> 0.1.0)
- fog-core (~> 1.45)
- fog-digitalocean (>= 0.3.0)
- fog-dnsimple (~> 1.0)
- fog-dynect (~> 0.0.2)
- fog-ecloud (~> 0.1)
- fog-google (<= 0.1.0)
- fog-internet-archive
- fog-joyent
- fog-json
- fog-local
- fog-openstack
- fog-ovirt
- fog-powerdns (>= 0.1.1)
- fog-profitbricks
- fog-rackspace
- fog-radosgw (>= 0.0.2)
- fog-riakcs
- fog-sakuracloud (>= 0.0.4)
- fog-serverlove
- fog-softlayer
- fog-storm_on_demand
- fog-terremark
- fog-vmfusion
- fog-voxel
- fog-vsphere (>= 0.4.0)
- fog-xenserver
- fog-xml (~> 0.1.1)
- ipaddress (~> 0.5)
- json (~> 2.0)
- fog-aliyun (0.4.0)
- addressable (~> 2.8.0)
- aliyun-sdk (~> 0.8.0)
- fog-core
- fog-json
- ipaddress (~> 0.8)
- xml-simple (~> 1.1)
- fog-atmos (0.1.0)
- fog-core
- fog-xml
- fog-aws (2.0.1)
- fog-core (~> 1.38)
- fog-json (~> 1.0)
+ fog-aws (3.19.0)
+ fog-core (~> 2.1)
+ fog-json (~> 1.1)
fog-xml (~> 0.1)
- ipaddress (~> 0.8)
- fog-brightbox (0.16.1)
- dry-inflector
- fog-core
- fog-json
- mime-types
- fog-cloudatcost (0.1.2)
- fog-core (~> 1.36)
- fog-json (~> 1.0)
- fog-xml (~> 0.1)
- ipaddress (~> 0.8)
- fog-core (1.45.0)
+ fog-core (2.3.0)
builder
- excon (~> 0.58)
- formatador (~> 0.2)
- fog-digitalocean (0.4.0)
- fog-core
- fog-json
- fog-xml
- ipaddress (>= 0.5)
- fog-dnsimple (1.0.0)
- fog-core (~> 1.38)
- fog-json (~> 1.0)
- fog-dynect (0.0.3)
- fog-core
- fog-json
- fog-xml
- fog-ecloud (0.3.0)
- fog-core
- fog-xml
- fog-google (0.1.0)
- fog-core
- fog-json
- fog-xml
- fog-internet-archive (0.0.2)
- fog-core
- fog-json
- fog-xml
- fog-joyent (0.0.1)
- fog-core (~> 1.42)
- fog-json (>= 1.0)
+ excon (~> 0.71)
+ formatador (>= 0.2, < 2.0)
+ mime-types
fog-json (1.2.0)
fog-core
multi_json (~> 1.10)
- fog-local (0.8.0)
- fog-core (>= 1.27, < 3.0)
- fog-openstack (0.3.10)
- fog-core (>= 1.45, <= 2.1.0)
- fog-json (>= 1.0)
- ipaddress (>= 0.8)
- fog-ovirt (2.0.2)
- activesupport
- fog-core
- fog-json
- fog-xml
- ovirt-engine-sdk (>= 4.3.1)
- fog-powerdns (0.2.0)
- fog-core
- fog-json
- fog-xml
- fog-profitbricks (4.1.1)
- fog-core (~> 1.42)
- fog-json (~> 1.0)
- fog-rackspace (0.1.6)
- fog-core (>= 1.35)
- fog-json (>= 1.0)
- fog-xml (>= 0.1)
- ipaddress (>= 0.8)
- fog-radosgw (0.0.5)
- fog-core (>= 1.21.0)
- fog-json
- fog-xml (>= 0.0.1)
- fog-riakcs (0.1.0)
- fog-core
- fog-json
- fog-xml
- fog-sakuracloud (1.7.5)
- fog-core
- fog-json
- fog-serverlove (0.1.2)
- fog-core
- fog-json
- fog-softlayer (1.1.4)
- fog-core
- fog-json
- fog-storm_on_demand (0.1.1)
- fog-core
- fog-json
- fog-terremark (0.1.0)
- fog-core
- fog-xml
- fog-vmfusion (0.1.0)
- fission
- fog-core
- fog-voxel (0.1.0)
- fog-core
- fog-xml
- fog-vsphere (3.6.0)
- fog-core
- rbvmomi2 (~> 3.0)
- fog-xenserver (1.0.0)
- fog-core
- fog-xml
- xmlrpc
fog-xml (0.1.4)
fog-core
nokogiri (>= 1.5.11, < 2.0.0)
- formatador (0.3.0)
+ formatador (1.1.0)
fugit (1.8.1)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
@@ -406,24 +263,23 @@ GEM
i18n (>= 0.7)
multi_json
request_store (>= 1.0)
- govuk-components (4.0.0)
+ govuk-components (4.1.0)
html-attributes-utils (~> 1.0.0, >= 1.0.0)
pagy (~> 6.0)
- view_component (~> 3.0.0)
+ view_component (~> 3.3.0)
hashdiff (1.0.1)
hashery (2.1.2)
hashie (3.6.0)
- html-attributes-utils (1.0.0)
+ html-attributes-utils (1.0.1)
activesupport (>= 6.1.4.4)
http-accept (1.7.0)
http-cookie (1.0.5)
domain_name (~> 0.5)
httpclient (2.8.3)
- i18n (1.13.0)
+ i18n (1.14.1)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
ice_nine (0.11.2)
- ipaddress (0.8.3)
jbuilder (2.10.2)
activesupport (>= 5.0.0)
jquery-rails (4.4.0)
@@ -434,8 +290,8 @@ GEM
railties (>= 3.2.16)
js_cookie_rails (2.1.4)
railties (>= 3.1)
- json (2.3.0)
- jwt (2.7.0)
+ json (2.6.3)
+ jwt (2.7.1)
kaminari (1.2.2)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.2)
@@ -460,9 +316,9 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.20.0)
+ loofah (2.21.3)
crass (~> 1.0.2)
- nokogiri (>= 1.5.9)
+ nokogiri (>= 1.12.0)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
@@ -476,21 +332,22 @@ GEM
notifications-ruby-client (~> 5.1)
rack (>= 2.1.4.1)
marcel (1.0.2)
+ matrix (0.4.2)
method_source (1.0.0)
middleware (0.1.0)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2023.0218.1)
mini_mime (1.1.2)
- mini_portile2 (2.8.2)
- minitest (5.18.0)
+ mini_portile2 (2.8.4)
+ minitest (5.18.1)
money (6.16.0)
i18n (>= 0.6.4, <= 2)
multi_json (1.15.0)
multipart-post (2.3.0)
mustermann (3.0.0)
ruby2_keywords (~> 0.0.1)
- net-imap (0.3.4)
+ net-imap (0.3.6)
date
net-protocol
net-pop (0.1.2)
@@ -504,26 +361,28 @@ GEM
activerecord (>= 4.0.0)
activesupport (>= 4.0.0)
nio4r (2.5.9)
- nokogiri (1.14.3)
- mini_portile2 (~> 2.8.0)
+ nokogiri (1.15.3)
+ mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- nokogiri (1.14.3-x86_64-darwin)
+ nokogiri (1.15.3-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.14.3-x86_64-linux)
+ nokogiri (1.15.3-x86_64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.15.3-x86_64-linux)
racc (~> 1.4)
notifications-ruby-client (5.4.0)
jwt (>= 1.5, < 3)
- optimist (3.0.1)
orm_adapter (0.5.0)
- ovirt-engine-sdk (4.4.1)
- json (>= 1, < 3)
pagy (6.0.4)
- paper_trail (10.3.1)
- activerecord (>= 4.2)
+ paper_trail (12.2.0)
+ activerecord (>= 5.2)
request_store (~> 1.1)
+ paper_trail-association_tracking (2.2.1)
+ paper_trail (>= 12.0)
parallel (1.23.0)
- parser (3.2.2.1)
+ parser (3.2.2.3)
ast (~> 2.4.1)
+ racc
pdf-core (0.9.0)
pdf-inspector (1.3.0)
pdf-reader (>= 1.0, < 3.0.a)
@@ -557,8 +416,8 @@ GEM
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
- public_suffix (5.0.1)
- puma (4.3.12)
+ public_suffix (5.0.3)
+ puma (6.3.1)
nio4r (~> 2.0)
pundit (0.3.0)
activesupport (>= 3.0.0)
@@ -568,7 +427,7 @@ GEM
pusher-signature (~> 0.1.8)
pusher-signature (0.1.8)
raabro (1.4.0)
- racc (1.6.2)
+ racc (1.7.1)
rack (2.2.7)
rack-cors (1.1.1)
rack (>= 2.0.0)
@@ -581,27 +440,27 @@ GEM
rack-ssl-enforcer (0.2.9)
rack-test (2.1.0)
rack (>= 1.3)
- rails (6.1.7.3)
- actioncable (= 6.1.7.3)
- actionmailbox (= 6.1.7.3)
- actionmailer (= 6.1.7.3)
- actionpack (= 6.1.7.3)
- actiontext (= 6.1.7.3)
- actionview (= 6.1.7.3)
- activejob (= 6.1.7.3)
- activemodel (= 6.1.7.3)
- activerecord (= 6.1.7.3)
- activestorage (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ rails (7.0.5.1)
+ actioncable (= 7.0.5.1)
+ actionmailbox (= 7.0.5.1)
+ actionmailer (= 7.0.5.1)
+ actionpack (= 7.0.5.1)
+ actiontext (= 7.0.5.1)
+ actionview (= 7.0.5.1)
+ activejob (= 7.0.5.1)
+ activemodel (= 7.0.5.1)
+ activerecord (= 7.0.5.1)
+ activestorage (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
bundler (>= 1.15.0)
- railties (= 6.1.7.3)
- sprockets-rails (>= 2.0.0)
+ railties (= 7.0.5.1)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
- rails-dom-testing (2.0.3)
- activesupport (>= 4.2.0)
+ rails-dom-testing (2.1.1)
+ activesupport (>= 5.0.0)
+ minitest
nokogiri (>= 1.6)
rails-healthcheck (1.4.0)
actionpack
@@ -617,23 +476,19 @@ GEM
railties (> 3.1)
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
- railties (6.1.7.3)
- actionpack (= 6.1.7.3)
- activesupport (= 6.1.7.3)
+ railties (7.0.5.1)
+ actionpack (= 7.0.5.1)
+ activesupport (= 7.0.5.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
+ zeitwerk (~> 2.5)
rainbow (3.1.1)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rb-readline (0.5.5)
- rbvmomi2 (3.6.0)
- builder (~> 3.2)
- json (~> 2.3)
- nokogiri (~> 1.12, >= 1.12.5)
- optimist (~> 3.0)
redis (5.0.6)
redis-client (>= 0.9.0)
redis-actionpack (5.3.0)
@@ -654,7 +509,7 @@ GEM
redis-store (>= 1.2, < 2)
redis-store (1.9.2)
redis (>= 4, < 6)
- regexp_parser (1.8.2)
+ regexp_parser (2.8.1)
request_store (1.5.1)
rack (>= 1.4)
responders (3.1.0)
@@ -665,7 +520,7 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
- rexml (3.2.5)
+ rexml (3.2.6)
rspec (3.12.0)
rspec-core (~> 3.12.0)
rspec-expectations (~> 3.12.0)
@@ -677,10 +532,10 @@ GEM
rspec-support (~> 3.12.0)
rspec-github (2.4.0)
rspec-core (~> 3.0)
- rspec-mocks (3.12.5)
+ rspec-mocks (3.12.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
- rspec-rails (6.0.2)
+ rspec-rails (6.0.3)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
@@ -691,7 +546,7 @@ GEM
rspec-sidekiq (3.1.0)
rspec-core (~> 3.0, >= 3.0.0)
sidekiq (>= 2.4.0)
- rspec-support (3.12.0)
+ rspec-support (3.12.1)
rspec_junit_formatter (0.2.3)
builder (< 4)
rspec-core (>= 2, < 4, != 2.12.0)
@@ -704,7 +559,7 @@ GEM
rubocop-ast (>= 0.6.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
- rubocop-ast (1.28.1)
+ rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
ruby-rc4 (0.1.5)
@@ -713,18 +568,18 @@ GEM
nokogiri (>= 1.10.8)
rubyzip (>= 1.3.0)
rubyzip (2.3.2)
- sanitize (6.0.1)
+ sanitize (6.0.2)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
sassc (2.4.0)
ffi (~> 1.9)
- sassc-rails (2.0.0)
+ sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
- selenium-webdriver (4.9.0)
+ selenium-webdriver (4.11.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
@@ -738,7 +593,7 @@ GEM
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.5.0)
- sidekiq-cron (1.10.0)
+ sidekiq-cron (1.10.1)
fugit (~> 1.8)
globalid (>= 1.0.1)
sidekiq (>= 6)
@@ -756,7 +611,7 @@ GEM
rack (~> 2.2, >= 2.2.4)
rack-protection (= 3.0.5)
tilt (~> 2.0)
- sixarm_ruby_unaccent (1.2.0)
+ sixarm_ruby_unaccent (1.2.2)
slim (4.1.0)
temple (>= 0.7.6, < 0.9)
tilt (>= 2.0.6, < 2.1)
@@ -776,11 +631,11 @@ GEM
ssrf_filter (1.0.8)
statesman (3.5.0)
temple (0.8.2)
- thor (1.2.1)
+ thor (1.2.2)
thread_safe (0.3.6)
tilt (2.0.11)
timecop (0.9.6)
- timeout (0.3.2)
+ timeout (0.4.0)
ttfunk (1.7.0)
turnip (4.2.0)
cucumber-gherkin (~> 14.0)
@@ -794,7 +649,7 @@ GEM
unf_ext (0.0.8.2)
unicode-display_width (1.8.0)
unicode_utils (1.4.0)
- view_component (3.0.0)
+ view_component (3.3.0)
activesupport (>= 5.2.0, < 8.0)
concurrent-ruby (~> 1.0)
method_source (~> 1.0)
@@ -812,34 +667,32 @@ GEM
descendants_tracker (~> 0.0, >= 0.0.3)
warden (1.2.9)
rack (>= 2.0.9)
- webmock (3.5.0)
- addressable (>= 2.3.6)
+ webmock (3.18.1)
+ addressable (>= 2.8.0)
crack (>= 0.3.2)
- hashdiff
- webpacker (6.0.0.beta.7)
+ hashdiff (>= 0.4.0, < 2.0.0)
+ webpacker (6.0.0.rc.6)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
- webrick (1.8.1)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
wicked (1.4.0)
railties (>= 3.0.7)
- xml-simple (1.1.9)
- rexml
- xmlrpc (0.3.2)
- webrick
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.8)
zxcvbn (0.1.9)
PLATFORMS
+ arm64-darwin-21
+ arm64-darwin-22
ruby
x86_64-darwin-21
+ x86_64-darwin-22
x86_64-linux
DEPENDENCIES
@@ -850,7 +703,7 @@ DEPENDENCIES
bootscale
bootstrap-sass (~> 3.4)
browser (= 2.4.0)
- capybara (= 3.33)
+ capybara (~> 3.39.0)
carrierwave (~> 1.3)
ckeditor
codeclimate_circle_ci_coverage
@@ -858,7 +711,6 @@ DEPENDENCIES
country_select (~> 3.1)
curb (= 0.9.10)
database_cleaner-active_record
- decent_decoration
decent_exposure
devise (~> 4.7)
devise-authy (>= 1.10.0)
@@ -869,7 +721,6 @@ DEPENDENCIES
email_validator
enumerize
factory_bot_rails
- fog (= 1.42.1)
fog-aws
gon (>= 6.4.0)
govuk-components
@@ -878,16 +729,18 @@ DEPENDENCIES
jquery-rails (= 4.4.0)
jquery-ui-rails (= 6.0.1)
js_cookie_rails (= 2.1.4)
- json (= 2.3.0)
+ json
kaminari
launchy
letter_opener
listen
lograge
mail-notify (~> 1.0)
+ matrix
nilify_blanks
nokogiri
- paper_trail (~> 10.3)
+ paper_trail (~> 12.2.0)
+ paper_trail-association_tracking
pdf-inspector
pg
pg_search (~> 2.3.3)
@@ -895,14 +748,14 @@ DEPENDENCIES
prawn
prawn-table
pry-byebug
- puma (~> 4.3.12)
+ puma (~> 6.3.1)
pundit (~> 0.3)
pusher (= 0.15.2)
rack-cors (~> 1.0)
rack-mini-profiler (>= 0.10.1)
rack-protection (= 3.0.5)
rack-ssl-enforcer
- rails (= 6.1.7.3)
+ rails (= 7.0.5.1)
rails-controller-testing
rails-healthcheck
rails-html-sanitizer (~> 1.4.4)
@@ -920,7 +773,7 @@ DEPENDENCIES
rubocop (~> 0.52)
rubyXL (~> 3.4)
sanitize
- sassc-rails (~> 2.0.0)
+ sassc-rails (~> 2.1.2)
selenium-webdriver
shog
shoulda-matchers
@@ -938,13 +791,13 @@ DEPENDENCIES
vigilion (~> 1.0.4)
vigilion-rails (~> 2.2.0)
virtus
- webmock (= 3.5.0)
- webpacker (= 6.0.0.beta.7)
+ webmock (= 3.18.1)
+ webpacker (= 6.0.0.rc.6)
websocket-extensions (~> 0.1.5)
wicked (~> 1.1)
RUBY VERSION
- ruby 2.7.7p221
+ ruby 3.2.2p53
BUNDLED WITH
- 2.4.8
+ 2.4.13
diff --git a/README.md b/README.md
index 097ee3c9a..79578d481 100644
--- a/README.md
+++ b/README.md
@@ -6,9 +6,9 @@
## Pre-requisites
-- Ruby 2.7.7
+- Ruby 3.2.2
- `gem install bundler -v 2.4.8`
-- Rails 6.1
+- Rails 7.0.5
- Postgresql 9.5+
- Redis 2.8
- Cloudfountry Client
diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico
new file mode 100644
index 000000000..31485ebf0
Binary files /dev/null and b/app/assets/images/favicon.ico differ
diff --git a/app/assets/images/icon_load_black.svg b/app/assets/images/icon_load_black.svg
new file mode 100644
index 000000000..b8d1ed74b
--- /dev/null
+++ b/app/assets/images/icon_load_black.svg
@@ -0,0 +1,24 @@
+
+
diff --git a/app/assets/images/icon_loading_black.svg b/app/assets/images/icon_loading_black.svg
new file mode 100644
index 000000000..aa07c1174
--- /dev/null
+++ b/app/assets/images/icon_loading_black.svg
@@ -0,0 +1 @@
+
diff --git a/app/assets/images/icon_update_black.svg b/app/assets/images/icon_update_black.svg
new file mode 100644
index 000000000..73824e58c
--- /dev/null
+++ b/app/assets/images/icon_update_black.svg
@@ -0,0 +1,18 @@
+
+
diff --git a/app/assets/javascripts/admin/applications-filter.js.coffee b/app/assets/javascripts/admin/applications-filter.js.coffee
index df455e626..5547609c7 100644
--- a/app/assets/javascripts/admin/applications-filter.js.coffee
+++ b/app/assets/javascripts/admin/applications-filter.js.coffee
@@ -1,6 +1,49 @@
ready = ->
filterApplicationsDropdowns()
+ # processing arrow keys in admin dropdowns
+ $(document).on "keydown", (e) ->
+ return unless $(".dropdown.open").length > 0
+
+ if e.keyCode == 40 || e.keyCode == 38
+ e.preventDefault()
+ e.stopPropagation()
+
+ $(document).on "keyup", (e) ->
+ return unless $(".dropdown.open").length > 0
+
+ select = $(".dropdown.open").first()
+
+ if e.keyCode == 40
+ e.preventDefault()
+ e.stopPropagation()
+
+ if $(".dropdown-menu li.checkbox input:focus", select).length is 0
+ $(".dropdown-menu li.checkbox input", select)[0].focus()
+ else
+ element = $(".dropdown-menu li.checkbox input:focus", select).closest("li")
+ next_element = element.next()
+
+ if next_element.hasClass("divider")
+ next_element = next_element.next()
+
+ $("input", next_element).focus()
+
+ if e.keyCode == 38
+ e.preventDefault()
+ e.stopPropagation()
+
+ if $(".dropdown-menu li.checkbox input:focus", select).length is 0
+ $(".dropdown-menu li.checkbox input", select).last().focus()
+ else
+ element = $(".dropdown-menu li.checkbox input:focus", select).closest("li")
+ prev_element = element.prev()
+
+ if prev_element.hasClass("divider")
+ prev_element = prev_element.prev()
+
+ $("input", prev_element).focus()
+
filterApplicationsDropdowns = () ->
# Change the checked value on dropbox and the filtered text
$(".applications-filter .dropdown-menu").each () ->
@@ -29,6 +72,7 @@ filterApplicationsDropdowns = () ->
$(this).find("label[data-value='select_all'] input").attr('checked', 'checked')
$(this).closest(".dropdown").find(".text-filter").text("All")
+
$(".applications-filter .dropdown-toggle").on "click", (e) ->
e.preventDefault()
e.stopPropagation()
diff --git a/app/assets/javascripts/admin/comments.js.coffee b/app/assets/javascripts/admin/comments.js.coffee
index cab48ec08..1bdc9a03b 100644
--- a/app/assets/javascripts/admin/comments.js.coffee
+++ b/app/assets/javascripts/admin/comments.js.coffee
@@ -56,8 +56,9 @@ ready = ->
else
signatureWrapper.html("")
- $(@).parents('.comment').remove()
+ window.fire(@, 'ajax:x:success', null)
+ $(@).parents('.comment').remove()
toggleFlagged()
deleteCommentAlert()
diff --git a/app/assets/javascripts/admin/dashboard.js.coffee b/app/assets/javascripts/admin/dashboard.js.coffee
index c2873378c..c23bcd031 100644
--- a/app/assets/javascripts/admin/dashboard.js.coffee
+++ b/app/assets/javascripts/admin/dashboard.js.coffee
@@ -18,3 +18,8 @@ jQuery ->
$("tbody", wrapper).load href, ->
link.removeClass("hidden")
$(".updating-data", wrapper).addClass("hidden")
+ if wrapper.find(".sr-only").text().length == 0
+ wrapper.find(".sr-only").text("Data loaded")
+ else
+ wrapper.find(".sr-only").empty()
+ wrapper.find(".sr-only").text("Data updated")
diff --git a/app/assets/javascripts/admin/financial_data.js.coffee b/app/assets/javascripts/admin/financial_data.js.coffee
index 96df61541..ee147ef99 100644
--- a/app/assets/javascripts/admin/financial_data.js.coffee
+++ b/app/assets/javascripts/admin/financial_data.js.coffee
@@ -6,13 +6,15 @@ jQuery ->
overallBenchmarksTable = ($ "#overall-financial-benchmarks")
financialTable = ($ "#financial-table")
- $("input", form).on "change keyup keydown paste", ->
- timer ||= setTimeout(saveFinancials, 500)
-
($ "button", form).on "click", (event) ->
do event.preventDefault
$(this).closest(".form-group").removeClass("form-edit")
+
+ ($ ".form-save-button", form).on "click", (event) ->
+ do event.preventDefault
+ saveFinancials()
+
updateExportsGrowth = (exports) ->
exportsGrowth = ($ 'tr.exports-growth td.value', benchmarksTable)
values = exports.map (i, td) ->
diff --git a/app/assets/javascripts/admin/form_answers.js.coffee b/app/assets/javascripts/admin/form_answers.js.coffee
index d36bc6d88..3dcd60f04 100644
--- a/app/assets/javascripts/admin/form_answers.js.coffee
+++ b/app/assets/javascripts/admin/form_answers.js.coffee
@@ -54,21 +54,6 @@ ready = ->
else
$('#commercial-figures-attachment-form').addClass('visuallyhidden')
- $("#new_review_audit_certificate").on "ajax:success", (e, data, status, xhr) ->
- $(this).find(".form-group").removeClass("form-edit")
- $(this).find(".form-edit-link").remove()
- $(".save-review-audit").remove()
- area = $(".audit-cert-description textarea")
- unless area.val()
- $(this).find(".form-value").html($("
No change necessary
"))
- else
- div = "#{area.val()}
"
- $(this).find(".form-value").html(div)
-
- $("#new_review_audit_certificate").on "click", ".save-review-audit", (e) ->
- e.preventDefault()
- $("#new_review_audit_certificate").submit()
-
$(".edit-review-audit").on "click", (e) ->
$(".save-review-audit").show()
@@ -154,15 +139,17 @@ ready = ->
result = $($.parseHTML(result))
$("#commercial-figures-buffer").append(result.text())
+ form = document.querySelector('#commercial-figures-attachment-form form')
+
if $("#commercial-figures-file-valid", $("#commercial-figures-buffer")).length
$("#commercial-figures-section").html(result.text())
moveAttachDocumentButton()
else
- form = $("#commercial-figures-attachment-form form")
- section = form.closest("#commercial-figures-section")
+ section = $(form).closest("#commercial-figures-section")
section.find(".document-list .p-empty").addClass("visuallyhidden")
section.find(".document-list ul").append(result.text())
+ window.fire(form, 'ajax:x:success', null)
toggleCommercialFiguresButtonVisibility()
$("#commercial-figures-buffer").empty()
@@ -179,6 +166,11 @@ ready = ->
$.ajax
url: form.attr('action'),
type: 'DELETE'
+ success: (_) ->
+ window.fire(form[0], 'ajax:x:success', null)
+ error: (_) ->
+ window.fire(form[0], 'ajax:x:error', null)
+
form.parents('.commercial-figures-file').remove()
if $('.commercial-figures-file').length == 0
section.find(".document-list .p-empty").removeClass("visuallyhidden")
@@ -200,16 +192,18 @@ ready = ->
result = $($.parseHTML(result))
$("#vat-returns-buffer").append(result.text())
+ form = document.querySelector('#vat-returns-attachment-form form')
+
if $("#vat-returns-file-valid", $("#vat-returns-buffer")).length
$("#application-attachment-form").html(result.text())
moveAttachDocumentButton()
initializeFileUpload()
else
- form = $("#vat-returns-attachment-form form")
- section = form.closest("#vat-returns-section")
+ section = $(form).closest("#vat-returns-section")
section.find(".document-list .p-empty").addClass("visuallyhidden")
section.find(".document-list ul").append(result.text())
+ window.fire(form, 'ajax:x:success', null)
$("#vat-returns-buffer").empty()
$("#vat-returns-attachment-form form").on "fileuploadsubmit", (e, data) ->
@@ -225,6 +219,11 @@ ready = ->
$.ajax
url: form.attr('action'),
type: 'DELETE'
+ success: (_) ->
+ window.fire(form[0], 'ajax:x:success', null)
+ error: (_) ->
+ window.fire(form[0], 'ajax:x:error', null)
+
form.parents('.vat-returns-file').remove()
if $('.vat-returns-file').length == 0
section.find(".document-list .p-empty").removeClass("visuallyhidden")
@@ -260,19 +259,21 @@ ready = ->
result = $($.parseHTML(result))
$("#attachment-buffer").append(result.text())
+ form = document.querySelector('#new_form_answer_attachment')
+
if $("#form-answer-attachment-valid", $("#attachment-buffer")).length
$("#application-attachment-form").html(result.text())
moveAttachDocumentButton()
initializeFileUpload()
else
- form = $("#new_form_answer_attachment")
- sidebarSection = form.closest(".sidebar-section")
+ sidebarSection = $(form).closest(".sidebar-section")
sidebarSection.find(".document-list .p-empty").addClass("visuallyhidden")
sidebarSection.find(".document-list ul").append(result.text())
sidebarSection.removeClass("show-attachment-form")
$("#form_answer_attachment_title").val(null)
$("#form_answer_attachment_restricted_to_admin").prop("checked", false)
+ window.fire(form, 'ajax:x:success', null)
$("#attachment-buffer").empty()
if $("html").hasClass("lte-ie7")
@@ -295,16 +296,18 @@ ready = ->
result = $($.parseHTML(result))
$("#audit-certificate-buffer").append(result.text())
+ form = document.querySelector('#new_audit_certificate')
+
if $("#form-audit_certificate-valid", $("#audit-certificate-buffer")).length
$("#audit-certificate-form").html(result.text())
moveAttachDocumentButton()
initializeFileUpload()
else
- form = $("#new_audit_certificate")
- sidebarSection = form.closest(".sidebar-section")
+ sidebarSection = $(form).closest(".sidebar-section")
sidebarSection.find(".document-list").html(result.text())
sidebarSection.removeClass("show-attachment-form")
+ window.fire(form, 'ajax:x:success', null)
$("#audit-certificate-buffer").empty()
moveAttachDocumentButton()
@@ -326,6 +329,7 @@ ready = ->
$.ajax
url: form.attr('action'),
type: 'DELETE'
+ window.fire(form[0], 'ajax:x:success', null)
form.parents('.form_answer_attachment').remove()
if $('.form_answer_attachment').length == 0
sidebarSection.find(".document-list .p-empty").removeClass("visuallyhidden")
@@ -336,29 +340,7 @@ ready = ->
if (element)
element.classList.add('form-edit')
- $('.submit-assessment').on 'ajax:error', (e, data, status, xhr) ->
- panel = this.closest('.panel-body')
- errors = data.responseJSON
-
- removeExistingErrorMessages(panel)
-
- Object.entries(errors).forEach ([key, values]) ->
- field = panel.querySelector("[name*='[#{key}]']")
- if field and shouldValidateField(field)
- showErrorForInvalidField(field, values)
-
- $(".submit-assessment").on "ajax:success", (e, data, status, xhr) ->
- panel = this.closest('.panel-body')
- message = "Assessment submitted"
- if panel.closest(".panel-collapse").classList.contains('section-case-summary')
- message = "Case summary submitted"
-
- removeExistingErrorMessages(panel)
- panel.insertAdjacentHTML('afterbegin', buildBannerHtml(message, 'success'))
-
- $(this).find('input:submit').remove()
-
- $(document).on "click", ".form-save-link", (e) ->
+ $(document).on "click", ".form-save-link:not(.js-form-save-link)", (e) ->
link = $(this)
e.preventDefault()
formGroup = link.closest(".form-group")
@@ -393,11 +375,11 @@ ready = ->
input.val(updatedSection)
form.submit()
else
- if area.first().val().length
- formGroup.find(".form-value p:first").html(area.first().val().replace(/\n/g, '
'))
- if area.last().val().length
- formGroup.find(".form-value p:last").html(area.last().val().replace(/\n/g, '
'))
- form.submit()
+ if area.first().val().length
+ formGroup.find(".form-value p:first").html(area.first().val().replace(/\n/g, '
'))
+ if area.last().val().length
+ formGroup.find(".form-value p:last").html(area.last().val().replace(/\n/g, '
'))
+ form.submit()
$("#new_review_audit_certificate input[type='radio']").on "change", ->
area = $(".audit-cert-description")
@@ -461,7 +443,7 @@ buildBannerHtml = (message, type, identifier = null) ->
"
#{message}
-
"
@@ -544,6 +526,11 @@ handleWinnersForm = ->
$(document).on "ajax:success", attendeeFormHolder, (e, data, status, xhr) ->
$(this).closest(attendeeFormHolder).replaceWith(data)
+ setTimeout (->
+ replaced = document.querySelector("##{e.target.id}")
+ window.fire(replaced, 'ajax:x:success', null)
+ ), 50
+
$(document).on "click", ".remove-palace-attendee", (e) ->
e.preventDefault()
$(this).closest("form").submit()
@@ -552,6 +539,12 @@ handleWinnersForm = ->
$(document).on "ajax:success", removeAttendeeForm, (e, data, status, xhr) ->
$(this).closest(attendeeFormHolder).remove()
$(".attendees-forms").closest(".form-group").find(".empty-message").removeClass("visuallyhidden")
+
+ setTimeout (->
+ removed = document.querySelector("##{e.target.id}")
+ window.fire(removed, 'ajax:x:success', null)
+ ), 50
+
$(document).on "click", ".add-another-attendee", (e) ->
e.preventDefault()
that = $(this)
@@ -636,6 +629,8 @@ handleReviewAuditCertificate = ->
else
div = "#{area.val()}
"
$(this).find(".form-value").html(div)
+ window.fire(e.target, 'ajax:x:success', null)
+
$("#new_review_audit_certificate").on "click", ".save-review-audit", (e) ->
e.preventDefault()
$("#new_review_audit_certificate").submit()
diff --git a/app/assets/javascripts/admin/timeout_popup.js.coffee b/app/assets/javascripts/admin/timeout_popup.js.coffee
new file mode 100644
index 000000000..9e63aba6d
--- /dev/null
+++ b/app/assets/javascripts/admin/timeout_popup.js.coffee
@@ -0,0 +1,36 @@
+$(window).load ->
+ prefix = '/' + window.namespace
+ hasDisplayedWarning = false
+
+ $(document).on 'click', '.extend-session', (e) ->
+ e.preventDefault()
+ $('.js-session-timeout-warning-popup').modal 'hide'
+ $.post prefix + '/session_checks/extend.json?__t=' + window.lastRequestAt, ->
+ $('.js-session-timeout-warning-popup').modal 'hide'
+ hasDisplayedWarning = false
+
+ if window.timeoutTime and window.timeoutTime > 0
+ checkInterval = setInterval((->
+ $.ajax
+ url: prefix + '/session_checks.json'
+ type: 'GET'
+ success: (data) ->
+ remaining = Math.round(window.timeoutTime / 60000 - (data.elapsed))
+ if remaining == 1
+ $('.js-session-timeout-warning-popup .time-target').html ' ' + remaining + ' minute'
+ else
+ $('.js-session-timeout-warning-popup .time-target').html ' ' + remaining + ' minutes'
+ if remaining < 5 and !hasDisplayedWarning
+ hasDisplayedWarning = true
+ $('.js-session-timeout-warning-popup').modal
+ backdrop: 'static'
+ keyboard: true
+ complete: (response) ->
+ if response.status == 401
+ clearInterval checkInterval
+ $('.js-session-timeout-warning-popup').modal 'hide'
+ $('.js-session-timeout-popup').modal
+ backdrop: 'static'
+ keyboard: false
+ dataType: 'json'
+ ), 10 * 1000)
diff --git a/app/assets/javascripts/application.js.coffee b/app/assets/javascripts/application.js.coffee
index 85341422f..f65a9efb3 100644
--- a/app/assets/javascripts/application.js.coffee
+++ b/app/assets/javascripts/application.js.coffee
@@ -262,6 +262,19 @@ jQuery ->
$(".js-conditional-drop-answer input").change () ->
dropConditionalQuestion($(this))
+ togglePressSummaryTextarea= () ->
+ if $('[name="press_summary[correct]"]:checked').val() == "true"
+ $("#press-summary-comment-textarea-container").removeClass("if-js-hide")
+ else
+ $("#press-summary-comment-textarea-container").addClass("if-js-hide")
+
+ $('[name="press_summary[correct]"]').on 'change', ->
+ if $(this).val() is 'true'
+ $("#press-summary-comment-textarea-container").removeClass("if-js-hide")
+ else
+ $("#press-summary-comment-textarea-container").addClass("if-js-hide")
+ togglePressSummaryTextarea()
+
# Get the latest financial year date from input
updateYearEndInput = () ->
fy_latest_changed_input = $(".js-financial-year-changed-dates .fy-latest .govuk-date-input")
diff --git a/app/assets/javascripts/frontend/form-validation.js.coffee b/app/assets/javascripts/frontend/form-validation.js.coffee
index 6e13747f0..0ef3b4aa2 100644
--- a/app/assets/javascripts/frontend/form-validation.js.coffee
+++ b/app/assets/javascripts/frontend/form-validation.js.coffee
@@ -159,11 +159,9 @@ window.FormValidation =
if subquestions.length
for subquestion in subquestions
if not @validateSingleQuestion($(subquestion))
- @logThis(question, "validateRequiredQuestion", "This field is required")
@addSubfieldError(question, subquestion)
else
if not @validateSingleQuestion(question)
- @logThis(question, "validateRequiredQuestion", "This field is required")
@addQuestionError(question)
addSubfieldError: (question, subquestion) ->
@@ -174,36 +172,58 @@ window.FormValidation =
incompleteMessage = "Question #{questionRef} is incomplete. It is required and must be filled in."
if question.hasClass('date-DDMMYYYY')
- @addErrorMessage($(subquestion), "#{incompleteMessage} Use the format DD/MM/YYYY.")
+ errorMessage = "#{incompleteMessage} Use the format DD/MM/YYYY."
+ @logThis(question, "validateRequiredSubQuestion", errorMessage)
+ @addErrorMessage($(subquestion), errorMessage)
else if question.hasClass('date-MMYYYY')
- @addErrorMessage($(subquestion), "#{incompleteMessage} Use the format MM/YYYY.")
+ errorMessage = "#{incompleteMessage} Use the format MM/YYYY."
+ @logThis(question, "validateRequiredSubQuestion", errorMessage)
+ @addErrorMessage($(subquestion), errorMessage)
else if question.hasClass('date-YYYY')
- @addErrorMessage($(subquestion), "#{incompleteMessage} Use the format YYYY.")
+ errorMessage = "#{incompleteMessage} Use the format YYYY."
+ @logThis(question, "validateRequiredSubQuestion", errorMessage)
+ @addErrorMessage($(subquestion), errorMessage)
else if input.hasClass("autocomplete__input")
- @addErrorMessage($(subquestion), "Question #{questionRef} is incomplete. #{label} is required and an option must be selected from the following dropdown list.")
+ errorMessage = "Question #{questionRef} is incomplete. #{label} is required and an option must be selected from the following dropdown list."
+ @logThis(question, "validateRequiredSubQuestion", errorMessage)
+ @addErrorMessage($(subquestion), errorMessage)
else
if question.find(".js-financial-year-latest").length
#avoid duplicate errors for financial year questions
return
else
- @addErrorMessage($(subquestion), "Question #{questionRef} is incomplete. #{label} is required and must be filled in.")
+ errorMessage = "Question #{questionRef} is incomplete. #{label} is required and must be filled in."
+ @logThis(question, "validateRequiredSubQuestion", errorMessage)
+ @addErrorMessage($(subquestion), errorMessage)
addQuestionError: (question) ->
questionRef = question.attr("data-question_ref")
incompleteMessage = "Question #{questionRef} is incomplete. It is required"
if @isOptionsQuestion(question)
- @addErrorMessage(question, "#{incompleteMessage} and an option must be chosen from the following list.")
+ errorMessage = "#{incompleteMessage} and an option must be chosen from the following list."
+ @logThis(question, "validateRequiredRadioQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
else if @isSelectQuestion(question)
- @addErrorMessage(question, "#{incompleteMessage} and an option must be selected from the following dropdown list.")
+ errorMessage = "#{incompleteMessage} and an option must be selected from the following dropdown list."
+ @logThis(question, "validateRequiredDropdownQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
else if @isTextishQuestion(question) && !question.hasClass("question-year")
- @addErrorMessage(question, "#{incompleteMessage} and must be filled in.")
+ errorMessage = "#{incompleteMessage} and must be filled in."
+ @logThis(question, "validateRequiredTextQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
else if question.hasClass("question-year")
- @addErrorMessage(question, "#{incompleteMessage} and must be filled in. Use the format YYYY.")
+ errorMessage = "#{incompleteMessage} and must be filled in. Use the format YYYY."
+ @logThis(question, "validateRequiredYearQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
else if @isCheckboxQuestion(question)
if question.find("input[type='checkbox']").length > 1
- @addErrorMessage(question, "#{incompleteMessage} and at least one option must be chosen from the following list.")
+ errorMessage = "#{incompleteMessage} and at least one option must be chosen from the following list."
+ @logThis(question, "validateRequiredCheckboxQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
else
- @addErrorMessage(question, "#{incompleteMessage} and confirmation must be given by ticking the checkbox.")
+ errorMessage = "#{incompleteMessage} and confirmation must be given by ticking the checkbox."
+ @logThis(question, "validateRequiredConfirmQuestion", errorMessage)
+ @addErrorMessage(question, errorMessage)
validateMatchQuestion: (question) ->
q = question.find(".match")
@@ -229,12 +249,14 @@ window.FormValidation =
diff = @compareDateInDays(questionDate, expDate)
if not questionYear or not questionMonth or not questionDay
- @logThis(question, "validateMaxDate", "This field is required")
- @addErrorMessage(question, "Question #{questionRef} is incomplete. It is required and must be filled in. Use the format DD/MM/YYYY.")
+ errorMessage = "Question #{questionRef} is incomplete. It is required and must be filled in. Use the format DD/MM/YYYY."
+ @logThis(question, "validateMaxDate", errorMessage)
+ @addErrorMessage(question, errorMessage)
return
if not @toDate(questionDate).isValid()
- @logThis(question, "validateMaxDate", "Not a valid date")
- @addErrorMessage(question, "Question #{questionRef} is incomplete. The date entered is not valid. Use the format DD/MM/YYYY.")
+ errorMessage = "Question #{questionRef} is incomplete. The date entered is not valid. Use the format DD/MM/YYYY."
+ @logThis(question, "validateMaxDate", errorMessage)
+ @addErrorMessage(question, errorMessage)
return
if diff > 0
@@ -470,7 +492,7 @@ window.FormValidation =
inputCellsCounter += 1
label = @extractText(subq.attr('id'))
if not subq.val() and question.hasClass("question-required")
- @logThis(question, "validateNumberByYears", "This field is required")
+ @logThis(question, "validateNumberByYears", "Question #{questionRef} is incomplete. #{label} is required and must be filled in.")
@appendMessage(errContainer, "Question #{questionRef} is incomplete. #{label} is required and must be filled in.")
@addErrorClass(question)
continue
@@ -553,16 +575,18 @@ window.FormValidation =
if question.hasClass("question-required") && errorsContainer.length < 1
if !(day and month and year)
- @logThis(question, "validateDateByYears", "This field is required")
- @appendMessage(qParent, "Question #{questionRef} is incomplete. #{label} is required and must be filled in. Use the format DD/MM/YYYY.")
+ errorMessage = "Question #{questionRef} is incomplete. #{label} is required and must be filled in. Use the format DD/MM/YYYY."
+ @logThis(question, "validateDateByYears", errorMessage)
+ @appendMessage(qParent, errorMessage)
@addErrorClass(question)
else
complexDateString = day + "/" + month + "/" + year
date = @toDate(complexDateString)
if not date.isValid()
- @logThis(question, "validateDateByYears", "Not a valid date")
- @appendMessage(qParent, "The date entered for question #{questionRef} #{label} is not valid. Use the format DD/MM/YYYY.")
+ errorMessage = "The date entered for question #{questionRef} #{label} is not valid. Use the format DD/MM/YYYY."
+ @logThis(question, errorMessage)
+ @appendMessage(qParent, errorMessage)
@addErrorClass(question)
validateInnovationFinancialDate: (question) ->
@@ -573,10 +597,13 @@ window.FormValidation =
questionDate = "#{questionDay}/#{questionMonth}/#{moment().format('Y')}"
if not (questionDay and questionMonth)
- @addErrorMessage(question, "Question #{questionRef} is incomplete. Year-end is required and must be filled in. Use the format DD/MM.")
+ errorMessage = "Question #{questionRef} is incomplete. Year-end is required and must be filled in. Use the format DD/MM."
+ @logThis(question, errorMessage)
+ @addErrorMessage(question, errorMessage)
else if not @toDate(questionDate).isValid()
- @logThis(question, "validateMaxDate", "Not a valid date")
- @addErrorMessage(question, "The date entered for #{questionRef} is not valid. Use the format DD/MM.")
+ errorMessage = "The date entered for #{questionRef} is not valid. Use the format DD/MM."
+ @logThis(question, errorMessage)
+ @addErrorMessage(question, errorMessage)
return
validateDiffBetweenDates: (question) ->
@@ -612,8 +639,9 @@ window.FormValidation =
err = true
if err
- @logThis(question, "validateDiffBetweenDates", "There is an error because financial year cannot be longer than 18 months, please double check your year end dates")
- @appendMessage(question, "There is an error because financial year cannot be longer than 18 months, please double check your year end dates")
+ errorMessage = "There is an error because financial year cannot be longer than 18 months, please double check your year end dates"
+ @logThis(question, "validateDiffBetweenDates", errorMessage)
+ @appendMessage(question, errorMessage)
@addErrorClass(question)
validateDateStartEnd: (question) ->
@@ -699,8 +727,9 @@ window.FormValidation =
else
missingOverseasTradeValue = true
if totalOverseasTradePercentage.toFixed(2) != (100).toFixed(2)
- @logThis(question, "validateGoodsServicesPercentage", "% of your total overseas trade should add up to 100")
- @appendMessage(question, "% of your total overseas trade should add up to 100")
+ errorMessage = "% of your total overseas trade should add up to 100"
+ @logThis(question, "validateGoodsServicesPercentage", errorMessage)
+ @appendMessage(question, errorMessage)
@addErrorClass(question)
validateSelectionLimit: (question) ->
@@ -717,7 +746,7 @@ window.FormValidation =
logThis: (question, validator, message) ->
stepData = question.closest(".js-step-condition").data("step")
stepTitle = $.trim($("a.js-step-link[data-step='#{stepData}']").text())
- qRef = $.trim(question.find("h2 span.visuallyhidden").text())
+ qRef = question.attr("data-question_ref")
qTitle = $.trim(question.find("h2").first().text())
if typeof console != "undefined"
diff --git a/app/assets/javascripts/frontend/password-strength-indicator.js b/app/assets/javascripts/frontend/password-strength-indicator.js
index 71f7b0791..6448b0dfd 100644
--- a/app/assets/javascripts/frontend/password-strength-indicator.js
+++ b/app/assets/javascripts/frontend/password-strength-indicator.js
@@ -138,6 +138,7 @@ $(function() {
if (someProblem) {
$('#password-guidance').removeClass("govuk-!-display-none");
+ $('#password-result-span').addClass("hide")
} else {
$('#password-guidance').addClass("govuk-!-display-none");
}
@@ -147,8 +148,10 @@ $(function() {
if ($passwordField.val().length == 0) {
$passwordField.attr('aria-invalid', "true");
+ $('#password-result-span').addClass("hide")
} else if ($.inArray('good-password', guidance) >= 0) {
$passwordField.attr('aria-invalid', "false");
+ $('#password-result-span').removeClass("hide")
} else {
$passwordField.attr('aria-invalid', "true");
}
@@ -160,13 +163,16 @@ $(function() {
if ($passwordConfirmationField.val().length == 0) {
$passwordConfirmationField.attr('aria-invalid', "true");
+ $('#password-confirmation-result-span').addClass("hide")
} else if ($.inArray('confirmation-not-matching', guidance) >= 0) {
$passwordConfirmationField.attr('aria-invalid', "true");
indicator.parent().removeClass('confirmation-matching');
+ $('#password-confirmation-result-span').addClass("hide")
} else if ($.inArray('confirmation-matching', guidance) >= 0) {
$passwordConfirmationField.attr('aria-invalid', "false");
if($.inArray('good-password', guidance) >= 0) {
indicator.parent().addClass('confirmation-matching');
+ $('#password-confirmation-result-span').removeClass("hide")
}
}
}
diff --git a/app/assets/stylesheets/admin/_pxToRem.scss b/app/assets/stylesheets/admin/_pxToRem.scss
new file mode 100644
index 000000000..b5983bee0
--- /dev/null
+++ b/app/assets/stylesheets/admin/_pxToRem.scss
@@ -0,0 +1,3 @@
+@function pxToRem($value) {
+ @return $value * 0.0625rem;
+}
diff --git a/app/assets/stylesheets/admin/_toRem.scss b/app/assets/stylesheets/admin/_toRem.scss
new file mode 100644
index 000000000..f648f1ab6
--- /dev/null
+++ b/app/assets/stylesheets/admin/_toRem.scss
@@ -0,0 +1,6 @@
+@use "sass:math";
+
+@function toRem($value) {
+ $remValue: math.div($value, 16) * 1rem;
+ @return $remValue;
+}
diff --git a/app/assets/stylesheets/admin/_toggle.scss b/app/assets/stylesheets/admin/_toggle.scss
index 4dfcd1812..8cc3bf517 100644
--- a/app/assets/stylesheets/admin/_toggle.scss
+++ b/app/assets/stylesheets/admin/_toggle.scss
@@ -1,3 +1,5 @@
+@import "pxToRem";
+
.hide {
display: none !important;
}
@@ -17,12 +19,12 @@
.rm {
border: 0;
clip: rect(0, 0, 0, 0);
- height: 1px;
- margin: -1px;
+ height: pxToRem(1);
+ margin: pxToRem(1);
overflow: hidden;
padding: 0;
position: absolute;
- width: 1px;
+ width: pxToRem(1);
z-index: -1;
}
diff --git a/app/assets/stylesheets/admin/_variables.scss b/app/assets/stylesheets/admin/_variables.scss
index 630ac5470..740857467 100644
--- a/app/assets/stylesheets/admin/_variables.scss
+++ b/app/assets/stylesheets/admin/_variables.scss
@@ -12,7 +12,7 @@ $grey-tab: #aaa;
$grey-tab-hover: #666;
$grey-panel: #dadad9;
$white-true: #fff;
-$green: #5C802D;
+$green: #3E541D;
$amber: #995C00;
$red: #A0030E;
$blue: #3276b1;
@@ -30,3 +30,5 @@ $header-hover: #444;
$blue-link-colour: #3264A3;
$govuk-light-blue: #5694ca;
+$govuk-highlight-yellow: #fd0;
+$govuk-warning-red: #d4351c;
diff --git a/app/assets/stylesheets/admin/base.scss b/app/assets/stylesheets/admin/base.scss
index 1bbe32c8b..66dfdcd4b 100644
--- a/app/assets/stylesheets/admin/base.scss
+++ b/app/assets/stylesheets/admin/base.scss
@@ -1,14 +1,48 @@
@import "mixins";
+@import "pxToRem";
// Basic
a {
color: $blue-link-colour;
+ text-decoration: underline;
&:active,
- &:focus {
+ &:focus:not(.btn-default, [role=tab]) {
+ outline: none !important;
+ text-decoration: none !important;
+ border-bottom-color: $black !important;
+ border-bottom-width: pxToRem(2) !important;
+ border-bottom-style: solid !important;
+ }
+}
+
+.btn, button, a, [role=menuitem], .button_to {
+ &:focus, &:focus-within {
+ background-color: $govuk-highlight-yellow !important;
+ border-color: $govuk-highlight-yellow;
+ color: $black !important;
outline: none !important;
}
}
+.search-submit, input[type=search],
+input[type=text], input[type=tel],
+input[type=email], input[type=password],
+input[type=checkbox], select {
+ &:focus {
+ outline: pxToRem(3) solid #ffdd00 !important;
+ outline-offset: 0 !important;
+ box-shadow: inset 0 0 0 pxToRem(2) !important;
+ }
+}
+
+.btn-primary, .button_to {
+ &:focus, &:focus-within {
+ border-bottom-color: $black !important;
+ border-bottom-width: pxToRem(2) !important;
+ border-bottom-style: solid !important;
+ }
+}
+
span {
&.visible-lg {
@include screen-lg-min {
@@ -45,11 +79,11 @@ span {
select,
select.form-control {
- padding-right: 20px;
+ padding-right: pxToRem(20);
background-image: image-url("icon-arrow-select.png");
background-repeat: no-repeat;
background-position: right center;
- background-size: 13px 14px;
+ background-size: pxToRem(13) pxToRem(14);
-moz-appearance: none;
-webkit-appearance: none;
@@ -94,7 +128,7 @@ h4 {
}
table .ellipsis {
- max-width: 175px;
+ max-width: pxToRem(175);
}
.admin-page-heading {
@@ -111,6 +145,7 @@ table .ellipsis {
.btn {
border-radius: 0;
+ text-decoration: none;
.icon-view,
.glyphicon,
@@ -128,7 +163,7 @@ table .ellipsis {
}
.glyphicon:first-child {
- margin-right: 5px;
+ margin-right: pxToRem(5);
}
}
@@ -182,28 +217,28 @@ table .ellipsis {
}
.btn-confirm-submit {
- font-size: 17px;
+ font-size: pxToRem(17);
}
.alert {
- padding-top: 10px;
- padding-bottom: 10px;
+ padding-top: pxToRem(10);
+ padding-bottom: pxToRem(10);
border-radius: 0;
}
.alert-glyphicon {
position: relative;
- padding-left: 40px;
+ padding-left: pxToRem(40);
.glyphicon {
position: absolute;
- top: 15px;
- left: 15px;
+ top: pxToRem(15);
+ left: pxToRem(15);
}
}
.panel-body .alert {
- margin-bottom: 30px;
+ margin-bottom: pxToRem(30);
}
.page-header {
@@ -212,7 +247,7 @@ table .ellipsis {
h1 {
margin-top: 0;
- font-size: 30px;
+ font-size: pxToRem(30);
}
}
@@ -226,7 +261,7 @@ table .ellipsis {
}
.pull-right a {
- margin-left: 20px;
+ margin-left: pxToRem(20);
}
.apps-navigation {
@@ -245,21 +280,21 @@ table .ellipsis {
.table {
width: 99.5%;
- margin-left: 1px;
+ margin-left: pxToRem(1);
}
.not-eligible {
- border-right: 2px solid $black;
- width: 75px;
+ border-right: pxToRem(2) solid $black;
+ width: pxToRem(75);
}
.table-total {
- width: 80px;
+ width: pxToRem(80);
}
.apps-in-proggress {
td {
- width: 70px;
+ width: pxToRem(70);
}
}
}
@@ -267,7 +302,7 @@ table .ellipsis {
.table {
&.table-striped tbody {
.lte-ie8 & {
- border: 2px solid $black-true;
+ border: pxToRem(2) solid $black-true;
border-collapse: initial !important;
}
}
@@ -296,7 +331,7 @@ table .ellipsis {
}
td {
- padding-top: 10px;
+ padding-top: pxToRem(10);
}
.td-assessment-submitted {
@@ -318,10 +353,10 @@ table .ellipsis {
}
.ellipsis {
- max-width: 350px;
+ max-width: pxToRem(350);
@include screen-md-max {
- max-width: 250px;
+ max-width: pxToRem(250);
}
}
}
@@ -343,7 +378,7 @@ table .ellipsis {
}
.question-group h2, h3 {
- font-size: 18px;
+ font-size: pxToRem(18);
font-weight: bold;
line-height: 1.5;
@@ -377,7 +412,7 @@ table .ellipsis {
.field-with-errors {
.error {
display: block;
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
color: $error-colour;
@include screen-md-min {
@@ -391,14 +426,14 @@ table .ellipsis {
}
.feedback-holder {
- margin-bottom: 15px;
+ margin-bottom: pxToRem(15);
}
}
.govuk-form-group--error {
.govuk-error-message {
display: block;
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
color: $error-colour;
@include screen-md-min {
@@ -412,7 +447,7 @@ table .ellipsis {
}
.feedback-holder {
- margin-bottom: 15px;
+ margin-bottom: pxToRem(15);
}
}
@@ -420,7 +455,7 @@ table .ellipsis {
display: block;
.form-group {
- margin-right: 36px;
+ margin-right: pxToRem(36);
}
.form-control {
@@ -430,7 +465,7 @@ table .ellipsis {
&,
&:first-child,
&:last-child {
- border-radius: 4px;
+ border-radius: pxToRem(4);
}
}
@@ -439,16 +474,16 @@ table .ellipsis {
position: absolute;
right: 0;
bottom: 0;
- width: 40px;
+ width: pxToRem(40);
height: 2.4em;
- border-left: 1px solid $grey-light;
+ border-left: pxToRem(1) solid $grey-light;
line-height: 1.5;
z-index: 2;
.lte-ie7 & {
- top: 1px !important;
+ top: pxToRem(1) !important;
padding: 0 !important;
- padding-top: 6px !important;
+ padding-top: pxToRem(6) !important;
}
.glyphicon {
@@ -480,14 +515,14 @@ table .ellipsis {
}
.form-actions {
- margin-top: 30px;
+ margin-top: pxToRem(30);
.show-sidebar & {
margin-top: 0;
}
.btn {
- margin-right: 15px;
+ margin-right: pxToRem(15);
&:last-child {
margin-right: 0;
@@ -502,23 +537,23 @@ table .ellipsis {
.selectable {
display: block;
position: relative;
- margin-top: 10px;
- margin-bottom: 10px;
- padding: 15px 20px;
+ margin-top: pxToRem(10);
+ margin-bottom: pxToRem(10);
+ padding: pxToRem(15) pxToRem(20);
float: none;
clear: left;
- border: 1px solid $selectable;
- border-radius: 4px;
+ border: pxToRem(1) solid $selectable;
+ border-radius: pxToRem(4);
background-color: $white-true;
cursor: pointer;
.checkbox & {
- padding-left: 35px;
+ padding-left: pxToRem(35);
}
}
label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
- margin-left: 10px;
+ margin-left: pxToRem(10);
}
// Fix boolean inputs
@@ -529,12 +564,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
&.control-label {
- padding-left: 20px;
+ padding-left: pxToRem(20);
}
input.boolean {
position: absolute;
- top: 14px;
+ top: pxToRem(14);
left: 1em;
}
@@ -545,17 +580,17 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
&.field-with-errors .checkbox {
- left: 20px;
+ left: pxToRem(20);
}
&.selectable-group {
.selectable {
- padding-left: 40px;
+ padding-left: pxToRem(40);
}
.checkbox {
- top: 15px;
- left: 15px;
+ top: pxToRem(15);
+ left: pxToRem(15);
margin-top: 0;
}
}
@@ -563,16 +598,16 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.hint {
display: block;
- margin-top: 10px;
- margin-bottom: 10px;
+ margin-top: pxToRem(10);
+ margin-bottom: pxToRem(10);
color: $grey-dark;
- font-size: 14px;
+ font-size: pxToRem(14);
}
.password-meter {
max-width: none;
- margin-top: 5px;
- margin-right: -80px;
+ margin-top: pxToRem(5);
+ margin-right: pxToRem(-80);
@include screen-sm-max {
margin-right: 0;
@@ -602,11 +637,11 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon {
- margin-right: 5px;
+ margin-right: pxToRem(5);
}
li {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
@extend .clearfix;
&:last-child {
@@ -615,13 +650,13 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.action-title {
display: block;
- margin-right: 110px;
+ margin-right: pxToRem(110);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.lte-ie8 & {
- max-width: 200px;
+ max-width: pxToRem(200);
margin-right: 0;
float: left;
}
@@ -640,7 +675,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
overflow: hidden;
.lte-ie8 & {
- max-height: 25px;
+ max-height: pxToRem(25);
}
input[type="file"] {
@@ -651,7 +686,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
left: auto;
width: 100%;
cursor: pointer;
- font-size: 200px;
+ font-size: pxToRem(200);
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
@@ -665,7 +700,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
// Alerts
.alert-container {
- margin-bottom: 30px;
+ margin-bottom: pxToRem(30);
z-index: 10001;
@include screen-sm-min {
@@ -673,18 +708,18 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
@include screen-md-min {
- max-width: 970px;
+ max-width: pxToRem(970);
}
@include screen-lg-min {
- max-width: 1170px;
+ max-width: pxToRem(1170);
}
.alert {
margin: 0;
.lte-ie7 & {
- max-width: 1170px;
+ max-width: pxToRem(1170);
text-align: left;
}
}
@@ -700,8 +735,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.icon-unflagged,
.icon-check {
display: inline-block;
- width: 30px;
- height: 30px;
+ width: pxToRem(30);
+ height: pxToRem(30);
text-align: left;
text-indent: -9999px;
background-repeat: no-repeat;
@@ -714,12 +749,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.icon-comment {
position: relative;
- width: 25px;
- height: 18px;
- top: 3px;
+ width: pxToRem(25);
+ height: pxToRem(18);
+ top: pxToRem(3);
background-image: image-url("icon-comment-sm.png");
background-position: left top;
- background-size: 20px 18px;
+ background-size: pxToRem(20) pxToRem(18);
@include is-retina {
background-image: image-url("icon-comment-sm@2.png");
@@ -727,28 +762,28 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.comment-count {
position: absolute;
- top: -6px;
- left: 23px;
+ top: pxToRem(-6);
+ left: pxToRem(23);
color: $black;
- font-size: 10px;
+ font-size: pxToRem(10);
font-weight: bold;
text-indent: 0;
}
}
.icon-comment-wrapper + .icon-flagged {
- margin-left: 10px;
+ margin-left: pxToRem(10);
display: inline-block;
}
.icon-flagged {
position: relative;
- width: 25px;
- height: 18px;
- top: 3px;
+ width: pxToRem(25);
+ height: pxToRem(18);
+ top: pxToRem(3);
background-image: image-url("icon-flag-sm.png");
background-position: left top;
- background-size: 12px 15px;
+ background-size: pxToRem(12) pxToRem(15);
@include is-retina {
background-image: image-url("icon-flag-sm@2.png");
@@ -764,10 +799,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.flag-count {
position: absolute;
- top: -6px;
- left: 13px;
+ top: pxToRem(-6);
+ left: pxToRem(13);
color: $black;
- font-size: 10px;
+ font-size: pxToRem(10);
font-weight: bold;
text-indent: 0;
}
@@ -776,7 +811,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.icon-unflagged {
background-image: image-url("icon-flag-sm-grey.png");
background-position: left top;
- background-size: 12px 15px;
+ background-size: pxToRem(12) pxToRem(15);
@include is-retina {
background-image: image-url("icon-flag-sm-grey@2.png");
@@ -785,12 +820,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.icon-check {
position: relative;
- width: 20px;
- height: 20px;
- top: -6px;
+ width: pxToRem(20);
+ height: pxToRem(20);
+ top: pxToRem(-6);
background-image: image-url("icon-check.png");
background-position: center center;
- background-size: 20px 14px;
+ background-size: pxToRem(20) pxToRem(14);
vertical-align: -webkit-baseline-middle;
@include is-retina {
@@ -803,12 +838,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.icon-view {
- width: 18px;
- min-height: 16px;
+ width: pxToRem(18);
+ min-height: pxToRem(16);
background-image: image-url("icon-computer-sm.png");
background-repeat: no-repeat;
background-position: center center;
- background-size: 18px 16px;
+ background-size: pxToRem(18) pxToRem(16);
text-align: left;
text-indent: -9999px;
opacity: 0.8;
@@ -829,12 +864,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.btn & {
position: relative;
- top: 2px;
- width: 20px;
- height: 16px;
- margin-right: 5px;
+ top: pxToRem(2);
+ width: pxToRem(20);
+ height: pxToRem(16);
+ margin-right: pxToRem(5);
background-image: image-url("icon-computer-sm.png");
- background-size: 18px 16px;
+ background-size: pxToRem(18) pxToRem(16);
opacity: 1;
@include is-retina {
@@ -854,13 +889,13 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
position: relative !important;
.lte-ie8 & {
- width: 350px;
+ width: pxToRem(350);
overflow: hidden;
}
.form_answers-index-page & {
@include screen-sm-max {
- margin-top: 15px;
+ margin-top: pxToRem(15);
}
}
@@ -868,7 +903,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
position: relative;
.lte-ie8 & {
- width: 350px;
+ width: pxToRem(350);
}
.lte-ie7 & {
@@ -878,8 +913,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
[type="search"],
input.form-control {
- padding-right: 40px;
- font-size: 16px;
+ padding-right: pxToRem(40);
+ font-size: pxToRem(16);
font-style: italic;
position: relative;
z-index: 10;
@@ -890,7 +925,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
top: 0;
right: 0;
bottom: 0;
- width: 30px;
+ width: pxToRem(30);
margin: 0;
padding: 0;
border: none;
@@ -898,7 +933,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
background-image: image-url("icon-search.png");
background-repeat: no-repeat;
background-position: center center;
- background-size: 15px 21px;
+ background-size: pxToRem(15) pxToRem(21);
text-align: left !important;
text-indent: -9999px;
white-space: nowrap;
@@ -921,10 +956,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
// Sortable Tables
.sortable {
a {
- padding-right: 16px;
+ padding-right: pxToRem(16);
background-repeat: no-repeat;
background-position: right center;
- background-size: 10px 6px;
+ background-size: pxToRem(10) pxToRem(6);
color: $black;
background-image: image-url("icon-arrow-sort-down-grey.png");
text-decoration: none;
@@ -975,13 +1010,13 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
// Filterable Dropdowns
.filter {
.dropdown-toggle {
- padding: 4px 10px;
+ padding: pxToRem(4) pxToRem(10);
color: $grey-dark;
font-size: inherit;
.lte-ie7 & {
position: relative;
- border-bottom: 1px solid $grey-light;
+ border-bottom: pxToRem(1) solid $grey-light;
zoom: 1;
}
@@ -995,7 +1030,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.caret {
- margin-left: 5px;
+ margin-left: pxToRem(5);
}
}
@@ -1004,11 +1039,11 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
margin: 0;
&.divider {
- margin: 5px 0;
+ margin: pxToRem(5) 0;
.lte-ie7 & {
width: 100%;
- height: 1px;
+ height: pxToRem(1);
background: $grey-light;
}
}
@@ -1025,15 +1060,15 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
input {
- margin-top: 11px;
- margin-left: 10px;
+ margin-top: pxToRem(11);
+ margin-left: pxToRem(10);
}
.label-contents {
display: block;
position: relative;
- padding: 7px 10px;
- padding-left: 30px;
+ padding: pxToRem(7) pxToRem(10);
+ padding-left: pxToRem(30);
z-index: 1;
}
@@ -1046,8 +1081,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
// Sidebar
.show-main-content,
.show-sidebar-container {
- padding-right: 15px;
- padding-left: 15px;
+ padding-right: pxToRem(15);
+ padding-left: pxToRem(15);
float: left;
}
@@ -1069,12 +1104,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.show-sidebar {
position: relative;
- padding: 15px;
+ padding: pxToRem(15);
background: $white-true;
zoom: 1;
@include screen-md-max {
- margin-bottom: 30px;
+ margin-bottom: pxToRem(30);
}
h1,
@@ -1085,45 +1120,45 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon {
- margin-right: 5px;
+ margin-right: pxToRem(5);
}
}
h1 {
- font-size: 32px;
+ font-size: pxToRem(32);
@include screen-md-max {
- font-size: 24px;
+ font-size: pxToRem(24);
}
}
h2 {
- margin-bottom: 20px;
- font-size: 16px;
+ margin-bottom: pxToRem(20);
+ font-size: pxToRem(16);
font-weight: bold;
text-transform: uppercase;
@include screen-md-max {
- font-size: 15px;
+ font-size: pxToRem(15);
}
.pull-right {
@include screen-md-max {
display: inline-block;
width: 100%;
- margin-top: 10px;
+ margin-top: pxToRem(10);
float: none !important;
}
}
}
h3 {
- margin-bottom: 20px;
- font-size: 16px;
+ margin-bottom: pxToRem(20);
+ font-size: pxToRem(16);
font-weight: bold;
@include screen-md-max {
- font-size: 15px;
+ font-size: pxToRem(15);
}
}
@@ -1131,16 +1166,16 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
display: block;
margin-top: 0.25em;
color: $grey-dark;
- font-size: 14px;
+ font-size: pxToRem(14);
text-transform: none;
}
.well {
margin: 0;
- padding: 20px 0;
+ padding: pxToRem(20) 0;
background: transparent;
border: none;
- border-bottom: 1px solid $grey;
+ border-bottom: pxToRem(1) solid $grey;
border-radius: 0;
box-shadow: none;
@@ -1155,8 +1190,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.well {
padding: 19px;
- border: 1px solid $grey;
- border-radius: 4px;
+ border: pxToRem(1) solid $grey;
+ border-radius: pxToRem(4);
}
}
@@ -1166,12 +1201,12 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.form-cancel-link:last-child {
- margin-right: 15px;
+ margin-right: pxToRem(15);
}
}
.sidebar-section {
- margin-bottom: 45px;
+ margin-bottom: pxToRem(45);
&:last-child {
margin-bottom: 0;
@@ -1190,7 +1225,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.comment {
position: relative;
- margin-bottom: 15px;
+ margin-bottom: pxToRem(15);
&:first-child {
padding-top: 0;
@@ -1199,11 +1234,11 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.comment-header {
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
h3 {
margin: 0;
- font-size: 16px;
+ font-size: pxToRem(16);
font-weight: bold;
line-height: 1.5;
}
@@ -1211,22 +1246,22 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.comment-action {
display: block;
- margin-top: 10px;
+ margin-top: pxToRem(10);
color: $grey-dark;
- font-size: 14px;
+ font-size: pxToRem(14);
.divider {
- margin: 0 8px;
+ margin: 0 pxToRem(8);
}
}
.link-flag-comment {
- margin-left: 3px;
- padding-left: 17px;
+ margin-left: pxToRem(3);
+ padding-left: pxToRem(17);
background-image: image-url("icon-flag-sm-grey.png");
background-repeat: no-repeat;
background-position: left center;
- background-size: 12px 15px;
+ background-size: pxToRem(12) pxToRem(15);
@include is-retina {
background-image: image-url("icon-flag-sm-grey@2.png");
@@ -1276,8 +1311,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.link-delete-comment {
display: inline-block;
position: relative;
- padding-right: 15px;
- font-size: 14px;
+ padding-right: pxToRem(15);
+ font-size: pxToRem(14);
font-weight: normal;
.show-delete-comment & {
@@ -1288,13 +1323,13 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
position: absolute;
top: 50%;
right: 0;
- width: 10px;
- height: 10px;
- margin-top: -5px;
+ width: pxToRem(10);
+ height: pxToRem(10);
+ margin-top: pxToRem(-5);
background-image: image-url("icon-close-comment.png");
background-repeat: no-repeat;
background-position: right;
- background-size: 10px 10px;
+ background-size: pxToRem(10) pxToRem(10);
@include is-retina {
background-image: image-url("icon-close-comment@2.png");
@@ -1330,20 +1365,20 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
width: 100%;
top: 50%;
left: 0;
- margin-top: -36px;
+ margin-top: pxToRem(-36);
}
}
.comment-insert {
- margin-top: 15px;
+ margin-top: pxToRem(15);
}
.comment-actions {
- margin-top: 10px;
+ margin-top: pxToRem(10);
.link-flag-comment {
display: inline-block;
- margin-top: 5px;
+ margin-top: pxToRem(5);
}
input[type="checkbox"] {
@@ -1374,10 +1409,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
tbody {
- border: 2px solid $black;
+ border: pxToRem(2) solid $black;
> tr > th {
- border-right: 2px solid $black;
+ border-right: pxToRem(2) solid $black;
}
}
@@ -1399,22 +1434,37 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
border: none;
border-radius: 0;
background-color: $grey-panel;
+
+ &:focus-within {
+ background-color: $govuk-highlight-yellow;
+ border-bottom-color: $black !important;
+ border-bottom-width: pxToRem(2) !important;
+ border-bottom-style: solid !important;
+ }
}
.panel-title {
font-weight: bold;
text-transform: uppercase;
- font-size: 16px;
+ font-size: pxToRem(16);
line-height: 1.1 !important;
> a {
- padding-left: 25px;
+ padding-left: pxToRem(25);
background-image: image-url("icon-arrow-collapse-down.png");
background-repeat: no-repeat;
background-position: 0 0.4em;
- background-size: 12px 8px;
+ background-size: pxToRem(12) pxToRem(8);
text-decoration: none;
+ &:focus {
+ border-bottom: none !important;
+
+ small {
+ color: $black !important;
+ }
+ }
+
@include is-retina {
background-image: image-url("icon-arrow-collapse-down@2.png");
}
@@ -1435,18 +1485,18 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
small {
display: inline-block;
width: 100%;
- margin-top: 10px;
- padding-left: 25px;
+ margin-top: pxToRem(10);
+ padding-left: pxToRem(25);
color: $grey-dark;
- font-size: 14px;
+ font-size: pxToRem(14);
font-style: italic;
text-transform: none;
@include screen-md-max {
display: inline-block;
width: 100%;
- margin-top: 10px;
- padding-left: 25px;
+ margin-top: pxToRem(10);
+ padding-left: pxToRem(25);
float: none !important;
}
@@ -1469,8 +1519,16 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
a {
background-image: image-url("icon-arrow-collapse-down-white.png");
+ &:focus {
+ background-image: image-url("icon-arrow-collapse-down.png") !important;
+ }
+
@include is-retina {
background-image: image-url("icon-arrow-collapse-down-white@2.png");
+
+ &:focus {
+ background-image: image-url("icon-arrow-collapse-down@2.png") !important;
+ }
}
}
}
@@ -1478,8 +1536,16 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
&.expanded > .panel-title a {
background-image: image-url("icon-arrow-collapse-up-white.png");
+ &:focus {
+ background-image: image-url("icon-arrow-collapse-up.png") !important;
+ }
+
@include is-retina {
background-image: image-url("icon-arrow-collapse-up-white@2.png");
+
+ &:focus {
+ background-image: image-url("icon-arrow-collapse-up@2.png") !important;
+ }
}
}
}
@@ -1493,8 +1559,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.form-label-rag {
display: block;
position: relative;
- margin-top: 10px;
- margin-bottom: 10px;
+ margin-top: pxToRem(10);
+ margin-bottom: pxToRem(10);
@include screen-xs-max {
margin-top: 0;
@@ -1517,7 +1583,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.btn-rag {
position: absolute;
right: 0;
- top: -5px;
+ top: pxToRem(-5);
@include screen-xs-max {
display: block;
@@ -1541,23 +1607,23 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
position: absolute;
top: 50%;
right: 0;
- width: 20px;
- height: 20px;
- margin-top: -10px;
- background-size: 20px 20px;
+ width: pxToRem(20);
+ height: pxToRem(20);
+ margin-top: pxToRem(-10);
+ background-size: pxToRem(20) pxToRem(20);
text-align: left;
text-indent: -9999px;
}
&.rag-editable .icon-rag {
- right: 15px;
+ right: pxToRem(15);
}
.caret {
position: absolute;
top: 50%;
right: 0;
- margin-top: -2px;
+ margin-top: pxToRem(-2);
}
.dropdown-toggle,
@@ -1567,7 +1633,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.dropdown-toggle {
- padding-right: 25px;
+ padding-right: pxToRem(25);
padding-left: 0;
@include screen-xs-max {
@@ -1588,7 +1654,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
&.rag-editable .dropdown-toggle {
- padding-right: 40px;
+ padding-right: pxToRem(40);
}
.dropdown-menu {
@@ -1605,9 +1671,9 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
a {
- padding-top: 6px;
- padding-bottom: 6px;
- padding-left: 37px;
+ padding-top: pxToRem(6);
+ padding-bottom: pxToRem(6);
+ padding-left: pxToRem(37);
@include screen-xs-max {
white-space: normal;
@@ -1615,10 +1681,15 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.icon-rag {
- left: 12px;
+ left: pxToRem(12);
}
}
+ .rag-error {
+ background-color: #f2dede;
+ color: #a94442 !important;
+ }
+
.rag-blank {
&,
a,
@@ -1731,7 +1802,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.form-control {
@include screen-sm-max {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
}
}
}
@@ -1741,7 +1812,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
@include screen-sm-max {
margin-top: 0;
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
}
}
}
@@ -1751,7 +1822,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
background: none;
border: none;
display: block;
- padding: 3px 20px;
+ padding: pxToRem(3) pxToRem(20);
clear: both;
font-weight: normal;
line-height: 1.42857143;
@@ -1770,7 +1841,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.page-header-nav .btn-link.pull-left,
.search-form h2 .btn-link {
- margin-right: 30px;
+ margin-right: pxToRem(30);
padding-right: 0;
padding-left: 0;
}
@@ -1794,10 +1865,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-paperclip {
- width: 16px;
- height: 16px;
+ width: pxToRem(16);
+ height: pxToRem(16);
background-image: image-url("icon-attach.png");
- background-size: 16px 16px;
+ background-size: pxToRem(16) pxToRem(16);
@include is-retina {
background-image: image-url("icon-attach@2.png");
@@ -1805,10 +1876,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-pencil {
- width: 15px;
- height: 13px;
+ width: pxToRem(15);
+ height: pxToRem(13);
background-image: image-url("icon-edit-black.png");
- background-size: 15px 13px;
+ background-size: pxToRem(15) pxToRem(13);
@include is-retina {
background-image: image-url("icon-edit-black@2.png");
@@ -1816,10 +1887,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-file {
- width: 12px;
- height: 16px;
+ width: pxToRem(12);
+ height: pxToRem(16);
background-image: image-url("icon-file.png");
- background-size: 12px 16px;
+ background-size: pxToRem(12) pxToRem(16);
@include is-retina {
background-image: image-url("icon-file@2.png");
@@ -1827,10 +1898,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-info-sign {
- width: 15px;
- height: 15px;
+ width: pxToRem(15);
+ height: pxToRem(15);
background-image: image-url("icon-info.png");
- background-size: 15px 15px;
+ background-size: pxToRem(15) pxToRem(15);
@include is-retina {
background-image: image-url("icon-info@2.png");
@@ -1838,10 +1909,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-download-alt {
- width: 15px;
- height: 16px;
+ width: pxToRem(15);
+ height: pxToRem(16);
background-image: image-url("icon-download.png");
- background-size: 15px 16px;
+ background-size: pxToRem(15) pxToRem(16);
&.black {
background-image: image-url("icon-download-black.png");
@@ -1857,10 +1928,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-user {
- width: 14px;
- height: 14px;
+ width: pxToRem(14);
+ height: pxToRem(14);
background-image: image-url("icon-user.png");
- background-size: 14px 14px;
+ background-size: pxToRem(14) pxToRem(14);
@include is-retina {
background-image: image-url("icon-user@2.png");
@@ -1868,10 +1939,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-ok {
- width: 15px;
- height: 12px;
+ width: pxToRem(15);
+ height: pxToRem(12);
background-image: image-url("icon-valid.png");
- background-size: 15px 12px;
+ background-size: pxToRem(15) pxToRem(12);
@include is-retina {
background-image: image-url("icon-valid@2.png");
@@ -1896,10 +1967,10 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.glyphicon-remove {
- width: 11px;
- height: 11px;
+ width: pxToRem(11);
+ height: pxToRem(11);
background-image: image-url("icon-invalid.png");
- background-size: 11px 11px;
+ background-size: pxToRem(11) pxToRem(11);
@include is-retina {
background-image: image-url("icon-invalid@2.png");
@@ -1934,8 +2005,9 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.award-year-dropdown {
- max-width: 142px;
- margin-left: 120px;
+ max-width: pxToRem(142);
+ margin-left: pxToRem(120);
+ margin: 0 !important;
}
&.award-year--vertical {
@@ -1958,9 +2030,9 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
right: 0;
bottom: 0;
left: auto;
- padding-right: 10px;
- padding-left: 10px;
- border-left: 1px solid $less-black;
+ padding-right: pxToRem(10);
+ padding-left: pxToRem(10);
+ border-left: pxToRem(1) solid $less-black;
background: $black-header;
.caret {
@@ -1982,8 +2054,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.btn:active .caret-container {
outline: 0;
background-image: none;
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ -webkit-box-shadow: inset 0 pxToRem(3) pxToRem(5) rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 pxToRem(3) pxToRem(5) rgba(0, 0, 0, 0.125);
}
.dropdown-menu {
@@ -1992,16 +2064,16 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
z-index: 2000;
> li > a {
- padding-left: 12px;
+ padding-left: pxToRem(12);
}
}
}
.glyphicon-star,
.glyphicon-star-empty {
- width: 16px;
- height: 15px;
- background-size: 16px 15px;
+ width: pxToRem(16);
+ height: pxToRem(15);
+ background-size: pxToRem(16) pxToRem(15);
}
.glyphicon-star {
@@ -2028,7 +2100,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.char-space {
display: inline-block;
- width: 160px;
+ width: pxToRem(160);
height: 1em;
}
@@ -2041,13 +2113,13 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.char-text-limit {
- font-size: 14px;
+ font-size: pxToRem(14);
margin-top: 0.5em;
margin-bottom: 0.2em;
text-align: right;
}
.char-text {
- font-size: 14px;
+ font-size: pxToRem(14);
margin-top: 0.2em;
text-align: right;
@@ -2057,13 +2129,17 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
}
.nav-subnav {
- margin-bottom: 15px;
- border-bottom: 4px solid $black-header;
+ margin-bottom: pxToRem(15);
+ border-bottom: pxToRem(4) solid $black-header;
ul {
margin: 0;
padding: 0;
list-style: none;
+ display: flex;
+ @include screen-sm-max {
+ display: block;
+ }
}
li {
@@ -2082,8 +2158,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
a {
display: block;
- padding: 10px 15px;
- padding-bottom: 15px;
+ padding: pxToRem(10) pxToRem(15);
+ padding-bottom: pxToRem(15);
float: left;
color: $black;
text-align: center;
@@ -2091,8 +2167,8 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
text-transform: uppercase;
@include screen-md-max {
- padding: 8px 10px;
- padding-bottom: 15px;
+ padding: pxToRem(8) pxToRem(10);
+ padding-bottom: pxToRem(15);
}
@include screen-sm-max {
@@ -2103,7 +2179,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.active a {
background: transparent image-url("icon-arrow-admin-subnav.png") no-repeat
center 110%;
- background-size: 24px 12px;
+ background-size: pxToRem(24) pxToRem(12);
color: $blue-link-colour;
@include is-retina {
@@ -2139,3 +2215,7 @@ label.govuk-label.govuk-checkboxes__label.boolean.optional.govuk-label {
.space-y-3 > :not([hidden]) ~ :not([hidden]) {
margin-top: 1.5rem;
}
+
+.alert button.close {
+ font-size: pxToRem(18);
+}
diff --git a/app/assets/stylesheets/admin/bootstrap-overrides.scss b/app/assets/stylesheets/admin/bootstrap-overrides.scss
new file mode 100644
index 000000000..472b85c36
--- /dev/null
+++ b/app/assets/stylesheets/admin/bootstrap-overrides.scss
@@ -0,0 +1,18 @@
+html { font-size: 100% }
+body { font-size: inherit !important; }
+
+.btn {
+ font-size: 1rem;
+}
+
+.form-control {
+ font-size: 1rem
+}
+
+.dropdown-menu {
+ font-size: 1rem;
+}
+
+.navbar-nav {
+ display: flex;
+}
diff --git a/app/assets/stylesheets/admin/date-time-picker.scss b/app/assets/stylesheets/admin/date-time-picker.scss
index b21e5dc51..81b86709f 100644
--- a/app/assets/stylesheets/admin/date-time-picker.scss
+++ b/app/assets/stylesheets/admin/date-time-picker.scss
@@ -1,15 +1,16 @@
+@import "pxToRem";
// Date/time Picker Inputs
.datepicker,
.timepicker {
display: inline-block;
- padding-left: 35px;
+ padding-left: pxToRem(35);
background-repeat: no-repeat;
- background-position: 7px 7px;
- background-size: 18px 18px;
+ background-position: pxToRem(7) pxToRem(7);
+ background-size: pxToRem(18) pxToRem(18);
}
.datepicker {
- width: 135px;
+ width: pxToRem(135);
background-image: image-url("icon-date-picker.png");
@include is-retina {
@@ -21,13 +22,13 @@
}
.lte-ie7 & {
- width: 80px !important;
+ width: pxToRem(80) !important;
}
}
.timepicker {
- width: 95px;
- margin-left: 10px;
+ width: pxToRem(95);
+ margin-left: pxToRem(10);
background-image: image-url("icon-time-picker.png");
@include is-retina {
@@ -36,7 +37,7 @@
@include screen-sm-max {
width: 100%;
- margin-top: 10px;
+ margin-top: pxToRem(10);
margin-left: 0;
}
@@ -49,26 +50,26 @@
.time-picker {
display: none;
position: absolute;
- min-width: 95px;
- max-height: 200px;
- margin: 2px 0 0;
- padding: 5px 0;
+ min-width: pxToRem(95);
+ max-height: pxToRem(200);
+ margin: pxToRem(2) 0 0;
+ padding: pxToRem(5) 0;
float: left;
- border: 1px solid $grey-light;
- border: 1px solid rgba(0, 0, 0, 0.15);
- border-radius: 4px;
+ border: pxToRem(1) solid $grey-light;
+ border: pxToRem(1) solid rgba(0, 0, 0, 0.15);
+ border-radius: pxToRem(4);
background-color: $white-true;
- font-size: 14px;
+ font-size: pxToRem(14);
list-style: none;
text-align: left;
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ box-shadow: 0 pxToRem(6) pxToRem(12) rgba(0, 0, 0, 0.175);
overflow: auto;
z-index: 99;
background-clip: padding-box;
li {
display: block;
- padding: 3px 20px;
+ padding: pxToRem(3) pxToRem(20);
clear: both;
cursor: pointer;
color: $black;
@@ -99,18 +100,18 @@ body .ui-datepicker {
top: 100%;
left: 0;
width: auto;
- min-width: 160px;
- margin: 2px 0 0;
- padding: 4px;
+ min-width: pxToRem(160);
+ margin: pxToRem(2) 0 0;
+ padding: pxToRem(4);
float: left;
- border: 1px solid $grey-light;
- border: 1px solid rgba(0, 0, 0, 0.15);
- border-radius: 4px;
+ border: pxToRem(1) solid $grey-light;
+ border: pxToRem(1) solid rgba(0, 0, 0, 0.15);
+ border-radius: pxToRem(4);
background-color: $white-true;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
- font-size: 14px;
+ font-size: pxToRem(14);
list-style: none;
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ box-shadow: 0 pxToRem(6) pxToRem(12) rgba(0, 0, 0, 0.175);
z-index: 1000;
background-clip: padding-box;
@@ -121,39 +122,39 @@ body .ui-datepicker {
.ui-datepicker-prev,
.ui-datepicker-next {
- width: 30px;
- height: 30px;
+ width: pxToRem(30);
+ height: pxToRem(30);
border: none;
- border-radius: 4px;
+ border-radius: pxToRem(4);
text-align: center;
&:hover {
- top: 2px;
+ top: pxToRem(2);
border: none;
background: $grey-lightest;
}
}
.ui-datepicker-prev:hover {
- left: 2px;
+ left: pxToRem(2);
}
.ui-datepicker-next:hover {
- right: 2px;
+ right: pxToRem(2);
}
.ui-datepicker-title {
- width: 145px;
- height: 30px;
- margin: 0 35px;
+ width: pxToRem(145);
+ height: pxToRem(30);
+ margin: 0 pxToRem(35);
border: none;
- border-radius: 4px;
+ border-radius: pxToRem(4);
text-align: center;
}
.ui-datepicker-calendar {
.lte-ie7 & {
- width: 200px !important;
+ width: pxToRem(200) !important;
}
}
@@ -163,11 +164,11 @@ body .ui-datepicker {
th,
td a {
- width: 30px;
- height: 30px;
- padding: 5px;
+ width: pxToRem(30);
+ height: pxToRem(30);
+ padding: pxToRem(5);
border: none;
- border-radius: 4px;
+ border-radius: pxToRem(4);
text-align: center;
}
diff --git a/app/assets/stylesheets/admin/forms.scss b/app/assets/stylesheets/admin/forms.scss
index cdc503797..1f12f10b9 100644
--- a/app/assets/stylesheets/admin/forms.scss
+++ b/app/assets/stylesheets/admin/forms.scss
@@ -1,15 +1,27 @@
+@import "pxToRem";
+
.selectable-group {
input[type='checkbox'],
input[type='radio'] {
margin-left: 0;
- top: 15px;
- left: 15px;
+ top: pxToRem(15);
+ left: pxToRem(15);
z-index: 999;
}
}
.has-royal-family-connections-wrapper {
- padding-left: 20px;
+ padding-left: pxToRem(20);
+}
+
+input.form-control, select.form-control,
+.input-group-addon, textarea,
+.btn-default {
+ border-color: #5C5C5C !important;
+}
+
+.input-group-addon {
+ height: 2.42em !important;
}
input.form-control, select.form-control,
diff --git a/app/assets/stylesheets/admin/header-footer.scss b/app/assets/stylesheets/admin/header-footer.scss
index 227771b72..1f5c0ee7a 100644
--- a/app/assets/stylesheets/admin/header-footer.scss
+++ b/app/assets/stylesheets/admin/header-footer.scss
@@ -1,4 +1,5 @@
@import "mixins";
+@import "pxToRem";
#site-header {
-webkit-font-smoothing: antialiased;
@@ -6,39 +7,38 @@
*z-index: 1000;
@include screen-lg-max {
- font-size: 14px;
+ font-size: pxToRem(14);
}
@include screen-md-max {
- font-size: 13px;
+ font-size: pxToRem(13);
}
@include screen-sm-max {
- font-size: 14px;
+ font-size: pxToRem(14);
}
.lte-ie8 & {
background: $black-header;
clear: both;
- height: 70px;
- margin-bottom: 40px !important;
+ height: pxToRem(70);
+ margin-bottom: pxToRem(40) !important;
}
.caret {
- margin-left: 5px;
- border-top-width: 7px;
- border-right-width: 6px;
- border-left-width: 6px;
+ margin-left: pxToRem(5);
+ border-top-width: pxToRem(7);
+ border-right-width: pxToRem(6);
+ border-left-width: pxToRem(6);
@include screen-md-max {
- margin-left: 3px;
- border-top-width: 5px;
- border-right-width: 4px;
- border-left-width: 4px;
+ margin-left: pxToRem(3);
+ border-top-width: pxToRem(5);
+ border-right-width: pxToRem(4);
+ border-left-width: pxToRem(4);
}
}
-
.container {
.lte-ie8 & {
width: 90% !important;
@@ -53,8 +53,8 @@
}
.navbar-toggle {
- margin-top: 16px;
- margin-bottom: 16px;
+ margin-top: pxToRem(16);
+ margin-bottom: pxToRem(16);
.icon-bar {
background-color: $white-true;
@@ -68,7 +68,7 @@
.navbar-collapse {
.lte-ie8 & {
display: block !important;
- margin-left: 50px;
+ margin-left: pxToRem(50);
}
&.collapse {
@@ -80,13 +80,13 @@
}
.navbar {
- margin-bottom: 40px;
+ margin-bottom: pxToRem(40);
border: none;
border-radius: 0;
background: $black-header;
-
+
.lte-ie7 & {
- height: 81px !important;
+ height: pxToRem(81) !important;
z-index: 100001 !important;
}
@@ -99,20 +99,27 @@
}
}
- .navbar-nav > li > a {
- padding-top: 24px;
- padding-bottom: 23px;
+ .navbar-nav > li > a,
+ .navbar-nav > li > details {
+ padding-top: pxToRem(24);
+ padding-bottom: pxToRem(23);
color: $white-true;
text-transform: uppercase;
background: transparent;
+ text-decoration: none;
@include screen-md-max {
- padding-right: 8px;
- padding-left: 8px;
+ padding-right: pxToRem(8);
+ padding-left: pxToRem(8);
}
@include screen-sm-max {
- padding: 20px 15px;
+ padding: pxToRem(20) pxToRem(15);
+ }
+
+ > .dropdown-menu {
+ display: block;
+ text-transform: none;
}
}
}
@@ -121,7 +128,7 @@
.lte-ie8 & {
float: left !important;
position: relative;
- top: -10px;
+ top: pxToRem(-10);
}
&.navbar-right {
@@ -150,22 +157,23 @@
margin-right: 0;
}
- > a {
+ > a, > details {
.lte-ie8 & {
display: block !important;
- padding-top: 26px !important;
- padding-bottom: 26px !important;
+ padding-top: pxToRem(26) !important;
+ padding-bottom: pxToRem(26) !important;
color: $white-true !important;
}
.lte-ie7 & {
- padding-top: 30px !important;
- padding-bottom: 30px !important;
+ padding-top: pxToRem(30) !important;
+ padding-bottom: pxToRem(30) !important;
}
&:hover,
&:focus {
background-color: $header-hover;
+ cursor: pointer;
@include is-ios {
background-color: transparent;
@@ -179,9 +187,26 @@
}
}
+ > details {
+ padding: 0 pxToRem(10);
+
+ &:focus-within {
+ background-color: $govuk-highlight-yellow !important;
+ color: $black !important;
+ outline: none !important;
+ border-bottom-color: $black !important;
+ border-bottom-width: pxToRem(2) !important;
+ border-bottom-style: solid !important;
+
+ summary {
+ outline: none !important;
+ }
+ }
+ }
+
&.active > a {
background: transparent image-url("icon-arrow-admin-nav.png") no-repeat center bottom;
- background-size: 24px 12px;
+ background-size: pxToRem(24) pxToRem(12);
@include is-retina {
background-image: image-url("icon-arrow-admin-nav@2.png");
@@ -206,32 +231,40 @@
z-index: 999999 !important;
}
- > li > span {
+ > li > span,
+ > li > .button_to {
display: block;
- padding: 3px 20px;
+ padding: pxToRem(3) pxToRem(20);
clear: both;
font-weight: normal;
line-height: 1.42857143;
color: #333333;
white-space: nowrap;
+
+ @include screen-sm-max {
+ padding: 0;
+ }
}
> li > a,
- > li > span {
+ > li > span,
+ > li > .button_to > input[type="submit"] {
@include screen-sm-max {
- padding: 15px;
- padding-left: 35px;
+ padding: pxToRem(15);
+ padding-left: pxToRem(35);
color: $white-true;
text-transform: uppercase;
+ text-align: left;
}
.lte-ie8 & {
- padding: 7px 10px !important;
+ padding: pxToRem(7) pxToRem(10) !important;
color: $black !important;
}
}
- > li > a {
+ > li > a,
+ > li > .button_to {
&:hover,
&:focus {
@include screen-sm-max {
@@ -243,6 +276,26 @@
}
}
}
+
+ .button_to {
+ display: inline;
+
+ input[type="submit"] {
+ background: none;
+ padding: 0;
+ border: none;
+ color: black;
+ text-decoration: underline;
+
+ .lte-ie7 & {
+ font-size: pxToRem(16);
+ }
+ }
+
+ &:hover {
+ background-color: $grey-lightest;
+ }
+ }
}
.open .dropdown-toggle {
@@ -250,15 +303,14 @@
background-color: $header-hover !important;
}
}
-
+
// moving down here seems to make it work
.navbar-brand {
- padding-top: 14px;
- padding-bottom: 0;
- text-align: left;
+ padding: pxToRem(14);
+ height: 100%;
img {
- width: 28px;
- height: 33px;
+ width: pxToRem(28);
+ height: pxToRem(33);
}
}
}
diff --git a/app/assets/stylesheets/admin/layout.scss b/app/assets/stylesheets/admin/layout.scss
index b492a89f2..b6c00a614 100644
--- a/app/assets/stylesheets/admin/layout.scss
+++ b/app/assets/stylesheets/admin/layout.scss
@@ -1,6 +1,8 @@
@import "mixins";
-$footer-height: 60px;
-$footer-height-sm: 30px;
+@import "pxToRem";
+
+$footer-height: pxToRem(60);
+$footer-height-sm: pxToRem(30);
html,
body,
@@ -56,7 +58,7 @@ body {
font-weight: bold;
color: #fff;
position: relative;
- top: -40px;
+ top: pxToRem(-40);
}
.dev-banner {
@@ -69,7 +71,7 @@ body {
.admin-assessor-js-status-banner {
position: relative;
- top: -40px;
+ top: pxToRem(-40);
padding: 0.5em;
text-align: center;
background-color: #fff2d3;
@@ -78,15 +80,15 @@ body {
.container {
.lte-ie8 & {
- max-width: 1170px;
+ max-width: pxToRem(1170);
}
}
.row {
.lte-ie8 & {
display: block;
- margin-right: -15px;
- margin-left: -15px;
+ margin-right: pxToRem(-15);
+ margin-left: pxToRem(-15);
clear: both;
}
@@ -111,9 +113,9 @@ body {
.lte-ie8 & {
float: left;
position: relative;
- min-height: 1px;
- padding-right: 15px;
- padding-left: 15px;
+ min-height: pxToRem(1);
+ padding-right: pxToRem(15);
+ padding-left: pxToRem(15);
}
.lte-ie7 & {
diff --git a/app/assets/stylesheets/admin/page-applications.scss b/app/assets/stylesheets/admin/page-applications.scss
index 4b2fb6d42..1553e5ac5 100644
--- a/app/assets/stylesheets/admin/page-applications.scss
+++ b/app/assets/stylesheets/admin/page-applications.scss
@@ -1,17 +1,18 @@
@import "mixins";
+@import "pxToRem";
.panel-subtitle-small {
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
}
.applications-filter {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
.applications-filter__label, .search-input__label {
display: block;
text-transform: uppercase;
- padding-right: 10px;
- padding-top: 7px;
+ padding-right: pxToRem(10);
+ padding-top: pxToRem(7);
@include screen-md-max {
text-align: left;
@@ -19,14 +20,14 @@
@include screen-sm-max {
min-width: 0;
- padding-right: 20px;
+ padding-right: pxToRem(20);
}
}
.dropdown {
position: relative;
display: inline-block;
- padding-right: 28px;
+ padding-right: pxToRem(28);
width: 100%;
vertical-align: bottom;
@@ -35,7 +36,7 @@
overflow: hidden;
max-width: 100%;
text-overflow: ellipsis;
- line-height: 19px;
+ line-height: pxToRem(19);
}
.caret-container {
@@ -44,9 +45,9 @@
right: 0;
bottom: 0;
left: auto;
- padding-right: 10px;
- padding-left: 10px;
- border-left: 1px solid #262626;
+ padding-right: pxToRem(10);
+ padding-left: pxToRem(10);
+ border-left: pxToRem(1) solid #262626;
background: #1c1c1b;
.caret {
@@ -56,26 +57,22 @@
}
.dropdown-menu {
- min-width: 250px;
+ min-width: pxToRem(250);
border-color: #666666;
li.checkbox,
li.apply {
- padding: 0 10px;
-
- .btn:focus {
- border-color: #5C5C5C;
- }
+ padding: 0 pxToRem(10);
}
}
}
}
.search-text {
- margin-bottom: 30px;
- padding: 10px 15px;
+ margin-bottom: pxToRem(30);
+ padding: pxToRem(10) pxToRem(15);
background-color: $grey-lighter;
- font-size: 18px;
+ font-size: pxToRem(18);
font-style: italic;
p {
@@ -90,8 +87,8 @@
.applications-table,
.admin-table {
> tbody > tr > td {
- padding-top: 13px;
- padding-bottom: 12px;
+ padding-top: pxToRem(13);
+ padding-bottom: pxToRem(12);
a:not(.link-edit-user) {
color: $blue-link-colour;
}
@@ -103,7 +100,7 @@
}
> tbody > tr:first-child > td {
- padding-top: 16px;
+ padding-top: pxToRem(16);
}
}
@@ -128,9 +125,9 @@
}
.nav-tabs.submitted-tabs {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
border-bottom: none;
- font-size: 11px;
+ font-size: pxToRem(11);
.no-js & {
display: none;
@@ -139,18 +136,18 @@
> li {
> a {
margin: 0;
- margin-left: 5px;
+ margin-left: pxToRem(5);
&,
&:focus {
- padding: 3px 10px;
- border: 2px solid $grey-tab;
- border-radius: 100px;
+ padding: pxToRem(3) pxToRem(10);
+ border: pxToRem(2) solid $grey-tab;
+ border-radius: pxToRem(100);
color: $grey-tab;
}
&:hover {
- border: 2px solid $grey-tab-hover;
+ border: pxToRem(2) solid $grey-tab-hover;
background: transparent;
color: $grey-tab-hover;
}
@@ -161,12 +158,12 @@
position: absolute;
bottom: 0;
left: 50%;
- width: 8px;
- height: 4px;
- margin-bottom: -6px;
- margin-left: -4px;
+ width: pxToRem(8);
+ height: pxToRem(4);
+ margin-bottom: pxToRem(-6);
+ margin-left: pxToRem(-4);
background-image: image-url("icon-arrow-tab.png");
- background-size: 8px 4px;
+ background-size: pxToRem(8) pxToRem(4);
@include is-retina {
background-image: image-url("icon-arrow-tab@2.png");
@@ -179,7 +176,7 @@
&,
&:hover,
&:focus {
- border: 2px solid #666;
+ border: pxToRem(2) solid #666;
color: #666;
}
}
@@ -192,7 +189,7 @@
.no-js .tab-content > .tab-pane {
display: block;
- margin-bottom: 30px;
+ margin-bottom: pxToRem(30);
visibility: visible;
&:last-child {
@@ -202,7 +199,7 @@
.tab-header {
display: none;
- margin-bottom: 15px;
+ margin-bottom: pxToRem(15);
.no-js & {
display: block;
@@ -211,12 +208,12 @@
.label-small {
display: block;
- font-size: 14px;
+ font-size: pxToRem(14);
text-align: left;
}
.good-services-list li {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
&:last-child {
margin-bottom: 0;
@@ -227,19 +224,19 @@
display: none;
color: gray;
font-style: italic;
- font-size: 14px;
- margin-bottom: 10px;
+ font-size: pxToRem(14);
+ margin-bottom: pxToRem(10);
}
.inline-form-view {
- margin-top: 15px;
+ margin-top: pxToRem(15);
.form-control {
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
}
.form-group .row {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
}
.no-js & {
@@ -260,7 +257,7 @@
.control-label {
display: block;
- font-size: 14px;
+ font-size: pxToRem(14);
text-align: left;
}
@@ -268,17 +265,17 @@
.form-fields,
.char-count {
display: none;
- min-width: 100px;
+ min-width: pxToRem(100);
}
.form-control-day,
.form-control-month,
.form-control-year {
- margin-right: 10px;
+ margin-right: pxToRem(10);
float: left;
.form-control {
- width: 50px;
+ width: pxToRem(50);
text-align: center;
}
}
@@ -286,13 +283,13 @@
.form-control-day,
.form-control-month {
.form-control {
- min-width: 50px;
+ min-width: pxToRem(50);
}
}
.form-control-year {
.form-control {
- min-width: 70px;
+ min-width: pxToRem(70);
}
}
@@ -329,7 +326,7 @@
}
.form-container {
- padding: 10px;
+ padding: pxToRem(10);
background: $grey-lighter;
.char-count.char-max-shift {
@@ -338,7 +335,7 @@
}
.form-group-multiple-parent {
- margin-bottom: 15px;
+ margin-bottom: pxToRem(15);
&:last-child {
margin-bottom: 0;
@@ -366,25 +363,25 @@
}
.form-edit-link {
- margin-top: 10px;
+ margin-top: pxToRem(10);
color: $black;
- font-size: 16px;
+ font-size: pxToRem(16);
.glyphicon {
- margin-right: 5px;
- font-size: 12px;
+ margin-right: pxToRem(5);
+ font-size: pxToRem(12);
}
}
.show-sidebar {
.form-save-button,
.form-save-link {
- margin-top: 10px;
+ margin-top: pxToRem(10);
}
ul.other-applications-list {
li {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
}
}
}
@@ -397,22 +394,22 @@
h2 {
margin-top: 0;
- margin-bottom: 10px;
- font-size: 24px;
+ margin-bottom: pxToRem(10);
+ font-size: pxToRem(24);
font-weight: normal;
text-transform: none;
}
p {
- font-size: 18px;
+ font-size: pxToRem(18);
@include screen-md-max {
- font-size: 16px;
+ font-size: pxToRem(16);
}
}
.btn {
- margin-top: 20px;
+ margin-top: pxToRem(20);
}
}
@@ -420,35 +417,35 @@
h2,
p {
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
}
p {
- font-size: 15px;
+ font-size: pxToRem(15);
&.p-lg {
- font-size: 20px;
+ font-size: pxToRem(20);
}
}
.btn-group {
display: block;
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
}
.dropdown-toggle {
display: inline-block;
padding: 0;
- padding-right: 20px;
+ padding-right: pxToRem(20);
float: none;
color: $black;
- font-size: 20px;
+ font-size: pxToRem(20);
text-align: left;
text-decoration: none;
background-image: image-url("icon-arrow-admin-dropdown-down.png");
background-repeat: no-repeat;
background-position: right center;
- background-size: 12px 9px;
+ background-size: pxToRem(12) pxToRem(9);
@include is-retina {
background-image: image-url("icon-arrow-admin-dropdown-down@2.png");
@@ -464,12 +461,11 @@
}
.state-container {
- position: relative;
+ display: flex;
+ justify-content: space-between;
h2 {
- position: absolute;
- top: 0.4em;
- left: 0;
+ margin-top: 0.35rem;
@include screen-lg-max {
position: static;
@@ -501,7 +497,7 @@
li {
position: relative;
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
clear: both;
&:last-child {
@@ -511,7 +507,7 @@
label {
display: block;
- font-size: 14px;
+ font-size: pxToRem(14);
font-weight: bold;
text-transform: uppercase;
}
@@ -526,7 +522,7 @@
@include screen-md-max {
width: auto;
- margin-left: 120px;
+ margin-left: pxToRem(120);
}
}
@@ -543,15 +539,15 @@
top: 0;
right: 0;
margin-top: 0;
- font-size: 14px;
+ font-size: pxToRem(14);
.lte-ie7 & {
- margin-top: -20px;
+ margin-top: pxToRem(-20);
}
}
.form-save-button {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
float: right;
clear: both;
}
@@ -561,10 +557,17 @@
display: inline;
}
}
+
+ .alert ~ form > .form-edit-link {
+ display: flex;
+ float: right;
+ margin-top: pxToRem(-54);
+ position: relative;
+ }
}
.centered {
- padding-left: 25px;
+ padding-left: pxToRem(25);
}
.audit-cert-no-change-val,
@@ -589,13 +592,13 @@
}
.form-group .list-attendees li .row {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
}
.bulk-assign-assessors-link {
position: relative;
- left: -9999px;
- margin-top: 10px;
+ left: pxToRem(-9999);
+ margin-top: pxToRem(10);
background-color: $blue-link-colour;
color: white;
@@ -603,6 +606,12 @@
left: 0;
}
+ &:hover {
+ color: #fff;
+ background-color: $govuk-light-blue;
+ border-color: #204d74
+ }
+
.show-bulk-assign & {
.js & {
display: none;
@@ -611,9 +620,9 @@
}
.bulk-assign-assessors-form {
- max-width: 755px;
- margin-top: 25px;
- margin-bottom: 10px;
+ max-width: pxToRem(755);
+ margin-top: pxToRem(25);
+ margin-bottom: pxToRem(10);
.js & {
display: none;
@@ -626,7 +635,7 @@
}
h2 {
- font-size: 18px;
+ font-size: pxToRem(18);
font-weight: bold;
line-height: 1.5;
}
@@ -640,7 +649,7 @@
}
.btn {
- margin-left: 10px;
+ margin-left: pxToRem(10);
}
.well {
@@ -670,7 +679,7 @@
zoom: 1;
.form-group {
- margin-top: 15px;
+ margin-top: pxToRem(15);
.form-control {
display: block;
diff --git a/app/assets/stylesheets/admin/page-custom-emails.scss b/app/assets/stylesheets/admin/page-custom-emails.scss
index 0e534cae6..20363b445 100644
--- a/app/assets/stylesheets/admin/page-custom-emails.scss
+++ b/app/assets/stylesheets/admin/page-custom-emails.scss
@@ -1,3 +1,5 @@
+@import "pxToRem";
+
.email-send-to,
.email-send-subject {
h3 {
@@ -6,11 +8,11 @@
}
.email-send-to {
- margin-top: 40px;
+ margin-top: pxToRem(40);
}
.email-send-subject {
- margin-top: 20px;
+ margin-top: pxToRem(20);
}
.email-send-to-help {
diff --git a/app/assets/stylesheets/admin/page-dashboard.scss b/app/assets/stylesheets/admin/page-dashboard.scss
index bab4e9feb..3c6a65a86 100644
--- a/app/assets/stylesheets/admin/page-dashboard.scss
+++ b/app/assets/stylesheets/admin/page-dashboard.scss
@@ -1,6 +1,4 @@
-.dashboard {
-
-}
+@import "pxToRem";
.download-link {
display: inline-block;
@@ -11,8 +9,8 @@
&:before {
content: " ";
display: block;
- width: 18px;
- height: 16px;
+ width: pxToRem(18);
+ height: pxToRem(16);
background-image: image-url("icon_download.svg");
background-repeat: no-repeat;
background-size: 100% auto;
@@ -20,7 +18,7 @@
position: absolute;
left: 0;
- top: 2px;
+ top: pxToRem(2);
}
}
@@ -32,15 +30,11 @@
.award-year-label {
text-transform: none !important;
display: block;
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
position: static;
font-weight: normal;
margin-top: 0;
- font-size: 18px;
- }
-
- .award-year-dropdown {
- margin: 0 !important;
+ font-size: pxToRem(18);
}
}
@@ -48,7 +42,7 @@
margin-top: 2em;
color: $blue-link-colour;
- @media (min-width: 992px) {
+ @media (min-width: pxToRem(992)) {
margin-top: 0;
position: absolute !important;
top: 1.5em;
@@ -75,7 +69,7 @@
.dashboard__section {
padding: 2em 0;
- border-top: 2px solid #ccc;
+ border-top: pxToRem(2) solid #ccc;
position: relative;
}
@@ -89,8 +83,8 @@
content: " ";
display: block;
position: absolute;
- top: 9px;
- left: 10px;
+ top: pxToRem(9);
+ left: pxToRem(10);
background-size: 1em auto;
background-repeat: no-repeat;
background-position: center;
@@ -98,7 +92,7 @@
height: 1em;
}
- @media (min-width: 768px) {
+ @media (min-width: pxToRem(768)) {
position: absolute;
right: 0;
top: 3em;
@@ -108,26 +102,44 @@
opacity: 0.7;
}
- &.btn--load:before {
- background-image: image-url("icon_load.svg");
+ &.btn--load {
+
+ &:before {
+ background-image: image-url("icon_load.svg");
+ }
+
+ &:focus:before {
+ background-image: image-url("icon_load_black.svg");
+ }
}
- &.btn--reload:before {
- background-image: image-url("icon_update.svg");
+ &.btn--reload {
+ &:before {
+ background-image: image-url("icon_update.svg");
+ }
+
+ &:focus:before {
+ background-image: image-url("icon_update_black.svg");
+ }
}
- &.btn--loading:before {
- background-image: image-url("icon_loading.svg");
- background-size: 1.15em auto;
- width: 1.2em;
- height: 1.5em;
- top: 7px;
+ &.btn--loading {
+ &:before {
+ background-image: image-url("icon_loading.svg");
+ background-size: 1.15em auto;
+ width: 1.2em;
+ height: 1.5em;
+ top: pxToRem(7);
+ }
+
+ &:focus:before {
+ background-image: image-url("icon_loading_black.svg");
+ }
}
}
}
.dashboard-table {
- table-layout: fixed;
overflow-x: scroll;
border-collapse: collapse;
@@ -152,22 +164,22 @@
position: relative;
font-weight: bold;
- @media (min-width: 768px) {
- padding-right: 200px;
+ @media (min-width: pxToRem(768)) {
+ padding-right: pxToRem(200);
}
&:before {
content: " ";
display: block;
- width: 23px;
- height: 23px;
+ width: pxToRem(23);
+ height: pxToRem(23);
background-image: image-url("icon_warning.svg");
background-size: 100% auto;
background-position: center;
background-repeat: no-repeat;
position: absolute;
left: 0;
- top: -1px;
+ top: pxToRem(-1);
}
}
}
@@ -184,7 +196,7 @@
}
&.border-right {
- border-right: 2px solid black;
+ border-right: pxToRem(2) solid black;
}
}
@@ -203,7 +215,7 @@
tbody {
th {
padding: 0.5em 1em;
- border-right: 2px solid black;
+ border-right: pxToRem(2) solid black;
font-weight: normal;
}
td {
@@ -219,11 +231,11 @@
}
.dashboard-table--small {
- font-size: 14px;
+ font-size: pxToRem(14);
th {
- font-size: 12px;
- padding: 1em 3px !important;
+ font-size: pxToRem(12);
+ padding: 1em pxToRem(3) !important;
}
td {
@@ -231,12 +243,12 @@
}
thead tr:first-of-type th {
- padding-top: 2px !important;
+ padding-top: pxToRem(2) !important;
}
}
.dashboard-table__wrapper {
- @media (max-width: 1199px) {
+ @media (max-width: pxToRem(1199)) {
overflow-x: scroll;
}
}
@@ -249,7 +261,7 @@
.downloads-page__section {
h2 {
- font-size: 24px;
+ font-size: pxToRem(24);
font-weight: bold;
color: black;
}
@@ -263,13 +275,13 @@
li {
padding: 1.2em 0 1.2em 1.5em;
position: relative;
- border-bottom: 1px solid #ccc;
+ border-bottom: pxToRem(1) solid #ccc;
&:before {
content: " ";
display: block;
- width: 11px;
- height: 20px;
+ width: pxToRem(11);
+ height: pxToRem(20);
background-image: image-url("icon_file.svg");
background-repeat: no-repeat;
background-size: 100% auto;
@@ -285,7 +297,7 @@
margin-top: 1.5em;
color: $blue-link-colour;
- @media (min-width: 992px) {
+ @media (min-width: pxToRem(992)) {
margin-top: 0;
position: absolute;
top: 1.2em;
@@ -297,19 +309,19 @@
color: black;
font-size: 1.11111em;
- @media (min-width: 992px) {
- margin-right: 200px;
+ @media (min-width: pxToRem(992)) {
+ margin-right: pxToRem(200);
}
}
.download-item__description {
font-size: 1.11111em;
- max-width: 700px;
+ max-width: pxToRem(700);
margin-bottom: 0;
color: $grey-panel-dark;
- @media (min-width: 992px) {
- margin-right: 200px;
+ @media (min-width: pxToRem(992)) {
+ margin-right: pxToRem(200);
}
}
}
diff --git a/app/assets/stylesheets/admin/page-feedback.scss b/app/assets/stylesheets/admin/page-feedback.scss
index ef510af40..e53e687d8 100644
--- a/app/assets/stylesheets/admin/page-feedback.scss
+++ b/app/assets/stylesheets/admin/page-feedback.scss
@@ -1,10 +1,12 @@
+@import "pxToRem";
+
.feedback-stars {
white-space: nowrap;
}
.feedback-description,
.feedback-table .read-more-container {
- font-size: 14px;
+ font-size: pxToRem(14);
}
.read-more-container {
diff --git a/app/assets/stylesheets/admin/page-settings.scss b/app/assets/stylesheets/admin/page-settings.scss
index da82ee915..12781189f 100644
--- a/app/assets/stylesheets/admin/page-settings.scss
+++ b/app/assets/stylesheets/admin/page-settings.scss
@@ -1,10 +1,12 @@
+@import "pxToRem";
+
.settings-page {
.panel-body ul {
margin: 0;
padding-left: 1.25em;
li {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
&:last-child {
margin-bottom: 0;
@@ -13,8 +15,8 @@
}
.panel-section {
- padding: 15px 0;
- border-bottom: 1px solid $grey;
+ padding: pxToRem(15) 0;
+ border-bottom: pxToRem(1) solid $grey;
&:first-child {
padding-top: 0;
@@ -33,7 +35,7 @@
@include screen-sm-max {
display: inline;
width: auto;
- margin-right: 10px;
+ margin-right: pxToRem(10);
}
}
@@ -42,13 +44,13 @@
}
.edit-deadline {
- margin-right: 10px;
+ margin-right: pxToRem(10);
color: $blue-link-colour;
text-decoration: underline;
}
.email-notification-help {
- margin-left: 10px;
+ margin-left: pxToRem(10);
}
.deadline-help, .email-notification-help {
@@ -58,10 +60,10 @@
.help-message {
position: absolute;
- top: -13px;
+ top: pxToRem(-13);
left: 0;
- width: 15px;
- height: 15px;
+ width: pxToRem(15);
+ height: pxToRem(15);
display: inline-block;
&:hover .help-message-text {
@@ -71,21 +73,21 @@
.help-message-text {
position: absolute;
z-index: 1;
- top: -5px;
+ top: pxToRem(-5);
left: 105%;
visibility: hidden;
background-color: #fff;
text-align: center;
- padding: 5px;
- width: 300px;
- border: 1px solid #ccc;
- border-radius: 6px;
+ padding: pxToRem(5);
+ width: pxToRem(300);
+ border: pxToRem(1) solid #ccc;
+ border-radius: pxToRem(6);
}
}
}
.btn-add-schedule {
- margin: 20px 0;
+ margin: pxToRem(20) 0;
}
.link-email-example {
@@ -95,8 +97,8 @@
.well {
display: block;
- max-width: 440px;
- margin: 20px 0;
+ max-width: pxToRem(440);
+ margin: pxToRem(20) 0;
background-color: $white-true;
box-shadow: none;
@@ -108,6 +110,7 @@
max-width: none;
a {
text-decoration: underline;
+ overflow-wrap: break-word;
}
}
@@ -125,7 +128,7 @@
}
.control-date {
- margin-right: 20px;
+ margin-right: pxToRem(20);
@include screen-sm-max {
margin-right: 0;
@@ -137,7 +140,7 @@
}
.control-hint {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
display: inline-block;
}
@@ -155,7 +158,7 @@
}
&:first-child {
- margin-right: 10px;
+ margin-right: pxToRem(10);
@include screen-sm-max {
margin-right: 0;
@@ -165,14 +168,14 @@
.btn-submit {
@include screen-sm-max {
- margin-bottom: 45px;
+ margin-bottom: pxToRem(45);
}
}
.btn-cancel {
@include screen-sm-max {
position: absolute;
- top: 45px;
+ top: pxToRem(45);
}
}
}
@@ -203,14 +206,14 @@
border: none;
.lte-ie7 & {
- font-size: 16px;
+ font-size: pxToRem(16);
}
}
}
}
.deadline-form-wrapper {
- @media (min-width: 768px) {
+ @media (min-width: pxToRem(768)) {
&:after {
clear: both;
content: " ";
diff --git a/app/assets/stylesheets/admin/page-users.scss b/app/assets/stylesheets/admin/page-users.scss
index cac748aa0..12da9e6c8 100644
--- a/app/assets/stylesheets/admin/page-users.scss
+++ b/app/assets/stylesheets/admin/page-users.scss
@@ -1,3 +1,5 @@
+@import "pxToRem";
+
.form-collaborator {
.well {
display: none;
@@ -34,11 +36,11 @@
}
.js-admin-search-collaborators-error-box {
- margin-bottom: 10px;
+ margin-bottom: pxToRem(10);
}
.js-admin-search-collaborators-results-box {
- margin-bottom: 20px;
+ margin-bottom: pxToRem(20);
}
.cant_add_to_collaborators_message {
@@ -46,26 +48,26 @@
}
.admin-user-debounce-api-check-block {
- padding-left: 25px;
- font-size: 14px;
+ padding-left: pxToRem(25);
+ font-size: pxToRem(14);
.heading-message {
- margin-bottom: 5px;
+ margin-bottom: pxToRem(5);
display: inline-block;
}
img {
- width: 20px;
- height: 20px;
- margin-right: 10px;
+ width: pxToRem(20);
+ height: pxToRem(20);
+ margin-right: pxToRem(10);
}
.next-run-info {
- margin-top: 7px;
+ margin-top: pxToRem(7);
display: inline-block;
}
a {
- margin-top: 7px;
+ margin-top: pxToRem(7);
}
-}
\ No newline at end of file
+}
diff --git a/app/assets/stylesheets/application-admin.scss b/app/assets/stylesheets/application-admin.scss
index 1a4466fc7..557769c28 100644
--- a/app/assets/stylesheets/application-admin.scss
+++ b/app/assets/stylesheets/application-admin.scss
@@ -15,6 +15,7 @@ $button-colour: #00823b;
@import "frontend/password_guidance";
@import "frontend/status";
+@import "admin/bootstrap-overrides";
@import "admin/variables";
@import "admin/toggle";
@import "admin/layout";
@@ -59,6 +60,5 @@ $todo-black: #333;
&:focus {
top: 20px;
left: 20px;
- color: white !important;
}
}
diff --git a/app/assets/stylesheets/frontend/layout.scss b/app/assets/stylesheets/frontend/layout.scss
index 34ad63f11..769a92fa3 100644
--- a/app/assets/stylesheets/frontend/layout.scss
+++ b/app/assets/stylesheets/frontend/layout.scss
@@ -628,6 +628,7 @@ header.page-header aside .inner {
&.sidebar-helpline {
a {
text-decoration: underline;
+ overflow-wrap: break-word;
}
}
}
diff --git a/app/controllers/admin/admins_controller.rb b/app/controllers/admin/admins_controller.rb
index 65753238b..d33e05489 100644
--- a/app/controllers/admin/admins_controller.rb
+++ b/app/controllers/admin/admins_controller.rb
@@ -20,7 +20,7 @@ def create
@resource.save
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
location = @resource.persisted? ? admin_admins_path : nil
respond_with :admin, @resource, location: location
@@ -35,7 +35,7 @@ def update
@resource.update_without_password(resource_params)
end
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_admins_path
end
@@ -44,7 +44,7 @@ def destroy
authorize @resource, :destroy?
@resource.soft_delete!
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_admins_path
end
diff --git a/app/controllers/admin/assessors_controller.rb b/app/controllers/admin/assessors_controller.rb
index f41faa68b..7408e8cb0 100644
--- a/app/controllers/admin/assessors_controller.rb
+++ b/app/controllers/admin/assessors_controller.rb
@@ -21,7 +21,7 @@ def create
@resource.save
location = @resource.persisted? ? admin_assessors_path : nil
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: location
end
@@ -35,7 +35,7 @@ def update
@resource.update_without_password(resource_params)
end
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_assessors_path
end
@@ -44,7 +44,7 @@ def destroy
authorize @resource, :destroy?
@resource.soft_delete!
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_assessors_path
end
diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb
index 8ea7ef5bc..43d10a6c4 100644
--- a/app/controllers/admin/base_controller.rb
+++ b/app/controllers/admin/base_controller.rb
@@ -22,7 +22,7 @@ def current_subject
def render_flash_message_for(resource, message: nil)
if resource.errors.any?
- flash[:error] = message || "An unknown error has occurred, please try again."
+ flash.now[:error] = message || "An unknown error has occurred, please try again."
else
flash[:notice] = message || "Success!"
end
diff --git a/app/controllers/admin/custom_emails_controller.rb b/app/controllers/admin/custom_emails_controller.rb
index 438461a96..49e1be858 100644
--- a/app/controllers/admin/custom_emails_controller.rb
+++ b/app/controllers/admin/custom_emails_controller.rb
@@ -14,7 +14,7 @@ def create
@form = CustomEmailForm.new(custom_email_form_attributes)
if @form.valid?
- CustomEmailWorker.perform_async(custom_email_form_attributes)
+ CustomEmailForm.new(custom_email_form_attributes.permit!.to_h.with_indifferent_access).send!
render_flash_message_for(@form)
redirect_to admin_custom_email_path, notice: "Email was successfully scheduled"
else
diff --git a/app/controllers/admin/dashboard_reports_controller.rb b/app/controllers/admin/dashboard_reports_controller.rb
index 432a3fcf0..8e0133b1d 100644
--- a/app/controllers/admin/dashboard_reports_controller.rb
+++ b/app/controllers/admin/dashboard_reports_controller.rb
@@ -10,44 +10,56 @@ class Admin::DashboardReportsController < Admin::BaseController
# that represents the type of the application
def all_applications
- authorize :dashboard, :reports?
-
- @report = Reports::Dashboard::ApplicationsReport.new(kind: params[:kind])
- render partial: "admin/dashboard/totals_#{params[:kind]}/table_body"
+ render_or_download_report nil, params[:kind], params[:format]
end
def international_trade
- authorize :dashboard, :reports?
-
- @report = Reports::Dashboard::ApplicationsReport.new(kind: params[:kind], award_type: :trade)
- render partial: "admin/dashboard/totals_#{params[:kind]}/table_body"
+ render_or_download_report :trade, params[:kind], params[:format]
end
def innovation
- authorize :dashboard, :reports?
-
- @report = Reports::Dashboard::ApplicationsReport.new(kind: params[:kind], award_type: :innovation)
- render partial: "admin/dashboard/totals_#{params[:kind]}/table_body"
+ render_or_download_report :innovation, params[:kind], params[:format]
end
def social_mobility
- authorize :dashboard, :reports?
-
- @report = Reports::Dashboard::ApplicationsReport.new(kind: params[:kind], award_type: :mobility)
- render partial: "admin/dashboard/totals_#{params[:kind]}/table_body"
+ render_or_download_report :mobility, params[:kind], params[:format]
end
def sustainable_development
- authorize :dashboard, :reports?
-
- @report = Reports::Dashboard::ApplicationsReport.new(kind: params[:kind], award_type: :development)
- render partial: "admin/dashboard/totals_#{params[:kind]}/table_body"
+ render_or_download_report :development, params[:kind], params[:format]
end
def account_registrations
authorize :dashboard, :reports?
@report = Reports::Dashboard::UsersReport.new(kind: params[:kind])
- render partial: "admin/dashboard/totals_#{params[:kind]}/users_table_body"
+
+ respond_to do |format|
+ format.csv do
+ send_data @report.as_csv, filename: @report.csv_filename
+ end
+
+ format.html do
+ render partial: "admin/dashboard/totals_#{params[:kind]}/users_table_body"
+ end
+ end
+ end
+
+ private
+
+ def render_or_download_report award_type, kind, format
+ authorize :dashboard, :reports?
+
+ @report = Reports::Dashboard::ApplicationsReport.new(kind: kind, award_type: award_type)
+
+ respond_to do |format|
+ format.csv do
+ send_data @report.as_csv, filename: @report.csv_filename
+ end
+
+ format.html do
+ render partial: "admin/dashboard/totals_#{kind}/table_body"
+ end
+ end
end
end
diff --git a/app/controllers/admin/judges_controller.rb b/app/controllers/admin/judges_controller.rb
index 5ee3060f8..3f174d28f 100644
--- a/app/controllers/admin/judges_controller.rb
+++ b/app/controllers/admin/judges_controller.rb
@@ -21,7 +21,7 @@ def create
@resource.save
location = @resource.persisted? ? admin_judges_path : nil
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: location
end
@@ -35,7 +35,7 @@ def update
@resource.update_without_password(resource_params)
end
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_judges_path
end
@@ -44,7 +44,7 @@ def destroy
authorize @resource, :destroy?
@resource.soft_delete!
- render_flash_message_for(@resource)
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_judges_path
end
diff --git a/app/controllers/admin/reports_controller.rb b/app/controllers/admin/reports_controller.rb
index 3c32cae33..ac21e9a4a 100644
--- a/app/controllers/admin/reports_controller.rb
+++ b/app/controllers/admin/reports_controller.rb
@@ -30,7 +30,7 @@ def show
type: "application/pdf",
disposition: 'attachment'
else
- redirect_to pdf.data
+ redirect_to pdf.data, allow_other_host: true
end
end
end
diff --git a/app/controllers/admin/session_checks_controller.rb b/app/controllers/admin/session_checks_controller.rb
index 0a0510a67..5ba9cc867 100644
--- a/app/controllers/admin/session_checks_controller.rb
+++ b/app/controllers/admin/session_checks_controller.rb
@@ -1,6 +1,18 @@
class Admin::SessionChecksController < ActionController::Base
include SessionStatusCheckMixin
+ def show
+ if session_is_valid?
+ render json: { elapsed: elapsed }, status: :ok
+ else
+ head :unauthorized
+ end
+ end
+
+ def extend
+ super
+ end
+
private
def namespace
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index b42612ab4..da90ff36a 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -28,7 +28,7 @@ def create
@resource.save
location = @resource.persisted? ? admin_users_path : nil
- render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.full_messages.join(", "))
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: location
end
@@ -42,7 +42,7 @@ def update
@resource.update_without_password(resource_params)
end
- render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.full_messages.join(", "))
+ render_flash_message_for(@resource, message: @resource.errors.none? ? nil : @resource.errors.messages.values.flatten.uniq.join("
"))
respond_with :admin, @resource, location: admin_users_path
end
diff --git a/app/controllers/assessor/base_controller.rb b/app/controllers/assessor/base_controller.rb
index c1bfb1560..1fd0b17de 100644
--- a/app/controllers/assessor/base_controller.rb
+++ b/app/controllers/assessor/base_controller.rb
@@ -21,7 +21,7 @@ def current_subject
def render_flash_message_for(resource, message: nil)
if resource.errors.any?
- flash[:error] = message || "An unknown error has occurred, please try again."
+ flash.now[:error] = message || "An unknown error has occurred, please try again."
else
flash[:notice] = message || "Success!"
end
diff --git a/app/controllers/assessor/reports_controller.rb b/app/controllers/assessor/reports_controller.rb
index d5cd7fa90..3b68cae27 100644
--- a/app/controllers/assessor/reports_controller.rb
+++ b/app/controllers/assessor/reports_controller.rb
@@ -24,7 +24,7 @@ def show
type: "application/pdf",
disposition: 'attachment'
else
- redirect_to pdf.data
+ redirect_to pdf.data, allow_other_host: true
end
end
end
diff --git a/app/controllers/assessor/session_checks_controller.rb b/app/controllers/assessor/session_checks_controller.rb
index fe2f0f382..9f56f9fc4 100644
--- a/app/controllers/assessor/session_checks_controller.rb
+++ b/app/controllers/assessor/session_checks_controller.rb
@@ -1,6 +1,18 @@
class Assessor::SessionChecksController < ActionController::Base
include SessionStatusCheckMixin
+ def show
+ if session_is_valid?
+ render json: { elapsed: elapsed }, status: :ok
+ else
+ head :unauthorized
+ end
+ end
+
+ def extend
+ super
+ end
+
private
def namespace
diff --git a/app/controllers/concerns/admin_shortlisted_docs_submission_context.rb b/app/controllers/concerns/admin_shortlisted_docs_submission_context.rb
index e3ddf4706..bd0bc7d84 100644
--- a/app/controllers/concerns/admin_shortlisted_docs_submission_context.rb
+++ b/app/controllers/concerns/admin_shortlisted_docs_submission_context.rb
@@ -2,7 +2,17 @@ module AdminShortlistedDocsSubmissionContext
def create
authorize resource, :submit?
- resource.submitted? ? resource.uncomplete : resource.complete
+ if resource.submitted?
+ resource.uncomplete
+ else
+ if resource.complete
+ if form_answer.assessors.primary.present?
+ Assessors::GeneralMailer.vat_returns_submitted(form_answer.id).deliver_later!
+ end
+
+ Users::CommercialFiguresMailer.notify(form_answer.id, form_answer.account.owner_id).deliver_later!
+ end
+ end
respond_to do |format|
format.html do
@@ -29,7 +39,7 @@ def resource
@resource ||= (form_answer.shortlisted_documents_wrapper || form_answer.build_shortlisted_documents_wrapper)
return @resource if @resource.persisted?
-
+
@resource.save!
@resource
end
diff --git a/app/controllers/concerns/assessment_submission_mixin.rb b/app/controllers/concerns/assessment_submission_mixin.rb
index 86b97f58e..3f4bf3380 100644
--- a/app/controllers/concerns/assessment_submission_mixin.rb
+++ b/app/controllers/concerns/assessment_submission_mixin.rb
@@ -19,6 +19,7 @@ def unlock
resource.update_column(:locked_at, nil)
log_event
+ render_flash_message_for(resource, message: flash_message)
redirect_to [namespace_name, resource.form_answer]
end
@@ -36,7 +37,7 @@ def form_answer
def flash_message
return nil if resource.errors.none?
- resource.errors.full_messages.join(", ")
+ resource.errors.full_messages.join("
")
end
def json_response
diff --git a/app/controllers/concerns/audit_certificate_context.rb b/app/controllers/concerns/audit_certificate_context.rb
index ab858e206..0166b5071 100644
--- a/app/controllers/concerns/audit_certificate_context.rb
+++ b/app/controllers/concerns/audit_certificate_context.rb
@@ -1,7 +1,7 @@
module AuditCertificateContext
def show
authorize form_answer, :download_audit_certificate_pdf?
- redirect_to resource.attachment_url
+ redirect_to resource.attachment_url, allow_other_host: true
end
def create
diff --git a/app/controllers/concerns/palace_attendees_mixin.rb b/app/controllers/concerns/palace_attendees_mixin.rb
index 3d2ffafdd..7ed8d9fe4 100644
--- a/app/controllers/concerns/palace_attendees_mixin.rb
+++ b/app/controllers/concerns/palace_attendees_mixin.rb
@@ -3,13 +3,15 @@ def new
invite = PalaceInvite.find(params[:palace_invite_id])
@enable_edition = true
@form_answer = invite.form_answer
- authorize @form_answer, :update?
+ authorize invite, :update?
palace_attendee = invite.palace_attendees.build
render_attendee_form(palace_attendee, invite)
end
def create
- authorize form_answer, :update?
+ form_answer
+
+ authorize palace_invite, :update?
limit = palace_invite.attendees_limit
if palace_invite.palace_attendees.count < limit
palace_attendee = palace_invite.palace_attendees.create(create_params)
@@ -21,7 +23,9 @@ def create
end
def update
- authorize form_answer, :update?
+ form_answer
+
+ authorize palace_invite, :update?
palace_attendee = palace_invite.palace_attendees.find(params[:id])
log_event if palace_attendee.update(create_params)
@@ -29,7 +33,7 @@ def update
end
def destroy
- authorize form_answer, :update?
+ authorize palace_invite, :update?
palace_attendee = palace_invite.palace_attendees.find(params[:id])
log_event if palace_attendee.destroy
respond_to do |format|
diff --git a/app/controllers/concerns/palace_invites_mixin.rb b/app/controllers/concerns/palace_invites_mixin.rb
index acd1d614f..e46264924 100644
--- a/app/controllers/concerns/palace_invites_mixin.rb
+++ b/app/controllers/concerns/palace_invites_mixin.rb
@@ -1,7 +1,7 @@
module PalaceInvitesMixin
def submit
@invite = PalaceInvite.find(params[:id])
- authorize @invite.form_answer, :update?
+ authorize @invite, :update?
@invite.submit!
diff --git a/app/controllers/concerns/session_status_check_mixin.rb b/app/controllers/concerns/session_status_check_mixin.rb
index 88ed65014..b0c63e07c 100644
--- a/app/controllers/concerns/session_status_check_mixin.rb
+++ b/app/controllers/concerns/session_status_check_mixin.rb
@@ -19,6 +19,10 @@ def show
end
end
+ def extend
+ render json: { elapsed: elapsed }, status: :ok
+ end
+
private
def skip_timeout
@@ -34,4 +38,19 @@ def session_is_valid?
judge_signed_in?
end
end
+
+ def now
+ Time.now.in_time_zone("UTC")
+ end
+
+ def elapsed
+ session = if namespace == ADMIN_NAMESPACE
+ admin_session
+ elsif namespace == ASSESSOR_NAMESPACE
+ assessor_session
+ elsif namespace == JUDGE_NAMESPACE
+ judge_session
+ end
+ (now - (session["last_request_at"] || params['__t'].to_i)).to_i / 1.minutes
+ end
end
diff --git a/app/controllers/judge/case_summaries_controller.rb b/app/controllers/judge/case_summaries_controller.rb
index 336b40158..c8debdf5d 100644
--- a/app/controllers/judge/case_summaries_controller.rb
+++ b/app/controllers/judge/case_summaries_controller.rb
@@ -16,7 +16,7 @@ def download
type: "application/pdf",
disposition: 'attachment'
else
- redirect_to pdf.data
+ redirect_to pdf.data, allow_other_host: true
end
end
end
diff --git a/app/controllers/judge/session_checks_controller.rb b/app/controllers/judge/session_checks_controller.rb
index 946c19527..ad9a5b962 100644
--- a/app/controllers/judge/session_checks_controller.rb
+++ b/app/controllers/judge/session_checks_controller.rb
@@ -1,6 +1,18 @@
class Judge::SessionChecksController < ActionController::Base
include SessionStatusCheckMixin
+ def show
+ if session_is_valid?
+ render json: { elapsed: elapsed }, status: :ok
+ else
+ head :unauthorized
+ end
+ end
+
+ def extend
+ super
+ end
+
private
def namespace
diff --git a/app/controllers/users/form_answers_controller.rb b/app/controllers/users/form_answers_controller.rb
index 1a704f9d9..8825a9b41 100644
--- a/app/controllers/users/form_answers_controller.rb
+++ b/app/controllers/users/form_answers_controller.rb
@@ -71,7 +71,7 @@ def can_render_pdf_on_fly?
def render_hard_copy_pdf
if form_answer.pdf_version.present?
- redirect_to form_answer.pdf_version.url
+ redirect_to form_answer.pdf_version.url, allow_other_host: true
else
if !admin_in_read_only_mode?
redirect_to dashboard_path,
diff --git a/app/helpers/form_answer_helper.rb b/app/helpers/form_answer_helper.rb
index c5195cccf..7bbfe8b12 100644
--- a/app/helpers/form_answer_helper.rb
+++ b/app/helpers/form_answer_helper.rb
@@ -37,7 +37,8 @@ def application_flags(fa, subject = nil)
if comments_count > 0
content_tag :span, class: "icon-flagged #{flag_type}" do
- content_tag :span, class: "flag-count" do
+ "#{current_user_class} flags: ".html_safe +
+ content_tag(:span, class: "flag-count") do
comments_count.to_s
end
end
diff --git a/app/helpers/winners_awards_helper.rb b/app/helpers/winners_awards_helper.rb
index 4c1bd031e..1baad0e05 100644
--- a/app/helpers/winners_awards_helper.rb
+++ b/app/helpers/winners_awards_helper.rb
@@ -1,7 +1,8 @@
module WinnersAwardsHelper
def static_s3_asset_path(year, file_name)
file_path = "winners assets #{year}/#{file_name}"
- URI.encode("https://s3-eu-west-1.amazonaws.com/qae-winners-assets/#{file_path}")
+
+ "https://s3-eu-west-1.amazonaws.com/qae-winners-assets/#{CGI.escape(file_path)}"
end
end
diff --git a/app/javascript/controllers/appraisal_form_controller.js b/app/javascript/controllers/appraisal_form_controller.js
new file mode 100644
index 000000000..82082b63a
--- /dev/null
+++ b/app/javascript/controllers/appraisal_form_controller.js
@@ -0,0 +1,211 @@
+import { scrollToElement } from '../helpers';
+
+export default class extends ApplicationController {
+ static values = {
+ success: String,
+ };
+
+ connect() {}
+
+ success(event) {
+ return this.handleSuccess(event);
+ }
+
+ error(event) {
+ return this.handleError(event);
+ }
+
+ handleSuccess = ({ target }) => {
+ const panel = target.closest('.panel-body');
+
+ this.resetErrors(panel);
+
+ const message = this.hasSuccessValue ? this.successValue : 'Success!';
+ const [alert, identifier] = this.createAlert('success', message);
+
+ panel.insertAdjacentHTML('afterbegin', alert);
+
+ const template = this.element.querySelector('[data-role=template]');
+
+ if ('content' in template) {
+ const replacement = template.content.cloneNode(true);
+ target.replaceWith(replacement.firstChild);
+ } else {
+ target.remove();
+ }
+ };
+
+ handleError = (event) => {
+ const {
+ target,
+ detail: { responseJSON: errors },
+ } = event;
+ const panel = target.closest('.panel-body');
+ let form;
+
+ this.resetErrors(panel);
+
+ Object.entries(errors).forEach(([key, values]) => {
+ const field = panel.querySelector(`[name*='[${key}]']`);
+ if (!form) {
+ form = field.closest('form');
+ }
+ const container = field.closest('.form-container');
+
+ if (field && this.shouldValidateField(field)) {
+ this.showFieldErrors(field, values);
+ }
+
+ if (key && key.endsWith('_rate')) {
+ const button = container.querySelector('label button');
+ if (button) button.classList.add('rag-error');
+ } else {
+ if (!this.visible(field)) {
+ const target = container.querySelector('.form-edit-link');
+ if (target) $(target).trigger('click');
+ }
+ }
+ });
+
+ const firstInvalidField = Array.from(form.elements).find((field) => field.ariaInvalid == 'true');
+
+ if (this.visible(firstInvalidField)) {
+ scrollToElement(firstInvalidField);
+ firstInvalidField.focus();
+ } else {
+ const altTarget = firstInvalidField.closest('.form-container').querySelector('label button');
+ if (altTarget) {
+ scrollToElement(altTarget);
+ altTarget.focus();
+ }
+ }
+ };
+
+ stash = (event) => {
+ event.preventDefault();
+ event.stopPropagation();
+
+ const { target: button } = event;
+ const wrapper = button.closest('.form-group');
+ const form = wrapper.closest('form');
+ const textarea = Array.from(wrapper.querySelectorAll('textarea')).filter(this.visible);
+
+ if (textarea.length > 1) {
+ for (let idx = 0; idx < textarea.length; idx++) {
+ LS.removeItem(textarea[idx].dataset.autosaveKey);
+ }
+ } else {
+ LS.removeItem(textarea[0].dataset.autosaveKey);
+ }
+
+ wrapper.classList.remove('form-edit');
+
+ if (Array.from(wrapper.querySelectorAll('.form-value p[data-for]')).length > 0) {
+ console.log(1);
+ Array.from(wrapper.querySelectorAll('.form-value p[data-for]')).forEach((el) => {
+ let identifier = el.dataset.for;
+ let element = document.querySelector(`#${identifier}`);
+
+ if (element) el.innerHTML = element.value;
+ });
+
+ return $(form).submit();
+ } else if (textarea.length === 1) {
+ let _textarea = textarea[0];
+
+ if (_textarea.value.length) {
+ const panel = event.target.closest('.panel-body');
+ const value = _textarea.value.replace(/\n/g, '
');
+ const updatedValue = button.dataset.updatedSection;
+
+ wrapper.querySelector('.form-value p').innerHTML = value;
+
+ panel.querySelector('.field-with-errors')?.classList?.remove('field-with-errors');
+ panel.querySelector('.feedback-holder')?.classList?.remove('error');
+ panel.querySelector('.btn-rag > button')?.classList?.remove('rag-error');
+
+ Array.from(wrapper.querySelectorAll('textarea')).forEach((el) => {
+ if (el.value && el.value.length) {
+ return el.closest('.input')?.classList?.remove('field-with-errors');
+ }
+ });
+
+ if (updatedValue) {
+ const input = form.querySelector("input[name='updated_section']");
+
+ if (input) {
+ input.value = updatedValue;
+ }
+ }
+
+ return $(form).submit();
+ }
+ } else {
+ if (textarea[0] && textarea[0].value.length) {
+ const value = textarea[0].value.replace(/\n/g, '
');
+ Array.from(wrapper.querySelectorAll('.form-value p'))[0].innerHTML = value;
+ }
+
+ if (textarea[-1] && textarea[-1].value.length) {
+ const value = textarea[-1].value.replace(/\n/g, '
');
+ Array.from(wrapper.querySelectorAll('.form-value p'))[-1].innerHTML = value;
+ }
+
+ return $(form).submit();
+ }
+ };
+
+ resetErrors(element) {
+ element.querySelectorAll('.field-with-errors').forEach((el) => el.classList.remove('field-with-errors'));
+ element.querySelectorAll('.rag-error').forEach((el) => el.classList.remove('rag-error'));
+ element.querySelectorAll('[aria-errormessage]').forEach((el) => el.removeAttribute('aria-errormessage'));
+ element.querySelectorAll('[aria-invalid]').forEach((el) => el.removeAttribute('aria-invalid'));
+ element.querySelectorAll('.alert').forEach((el) => el.remove());
+ }
+
+ shouldValidateField(field) {
+ return !field.disabled && field.type !== void 0 && !['file', 'reset', 'submit', 'button'].includes(field.type);
+ }
+
+ showFieldErrors(field, errors, selector) {
+ if (selector == null) {
+ selector = '.form-container';
+ }
+
+ const container = field.closest(selector);
+ const group = field.closest('.govuk-form-group');
+
+ if (group) {
+ group.classList.add('field-with-errors');
+ }
+
+ if (container) {
+ return errors.forEach((message) => {
+ const [alert, identifier] = this.createAlert('danger', message);
+ field.setAttribute('aria-errormessage', identifier);
+ field.setAttribute('aria-invalid', true);
+ return container.insertAdjacentHTML('afterbegin', alert);
+ });
+ }
+ }
+
+ createAlert = (type, message) => {
+ const id = 'alert__' + String(Math.random()).slice(2, -1);
+ const element = `
+
+ ${message}
+
+ ×
+
+
+ `;
+
+ return [element, id];
+ };
+
+ visible(field) {
+ return (
+ !field.hidden && (!field.type || field.type != 'hidden') && (field.offsetWidth > 0 || field.offsetHeight > 0)
+ );
+ }
+}
diff --git a/app/javascript/controllers/element_scroll_controller.js b/app/javascript/controllers/element_scroll_controller.js
index d905ccc57..d79c3ef83 100644
--- a/app/javascript/controllers/element_scroll_controller.js
+++ b/app/javascript/controllers/element_scroll_controller.js
@@ -5,14 +5,14 @@ export default class extends ApplicationController {
connect() {
if (this.firstInvalidField) {
- if (!this.visible(this.firstInvalidField)) {
- const collapsible = this.accordionTargets.find((target) => {
- return target.contains(this.firstInvalidField);
- });
- if (collapsible) $(collapsible).collapse('show');
- }
-
setTimeout(() => {
+ if (!this.visible(this.firstInvalidField)) {
+ const collapsible = this.accordionTargets.find((target) => {
+ return target.contains(this.firstInvalidField);
+ });
+ if (collapsible) $(collapsible).collapse('show');
+ }
+
this.firstInvalidField.focus();
scrollToElement(this.firstInvalidField);
}, 300);
diff --git a/app/javascript/controllers/inline_flash_controller.js b/app/javascript/controllers/inline_flash_controller.js
index 481c3316e..127dd8f40 100644
--- a/app/javascript/controllers/inline_flash_controller.js
+++ b/app/javascript/controllers/inline_flash_controller.js
@@ -32,14 +32,14 @@ export default class extends ApplicationController {
const msg = this.hasSuccessValue ? this.successValue : 'Success!';
const [alert, identifier] = this.createAlert('success', msg);
- setTimeout(() => this.showAlert(alert, identifier), 1);
+ setTimeout(() => this.showAlert(alert, identifier), 10);
};
onError = (event) => {
const msg = this.hasErrorValue ? this.errorValue : 'An unknown error has occurred, please try again.';
const [alert, identifier] = this.createAlert('danger', msg);
- setTimeout(() => this.showAlert(alert, identifier), 1);
+ setTimeout(() => this.showAlert(alert, identifier), 10);
};
createAlert = (type, message) => {
@@ -47,7 +47,7 @@ export default class extends ApplicationController {
const element = `
${message}
-
+
×
@@ -57,8 +57,8 @@ export default class extends ApplicationController {
};
showAlert = (alert, identifier) => {
- const existing = this.element.querySelector('[id*=alert__]')
- if (existing) existing.remove()
+ const existing = this.element.querySelector('[id*=alert__]');
+ if (existing) existing.remove();
this.element.insertAdjacentHTML('afterbegin', alert);
diff --git a/app/models/account.rb b/app/models/account.rb
index 8e3efbc74..f97d35e10 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -10,7 +10,7 @@ class Account < ApplicationRecord
has_many :mobility_eligibilities, class_name: 'Eligibility::Mobility'
has_many :promotion_eligibilities, class_name: 'Eligibility::Promotion'
- belongs_to :owner, class_name: 'User', autosave: false, inverse_of: :owned_account
+ belongs_to :owner, class_name: 'User', autosave: false, inverse_of: :owned_account, optional: true
validates :owner, presence: true
def basic_eligibility
diff --git a/app/models/aggregated_award_year_pdf.rb b/app/models/aggregated_award_year_pdf.rb
index f8495bf82..6cb3e49c9 100644
--- a/app/models/aggregated_award_year_pdf.rb
+++ b/app/models/aggregated_award_year_pdf.rb
@@ -2,7 +2,7 @@ class AggregatedAwardYearPdf < ApplicationRecord
TYPES = %w(case_summary feedback)
- belongs_to :award_year
+ belongs_to :award_year, optional: true
validates :award_year_id, uniqueness: { scope: [:award_category, :type_of_report, :sub_type] },
presence: true
diff --git a/app/models/assessor_assignment.rb b/app/models/assessor_assignment.rb
index 5952da3a9..185c384ca 100644
--- a/app/models/assessor_assignment.rb
+++ b/app/models/assessor_assignment.rb
@@ -31,10 +31,10 @@ class AssessorAssignment < ApplicationRecord
end
begin :associations
- belongs_to :assessor
- belongs_to :form_answer
- belongs_to :editable, polymorphic: true
- belongs_to :award_year
+ belongs_to :assessor, optional: true
+ belongs_to :form_answer, optional: true
+ belongs_to :editable, polymorphic: true, optional: true
+ belongs_to :award_year, optional: true
end
begin :scopes
@@ -152,7 +152,13 @@ def not_submitted_or_not_locked?
def award_specific_attributes
struct.diff(form_answer, moderated?).each do |att|
if public_send(att).present?
- errors.add(att, "cannot be present for this Award Type")
+ message = if att.ends_with?("_rate")
+ "RAG rating for '#{section_name(att)}' cannot be present for this Award Type"
+ else
+ "An appraisal comment for '#{section_name(att)}' cannot be present for this Award Type"
+ end
+
+ errors.add(att, message: message)
end
end
end
@@ -162,7 +168,13 @@ def mandatory_fields_for_submitted
struct.meths_for_award_type(form_answer, moderated?).each do |meth|
if public_send(meth).blank?
- errors.add(meth, "cannot be blank for submitted assessment")
+ message = if meth.ends_with?("_rate")
+ "RAG rating is required for '#{section_name(meth)}'. Select an option from the dropdown list."
+ else
+ "An appraisal comment is required for '#{section_name(meth)}' and must be filled in."
+ end
+
+ errors.add(meth, message: message)
end
end
end
@@ -174,7 +186,8 @@ def validate_rate(rate_type)
c = "#{rate_type.upcase}_ALLOWED_VALUES"
if val && !struct.const_get(c).include?(val)
sect_name = struct.rate(section)
- errors.add(sect_name, "#{rate_type} field has not permitted value")
+ message = "#{rate_type} field for '#{section_name(section)}' has not permitted value."
+ errors.add(sect_name, message: message)
end
end
end
@@ -183,6 +196,14 @@ def section_rate(section)
public_send(struct.rate(section))
end
+ def section_name(key)
+ @_sections ||= struct.struct(form_answer).to_h
+ section_key = key.to_s.gsub(/_desc$/, "").gsub(/_rate$/, "")
+ if section = @_sections.dig(section_key.to_sym)
+ section[:label].gsub(/:$/, "")
+ end
+ end
+
def struct
AppraisalForm
end
diff --git a/app/models/audit_log.rb b/app/models/audit_log.rb
index 8d4da014a..5874ff467 100644
--- a/app/models/audit_log.rb
+++ b/app/models/audit_log.rb
@@ -3,8 +3,8 @@ class AuditLog < ApplicationRecord
validates :subject_id, presence: true
validates :action_type, presence: true
- belongs_to :subject, polymorphic: true
- belongs_to :auditable, polymorphic: true
+ belongs_to :subject, polymorphic: true, optional: true
+ belongs_to :auditable, polymorphic: true, optional: true
scope :data_export, -> { where(auditable_type: nil).or(where(action_type: "download_form_answer")) }
scope :data_update, -> { where(auditable_type: "FormAnswer").where("action_type != 'download_form_answer'") }
diff --git a/app/models/award_year.rb b/app/models/award_year.rb
index 98c1a974b..2fbc868ef 100644
--- a/app/models/award_year.rb
+++ b/app/models/award_year.rb
@@ -256,8 +256,8 @@ def current_year_deadline(title)
res
end
- def buckingham_palace_reception_deadline
- current_year_deadline("buckingham_palace_attendees_invite")
+ def buckingham_palace_reception_deadline(award_year)
+ award_year.settings.deadlines.where(kind: "buckingham_palace_attendees_invite").first
end
def buckingham_palace_reception_date
diff --git a/app/models/case_summary_hard_copy_pdf.rb b/app/models/case_summary_hard_copy_pdf.rb
index 9bdaae6aa..9f9e3c03c 100644
--- a/app/models/case_summary_hard_copy_pdf.rb
+++ b/app/models/case_summary_hard_copy_pdf.rb
@@ -1,5 +1,5 @@
class CaseSummaryHardCopyPdf < ApplicationRecord
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
mount_uploader :file, FormAnswerPdfVersionUploader
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 641f20a33..74bfbb6b4 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -1,6 +1,6 @@
class Comment < ApplicationRecord
- belongs_to :commentable, polymorphic: true
- belongs_to :authorable, polymorphic: true
+ belongs_to :commentable, polymorphic: true, optional: true
+ belongs_to :authorable, polymorphic: true, optional: true
validates :body, presence: true
diff --git a/app/models/commercial_figures_file.rb b/app/models/commercial_figures_file.rb
index 641fe786e..255f3f0b4 100644
--- a/app/models/commercial_figures_file.rb
+++ b/app/models/commercial_figures_file.rb
@@ -10,5 +10,5 @@ class CommercialFiguresFile < ActiveRecord::Base
validates :form_answer_id, uniqueness: true,
presence: true
- belongs_to :shortlisted_documents_wrapper
+ belongs_to :shortlisted_documents_wrapper, optional: true
end
diff --git a/app/models/concerns/reviewable.rb b/app/models/concerns/reviewable.rb
index 2f444bc7f..0e4c81aeb 100644
--- a/app/models/concerns/reviewable.rb
+++ b/app/models/concerns/reviewable.rb
@@ -2,7 +2,7 @@ module Reviewable
extend ActiveSupport::Concern
included do
- belongs_to :reviewable, polymorphic: true
+ belongs_to :reviewable, polymorphic: true, optional: true
validates :reviewable_type,
:reviewable_id,
diff --git a/app/models/concerns/shortlisted_document.rb b/app/models/concerns/shortlisted_document.rb
index 337294792..8b69b02e2 100644
--- a/app/models/concerns/shortlisted_document.rb
+++ b/app/models/concerns/shortlisted_document.rb
@@ -8,7 +8,7 @@ module ShortlistedDocument
include ::InfectedFileCleaner
clean_after_scan :attachment
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
end
def original_filename
diff --git a/app/models/deadline.rb b/app/models/deadline.rb
index e5c8f8eef..c26e7c59d 100644
--- a/app/models/deadline.rb
+++ b/app/models/deadline.rb
@@ -6,7 +6,7 @@ class Deadline < ApplicationRecord
date_time_for :trigger_at
- belongs_to :settings
+ belongs_to :settings, optional: true
AVAILABLE_DEADLINES = [
"award_year_switch",
diff --git a/app/models/draft_note.rb b/app/models/draft_note.rb
index 260443cfb..01594bb6d 100644
--- a/app/models/draft_note.rb
+++ b/app/models/draft_note.rb
@@ -5,8 +5,8 @@ class DraftNote < ApplicationRecord
:authorable_id,
presence: true
- belongs_to :notable, polymorphic: true
- belongs_to :authorable, polymorphic: true
+ belongs_to :notable, polymorphic: true, optional: true
+ belongs_to :authorable, polymorphic: true, optional: true
before_save :update_content_updated_at
diff --git a/app/models/eligibility.rb b/app/models/eligibility.rb
index a353f8cae..85962561e 100644
--- a/app/models/eligibility.rb
+++ b/app/models/eligibility.rb
@@ -3,8 +3,8 @@ class Eligibility < ApplicationRecord
AWARD_NAME = ""
- belongs_to :account
- belongs_to :form_answer
+ belongs_to :account, optional: true
+ belongs_to :form_answer, optional: true
attr_accessor :current_step,
:force_validate_now
diff --git a/app/models/email_notification.rb b/app/models/email_notification.rb
index 962ae406c..75088f18c 100644
--- a/app/models/email_notification.rb
+++ b/app/models/email_notification.rb
@@ -25,7 +25,7 @@ class EmailNotification < ApplicationRecord
date_time_for :trigger_at
- belongs_to :settings
+ belongs_to :settings, optional: true
enumerize :kind, in: NOTIFICATION_KINDS
diff --git a/app/models/feedback.rb b/app/models/feedback.rb
index bed274f16..1b518f5f3 100644
--- a/app/models/feedback.rb
+++ b/app/models/feedback.rb
@@ -2,13 +2,13 @@ class Feedback < ApplicationRecord
has_paper_trail unless: Proc.new { |t| Rails.env.test? }
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
store_accessor :document, FeedbackForm.fields
scope :submitted, -> { where submitted: true }
- belongs_to :authorable, polymorphic: true
- belongs_to :award_year
+ belongs_to :authorable, polymorphic: true, optional: true
+ belongs_to :award_year, optional: true
validates :form_answer_id, uniqueness: true
diff --git a/app/models/feedback_hard_copy_pdf.rb b/app/models/feedback_hard_copy_pdf.rb
index 6c5e55e2c..f3db0d1b7 100644
--- a/app/models/feedback_hard_copy_pdf.rb
+++ b/app/models/feedback_hard_copy_pdf.rb
@@ -1,5 +1,5 @@
class FeedbackHardCopyPdf < ApplicationRecord
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
mount_uploader :file, FormAnswerPdfVersionUploader
diff --git a/app/models/form_answer.rb b/app/models/form_answer.rb
index 61359773a..51d63765b 100644
--- a/app/models/form_answer.rb
+++ b/app/models/form_answer.rb
@@ -75,10 +75,10 @@ class FormAnswer < ApplicationRecord
mount_uploader :pdf_version, FormAnswerPdfVersionUploader
begin :associations
- belongs_to :user
- belongs_to :account
- belongs_to :award_year
- belongs_to :company_details_editable, polymorphic: true
+ belongs_to :user, optional: true
+ belongs_to :account, optional: true
+ belongs_to :award_year, optional: true
+ belongs_to :company_details_editable, polymorphic: true, optional: true
has_one :form_basic_eligibility, class_name: 'Eligibility::Basic', dependent: :destroy
has_one :trade_eligibility, class_name: 'Eligibility::Trade', dependent: :destroy
@@ -99,8 +99,8 @@ class FormAnswer < ApplicationRecord
has_one :case_summary_hard_copy_pdf, dependent: :destroy
has_one :feedback_hard_copy_pdf, dependent: :destroy
- belongs_to :primary_assessor, class_name: "Assessor", foreign_key: :primary_assessor_id
- belongs_to :secondary_assessor, class_name: "Assessor", foreign_key: :secondary_assessor_id
+ belongs_to :primary_assessor, optional: true, class_name: "Assessor", foreign_key: :primary_assessor_id
+ belongs_to :secondary_assessor, optional: true, class_name: "Assessor", foreign_key: :secondary_assessor_id
has_many :form_answer_attachments, dependent: :destroy
has_many :support_letter_attachments, dependent: :destroy
has_many :commercial_figures_files, dependent: :destroy
diff --git a/app/models/form_answer_attachment.rb b/app/models/form_answer_attachment.rb
index fd4c4eb3c..6fdc27ef2 100644
--- a/app/models/form_answer_attachment.rb
+++ b/app/models/form_answer_attachment.rb
@@ -1,6 +1,6 @@
class FormAnswerAttachment < ApplicationRecord
- belongs_to :form_answer
- belongs_to :attachable, polymorphic: true
+ belongs_to :form_answer, optional: true
+ belongs_to :attachable, polymorphic: true, optional: true
mount_uploader :file, FormAnswerAttachmentUploader
scan_file :file
diff --git a/app/models/form_answer_progress.rb b/app/models/form_answer_progress.rb
index 7d2d0b592..0327009eb 100644
--- a/app/models/form_answer_progress.rb
+++ b/app/models/form_answer_progress.rb
@@ -1,5 +1,5 @@
class FormAnswerProgress < ApplicationRecord
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
validates :form_answer_id, presence: true
diff --git a/app/models/form_answer_transition.rb b/app/models/form_answer_transition.rb
index c62212972..f08891410 100644
--- a/app/models/form_answer_transition.rb
+++ b/app/models/form_answer_transition.rb
@@ -1,7 +1,7 @@
class FormAnswerTransition < ApplicationRecord
include Statesman::Adapters::ActiveRecordTransition
- belongs_to :form_answer, inverse_of: :form_answer_transitions
+ belongs_to :form_answer, optional: true, inverse_of: :form_answer_transitions
def transitable
t_type = metadata["transitable_type"]
diff --git a/app/models/palace_attendee.rb b/app/models/palace_attendee.rb
index d30a36d0c..9f2f170b3 100644
--- a/app/models/palace_attendee.rb
+++ b/app/models/palace_attendee.rb
@@ -1,5 +1,5 @@
class PalaceAttendee < ApplicationRecord
- belongs_to :palace_invite
+ belongs_to :palace_invite, optional: true
validates :palace_invite,
:title,
diff --git a/app/models/palace_invite.rb b/app/models/palace_invite.rb
index ed426eb90..5304ef1aa 100644
--- a/app/models/palace_invite.rb
+++ b/app/models/palace_invite.rb
@@ -1,5 +1,5 @@
class PalaceInvite < ApplicationRecord
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
has_many :palace_attendees, dependent: :destroy, autosave: true
diff --git a/app/models/press_summary.rb b/app/models/press_summary.rb
index 1a7ddbd21..896d127b6 100644
--- a/app/models/press_summary.rb
+++ b/app/models/press_summary.rb
@@ -1,5 +1,5 @@
class PressSummary < ApplicationRecord
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
validates :form_answer, :token, presence: true
validates :body, presence: true, unless: :contact_details_update?
@@ -15,7 +15,7 @@ class PressSummary < ApplicationRecord
before_validation :set_token, on: :create
- belongs_to :authorable, polymorphic: true
+ belongs_to :authorable, optional: true, polymorphic: true
attr_accessor :contact_details_update, :body_update
diff --git a/app/models/reports/dashboard/applications_report.rb b/app/models/reports/dashboard/applications_report.rb
index cf125bfc1..da9419fac 100644
--- a/app/models/reports/dashboard/applications_report.rb
+++ b/app/models/reports/dashboard/applications_report.rb
@@ -80,4 +80,33 @@ def generate_content(form_answers, date)
[" ".html_safe, " ".html_safe]
end
end
+
+ def as_csv
+ CSV.generate do |csv|
+ headers = ["Year"]
+ case kind
+ when "by_month"
+ columns = ["By end of April", "By end of May", "By end of June", "By end of July", "By end of August", "Totals on deadline"]
+ when "by_week"
+ columns = ["6 weeks before deadline", "5 weeks before deadline", "4 weeks before deadline", "3 weeks before deadline", "2 weeks before deadline", "1 week before deadline", "Totals on deadline"]
+ when "by_day"
+ columns = ["6 days before deadline", "5 days before deadline", "4 days before deadline", "3 days before deadline", "2 days before deadline", "1 day before deadline", "Totals on deadline"]
+ end
+ csv << (headers + columns.map{|c| [c] << nil}).flatten
+ subheaders =[""]
+ columns.each{subheaders << ["In progress", "Submitted"]}
+ csv << subheaders.flatten
+
+ stats.each do |row|
+ content = []
+ content << row.label
+ row.content.each{|c| content << (c == " " ? nil : c)}
+ csv << content
+ end
+ end
+ end
+
+ def csv_filename
+ "#{award_type || "all"}_applications_report_#{kind}.csv"
+ end
end
diff --git a/app/models/reports/dashboard/users_report.rb b/app/models/reports/dashboard/users_report.rb
index ff116776e..a732a26db 100644
--- a/app/models/reports/dashboard/users_report.rb
+++ b/app/models/reports/dashboard/users_report.rb
@@ -69,4 +69,30 @@ def generate_content(users, date)
" ".html_safe
end
end
+
+ def as_csv
+ CSV.generate do |csv|
+ headers = ["Year"]
+ case kind
+ when "by_month"
+ columns = ["By end of April", "By end of May", "By end of June", "By end of July", "By end of August", "Totals on deadline"]
+ when "by_week"
+ columns = ["6 weeks before deadline", "5 weeks before deadline", "4 weeks before deadline", "3 weeks before deadline", "2 weeks before deadline", "1 week before deadline", "Totals on deadline"]
+ when "by_day"
+ columns = ["6 days before deadline", "5 days before deadline", "4 days before deadline", "3 days before deadline", "2 days before deadline", "1 day before deadline", "Totals on deadline"]
+ end
+ csv << (headers + columns).flatten
+
+ stats.each do |row|
+ content = []
+ content << row.label
+ row.content.each{|c| content << (c == " " ? nil : c)}
+ csv << content
+ end
+ end
+ end
+
+ def csv_filename
+ "account_registrations_#{kind}.csv"
+ end
end
diff --git a/app/models/reports/discrepancies_between_primary_and_secondary_appraisals.rb b/app/models/reports/discrepancies_between_primary_and_secondary_appraisals.rb
index 3686ec361..0fe35c319 100644
--- a/app/models/reports/discrepancies_between_primary_and_secondary_appraisals.rb
+++ b/app/models/reports/discrepancies_between_primary_and_secondary_appraisals.rb
@@ -45,22 +45,22 @@ def initialize(year, award_type, current_subject=nil)
raise "Access Denied!"
end
- end
- def stream
- scoped = @year.form_answers.order(:id)
- .joins(%Q{
+ @scope = @year.form_answers.order(:id)
+ .joins(%Q{
JOIN assessor_assignments primary_assignments ON primary_assignments.form_answer_id = form_answers.id
JOIN assessor_assignments secondary_assignments ON secondary_assignments.form_answer_id = form_answers.id
})
- .where(primary_assignments: { position: AssessorAssignment.positions[:primary] })
- .where.not(primary_assignments: { position: nil })
- .where(secondary_assignments: { position: AssessorAssignment.positions[:secondary] })
- .where.not(secondary_assignments: { position: nil })
- .primary_and_secondary_appraisals_are_not_match
- .where(award_type: @award_type)
+ .where(primary_assignments: { position: AssessorAssignment.positions[:primary] })
+ .where.not(primary_assignments: { position: nil })
+ .where(secondary_assignments: { position: AssessorAssignment.positions[:secondary] })
+ .where.not(secondary_assignments: { position: nil })
+ .primary_and_secondary_appraisals_are_not_match
+ .where(award_type: @award_type)
+ end
- prepare_stream(scoped)
+ def stream
+ prepare_stream(@scope)
end
private
diff --git a/app/models/settings.rb b/app/models/settings.rb
index e5d6d8ae0..fa0a5c8a8 100644
--- a/app/models/settings.rb
+++ b/app/models/settings.rb
@@ -6,7 +6,7 @@ class Settings < ApplicationRecord
has_many :deadlines, dependent: :destroy
has_many :email_notifications, dependent: :destroy
- belongs_to :award_year, inverse_of: :settings
+ belongs_to :award_year, optional: true, inverse_of: :settings
validates :award_year, presence: true
diff --git a/app/models/shortlisted_documents_wrapper.rb b/app/models/shortlisted_documents_wrapper.rb
index dfa451c06..89cee9aee 100644
--- a/app/models/shortlisted_documents_wrapper.rb
+++ b/app/models/shortlisted_documents_wrapper.rb
@@ -3,7 +3,7 @@ class ShortlistedDocumentsWrapper < ActiveRecord::Base
has_one :commercial_figures_file
has_many :vat_returns_files
- belongs_to :form_answer
+ belongs_to :form_answer, optional: true
validate :valid_for_submission?
diff --git a/app/models/support_letter.rb b/app/models/support_letter.rb
index 8c7e2bc24..b0d78d59e 100644
--- a/app/models/support_letter.rb
+++ b/app/models/support_letter.rb
@@ -1,8 +1,8 @@
class SupportLetter < ApplicationRecord
begin :associations
- belongs_to :supporter
- belongs_to :form_answer
- belongs_to :user
+ belongs_to :supporter, optional: true
+ belongs_to :form_answer, optional: true
+ belongs_to :user, optional: true
has_one :support_letter_attachment, autosave: true, dependent: :destroy
end
diff --git a/app/models/support_letter_attachment.rb b/app/models/support_letter_attachment.rb
index c3640ba45..81c6f2eb1 100644
--- a/app/models/support_letter_attachment.rb
+++ b/app/models/support_letter_attachment.rb
@@ -6,9 +6,9 @@ class SupportLetterAttachment < ApplicationRecord
clean_after_scan :attachment
begin :associations
- belongs_to :user
- belongs_to :form_answer
- belongs_to :support_letter
+ belongs_to :user, optional: true
+ belongs_to :form_answer, optional: true
+ belongs_to :support_letter, optional: true
end
begin :validations
diff --git a/app/models/supporter.rb b/app/models/supporter.rb
index c8984b14a..068289c0e 100644
--- a/app/models/supporter.rb
+++ b/app/models/supporter.rb
@@ -2,8 +2,8 @@
class Supporter < ApplicationRecord
begin :associations
- belongs_to :form_answer
- belongs_to :user
+ belongs_to :form_answer, optional: true
+ belongs_to :user, optional: true
has_one :support_letter, dependent: :destroy
end
diff --git a/app/models/user.rb b/app/models/user.rb
index ef27ff22a..b117a164e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -44,7 +44,7 @@ class User < ApplicationRecord
source: :feedback
has_one :owned_account, foreign_key: :owner_id, class_name: 'Account'
- belongs_to :account
+ belongs_to :account, optional: true
has_many :form_answer_attachments, as: :attachable
has_many :support_letter_attachments, dependent: :destroy
has_many :supporters, dependent: :destroy
@@ -161,7 +161,7 @@ def new_member?
end
def timeout_in
- 24.hours
+ ENV.fetch("SESSION_TIMEOUT", 24).to_i.hours
end
def check_email_on_bounces!
diff --git a/app/models/vat_returns_file.rb b/app/models/vat_returns_file.rb
index 27f81a131..dc7570503 100644
--- a/app/models/vat_returns_file.rb
+++ b/app/models/vat_returns_file.rb
@@ -7,7 +7,7 @@ class VatReturnsFile < ActiveRecord::Base
maximum: 5.megabytes.to_i
}
- belongs_to :shortlisted_documents_wrapper
+ belongs_to :shortlisted_documents_wrapper, optional: true
after_destroy :unsubmit_if_needed
diff --git a/app/pdf_generators/case_summary_pdfs/base.rb b/app/pdf_generators/case_summary_pdfs/base.rb
index 290ee8b01..ca160e1bc 100644
--- a/app/pdf_generators/case_summary_pdfs/base.rb
+++ b/app/pdf_generators/case_summary_pdfs/base.rb
@@ -24,10 +24,10 @@ def add_page_numbers
end
def all_mode
- set_form_answers
+ @_form_answers = set_form_answers
- if form_answers.present?
- form_answers.each_with_index do |form_answer, index|
+ if @_form_answers.present?
+ @_form_answers.each_with_index do |form_answer, index|
start_new_page if index.to_i != 0
render_item(form_answer)
end
@@ -54,7 +54,11 @@ def set_form_answers
scope = scope.where("form_answers.document #>> '{trade_commercial_success}' = '#{years_mode}'")
end
- @form_answers = scope
+ puts "*"*100
+ puts scope.count
+ puts "*"*100
+
+ scope
end
def render_item(form_answer)
diff --git a/app/pdf_generators/hard_copy_generators/base.rb b/app/pdf_generators/hard_copy_generators/base.rb
index 2081bd33c..af700a72a 100644
--- a/app/pdf_generators/hard_copy_generators/base.rb
+++ b/app/pdf_generators/hard_copy_generators/base.rb
@@ -18,19 +18,21 @@ def initialize(form_answer, use_latest_version=false)
def run
# Create a tempfile
@tmpfile = Tempfile.new([tempfile_name, '.pdf'])
-
- # set to binary mode to avoid UTF-8 conversion errors
- tmpfile.binmode
-
- # Use render to write the file contents
- tmpfile.write pdf.render
-
- # Upload the tempfile with your Carrierwave uploader
- attach_generated_file!
-
- # Close the tempfile and delete it
- tmpfile.close
- tmpfile.unlink
+
+ begin
+ # set to binary mode to avoid UTF-8 conversion errors
+ tmpfile.binmode
+
+ # Use render to write the file contents
+ tmpfile.write pdf.render
+
+ # Upload the tempfile with your Carrierwave uploader
+ attach_generated_file!
+ ensure
+ # Close the tempfile and delete it
+ tmpfile.close
+ tmpfile.unlink if tmpfile
+ end
end
private
diff --git a/app/policies/palace_invite_policy.rb b/app/policies/palace_invite_policy.rb
new file mode 100644
index 000000000..5846e93ff
--- /dev/null
+++ b/app/policies/palace_invite_policy.rb
@@ -0,0 +1,6 @@
+class PalaceInvitePolicy < ApplicationPolicy
+ def update?
+ admin? ||
+ subject.lead_or_assigned?(record.form_answer)
+ end
+end
diff --git a/app/services/assessment_submission_service.rb b/app/services/assessment_submission_service.rb
index 76b3f61f7..c2dd1b691 100644
--- a/app/services/assessment_submission_service.rb
+++ b/app/services/assessment_submission_service.rb
@@ -156,11 +156,11 @@ def check_if_there_are_any_discrepancies_between_primary_and_secondary_appraisal
res = {
discrepancies: discrepancies,
- primary_assessor_name: primary_assessor.full_name,
- primary_assessor_email: primary_assessor.email,
+ primary_assessor_name: primary_assessor&.full_name,
+ primary_assessor_email: primary_assessor&.email,
primary_assessor_submitted_at: format_date(primary_assessment.submitted_at),
- secondary_assessor_name: secondary_assessor.full_name,
- secondary_assessor_email: secondary_assessor.email,
+ secondary_assessor_name: secondary_assessor&.full_name,
+ secondary_assessor_email: secondary_assessor&.email,
secondary_assessor_submitted_at: format_date(secondary_assessment.submitted_at)
}
diff --git a/app/validators/advanced_email_validator.rb b/app/validators/advanced_email_validator.rb
index fef46dec3..eda403dc9 100644
--- a/app/validators/advanced_email_validator.rb
+++ b/app/validators/advanced_email_validator.rb
@@ -24,12 +24,12 @@ def has_mx_records(domain)
end
def set_error(record)
- record.errors.add(:email, "is not a valid address")
+ record.errors.add(:email, :invalid)
end
def maybe_set_error(record, message)
yield.tap do |value|
- record.errors.add(:email, message) if value
+ record.errors.add(:email, message: message) if value
end
end
diff --git a/app/validators/company_registration_number_validator.rb b/app/validators/company_registration_number_validator.rb
index 21c582083..1f155421e 100644
--- a/app/validators/company_registration_number_validator.rb
+++ b/app/validators/company_registration_number_validator.rb
@@ -18,7 +18,7 @@ def validate_each(record, attribute, value)
return if options[:allow_blank] && value.blank?
return if options[:allow_empty] && value == ""
unless self.class.valid?(value)
- record.errors[attribute] << (options[:message] || "is not a valid company registration number")
+ record.errors.add(attribute, message: options[:message] || "is not a valid company registration number")
end
end
end
diff --git a/app/validators/file_size_validator.rb b/app/validators/file_size_validator.rb
index a2f729339..fad3ec6d3 100644
--- a/app/validators/file_size_validator.rb
+++ b/app/validators/file_size_validator.rb
@@ -56,7 +56,7 @@ def validate_each(record, attribute, value)
default_message = options[MESSAGES[key]]
errors_options[:message] ||= default_message if default_message
- record.errors.add(attribute, MESSAGES[key], errors_options)
+ record.errors.add(attribute, MESSAGES[key], **errors_options)
end
end
diff --git a/app/views/admin/admins/_form.html.slim b/app/views/admin/admins/_form.html.slim
index 15ec8cd34..d714f5004 100644
--- a/app/views/admin/admins/_form.html.slim
+++ b/app/views/admin/admins/_form.html.slim
@@ -1,6 +1,6 @@
.js-admin-strict-password-form
-= simple_form_for [:admin, resource], html: { class: 'qae-form' } do |f|
+= simple_form_for [:admin, resource], html: { class: 'qae-form', data: { type: "json", controller: "inline-flash element-scroll", inline_flash_target: "form" } } do |f|
.row.question-group
.col-lg-2.col-md-3.col-sm-4
h3 = f.label :first_name, class: "form-label"
@@ -26,6 +26,14 @@
.question-group#password-change-panel
#password-control-group
h3 = f.label :password, class: "form-label"
+ .guidance-panel.if-no-js-hide
+ .govuk-form-group--error#password-guidance
+ p.govuk-error-message.text-underline Please improve your password
+ p.govuk-error-message#password-too-short
+ ' It must be at least 10 characters.
+ p.govuk-error-message#parts-of-email It shouldn't include part or all of your email address.
+ p.govuk-error-message#password-entropy
+ ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
.row
.col-md-4.col-sm-6
.input-group
@@ -33,23 +41,15 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control', "data-min-password-length" => "10" },
label: false
- span#password-result-span.input-group-addon
+ span#password-result-span.input-group-addon.hide
i#password-result.glyphicon.glyphicon-ok
.clear
- .guidance-panel.if-no-js-hide
- #password-guidance
- br
- .alert.alert-warning
- p.text-underline Please improve your password
- p#password-too-short
- ' It must be at least 10 characters.
- p#parts-of-email It shouldn't include part or all of your email address.
- p#password-entropy
- ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
-
#password-confirmation-control-group
h3 = f.label :password_confirmation, label: "Retype password", class: "form-label"
+ .if-no-js-hide
+ .govuk-form-group--error#password-confirmation-guidance
+ p.govuk-error-message#password-confirmation-match The confirmation must match the password
.row
.col-md-4.col-sm-6
.input-group
@@ -57,16 +57,10 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control' },
label: false
- span#password-confirmation-result-span.input-group-addon
+ span#password-confirmation-result-span.input-group-addon.hide
i#password-confirmation-result.glyphicon.glyphicon-ok
.clear
- .if-no-js-hide
- #password-confirmation-guidance
- br
- .alert.alert-warning
- p#password-confirmation-match The confirmation must match the password
-
br
.row
.col-md-4.col-sm-6
diff --git a/app/views/admin/assessors/_form.html.slim b/app/views/admin/assessors/_form.html.slim
index 2a1b556d3..4af2e46ce 100644
--- a/app/views/admin/assessors/_form.html.slim
+++ b/app/views/admin/assessors/_form.html.slim
@@ -1,4 +1,4 @@
-= simple_form_for [:admin, resource], as: :assessor, url: resource.persisted? ? admin_assessor_path(resource) : admin_assessors_path, html: { class: 'qae-form' } do |f|
+= simple_form_for [:admin, resource], as: :assessor, url: resource.persisted? ? admin_assessor_path(resource) : admin_assessors_path, html: { class: 'qae-form', data: { controller: "inline-flash element-scroll", inline_flash_target: "form" } } do |f|
.row.question-group
.col-lg-2.col-md-3.col-sm-4
h2 = f.label :first_name, class: "form-label"
@@ -42,6 +42,14 @@
.question-group#password-change-panel
#password-control-group
h2 = f.label :password, class: "form-label"
+ .guidance-panel.if-no-js-hide
+ .govuk-form-group--error#password-guidance
+ p.govuk-error-message.text-underline Please improve your password
+ p.govuk-error-message#password-too-short
+ ' It must be at least 10 characters.
+ p.govuk-error-message#parts-of-email It shouldn't include part or all of your email address.
+ p.govuk-error-message#password-entropy
+ ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
.row
.col-md-4.col-sm-6
.input-group
@@ -49,22 +57,15 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control' },
label: false
- span#password-result-span.input-group-addon
+ span#password-result-span.input-group-addon.hide
i#password-result.glyphicon.glyphicon-ok
.clear
- .guidance-panel.if-no-js-hide
- #password-guidance
- br
- .alert.alert-warning
- p.text-underline Please improve your password
- p#password-too-short
- ' It must be at least 10 characters.
- p#parts-of-email It shouldn't include part or all of your email address.
- p#password-entropy
- ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
#password-confirmation-control-group
h2 = f.label :password_confirmation, label: "Retype password", class: "form-label"
+ .if-no-js-hide
+ .govuk-form-group--error#password-confirmation-guidance
+ p.govuk-error-message#password-confirmation-match The confirmation must match the password
.row
.col-md-4.col-sm-6
.input-group
@@ -72,16 +73,10 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control' },
label: false
- span#password-confirmation-result-span.input-group-addon
+ span#password-confirmation-result-span.input-group-addon.hide
i#password-confirmation-result.glyphicon.glyphicon-ok
.clear
- .if-no-js-hide
- #password-confirmation-guidance
- br
- .alert.alert-warning
- p#password-confirmation-match The confirmation must match the password
-
br
.row
diff --git a/app/views/admin/audit_certificate/_form.html.slim b/app/views/admin/audit_certificate/_form.html.slim
index 943f44582..dbb14c45c 100644
--- a/app/views/admin/audit_certificate/_form.html.slim
+++ b/app/views/admin/audit_certificate/_form.html.slim
@@ -3,15 +3,15 @@
/ whether file was saved or not
.span
= hidden_field_tag "valid", "false", id: "form-audit_certificate-valid"
-= form_for [namespace_name, form_answer, audit_certificate], html: { multipart: true, data: { inline_flash_target: "form" } } do |form|
+= form_for [namespace_name, form_answer, audit_certificate], html: { multipart: true, data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" } } do |form|
.well.js-attachment-form
h3 Attach document
- if form.object.errors.any?
.errors
- .alert.alert-danger[data-controller="element-removal" role="alert"']
+ .alert.alert-danger[data-controller="element-removal" role="alert"]
= form.object.errors.full_messages.join(", ")
- button[type="button" class="close" data-action="click->element-removal#remove" aria-label="Close" style="font-size: 18px;"]
+ button[type="button" class="close" data-action="click->element-removal#remove" aria-label="Close"]
span[aria-hidden="true"] ×
.attachment-link.if-js-hide
diff --git a/app/views/admin/comments/_form.html.slim b/app/views/admin/comments/_form.html.slim
index a2c28adab..8019516df 100644
--- a/app/views/admin/comments/_form.html.slim
+++ b/app/views/admin/comments/_form.html.slim
@@ -2,7 +2,7 @@
label
' Add a comment
= f.hidden_field :section, id: "#{f.object.section}_section_hidden_field"
- = f.text_area :body, id: "#{f.object.section}_comment_body", autofocus: true, class: 'form-control', rows: 4, "data-behavior" => "autosave", "data-autosave-key" => "#{@form_answer.id}-#{f.object.section}-new-comment", required: true
+ = f.text_area :body, id: "#{f.object.section}_comment_body", class: 'form-control', rows: 4, "data-behavior" => "autosave", "data-autosave-key" => "#{@form_answer.id}-#{f.object.section}-new-comment", required: true
.comment-actions
= f.check_box :flagged, id: "#{f.object.section}_flagged_hidden_checkbox"
= link_to "#flag-comment", class: "link-flag-comment js-link-flag-comment"
diff --git a/app/views/admin/dashboard/_applications_report.html.slim b/app/views/admin/dashboard/_applications_report.html.slim
index 44f48f55a..9b2592d2e 100644
--- a/app/views/admin/dashboard/_applications_report.html.slim
+++ b/app/views/admin/dashboard/_applications_report.html.slim
@@ -1,9 +1,12 @@
.dashboard-table__wrapper.dashboard-report
- button.btn.btn-primary.btn--load.update-report href=url aria-label="Load #{title} data"
+ button.btn.btn-primary.btn--load.update-report.if-no-js-hide href=url aria-label="Load #{title} data"
| Load data
+ = link_to "Download data", url, class: "btn btn-primary btn--load update-report if-js-hide", aria: { label: "Download #{title} data" }
button.btn.btn-primary.btn--loading.updating-data.hidden aria-label="Updating #{title} data"
| Updating data
+ span.sr-only role="status" aria-live="polite" aria-relevant="all"
+
table.dashboard-table.dashboard-table--small width="1000"
caption
= title
diff --git a/app/views/admin/dashboard/totals_by_day.html.slim b/app/views/admin/dashboard/totals_by_day.html.slim
index ece3fcb8f..0fabfcde6 100644
--- a/app/views/admin/dashboard/totals_by_day.html.slim
+++ b/app/views/admin/dashboard/totals_by_day.html.slim
@@ -9,15 +9,25 @@
p.dashboard__subheading
| Running totals compared to previous years
- .dashboard__section
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_day"), title: "All applications", kind: "by_day"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_day", format: :csv), title: "All applications", kind: "by_day"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_day"), title: "International trade", kind: "by_day"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_day", format: :csv), title: "International trade", kind: "by_day"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_day"), title: "Innovation", kind: "by_day"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_day", format: :csv), title: "Innovation", kind: "by_day"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_day"), title: "Social mobility", kind: "by_day"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_day", format: :csv), title: "Social mobility", kind: "by_day"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_day"), title: "Sustainable development", kind: "by_day"
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_day", format: :csv), title: "Sustainable development", kind: "by_day"
.dashboard__section
= render "admin/dashboard/totals_by_day/registrations"
diff --git a/app/views/admin/dashboard/totals_by_day/_registrations.html.slim b/app/views/admin/dashboard/totals_by_day/_registrations.html.slim
index 3040fc893..b69b2e951 100644
--- a/app/views/admin/dashboard/totals_by_day/_registrations.html.slim
+++ b/app/views/admin/dashboard/totals_by_day/_registrations.html.slim
@@ -1,9 +1,13 @@
.dashboard-table__wrapper.dashboard-report
- button.btn.btn-primary.btn--load.update-report href=account_registrations_admin_dashboard_reports_path(kind: "by_day") aria-label="Load data for new account registrations table"
+ button.btn.btn-primary.btn--load.update-report.if-no-js-hide href=account_registrations_admin_dashboard_reports_path(kind: "by_day") aria-label="Load data for new account registrations table"
| Load data
+ = link_to "Download data", account_registrations_admin_dashboard_reports_path(kind: "by_day", format: :csv),
+ class: "btn btn-primary btn--load update-report if-js-hide", aria: { label: "Download registration totals by day" }
button.btn.btn-primary.btn--loading.updating-data.hidden
| Updating data
+ span.sr-only role="status" aria-live="polite" aria-relevant="all"
+
table.dashboard-table.dashboard-table--small width="1000"
caption
| New account registrations
diff --git a/app/views/admin/dashboard/totals_by_month.html.slim b/app/views/admin/dashboard/totals_by_month.html.slim
index f2d2e509a..5d7ac67ef 100644
--- a/app/views/admin/dashboard/totals_by_month.html.slim
+++ b/app/views/admin/dashboard/totals_by_month.html.slim
@@ -9,15 +9,25 @@
p.dashboard__subheading
| Running totals compared to previous years
- .dashboard__section
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_month"), title: "All applications", kind: "by_month"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_month", format: :csv), title: "All applications", kind: "by_month"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_month"), title: "International trade", kind: "by_month"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_month", format: :csv), title: "International trade", kind: "by_month"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_month"), title: "Innovation", kind: "by_month"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_month", format: :csv), title: "Innovation", kind: "by_month"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_month"), title: "Social mobility", kind: "by_month"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_month", format: :csv), title: "Social mobility", kind: "by_month"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_month"), title: "Sustainable development", kind: "by_month"
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_month", format: :csv), title: "Sustainable development", kind: "by_month"
.dashboard__section
= render "admin/dashboard/totals_by_month/registrations"
diff --git a/app/views/admin/dashboard/totals_by_month/_registrations.html.slim b/app/views/admin/dashboard/totals_by_month/_registrations.html.slim
index ed6d8d4da..8aec25538 100644
--- a/app/views/admin/dashboard/totals_by_month/_registrations.html.slim
+++ b/app/views/admin/dashboard/totals_by_month/_registrations.html.slim
@@ -1,6 +1,8 @@
.dashboard-table__wrapper.dashboard-report
button.btn.btn-primary.btn--load.update-report href=account_registrations_admin_dashboard_reports_path(kind: "by_month") aria-label="Load data for new account registrations table"
| Load data
+ = link_to "Download data", account_registrations_admin_dashboard_reports_path(kind: "by_month", format: :csv),
+ class: "btn btn-primary btn--load update-report if-js-hide", aria: { label: "Download registration totals by month" }
button.btn.btn-primary.btn--loading.updating-data.hidden
| Updating data
diff --git a/app/views/admin/dashboard/totals_by_week.html.slim b/app/views/admin/dashboard/totals_by_week.html.slim
index 565b8ba4d..e8cbdc598 100644
--- a/app/views/admin/dashboard/totals_by_week.html.slim
+++ b/app/views/admin/dashboard/totals_by_week.html.slim
@@ -9,15 +9,25 @@
p.dashboard__subheading
| Running totals compared to previous years
- .dashboard__section
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_week"), title: "All applications", kind: "by_week"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: all_applications_admin_dashboard_reports_path(kind: "by_week", format: :csv), title: "All applications", kind: "by_week"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_week"), title: "International trade", kind: "by_week"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: international_trade_admin_dashboard_reports_path(kind: "by_week", format: :csv), title: "International trade", kind: "by_week"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_week"), title: "Innovation", kind: "by_week"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: innovation_admin_dashboard_reports_path(kind: "by_week", format: :csv), title: "Innovation", kind: "by_week"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_week"), title: "Social mobility", kind: "by_week"
- .dashboard__section
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: social_mobility_admin_dashboard_reports_path(kind: "by_week", format: :csv), title: "Social mobility", kind: "by_week"
+ .dashboard__section.if-no-js-hide
= render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_week"), title: "Sustainable development", kind: "by_week"
+ .dashboard__section.if-js-hide
+ = render "admin/dashboard/applications_report", url: sustainable_development_admin_dashboard_reports_path(kind: "by_week", format: :csv), title: "Sustainable development", kind: "by_week"
.dashboard__section
= render "admin/dashboard/totals_by_week/registrations"
diff --git a/app/views/admin/dashboard/totals_by_week/_registrations.html.slim b/app/views/admin/dashboard/totals_by_week/_registrations.html.slim
index cbb416c7a..985c7edae 100644
--- a/app/views/admin/dashboard/totals_by_week/_registrations.html.slim
+++ b/app/views/admin/dashboard/totals_by_week/_registrations.html.slim
@@ -1,6 +1,8 @@
.dashboard-table__wrapper.dashboard-report
- button.btn.btn-primary.btn--load.update-report href=account_registrations_admin_dashboard_reports_path(kind: "by_week") aria-label="Load data for new account registrations table"
+ button.btn.btn-primary.btn--load.update-report.if-no-js-hide href=account_registrations_admin_dashboard_reports_path(kind: "by_week") aria-label="Load data for new account registrations table"
| Load data
+ = link_to "Download data", account_registrations_admin_dashboard_reports_path(kind: "by_week", format: :csv),
+ class: "btn btn-primary btn--load update-report if-js-hide", aria: { label: "Download registration totals by week" }
button.btn.btn-primary.btn--loading.updating-data.hidden
| Updating data
diff --git a/app/views/admin/email_notifications/destroy.js.erb b/app/views/admin/email_notifications/destroy.js.erb
index b1cf4effd..bef895013 100644
--- a/app/views/admin/email_notifications/destroy.js.erb
+++ b/app/views/admin/email_notifications/destroy.js.erb
@@ -1,2 +1,3 @@
wrapper = $("#notification-" + "<%= @email_notification.id %>");
+window.fire($(".edit_email_notification", wrapper)[0], 'ajax:x:success', null)
wrapper.remove()
diff --git a/app/views/admin/figures_and_vat_returns/_actual_figures.html.slim b/app/views/admin/figures_and_vat_returns/_actual_figures.html.slim
index 016c534b5..ac1058961 100644
--- a/app/views/admin/figures_and_vat_returns/_actual_figures.html.slim
+++ b/app/views/admin/figures_and_vat_returns/_actual_figures.html.slim
@@ -1,13 +1,14 @@
label
| Variance explanation document
-.document-list.space-y-3
- p.p-empty class="#{'visuallyhidden' if figures_form.commercial_figures_file.present?}"
- ' No document has been attached.
- ul.list-unstyled.list-actions
- - if figures_form.commercial_figures_file.present?
- = render(partial: "admin/figures_and_vat_returns/file", collection: Array.wrap(figures_form.commercial_figures_file), as: :attachment)
- .clear
+div[data-controller="inline-flash"]
+ .document-list.space-y-3
+ p.p-empty class="#{'visuallyhidden' if figures_form.commercial_figures_file.present?}"
+ ' No document has been attached.
+ ul.list-unstyled.list-actions
+ - if figures_form.commercial_figures_file.present?
+ = render(partial: "admin/figures_and_vat_returns/file", collection: Array.wrap(figures_form.commercial_figures_file), as: :attachment)
+ .clear
-#commercial-figures-attachment-form
- = render("admin/figures_and_vat_returns/form", form_answer: form_answer, attachment: figures_form.commercial_figures_file || figures_form.build_commercial_figures_file)
+ #commercial-figures-attachment-form
+ = render("admin/figures_and_vat_returns/form", form_answer: form_answer, attachment: figures_form.commercial_figures_file || figures_form.build_commercial_figures_file)
diff --git a/app/views/admin/figures_and_vat_returns/_file.html.slim b/app/views/admin/figures_and_vat_returns/_file.html.slim
index 573d9f6d8..ddf1b1a8f 100644
--- a/app/views/admin/figures_and_vat_returns/_file.html.slim
+++ b/app/views/admin/figures_and_vat_returns/_file.html.slim
@@ -3,7 +3,7 @@
- if show_shortlisted_document?(attachment)
small.pull-right
= form_for([namespace_name, attachment.form_answer, attachment],
- html: { class: "#{attachment.model_name.param_key.dasherize}-destroyer", method: :delete, style: "display:inline-block;" }) do |f|
+ html: { class: "#{attachment.model_name.param_key.dasherize}-destroyer", method: :delete, style: "display:inline-block;", data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" } }) do |f|
= f.submit 'Remove', class: 'if-js-hide'
diff --git a/app/views/admin/figures_and_vat_returns/_form.html.slim b/app/views/admin/figures_and_vat_returns/_form.html.slim
index 7b2be8c2f..8a5f591c9 100644
--- a/app/views/admin/figures_and_vat_returns/_form.html.slim
+++ b/app/views/admin/figures_and_vat_returns/_form.html.slim
@@ -11,7 +11,7 @@
.errors
.alert.alert-danger[data-controller="element-removal" role="alert"]
= form.object.errors.full_messages.join(", ")
- button[type="button" class="close" data-action="click->element-removal#remove" aria-label="Close" style="font-size: 18px;"]
+ button[type="button" class="close" data-action="click->element-removal#remove" aria-label="Close"]
span[aria-hidden="true"] ×
.attachment-link.if-js-hide
diff --git a/app/views/admin/figures_and_vat_returns/_vat_returns.html.slim b/app/views/admin/figures_and_vat_returns/_vat_returns.html.slim
index 8d9aeb453..9d2e27bc5 100644
--- a/app/views/admin/figures_and_vat_returns/_vat_returns.html.slim
+++ b/app/views/admin/figures_and_vat_returns/_vat_returns.html.slim
@@ -1,13 +1,14 @@
label
| Latest financial statements and VAT returns
-.document-list.space-y-3
- p.p-empty class="#{'visuallyhidden' if figures_form.vat_returns_files.any?}"
- ' No documents have been attached.
- ul.list-unstyled.list-actions
- - if figures_form.vat_returns_files.any?
- = render(partial: "admin/figures_and_vat_returns/file", collection: figures_form.vat_returns_files, as: :attachment)
- .clear
+div[data-controller="inline-flash"]
+ .document-list.space-y-3
+ p.p-empty class="#{'visuallyhidden' if figures_form.vat_returns_files.any?}"
+ ' No documents have been attached.
+ ul.list-unstyled.list-actions
+ - if figures_form.vat_returns_files.any?
+ = render(partial: "admin/figures_and_vat_returns/file", collection: figures_form.vat_returns_files, as: :attachment)
+ .clear
-#vat-returns-attachment-form
- = render("admin/figures_and_vat_returns/form", form_answer: form_answer, attachment: figures_form.vat_returns_files.build)
+ #vat-returns-attachment-form
+ = render("admin/figures_and_vat_returns/form", form_answer: form_answer, attachment: figures_form.vat_returns_files.build)
diff --git a/app/views/admin/form_answer_attachments/_form.html.slim b/app/views/admin/form_answer_attachments/_form.html.slim
index 14127c8da..04b8c1908 100644
--- a/app/views/admin/form_answer_attachments/_form.html.slim
+++ b/app/views/admin/form_answer_attachments/_form.html.slim
@@ -3,14 +3,18 @@
/ whether file was saved or not
.span
= hidden_field_tag "valid", "false", id: "form-answer-attachment-valid"
-= form_for [namespace_name, form_answer, form_answer_attachment], html: { multipart: true } do |form|
+= form_for [namespace_name, form_answer, form_answer_attachment], html: { multipart: true, data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" } } do |form|
.well.js-attachment-form
h3 Attach document
- if form.object.errors.any?
- .errors = form.object.errors.full_messages.join(", ")
+ .alert.alert-danger[data-controller="element-removal" role="alert"]
+ = form.object.errors.full_messages.join(", ")
+ button[type="button" class="close" data-action="click->element-removal#remove" aria-label="Close"]
+ span[aria-hidden="true"] ×
.attachment-link.if-js-hide
+ = form.label :file, "Attach document", class: "visuallyhidden"
= form.file_field :file
.form-group
diff --git a/app/views/admin/form_answer_attachments/_form_answer_attachment.html.slim b/app/views/admin/form_answer_attachments/_form_answer_attachment.html.slim
index 7a2d2bfe2..99356008b 100644
--- a/app/views/admin/form_answer_attachments/_form_answer_attachment.html.slim
+++ b/app/views/admin/form_answer_attachments/_form_answer_attachment.html.slim
@@ -4,7 +4,7 @@
- if show_remove_form_answer_attachment?(form_answer_attachment)
small.pull-right
= form_for([namespace_name, form_answer_attachment.form_answer, form_answer_attachment],
- html: { data: { inline_flash_target: "form" }, method: :delete, style: "display: inline-block;" }) do |f|
+ html: { data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" }, method: :delete, style: "display: inline-block;" }) do |f|
= f.submit 'Remove', class: 'if-js-hide'
diff --git a/app/views/admin/form_answers/_comment.html.slim b/app/views/admin/form_answers/_comment.html.slim
index d5ab863bb..1549cab69 100644
--- a/app/views/admin/form_answers/_comment.html.slim
+++ b/app/views/admin/form_answers/_comment.html.slim
@@ -6,7 +6,7 @@
p Delete this comment?
.btn-actions
= form_for [namespace_name, @form_answer, comment],
- html: { method: :delete, class: "destroy-comment"} do |f|
+ html: { method: :delete, class: "destroy-comment", id: "overlay-destroy-comment", data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" } } do |f|
= f.submit 'Yes', class: "btn btn-danger link-delete-comment-confirm"
'
@@ -25,7 +25,7 @@
- if comment.author?(current_subject)
= form_for [namespace_name, @form_answer, comment],
- html: { method: :delete, class: "destroy-comment"} do |f|
+ html: { method: :delete, class: "destroy-comment", id: "destroy-comment", data: { inline_flash_target: "form", action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error" } } do |f|
= f.submit 'Delete', class: "btn btn-danger link-delete-comment-confirm"
@@ -37,7 +37,7 @@
authenticity_token: true) do |f|
label.if-js-hide Flag
- = f.check_box :flagged, class: "flag-comment-checkbox if-js-hide"
+ = f.check_box :flagged, class: "flag-comment-checkbox if-js-hide", id: "flag-comment-#{comment.id}"
.comment-action
= l comment.created_at, format: :date_at_time
span.divider •
diff --git a/app/views/admin/form_answers/_financials_review.html.slim b/app/views/admin/form_answers/_financials_review.html.slim
index 082ed2b1a..af85daba9 100644
--- a/app/views/admin/form_answers/_financials_review.html.slim
+++ b/app/views/admin/form_answers/_financials_review.html.slim
@@ -7,7 +7,7 @@
= simple_form_for([namespace_name, review_audit_certificate],
remote: true,
authenticity_token: true,
- html: { controller: "inline-flash", inline_flash_target: "form" }) do |f|
+ html: { data: { controller: "inline-flash", inline_flash_target: "form" } }) do |f|
= f.input :form_answer_id, as: :hidden
diff --git a/app/views/admin/form_answers/_previous_applications_section.html.slim b/app/views/admin/form_answers/_previous_applications_section.html.slim
index 997af30f8..172ab2fc2 100644
--- a/app/views/admin/form_answers/_previous_applications_section.html.slim
+++ b/app/views/admin/form_answers/_previous_applications_section.html.slim
@@ -10,4 +10,5 @@
- else
= application.award_type_and_year
- else
- ' None
+ li
+ ' None
diff --git a/app/views/admin/form_answers/_section_appraisal_form_moderated.html.slim b/app/views/admin/form_answers/_section_appraisal_form_moderated.html.slim
index 4e34590b7..00d8ad505 100644
--- a/app/views/admin/form_answers/_section_appraisal_form_moderated.html.slim
+++ b/app/views/admin/form_answers/_section_appraisal_form_moderated.html.slim
@@ -1,18 +1,18 @@
-.panel.panel-default
+.panel.panel-default[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#appraisal-form-moderated-heading
h3.panel-title
- a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-moderated" aria-expanded="true" aria-controls="section-appraisal-form-moderated"
+ a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-moderated" aria-expanded="true" aria-controls="section-appraisal-form-moderated" data-element-focus-target="reveal"
' Appraisal Form (Moderated)
- if moderated_assessment.last_editor_info.present?
small
= moderated_assessment.last_editor_info
- #section-appraisal-form-moderated.section-appraisal-form.section-appraisal-form-moderated.panel-collapse.collapse[aria-labelledby="appraisal-form-moderated-heading"]
+ #section-appraisal-form-moderated.section-appraisal-form.section-appraisal-form-moderated.panel-collapse.collapse[aria-labelledby="appraisal-form-moderated-heading" data-controller="appraisal-form" data-appraisal-form-success-value="Appraisal form (moderated) has been submitted"]
.panel-body[data-controller="inline-flash"]
= simple_form_for([namespace_name, moderated_assessment],
remote: true,
authenticity_token: true,
- html: { data: { type: "json", inline_flash_target: "form", controller: "html5-form-validation", html5_form_validation_selectors_value: ["textarea"] } }) do |f|
+ html: { data: { type: "json", inline_flash_target: "form" } }) do |f|
= render_section(resource, f)
= hidden_field_tag :updated_section
diff --git a/app/views/admin/form_answers/_section_appraisal_form_primary.html.slim b/app/views/admin/form_answers/_section_appraisal_form_primary.html.slim
index 12430e2f2..b6708f1dc 100644
--- a/app/views/admin/form_answers/_section_appraisal_form_primary.html.slim
+++ b/app/views/admin/form_answers/_section_appraisal_form_primary.html.slim
@@ -1,17 +1,17 @@
-.panel.panel-default
+.panel.panel-default[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#appraisal-form-primary-heading
h3.panel-title
- a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-primary" aria-expanded="true" aria-controls="section-appraisal-form-primary"
+ a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-primary" aria-expanded="true" aria-controls="section-appraisal-form-primary" data-element-focus-target="reveal"
' Appraisal Form (Primary)
- if primary_assessment.last_editor_info.present?
small
= primary_assessment.last_editor_info
- #section-appraisal-form-primary.section-appraisal-form.section-appraisal-form-primary.panel-collapse.collapse aria-labelledby="appraisal-form-primary-heading"
+ #section-appraisal-form-primary.section-appraisal-form.section-appraisal-form-primary.panel-collapse.collapse[aria-labelledby="appraisal-form-primary-heading" data-controller="appraisal-form" data-appraisal-form-success-value="Appraisal form (primary) has been submitted"]
.panel-body[data-controller="inline-flash"]
= simple_form_for([namespace_name, primary_assessment],
remote: true,
authenticity_token: true,
- html: { data: { type: "json", inline_flash_target: "form", html5_form_validation_selectors_value: ["textarea"], controller: "html5-form-validation" }, id: "primary_appraisal_form" }) do |f|
+ html: { data: { type: "json", inline_flash_target: "form" }, id: "primary_appraisal_form" }) do |f|
= hidden_field_tag :updated_section, nil, id: "primary_updated_section_hidden_field"
= render_section(resource, f)
diff --git a/app/views/admin/form_answers/_section_appraisal_form_secondary.html.slim b/app/views/admin/form_answers/_section_appraisal_form_secondary.html.slim
index 27e6acd61..c76ed0d29 100644
--- a/app/views/admin/form_answers/_section_appraisal_form_secondary.html.slim
+++ b/app/views/admin/form_answers/_section_appraisal_form_secondary.html.slim
@@ -1,17 +1,17 @@
-.panel.panel-default
+.panel.panel-default[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#appraisal-form-secondary-heading
h3.panel-title
- a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-secondary" aria-expanded="true" aria-controls="section-appraisal-form-secondary"
+ a data-toggle="collapse" data-parent="#panel-assessment" href="#section-appraisal-form-secondary" aria-expanded="true" aria-controls="section-appraisal-form-secondary" data-element-focus-target="reveal"
' Appraisal Form (Secondary)
- if secondary_assessment.last_editor_info.present?
small
= secondary_assessment.last_editor_info
- #section-appraisal-form-secondary.section-appraisal-form.section-appraisal-form-secondary.panel-collapse.collapse aria-labelledby="appraisal-form-secondary-heading"
+ #section-appraisal-form-secondary.section-appraisal-form.section-appraisal-form-secondary.panel-collapse.collapse[aria-labelledby="appraisal-form-secondary-heading" data-controller="appraisal-form" data-appraisal-form-success-value="Appraisal form (secondary) has been submitted"]
.panel-body[data-controller="inline-flash"]
= simple_form_for([namespace_name, secondary_assessment],
remote: true,
authenticity_token: true,
- html: { data: { type: "json", inline_flash_target: "form", controller: "html5-form-validation", html5_form_validation_selectors_value: ["textarea"] }, id: "secondary_appraisal_form"}) do |f|
+ html: { data: { type: "json", inline_flash_target: "form" }, id: "secondary_appraisal_form"}) do |f|
= hidden_field_tag :updated_section, nil, id: "secondary_updated_section_hidden_field"
= render_section(resource, f)
diff --git a/app/views/admin/form_answers/_section_case_summary.html.slim b/app/views/admin/form_answers/_section_case_summary.html.slim
index 7bc5b8538..0077f5aaf 100644
--- a/app/views/admin/form_answers/_section_case_summary.html.slim
+++ b/app/views/admin/form_answers/_section_case_summary.html.slim
@@ -1,29 +1,20 @@
- if visible_case_summaries(current_subject, resource)
- visible_case_summaries(current_subject, resource).each do |assessment_obj|
- assessment = assessment_obj.assessment
- .panel.panel-parent
+ .panel.panel-parent.panel-default[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading id="case-summary-heading-#{assessment.position}"
h3.panel-title
- a data-toggle="collapse" href="#section-case-summary-#{assessment.position}" aria-expanded="true" aria-controls="section-case-summary-#{assessment.position}"
+ a data-toggle="collapse" href="#section-case-summary-#{assessment.position}" aria-expanded="true" aria-controls="section-case-summary-#{assessment.position}" data-element-focus-target="reveal"
' Case Summary (for recommended or reserved applications only)
small.panel-subtitle-small
| This will be presented to the panel members and is used when making the final decision
- if assessment.editable.present?
small
= "Updated by #{message_author_name(assessment.editable)} - #{format_date(assessment.updated_at)}"
- .panel-collapse.collapse aria-labelledby="case-summary-heading-#{assessment.position}" id="section-case-summary-#{assessment.position}" class="section-case-summary-#{assessment.position}"
+ .panel-collapse.collapse[aria-labelledby="case-summary-heading-#{assessment.position}" id="section-case-summary-#{assessment.position}" class="section-case-summary-#{assessment.position}" data-controller="appraisal-form" data-appraisal-form-success-value="Case summary has been submitted"]
.panel-body[data-controller="inline-flash"]
- /.alert.alert-glyphicon.alert-info
- span.glyphicon.glyphicon-info-sign
- p.todo-placeholder
- ' Some instructions on how to use this or what this section is about. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.
-
- / Only show if Moderated Appraisal is submitted
- / For Primary Assessor
- / It becomes read-only for primary assessor after submission
-
- = simple_form_for([namespace_name, assessment], remote: true, authenticity_token: true, html: { data: { inline_flash_target: "form", controller: "html5-form-validation", html5_form_validation_selectors_value: ["textarea"] } }) do |f|
+ = simple_form_for([namespace_name, assessment], remote: true, authenticity_token: true, html: { data: { inline_flash_target: "form" } }) do |f|
= render partial: "admin/form_answers/appraisal_form_components/application_background_section",
locals: { f: f}
= render_section(resource, f)
diff --git a/app/views/admin/form_answers/_section_company_details.html.slim b/app/views/admin/form_answers/_section_company_details.html.slim
index fc8ce6b9b..ba8074c09 100644
--- a/app/views/admin/form_answers/_section_company_details.html.slim
+++ b/app/views/admin/form_answers/_section_company_details.html.slim
@@ -1,4 +1,4 @@
-.panel.panel-default[data-controller="element-focus"]
+.panel.panel-default[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#company-details-heading
h3.panel-title
a data-toggle="collapse" data-parent="#panel-application-info" href="#section-company-details" aria-expanded="true" aria-controls="section-company-details" data-element-focus-target="reveal"
diff --git a/app/views/admin/form_answers/_section_documents.html.slim b/app/views/admin/form_answers/_section_documents.html.slim
index 30017bb46..f25fbebc5 100644
--- a/app/views/admin/form_answers/_section_documents.html.slim
+++ b/app/views/admin/form_answers/_section_documents.html.slim
@@ -27,16 +27,17 @@
' Post Shortlisting Docs
- if @form_answer.requires_vocf?
- .document-list.space-y-2
- = render(partial: "admin/form_answers/docs/status", locals: { form_answer: @form_answer })
- = render "admin/form_answers/docs/post_shortlisting_docs", resource: resource
+ div[data-controller="inline-flash"]
+ .document-list.space-y-2
+ = render(partial: "admin/form_answers/docs/status", locals: { form_answer: @form_answer })
+ = render "admin/form_answers/docs/post_shortlisting_docs", resource: resource
- - if @form_answer.audit_certificate.blank? && Settings.after_shortlisting_stage?
- .sidebar-section.no-margin-bottom.space-y-3
- - if @form_answer.requires_vocf?
- #audit-certificate-form[data-controller="inline-flash"]
- - audit_certificate = @form_answer.build_audit_certificate
- = render "admin/audit_certificate/form", form_answer: @form_answer, audit_certificate: audit_certificate
+ - if @form_answer.audit_certificate.blank? && Settings.after_shortlisting_stage?
+ .sidebar-section.no-margin-bottom.space-y-3
+ - if @form_answer.requires_vocf?
+ #audit-certificate-form[data-controller="inline-flash"]
+ - audit_certificate = @form_answer.build_audit_certificate
+ = render "admin/audit_certificate/form", form_answer: @form_answer, audit_certificate: audit_certificate
- elsif @form_answer.provided_estimates?
- figures_form = @form_answer.shortlisted_documents_wrapper || @form_answer.build_shortlisted_documents_wrapper
@@ -57,16 +58,17 @@
.sidebar-section
h2
' Other Docs
- .document-list
- p.p-empty class="#{'visuallyhidden' if @form_answer.form_answer_attachments.any?}"
- ' No documents have been attached.
- ul.list-unstyled.list-actions
- - if @form_answer.form_answer_attachments.uploaded_not_by_user.any?
- = render(partial: "admin/form_answer_attachments/form_answer_attachment", collection: @form_answer.form_answer_attachments.uploaded_not_by_user.visible_for(current_subject))
- .clear
- br
- #application-attachment-form
- = render "admin/form_answer_attachments/form", form_answer: @form_answer, form_answer_attachment: @form_answer.form_answer_attachments.build
+ div[data-controller="inline-flash"]
+ .document-list
+ p.p-empty class="#{'visuallyhidden' if @form_answer.form_answer_attachments.any?}"
+ ' No documents have been attached.
+ ul.list-unstyled.list-actions
+ - if @form_answer.form_answer_attachments.uploaded_not_by_user.any?
+ = render(partial: "admin/form_answer_attachments/form_answer_attachment", collection: @form_answer.form_answer_attachments.uploaded_not_by_user.visible_for(current_subject))
+ .clear
+ br
+ #application-attachment-form
+ = render "admin/form_answer_attachments/form", form_answer: @form_answer, form_answer_attachment: @form_answer.form_answer_attachments.build
#audit-certificate-buffer
diff --git a/app/views/admin/form_answers/_submitted_view.html.slim b/app/views/admin/form_answers/_submitted_view.html.slim
index f2f618d21..56fda0ce7 100644
--- a/app/views/admin/form_answers/_submitted_view.html.slim
+++ b/app/views/admin/form_answers/_submitted_view.html.slim
@@ -1,10 +1,10 @@
- title "Admin: Application #{@form_answer.urn.presence}"
.panel-group#submitted-application-parent-parent
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#application-info-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-application-info" aria-expanded="true" aria-controls="section-application-info"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-application-info" aria-expanded="true" aria-controls="section-application-info" data-element-focus-target="reveal"
' Application info
#section-application-info.section-application-info.panel-collapse.collapse.in aria-labelledby="application-info-heading"
.panel-body
@@ -13,10 +13,10 @@
= render "section_company_details"
= render "section_financial_summary"
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#assessment-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-assessment" aria-expanded="true" aria-controls="section-assessment"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-assessment" aria-expanded="true" aria-controls="section-assessment" data-element-focus-target="reveal"
' Assessment
#section-assessment.section-application-info.panel-collapse.collapse.in aria-labelledby="assessment-heading"
.panel-body
@@ -31,10 +31,10 @@
= render "section_case_summary"
- if show_feedback_section?
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#feedback-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-feedback" aria-expanded="true" aria-controls="section-feedback"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-feedback" aria-expanded="true" aria-controls="section-feedback" data-element-focus-target="reveal"
' Feedback (for not recommended applications only)
small.panel-subtitle-small
| This will be sent to the applicants to help improve their business and/or future award applications
@@ -48,10 +48,10 @@
= render "admin/feedbacks/section", form_answer: @form_answer
- if show_winners_section?
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#winners-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-winners" aria-expanded="true" aria-controls="section-winners"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-winners" aria-expanded="true" aria-controls="section-winners" data-element-focus-target="reveal"
' Recipients
#section-winners.section-application-info.panel-collapse.collapse.in aria-labelledby="winners-heading"
.panel-body
@@ -61,10 +61,10 @@
- if show_palace_attendees_subsection?
= render "section_palace_attendees"
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#logs-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-logs" aria-expanded="true" aria-controls="section-logs"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-logs" aria-expanded="true" aria-controls="section-logs" data-element-focus-target="reveal"
' Application Audit Log
#section-logs.section-application-info.panel-collapse.collapse aria-labelledby="logs-heading"
.panel-body
diff --git a/app/views/admin/form_answers/appraisal_form_components/_application_background_section.html.slim b/app/views/admin/form_answers/appraisal_form_components/_application_background_section.html.slim
index 1b49d9e47..70ef64e0d 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_application_background_section.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_application_background_section.html.slim
@@ -23,5 +23,5 @@
= link_to "#", class: "form-edit-link pull-right", data: { element_focus_target: "reveal" }
span.glyphicon.glyphicon-pencil
' Edit
- = link_to "Save", "#", class: "btn btn-primary form-save-link pull-right if-no-js-hide", data: { action: "click->html5-form-validation#validate" }
+ = link_to "Save", "#", class: "btn btn-primary form-save-link js-form-save-link pull-right if-no-js-hide", data: { action: "click->appraisal-form#stash" }
.clear
diff --git a/app/views/admin/form_answers/appraisal_form_components/_case_summary_submit_block.html.slim b/app/views/admin/form_answers/appraisal_form_components/_case_summary_submit_block.html.slim
index 377907f0c..4952e8d9b 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_case_summary_submit_block.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_case_summary_submit_block.html.slim
@@ -1,6 +1,6 @@
- if policy(assessment).can_be_submitted? || policy(assessment).can_be_re_submitted?
- = form_tag(url_for([namespace_name, :assessment_submissions]), remote: true, authenticity_token: true, class: "submit-assessment", "data-type" => "json")
+ = form_tag(url_for([namespace_name, :assessment_submissions]), remote: true, authenticity_token: true, class: "submit-assessment", data: { action: "ajax:x:success->appraisal-form#success ajax:x:error->appraisal-form#error", type: "json" })
= hidden_field_tag :assessment_id, assessment.id
.feedback-holder
@@ -9,10 +9,21 @@
= submit_tag submit_case_summary_title(assessment), class: "btn btn-primary btn-confirm-submit"
.clear
-- elsif assessment.submitted?
+ template[data-role='template']
+ - if policy(assessment).admin_or_lead?
+ - unlock_url = namespace_name == :admin ? unlock_admin_assessment_submission_url(assessment) : unlock_assessor_assessment_submission_url(assessment)
- - if policy(assessment).can_unlock?
+ = form_tag unlock_url, method: :patch do
+ = hidden_field_tag :assessment_id, assessment.id
+ .feedback-holder.alert.alert-success
+ ' Case Summary Submitted
+
+ .pull-right
+ = submit_tag "Unlock", class: "btn btn-primary"
+ .clear
+- elsif assessment.submitted?
+ - if policy(assessment).can_unlock?
- unlock_url = namespace_name == :admin ? unlock_admin_assessment_submission_url(assessment) : unlock_assessor_assessment_submission_url(assessment)
= form_tag unlock_url, method: :patch do
@@ -29,6 +40,5 @@
' Case Summary Submitted
- elsif !assessment.submitted?
-
.feedback-holder.alert.alert-info
' Case Summary is not submitted yet!
diff --git a/app/views/admin/form_answers/appraisal_form_components/_non_rag_section.html.slim b/app/views/admin/form_answers/appraisal_form_components/_non_rag_section.html.slim
index 3a1610933..b41eb85b8 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_non_rag_section.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_non_rag_section.html.slim
@@ -26,6 +26,6 @@
span.glyphicon.glyphicon-pencil
' Edit
.form-actions.text-right
- = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss", action: "click->html5-form-validation#discard" }
- = link_to "Save", "#", class: "btn btn-primary form-save-link pull-right if-no-js-hide", data: { action: "click->html5-form-validation#validate", updated_section: section.desc }
+ = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss" }
+ = link_to "Save", "#", class: "btn btn-primary form-save-link js-form-save-link pull-right if-no-js-hide", data: { updated_section: section.desc, action: "click->appraisal-form#stash" }
.clear
diff --git a/app/views/admin/form_answers/appraisal_form_components/_rag_section.html.slim b/app/views/admin/form_answers/appraisal_form_components/_rag_section.html.slim
index 6747cf373..0af874821 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_rag_section.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_rag_section.html.slim
@@ -46,6 +46,6 @@
span.glyphicon.glyphicon-pencil
' Edit
.form-actions.text-right
- = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss", action: "click->html5-form-validation#discard" }
- = link_to "Save", "#", class: "btn btn-primary form-save-link pull-right if-no-js-hide", data: { action: "click->html5-form-validation#validate", updated_section: section.desc }
+ = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss" }
+ = link_to "Save", "#", class: "btn btn-primary form-save-link js-form-save-link pull-right if-no-js-hide", data: { updated_section: section.desc, action: "click->appraisal-form#stash" }
.clear
diff --git a/app/views/admin/form_answers/appraisal_form_components/_submit_appraisal_form.html.slim b/app/views/admin/form_answers/appraisal_form_components/_submit_appraisal_form.html.slim
index ecf440071..afd2f9ee3 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_submit_appraisal_form.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_submit_appraisal_form.html.slim
@@ -3,7 +3,7 @@
authenticity_token: true,
remote: true,
class: "submit-assessment",
- data: { type: "json" })
+ data: { action: "ajax:x:success->appraisal-form#success ajax:x:error->appraisal-form#error", type: "json" })
= hidden_field_tag :assessment_id, assessment.id, id: "#{assessment.position}_assessment_id_submit_appraisal_form_hidden_field"
@@ -13,6 +13,19 @@
= submit_tag (assessment.submitted? ? "Re-submit appraisal" : "Submit appraisal"), class: "btn btn-primary btn-confirm-submit"
.clear
+ template[data-role='template']
+ - if policy(assessment).admin_or_lead?
+ - unlock_url = namespace_name == :admin ? unlock_admin_assessment_submission_url(assessment) : unlock_assessor_assessment_submission_url(assessment)
+
+ = form_tag unlock_url, method: :patch do
+ = hidden_field_tag :assessment_id, assessment.id, id: "#{assessment.position}_assessment_id_unlock_appraisal_form_hidden_field"
+ .feedback-holder.alert.alert-success
+ ' Assessment submitted
+
+ .pull-right
+ = submit_tag "Unsubmit", class: "btn btn-primary"
+ .clear
+
- elsif assessment.submitted?
- if policy(assessment).can_unlock?
diff --git a/app/views/admin/form_answers/appraisal_form_components/_verdict_section.html.slim b/app/views/admin/form_answers/appraisal_form_components/_verdict_section.html.slim
index c0102babf..4eacdcbd2 100644
--- a/app/views/admin/form_answers/appraisal_form_components/_verdict_section.html.slim
+++ b/app/views/admin/form_answers/appraisal_form_components/_verdict_section.html.slim
@@ -44,6 +44,6 @@
span.glyphicon.glyphicon-pencil
' Edit
.form-actions.text-right
- = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss", action: "click->html5-form-validation#discard" }
- = link_to "Save", "#", class: "btn btn-primary form-save-link pull-right if-no-js-hide", data: { action: "click->html5-form-validation#validate" }
+ = link_to "Cancel", "#", class: "btn btn-default form-cancel-link if-no-js-hide", data: { element_focus_target: "dismiss" }
+ = link_to "Save", "#", class: "btn btn-primary form-save-link pull-right if-no-js-hide"
.clear
diff --git a/app/views/admin/form_answers/company_details/_goods_services_form.html.slim b/app/views/admin/form_answers/company_details/_goods_services_form.html.slim
index 620fce08e..1351b4703 100644
--- a/app/views/admin/form_answers/company_details/_goods_services_form.html.slim
+++ b/app/views/admin/form_answers/company_details/_goods_services_form.html.slim
@@ -18,7 +18,7 @@
= simple_form_for [namespace_name, resource], remote: true, authenticity_token: true, html: { data: { type: "html", inline_flash_target: "form" }, id: "goods_services_form_admin_appraisal" } do |f|
= hidden_field_tag :section, "goods_services", id: "section_goods_services_hidden_field"
.form-fields.form-block
- = f.simple_fields_for(:data) do |f|
+ = f.simple_fields_for :data, include_id: false do |f|
- if !@form_answer.trade?
= f.input @form_answer.goods_and_services_key, as: :text, label: false, input_html: { class: "form-control js-char-count", rows: 3, "data-word-max" => 15 }
- elsif @form_answer.document["trade_goods_and_services_explanations"].present?
diff --git a/app/views/admin/form_answers/company_details/_organisation_head_form.html.slim b/app/views/admin/form_answers/company_details/_organisation_head_form.html.slim
index 9772d1ea0..c8df35163 100644
--- a/app/views/admin/form_answers/company_details/_organisation_head_form.html.slim
+++ b/app/views/admin/form_answers/company_details/_organisation_head_form.html.slim
@@ -25,7 +25,7 @@
- if @form_answer.head_of_business_email.present?
= @form_answer.head_of_business_email
.form-fields.form-block
- = f.simple_fields_for(:data) do |f|
+ = f.simple_fields_for :data, include_id: false do |f|
.row
.col-md-2
= f.input :head_of_business_title,
diff --git a/app/views/admin/form_answers/company_details/_organisation_type_form.html.slim b/app/views/admin/form_answers/company_details/_organisation_type_form.html.slim
index 0b08fde0d..8a98a5321 100644
--- a/app/views/admin/form_answers/company_details/_organisation_type_form.html.slim
+++ b/app/views/admin/form_answers/company_details/_organisation_type_form.html.slim
@@ -20,7 +20,7 @@
.form-fields.form-block
.row
.col-xs-6.col-md-6
- = f.simple_fields_for(:data) do |f|
+ = f.simple_fields_for :data, include_id: false do |f|
= f.input :organisation_type,
collection: AppraisalFormHelper::COMPANY_ORGANISATION_TYPES,
label: false,
diff --git a/app/views/admin/form_answers/company_details/_registration_number_form.html.slim b/app/views/admin/form_answers/company_details/_registration_number_form.html.slim
index a4a84b6bd..2d28b1ac0 100644
--- a/app/views/admin/form_answers/company_details/_registration_number_form.html.slim
+++ b/app/views/admin/form_answers/company_details/_registration_number_form.html.slim
@@ -16,7 +16,7 @@
- else
em.text-muted No company/charity registration number added yet.
.form-fields.form-block
- = f.simple_fields_for(:data) do |f|
+ = f.simple_fields_for :data, include_id: false do |f|
= f.input :registration_number,
as: :string,
label: false,
diff --git a/app/views/admin/form_answers/company_details/_website_form.html.slim b/app/views/admin/form_answers/company_details/_website_form.html.slim
index 319abec8a..271dc91dd 100644
--- a/app/views/admin/form_answers/company_details/_website_form.html.slim
+++ b/app/views/admin/form_answers/company_details/_website_form.html.slim
@@ -16,7 +16,7 @@
- else
em.text-muted No website added.
.form-fields.form-block
- = f.simple_fields_for(:data) do |f|
+ = f.simple_fields_for :data, include_id: false do |f|
= f.input :website_url,
as: :string,
label: false,
diff --git a/app/views/admin/form_answers/docs/_application_and_supporting_docs.html.slim b/app/views/admin/form_answers/docs/_application_and_supporting_docs.html.slim
index 7699b7983..d7eb6c2b9 100644
--- a/app/views/admin/form_answers/docs/_application_and_supporting_docs.html.slim
+++ b/app/views/admin/form_answers/docs/_application_and_supporting_docs.html.slim
@@ -1,4 +1,4 @@
-.document-list
+.document-list[data-controller="inline-flash"]
- if @form_answer.form_answer_attachments.uploaded_by_user.any? || @form_answer.support_letters.any?
ul.list-unstyled.list-actions
diff --git a/app/views/admin/form_answers/winners_components/_palace_attendee.html.slim b/app/views/admin/form_answers/winners_components/_palace_attendee.html.slim
index 24f07136b..df16ad612 100644
--- a/app/views/admin/form_answers/winners_components/_palace_attendee.html.slim
+++ b/app/views/admin/form_answers/winners_components/_palace_attendee.html.slim
@@ -1,4 +1,4 @@
-.form-group.palace-attendee-container[class=("form-edit" if pa.errors.present? || defined?(@enable_edition)) data-controller="element-focus"]
+.form-group.palace-attendee-container[class=("form-edit" if pa.errors.present? || defined?(@enable_edition)) data-controller="inline-flash element-focus"]
.form-value
.empty-message class="#{'visuallyhidden' if palace_invite.palace_attendees.exists?}"
p.p-empty No attendees confirmed.
diff --git a/app/views/admin/form_answers/winners_components/_palace_attendee_form.html.slim b/app/views/admin/form_answers/winners_components/_palace_attendee_form.html.slim
index d73d9814c..1bbf66cf4 100644
--- a/app/views/admin/form_answers/winners_components/_palace_attendee_form.html.slim
+++ b/app/views/admin/form_answers/winners_components/_palace_attendee_form.html.slim
@@ -2,12 +2,12 @@ ul.list-add.list-attendees class=('if-js-hide' if palace_attendee.new_record? &&
li.well
.pull-right
- unless palace_attendee.new_record?
- = simple_form_for([namespace_name, palace_attendee], remote: true, authenticity_token: true, method: :delete, html: { class: "remove-palace-attendee-form" }) do |f|
+ = simple_form_for([namespace_name, palace_attendee], remote: true, authenticity_token: true, method: :delete, html: { class: "remove-palace-attendee-form", data: { inline_flash_target: "form" } }) do |f|
= f.input :palace_invite_id, as: :hidden
= f.submit "Remove", class: "if-js-hide"
= link_to "Remove", "", class: "remove-palace-attendee if-no-js-hide", data: {confirm: "Are you sure?"}
- = simple_form_for([namespace_name, palace_attendee], remote: true, authenticity_token: true, html: { class: "palace-attendee-form" }) do |f|
+ = simple_form_for([namespace_name, palace_attendee], remote: true, authenticity_token: true, html: { class: "palace-attendee-form", data: { inline_flash_target: "form" } }) do |f|
= f.input :palace_invite_id, as: :hidden
.row
.col-md-2
diff --git a/app/views/admin/judges/_form.html.slim b/app/views/admin/judges/_form.html.slim
index 63a29d781..e188f7d6b 100644
--- a/app/views/admin/judges/_form.html.slim
+++ b/app/views/admin/judges/_form.html.slim
@@ -1,4 +1,4 @@
-= simple_form_for [:admin, resource], as: :judge, url: resource.persisted? ? admin_judge_path(resource) : admin_judges_path, html: { class: 'qae-form' } do |f|
+= simple_form_for [:admin, resource], as: :judge, url: resource.persisted? ? admin_judge_path(resource) : admin_judges_path, html: { class: 'qae-form', data: { type: "json", controller: "inline-flash element-scroll", inline_flash_target: "form" } } do |f|
.row.question-group
.col-lg-2.col-md-3.col-sm-4
h3 = f.label :first_name, class: "form-label"
@@ -26,6 +26,15 @@
.question-group#password-change-panel
#password-control-group
h3 = f.label :password, class: "form-label"
+ .guidance-panel.if-no-js-hide
+ .govuk-form-group--error#password-guidance
+ p.govuk-error-message.text-underline Please improve your password
+ p.govuk-error-message#password-too-short
+ ' It must be at least 10 characters.
+ p.govuk-error-message#parts-of-email It shouldn't include part or all of your email address.
+ p.govuk-error-message#password-entropy
+ ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
+
.row
.col-md-4.col-sm-6
.input-group
@@ -33,19 +42,9 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control' },
label: false
- span#password-result-span.input-group-addon
+ span#password-result-span.input-group-addon.hide
i#password-result.glyphicon.glyphicon-ok
.clear
- .guidance-panel.if-no-js-hide
- #password-guidance
- br
- .alert.alert-warning
- p.text-underline Please improve your password
- p#password-too-short
- ' It must be at least 10 characters.
- p#parts-of-email It shouldn't include part or all of your email address.
- p#password-entropy
- ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
#password-confirmation-control-group
h3 = f.label :password_confirmation, label: "Retype password", class: "form-label"
@@ -56,15 +55,13 @@
wrapper_html: { class: 'form-group' },
input_html: { class: 'form-control' },
label: false
- span#password-confirmation-result-span.input-group-addon
+ span#password-confirmation-result-span.input-group-addon.hide
i#password-confirmation-result.glyphicon.glyphicon-ok
.clear
.if-no-js-hide
- #password-confirmation-guidance
- br
- .alert.alert-warning
- p#password-confirmation-match The confirmation must match the password
+ .govuk-form-group--error#password-confirmation-guidance
+ p.govuk-error-message#password-confirmation-match The confirmation must match the password
br
diff --git a/app/views/admin/settings/_email_notification.html.slim b/app/views/admin/settings/_email_notification.html.slim
index 4fac1ba1b..3f74339f0 100644
--- a/app/views/admin/settings/_email_notification.html.slim
+++ b/app/views/admin/settings/_email_notification.html.slim
@@ -7,7 +7,7 @@
span.email-notification-help
- if (help_message = t("email_notification_help_messages.#{kind}", default: "")).present?
- span.glyphicon-info-sign.help-message
+ span.glyphicon-info-sign.help-message role="tooltip" aria-label=help_message
span.help-message-text
= help_message
diff --git a/app/views/admin/settings/_notification.html.slim b/app/views/admin/settings/_notification.html.slim
index b60ca7ba3..60ab8eb71 100644
--- a/app/views/admin/settings/_notification.html.slim
+++ b/app/views/admin/settings/_notification.html.slim
@@ -14,9 +14,9 @@ li id="notification-#{notification.id}"
- if policy(notification).destroy?
span.if-no-js-hide
' |
- = button_to "Delete", admin_settings_email_notification_path(notification), { onclick: "return confirm('Are you sure?')", method: :delete, remote: true }
+ = button_to "Delete", admin_settings_email_notification_path(notification), { onclick: "return confirm('Are you sure?')", method: :delete, remote: true, data: { action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error", inline_flash_target: "form" } }
.notification-edit-form.well
- = simple_form_for notification, url: admin_settings_email_notification_path(notification, year: params[:year]), remote: true, authenticity_token: true, html: { data: { inline_flash_target: "form", controller: "html5-form-validation", html5_form_validation_selectors_value: ["input"] } } do |f|
+ = simple_form_for notification, url: admin_settings_email_notification_path(notification, year: params[:year]), remote: true, authenticity_token: true, html: { data: { action: "ajax:x:success->inline-flash#success ajax:x:error->inline-flash#error", inline_flash_target: "form", controller: "html5-form-validation", html5_form_validation_selectors_value: ["input"] } } do |f|
.control-date
label.control-label Edit schedule
= f.input :trigger_at,
diff --git a/app/views/admin/users/_fields_password.html.slim b/app/views/admin/users/_fields_password.html.slim
index 02de52d9a..e9ce0f421 100644
--- a/app/views/admin/users/_fields_password.html.slim
+++ b/app/views/admin/users/_fields_password.html.slim
@@ -18,6 +18,14 @@
- else
= f.label :password, label: "Password"
- password_hint = ""
+ .guidance-panel.if-no-js-hide
+ .govuk-form-group--error#password-guidance
+ p.govuk-error-message.text-underline Please improve your password
+ p.govuk-error-message#password-too-short
+ ' It must be at least 10 characters.
+ p.govuk-error-message#parts-of-email It shouldn't include part or all of your email address.
+ p.govuk-error-message#password-entropy
+ ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
.row
.col-md-4.col-sm-6
.input-group
@@ -25,22 +33,15 @@
wrapper_html: { class: "form-group" },
input_html: { class: "form-control password-strength-meter" },
label_html: { class: "visuallyhidden" }
- span#password-result-span.input-group-addon
+ span#password-result-span.input-group-addon.hide
i#password-result.glyphicon.glyphicon-ok
span.hint = password_hint
- .guidance-panel.if-no-js-hide
- #password-guidance
- .alert.alert-warning
- p.text-underline Please improve your password
- p#password-too-short
- ' It must be at least 10 characters.
- p#parts-of-email It shouldn't include part or all of your email address.
- p#password-entropy
- ' It must be more complex. Consider using whole sentences (with spaces), lyrics or phrases to make it more memorable.
-
.question-group#password-confirmation-control-group
h3 = f.label :password_confirmation, label: "Retype password"
+ .if-no-js-hide
+ .govuk-form-group--error#password-confirmation-guidance
+ p.govuk-error-message#password-confirmation-match The confirmation must match the password
.row
.col-md-4.col-sm-6
.input-group
@@ -48,11 +49,5 @@
wrapper_html: { class: "form-group" },
input_html: { class: "form-control" },
label_html: { class: "visuallyhidden" }
- span#password-confirmation-result-span.input-group-addon
+ span#password-confirmation-result-span.input-group-addon.hide
i#password-confirmation-result.glyphicon.glyphicon-ok
-
- .if-no-js-hide
- #password-confirmation-guidance
- br
- .alert.alert-warning
- p#password-confirmation-match The confirmation must match the password
diff --git a/app/views/assessor/form_answers/_bulk_assignment.html.slim b/app/views/assessor/form_answers/_bulk_assignment.html.slim
index 78ffd2bee..8c1b852c3 100644
--- a/app/views/assessor/form_answers/_bulk_assignment.html.slim
+++ b/app/views/assessor/form_answers/_bulk_assignment.html.slim
@@ -1,6 +1,7 @@
- if show_bulk_assignment?
.if-no-js-hide[data-controller="element-focus"]
- .btn.bulk-assign-assessors-link[data-element-focus-target="reveal"] Bulk Assign Assessors
+ button.btn.bulk-assign-assessors-link[data-element-focus-target="reveal" type="button"]
+ | Bulk Assign Assessors
.bulk-assign-assessors-form
.well
diff --git a/app/views/assessor/form_answers/_submitted_view.html.slim b/app/views/assessor/form_answers/_submitted_view.html.slim
index aeab1be95..5558e7229 100644
--- a/app/views/assessor/form_answers/_submitted_view.html.slim
+++ b/app/views/assessor/form_answers/_submitted_view.html.slim
@@ -1,8 +1,8 @@
.panel-group#submitted-application-parent
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#application-info-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-application-info" aria-expanded="true" aria-controls="section-application-info"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-application-info" aria-expanded="true" aria-controls="section-application-info" data-element-focus-target="reveal"
' Application info
#section-application-info.section-application-info.panel-collapse.collapse.in aria-labelledby="application-info-heading"
.panel-body
@@ -11,10 +11,10 @@
= render "admin/form_answers/section_company_details"
= render "admin/form_answers/section_financial_summary"
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#assessment-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-assessment" aria-expanded="true" aria-controls="section-assessment"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-assessment" aria-expanded="true" aria-controls="section-assessment" data-element-focus-target="reveal"
' Assessment
#section-assessment.section-application-info.panel-collapse.collapse.in aria-labelledby="assessment-heading"
.panel-body
@@ -32,10 +32,10 @@
= render "admin/form_answers/section_case_summary"
- if show_feedback_section?
- .panel.panel-default.panel-parent
+ .panel.panel-default.panel-parent[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
.panel-heading#feedback-heading
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-feedback" aria-expanded="true" aria-controls="section-feedback"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-feedback" aria-expanded="true" aria-controls="section-feedback" data-element-focus-target="reveal"
' Feedback (for not recommended applications only)
small.panel-subtitle-small
| This will be sent to the applicants to help improve their business and/or future award applications
@@ -50,9 +50,9 @@
- if show_winners_section?
.panel.panel-default.panel-parent
- .panel-heading#winners-heading
+ .panel-heading#winners-heading[data-controller="element-focus" data-element-focus-selector-value="input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [href='#']"]
h2.panel-title
- a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-winners" aria-expanded="true" aria-controls="section-winners"
+ a data-toggle="collapse" data-parent="#submitted-application-parent" href="#section-winners" aria-expanded="true" aria-controls="section-winners" data-element-focus-target="reveal"
' Recipients
#section-winners.section-application-info.panel-collapse.collapse.in aria-labelledby="winners-heading"
.panel-body
diff --git a/app/views/assessor/form_answers/index.html.slim b/app/views/assessor/form_answers/index.html.slim
index 99b88c377..80ef5bf70 100644
--- a/app/views/assessor/form_answers/index.html.slim
+++ b/app/views/assessor/form_answers/index.html.slim
@@ -34,25 +34,19 @@ h1.admin-page-heading
= simple_form_for @search, url: assessor_form_answers_path, method: :get, as: :search, html: { class: 'search-form', id: 'application_table_search_form' } do |f|
= hidden_field_tag :award_type, category_picker.current_award_type, id: "award_type_application_table_search_form"
- label for="year" class="visuallyhidden" aria-hidden="true"
- ' Award year
- = text_field_tag :year, @award_year.year, class: "visuallyhidden", aria: { hidden: true }
+ = hidden_field_tag :year, @award_year.year
- # status filters need to be here because the filtering is done in the other form above, so in order not to break filtering, we need to duplicate it here
= f.simple_fields_for [:filters, @search.filters] do |h|
- = h.label :status, class: "visuallyhidden", for: "status_application_table_search_form", aria: { hidden: true }
= h.input :status,
collection: FormAnswerStatus::AssessorFilter.options,
label: false,
- input_html: { multiple: true, class: 'visuallyhidden', id: 'status_application_table_search_form' },
- aria: { hidden: true }
+ input_html: { multiple: true, id: 'status_application_table_search_form', class: 'hide' }
- = h.label :sub_status, class: "visuallyhidden", for: "sub_status_application_table_search_form", aria: { hidden: true }
= h.input :sub_status,
collection: FormAnswerStatus::AssessorFilter.sub_options(current_assessor),
label: false,
- input_html: { multiple: true, class: 'visuallyhidden', id: 'sub_status_application_table_search_form'},
- aria: { hidden: true }
+ input_html: { multiple: true, id: 'sub_status_application_table_search_form', class: 'hide'}
.row
.col-xs-12
@@ -61,7 +55,6 @@ h1.admin-page-heading
tr
- if current_subject.categories_as_lead.include?(category_picker.current_award_type)
th
- span.visuallyhidden Select for bulk action
span.if-no-js-hide
= check_box_tag :check_all, "Check all", false, aria: { label: "Select all applications for bulk action" }
th.sortable width="250"
diff --git a/app/views/judge/case_summaries/index.html.slim b/app/views/judge/case_summaries/index.html.slim
index 35553156c..c0247edc8 100644
--- a/app/views/judge/case_summaries/index.html.slim
+++ b/app/views/judge/case_summaries/index.html.slim
@@ -5,7 +5,7 @@
.downloads-page
.downloads-page__section
- h3
+ h2
' Case Summaries
ul.download-list
- FormAnswer::AWARD_TYPE_FULL_NAMES.select { |key, value| current_judge.assigned_award_types.include?(key) }.each do |key, value|
diff --git a/app/views/layouts/_vertical_admin_award_year.html.slim b/app/views/layouts/_vertical_admin_award_year.html.slim
index 453df072e..c41a679eb 100644
--- a/app/views/layouts/_vertical_admin_award_year.html.slim
+++ b/app/views/layouts/_vertical_admin_award_year.html.slim
@@ -1,4 +1,4 @@
-.col-lg-2.col-md-3.col-sm-4.award-year-z-index.applications-filter
+.col-md-3.col-sm-4.award-year-z-index.applications-filter
label.applications-filter__label
' Award year
.dropdown
diff --git a/app/views/layouts/application-admin.html.slim b/app/views/layouts/application-admin.html.slim
index 25b0cbe50..edcc389b8 100644
--- a/app/views/layouts/application-admin.html.slim
+++ b/app/views/layouts/application-admin.html.slim
@@ -79,8 +79,28 @@ html.no-js
= link_to "Data Export Log", admin_audit_logs_path
ul.nav.navbar-nav.navbar-right
- li.dropdown
- a.dropdown-toggle href="#" data-toggle="dropdown" role="button" aria-expanded="false"
+ li
+ details.if-js-hide.dropdown-toggle
+ summary
+ ' My Account
+ span.caret
+ ul.dropdown-menu
+ li
+ span
+ strong = current_subject.decorate.full_name
+ br
+ small = current_subject.email
+ li.divider
+ - unless current_admin.authy_enabled
+ li
+ = link_to "Enable 2FA", admin_enable_authy_path
+ li
+ = button_to "Sign out",
+ destroy_admin_session_path,
+ method: :delete,
+ class: "btn as-link"
+
+ a.dropdown-toggle.if-no-js-hide href="#" data-toggle="dropdown" role="button" aria-expanded="false"
' My account
span.caret
ul.dropdown-menu
@@ -99,6 +119,7 @@ html.no-js
method: :delete
= render "shared/dev_or_staging_banner"
= render "shared/non_js_banner"
+ = render "shared/timeout_warning_popup"
#main-container role="main"
.container
diff --git a/app/views/layouts/application-assessor.html.slim b/app/views/layouts/application-assessor.html.slim
index 6323148a3..f90988523 100644
--- a/app/views/layouts/application-assessor.html.slim
+++ b/app/views/layouts/application-assessor.html.slim
@@ -60,8 +60,25 @@ html.no-js
= link_to "Reports", assessor_reports_path(year: @award_year.year), role: "tab"
ul.nav.navbar-nav.navbar-right
- li.dropdown
- a.dropdown-toggle href="#" data-toggle="dropdown" role="button" aria-expanded="false"
+ li
+ details.if-js-hide
+ summary
+ ' My Account
+ span.caret
+ ul.dropdown-menu
+ li
+ span
+ strong = current_subject.decorate.full_name
+ br
+ small = current_subject.email
+ li.divider
+ li
+ = button_to "Sign out",
+ destroy_assessor_session_path,
+ method: :delete,
+ class: "btn as-link"
+
+ a.dropdown-toggle.if-no-js-hide href="#" data-toggle="dropdown" role="button" aria-expanded="false"
' My account
span.caret
ul.dropdown-menu
@@ -77,6 +94,8 @@ html.no-js
method: :delete
= render "shared/dev_or_staging_banner"
= render "shared/non_js_banner"
+ = render "shared/timeout_warning_popup"
+
#main-container role="main"
.container
@@ -88,6 +107,10 @@ html.no-js
.alert-container
.alert.alert-danger
== alert
+ - unless flash[:error].blank?
+ .alert-container
+ .alert.alert-danger
+ == flash[:error]
= yield
diff --git a/app/views/layouts/application-judge.html.slim b/app/views/layouts/application-judge.html.slim
index a1d45d573..f8c2e45e2 100644
--- a/app/views/layouts/application-judge.html.slim
+++ b/app/views/layouts/application-judge.html.slim
@@ -57,8 +57,25 @@ html.no-js
= link_to "Downloads", judge_case_summaries_path
ul.nav.navbar-nav.navbar-right role="navigation"
- li.dropdown
- a.dropdown-toggle href="#" data-toggle="dropdown" role="button" aria-expanded="false"
+ li
+ details.if-js-hide
+ summary
+ ' My Account
+ span.caret
+ ul.dropdown-menu
+ li
+ span
+ strong = current_subject.decorate.full_name
+ br
+ small = current_subject.email
+ li.divider
+ li
+ = button_to "Sign out",
+ destroy_judge_session_path,
+ method: :delete,
+ class: "btn as-link"
+
+ a.dropdown-toggle.if-no-js-hide href="#" data-toggle="dropdown" role="button" aria-expanded="false"
' My account
span.caret
ul.dropdown-menu
@@ -74,6 +91,7 @@ html.no-js
method: :delete
= render "shared/dev_or_staging_banner"
= render "shared/non_js_banner"
+ = render "shared/timeout_warning_popup"
#main-container role="main"
.container
@@ -85,6 +103,10 @@ html.no-js
.alert-container
.alert.alert-danger
== alert
+ - unless flash[:error].blank?
+ .alert-container
+ .alert.alert-danger
+ == flash[:error]
= yield
diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim
index fa4520555..0c12654f2 100644
--- a/app/views/layouts/application.html.slim
+++ b/app/views/layouts/application.html.slim
@@ -1,4 +1,4 @@
-title = content_for?(:title) ? yield(:title) + " - King's Awards for Enterprise" : "King's Awards for Enterprise"
+title = content_for?(:title) ? "#{'Appraisal view of ' if admin_in_read_only_mode?}" + yield(:title) + " - King's Awards for Enterprise" : "King's Awards for Enterprise"
- content_for :head do
= stylesheet_link_tag "application.css"
diff --git a/app/views/layouts/govuk_template.html.erb b/app/views/layouts/govuk_template.html.erb
index 903d250f9..2e35de968 100644
--- a/app/views/layouts/govuk_template.html.erb
+++ b/app/views/layouts/govuk_template.html.erb
@@ -20,8 +20,8 @@