diff --git a/constants/index.js b/constants/index.js
index 5dbc0a399..09a839bac 100644
--- a/constants/index.js
+++ b/constants/index.js
@@ -8,10 +8,10 @@ function getRopsYears(start) {
module.exports = {
dateFormat: {
- short: 'DD/MM/YYYY',
+ short: 'D/M/YYYY',
medium: 'D MMM YYYY',
- long: 'DD MMMM YYYY',
- datetime: 'DD MMMM YYYY HH:mm'
+ long: 'D MMMM YYYY',
+ datetime: 'D MMMM YYYY HH:mm'
},
ropsYears: getRopsYears(2021)
};
diff --git a/lib/validation/index.js b/lib/validation/index.js
index ac1b8a5d6..bc58afad8 100644
--- a/lib/validation/index.js
+++ b/lib/validation/index.js
@@ -13,7 +13,7 @@ const defaultValidators = [
}
];
-const validateField = (key, { value, validate }, fields, model) => {
+const validateField = (key, { value, validate = [] }, fields, model) => {
return validate.reduce((err, options) => {
const { validator, params } = options;
return err || (!validators[validator](key, value, params, fields, model) && validator);
@@ -32,6 +32,7 @@ const validate = (fields, model) => {
const normaliseValidators = field => {
if (!field.validate) {
+ field.validate = [];
return field;
}
return {
@@ -52,7 +53,7 @@ const normaliseValidators = field => {
};
};
-const mapDefaults = (field, key) => {
+const mapDefaults = (field) => {
const defaults = (defaultValidators.find(v => v.inputType === field.inputType) || {}).validate;
return {
...field,
@@ -69,9 +70,9 @@ const middleware = (values, schema, model) => {
.mapValues(mapDefaults)
.pickBy((field, key) => {
if (!field.conditionalReveal) {
- return field.validate;
+ return true;
}
- return values[`conditional-reveal-${key}`] === 'true' && field.validate;
+ return values[`conditional-reveal-${key}`] === 'true';
})
.value();
diff --git a/package-lock.json b/package-lock.json
index f512ac6e0..6b8f7bb9a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,18 +1,18 @@
{
"name": "@asl/pages",
- "version": "31.0.1",
+ "version": "31.1.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@asl/pages",
- "version": "31.0.1",
+ "version": "31.1.0",
"license": "MIT",
"dependencies": {
"@asl/projects": "^15.0.1",
"@asl/service": "^10.0.0",
"@joefitter/docx": "^4.7.0",
- "@ukhomeoffice/asl-components": "13.0.0",
+ "@ukhomeoffice/asl-components": "13.2.0",
"@ukhomeoffice/asl-constants": "^2.1.0",
"@ukhomeoffice/asl-dictionary": "^2.1.0",
"@ukhomeoffice/frontend-toolkit": "^3.0.0",
@@ -140,6 +140,41 @@
"slate-react": "^0.22.4"
}
},
+ "node_modules/@asl/projects/node_modules/@ukhomeoffice/asl-components": {
+ "version": "13.0.0",
+ "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.0.0/716829e6e9cc254cabac253725084fb76ca413bd",
+ "integrity": "sha512-33byjEXUq1dtblvWgBOe7ETehw9h0mAmaRsqLWk4//V3lza+GGdhlclOg4gDtdVQdnjZZ1SFwJmfM3wWEh3MzQ==",
+ "dependencies": {
+ "@ukhomeoffice/asl-constants": "^2.0.0",
+ "@ukhomeoffice/asl-dictionary": "^2.1.0",
+ "@ukhomeoffice/react-components": "^1.0.0",
+ "accessible-autocomplete": "^2.0.3",
+ "babel-plugin-transform-class-properties": "^6.24.1",
+ "classnames": "^2.2.6",
+ "date-fns": "^1.29.0",
+ "diff": "^4.0.1",
+ "lodash": "^4.17.21",
+ "moment": "^2.29.4",
+ "mustache": "^3.0.1",
+ "qs": "^6.6.1",
+ "react": "^16.9.0",
+ "react-markdown": "^6.0.2",
+ "react-redux": "^7.1.0",
+ "redux": "^4.0.1",
+ "remark-breaks": "^2.0.2",
+ "shasum": "^1.0.2",
+ "url": "^0.11.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "node_modules/@asl/projects/node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
"node_modules/@asl/projects/node_modules/immutable": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
@@ -148,6 +183,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/@asl/projects/node_modules/mustache": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.2.1.tgz",
+ "integrity": "sha512-RERvMFdLpaFfSRIEe632yDm5nsd0SDKn8hGmcUwswnyiE5mtdZLDybtHAz6hjJhawokF0hXvGLtx9mrQfm6FkA==",
+ "bin": {
+ "mustache": "bin/mustache"
+ },
+ "engines": {
+ "npm": ">=1.4.0"
+ }
+ },
"node_modules/@asl/service": {
"version": "10.3.0",
"resolved": "https://artifactory.digital.homeoffice.gov.uk/artifactory/api/npm/npm-virtual/@asl/service/-/@asl/service-10.3.0.tgz",
@@ -3016,9 +3062,9 @@
"dev": true
},
"node_modules/@ukhomeoffice/asl-components": {
- "version": "13.0.0",
- "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.0.0/716829e6e9cc254cabac253725084fb76ca413bd",
- "integrity": "sha512-33byjEXUq1dtblvWgBOe7ETehw9h0mAmaRsqLWk4//V3lza+GGdhlclOg4gDtdVQdnjZZ1SFwJmfM3wWEh3MzQ==",
+ "version": "13.2.0",
+ "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.2.0/88566a0a97f97f20521f1bc6960272aefde49c52",
+ "integrity": "sha512-+KlGJAapdeFEcgO7SarfoNqNCQ2Q2+etOmmboq3qsw3ziIPCAbpQgi871QiWJNFaFRCQwYCMJsGT2qbGz+pAZg==",
"dependencies": {
"@ukhomeoffice/asl-constants": "^2.0.0",
"@ukhomeoffice/asl-dictionary": "^2.1.0",
@@ -7467,9 +7513,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "version": "1.15.5",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
+ "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"funding": [
{
"type": "individual",
@@ -16224,10 +16270,47 @@
"slate-schema-violations": "^0.1.39"
}
},
+ "@ukhomeoffice/asl-components": {
+ "version": "13.0.0",
+ "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.0.0/716829e6e9cc254cabac253725084fb76ca413bd",
+ "integrity": "sha512-33byjEXUq1dtblvWgBOe7ETehw9h0mAmaRsqLWk4//V3lza+GGdhlclOg4gDtdVQdnjZZ1SFwJmfM3wWEh3MzQ==",
+ "requires": {
+ "@ukhomeoffice/asl-constants": "^2.0.0",
+ "@ukhomeoffice/asl-dictionary": "^2.1.0",
+ "@ukhomeoffice/react-components": "^1.0.0",
+ "accessible-autocomplete": "^2.0.3",
+ "babel-plugin-transform-class-properties": "^6.24.1",
+ "classnames": "^2.2.6",
+ "date-fns": "^1.29.0",
+ "diff": "^4.0.1",
+ "lodash": "^4.17.21",
+ "moment": "^2.29.4",
+ "mustache": "^3.0.1",
+ "qs": "^6.6.1",
+ "react": "^16.9.0",
+ "react-markdown": "^6.0.2",
+ "react-redux": "^7.1.0",
+ "redux": "^4.0.1",
+ "remark-breaks": "^2.0.2",
+ "shasum": "^1.0.2",
+ "url": "^0.11.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
+ },
"immutable": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
"integrity": "sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg=="
+ },
+ "mustache": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/mustache/-/mustache-3.2.1.tgz",
+ "integrity": "sha512-RERvMFdLpaFfSRIEe632yDm5nsd0SDKn8hGmcUwswnyiE5mtdZLDybtHAz6hjJhawokF0hXvGLtx9mrQfm6FkA=="
}
}
},
@@ -18411,9 +18494,9 @@
"dev": true
},
"@ukhomeoffice/asl-components": {
- "version": "13.0.0",
- "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.0.0/716829e6e9cc254cabac253725084fb76ca413bd",
- "integrity": "sha512-33byjEXUq1dtblvWgBOe7ETehw9h0mAmaRsqLWk4//V3lza+GGdhlclOg4gDtdVQdnjZZ1SFwJmfM3wWEh3MzQ==",
+ "version": "13.2.0",
+ "resolved": "https://npm.pkg.github.com/download/@ukhomeoffice/asl-components/13.2.0/88566a0a97f97f20521f1bc6960272aefde49c52",
+ "integrity": "sha512-+KlGJAapdeFEcgO7SarfoNqNCQ2Q2+etOmmboq3qsw3ziIPCAbpQgi871QiWJNFaFRCQwYCMJsGT2qbGz+pAZg==",
"requires": {
"@ukhomeoffice/asl-constants": "^2.0.0",
"@ukhomeoffice/asl-dictionary": "^2.1.0",
@@ -21958,9 +22041,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ "version": "1.15.5",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
+ "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw=="
},
"for-each": {
"version": "0.3.3",
diff --git a/package.json b/package.json
index 0c03d5ca7..49629b3f6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@asl/pages",
- "version": "31.0.1",
+ "version": "31.1.0",
"description": "",
"main": "index.js",
"style": "pages/common/assets/sass/style.scss",
@@ -29,7 +29,7 @@
"@asl/projects": "^15.0.1",
"@asl/service": "^10.0.0",
"@joefitter/docx": "^4.7.0",
- "@ukhomeoffice/asl-components": "13.0.0",
+ "@ukhomeoffice/asl-components": "13.2.0",
"@ukhomeoffice/asl-constants": "^2.1.0",
"@ukhomeoffice/asl-dictionary": "^2.1.0",
"@ukhomeoffice/frontend-toolkit": "^3.0.0",
diff --git a/pages/common/content/index.js b/pages/common/content/index.js
index 0e8869734..023419ab0 100644
--- a/pages/common/content/index.js
+++ b/pages/common/content/index.js
@@ -204,14 +204,14 @@ module.exports = {
}
},
errors: {
- heading: 'Please fix the following error',
- headingPlural: 'Please fix the following errors',
+ heading: 'There is a problem',
+ headingPlural: 'There is a problem',
form: {
unchanged: 'No changes have been made',
csrf: 'This form data has been changed somewhere else.'
},
declaration: {
- required: 'Please confirm that you understand.'
+ required: 'Select to confirm that you understand.'
},
default: {
maxLength: 'This field is limited to 256 characters',
diff --git a/pages/common/routers/form.js b/pages/common/routers/form.js
index 712b1af2a..b49f8a696 100644
--- a/pages/common/routers/form.js
+++ b/pages/common/routers/form.js
@@ -198,7 +198,14 @@ const schemaWithReveals = (schema) =>
return {
...obj,
[key]: value,
- ...(value.reveal || {})
+ ...(value.reveal || {}),
+ ...(value.options || []).reduce(
+ (acc, opt) => ({
+ ...acc,
+ ...(opt.reveal ? schemaWithReveals(opt.reveal) : {})
+ }),
+ {}
+ )
};
},
{}
@@ -242,11 +249,11 @@ module.exports = ({
process = defaultMiddleware,
validate = defaultMiddleware,
saveValues = defaultMiddleware,
- requiresDeclaration = (req) => false,
- cancelEdit = (req, res, next) => {
+ requiresDeclaration = () => false,
+ cancelEdit = (req, res) => {
return res.redirect(cancelPath);
},
- editAnswers = (req, res, next) => {
+ editAnswers = (req, res) => {
return res.redirect(req.baseUrl.replace(/\/confirm/, ''));
}
} = {}) => {
diff --git a/pages/establishment/licence-fees/content/index.js b/pages/establishment/licence-fees/content/index.js
index 83544e326..cbb3b35e9 100644
--- a/pages/establishment/licence-fees/content/index.js
+++ b/pages/establishment/licence-fees/content/index.js
@@ -4,7 +4,7 @@ module.exports = {
},
fees: {
title: 'Estimated licence fees',
- period: 'Covering the period:',
+ period: 'Covering the financial year:',
disclaimer: 'These projections are based on the number of billable licences held and may differ from the final numbers.',
details: {
summary: 'How these fees are calculated',
diff --git a/pages/establishment/licence-fees/details/content/index.js b/pages/establishment/licence-fees/details/content/index.js
index acf8e3727..346a06626 100644
--- a/pages/establishment/licence-fees/details/content/index.js
+++ b/pages/establishment/licence-fees/details/content/index.js
@@ -5,22 +5,58 @@ module.exports = merge({}, content, {
title: 'Contact information for billing',
fields: {
contactName: {
- label: 'Billing contact'
+ label: 'Billing contact name'
},
contactNumber: {
- label: 'Contact number'
+ label: 'Telephone number'
},
contactEmail: {
- label: 'Contact email address'
+ label: 'Email address'
},
contactAddress: {
label: 'Billing address'
},
+ hasPurchaseOrder: {
+ label: 'Do you have a purchase order number?',
+ options: {
+ yes: 'Yes',
+ no: 'No'
+ }
+ },
purchaseOrder: {
label: 'Purchase order number'
},
+ alternativePaymentMethod: {
+ label: 'Provide details for your payment method'
+ },
otherInformation: {
- label: 'Any other billing information'
+ label: 'Other billing information (optional)'
+ },
+ declaredCurrent: {
+ label: 'These details are correct for the period {{ currentPeriod }}'
+ }
+ },
+ errors: {
+ contactName: {
+ required: 'Enter a contact name'
+ },
+ contactNumber: {
+ required: 'Enter a telephone number'
+ },
+ contactEmail: {
+ required: 'Enter an email address'
+ },
+ contactAddress: {
+ required: 'Enter an address'
+ },
+ purchaseOrder: {
+ required: 'Enter a purchase order number'
+ },
+ alternativePaymentMethod: {
+ required: 'Enter details for your payment method'
+ },
+ declaredCurrent: {
+ required: 'Select to confirm that all details are up to date'
}
},
actions: {
diff --git a/pages/establishment/licence-fees/details/read/views/index.jsx b/pages/establishment/licence-fees/details/read/views/index.jsx
index 7c4d30c66..cb1c64fd6 100644
--- a/pages/establishment/licence-fees/details/read/views/index.jsx
+++ b/pages/establishment/licence-fees/details/read/views/index.jsx
@@ -3,9 +3,32 @@ import Layout from '../../../views';
import { ModelSummary, Link, Snippet } from '@ukhomeoffice/asl-components';
export default function Details() {
+ const formatters = {
+ hasPurchaseOrder: {
+ format: (value, model) => {
+ switch (model.hasPurchaseOrder) {
+ case 'yes':
+ return 'Yes';
+ case 'no':
+ return 'No';
+ default:
+ return '-';
+ }
+ }
+ },
+ declaredCurrent: {
+ format: (value, model) => {
+ return model.declaredCurrent ? 'Yes' : 'No';
+ },
+ renderContext: {
+ currentPeriod: '6 April 2024 to 5 April 2025'
+ }
+ }
+ };
+
return (
-
+
actions.editLink}/>
);
diff --git a/pages/establishment/licence-fees/details/schema/index.js b/pages/establishment/licence-fees/details/schema/index.js
index 08ff6c81f..07d73b522 100644
--- a/pages/establishment/licence-fees/details/schema/index.js
+++ b/pages/establishment/licence-fees/details/schema/index.js
@@ -1,20 +1,51 @@
module.exports = {
contactName: {
- inputType: 'inputText'
+ inputType: 'inputText',
+ validate: ['required']
},
contactNumber: {
- inputType: 'inputText'
+ inputType: 'inputText',
+ validate: ['required']
},
contactEmail: {
- inputType: 'inputText'
+ inputType: 'inputText',
+ validate: ['required']
},
contactAddress: {
- inputType: 'textarea'
+ inputType: 'textarea',
+ validate: ['required']
},
- purchaseOrder: {
- inputType: 'inputText'
+ hasPurchaseOrder: {
+ inputType: 'radioGroup',
+ automapReveals: true,
+ validate: ['required'],
+ options: [
+ {
+ value: 'yes',
+ reveal: {
+ purchaseOrder: {
+ inputType: 'inputText',
+ validate: ['required']
+ }
+ }
+ },
+ {
+ value: 'no',
+ reveal: {
+ alternativePaymentMethod: {
+ inputType: 'textarea',
+ validate: ['required']
+ }
+ }
+ }
+ ]
},
otherInformation: {
inputType: 'textarea'
+ },
+ declaredCurrent: {
+ inputType: 'declaration',
+ title: 'Confirm that all details are up to date',
+ validate: ['required']
}
};
diff --git a/pages/establishment/licence-fees/details/update/content/index.js b/pages/establishment/licence-fees/details/update/content/index.js
index 9465fc456..4f8b86746 100644
--- a/pages/establishment/licence-fees/details/update/content/index.js
+++ b/pages/establishment/licence-fees/details/update/content/index.js
@@ -1,7 +1,4 @@
const { merge } = require('lodash');
const content = require('../../content');
-module.exports = merge({}, content, {
- intro: 'These details can be used for any contact regarding billing or finances.',
- inset: 'All fields are optional.'
-});
+module.exports = merge({}, content, {});
diff --git a/pages/establishment/licence-fees/details/update/views/index.jsx b/pages/establishment/licence-fees/details/update/views/index.jsx
index a50f1ed6a..1f3a44815 100644
--- a/pages/establishment/licence-fees/details/update/views/index.jsx
+++ b/pages/establishment/licence-fees/details/update/views/index.jsx
@@ -1,20 +1,24 @@
import React from 'react';
import { useSelector } from 'react-redux';
-import { FormLayout, Header, Snippet, Inset } from '@ukhomeoffice/asl-components';
+import { FormLayout, Header, Snippet } from '@ukhomeoffice/asl-components';
import EstablishmentHeader from '../../../../../common/components/establishment-header';
export default function Details() {
const establishment = useSelector(state => state.static.establishment);
+ const formatters = {
+ declaredCurrent: {
+ renderContext: {
+ currentPeriod: '6 April 2024 to 5 April 2025'
+ }
+ }
+ };
+
return (
-
+
title}
subtitle={}
/>
- intro
-
- inset
-
);
}
diff --git a/pages/establishment/licence-fees/views/index.jsx b/pages/establishment/licence-fees/views/index.jsx
index ca54d345f..6274341af 100644
--- a/pages/establishment/licence-fees/views/index.jsx
+++ b/pages/establishment/licence-fees/views/index.jsx
@@ -94,7 +94,7 @@ export default function Fees({ tab, tabs, children, subtitle = '' }) {
className="inline"
onChange={onYearSelect}
value={year}
- nullOption={false}
+ nullOption={null}
/>
fees.disclaimer