From 651f82be67738869618694559912fc7383059c64 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 20 May 2024 14:00:25 +0100 Subject: [PATCH 001/127] more work on splitting the classes --- src/controllers/resultsController.js | 72 +++++++------- src/controllers/statusController.js | 16 +-- src/models/requestData.js | 28 +++++- src/models/responseDetails.js | 39 +------- test/unit/errorsPage.test.js | 11 ++- test/unit/noErrorsPage.test.js | 14 +-- test/unit/resultsController.test.js | 143 +++++++++++++++++---------- test/unit/statusController.test.js | 43 +++----- 8 files changed, 186 insertions(+), 180 deletions(-) diff --git a/src/controllers/resultsController.js b/src/controllers/resultsController.js index 13188a51..3ad7de01 100644 --- a/src/controllers/resultsController.js +++ b/src/controllers/resultsController.js @@ -6,51 +6,49 @@ const errorsTemplate = 'results/errors' const noErrorsTemplate = 'results/no-errors' class ResultsController extends PageController { - async configure (req, res, next) { - try { - this.result = await getRequestData(req.params.id) - if (!this.result.isComplete()) { - res.redirect(`/status/${req.params.id}`) - return - } else if (this.result.isFailed()) { - this.template = failedRequestTemplate - } else if (this.result.hasErrors()) { - this.template = errorsTemplate - await this.result.fetchResponseDetails(req.params.pageNumber, 50, 'error') - } else { - this.template = noErrorsTemplate - await this.result.fetchResponseDetails(req.params.pageNumber) - } - - super.configure(req, res, next) - } catch (error) { - next(error, req, res, next) + async locals (req, res, next) { + let requestData; + try{ + requestData = await getRequestData(req.params.id) + } catch (e){ + next(e, req, res, next) + return } - } - async locals (req, res, next) { - req.form.options.template = this.template - req.form.options.requestParams = this.result.getParams() - - if (this.template !== failedRequestTemplate) { - req.form.options.errorSummary = this.result.getErrorSummary() - req.form.options.columns = this.result.getColumns() - req.form.options.fields = this.result.getFields() - req.form.options.mappings = this.result.getFieldMappings() - req.form.options.verboseRows = this.result.getRowsWithVerboseColumns(this.result.hasErrors()) - req.form.options.geometries = this.result.getGeometries() - req.form.options.pagination = this.result.getPagination(req.params.pageNumber) + if (!requestData.isComplete()) { + res.redirect(`/status/${req.params.id}`) + return + } + + let responseDetails; + + if (requestData.isFailed()) { + req.form.options.template = failedRequestTemplate + } else if (requestData.hasErrors()) { + req.form.options.template = errorsTemplate + responseDetails = await requestData.fetchResponseDetails(req.params.pageNumber, 50, 'error') + } else { + req.form.options.template = noErrorsTemplate + responseDetails = await requestData.fetchResponseDetails(req.params.pageNumber) + } + + req.form.options.requestParams = requestData.getParams() + + if (req.form.options.template !== failedRequestTemplate) { + req.form.options.errorSummary = requestData.getErrorSummary() + req.form.options.columns = responseDetails.getColumns() + req.form.options.fields = responseDetails.getFields() + req.form.options.mappings = responseDetails.getFieldMappings() + req.form.options.verboseRows = responseDetails.getRowsWithVerboseColumns(requestData.hasErrors()) + req.form.options.geometries = responseDetails.getGeometries() + req.form.options.pagination = requestData.getPagination(req.params.pageNumber) req.form.options.id = req.params.id } else { - req.form.options.error = this.result.getError() + req.form.options.error = requestData.getError() } super.locals(req, res, next) } - - noErrors (req, res, next) { - return !this.result.hasErrors() - } } export default ResultsController diff --git a/src/controllers/statusController.js b/src/controllers/statusController.js index 1b4132a7..1ceb43d6 100644 --- a/src/controllers/statusController.js +++ b/src/controllers/statusController.js @@ -3,19 +3,11 @@ import { getRequestData } from '../utils/asyncRequestApi.js' import { finishedProcessingStatuses } from '../utils/utils.js' class StatusController extends PageController { - async configure (req, res, next) { - try { - this.result = await getRequestData(req.params.id) - super.configure(req, res, next) - } catch (error) { - next(error, req, res, next) - } - } - async locals (req, res, next) { - req.form.options.data = this.result - req.form.options.processingComplete = finishedProcessingStatuses.includes(this.result.status) - req.form.options.pollingEndpoint = `/api/status/${this.result.id}` + const requestData = await getRequestData(req.params.id) + req.form.options.data = requestData + req.form.options.processingComplete = finishedProcessingStatuses.includes(requestData.status) + req.form.options.pollingEndpoint = `/api/status/${requestData.id}` super.locals(req, res, next) } } diff --git a/src/models/requestData.js b/src/models/requestData.js index 15f34217..0533d43a 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -1,6 +1,7 @@ import logger from '../utils/logger.js' import axios from 'axios' import config from '../../config/index.js' +import ResponseDetails from './responseDetails.js' export default class RequestData { constructor (response) { @@ -16,13 +17,22 @@ export default class RequestData { } const request = await axios.get(`${config.asyncRequestApi.url}/${config.asyncRequestApi.requestsEndpoint}/${this.id}/response-details?${urlParams.toString()}`, { timeout: 30000 }) - this.response.details = request.data this.pagination = { totalResults: request.headers['x-pagination-total-results'], offset: request.headers['x-pagination-offset'], limit: request.headers['x-pagination-limit'] } + + return new ResponseDetails(request.data) + } + + getErrorSummary () { + if (!this.response || !this.response.data || !this.response.data['error-summary']) { + logger.error('trying to get error summary when there is none: request id: ' + this.id) + return [] + } + return this.response.data['error-summary'] } isFailed () { @@ -55,6 +65,22 @@ export default class RequestData { return this.response.data['error-summary'].length > 0 } + getGeometryKey () { + const columnFieldLog = this.getColumnFieldLog() + + if (!columnFieldLog) { + return null + } + + let columnFieldEntry = columnFieldLog.find(column => column.field === 'point') || columnFieldLog.find(column => column.field === 'geometry') + + if(!columnFieldEntry){ + return null + } + + return columnFieldEntry.column + } + isComplete () { const finishedProcessingStatuses = ['COMPLETE', 'FAILED'] return finishedProcessingStatuses.includes(this.status) diff --git a/src/models/responseDetails.js b/src/models/responseDetails.js index e33052e2..f13c4ef8 100644 --- a/src/models/responseDetails.js +++ b/src/models/responseDetails.js @@ -7,11 +7,11 @@ export default class ResponseDetails { } getRows () { - if (!this.response || !this.response.details) { + if (!this.response || !this.response.data) { logger.error('trying to get response details when there are none: request id: ' + this.id) return [] } - return this.response.details + return this.response.data } getColumnFieldLog () { @@ -22,30 +22,6 @@ export default class ResponseDetails { return this.response.data['column-field-log'] } - getGeometryKey () { - if (!this.params) { - logger.error('trying to get geometry key when there are no params: request id: ' + this.id) - return null - } - - const geometryType = this.params.geom_type - const columnFieldLog = this.getColumnFieldLog() - - if (!columnFieldLog) { - return null - } - - let geometryKey - - if (geometryType === 'point' && columnFieldLog.find(column => column.field === 'point')) { - geometryKey = columnFieldLog.find(column => column.field === 'point').column - } else if (columnFieldLog.find(column => column.field === 'geometry')) { - geometryKey = columnFieldLog.find(column => column.field === 'geometry').column - } - - return geometryKey - } - getColumns (includeNonMapped = true) { if (!this.getRows().length) { return [] @@ -76,14 +52,6 @@ export default class ResponseDetails { })) } - getErrorSummary () { - if (!this.response || !this.response.data || !this.response.data['error-summary']) { - logger.error('trying to get error summary when there is none: request id: ' + this.id) - return [] - } - return this.response.data['error-summary'] - } - // This function returns an array of rows with verbose columns getRowsWithVerboseColumns (filterNonErrors = false) { if (!this.response || !this.response.details) { @@ -105,13 +73,12 @@ export default class ResponseDetails { })) } - getGeometries () { + getGeometries (geometryKey) { if (!this.response || !this.response.details) { logger.error('trying to get response details when there are none: request id: ' + this.id) return undefined } - const geometryKey = this.getGeometryKey() const geometries = this.response.details.map(row => row.converted_row[geometryKey]).filter(geometry => geometry !== '') if (geometries.length === 0) { return null diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index dbb75d3c..1ef1b33d 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -6,6 +6,7 @@ import addFilters from '../../src/filters/filters' import errorResponse from '../../docker/request-api-stub/wiremock/__files/check_file/article-4/request-complete-errors.json' import errorResponseDetails from '../../docker/request-api-stub/wiremock/__files/check_file/article-4/request-complete-errors-details.json' +import ResponseDetails from '../../src/models/responseDetails.js' const nunjucksEnv = nunjucks.configure([ 'src/views', @@ -23,7 +24,7 @@ describe('errors page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - requestData.response.details = errorResponseDetails + const responseDetails = new ResponseDetails(errorResponseDetails) requestData.response.pagination = { totalResults: 100, @@ -35,11 +36,11 @@ describe('errors page', () => { options: { requestParams: requestData.getParams(), errorSummary: requestData.getErrorSummary(), - rows: requestData.getRows(), + rows: responseDetails.getRows(), geometryKey: requestData.getGeometryKey(), - columns: requestData.getColumns(), - fields: requestData.getFields(), - verboseRows: requestData.getRowsWithVerboseColumns() + columns: responseDetails.getColumns(), + fields: responseDetails.getFields(), + verboseRows: responseDetails.getRowsWithVerboseColumns() } } diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 6cf223d8..2a2b9144 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -6,6 +6,7 @@ import addFilters from '../../src/filters/filters' import errorResponse from '../../docker/request-api-stub/wiremock/__files/check_file/article-4/request-complete-errors.json' import errorResponseDetails from '../../docker/request-api-stub/wiremock/__files/check_file/article-4/request-complete-errors-details.json' +import ResponseDetails from '../../src/models/responseDetails.js' const nunjucksEnv = nunjucks.configure([ 'src/views', @@ -22,8 +23,7 @@ addFilters(nunjucksEnv) describe('no Errors Page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - - requestData.response.details = errorResponseDetails + const responseDetails = new ResponseDetails({data: errorResponseDetails}) requestData.response.pagination = { totalResults: 100, @@ -35,12 +35,12 @@ describe('no Errors Page', () => { options: { requestParams: requestData.getParams(), errorSummary: requestData.getErrorSummary(), - rows: requestData.getRows(), + rows: responseDetails.getRows(), geometryKey: requestData.getGeometryKey(), - columns: requestData.getColumns(), - fields: requestData.getFields(), - mappings: requestData.getFieldMappings(), - verboseRows: requestData.getRowsWithVerboseColumns() + columns: responseDetails.getColumns(), + fields: responseDetails.getFields(), + mappings: responseDetails.getFieldMappings(), + verboseRows: responseDetails.getRowsWithVerboseColumns() }, errors: {} } diff --git a/test/unit/resultsController.test.js b/test/unit/resultsController.test.js index 9b7fff72..36374562 100644 --- a/test/unit/resultsController.test.js +++ b/test/unit/resultsController.test.js @@ -9,7 +9,8 @@ describe('ResultsController', () => { const req = { params: { id: 'testId' }, - form: { options: {} } + form: { options: {} }, + session: { template: 'template'} } beforeEach(async () => { @@ -20,22 +21,14 @@ describe('ResultsController', () => { }) }) - describe('configure', () => { - it('should add the result to the controller class', async () => { - const mockResult = { hasErrors: () => false } - asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - - await resultsController.configure(req, {}, () => {}) - expect(resultsController.result).toBeDefined() - }) - + describe('locals', () => { it("should call next with a 404 error if the result wasn't found", async () => { asyncRequestApi.getRequestData = vi.fn().mockImplementation(() => { throw new Error('Request not found', { message: 'Request not found', status: 404 }) }) const nextMock = vi.fn() - await resultsController.configure(req, {}, nextMock) + await resultsController.locals(req, {}, nextMock) expect(nextMock).toHaveBeenCalledWith(new Error('Request not found', { message: 'Request not found', status: 404 }), req, {}, nextMock) }) @@ -45,58 +38,112 @@ describe('ResultsController', () => { }) const nextMock = vi.fn() - await resultsController.configure(req, {}, nextMock) + await resultsController.locals(req, {}, nextMock) expect(nextMock).toHaveBeenCalledWith(new Error('Unexpected error', { message: 'Unexpected error', status: 500 }), req, {}, nextMock) }) it('should set the template to the errors template if the result has errors', async () => { - const mockResult = { hasErrors: () => true, isFailed: () => false, isComplete: () => true } + const mockDetails = { + getErrorSummary: () => ['error summary'], + getColumns: () => ['columns'], + getFields: () => ['fields'], + getFieldMappings: () => 'fieldMappings', + getRowsWithVerboseColumns: () => ['verbose-columns'], + getGeometries: () => ['geometries'] + } + + const mockResult = { + isFailed: () => false, + getError: () => 'error', + hasErrors: () => true, + isComplete: () => true, + getParams: () => ('params'), + getId: () => 'fake_id', + getPagination: () => 'pagination', + fetchResponseDetails: () => mockDetails + } + asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - await resultsController.configure(req, {}, () => {}) - expect(resultsController.template).toBe('results/errors') + await resultsController.locals(req, {}, () => {}) + expect(req.form.options.template).toBe('results/errors') }) it('should set the template to the no-errors template if the result has no errors', async () => { - const mockResult = { hasErrors: () => false, isFailed: () => false, isComplete: () => true } + const mockDetails = { + getErrorSummary: () => ['error summary'], + getColumns: () => ['columns'], + getFields: () => ['fields'], + getFieldMappings: () => 'fieldMappings', + getRowsWithVerboseColumns: () => ['verbose-columns'], + getGeometries: () => ['geometries'] + } + + const mockResult = { + isFailed: () => false, + getError: () => 'error', + hasErrors: () => false, + isComplete: () => true, + getParams: () => ('params'), + getId: () => 'fake_id', + getPagination: () => 'pagination', + fetchResponseDetails: () => mockDetails + } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - await resultsController.configure(req, {}, () => {}) - expect(resultsController.template).toBe('results/no-errors') + await resultsController.locals(req, {}, () => {}) + expect(req.form.options.template).toBe('results/no-errors') }) it('should set the template to the failedRequest template if the result is failed', async () => { - const mockResult = { isFailed: () => true, hasErrors: () => false, isComplete: () => true } - asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - - await resultsController.configure(req, {}, () => {}) - expect(resultsController.template).toBe('results/failedRequest') - }) - - it('should redirect to the status page if the result is not complete', async () => { - const mockResult = { isFailed: () => true, hasErrors: () => false, isComplete: () => false } + const mockDetails = { + getErrorSummary: () => ['error summary'], + getColumns: () => ['columns'], + getFields: () => ['fields'], + getFieldMappings: () => 'fieldMappings', + getRowsWithVerboseColumns: () => ['verbose-columns'], + getGeometries: () => ['geometries'] + } + + const mockResult = { + isFailed: () => true, + getError: () => 'error', + hasErrors: () => false, + isComplete: () => true, + getParams: () => ('params'), + getId: () => 'fake_id', + getPagination: () => 'pagination', + fetchResponseDetails: () => mockDetails + } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - const res = { redirect: vi.fn() } - await resultsController.configure(req, res, () => {}) - expect(res.redirect).toHaveBeenCalledWith(`/status/${req.params.id}`) + await resultsController.locals(req, {}, () => {}) + expect(req.form.options.template).toBe('results/failedRequest') }) - }) - describe('locals', () => { - it('should set the result to the form options if the result is complete', async () => { - resultsController.result = { + it('should redirect to the status page if the form is complete', async () => { + const mockDetails = { + getErrorSummary: () => ['error summary'], + getColumns: () => ['columns'], + getFields: () => ['fields'], + getFieldMappings: () => 'fieldMappings', + getRowsWithVerboseColumns: () => ['verbose-columns'], + getGeometries: () => ['geometries'] + } + + const mockResult = { + isFailed: () => false, + getError: () => 'error', + hasErrors: () => false, isComplete: () => true, getParams: () => ('params'), - getErrorSummary: () => (['error summary']), - getGeometries: () => ['geometries'], - getColumns: () => (['columns']), - getRowsWithVerboseColumns: () => (['verbose-columns']), - getFields: () => (['fields']), - getFieldMappings: () => ({ fields: 'geometries' }), - hasErrors: () => false, - getPagination: () => 'pagination' + getId: () => 'fake_id', + getPagination: () => 'pagination', + fetchResponseDetails: () => mockDetails } + + asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) + const res = { redirect: vi.fn() } await resultsController.locals(req, res, () => {}) @@ -109,16 +156,4 @@ describe('ResultsController', () => { expect(req.form.options.pagination).toBe('pagination') }) }) - - describe('noErrors', () => { - it('should return false if the result has errors', () => { - resultsController.result = { hasErrors: () => true } - expect(resultsController.noErrors()).toBe(false) - }) - - it('should return true if the result has no errors', () => { - resultsController.result = { hasErrors: () => false } - expect(resultsController.noErrors()).toBe(true) - }) - }) }) diff --git a/test/unit/statusController.test.js b/test/unit/statusController.test.js index 8cc6157a..a955b4ab 100644 --- a/test/unit/statusController.test.js +++ b/test/unit/statusController.test.js @@ -15,42 +15,29 @@ describe('StatusController', () => { }) }) - describe('configure', () => { - it('configure should make a request and attach the result of that request to the req.form.options object', async () => { - const req = { - params: { id: 'test_id' }, - form: { - options: { - - } - } - } - const res = { render: vi.fn(), redirect: vi.fn() } - const next = vi.fn() - - const mockResult = { response: { test: 'test' }, hasErrors: () => false } - asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - - await statusController.configure(req, res, next) - - expect(asyncRequestApi.getRequestData).toHaveBeenCalledWith(req.params.id) - }) - }) - describe('locals', () => { it('should attach the result of the request to the req.form.options.data object', async () => { + const mockResult = { id: 'test_id', status: 'COMPLETE', response: { test: 'test' }, hasErrors: () => false } + asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) + const req = { form: { options: {} - } + }, + params: 'fake_id' } - const res = {} - const next = vi.fn() - const mockResult = { response: { test: 'test' }, hasErrors: () => false } - statusController.result = mockResult - statusController.locals(req, res, next) + + const res = {} + const next = vi.fn() + + await statusController.locals(req, res, next) + + expect(req.form.options.data).toBe(mockResult) + expect(req.form.options.processingComplete).toBe(true) + expect(req.form.options.pollingEndpoint).toBe(`/api/status/${mockResult.id}`) + expect(asyncRequestApi.getRequestData).toHaveBeenCalledWith(req.params.id) expect(req.form.options.data).toBe(mockResult) }) From 9f3dddd00075de79ed6e4abaf82525c13000c63e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 20 May 2024 14:00:37 +0100 Subject: [PATCH 002/127] linting --- src/controllers/resultsController.js | 8 ++++---- src/models/requestData.js | 4 ++-- test/unit/noErrorsPage.test.js | 2 +- test/unit/resultsController.test.js | 10 +++++----- test/unit/statusController.test.js | 6 ++---- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/controllers/resultsController.js b/src/controllers/resultsController.js index 3ad7de01..c4b41a24 100644 --- a/src/controllers/resultsController.js +++ b/src/controllers/resultsController.js @@ -7,10 +7,10 @@ const noErrorsTemplate = 'results/no-errors' class ResultsController extends PageController { async locals (req, res, next) { - let requestData; - try{ + let requestData + try { requestData = await getRequestData(req.params.id) - } catch (e){ + } catch (e) { next(e, req, res, next) return } @@ -20,7 +20,7 @@ class ResultsController extends PageController { return } - let responseDetails; + let responseDetails if (requestData.isFailed()) { req.form.options.template = failedRequestTemplate diff --git a/src/models/requestData.js b/src/models/requestData.js index 0533d43a..2125e9d8 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -72,9 +72,9 @@ export default class RequestData { return null } - let columnFieldEntry = columnFieldLog.find(column => column.field === 'point') || columnFieldLog.find(column => column.field === 'geometry') + const columnFieldEntry = columnFieldLog.find(column => column.field === 'point') || columnFieldLog.find(column => column.field === 'geometry') - if(!columnFieldEntry){ + if (!columnFieldEntry) { return null } diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 2a2b9144..8b6f554d 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -23,7 +23,7 @@ addFilters(nunjucksEnv) describe('no Errors Page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - const responseDetails = new ResponseDetails({data: errorResponseDetails}) + const responseDetails = new ResponseDetails({ data: errorResponseDetails }) requestData.response.pagination = { totalResults: 100, diff --git a/test/unit/resultsController.test.js b/test/unit/resultsController.test.js index 36374562..f6c71f19 100644 --- a/test/unit/resultsController.test.js +++ b/test/unit/resultsController.test.js @@ -10,7 +10,7 @@ describe('ResultsController', () => { const req = { params: { id: 'testId' }, form: { options: {} }, - session: { template: 'template'} + session: { template: 'template' } } beforeEach(async () => { @@ -51,7 +51,7 @@ describe('ResultsController', () => { getRowsWithVerboseColumns: () => ['verbose-columns'], getGeometries: () => ['geometries'] } - + const mockResult = { isFailed: () => false, getError: () => 'error', @@ -78,7 +78,7 @@ describe('ResultsController', () => { getRowsWithVerboseColumns: () => ['verbose-columns'], getGeometries: () => ['geometries'] } - + const mockResult = { isFailed: () => false, getError: () => 'error', @@ -104,7 +104,7 @@ describe('ResultsController', () => { getRowsWithVerboseColumns: () => ['verbose-columns'], getGeometries: () => ['geometries'] } - + const mockResult = { isFailed: () => true, getError: () => 'error', @@ -130,7 +130,7 @@ describe('ResultsController', () => { getRowsWithVerboseColumns: () => ['verbose-columns'], getGeometries: () => ['geometries'] } - + const mockResult = { isFailed: () => false, getError: () => 'error', diff --git a/test/unit/statusController.test.js b/test/unit/statusController.test.js index a955b4ab..19280175 100644 --- a/test/unit/statusController.test.js +++ b/test/unit/statusController.test.js @@ -27,13 +27,11 @@ describe('StatusController', () => { params: 'fake_id' } - - const res = {} const next = vi.fn() - + await statusController.locals(req, res, next) - + expect(req.form.options.data).toBe(mockResult) expect(req.form.options.processingComplete).toBe(true) expect(req.form.options.pollingEndpoint).toBe(`/api/status/${mockResult.id}`) From e86923319cb686f1fdf9a89b265d0f6d2abdd230 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 21 May 2024 13:14:49 +0100 Subject: [PATCH 003/127] print out provided headers instead of expected headers --- src/views/results/errors.html | 4 ++-- src/views/results/no-errors.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/results/errors.html b/src/views/results/errors.html index 83540664..5bfe5053 100644 --- a/src/views/results/errors.html +++ b/src/views/results/errors.html @@ -48,8 +48,8 @@

- {% for field in options.fields %} - + {% for column in options.columns %} + {% endfor %} diff --git a/src/views/results/no-errors.html b/src/views/results/no-errors.html index e28cf850..1c4fc732 100644 --- a/src/views/results/no-errors.html +++ b/src/views/results/no-errors.html @@ -49,8 +49,8 @@

{{field}}{{column}}
- {% for field in options.fields %} - + {% for column in options.columns %} + {% endfor %} From 6d3b9b4983b698e7068d962daf81f96cac77796e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 21 May 2024 13:15:17 +0100 Subject: [PATCH 004/127] further work on splitting requestData into two classes --- src/controllers/resultsController.js | 2 +- src/models/requestData.js | 89 +---------------------- src/models/responseDetails.js | 102 +++++++++++++++++++++++---- 3 files changed, 92 insertions(+), 101 deletions(-) diff --git a/src/controllers/resultsController.js b/src/controllers/resultsController.js index c4b41a24..1c79897b 100644 --- a/src/controllers/resultsController.js +++ b/src/controllers/resultsController.js @@ -41,7 +41,7 @@ class ResultsController extends PageController { req.form.options.mappings = responseDetails.getFieldMappings() req.form.options.verboseRows = responseDetails.getRowsWithVerboseColumns(requestData.hasErrors()) req.form.options.geometries = responseDetails.getGeometries() - req.form.options.pagination = requestData.getPagination(req.params.pageNumber) + req.form.options.pagination = responseDetails.getPagination(req.params.pageNumber) req.form.options.id = req.params.id } else { req.form.options.error = requestData.getError() diff --git a/src/models/requestData.js b/src/models/requestData.js index 25ae8e89..c17cd166 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -1,4 +1,3 @@ -import getVerboseColumns from '../utils/getVerboseColumns.js' import logger from '../utils/logger.js' import axios from 'axios' import config from '../../config/index.js' @@ -19,13 +18,13 @@ export default class RequestData { const request = await axios.get(`${config.asyncRequestApi.url}/${config.asyncRequestApi.requestsEndpoint}/${this.id}/response-details?${urlParams.toString()}`, { timeout: 30000 }) - this.pagination = { + const pagination = { totalResults: request.headers['x-pagination-total-results'], offset: request.headers['x-pagination-offset'], limit: request.headers['x-pagination-limit'] } - return new ResponseDetails(request.data) + return new ResponseDetails(request.data, pagination, this.getColumnFieldLog()) } getErrorSummary () { @@ -141,27 +140,6 @@ export default class RequestData { return this.id } - // This function returns an array of rows with verbose columns - getRowsWithVerboseColumns (filterNonErrors = false) { - if (!this.response || !this.response.details) { - logger.error('trying to get response details when there are none: request id: ' + this.id) - return [] - } - - let rows = this.response.details - - if (filterNonErrors) { - rows = rows.filter(row => row.issue_logs.filter(issue => issue.severity === 'error').length > 0) - } - - // Map over the details in the response and return an array of rows with verbose columns - return rows.map(row => ({ - entryNumber: row.entry_number, - hasErrors: row.issue_logs.filter(issue => issue.severity === 'error').length > 0, - columns: getVerboseColumns(row, this.getColumnFieldLog()) - })) - } - getGeometries () { if (!this.response || !this.response.details) { logger.error('trying to get response details when there are none: request id: ' + this.id) @@ -175,67 +153,4 @@ export default class RequestData { } return geometries } - - getPagination (pageNumber) { - pageNumber = parseInt(pageNumber) - const totalPages = Math.ceil(this.pagination.totalResults / this.pagination.limit) - - const items = pagination(totalPages, pageNumber + 1).map(item => { - if (item === '...') { - return { - ellipsis: true, - href: '#' - } - } else { - return { - number: item, - href: `/results/${this.id}/${parseInt(item) - 1}`, - current: pageNumber === parseInt(item) - 1 - } - } - }) - - return { - totalResults: parseInt(this.pagination.totalResults), - offset: parseInt(this.pagination.offset), - limit: parseInt(this.pagination.limit), - currentPage: pageNumber + 1, - nextPage: pageNumber < totalPages - 1 ? pageNumber + 1 : null, - previousPage: pageNumber > 0 ? pageNumber - 1 : null, - totalPages, - items - } - } -} - -const { min, max } = Math -const range = (lo, hi) => Array.from({ length: hi - lo }, (_, i) => i + lo) - -export const pagination = (count, current, ellipsis = '...') => { - if (count <= 5) { - return range(1, count + 1) - } - const adjacent = 1 - const left = current === count ? current - 2 * adjacent : max(0, current - adjacent) - const right = current === 1 ? 1 + adjacent * 2 : min(count, current + adjacent) - const middle = range(left, right + 1) - let leftEllipsis = left > 1 - let rightEllipsis = right < count - - if (leftEllipsis && middle[0] === 2) { - leftEllipsis = false - middle.unshift(1) - } - - if (rightEllipsis && middle[middle.length - 1] === count - 1) { - rightEllipsis = false - middle.push(count) - } - - const result = [ - ...(leftEllipsis ? [1, ellipsis] : middle), - ...(leftEllipsis && rightEllipsis ? middle : []), - ...(rightEllipsis ? [ellipsis, count] : middle) - ] - return result } diff --git a/src/models/responseDetails.js b/src/models/responseDetails.js index f13c4ef8..c77fe2ab 100644 --- a/src/models/responseDetails.js +++ b/src/models/responseDetails.js @@ -2,35 +2,48 @@ import getVerboseColumns from '../utils/getVerboseColumns.js' import logger from '../utils/logger.js' export default class ResponseDetails { - constructor (response) { + constructor (response, pagination, columnFieldLog) { this.response = response + this.pagination = pagination + this.columnFieldLog = columnFieldLog } getRows () { - if (!this.response || !this.response.data) { + if (!this.response) { logger.error('trying to get response details when there are none: request id: ' + this.id) return [] } - return this.response.data + return this.response } getColumnFieldLog () { - if (!this.response || !this.response.data || !this.response.data['column-field-log']) { + if (!this.columnFieldLog) { logger.error('trying to get column field log when there is none: request id: ' + this.id) return [] } - return this.response.data['column-field-log'] + return this.columnFieldLog } - getColumns (includeNonMapped = true) { + getColumns () { if (!this.getRows().length) { return [] } - return [...new Set(this.getRows().map(row => row.converted_row).flatMap(row => Object.keys(row)))] + + const fields = this.getFields() + + const ColumnsWithDuplicates = fields.map(field => { + const columnFieldLog = this.getColumnFieldLog() + const fieldLog = columnFieldLog.find(fieldLog => fieldLog.field === field) + return fieldLog ? fieldLog.column : field + }) + + return [...new Set(ColumnsWithDuplicates)] } - getFields (includeNonMapped = true) { - return [...new Set(this.getColumns().map(column => { + getFields () { + const columnKeys = [...new Set(this.getRows().map(row => row.converted_row).flatMap(row => Object.keys(row)))] + + return [...new Set(columnKeys.map(column => { const columnFieldLog = this.getColumnFieldLog() const fieldLog = columnFieldLog.find(fieldLog => fieldLog.column === column) if (!fieldLog) { @@ -54,12 +67,12 @@ export default class ResponseDetails { // This function returns an array of rows with verbose columns getRowsWithVerboseColumns (filterNonErrors = false) { - if (!this.response || !this.response.details) { + if (!this.response) { logger.error('trying to get response details when there are none: request id: ' + this.id) return [] } - let rows = this.response.details + let rows = this.response if (filterNonErrors) { rows = rows.filter(row => row.issue_logs.filter(issue => issue.severity === 'error').length > 0) @@ -74,15 +87,78 @@ export default class ResponseDetails { } getGeometries (geometryKey) { - if (!this.response || !this.response.details) { + if (!this.response) { logger.error('trying to get response details when there are none: request id: ' + this.id) return undefined } - const geometries = this.response.details.map(row => row.converted_row[geometryKey]).filter(geometry => geometry !== '') + const geometries = this.response.map(row => row.converted_row[geometryKey]).filter(geometry => geometry !== '') if (geometries.length === 0) { return null } return geometries } + + getPagination (pageNumber) { + pageNumber = parseInt(pageNumber) + const totalPages = Math.ceil(this.pagination.totalResults / this.pagination.limit) + + const items = pagination(totalPages, pageNumber + 1).map(item => { + if (item === '...') { + return { + ellipsis: true, + href: '#' + } + } else { + return { + number: item, + href: `/results/${this.id}/${parseInt(item) - 1}`, + current: pageNumber === parseInt(item) - 1 + } + } + }) + + return { + totalResults: parseInt(this.pagination.totalResults), + offset: parseInt(this.pagination.offset), + limit: parseInt(this.pagination.limit), + currentPage: pageNumber + 1, + nextPage: pageNumber < totalPages - 1 ? pageNumber + 1 : null, + previousPage: pageNumber > 0 ? pageNumber - 1 : null, + totalPages, + items + } + } +} + +const { min, max } = Math +const range = (lo, hi) => Array.from({ length: hi - lo }, (_, i) => i + lo) + +export const pagination = (count, current, ellipsis = '...') => { + if (count <= 5) { + return range(1, count + 1) + } + const adjacent = 1 + const left = current === count ? current - 2 * adjacent : max(0, current - adjacent) + const right = current === 1 ? 1 + adjacent * 2 : min(count, current + adjacent) + const middle = range(left, right + 1) + let leftEllipsis = left > 1 + let rightEllipsis = right < count + + if (leftEllipsis && middle[0] === 2) { + leftEllipsis = false + middle.unshift(1) + } + + if (rightEllipsis && middle[middle.length - 1] === count - 1) { + rightEllipsis = false + middle.push(count) + } + + const result = [ + ...(leftEllipsis ? [1, ellipsis] : middle), + ...(leftEllipsis && rightEllipsis ? middle : []), + ...(rightEllipsis ? [ellipsis, count] : middle) + ] + return result } From bc0cd77d88ea165a9813dbefc496a9d933c1da3c Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 21 May 2024 13:15:25 +0100 Subject: [PATCH 005/127] fix tests --- .../test_recieving_results.test.js | 14 ++--- test/unit/errorsPage.test.js | 8 +-- test/unit/noErrorsPage.test.js | 7 +-- test/unit/requestData.test.js | 52 ++----------------- test/unit/responseDetails.test.js | 50 ++++++++++++++++++ test/unit/resultsController.test.js | 26 ++++++---- 6 files changed, 85 insertions(+), 72 deletions(-) create mode 100644 test/unit/responseDetails.test.js diff --git a/test/integration/test_recieving_results.test.js b/test/integration/test_recieving_results.test.js index 6d40e844..27756ec9 100644 --- a/test/integration/test_recieving_results.test.js +++ b/test/integration/test_recieving_results.test.js @@ -118,18 +118,20 @@ const getTableValuesFromResponse = (response, details) => { const columnFieldLog = response.response.data['column-field-log'] // Map over the details array and extract the necessary values - const columnHeaders = Object.keys(details[0].converted_row).map(column => { - const log = columnFieldLog.find(log => log.column === column) - if (log) { return log.field } else { return column } + const columnHeaders = Object.keys(details[0].converted_row) + + const notUniqueHeaders = columnHeaders.map(field => { + const fieldLog = columnFieldLog.find(fieldLog => fieldLog.field === field) + return fieldLog ? fieldLog.column : field }) - const uniqueColumnHeaders = [...new Set(columnHeaders)] + const uniqueHeaders = [...new Set(notUniqueHeaders)] - tableValues.unshift(uniqueColumnHeaders) + tableValues.unshift(uniqueHeaders) tableValues.push(...details.map(detail => { const convertedRow = detail.converted_row - return uniqueColumnHeaders.map(header => { + return uniqueHeaders.map(header => { const log = columnFieldLog.find(log => log.field === header) if (log) { header = log.column } diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index 1ef1b33d..ec333991 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -24,7 +24,7 @@ describe('errors page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - const responseDetails = new ResponseDetails(errorResponseDetails) + const responseDetails = new ResponseDetails(errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) requestData.response.pagination = { totalResults: 100, @@ -40,7 +40,9 @@ describe('errors page', () => { geometryKey: requestData.getGeometryKey(), columns: responseDetails.getColumns(), fields: responseDetails.getFields(), - verboseRows: responseDetails.getRowsWithVerboseColumns() + mappings: responseDetails.getFieldMappings(), + verboseRows: responseDetails.getRowsWithVerboseColumns(), + pagination: responseDetails.getPagination(0) } } @@ -49,7 +51,7 @@ describe('errors page', () => { // error summary expect(html).toContain('
  • 1 geometry must be in Well-Known Text (WKT) format
  • 1 documentation URL must be a real URL
  • 1 entry date must be today or in the past
  • 1 start date must be a real date
  • 1 geometry missing
  • Reference column missing
') // table headers - expect(html).toContain('
') + expect(html).toContain('') // table rows expect(html).toContain('') diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 8b6f554d..16b54ebd 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -23,7 +23,7 @@ addFilters(nunjucksEnv) describe('no Errors Page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - const responseDetails = new ResponseDetails({ data: errorResponseDetails }) + const responseDetails = new ResponseDetails(errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) requestData.response.pagination = { totalResults: 100, @@ -40,7 +40,8 @@ describe('no Errors Page', () => { columns: responseDetails.getColumns(), fields: responseDetails.getFields(), mappings: responseDetails.getFieldMappings(), - verboseRows: responseDetails.getRowsWithVerboseColumns() + verboseRows: responseDetails.getRowsWithVerboseColumns(), + pagination: responseDetails.getPagination(0) }, errors: {} } @@ -48,7 +49,7 @@ describe('no Errors Page', () => { const html = nunjucks.render('results/no-errors.html', params).replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ') // expect the table column headers to be correct - expect(html).toContain('') + expect(html).toContain('') // expect the table rows to be correct expect(html).toContain(' ') expect(html).toContain(' ') diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 16e80b0f..bd9b9f8b 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -1,54 +1,8 @@ -import { pagination } from '../../src/models/requestData' import { describe, it, expect } from 'vitest' // // Tech Debt: we should write some tests around the requestData.js file -// describe('RequestData', () => { -// }) - -describe('Pagination', () => { - const testCases = [ - { - input: { - count: 1, - current: 0 - }, - expected: [1] - }, - { - input: { - count: 5, - current: 3 - }, - expected: [1, 2, 3, 4, 5] - }, - { - input: { - count: 6, - current: 2 - }, - expected: [1, 2, 3, '...', 6] - }, - { - input: { - count: 6, - current: 5 - }, - expected: [1, '...', 4, 5, 6] - }, - { - input: { - count: 10, - current: 5 - }, - expected: [1, '...', 4, 5, 6, '...', 10] - } - ] - - testCases.forEach((testCase, index) => { - it(`should return the expected pagination for test case ${index + 1}`, () => { - const { input, expected } = testCase - const result = pagination(input.count, input.current) - expect(result).toEqual(expected) - }) +describe('RequestData', () => { + it('need to write these tests', () => { + expect(true).toBe(true) }) }) diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js new file mode 100644 index 00000000..05924cc7 --- /dev/null +++ b/test/unit/responseDetails.test.js @@ -0,0 +1,50 @@ +import { pagination } from '../../src/models/responseDetails' +import { describe, it, expect } from 'vitest' + +describe('Pagination', () => { + const testCases = [ + { + input: { + count: 1, + current: 0 + }, + expected: [1] + }, + { + input: { + count: 5, + current: 3 + }, + expected: [1, 2, 3, 4, 5] + }, + { + input: { + count: 6, + current: 2 + }, + expected: [1, 2, 3, '...', 6] + }, + { + input: { + count: 6, + current: 5 + }, + expected: [1, '...', 4, 5, 6] + }, + { + input: { + count: 10, + current: 5 + }, + expected: [1, '...', 4, 5, 6, '...', 10] + } + ] + + testCases.forEach((testCase, index) => { + it(`should return the expected pagination for test case ${index + 1}`, () => { + const { input, expected } = testCase + const result = pagination(input.count, input.current) + expect(result).toEqual(expected) + }) + }) +}) diff --git a/test/unit/resultsController.test.js b/test/unit/resultsController.test.js index f6c71f19..f27c333b 100644 --- a/test/unit/resultsController.test.js +++ b/test/unit/resultsController.test.js @@ -49,7 +49,8 @@ describe('ResultsController', () => { getFields: () => ['fields'], getFieldMappings: () => 'fieldMappings', getRowsWithVerboseColumns: () => ['verbose-columns'], - getGeometries: () => ['geometries'] + getGeometries: () => ['geometries'], + getPagination: () => 'pagination' } const mockResult = { @@ -59,8 +60,8 @@ describe('ResultsController', () => { isComplete: () => true, getParams: () => ('params'), getId: () => 'fake_id', - getPagination: () => 'pagination', - fetchResponseDetails: () => mockDetails + fetchResponseDetails: () => mockDetails, + getErrorSummary: () => ['error summary'] } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) @@ -76,7 +77,8 @@ describe('ResultsController', () => { getFields: () => ['fields'], getFieldMappings: () => 'fieldMappings', getRowsWithVerboseColumns: () => ['verbose-columns'], - getGeometries: () => ['geometries'] + getGeometries: () => ['geometries'], + getPagination: () => 'pagination' } const mockResult = { @@ -86,8 +88,8 @@ describe('ResultsController', () => { isComplete: () => true, getParams: () => ('params'), getId: () => 'fake_id', - getPagination: () => 'pagination', - fetchResponseDetails: () => mockDetails + fetchResponseDetails: () => mockDetails, + getErrorSummary: () => ['error summary'] } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) @@ -102,7 +104,8 @@ describe('ResultsController', () => { getFields: () => ['fields'], getFieldMappings: () => 'fieldMappings', getRowsWithVerboseColumns: () => ['verbose-columns'], - getGeometries: () => ['geometries'] + getGeometries: () => ['geometries'], + getPagination: () => 'pagination' } const mockResult = { @@ -112,7 +115,6 @@ describe('ResultsController', () => { isComplete: () => true, getParams: () => ('params'), getId: () => 'fake_id', - getPagination: () => 'pagination', fetchResponseDetails: () => mockDetails } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) @@ -128,7 +130,8 @@ describe('ResultsController', () => { getFields: () => ['fields'], getFieldMappings: () => 'fieldMappings', getRowsWithVerboseColumns: () => ['verbose-columns'], - getGeometries: () => ['geometries'] + getGeometries: () => ['geometries'], + getPagination: () => 'pagination' } const mockResult = { @@ -138,8 +141,8 @@ describe('ResultsController', () => { isComplete: () => true, getParams: () => ('params'), getId: () => 'fake_id', - getPagination: () => 'pagination', - fetchResponseDetails: () => mockDetails + fetchResponseDetails: () => mockDetails, + getErrorSummary: () => ['error summary'] } asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) @@ -154,6 +157,7 @@ describe('ResultsController', () => { expect(req.form.options.verboseRows).toStrictEqual(['verbose-columns']) expect(req.form.options.geometries).toStrictEqual(['geometries']) expect(req.form.options.pagination).toBe('pagination') + expect(req.form.options.errorSummary).toStrictEqual(['error summary']) }) }) }) From 5ec7a730a0ba42190af53af98c80b61cd739cba1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 21 May 2024 14:36:34 +0100 Subject: [PATCH 006/127] refactor controller classes --- src/models/requestData.js | 68 ----------------------------------- src/models/responseDetails.js | 20 ++++++++++- 2 files changed, 19 insertions(+), 69 deletions(-) diff --git a/src/models/requestData.js b/src/models/requestData.js index c17cd166..82b5bda0 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -65,35 +65,11 @@ export default class RequestData { return this.response.data['error-summary'].length > 0 } - getGeometryKey () { - const columnFieldLog = this.getColumnFieldLog() - - if (!columnFieldLog) { - return null - } - - const columnFieldEntry = columnFieldLog.find(column => column.field === 'point') || columnFieldLog.find(column => column.field === 'geometry') - - if (!columnFieldEntry) { - return null - } - - return columnFieldEntry.column - } - isComplete () { const finishedProcessingStatuses = ['COMPLETE', 'FAILED'] return finishedProcessingStatuses.includes(this.status) } - getRows () { - if (!this.response || !this.response.details) { - logger.error('trying to get response details when there are none: request id: ' + this.id) - return [] - } - return this.response.details - } - getColumnFieldLog () { if (!this.response || !this.response.data || !this.response.data['column-field-log']) { logger.error('trying to get column field log when there is none: request id: ' + this.id) @@ -102,36 +78,6 @@ export default class RequestData { return this.response.data['column-field-log'] } - getColumns (includeNonMapped = true) { - if (!this.getRows().length) { - return [] - } - return [...new Set(this.getRows().map(row => row.converted_row).flatMap(row => Object.keys(row)))] - } - - getFields (includeNonMapped = true) { - return [...new Set(this.getColumns().map(column => { - const columnFieldLog = this.getColumnFieldLog() - const fieldLog = columnFieldLog.find(fieldLog => fieldLog.column === column) - if (!fieldLog) { - return column - } else { - return fieldLog.field - } - }))] - } - - getFieldMappings () { - return Object.fromEntries(this.getFields().map(field => { - const columnFieldLog = this.getColumnFieldLog() - const columnLog = columnFieldLog.find(fieldLog => fieldLog.field === field) - return [ - field, - columnLog ? columnLog.column : null - ] - })) - } - getParams () { return this.params } @@ -139,18 +85,4 @@ export default class RequestData { getId () { return this.id } - - getGeometries () { - if (!this.response || !this.response.details) { - logger.error('trying to get response details when there are none: request id: ' + this.id) - return undefined - } - - const geometryKey = this.getGeometryKey() - const geometries = this.response.details.map(row => row.converted_row[geometryKey]).filter(geometry => geometry !== '') - if (geometries.length === 0) { - return null - } - return geometries - } } diff --git a/src/models/responseDetails.js b/src/models/responseDetails.js index c77fe2ab..cbaa8853 100644 --- a/src/models/responseDetails.js +++ b/src/models/responseDetails.js @@ -86,12 +86,30 @@ export default class ResponseDetails { })) } - getGeometries (geometryKey) { + getGeometryKey () { + const columnFieldLog = this.getColumnFieldLog() + + if (!columnFieldLog) { + return null + } + + const columnFieldEntry = columnFieldLog.find(column => column.field === 'point') || columnFieldLog.find(column => column.field === 'geometry') + + if (!columnFieldEntry) { + return null + } + + return columnFieldEntry.column + } + + getGeometries () { if (!this.response) { logger.error('trying to get response details when there are none: request id: ' + this.id) return undefined } + const geometryKey = this.getGeometryKey() + const geometries = this.response.map(row => row.converted_row[geometryKey]).filter(geometry => geometry !== '') if (geometries.length === 0) { return null From 92badada4a35a6f5091c54bf5b76fcf7d1626065 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 21 May 2024 15:26:59 +0100 Subject: [PATCH 007/127] fix tests --- test/unit/errorsPage.test.js | 1 - test/unit/noErrorsPage.test.js | 1 - 2 files changed, 2 deletions(-) diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index ec333991..388a470c 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -37,7 +37,6 @@ describe('errors page', () => { requestParams: requestData.getParams(), errorSummary: requestData.getErrorSummary(), rows: responseDetails.getRows(), - geometryKey: requestData.getGeometryKey(), columns: responseDetails.getColumns(), fields: responseDetails.getFields(), mappings: responseDetails.getFieldMappings(), diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 16b54ebd..539f5387 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -36,7 +36,6 @@ describe('no Errors Page', () => { requestParams: requestData.getParams(), errorSummary: requestData.getErrorSummary(), rows: responseDetails.getRows(), - geometryKey: requestData.getGeometryKey(), columns: responseDetails.getColumns(), fields: responseDetails.getFields(), mappings: responseDetails.getFieldMappings(), From b08cc892cf0c8516409c6f2d8abacda0c6ab653d Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 30 May 2024 10:40:18 +0100 Subject: [PATCH 008/127] started adding test outline --- test/unit/responseDetails.test.js | 72 +++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js index 05924cc7..bfb0ea3d 100644 --- a/test/unit/responseDetails.test.js +++ b/test/unit/responseDetails.test.js @@ -1,6 +1,78 @@ +import test from 'node:test' import { pagination } from '../../src/models/responseDetails' import { describe, it, expect } from 'vitest' +describe('ResponseDetails', () => { + // let responseDetails + // const mockResponse = [] // Fill with mock data + // const mockPagination = {} // Fill with mock data + // const mockColumnFieldLog = [] // Fill with mock data + + // beforeEach(() => { + // // responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + // }) + + describe('getRows', () => { + test('returns the rows', () => { + // TODO: Write test + }) + + test('returns an empty array if there are no rows and logs an error', () => { + + }) + }) + + describe('getColumnFieldLog', () => { + test('returns the column field log', () => { + // TODO: Write test + }) + + test('returns an empty array if there is no column field log and logs an error', () => { + + }) + }) + + describe('getColumns', () => { + test('returns the columns', () => { + + }) + + test('returns an empty array if there are no rows', () => { + + }) + }) + + test('getFields', () => { + // TODO: Write test + }) + + test('getFieldMappings', () => { + // TODO: Write test + }) + + describe('getRowsWithVerboseColumns', () => { + test('returns the rows with verbose columns', () => { + + }) + + test('returns an empty array if there are no rows and logs an error', () => { + + }) + }) + + test('getGeometryKey', () => { + // TODO: Write test + }) + + test('getGeometries', () => { + // TODO: Write test + }) + + test('getPagination', () => { + // TODO: Write test + }) +}) + describe('Pagination', () => { const testCases = [ { From 288f90498db5bae6d121200918605f4bd5f63c7b Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 4 Jun 2024 16:29:55 +0100 Subject: [PATCH 009/127] remove unneeded test --- test/unit/resultsController.test.js | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/unit/resultsController.test.js b/test/unit/resultsController.test.js index 033a77f8..7d95eb5e 100644 --- a/test/unit/resultsController.test.js +++ b/test/unit/resultsController.test.js @@ -77,32 +77,6 @@ describe('ResultsController', () => { expect(req.form.options.template).toBe('results/no-errors') }) - it('should set the template to the failedRequest template if the result is failed', async () => { - const mockDetails = { - getErrorSummary: () => ['error summary'], - getColumns: () => ['columns'], - getFields: () => ['fields'], - getFieldMappings: () => 'fieldMappings', - getRowsWithVerboseColumns: () => ['verbose-columns'], - getGeometries: () => ['geometries'], - getPagination: () => 'pagination' - } - - const mockResult = { - isFailed: () => true, - getError: () => 'error', - hasErrors: () => false, - isComplete: () => true, - getParams: () => ('params'), - getId: () => 'fake_id', - fetchResponseDetails: () => mockDetails - } - asyncRequestApi.getRequestData = vi.fn().mockResolvedValue(mockResult) - - await resultsController.locals(req, {}, () => {}) - expect(req.form.options.template).toBe('results/failedRequest') - }) - it('should redirect to the status page if the form is complete', async () => { const mockResult = { isComplete: () => true, From 556cc3488138d9ab25a84a6f63ebdea62ed36049 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 4 Jun 2024 16:31:47 +0100 Subject: [PATCH 010/127] start working on response details tests --- test/unit/responseDetails.test.js | 197 ++++++++++++++++++++++++------ 1 file changed, 157 insertions(+), 40 deletions(-) diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js index bfb0ea3d..5f039ff6 100644 --- a/test/unit/responseDetails.test.js +++ b/test/unit/responseDetails.test.js @@ -1,76 +1,193 @@ -import test from 'node:test' -import { pagination } from '../../src/models/responseDetails' -import { describe, it, expect } from 'vitest' +import ResponseDetails, { pagination } from '../../src/models/responseDetails' +import { describe, it, expect, vi, beforeEach } from 'vitest' +import logger from '../../src/utils/logger.js' describe('ResponseDetails', () => { - // let responseDetails - // const mockResponse = [] // Fill with mock data - // const mockPagination = {} // Fill with mock data - // const mockColumnFieldLog = [] // Fill with mock data + const mockResponse = [ + { + issue_logs: [], + entry_number: 1, + converted_row: { + id: '4', + wkt: 'POINT (423432.0000000000000000 564564.0000000000000000)', + name: 'South Jesmond', + Layer: 'Conservation Area', + 'area(ha)': '35.4', + geometry: '', + 'entry-date': '04/04/2025', + 'start-date': '04/04/2024', + 'documentation-url': 'www.example.com' + } + }, + { + issue_logs: [], + entry_number: 2, + converted_row: { + id: '5', + wkt: 'POINT (423432.0000000000000000 564564.0000000000000000)', + name: 'North Jesmond', + Layer: 'Conservation Area', + 'area(ha)': '35.4', + geometry: '', + 'entry-date': '04/04/2025', + 'start-date': '04/04/2024', + 'documentation-url': 'www.example.com' + } + } + ] - // beforeEach(() => { - // // responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) - // }) + const mockPagination = { + totalResults: 2, + offset: 0, + limit: 50 + } + + const mockColumnFieldLog = [ + { column: 'id', field: 'ID' }, + { column: 'wkt', field: 'WKT' }, + { column: 'name', field: 'Name' }, + { column: 'Layer', field: 'Layer' }, + { column: 'area(ha)', field: 'Area' }, + { column: 'geometry', field: 'Geometry' }, + { column: 'entry-date', field: 'Entry Date' }, + { column: 'start-date', field: 'Start Date' }, + { column: 'documentation-url', field: 'Documentation URL' } + ] + + vi.mock('../utils/logger.js', () => { + return { + default: { + error: vi.fn() + } + } + }) + + const loggerErrorSpy = vi.spyOn(logger, 'error') + + beforeEach(() => { + loggerErrorSpy.mockClear() + }) describe('getRows', () => { - test('returns the rows', () => { - // TODO: Write test + it('returns the rows', () => { + const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const result = responseDetails.getRows() + expect(result).toBe(mockResponse) }) - test('returns an empty array if there are no rows and logs an error', () => { - + it('returns an empty array if there are no rows and logs an error', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getRows() + expect(result).toStrictEqual([]) + expect(loggerErrorSpy).toHaveBeenCalled() }) }) describe('getColumnFieldLog', () => { - test('returns the column field log', () => { - // TODO: Write test + it('returns the column field log', () => { + const responseDetails = new ResponseDetails(undefined, undefined, mockColumnFieldLog) + const result = responseDetails.getColumnFieldLog() + expect(result).toStrictEqual(mockColumnFieldLog) }) - test('returns an empty array if there is no column field log and logs an error', () => { + it('returns an empty array if there is no column field log and logs an error', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getColumnFieldLog() + expect(result).toStrictEqual([]) + expect(loggerErrorSpy).toHaveBeenCalled() + }) + }) + describe('getFields', () => { + it('returns the unique fields from the column keys', () => { + const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const result = responseDetails.getFields() + const expected = ['ID', 'WKT', 'Name', 'Layer', 'Area', 'Geometry', 'Entry Date', 'Start Date', 'Documentation URL'] + expect(result).toEqual(expected) }) }) describe('getColumns', () => { - test('returns the columns', () => { - + it('returns the columns', () => { + const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + responseDetails.getFields = vi.fn(() => ['ID', 'WKT', 'Name', 'Layer', 'Area', 'Geometry', 'Entry Date', 'Start Date', 'Documentation URL']) + const result = responseDetails.getColumns() + expect(result).toEqual(['id', 'wkt', 'name', 'Layer', 'area(ha)', 'geometry', 'entry-date', 'start-date', 'documentation-url']) }) - test('returns an empty array if there are no rows', () => { - + it('returns an empty array if there are no rows', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getColumns() + expect(result).toStrictEqual([]) }) }) - test('getFields', () => { - // TODO: Write test - }) - - test('getFieldMappings', () => { - // TODO: Write test + it('getFieldMappings', () => { + const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const result = responseDetails.getFieldMappings() + const expected = { + ID: 'id', + WKT: 'wkt', + Name: 'name', + Layer: 'Layer', + Area: 'area(ha)', + Geometry: 'geometry', + 'Entry Date': 'entry-date', + 'Start Date': 'start-date', + 'Documentation URL': 'documentation-url' + } + expect(result).toEqual(expected) }) describe('getRowsWithVerboseColumns', () => { - test('returns the rows with verbose columns', () => { - + vi.mock('../utils/getVerboseColumns.js', () => { + return vi.fn((row, columnFieldLog) => { + return { row, columnFieldLog } + }) }) - test('returns an empty array if there are no rows and logs an error', () => { - + it('returns the rows with verbose columns', () => { + const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const result = responseDetails.getRowsWithVerboseColumns() + const expected = [ + { + entryNumber: 1, + hasErrors: false, + columns: { row: mockResponse[0], columnFieldLog: mockColumnFieldLog } + }, + { + entryNumber: 2, + hasErrors: false, + columns: { row: mockResponse[1], columnFieldLog: mockColumnFieldLog } + } + ] + expect(result).toStrictEqual(expected) }) - }) - test('getGeometryKey', () => { - // TODO: Write test + // it('returns the rows with verbose columns and filters out non-errors', () => { + // const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + // const result = responseDetails.getRowsWithVerboseColumns(true) + // }) + + // it('returns an empty array if there are no rows and logs an error', () => { + // const responseDetails = new ResponseDetails(undefined, undefined, undefined) + // const result = responseDetails.getRowsWithVerboseColumns() + // expect(result).toStrictEqual([]) + // expect(loggerErrorSpy).toHaveBeenCalled() + // }) }) - test('getGeometries', () => { - // TODO: Write test - }) + // it('getGeometryKey', () => { + // // TODO: Write test + // }) - test('getPagination', () => { - // TODO: Write test - }) + // it('getGeometries', () => { + // // TODO: Write test + // }) + + // it('getPagination', () => { + // // TODO: Write test + // }) }) describe('Pagination', () => { From 8fb931d784804449823ee1c41c5b33b7057e4907 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:11:37 +0100 Subject: [PATCH 011/127] further testing on response details --- test/unit/responseDetails.test.js | 79 +++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js index 7f0f2c3b..b7fe9db2 100644 --- a/test/unit/responseDetails.test.js +++ b/test/unit/responseDetails.test.js @@ -13,7 +13,7 @@ describe('ResponseDetails', () => { name: 'South Jesmond', Layer: 'Conservation Area', 'area(ha)': '35.4', - geometry: '', + geometry: 'POINT (423432.0000000000000000 564564.0000000000000000)', 'entry-date': '04/04/2025', 'start-date': '04/04/2024', 'documentation-url': 'www.example.com' @@ -28,7 +28,7 @@ describe('ResponseDetails', () => { name: 'North Jesmond', Layer: 'Conservation Area', 'area(ha)': '35.4', - geometry: '', + geometry: 'POINT (423432.0000000000000000 564564.0000000000000000)', 'entry-date': '04/04/2025', 'start-date': '04/04/2024', 'documentation-url': 'www.example.com' @@ -177,13 +177,76 @@ describe('ResponseDetails', () => { // }) }) - // it('getGeometryKey', () => { - // // TODO: Write test - // }) + describe('getGeometryKey', () => { + it('returns the column for "point" field', () => { + const responseDetails = new ResponseDetails(undefined, undefined, [ + { column: 'id', field: 'ID' }, + { column: 'wkt', field: 'WKT' }, + { column: 'point', field: 'point' }, + { column: 'name', field: 'Name' } + ]) + const result = responseDetails.getGeometryKey() + expect(result).toBe('point') + }) + + it('returns the column for "geometry" field', () => { + const responseDetails = new ResponseDetails(undefined, undefined, [ + { column: 'id', field: 'ID' }, + { column: 'wkt', field: 'WKT' }, + { column: 'geometry', field: 'geometry' }, + { column: 'name', field: 'Name' } + ]) + const result = responseDetails.getGeometryKey() + expect(result).toBe('geometry') + }) + + it('returns null if columnFieldLog is undefined', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getGeometryKey() + expect(result).toBeNull() + }) - // it('getGeometries', () => { - // // TODO: Write test - // }) + it('returns null if no columnFieldEntry is found', () => { + const responseDetails = new ResponseDetails(undefined, undefined, [ + { column: 'id', field: 'ID' }, + { column: 'wkt', field: 'WKT' }, + { column: 'name', field: 'Name' } + ]) + const result = responseDetails.getGeometryKey() + expect(result).toBeNull() + }) + }) + + describe('getGeometries', () => { + it('returns undefined and logs an error if there is no response', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getGeometries() + expect(result).toBeUndefined() + expect(loggerErrorSpy).toHaveBeenCalled() + }) + + it('returns null if there are no geometries', () => { + const responseDetails = new ResponseDetails([], undefined, undefined) + const result = responseDetails.getGeometries() + expect(result).toBeNull() + }) + + it('returns an array of geometries', () => { + const mockColumnFieldLog = [ + { column: 'id', field: 'ID' }, + { column: 'wkt', field: 'WKT' }, + { column: 'geometry', field: 'geometry' }, + { column: 'name', field: 'Name' } + ] + const responseDetails = new ResponseDetails(mockResponse, undefined, mockColumnFieldLog) + const result = responseDetails.getGeometries() + const expected = [ + 'POINT (423432.0000000000000000 564564.0000000000000000)', + 'POINT (423432.0000000000000000 564564.0000000000000000)' + ] + expect(result).toEqual(expected) + }) + }) describe('getPagination', () => { it('should return correct pagination data', () => { From 31de367ff24eb59474922c45a5b285e6522c82af Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:28:11 +0100 Subject: [PATCH 012/127] add tests for requestData.fetchResponseDetails --- test/unit/requestData.test.js | 70 +++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index b1426d3e..2a0fa73b 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -1,9 +1,71 @@ -// import RequestData from '../../src/models/requestData' -import { describe, it, expect } from 'vitest' +import RequestData from '../../src/models/requestData' +import ResponseDetails from '../../src/models/responseDetails' +import { describe, it, expect, vi } from 'vitest' +import axios from 'axios' + +vi.mock('axios') // Tech Debt: we should write some more tests around the requestData.js file describe('RequestData', () => { - it('empty test', () => { - expect(false).toBe(true) + describe('fetchResponseDetails', () => { + it('should return a new ResponseDetails object', async () => { + + axios.get.mockResolvedValue({ + headers: { + 'x-pagination-total-results': 1, + 'x-pagination-offset': 0, + 'x-pagination-limit': 50 + }, + data: { + 'error-summary': ['error1', 'error2'] + } + }) + + const response = { + id: 1, + getColumnFieldLog: () => [] + } + const requestData = new RequestData(response) + + const responseDetails = await requestData.fetchResponseDetails() + + expect(responseDetails).toBeInstanceOf(ResponseDetails) + + expect(responseDetails.pagination.totalResults).toBe(1) + expect(responseDetails.pagination.offset).toBe(0) + expect(responseDetails.pagination.limit).toBe(50) + expect(responseDetails.response).toStrictEqual({ + 'error-summary': ['error1', 'error2'] + }) + + expect(axios.get).toHaveBeenCalledWith('http://localhost:8001/requests/1/response-details?offset=0&limit=50', { timeout: 30000 }) + }) + + it('correctly sets the jsonpath if severity is provided', async () => { + axios.get.mockResolvedValue({ + headers: { + 'x-pagination-total-results': 1, + 'x-pagination-offset': 0, + 'x-pagination-limit': 50 + }, + data: { + 'error-summary': ['error1', 'error2'] + } + }) + + const response = { + id: 1, + getColumnFieldLog: () => [] + } + const requestData = new RequestData(response) + + await requestData.fetchResponseDetails(0, 50, 'error') + + expect(axios.get).toHaveBeenCalledWith(`http://localhost:8001/requests/1/response-details?offset=0&limit=50&jsonpath=${encodeURIComponent('$.issue_logs[*].severity=="error"')}`, { timeout: 30000 }) + }) + }) + + describe('getErrorSummary', () => { + }) }) From 9180d886c292204f6a1dbce374f9cc1478e2b536 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:28:18 +0100 Subject: [PATCH 013/127] linting --- test/unit/requestData.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 2a0fa73b..812348e3 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -9,7 +9,6 @@ vi.mock('axios') describe('RequestData', () => { describe('fetchResponseDetails', () => { it('should return a new ResponseDetails object', async () => { - axios.get.mockResolvedValue({ headers: { 'x-pagination-total-results': 1, @@ -66,6 +65,6 @@ describe('RequestData', () => { }) describe('getErrorSummary', () => { - + }) }) From d08c1412b16ff88dac01b4d5e5b98d6ca3bd0e7d Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:33:56 +0100 Subject: [PATCH 014/127] added tests for requestData.getErrorSummary --- test/unit/requestData.test.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 812348e3..81a0ad76 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -2,9 +2,20 @@ import RequestData from '../../src/models/requestData' import ResponseDetails from '../../src/models/responseDetails' import { describe, it, expect, vi } from 'vitest' import axios from 'axios' +import logger from '../../src/utils/logger' vi.mock('axios') +vi.mock('../utils/logger.js', () => { + return { + default: { + error: vi.fn() + } + } +}) + +vi.spyOn(logger, 'error') + // Tech Debt: we should write some more tests around the requestData.js file describe('RequestData', () => { describe('fetchResponseDetails', () => { @@ -65,6 +76,28 @@ describe('RequestData', () => { }) describe('getErrorSummary', () => { + it('should return the error summary from the response', () => { + const response = { + data: { + 'error-summary': ['error1', 'error2'] + } + } + const requestData = new RequestData({ response }) + const errorSummary = requestData.getErrorSummary() + + expect(errorSummary).toStrictEqual(['error1', 'error2']) + }) + + it('should return an empty array if there is no error summary and log an error', () => { + const response = {} + const requestData = new RequestData(response) + + const errorSummary = requestData.getErrorSummary() + + expect(errorSummary).toStrictEqual([]) + + expect(logger.error).toHaveBeenCalledWith('trying to get error summary when there is none: request id: undefined') + }) }) }) From d9fd1928548a2eea7eb925155dbf15fb0d458493 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:34:55 +0100 Subject: [PATCH 015/127] added tests for isFailed --- test/unit/requestData.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 81a0ad76..17690212 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -100,4 +100,30 @@ describe('RequestData', () => { expect(logger.error).toHaveBeenCalledWith('trying to get error summary when there is none: request id: undefined') }) }) + + describe('isFailed', () => { + it('should return true if the status is FAILED', () => { + const response = { + status: 'FAILED' + } + const requestData = new RequestData(response) + + const isFailed = requestData.isFailed() + + expect(isFailed).toBe(true) + }) + + it('should return false if the status is not FAILED', () => { + const response = { + status: 'SUCCESS' + } + const requestData = new RequestData(response) + + const isFailed = requestData.isFailed() + + expect(isFailed).toBe(false) + }) + }) + + }) From 9fc7bc993c6aa272a2145ecbfab24f26efdc0c84 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:36:39 +0100 Subject: [PATCH 016/127] added tests for getType and getError --- test/unit/requestData.test.js | 36 ++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 17690212..9de1565e 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -125,5 +125,39 @@ describe('RequestData', () => { }) }) - + describe('getType', () => { + it('should return the type', () => { + const response = { + type: 'type1' + } + const requestData = new RequestData(response) + + const type = requestData.getType() + + expect(type).toBe('type1') + }) + }) + + describe('getError', () => { + it('should return the error from the response', () => { + const response = { + error: { message: 'error message' } + } + const requestData = new RequestData({response}) + + const error = requestData.getError() + + expect(error).toStrictEqual({ message: 'error message' }) + }) + + it('should return an unknown error if there is no error and log an error', () => { + const requestData = new RequestData({}) + + const error = requestData.getError() + + expect(error).toStrictEqual({ message: 'An unknown error occurred.' }) + + expect(logger.error).toHaveBeenCalledWith('trying to get error when there are none: request id: undefined') + }) + }) }) From 36713a7968ad0f701f90d5098b8382611257b5c9 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:36:46 +0100 Subject: [PATCH 017/127] linting --- test/unit/requestData.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 9de1565e..3d502592 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -143,7 +143,7 @@ describe('RequestData', () => { const response = { error: { message: 'error message' } } - const requestData = new RequestData({response}) + const requestData = new RequestData({ response }) const error = requestData.getError() From 26e83e5b0b5036999657842c4ee15d333303ee92 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:42:21 +0100 Subject: [PATCH 018/127] added tests for the requestData hasErrors method --- src/models/requestData.js | 7 +---- test/unit/requestData.test.js | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/models/requestData.js b/src/models/requestData.js index 16c287cd..ece9f04f 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -57,13 +57,8 @@ export default class RequestData { logger.error('trying to check for errors when there are none: request id: ' + this.id) return true } - if (this.response == null) { - return true - } - if (this.response.data == null) { - return true - } if (this.response.data['error-summary'] == null) { + logger.error('trying to check for errors but there is no error-summary: request id: ' + this.id) return true } return this.response.data['error-summary'].length > 0 diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 3d502592..00cc5a27 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -160,4 +160,55 @@ describe('RequestData', () => { expect(logger.error).toHaveBeenCalledWith('trying to get error when there are none: request id: undefined') }) }) + + describe('hasErrors', () => { + it('should return true if there are errors', () => { + const response = { + data: { + 'error-summary': ['error1', 'error2'] + } + } + const requestData = new RequestData({ response }) + + const hasErrors = requestData.hasErrors() + + expect(hasErrors).toBe(true) + }) + + it('should return true if there are no errors and log an error', () => { + const requestData = new RequestData({}) + + const hasErrors = requestData.hasErrors() + + expect(hasErrors).toBe(true) + + expect(logger.error).toHaveBeenCalledWith('trying to check for errors when there are none: request id: undefined') + }) + + it('should return true if there is no error summary and log an error', () => { + const response = { + data: {} + } + const requestData = new RequestData({ response }) + + const hasErrors = requestData.hasErrors() + + expect(hasErrors).toBe(true) + + expect(logger.error).toHaveBeenCalledWith('trying to check for errors but there is no error-summary: request id: undefined') + }) + + it('should return false if the error summary is empty', () => { + const response = { + data: { + 'error-summary': [] + } + } + const requestData = new RequestData({ response }) + + const hasErrors = requestData.hasErrors() + + expect(hasErrors).toBe(false) + }) + }) }) From 6961848e2f52c8a2d8b47df325b74aa224c46ae1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:43:02 +0100 Subject: [PATCH 019/127] added tests for the isComplete method --- test/unit/requestData.test.js | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index 00cc5a27..fda7a9b6 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -211,4 +211,41 @@ describe('RequestData', () => { expect(hasErrors).toBe(false) }) }) + + describe('isComplete', () => { + it('should return true if the status is COMPLETE', () => { + const response = { + status: 'COMPLETE' + } + const requestData = new RequestData(response) + + const isComplete = requestData.isComplete() + + expect(isComplete).toBe(true) + }) + + it('should return true if the status is FAILED', () => { + const response = { + status: 'FAILED' + } + const requestData = new RequestData(response) + + const isComplete = requestData.isComplete() + + expect(isComplete).toBe(true) + }) + + it('should return false if the status is not COMPLETE or FAILED', () => { + const response = { + status: 'IN_PROGRESS' + } + const requestData = new RequestData(response) + + const isComplete = requestData.isComplete() + + expect(isComplete).toBe(false) + }) + }) + + }) From c1991166860a0cea926051118b32fe7cd349c4cd Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 10:44:43 +0100 Subject: [PATCH 020/127] added tests for getColumnFieldLog, getParams and getID --- test/unit/requestData.test.js | 45 ++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/test/unit/requestData.test.js b/test/unit/requestData.test.js index fda7a9b6..3e2b714c 100644 --- a/test/unit/requestData.test.js +++ b/test/unit/requestData.test.js @@ -247,5 +247,48 @@ describe('RequestData', () => { }) }) - + describe('getColumnFieldLog', () => { + it('should return the column field log from the response', () => { + const response = { + data: { + 'column-field-log': ['column1', 'column2'] + } + } + const requestData = new RequestData({ response }) + + const columnFieldLog = requestData.getColumnFieldLog() + + expect(columnFieldLog).toStrictEqual(['column1', 'column2']) + }) + + it('should return an empty array if there is no column field log and log an error', () => { + const requestData = new RequestData({}) + + const columnFieldLog = requestData.getColumnFieldLog() + + expect(columnFieldLog).toStrictEqual([]) + + expect(logger.error).toHaveBeenCalledWith('trying to get column field log when there is none: request id: undefined') + }) + }) + + describe('getParams', () => { + it('should return the params', () => { + const requestData = new RequestData({ params: { param1: 'value1' } }) + + const params = requestData.getParams() + + expect(params).toStrictEqual({ param1: 'value1' }) + }) + }) + + describe('getId', () => { + it('should return the id', () => { + const requestData = new RequestData({ id: 1 }) + + const id = requestData.getId() + + expect(id).toBe(1) + }) + }) }) From 2d67c75e0bcdfc264b73c56ed30862ac4de617cf Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 5 Jun 2024 14:58:02 +0100 Subject: [PATCH 021/127] test responseDetails getRowsWithVerboseColumns --- src/models/responseDetails.js | 2 +- src/utils/getVerboseColumns.js | 4 +- test/unit/responseDetails.test.js | 68 +++++++++++++++++++++++-------- 3 files changed, 55 insertions(+), 19 deletions(-) diff --git a/src/models/responseDetails.js b/src/models/responseDetails.js index b49920e0..440c62d2 100644 --- a/src/models/responseDetails.js +++ b/src/models/responseDetails.js @@ -1,4 +1,4 @@ -import getVerboseColumns from '../utils/getVerboseColumns.js' +import { getVerboseColumns } from '../utils/getVerboseColumns.js' import logger from '../utils/logger.js' export default class ResponseDetails { diff --git a/src/utils/getVerboseColumns.js b/src/utils/getVerboseColumns.js index bc30236f..220f5017 100644 --- a/src/utils/getVerboseColumns.js +++ b/src/utils/getVerboseColumns.js @@ -3,7 +3,7 @@ */ import logger from './logger.js' -export default (row, columnFieldLog) => { +const getVerboseColumns = (row, columnFieldLog) => { if (!columnFieldLog || !row.issue_logs) { // Log an error if the["column-field-log"] or issue_logs are missing, and return what we can logger.error('Invalid row data, missing["column-field-log"] or issue_logs') @@ -49,3 +49,5 @@ const reduceVerboseValues = (verboseValuesAsArray) => { return acc }, {}) } + +export { getVerboseColumns } diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js index b7fe9db2..1e8eda3a 100644 --- a/test/unit/responseDetails.test.js +++ b/test/unit/responseDetails.test.js @@ -2,6 +2,14 @@ import ResponseDetails, { pagination } from '../../src/models/responseDetails' import { describe, it, expect, vi, beforeEach } from 'vitest' import logger from '../../src/utils/logger.js' +vi.mock('../../src/utils/getVerboseColumns.js', () => { + return { + getVerboseColumns: vi.fn((row, columnFieldLog) => { + return { row, columnFieldLog } + }) + } +}) + describe('ResponseDetails', () => { const mockResponse = [ { @@ -140,12 +148,6 @@ describe('ResponseDetails', () => { }) describe('getRowsWithVerboseColumns', () => { - vi.mock('../utils/getVerboseColumns.js', () => { - return vi.fn((row, columnFieldLog) => { - return { row, columnFieldLog } - }) - }) - it('returns the rows with verbose columns', () => { const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getRowsWithVerboseColumns() @@ -164,17 +166,49 @@ describe('ResponseDetails', () => { expect(result).toStrictEqual(expected) }) - // it('returns the rows with verbose columns and filters out non-errors', () => { - // const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) - // const result = responseDetails.getRowsWithVerboseColumns(true) - // }) - - // it('returns an empty array if there are no rows and logs an error', () => { - // const responseDetails = new ResponseDetails(undefined, undefined, undefined) - // const result = responseDetails.getRowsWithVerboseColumns() - // expect(result).toStrictEqual([]) - // expect(loggerErrorSpy).toHaveBeenCalled() - // }) + it('returns the rows with verbose columns and filters out non-errors', () => { + const errorRow = { + issue_logs: [ + { + message: 'a made up issue with this row', + severity: 'error' + } + ], + entry_number: 3, + converted_row: { + id: '4', + wkt: 'POINT (423432.0000000000000000 564564.0000000000000000)', + name: 'South Jesmond', + Layer: 'Conservation Area', + 'area(ha)': '35.4', + geometry: 'POINT (423432.0000000000000000 564564.0000000000000000)', + 'entry-date': '04/04/2025', + 'start-date': '04/04/2024', + 'documentation-url': 'www.example.com' + } + } + const _mockResponse = [ + ...mockResponse, + errorRow + ] + const responseDetails = new ResponseDetails(_mockResponse, mockPagination, mockColumnFieldLog) + const result = responseDetails.getRowsWithVerboseColumns(true) + const expected = [ + { + entryNumber: 3, + hasErrors: true, + columns: { row: errorRow, columnFieldLog: mockColumnFieldLog } + } + ] + expect(result).toStrictEqual(expected) + }) + + it('returns an empty array if there are no rows and logs an error', () => { + const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const result = responseDetails.getRowsWithVerboseColumns() + expect(result).toStrictEqual([]) + expect(loggerErrorSpy).toHaveBeenCalled() + }) }) describe('getGeometryKey', () => { From 1f9d4074d58542adb77fd5f0b41c247beafda4d8 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:16:14 +0100 Subject: [PATCH 022/127] initial commit --- .gitignore | 1 + package.json | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 .gitignore create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d8b83df9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +package-lock.json diff --git a/package.json b/package.json new file mode 100644 index 00000000..05c798e7 --- /dev/null +++ b/package.json @@ -0,0 +1,11 @@ +{ + "name": "endpoint-submission-form", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} From 06dd6817003461d9ecc21c320ce2b197e2e2a8fe Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:38:40 +0100 Subject: [PATCH 023/127] add standard linting --- .gitignore | 1 + package.json | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d8b83df9..a4accdd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ package-lock.json +node_modules/* diff --git a/package.json b/package.json index 05c798e7..33bae779 100644 --- a/package.json +++ b/package.json @@ -7,5 +7,8 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", - "license": "ISC" + "license": "ISC", + "dependencies": { + "standard": "^17.1.0" + } } From 3a8b5448b98a4cf11d66f6c0e0e85d59ecf39359 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:39:56 +0100 Subject: [PATCH 024/127] add linting scripts --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 33bae779..a33fbc61 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,13 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "lint": "standard", + "lint:fix": "standard --fix" }, "author": "", "license": "ISC", - "dependencies": { + "devDependencies": { "standard": "^17.1.0" } } From 03b91b484d13e855d03460679e453a2888105a29 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:41:58 +0100 Subject: [PATCH 025/127] add husky and init command --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index a33fbc61..86a47247 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "main": "index.js", "scripts": { + "prepare": "husky init", "test": "echo \"Error: no test specified\" && exit 1", "lint": "standard", "lint:fix": "standard --fix" @@ -11,6 +12,7 @@ "author": "", "license": "ISC", "devDependencies": { + "husky": "^9.0.11", "standard": "^17.1.0" } } From d5e2b7f8fc7750a78f5f818869554e4148b984d3 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:45:15 +0100 Subject: [PATCH 026/127] add husky scripts and empty index.js --- .husky/pre-commit | 2 ++ package.json | 2 +- src/index.js | 0 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .husky/pre-commit create mode 100644 src/index.js diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..3e58d0a6 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +npm run lint:fix +npm run lint diff --git a/package.json b/package.json index 86a47247..38d2cd0a 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "", "main": "index.js", "scripts": { - "prepare": "husky init", + "prepare": "husky", "test": "echo \"Error: no test specified\" && exit 1", "lint": "standard", "lint:fix": "standard --fix" diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..e69de29b From e261fc0ef8fb9027fcab756c630178c494bf4a04 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 6 Jun 2024 14:53:04 +0100 Subject: [PATCH 027/127] add lint and test github ci action --- .github/workflows/lint_and_test_on_push.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/lint_and_test_on_push.yml diff --git a/.github/workflows/lint_and_test_on_push.yml b/.github/workflows/lint_and_test_on_push.yml new file mode 100644 index 00000000..d5ffba6f --- /dev/null +++ b/.github/workflows/lint_and_test_on_push.yml @@ -0,0 +1,19 @@ +name: Run Tests and Lint Files +on: pull_request +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + npm ci + npm run lint + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: | + npm ci + npx playwright install --with-deps + npm run test \ No newline at end of file From e6ecc915955cf34de2c668376b6db04744d4d94f Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 7 Jun 2024 11:00:09 +0100 Subject: [PATCH 028/127] setting up the form wizard and adding the start page --- index.js | 11 +++++ package.json | 9 +++- src/index.js | 0 src/routes/form-wizard/fields.js | 3 ++ src/routes/form-wizard/index.js | 10 +++++ src/routes/form-wizard/steps.js | 6 +++ src/serverSetup/routes.js | 5 +++ src/views/start.html | 76 ++++++++++++++++++++++++++++++++ 8 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 index.js delete mode 100644 src/index.js create mode 100644 src/routes/form-wizard/fields.js create mode 100644 src/routes/form-wizard/index.js create mode 100644 src/routes/form-wizard/steps.js create mode 100644 src/serverSetup/routes.js create mode 100644 src/views/start.html diff --git a/index.js b/index.js new file mode 100644 index 00000000..e84d1fd8 --- /dev/null +++ b/index.js @@ -0,0 +1,11 @@ +import express from 'express' +import { setupRoutes } from './src/serverSetup/routes.js' + +const app = express() +const port = 3000 + +setupRoutes(app) + +app.listen(port, () => { + console.log(`Server listening at http://localhost:${port}`) +}); \ No newline at end of file diff --git a/package.json b/package.json index 38d2cd0a..a5e0fc69 100644 --- a/package.json +++ b/package.json @@ -3,16 +3,23 @@ "version": "1.0.0", "description": "", "main": "index.js", + "type": "module", "scripts": { "prepare": "husky", "test": "echo \"Error: no test specified\" && exit 1", "lint": "standard", - "lint:fix": "standard --fix" + "lint:fix": "standard --fix", + "start": "node index.js" }, "author": "", "license": "ISC", "devDependencies": { "husky": "^9.0.11", "standard": "^17.1.0" + }, + "dependencies": { + "hmpo-config": "^3.0.0", + "hmpo-form-wizard": "^13.0.0", + "hmpo-i18n": "^6.0.1" } } diff --git a/src/index.js b/src/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js new file mode 100644 index 00000000..ff2dbcee --- /dev/null +++ b/src/routes/form-wizard/fields.js @@ -0,0 +1,3 @@ +export default { + +} \ No newline at end of file diff --git a/src/routes/form-wizard/index.js b/src/routes/form-wizard/index.js new file mode 100644 index 00000000..1b2ffae5 --- /dev/null +++ b/src/routes/form-wizard/index.js @@ -0,0 +1,10 @@ +import { Router } from 'express' +import wizard from 'hmpo-form-wizard' +import steps from './steps.js' +import fields from './fields.js' + +const app = Router() + +app.use(wizard(steps, fields, { name: 'my-wizard', csrf: false })) + +export default app \ No newline at end of file diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js new file mode 100644 index 00000000..182406dd --- /dev/null +++ b/src/routes/form-wizard/steps.js @@ -0,0 +1,6 @@ +export default { + '/start': { + + } + +} \ No newline at end of file diff --git a/src/serverSetup/routes.js b/src/serverSetup/routes.js new file mode 100644 index 00000000..ce938085 --- /dev/null +++ b/src/serverSetup/routes.js @@ -0,0 +1,5 @@ +import formWizard from '../routes/form-wizard/index.js' + +export function setupRoutes(app) { + app.use('/', formWizard); +} \ No newline at end of file diff --git a/src/views/start.html b/src/views/start.html new file mode 100644 index 00000000..d8a3f634 --- /dev/null +++ b/src/views/start.html @@ -0,0 +1,76 @@ +{% extends "layouts/main.html" %} + +{% set pageName = serviceName %} + +{% block content %} + +{% set content %} + +Use this service to submit your: + +- article 4 direction data +- conservation area data +{# - listed building data #} +{# - tree preservation order data #} + +## Before you start + +### Publish data on your website + +Your data must be on a URL the public can access. We collect the latest data from there every day. + +You must link to that URL from a webpage about the data. This needs to be on your official planning authority website, +usually ending in gov.uk. + +The webpage must include, for each dataset: + +- the link to the data URL +- a summary of what the data is about +- a statement that the data is provided under the Open Government Licence + + +{{ govukButton({ + text: "Start now", + href: "/submit-endpoint/lpa-details", + isStartButton: true + }) }} + +{% endset %} + +
+
+

+ {{ pageName }} +

+
+
+ +
+
+ {{content | govukMarkdown(headingsStartWith="l")}} +
+
+ {{ xGovukRelatedNavigation({ + sections: [{ + items: [ + { + text: "Prepare data to the specifications", + href: "https://www.planning.data.gov.uk/guidance/specifications/" + }, + { + text: "Publish data on your website", + href: "https://www.planning.data.gov.uk/guidance/publish-data-on-your-website" + } + ], + subsections: [{ + title: "Explore the topic", + items: [{ + text: "Housing and planning", + href: "/browse/performing-arts" + }] + }] + }] + }) }} +
+
+{% endblock %} \ No newline at end of file From ada9e8fe66ff838c7eb715ad96aa1bdad2415a3e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 7 Jun 2024 11:01:40 +0100 Subject: [PATCH 029/127] linting --- index.js | 4 ++-- src/routes/form-wizard/fields.js | 4 ++-- src/routes/form-wizard/index.js | 2 +- src/routes/form-wizard/steps.js | 6 +++--- src/serverSetup/routes.js | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index e84d1fd8..337e0303 100644 --- a/index.js +++ b/index.js @@ -7,5 +7,5 @@ const port = 3000 setupRoutes(app) app.listen(port, () => { - console.log(`Server listening at http://localhost:${port}`) -}); \ No newline at end of file + console.log(`Server listening at http://localhost:${port}`) +}) diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index ff2dbcee..03048022 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -1,3 +1,3 @@ export default { - -} \ No newline at end of file + +} diff --git a/src/routes/form-wizard/index.js b/src/routes/form-wizard/index.js index 1b2ffae5..032b56fa 100644 --- a/src/routes/form-wizard/index.js +++ b/src/routes/form-wizard/index.js @@ -7,4 +7,4 @@ const app = Router() app.use(wizard(steps, fields, { name: 'my-wizard', csrf: false })) -export default app \ No newline at end of file +export default app diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index 182406dd..3942e730 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,6 +1,6 @@ export default { - '/start': { + '/start': { - } + } -} \ No newline at end of file +} diff --git a/src/serverSetup/routes.js b/src/serverSetup/routes.js index ce938085..02e1272f 100644 --- a/src/serverSetup/routes.js +++ b/src/serverSetup/routes.js @@ -1,5 +1,5 @@ import formWizard from '../routes/form-wizard/index.js' -export function setupRoutes(app) { - app.use('/', formWizard); -} \ No newline at end of file +export function setupRoutes (app) { + app.use('/', formWizard) +} From 77e13a7ad167941721db9d1e8546547c0d821256 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 13:23:49 +0100 Subject: [PATCH 030/127] further server setup, getting the start page working --- index.js | 7 + package.json | 8 +- public/stylesheets/index.css | 8391 ++++++++++++++++++++++++++++++ public/stylesheets/index.css.map | 1 + src/filters/filters.js | 9 + src/routes/form-wizard/steps.js | 6 +- src/serverSetup/middlewares.js | 34 + src/serverSetup/nunjucks.js | 27 + src/serverSetup/setupSession.js | 32 + src/views/layouts/main.html | 75 + src/views/start.html | 4 +- 11 files changed, 8590 insertions(+), 4 deletions(-) create mode 100644 public/stylesheets/index.css create mode 100644 public/stylesheets/index.css.map create mode 100644 src/filters/filters.js create mode 100644 src/serverSetup/middlewares.js create mode 100644 src/serverSetup/nunjucks.js create mode 100644 src/serverSetup/setupSession.js create mode 100644 src/views/layouts/main.html diff --git a/index.js b/index.js index 337e0303..860e91aa 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,17 @@ import express from 'express' import { setupRoutes } from './src/serverSetup/routes.js' +import { setupSession } from './src/serverSetup/setupSession.js' +import { setupNunjucks } from './src/serverSetup/nunjucks.js' +import { setupMiddlewares } from './src/serverSetup/middlewares.js' const app = express() const port = 3000 +setupSession(app) setupRoutes(app) +setupNunjucks(app) +setupMiddlewares(app) + app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`) diff --git a/package.json b/package.json index a5e0fc69..10fce164 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,14 @@ "standard": "^17.1.0" }, "dependencies": { + "@x-govuk/govuk-prototype-components": "^3.0.5", + "@x-govuk/govuk-prototype-filters": "^1.4.0", + "cookie-parser": "^1.4.6", + "express-session": "^1.18.0", + "govuk-frontend": "^5.4.0", "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", - "hmpo-i18n": "^6.0.1" + "hmpo-i18n": "^6.0.1", + "nunjucks": "^3.2.4" } } diff --git a/public/stylesheets/index.css b/public/stylesheets/index.css new file mode 100644 index 00000000..8df6d862 --- /dev/null +++ b/public/stylesheets/index.css @@ -0,0 +1,8391 @@ +@charset "UTF-8"; +:root { + --govuk-frontend-version: "4.7.0"; +} + +a, .govuk-link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; +} +/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */ /* stylelint-disable-line scss/comment-no-loud */ +@font-face { + font-family: "GDS Transport"; + font-style: normal; + font-weight: normal; + src: url("/assets/fonts/light-94a07e06a1-v2.woff2") format("woff2"), url("/assets/fonts/light-f591b13f7d-v2.woff") format("woff"); + font-display: fallback; +} +@font-face { + font-family: "GDS Transport"; + font-style: normal; + font-weight: bold; + src: url("/assets/fonts/bold-b542beb274-v2.woff2") format("woff2"), url("/assets/fonts/bold-affa96571d-v2.woff") format("woff"); + font-display: fallback; +} +@media print { + a, .govuk-link { + font-family: sans-serif; + } +} +a:focus, .govuk-link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +a:link, .govuk-link:link { + color: #1d70b8; +} +a:visited, .govuk-link:visited { + color: #4c2c92; +} +a:hover, .govuk-link:hover { + color: #003078; +} +a:active, .govuk-link:active { + color: #0b0c0c; +} +a:focus, .govuk-link:focus { + color: #0b0c0c; +} +@media print { + a[href^="/"]:after, [href^="/"].govuk-link:after, a[href^="http://"]:after, [href^="http://"].govuk-link:after, a[href^="https://"]:after, [href^="https://"].govuk-link:after { + content: " (" attr(href) ")"; + font-size: 90%; + word-wrap: break-word; + } +} + +.govuk-link--muted:link, .govuk-link--muted:visited { + color: #505a5f; +} +.govuk-link--muted:hover, .govuk-link--muted:active { + color: #0b0c0c; +} +.govuk-link--muted:focus { + color: #0b0c0c; +} + +.govuk-link--text-colour:link, .govuk-link--text-colour:visited { + color: #0b0c0c; +} +@media print { + .govuk-link--text-colour:link, .govuk-link--text-colour:visited { + color: #000000; + } +} +.govuk-link--text-colour:hover { + color: rgba(11, 12, 12, 0.99); +} +.govuk-link--text-colour:active, .govuk-link--text-colour:focus { + color: #0b0c0c; +} +@media print { + .govuk-link--text-colour:active, .govuk-link--text-colour:focus { + color: #000000; + } +} + +.govuk-link--inverse:link, .govuk-link--inverse:visited { + color: #ffffff; +} +.govuk-link--inverse:hover, .govuk-link--inverse:active { + color: rgba(255, 255, 255, 0.99); +} +.govuk-link--inverse:focus { + color: #0b0c0c; +} + +.govuk-link--no-underline:not(:hover):not(:active) { + text-decoration: none; +} + +.govuk-link--no-visited-state:link { + color: #1d70b8; +} +.govuk-link--no-visited-state:visited { + color: #1d70b8; +} +.govuk-link--no-visited-state:hover { + color: #003078; +} +.govuk-link--no-visited-state:active { + color: #0b0c0c; +} +.govuk-link--no-visited-state:focus { + color: #0b0c0c; +} + +.govuk-list { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + margin-top: 0; + margin-bottom: 15px; + padding-left: 0; + list-style-type: none; +} +@media print { + .govuk-list { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-list { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-list { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-list { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-list { + margin-bottom: 20px; + } +} +.govuk-list .govuk-list { + margin-top: 10px; +} + +.govuk-list > li { + margin-bottom: 5px; +} + +.govuk-list--bullet { + padding-left: 20px; + list-style-type: disc; +} + +.govuk-list--number { + padding-left: 20px; + list-style-type: decimal; +} + +.govuk-list--bullet > li, +.govuk-list--number > li { + margin-bottom: 0; +} +@media (min-width: 40.0625em) { + .govuk-list--bullet > li, + .govuk-list--number > li { + margin-bottom: 5px; + } +} + +.govuk-list--spaced > li { + margin-bottom: 10px; +} +@media (min-width: 40.0625em) { + .govuk-list--spaced > li { + margin-bottom: 15px; + } +} + +.govuk-heading-xl { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; + display: block; + margin-top: 0; + margin-bottom: 30px; +} +@media print { + .govuk-heading-xl { + color: #000000; + } +} +@media print { + .govuk-heading-xl { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-xl { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .govuk-heading-xl { + font-size: 32pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-xl { + margin-bottom: 50px; + } +} + +.govuk-heading-l { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; + display: block; + margin-top: 0; + margin-bottom: 20px; +} +@media print { + .govuk-heading-l { + color: #000000; + } +} +@media print { + .govuk-heading-l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-l { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-heading-l { + font-size: 24pt; + line-height: 1.05; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-l { + margin-bottom: 30px; + } +} + +.govuk-heading-m { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + display: block; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + .govuk-heading-m { + color: #000000; + } +} +@media print { + .govuk-heading-m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-m { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-heading-m { + font-size: 18pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-m { + margin-bottom: 20px; + } +} + +.govuk-heading-s { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: block; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + .govuk-heading-s { + color: #000000; + } +} +@media print { + .govuk-heading-s { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-s { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-heading-s { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-heading-s { + margin-bottom: 20px; + } +} + +.govuk-caption-xl { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + display: block; + margin-bottom: 5px; + color: #505a5f; +} +@media print { + .govuk-caption-xl { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-caption-xl { + font-size: 27px; + font-size: 1.6875rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-caption-xl { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-caption-l { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + display: block; + margin-bottom: 5px; + color: #505a5f; +} +@media print { + .govuk-caption-l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-caption-l { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-caption-l { + font-size: 18pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-caption-l { + margin-bottom: 0; + } +} + +.govuk-caption-m { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: block; + color: #505a5f; +} +@media print { + .govuk-caption-m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-caption-m { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-caption-m { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-body-lead, .govuk-body-l { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin-top: 0; + margin-bottom: 20px; +} +@media print { + .govuk-body-lead, .govuk-body-l { + color: #000000; + } +} +@media print { + .govuk-body-lead, .govuk-body-l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-body-lead, .govuk-body-l { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-body-lead, .govuk-body-l { + font-size: 18pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-body-lead, .govuk-body-l { + margin-bottom: 30px; + } +} + +p, .govuk-body, .govuk-body-m { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + p, .govuk-body, .govuk-body-m { + color: #000000; + } +} +@media print { + p, .govuk-body, .govuk-body-m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + p, .govuk-body, .govuk-body-m { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + p, .govuk-body, .govuk-body-m { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + p, .govuk-body, .govuk-body-m { + margin-bottom: 20px; + } +} + +.govuk-body-s { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + .govuk-body-s { + color: #000000; + } +} +@media print { + .govuk-body-s { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-body-s { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-body-s { + font-size: 14pt; + line-height: 1.2; + } +} +@media (min-width: 40.0625em) { + .govuk-body-s { + margin-bottom: 20px; + } +} + +.govuk-body-xs { + color: #0b0c0c; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 12px; + font-size: 0.75rem; + line-height: 1.25; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + .govuk-body-xs { + color: #000000; + } +} +@media print { + .govuk-body-xs { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-body-xs { + font-size: 14px; + font-size: 0.875rem; + line-height: 1.4285714286; + } +} +@media print { + .govuk-body-xs { + font-size: 12pt; + line-height: 1.2; + } +} +@media (min-width: 40.0625em) { + .govuk-body-xs { + margin-bottom: 20px; + } +} + +.govuk-body-l + .govuk-heading-l, .govuk-body-lead + .govuk-heading-l { + padding-top: 5px; +} +@media (min-width: 40.0625em) { + .govuk-body-l + .govuk-heading-l, .govuk-body-lead + .govuk-heading-l { + padding-top: 10px; + } +} + +p + .govuk-heading-l, .govuk-body-m + .govuk-heading-l, .govuk-body + .govuk-heading-l, +.govuk-body-s + .govuk-heading-l, +.govuk-list + .govuk-heading-l { + padding-top: 15px; +} +@media (min-width: 40.0625em) { + p + .govuk-heading-l, .govuk-body-m + .govuk-heading-l, .govuk-body + .govuk-heading-l, + .govuk-body-s + .govuk-heading-l, + .govuk-list + .govuk-heading-l { + padding-top: 20px; + } +} + +p + .govuk-heading-m, .govuk-body-m + .govuk-heading-m, .govuk-body + .govuk-heading-m, +.govuk-body-s + .govuk-heading-m, +.govuk-list + .govuk-heading-m, +p + .govuk-heading-s, +.govuk-body-m + .govuk-heading-s, +.govuk-body + .govuk-heading-s, +.govuk-body-s + .govuk-heading-s, +.govuk-list + .govuk-heading-s { + padding-top: 5px; +} +@media (min-width: 40.0625em) { + p + .govuk-heading-m, .govuk-body-m + .govuk-heading-m, .govuk-body + .govuk-heading-m, + .govuk-body-s + .govuk-heading-m, + .govuk-list + .govuk-heading-m, + p + .govuk-heading-s, + .govuk-body-m + .govuk-heading-s, + .govuk-body + .govuk-heading-s, + .govuk-body-s + .govuk-heading-s, + .govuk-list + .govuk-heading-s { + padding-top: 10px; + } +} + +.govuk-section-break { + margin: 0; + border: 0; +} + +.govuk-section-break--xl { + margin-top: 30px; + margin-bottom: 30px; +} +@media (min-width: 40.0625em) { + .govuk-section-break--xl { + margin-top: 50px; + } +} +@media (min-width: 40.0625em) { + .govuk-section-break--xl { + margin-bottom: 50px; + } +} + +.govuk-section-break--l { + margin-top: 20px; + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-section-break--l { + margin-top: 30px; + } +} +@media (min-width: 40.0625em) { + .govuk-section-break--l { + margin-bottom: 30px; + } +} + +.govuk-section-break--m { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 40.0625em) { + .govuk-section-break--m { + margin-top: 20px; + } +} +@media (min-width: 40.0625em) { + .govuk-section-break--m { + margin-bottom: 20px; + } +} + +.govuk-section-break--visible { + border-bottom: 1px solid #b1b4b6; +} + +.govuk-button-group { + margin-bottom: 5px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; +} +@media (min-width: 40.0625em) { + .govuk-button-group { + margin-bottom: 15px; + } +} +.govuk-button-group .govuk-link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.1875; + display: inline-block; + max-width: 100%; + margin-top: 5px; + margin-bottom: 20px; + text-align: center; +} +@media print { + .govuk-button-group .govuk-link { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-button-group .govuk-link { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1; + } +} +@media print { + .govuk-button-group .govuk-link { + font-size: 14pt; + line-height: 19px; + } +} +.govuk-button-group .govuk-button { + margin-bottom: 17px; +} +@media (min-width: 40.0625em) { + .govuk-button-group { + margin-right: -15px; + -ms-flex-direction: row; + flex-direction: row; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: baseline; + align-items: baseline; + } + .govuk-button-group .govuk-button, + .govuk-button-group .govuk-link { + margin-right: 15px; + } + .govuk-button-group .govuk-link { + text-align: left; + } +} + +.govuk-form-group { + margin-bottom: 20px; +} +.govuk-form-group:after { + content: ""; + display: block; + clear: both; +} +@media (min-width: 40.0625em) { + .govuk-form-group { + margin-bottom: 30px; + } +} +.govuk-form-group .govuk-form-group:last-of-type { + margin-bottom: 0; +} + +.govuk-form-group--error { + padding-left: 15px; + border-left: 5px solid #d4351c; +} +.govuk-form-group--error .govuk-form-group { + padding: 0; + border: 0; +} + +.govuk-grid-row { + margin-right: -15px; + margin-left: -15px; +} +.govuk-grid-row:after { + content: ""; + display: block; + clear: both; +} + +.govuk-grid-column-one-quarter { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-one-quarter { + width: 25%; + float: left; + } +} + +.govuk-grid-column-one-third { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-one-third { + width: 33.3333333333%; + float: left; + } +} + +.govuk-grid-column-one-half { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-one-half { + width: 50%; + float: left; + } +} + +.govuk-grid-column-two-thirds { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-two-thirds { + width: 66.6666666667%; + float: left; + } +} + +.govuk-grid-column-three-quarters { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-three-quarters { + width: 75%; + float: left; + } +} + +.govuk-grid-column-full { + box-sizing: border-box; + width: 100%; + padding: 0 15px; +} +@media (min-width: 40.0625em) { + .govuk-grid-column-full { + width: 100%; + float: left; + } +} + +.govuk-grid-column-one-quarter-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-one-quarter-from-desktop { + width: 25%; + float: left; + } +} + +.govuk-grid-column-one-third-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-one-third-from-desktop { + width: 33.3333333333%; + float: left; + } +} + +.govuk-grid-column-one-half-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-one-half-from-desktop { + width: 50%; + float: left; + } +} + +.govuk-grid-column-two-thirds-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-two-thirds-from-desktop { + width: 66.6666666667%; + float: left; + } +} + +.govuk-grid-column-three-quarters-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-three-quarters-from-desktop { + width: 75%; + float: left; + } +} + +.govuk-grid-column-full-from-desktop { + box-sizing: border-box; + padding: 0 15px; +} +@media (min-width: 48.0625em) { + .govuk-grid-column-full-from-desktop { + width: 100%; + float: left; + } +} + +.govuk-main-wrapper { + display: block; + padding-top: 20px; + padding-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-main-wrapper { + padding-top: 40px; + padding-bottom: 40px; + } +} + +.govuk-main-wrapper--auto-spacing:first-child, +.govuk-main-wrapper--l { + padding-top: 30px; +} +@media (min-width: 40.0625em) { + .govuk-main-wrapper--auto-spacing:first-child, + .govuk-main-wrapper--l { + padding-top: 50px; + } +} + +.govuk-template { + background-color: #f3f2f1; + -webkit-text-size-adjust: 100%; + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; +} +@supports (position: -webkit-sticky) or (position: sticky) { + .govuk-template { + scroll-padding-top: 60px; + } + .govuk-template:not(:has(.govuk-exit-this-page)) { + scroll-padding-top: 0; + } +} +@media screen { + .govuk-template { + overflow-y: scroll; + } +} + +.govuk-template__body { + margin: 0; + background-color: #ffffff; +} + +.govuk-width-container { + max-width: 960px; + margin-right: 15px; + margin-left: 15px; +} +@supports (margin: max(calc(0px))) { + .govuk-width-container { + margin-right: max(15px, calc(15px + env(safe-area-inset-right))); + margin-left: max(15px, calc(15px + env(safe-area-inset-left))); + } +} +@media (min-width: 40.0625em) { + .govuk-width-container { + margin-right: 30px; + margin-left: 30px; + } + @supports (margin: max(calc(0px))) { + .govuk-width-container { + margin-right: max(30px, calc(15px + env(safe-area-inset-right))); + margin-left: max(30px, calc(15px + env(safe-area-inset-left))); + } + } +} +@media (min-width: 1020px) { + .govuk-width-container { + margin-right: auto; + margin-left: auto; + } + @supports (margin: max(calc(0px))) { + .govuk-width-container { + margin-right: auto; + margin-left: auto; + } + } +} + +.govuk-accordion { + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-accordion { + margin-bottom: 30px; + } +} + +.govuk-accordion__section { + padding-top: 15px; +} + +.govuk-accordion__section-heading { + margin-top: 0; + margin-bottom: 0; + padding-top: 15px; + padding-bottom: 15px; +} + +.govuk-accordion__section-button { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + color: #0b0c0c; + display: block; + margin-bottom: 0; + padding-top: 15px; +} +@media print { + .govuk-accordion__section-button { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-accordion__section-button { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-accordion__section-button { + font-size: 18pt; + line-height: 1.15; + } +} +@media print { + .govuk-accordion__section-button { + color: #000000; + } +} + +.govuk-accordion__section-content > :last-child { + margin-bottom: 0; +} + +.js-enabled .govuk-accordion { + border-bottom: 1px solid #b1b4b6; +} +.js-enabled .govuk-accordion__section { + padding-top: 0; +} +.js-enabled .govuk-accordion__section-content { + display: none; + padding-top: 15px; + padding-bottom: 30px; +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__section-content { + padding-bottom: 50px; + } +} +.js-enabled .govuk-accordion__section-content[hidden] { + padding-top: 0; + padding-bottom: 0; +} +@supports (content-visibility: hidden) { + .js-enabled .govuk-accordion__section-content[hidden] { + content-visibility: hidden; + display: inherit; + } +} +.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content { + display: block; +} +.js-enabled .govuk-accordion__show-all { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + position: relative; + z-index: 1; + margin-bottom: 9px; + padding: 5px 2px 5px 0; + border-width: 0; + color: #1d70b8; + background: none; + cursor: pointer; + -webkit-appearance: none; +} +@media print { + .js-enabled .govuk-accordion__show-all { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__show-all { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .js-enabled .govuk-accordion__show-all { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__show-all { + margin-bottom: 14px; + } +} +.js-enabled .govuk-accordion__show-all::-moz-focus-inner { + padding: 0; + border: 0; +} +.js-enabled .govuk-accordion__show-all:hover { + color: #0b0c0c; + background: #f3f2f1; + box-shadow: 0 -2px #f3f2f1, 0 4px #f3f2f1; +} +.js-enabled .govuk-accordion__show-all:hover .govuk-accordion__section-toggle-text { + color: #0b0c0c; +} +.js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron { + color: #0b0c0c; + background: #0b0c0c; +} +.js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron:after { + color: #f3f2f1; +} +.js-enabled .govuk-accordion__show-all:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron { + background: #0b0c0c; +} +.js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron:after { + color: #ffdd00; +} +.js-enabled .govuk-accordion__section-heading { + padding: 0; +} +.js-enabled .govuk-accordion-nav__chevron { + box-sizing: border-box; + display: inline-block; + position: relative; + width: 1.25rem; + height: 1.25rem; + border: 0.0625rem solid; + border-radius: 50%; + vertical-align: middle; +} +.js-enabled .govuk-accordion-nav__chevron:after { + content: ""; + box-sizing: border-box; + display: block; + position: absolute; + bottom: 0.3125rem; + left: 0.375rem; + width: 0.375rem; + height: 0.375rem; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); + border-top: 0.125rem solid; + border-right: 0.125rem solid; +} +.js-enabled .govuk-accordion-nav__chevron--down { + -webkit-transform: rotate(180deg); + -ms-transform: rotate(180deg); + transform: rotate(180deg); +} +.js-enabled .govuk-accordion__section-button { + width: 100%; + padding: 10px 0 0 0; + border: 0; + border-top: 1px solid #b1b4b6; + border-bottom: 10px solid transparent; + color: #0b0c0c; + background: none; + text-align: left; + cursor: pointer; + -webkit-appearance: none; +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__section-button { + padding-bottom: 10px; + } +} +.js-enabled .govuk-accordion__section-button:active { + color: #0b0c0c; + background: none; +} +.js-enabled .govuk-accordion__section-button:hover { + color: #0b0c0c; + background: #f3f2f1; +} +.js-enabled .govuk-accordion__section-button:hover .govuk-accordion__section-toggle-text { + color: #0b0c0c; +} +.js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron { + color: #0b0c0c; + background: #0b0c0c; +} +.js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron:after { + color: #f3f2f1; +} +.js-enabled .govuk-accordion__section-button:focus { + outline: 0; +} +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-heading-text-focus, +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-summary-focus, +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron { + color: #0b0c0c; + background: #0b0c0c; +} +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron:after { + color: #ffdd00; +} +.js-enabled .govuk-accordion__section-button::-moz-focus-inner { + padding: 0; + border: 0; +} +.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-button { + padding-bottom: 15px; + border-bottom: 0; +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-button { + padding-bottom: 20px; + } +} +.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { + padding-bottom: 3px; +} +@media (min-width: 48.0625em) { + .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { + padding-bottom: 2px; + } +} +.js-enabled .govuk-accordion__section-toggle, +.js-enabled .govuk-accordion__section-heading-text, +.js-enabled .govuk-accordion__section-summary { + display: block; + margin-bottom: 13px; +} +.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-heading-text-focus, +.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-summary-focus, +.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-toggle-focus, +.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-heading-text-focus, +.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-summary-focus, +.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-toggle-focus, +.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-heading-text-focus, +.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-summary-focus, +.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-toggle-focus { + display: inline; +} +.js-enabled .govuk-accordion__section-toggle { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + font-weight: 400; + color: #1d70b8; +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-accordion__section-toggle { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .js-enabled .govuk-accordion__section-toggle { + font-size: 14pt; + line-height: 1.15; + } +} +.js-enabled .govuk-accordion__show-all-text, +.js-enabled .govuk-accordion__section-toggle-text { + margin-left: 5px; + vertical-align: middle; +} +@media screen and (forced-colors: active) { + .js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron, + .js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron { + background-color: transparent; + } + .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-heading-text-focus, + .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-summary-focus, + .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-toggle-focus, + .js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron, + .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-heading-text-focus, + .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-summary-focus, + .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus, + .js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron { + background: transparent; + background-color: transparent; + } +} +@media (hover: none) { + .js-enabled .govuk-accordion__section-header:hover { + border-top-color: #b1b4b6; + box-shadow: inset 0 3px 0 0 #1d70b8; + } + .js-enabled .govuk-accordion__section-header:hover .govuk-accordion__section-button { + border-top-color: #b1b4b6; + } +} + +.govuk-back-link { + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + display: inline-block; + position: relative; + margin-top: 15px; + margin-bottom: 15px; + padding-left: 0.875em; +} +@media (min-width: 40.0625em) { + .govuk-back-link { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-back-link { + font-size: 14pt; + line-height: 1.2; + } +} +@media print { + .govuk-back-link { + font-family: sans-serif; + } +} +.govuk-back-link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-back-link:link, .govuk-back-link:visited { + color: #0b0c0c; +} +@media print { + .govuk-back-link:link, .govuk-back-link:visited { + color: #000000; + } +} +.govuk-back-link:hover { + color: rgba(11, 12, 12, 0.99); +} +.govuk-back-link:active, .govuk-back-link:focus { + color: #0b0c0c; +} +@media print { + .govuk-back-link:active, .govuk-back-link:focus { + color: #000000; + } +} + +.govuk-back-link:before { + content: ""; + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0.1875em; + width: 0.4375em; + height: 0.4375em; + margin: auto 0; + -webkit-transform: rotate(225deg); + -ms-transform: rotate(225deg); + transform: rotate(225deg); + border: solid; + border-width: 1px 1px 0 0; + border-color: #505a5f; +} +@supports (border-width: max(0px)) { + .govuk-back-link:before { + border-width: max(1px, 0.0625em) max(1px, 0.0625em) 0 0; + font-size: max(16px, 1em); + } +} + +.govuk-back-link:focus:before { + border-color: #0b0c0c; +} + +.govuk-back-link:after { + content: ""; + position: absolute; + top: -14px; + right: 0; + bottom: -14px; + left: 0; +} + +.govuk-back-link--inverse:link, .govuk-back-link--inverse:visited { + color: #ffffff; +} +.govuk-back-link--inverse:hover, .govuk-back-link--inverse:active { + color: rgba(255, 255, 255, 0.99); +} +.govuk-back-link--inverse:focus { + color: #0b0c0c; +} +.govuk-back-link--inverse:before { + border-color: currentcolor; +} + +.govuk-breadcrumbs { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + color: #0b0c0c; + margin-top: 15px; + margin-bottom: 10px; +} +@media print { + .govuk-breadcrumbs { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-breadcrumbs { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-breadcrumbs { + font-size: 14pt; + line-height: 1.2; + } +} +@media print { + .govuk-breadcrumbs { + color: #000000; + } +} + +.govuk-breadcrumbs__list { + margin: 0; + padding: 0; + list-style-type: none; +} +.govuk-breadcrumbs__list:after { + content: ""; + display: block; + clear: both; +} + +.govuk-breadcrumbs__list-item { + display: inline-block; + position: relative; + margin-bottom: 5px; + margin-left: 0.625em; + padding-left: 0.9784375em; + float: left; +} +.govuk-breadcrumbs__list-item:before { + content: ""; + display: block; + position: absolute; + top: 0; + bottom: 0; + left: -0.206875em; + width: 0.4375em; + height: 0.4375em; + margin: auto 0; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + border: solid; + border-width: 1px 1px 0 0; + border-color: #505a5f; +} +@supports (border-width: max(0px)) { + .govuk-breadcrumbs__list-item:before { + border-width: max(1px, 0.0625em) max(1px, 0.0625em) 0 0; + font-size: max(16px, 1em); + } +} +.govuk-breadcrumbs__list-item:first-child { + margin-left: 0; + padding-left: 0; +} +.govuk-breadcrumbs__list-item:first-child:before { + content: none; + display: none; +} + +.govuk-breadcrumbs__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; +} +@media print { + .govuk-breadcrumbs__link { + font-family: sans-serif; + } +} +.govuk-breadcrumbs__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-breadcrumbs__link:link, .govuk-breadcrumbs__link:visited { + color: #0b0c0c; +} +@media print { + .govuk-breadcrumbs__link:link, .govuk-breadcrumbs__link:visited { + color: #000000; + } +} +.govuk-breadcrumbs__link:hover { + color: rgba(11, 12, 12, 0.99); +} +.govuk-breadcrumbs__link:active, .govuk-breadcrumbs__link:focus { + color: #0b0c0c; +} +@media print { + .govuk-breadcrumbs__link:active, .govuk-breadcrumbs__link:focus { + color: #000000; + } +} + +@media (max-width: 40.0525em) { + .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item { + display: none; + } + .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:first-child, .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:last-child { + display: inline-block; + } + .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:before { + top: 0.375em; + margin: 0; + } + .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list { + display: -ms-flexbox; + display: flex; + } +} + +.govuk-breadcrumbs--inverse { + color: #ffffff; +} +.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:link, .govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:visited { + color: #ffffff; +} +.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:hover, .govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:active { + color: rgba(255, 255, 255, 0.99); +} +.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:focus { + color: #0b0c0c; +} +.govuk-breadcrumbs--inverse .govuk-breadcrumbs__list-item:before { + border-color: currentcolor; +} + +.govuk-button { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.1875; + box-sizing: border-box; + display: inline-block; + position: relative; + width: 100%; + margin-top: 0; + margin-right: 0; + margin-left: 0; + margin-bottom: 22px; + padding: 8px 10px 7px; + border: 2px solid transparent; + border-radius: 0; + color: #ffffff; + background-color: #00703c; + box-shadow: 0 2px 0 #002d18; + text-align: center; + vertical-align: top; + cursor: pointer; + -webkit-appearance: none; +} +@media print { + .govuk-button { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-button { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1; + } +} +@media print { + .govuk-button { + font-size: 14pt; + line-height: 19px; + } +} +@media (min-width: 40.0625em) { + .govuk-button { + margin-bottom: 32px; + } +} +@media (min-width: 40.0625em) { + .govuk-button { + width: auto; + } +} +.govuk-button:link, .govuk-button:visited, .govuk-button:active, .govuk-button:hover { + color: #ffffff; + text-decoration: none; +} +.govuk-button::-moz-focus-inner { + padding: 0; + border: 0; +} +.govuk-button:hover { + background-color: #005a30; +} +.govuk-button:active { + top: 2px; +} +.govuk-button:focus { + border-color: #ffdd00; + outline: 3px solid transparent; + box-shadow: inset 0 0 0 1px #ffdd00; +} +.govuk-button:focus:not(:active):not(:hover) { + border-color: #ffdd00; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 2px 0 #0b0c0c; +} +.govuk-button:before { + content: ""; + display: block; + position: absolute; + top: -2px; + right: -2px; + bottom: -4px; + left: -2px; + background: transparent; +} +.govuk-button:active:before { + top: -4px; +} + +.govuk-button--disabled, +.govuk-button[disabled=disabled], +.govuk-button[disabled] { + opacity: 0.5; +} +.govuk-button--disabled:hover, +.govuk-button[disabled=disabled]:hover, +.govuk-button[disabled]:hover { + background-color: #00703c; + cursor: not-allowed; +} +.govuk-button--disabled:active, +.govuk-button[disabled=disabled]:active, +.govuk-button[disabled]:active { + top: 0; + box-shadow: 0 2px 0 #002d18; +} + +.govuk-button--secondary { + background-color: #f3f2f1; + box-shadow: 0 2px 0 #929191; +} +.govuk-button--secondary, .govuk-button--secondary:link, .govuk-button--secondary:visited, .govuk-button--secondary:active, .govuk-button--secondary:hover { + color: #0b0c0c; +} +.govuk-button--secondary:hover { + background-color: #dbdad9; +} +.govuk-button--secondary:hover[disabled] { + background-color: #f3f2f1; +} + +.govuk-button--warning { + background-color: #d4351c; + box-shadow: 0 2px 0 #55150b; +} +.govuk-button--warning, .govuk-button--warning:link, .govuk-button--warning:visited, .govuk-button--warning:active, .govuk-button--warning:hover { + color: #ffffff; +} +.govuk-button--warning:hover { + background-color: #aa2a16; +} +.govuk-button--warning:hover[disabled] { + background-color: #d4351c; +} + +.govuk-button--inverse { + background-color: #ffffff; + box-shadow: 0 2px 0 #144e81; +} +.govuk-button--inverse, .govuk-button--inverse:link, .govuk-button--inverse:visited, .govuk-button--inverse:active, .govuk-button--inverse:hover { + color: #1d70b8; +} +.govuk-button--inverse:hover { + background-color: #e8f1f8; +} +.govuk-button--inverse:hover[disabled] { + background-color: #ffffff; +} + +.govuk-button--start { + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1; + display: -ms-inline-flexbox; + display: inline-flex; + min-height: auto; + -ms-flex-pack: center; + justify-content: center; +} +@media (min-width: 40.0625em) { + .govuk-button--start { + font-size: 24px; + font-size: 1.5rem; + line-height: 1; + } +} +@media print { + .govuk-button--start { + font-size: 18pt; + line-height: 1; + } +} + +.govuk-button__start-icon { + margin-left: 5px; + vertical-align: middle; + -ms-flex-negative: 0; + flex-shrink: 0; + -ms-flex-item-align: center; + align-self: center; + forced-color-adjust: auto; +} +@media (min-width: 48.0625em) { + .govuk-button__start-icon { + margin-left: 10px; + } +} + +.govuk-error-message { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: block; + margin-top: 0; + margin-bottom: 15px; + clear: both; + color: #d4351c; +} +@media print { + .govuk-error-message { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-error-message { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-error-message { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-fieldset { + min-width: 0; + margin: 0; + padding: 0; + border: 0; +} +.govuk-fieldset:after { + content: ""; + display: block; + clear: both; +} + +@supports not (caret-color: auto) { + .govuk-fieldset, + x:-moz-any-link { + display: table-cell; + } +} +.govuk-fieldset__legend { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + box-sizing: border-box; + display: table; + max-width: 100%; + margin-bottom: 10px; + padding: 0; + white-space: normal; +} +@media print { + .govuk-fieldset__legend { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-fieldset__legend { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-fieldset__legend { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-fieldset__legend { + color: #000000; + } +} + +.govuk-fieldset__legend--xl { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; + margin-bottom: 15px; +} +@media print { + .govuk-fieldset__legend--xl { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-fieldset__legend--xl { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .govuk-fieldset__legend--xl { + font-size: 32pt; + line-height: 1.15; + } +} + +.govuk-fieldset__legend--l { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; + margin-bottom: 15px; +} +@media print { + .govuk-fieldset__legend--l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-fieldset__legend--l { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-fieldset__legend--l { + font-size: 24pt; + line-height: 1.05; + } +} + +.govuk-fieldset__legend--m { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin-bottom: 15px; +} +@media print { + .govuk-fieldset__legend--m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-fieldset__legend--m { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-fieldset__legend--m { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-fieldset__legend--s { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; +} +@media print { + .govuk-fieldset__legend--s { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-fieldset__legend--s { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-fieldset__legend--s { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-fieldset__heading { + margin: 0; + font-size: inherit; + font-weight: inherit; +} + +.govuk-hint { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin-bottom: 15px; + color: #505a5f; +} +@media print { + .govuk-hint { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-hint { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-hint { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl) + .govuk-hint { + margin-bottom: 10px; +} + +.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl) + .govuk-hint { + margin-bottom: 10px; +} + +.govuk-fieldset__legend + .govuk-hint { + margin-top: -5px; +} + +.govuk-label { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + display: block; + margin-bottom: 5px; +} +@media print { + .govuk-label { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-label { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-label { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-label { + color: #000000; + } +} + +.govuk-label--xl { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; + margin-bottom: 15px; +} +@media print { + .govuk-label--xl { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-label--xl { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .govuk-label--xl { + font-size: 32pt; + line-height: 1.15; + } +} + +.govuk-label--l { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; + margin-bottom: 15px; +} +@media print { + .govuk-label--l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-label--l { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-label--l { + font-size: 24pt; + line-height: 1.05; + } +} + +.govuk-label--m { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin-bottom: 10px; +} +@media print { + .govuk-label--m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-label--m { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-label--m { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-label--s { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; +} +@media print { + .govuk-label--s { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-label--s { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-label--s { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-label-wrapper { + margin: 0; +} + +.govuk-checkboxes__item { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: block; + position: relative; + min-height: 40px; + margin-bottom: 10px; + padding-left: 40px; + clear: left; +} +@media print { + .govuk-checkboxes__item { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-checkboxes__item { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-checkboxes__item { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-checkboxes__item:last-child, +.govuk-checkboxes__item:last-of-type { + margin-bottom: 0; +} + +.govuk-checkboxes__input { + cursor: pointer; + position: absolute; + z-index: 1; + top: -2px; + left: -2px; + width: 44px; + height: 44px; + margin: 0; + opacity: 0; +} + +.govuk-checkboxes__label { + display: inline-block; + margin-bottom: 0; + padding: 8px 15px 5px; + cursor: pointer; + -ms-touch-action: manipulation; + touch-action: manipulation; +} + +.govuk-checkboxes__label:before { + content: ""; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + width: 40px; + height: 40px; + border: 2px solid currentcolor; + background: transparent; +} + +.govuk-checkboxes__label:after { + content: ""; + box-sizing: border-box; + position: absolute; + top: 11px; + left: 9px; + width: 23px; + height: 12px; + -webkit-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + transform: rotate(-45deg); + border: solid; + border-width: 0 0 5px 5px; + border-top-color: transparent; + opacity: 0; + background: transparent; +} + +.govuk-checkboxes__hint { + display: block; + padding-right: 15px; + padding-left: 15px; +} + +.govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { + border-width: 4px; + outline: 3px solid transparent; + outline-offset: 1px; + box-shadow: 0 0 0 3px #ffdd00; +} +@media screen and (forced-colors: active), (-ms-high-contrast: active) { + .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { + outline-color: Highlight; + } +} + +.govuk-checkboxes__input:checked + .govuk-checkboxes__label:after { + opacity: 1; +} + +.govuk-checkboxes__input:disabled, +.govuk-checkboxes__input:disabled + .govuk-checkboxes__label { + cursor: not-allowed; +} + +.govuk-checkboxes__input:disabled + .govuk-checkboxes__label, +.govuk-checkboxes__input:disabled ~ .govuk-hint { + opacity: 0.5; +} + +.govuk-checkboxes__divider { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + width: 40px; + margin-bottom: 10px; + text-align: center; +} +@media print { + .govuk-checkboxes__divider { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-checkboxes__divider { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-checkboxes__divider { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-checkboxes__divider { + color: #000000; + } +} + +.govuk-checkboxes__conditional { + margin-bottom: 15px; + margin-left: 18px; + padding-left: 33px; + border-left: 4px solid #b1b4b6; +} +@media (min-width: 40.0625em) { + .govuk-checkboxes__conditional { + margin-bottom: 20px; + } +} +.js-enabled .govuk-checkboxes__conditional--hidden { + display: none; +} +.govuk-checkboxes__conditional > :last-child { + margin-bottom: 0; +} + +.govuk-checkboxes--small .govuk-checkboxes__item { + min-height: 0; + margin-bottom: 0; + padding-left: 34px; + float: left; +} +.govuk-checkboxes--small .govuk-checkboxes__item:after { + content: ""; + display: block; + clear: both; +} +.govuk-checkboxes--small .govuk-checkboxes__input { + left: -10px; +} +.govuk-checkboxes--small .govuk-checkboxes__label { + margin-top: -2px; + padding: 13px 15px 13px 1px; + float: left; +} +@media (min-width: 40.0625em) { + .govuk-checkboxes--small .govuk-checkboxes__label { + padding: 11px 15px 10px 1px; + } +} +.govuk-checkboxes--small .govuk-checkboxes__label:before { + top: 8px; + width: 24px; + height: 24px; +} +.govuk-checkboxes--small .govuk-checkboxes__label:after { + top: 15px; + left: 6px; + width: 12px; + height: 6.5px; + border-width: 0 0 3px 3px; +} +.govuk-checkboxes--small .govuk-checkboxes__hint { + padding: 0; + clear: both; +} +.govuk-checkboxes--small .govuk-checkboxes__conditional { + margin-left: 10px; + padding-left: 20px; + clear: both; +} +.govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label:before { + box-shadow: 0 0 0 10px #b1b4b6; +} +.govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { + box-shadow: 0 0 0 3px #ffdd00, 0 0 0 10px #b1b4b6; +} +@media (hover: none), (pointer: coarse) { + .govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label:before { + box-shadow: initial; + } + .govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { + box-shadow: 0 0 0 3px #ffdd00; + } +} + +.govuk-textarea { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + display: block; + width: 100%; + min-height: 40px; + margin-bottom: 20px; + padding: 5px; + resize: vertical; + border: 2px solid #0b0c0c; + border-radius: 0; + -webkit-appearance: none; +} +@media print { + .govuk-textarea { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-textarea { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.25; + } +} +@media print { + .govuk-textarea { + font-size: 14pt; + line-height: 1.25; + } +} +@media (min-width: 40.0625em) { + .govuk-textarea { + margin-bottom: 30px; + } +} +.govuk-textarea:focus { + outline: 3px solid #ffdd00; + outline-offset: 0; + box-shadow: inset 0 0 0 2px; +} +.govuk-textarea:disabled { + opacity: 0.5; + color: inherit; + background-color: transparent; + cursor: not-allowed; +} + +.govuk-textarea--error { + border-color: #d4351c; +} +.govuk-textarea--error:focus { + border-color: #0b0c0c; +} + +.govuk-character-count { + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-character-count { + margin-bottom: 30px; + } +} +.govuk-character-count .govuk-form-group, +.govuk-character-count .govuk-textarea { + margin-bottom: 5px; +} + +.govuk-character-count__message { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-font-feature-settings: "tnum" 1; + font-feature-settings: "tnum" 1; + font-weight: 400; + margin-top: 0; + margin-bottom: 0; +} +@media print { + .govuk-character-count__message { + font-family: sans-serif; + } +} +@supports (font-variant-numeric: tabular-nums) { + .govuk-character-count__message { + -webkit-font-feature-settings: normal; + font-feature-settings: normal; + font-variant-numeric: tabular-nums; + } +} +.govuk-character-count__message:after { + content: "​"; +} + +.govuk-character-count__message--disabled { + visibility: hidden; +} + +.govuk-cookie-banner { + padding-top: 20px; + border-bottom: 10px solid transparent; + background-color: #f3f2f1; +} + +.govuk-cookie-banner[hidden] { + display: none; +} + +.govuk-cookie-banner__message { + margin-bottom: -10px; +} +.govuk-cookie-banner__message[hidden] { + display: none; +} +.govuk-cookie-banner__message:focus { + outline: none; +} + +.govuk-input { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + width: 100%; + height: 40px; + height: 2.5rem; + margin-top: 0; + padding: 5px; + border: 2px solid #0b0c0c; + border-radius: 0; + -webkit-appearance: none; + appearance: none; +} +@media print { + .govuk-input { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-input { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-input { + font-size: 14pt; + line-height: 1.15; + } +} +.govuk-input:focus { + outline: 3px solid #ffdd00; + outline-offset: 0; + box-shadow: inset 0 0 0 2px; +} +.govuk-input:disabled { + opacity: 0.5; + color: inherit; + background-color: transparent; + cursor: not-allowed; +} + +.govuk-input::-webkit-outer-spin-button, +.govuk-input::-webkit-inner-spin-button { + margin: 0; + -webkit-appearance: none; +} + +.govuk-input[type=number] { + -moz-appearance: textfield; +} + +.govuk-input--error { + border-color: #d4351c; +} +.govuk-input--error:focus { + border-color: #0b0c0c; +} + +.govuk-input--extra-letter-spacing { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-font-feature-settings: "tnum" 1; + font-feature-settings: "tnum" 1; + font-weight: 400; + letter-spacing: 0.05em; +} +@media print { + .govuk-input--extra-letter-spacing { + font-family: sans-serif; + } +} +@supports (font-variant-numeric: tabular-nums) { + .govuk-input--extra-letter-spacing { + -webkit-font-feature-settings: normal; + font-feature-settings: normal; + font-variant-numeric: tabular-nums; + } +} + +.govuk-input--width-30 { + max-width: 29.5em; +} + +.govuk-input--width-20 { + max-width: 20.5em; +} + +.govuk-input--width-10 { + max-width: 11.5em; +} + +.govuk-input--width-5 { + max-width: 5.5em; +} + +.govuk-input--width-4 { + max-width: 4.5em; +} + +.govuk-input--width-3 { + max-width: 3.75em; +} + +.govuk-input--width-2 { + max-width: 2.75em; +} + +.govuk-input__wrapper { + display: -ms-flexbox; + display: flex; +} +.govuk-input__wrapper .govuk-input { + -ms-flex: 0 1 auto; + flex: 0 1 auto; +} +.govuk-input__wrapper .govuk-input:focus { + z-index: 1; +} +@media (max-width: 19.99em) { + .govuk-input__wrapper { + display: block; + } + .govuk-input__wrapper .govuk-input { + max-width: 100%; + } +} + +.govuk-input__prefix, +.govuk-input__suffix { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + display: inline-block; + min-width: 40px; + min-width: 2.5rem; + height: 40px; + height: 2.5rem; + padding: 5px; + border: 2px solid #0b0c0c; + background-color: #f3f2f1; + text-align: center; + white-space: nowrap; + cursor: default; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} +@media print { + .govuk-input__prefix, + .govuk-input__suffix { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-input__prefix, + .govuk-input__suffix { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-input__prefix, + .govuk-input__suffix { + font-size: 14pt; + line-height: 1.15; + } +} +@media (max-width: 40.0525em) { + .govuk-input__prefix, + .govuk-input__suffix { + line-height: 1.6; + } +} +@media (max-width: 19.99em) { + .govuk-input__prefix, + .govuk-input__suffix { + display: block; + height: 100%; + white-space: normal; + } +} + +@media (max-width: 19.99em) { + .govuk-input__prefix { + border-bottom: 0; + } +} +@media (min-width: 20em) { + .govuk-input__prefix { + border-right: 0; + } +} + +@media (max-width: 19.99em) { + .govuk-input__suffix { + border-top: 0; + } +} +@media (min-width: 20em) { + .govuk-input__suffix { + border-left: 0; + } +} + +.govuk-date-input { + font-size: 0; +} +.govuk-date-input:after { + content: ""; + display: block; + clear: both; +} + +.govuk-date-input__item { + display: inline-block; + margin-right: 20px; + margin-bottom: 0; +} + +.govuk-date-input__label { + display: block; +} + +.govuk-date-input__input { + margin-bottom: 0; +} + +.govuk-details { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + margin-bottom: 20px; + display: block; +} +@media print { + .govuk-details { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-details { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-details { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-details { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-details { + margin-bottom: 30px; + } +} + +.govuk-details__summary { + display: inline-block; + position: relative; + margin-bottom: 5px; + padding-left: 25px; + color: #1d70b8; + cursor: pointer; +} +.govuk-details__summary:hover { + color: #003078; +} +.govuk-details__summary:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} + +.govuk-details__summary-text { + text-decoration: underline; +} + +.govuk-details__summary:focus .govuk-details__summary-text { + text-decoration: none; +} + +.govuk-details__summary::-webkit-details-marker { + display: none; +} + +.govuk-details__summary:before { + content: ""; + position: absolute; + top: -1px; + bottom: 0; + left: 0; + margin: auto; + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + -webkit-clip-path: polygon(0% 0%, 100% 50%, 0% 100%); + clip-path: polygon(0% 0%, 100% 50%, 0% 100%); + border-width: 7px 0 7px 12.124px; + border-left-color: inherit; +} +.govuk-details[open] > .govuk-details__summary:before { + display: block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + -webkit-clip-path: polygon(0% 0%, 50% 100%, 100% 0%); + clip-path: polygon(0% 0%, 50% 100%, 100% 0%); + border-width: 12.124px 7px 0 7px; + border-top-color: inherit; +} + +.govuk-details__text { + padding-top: 15px; + padding-bottom: 15px; + padding-left: 20px; + border-left: 5px solid #b1b4b6; +} + +.govuk-details__text p { + margin-top: 0; + margin-bottom: 20px; +} + +.govuk-details__text > :last-child { + margin-bottom: 0; +} + +.govuk-error-summary { + color: #0b0c0c; + padding: 15px; + margin-bottom: 30px; + border: 5px solid #d4351c; +} +@media print { + .govuk-error-summary { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-error-summary { + padding: 20px; + } +} +@media (min-width: 40.0625em) { + .govuk-error-summary { + margin-bottom: 50px; + } +} +.govuk-error-summary:focus { + outline: 3px solid #ffdd00; +} + +.govuk-error-summary__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin-top: 0; + margin-bottom: 15px; +} +@media print { + .govuk-error-summary__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-error-summary__title { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-error-summary__title { + font-size: 18pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-error-summary__title { + margin-bottom: 20px; + } +} + +.govuk-error-summary__body { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; +} +@media print { + .govuk-error-summary__body { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-error-summary__body { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-error-summary__body { + font-size: 14pt; + line-height: 1.15; + } +} +.govuk-error-summary__body p { + margin-top: 0; + margin-bottom: 15px; +} +@media (min-width: 40.0625em) { + .govuk-error-summary__body p { + margin-bottom: 20px; + } +} + +.govuk-error-summary__list { + margin-top: 0; + margin-bottom: 0; +} + +.govuk-error-summary__list a { + font-weight: 700; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; +} +@media print { + .govuk-error-summary__list a { + font-family: sans-serif; + } +} +.govuk-error-summary__list a:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-error-summary__list a:link, .govuk-error-summary__list a:visited { + color: #d4351c; +} +.govuk-error-summary__list a:hover { + color: #942514; +} +.govuk-error-summary__list a:active { + color: #d4351c; +} +.govuk-error-summary__list a:focus { + color: #0b0c0c; +} + +.govuk-exit-this-page { + margin-bottom: 30px; + position: -webkit-sticky; + position: sticky; + z-index: 1000; + top: 0; + left: 0; + width: 100%; +} +@media (min-width: 40.0625em) { + .govuk-exit-this-page { + margin-bottom: 50px; + } +} +@media (min-width: 40.0625em) { + .govuk-exit-this-page { + display: inline-block; + right: 0; + left: auto; + width: auto; + float: right; + } +} + +.govuk-exit-this-page__button { + margin-bottom: 0; +} + +.govuk-exit-this-page__indicator { + padding: 10px; + display: none; + padding-bottom: 0; + color: inherit; + line-height: 0; + text-align: center; + pointer-events: none; +} + +.govuk-exit-this-page__indicator--visible { + display: block; +} + +.govuk-exit-this-page__indicator-light { + box-sizing: border-box; + display: inline-block; + width: 0.75em; + height: 0.75em; + margin: 0 0.125em; + border-width: 2px; + border-style: solid; + border-radius: 50%; + border-color: currentcolor; +} + +.govuk-exit-this-page__indicator-light--on { + border-width: 0.375em; +} + +@media only print { + .govuk-exit-this-page { + display: none; + } +} +.govuk-exit-this-page-overlay { + position: fixed; + z-index: 9999; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #ffffff; +} + +.govuk-exit-this-page-hide-content * { + display: none !important; +} +.govuk-exit-this-page-hide-content .govuk-exit-this-page-overlay { + display: block !important; +} + +.govuk-file-upload { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + max-width: 100%; + margin-left: -5px; + padding: 5px; +} +@media print { + .govuk-file-upload { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-file-upload { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-file-upload { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-file-upload { + color: #000000; + } +} +.govuk-file-upload::-webkit-file-upload-button { + -webkit-appearance: button; + color: inherit; + font: inherit; +} +.govuk-file-upload:focus { + outline: 3px solid #ffdd00; + box-shadow: inset 0 0 0 4px #0b0c0c; +} +.govuk-file-upload:focus-within { + outline: 3px solid #ffdd00; + box-shadow: inset 0 0 0 4px #0b0c0c; +} +.govuk-file-upload:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.govuk-footer { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + padding-top: 25px; + padding-bottom: 15px; + border-top: 1px solid #b1b4b6; + color: #0b0c0c; + background: #f3f2f1; +} +@media print { + .govuk-footer { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-footer { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-footer { + font-size: 14pt; + line-height: 1.2; + } +} +@media (min-width: 40.0625em) { + .govuk-footer { + padding-top: 40px; + } +} +@media (min-width: 40.0625em) { + .govuk-footer { + padding-bottom: 25px; + } +} + +.govuk-footer__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; +} +@media print { + .govuk-footer__link { + font-family: sans-serif; + } +} +.govuk-footer__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-footer__link:link, .govuk-footer__link:visited { + color: #0b0c0c; +} +@media print { + .govuk-footer__link:link, .govuk-footer__link:visited { + color: #000000; + } +} +.govuk-footer__link:hover { + color: rgba(11, 12, 12, 0.99); +} +.govuk-footer__link:active, .govuk-footer__link:focus { + color: #0b0c0c; +} +@media print { + .govuk-footer__link:active, .govuk-footer__link:focus { + color: #000000; + } +} + +.govuk-footer__section-break { + margin: 0; + margin-bottom: 30px; + border: 0; + border-bottom: 1px solid #b1b4b6; +} +@media (min-width: 40.0625em) { + .govuk-footer__section-break { + margin-bottom: 50px; + } +} + +.govuk-footer__meta { + display: -ms-flexbox; + display: flex; + margin-right: -15px; + margin-left: -15px; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: end; + align-items: flex-end; + -ms-flex-pack: center; + justify-content: center; +} + +.govuk-footer__meta-item { + margin-right: 15px; + margin-bottom: 25px; + margin-left: 15px; +} + +.govuk-footer__meta-item--grow { + -ms-flex: 1; + flex: 1; +} +@media (max-width: 40.0525em) { + .govuk-footer__meta-item--grow { + -ms-flex-preferred-size: 320px; + flex-basis: 320px; + } +} + +.govuk-footer__licence-logo { + display: inline-block; + margin-right: 10px; + vertical-align: top; + forced-color-adjust: auto; +} +@media (max-width: 48.0525em) { + .govuk-footer__licence-logo { + margin-bottom: 15px; + } +} + +.govuk-footer__licence-description { + display: inline-block; +} + +.govuk-footer__copyright-logo { + display: inline-block; + min-width: 125px; + padding-top: 112px; + background-image: url("/assets/images/govuk-crest.png"); + background-repeat: no-repeat; + background-position: 50% 0%; + background-size: 125px 102px; + text-align: center; + white-space: nowrap; +} +@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { + .govuk-footer__copyright-logo { + background-image: url("/assets/images/govuk-crest-2x.png"); + } +} + +.govuk-footer__inline-list { + margin-top: 0; + margin-bottom: 15px; + padding: 0; +} + +.govuk-footer__meta-custom { + margin-bottom: 20px; +} + +.govuk-footer__inline-list-item { + display: inline-block; + margin-right: 15px; + margin-bottom: 5px; +} + +.govuk-footer__heading { + margin-bottom: 30px; + padding-bottom: 20px; + border-bottom: 1px solid #b1b4b6; +} +@media (max-width: 40.0525em) { + .govuk-footer__heading { + padding-bottom: 10px; + } +} + +.govuk-footer__navigation { + margin-right: -15px; + margin-left: -15px; +} +.govuk-footer__navigation:after { + content: ""; + display: block; + clear: both; +} + +.govuk-footer__section { + display: inline-block; + margin-bottom: 30px; + vertical-align: top; +} + +.govuk-footer__list { + margin: 0; + padding: 0; + list-style: none; + -webkit-column-gap: 30px; + column-gap: 30px; +} + +@media (min-width: 48.0625em) { + .govuk-footer__list--columns-2 { + -webkit-column-count: 2; + column-count: 2; + } + .govuk-footer__list--columns-3 { + -webkit-column-count: 3; + column-count: 3; + } +} +.govuk-footer__list-item { + margin-bottom: 15px; +} +@media (min-width: 40.0625em) { + .govuk-footer__list-item { + margin-bottom: 20px; + } +} + +.govuk-footer__list-item:last-child { + margin-bottom: 0; +} + +.govuk-header { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + border-bottom: 10px solid #ffffff; + color: #ffffff; + background: #0b0c0c; +} +@media print { + .govuk-header { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-header { + font-size: 14pt; + line-height: 1.2; + } +} + +.govuk-header__container--full-width { + padding: 0 15px; + border-color: #1d70b8; +} +.govuk-header__container--full-width .govuk-header__menu-button { + right: 15px; +} + +.govuk-header__container { + position: relative; + margin-bottom: -10px; + padding-top: 10px; + border-bottom: 10px solid #1d70b8; +} +.govuk-header__container:after { + content: ""; + display: block; + clear: both; +} + +.govuk-header__logotype { + display: inline-block; + margin-right: 5px; +} +@media (forced-colors: active) { + .govuk-header__logotype { + forced-color-adjust: none; + color: linktext; + } +} +.govuk-header__logotype:last-child { + margin-right: 0; +} + +.govuk-header__logotype-crown { + position: relative; + top: -1px; + margin-right: 1px; + fill: currentcolor; + vertical-align: top; +} + +.govuk-header__logotype-crown-fallback-image { + width: 36px; + height: 32px; + border: 0; + vertical-align: bottom; +} + +.govuk-header__product-name { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 18px; + font-size: 1.125rem; + line-height: 1; + display: inline-table; +} +@media print { + .govuk-header__product-name { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header__product-name { + font-size: 24px; + font-size: 1.5rem; + line-height: 1; + } +} +@media print { + .govuk-header__product-name { + font-size: 18pt; + line-height: 1; + } +} + +.govuk-header__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: none; +} +@media print { + .govuk-header__link { + font-family: sans-serif; + } +} +.govuk-header__link:link, .govuk-header__link:visited { + color: #ffffff; +} +.govuk-header__link:hover, .govuk-header__link:active { + color: rgba(255, 255, 255, 0.99); +} +.govuk-header__link:focus { + color: #0b0c0c; +} +.govuk-header__link:hover { + text-decoration: underline; + text-decoration-thickness: 3px; + text-underline-offset: 0.1578em; +} +.govuk-header__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} + +.govuk-header__link--homepage { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + display: inline-block; + margin-right: 10px; + font-size: 30px; + line-height: 1; +} +@media print { + .govuk-header__link--homepage { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header__link--homepage { + display: inline; + } + .govuk-header__link--homepage:focus { + box-shadow: 0 0 #ffdd00; + } +} +.govuk-header__link--homepage:link, .govuk-header__link--homepage:visited { + text-decoration: none; +} +.govuk-header__link--homepage:hover, .govuk-header__link--homepage:active { + margin-bottom: -3px; + border-bottom: 3px solid; +} +.govuk-header__link--homepage:focus { + margin-bottom: 0; + border-bottom: 0; +} + +.govuk-header__service-name, +.govuk-header__link--service-name { + display: inline-block; + margin-bottom: 10px; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; +} +@media print { + .govuk-header__service-name, + .govuk-header__link--service-name { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header__service-name, + .govuk-header__link--service-name { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-header__service-name, + .govuk-header__link--service-name { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-header__logo, +.govuk-header__content { + box-sizing: border-box; +} + +.govuk-header__logo { + margin-bottom: 10px; + padding-right: 50px; +} +@media (min-width: 48.0625em) { + .govuk-header__logo { + width: 33.33%; + padding-right: 15px; + float: left; + vertical-align: top; + } +} + +@media (min-width: 48.0625em) { + .govuk-header__content { + width: 66.66%; + padding-left: 15px; + float: left; + } +} + +.govuk-header__menu-button { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + display: none; + position: absolute; + top: 20px; + right: 0; + margin: 0; + padding: 0; + border: 0; + color: #ffffff; + background: none; + cursor: pointer; +} +@media print { + .govuk-header__menu-button { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header__menu-button { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-header__menu-button { + font-size: 14pt; + line-height: 1.2; + } +} +.govuk-header__menu-button:hover { + -webkit-text-decoration: solid underline 3px; + text-decoration: solid underline 3px; + text-underline-offset: 0.1578em; +} +.govuk-header__menu-button:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-header__menu-button:after { + display: inline-block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + -webkit-clip-path: polygon(0% 0%, 50% 100%, 100% 0%); + clip-path: polygon(0% 0%, 50% 100%, 100% 0%); + border-width: 8.66px 5px 0 5px; + border-top-color: inherit; + content: ""; + margin-left: 5px; +} +.govuk-header__menu-button[aria-expanded=true]:after { + display: inline-block; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + -webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%); + clip-path: polygon(50% 0%, 0% 100%, 100% 100%); + border-width: 0 5px 8.66px 5px; + border-bottom-color: inherit; +} +@media (min-width: 40.0625em) { + .govuk-header__menu-button { + top: 15px; + } +} +.js-enabled .govuk-header__menu-button { + display: block; +} +.govuk-header__menu-button[hidden], .js-enabled .govuk-header__menu-button[hidden] { + display: none; +} + +@media (min-width: 48.0625em) { + .govuk-header__navigation { + margin-bottom: 10px; + } +} + +.govuk-header__navigation-list { + margin: 0; + padding: 0; + list-style: none; +} +.govuk-header__navigation-list[hidden] { + display: none; +} + +@media (min-width: 48.0625em) { + .govuk-header__navigation--end { + margin: 0; + padding: 5px 0; + text-align: right; + } +} + +.govuk-header__navigation--no-service-name { + padding-top: 40px; +} + +.govuk-header__navigation-item { + padding: 10px 0; + border-bottom: 1px solid #2e3133; +} +@media (min-width: 48.0625em) { + .govuk-header__navigation-item { + display: inline-block; + margin-right: 15px; + padding: 5px 0; + border: 0; + } +} +.govuk-header__navigation-item a { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + white-space: nowrap; +} +@media print { + .govuk-header__navigation-item a { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-header__navigation-item a { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-header__navigation-item a { + font-size: 14pt; + line-height: 1.2; + } +} + +.govuk-header__navigation-item--active a:link, .govuk-header__navigation-item--active a:hover, .govuk-header__navigation-item--active a:visited { + color: #1d8feb; +} +@media print { + .govuk-header__navigation-item--active a { + color: #1d70b8; + } +} +.govuk-header__navigation-item--active a:focus { + color: #0b0c0c; +} + +.govuk-header__navigation-item:last-child { + margin-right: 0; + border-bottom: 0; +} + +@media print { + .govuk-header { + border-bottom-width: 0; + color: #0b0c0c; + background: transparent; + } + .govuk-header__logotype-crown-fallback-image { + display: none; + } + .govuk-header__link:link, .govuk-header__link:visited { + color: #0b0c0c; + } + .govuk-header__link:after { + display: none; + } +} +.govuk-inset-text { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + padding: 15px; + margin-top: 20px; + margin-bottom: 20px; + clear: both; + border-left: 10px solid #b1b4b6; +} +@media print { + .govuk-inset-text { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-inset-text { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-inset-text { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-inset-text { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-inset-text { + margin-top: 30px; + } +} +@media (min-width: 40.0625em) { + .govuk-inset-text { + margin-bottom: 30px; + } +} +.govuk-inset-text > :first-child { + margin-top: 0; +} +.govuk-inset-text > :only-child, +.govuk-inset-text > :last-child { + margin-bottom: 0; +} + +.govuk-notification-banner { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin-bottom: 30px; + border: 5px solid #1d70b8; + background-color: #1d70b8; +} +@media print { + .govuk-notification-banner { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-notification-banner { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-notification-banner { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-notification-banner { + margin-bottom: 50px; + } +} +.govuk-notification-banner:focus { + outline: 3px solid #ffdd00; +} + +.govuk-notification-banner__header { + padding: 2px 15px 5px; + border-bottom: 1px solid transparent; +} +@media (min-width: 40.0625em) { + .govuk-notification-banner__header { + padding: 2px 20px 5px; + } +} + +.govuk-notification-banner__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin: 0; + padding: 0; + color: #ffffff; +} +@media print { + .govuk-notification-banner__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-notification-banner__title { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-notification-banner__title { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-notification-banner__content { + color: #0b0c0c; + padding: 15px; + background-color: #ffffff; +} +@media print { + .govuk-notification-banner__content { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-notification-banner__content { + padding: 20px; + } +} +.govuk-notification-banner__content > * { + box-sizing: border-box; + max-width: 605px; +} +.govuk-notification-banner__content > :last-child { + margin-bottom: 0; +} + +.govuk-notification-banner__heading { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin: 0 0 15px 0; + padding: 0; +} +@media print { + .govuk-notification-banner__heading { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-notification-banner__heading { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-notification-banner__heading { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-notification-banner__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; +} +@media print { + .govuk-notification-banner__link { + font-family: sans-serif; + } +} +.govuk-notification-banner__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-notification-banner__link:link { + color: #1d70b8; +} +.govuk-notification-banner__link:visited { + color: #1d70b8; +} +.govuk-notification-banner__link:hover { + color: #003078; +} +.govuk-notification-banner__link:active { + color: #0b0c0c; +} +.govuk-notification-banner__link:focus { + color: #0b0c0c; +} + +.govuk-notification-banner--success { + border-color: #00703c; + background-color: #00703c; +} +.govuk-notification-banner--success .govuk-notification-banner__link:link, .govuk-notification-banner--success .govuk-notification-banner__link:visited { + color: #00703c; +} +.govuk-notification-banner--success .govuk-notification-banner__link:hover { + color: #004e2a; +} +.govuk-notification-banner--success .govuk-notification-banner__link:active { + color: #00703c; +} +.govuk-notification-banner--success .govuk-notification-banner__link:focus { + color: #0b0c0c; +} + +.govuk-pagination { + margin-bottom: 20px; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: center; + align-items: center; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} +@media (min-width: 40.0625em) { + .govuk-pagination { + margin-bottom: 30px; + } +} +@media (min-width: 40.0625em) { + .govuk-pagination { + -ms-flex-direction: row; + flex-direction: row; + -ms-flex-align: start; + align-items: flex-start; + } +} + +.govuk-pagination__list { + margin: 0; + padding: 0; + list-style: none; +} + +.govuk-pagination__item, +.govuk-pagination__next, +.govuk-pagination__prev { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + position: relative; + min-width: 45px; + min-height: 45px; + padding: 10px 15px; + float: left; +} +@media print { + .govuk-pagination__item, + .govuk-pagination__next, + .govuk-pagination__prev { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-pagination__item, + .govuk-pagination__next, + .govuk-pagination__prev { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-pagination__item, + .govuk-pagination__next, + .govuk-pagination__prev { + font-size: 14pt; + line-height: 1.15; + } +} +.govuk-pagination__item:hover, +.govuk-pagination__next:hover, +.govuk-pagination__prev:hover { + background-color: #f3f2f1; +} + +.govuk-pagination__item { + display: none; + text-align: center; +} +@media (min-width: 40.0625em) { + .govuk-pagination__item { + display: block; + } +} + +.govuk-pagination__prev, +.govuk-pagination__next { + font-weight: 700; +} +.govuk-pagination__prev .govuk-pagination__link, +.govuk-pagination__next .govuk-pagination__link { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} + +.govuk-pagination__prev { + padding-left: 0; +} + +.govuk-pagination__next { + padding-right: 0; +} + +.govuk-pagination__item--current, +.govuk-pagination__item--ellipses, +.govuk-pagination__item:first-child, +.govuk-pagination__item:last-child { + display: block; +} + +.govuk-pagination__item--current { + font-weight: 700; + outline: 1px solid transparent; + background-color: #1d70b8; +} +.govuk-pagination__item--current:hover { + background-color: #1d70b8; +} +.govuk-pagination__item--current .govuk-pagination__link:link, .govuk-pagination__item--current .govuk-pagination__link:visited { + color: #ffffff; +} +.govuk-pagination__item--current .govuk-pagination__link:hover, .govuk-pagination__item--current .govuk-pagination__link:active { + color: rgba(255, 255, 255, 0.99); +} +.govuk-pagination__item--current .govuk-pagination__link:focus { + color: #0b0c0c; +} + +.govuk-pagination__item--ellipses { + font-weight: 700; + color: #505a5f; +} +.govuk-pagination__item--ellipses:hover { + background-color: transparent; +} + +.govuk-pagination__link { + display: block; + min-width: 15px; +} +@media screen { + .govuk-pagination__link:after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } +} +.govuk-pagination__link:hover .govuk-pagination__link-title--decorated, .govuk-pagination__link:active .govuk-pagination__link-title--decorated { + text-decoration: underline; +} +.govuk-pagination__link:focus .govuk-pagination__icon { + color: #0b0c0c; +} +.govuk-pagination__link:focus .govuk-pagination__link-label { + text-decoration: none; +} +.govuk-pagination__link:focus .govuk-pagination__link-title--decorated { + text-decoration: none; +} + +.govuk-pagination__link-label { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + text-decoration: underline; + display: inline-block; + padding-left: 30px; +} +@media print { + .govuk-pagination__link-label { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-pagination__link-label { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-pagination__link-label { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-pagination__icon { + width: 0.9375rem; + height: 0.8125rem; + color: #505a5f; + fill: currentcolor; + forced-color-adjust: auto; +} + +.govuk-pagination__icon--prev { + margin-right: 15px; +} + +.govuk-pagination__icon--next { + margin-left: 15px; +} + +.govuk-pagination--block { + display: block; +} +.govuk-pagination--block .govuk-pagination__item { + padding: 15px; + float: none; +} +.govuk-pagination--block .govuk-pagination__next, +.govuk-pagination--block .govuk-pagination__prev { + padding-left: 0; + float: none; +} +.govuk-pagination--block .govuk-pagination__next { + padding-right: 15px; +} +.govuk-pagination--block .govuk-pagination__next .govuk-pagination__icon { + margin-left: 0; +} +.govuk-pagination--block .govuk-pagination__prev + .govuk-pagination__next { + border-top: 1px solid #b1b4b6; +} +.govuk-pagination--block .govuk-pagination__link, +.govuk-pagination--block .govuk-pagination__link-title { + display: inline; +} +.govuk-pagination--block .govuk-pagination__link-title:after { + content: ""; + display: block; +} +.govuk-pagination--block .govuk-pagination__link { + text-align: left; +} +.govuk-pagination--block .govuk-pagination__link:focus .govuk-pagination__link-label { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-pagination--block .govuk-pagination__link:not(:focus) { + text-decoration: none; +} +.govuk-pagination--block .govuk-pagination__icon { + margin-right: 10px; +} + +.govuk-panel { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + margin-bottom: 15px; + padding: 35px; + border: 5px solid transparent; + text-align: center; +} +@media print { + .govuk-panel { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-panel { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-panel { + font-size: 14pt; + line-height: 1.15; + } +} +@media (max-width: 40.0525em) { + .govuk-panel { + padding: 10px; + overflow-wrap: break-word; + word-wrap: break-word; + } +} + +.govuk-panel--confirmation { + color: #ffffff; + background: #00703c; +} +@media print { + .govuk-panel--confirmation { + border-color: currentcolor; + color: #000000; + background: none; + } +} + +.govuk-panel__title { + margin-top: 0; + margin-bottom: 30px; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; +} +@media print { + .govuk-panel__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-panel__title { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .govuk-panel__title { + font-size: 32pt; + line-height: 1.15; + } +} + +.govuk-panel__title:last-child { + margin-bottom: 0; +} + +.govuk-panel__body { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; +} +@media print { + .govuk-panel__body { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-panel__body { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-panel__body { + font-size: 24pt; + line-height: 1.05; + } +} + +.govuk-tag { + display: inline-block; + outline: 2px solid transparent; + outline-offset: -2px; + color: #ffffff; + background-color: #1d70b8; + letter-spacing: 1px; + text-decoration: none; + text-transform: uppercase; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 14px; + font-size: 0.875rem; + line-height: 1; + padding-top: 5px; + padding-right: 8px; + padding-bottom: 4px; + padding-left: 8px; +} +@media print { + .govuk-tag { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-tag { + font-size: 16px; + font-size: 1rem; + line-height: 1; + } +} +@media print { + .govuk-tag { + font-size: 14pt; + line-height: 1; + } +} + +.govuk-tag--grey { + color: #383f43; + background: #eeefef; +} + +.govuk-tag--purple { + color: #3d2375; + background: #dbd5e9; +} + +.govuk-tag--turquoise { + color: #10403c; + background: #bfe3e0; +} + +.govuk-tag--blue { + color: #144e81; + background: #d2e2f1; +} + +.govuk-tag--yellow { + color: #594d00; + background: #fff7bf; +} + +.govuk-tag--orange { + color: #6e3619; + background: #fcd6c3; +} + +.govuk-tag--red { + color: #942514; + background: #f6d7d2; +} + +.govuk-tag--pink { + color: #80224d; + background: #f7d7e6; +} + +.govuk-tag--green { + color: #005a30; + background: #cce2d8; +} + +.govuk-phase-banner { + padding-top: 10px; + padding-bottom: 10px; + border-bottom: 1px solid #b1b4b6; +} + +.govuk-phase-banner__content { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + color: #0b0c0c; + display: table; + margin: 0; +} +@media print { + .govuk-phase-banner__content { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-phase-banner__content { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-phase-banner__content { + font-size: 14pt; + line-height: 1.2; + } +} +@media print { + .govuk-phase-banner__content { + color: #000000; + } +} + +.govuk-phase-banner__content__tag { + margin-right: 10px; +} + +.govuk-phase-banner__text { + display: table-cell; + vertical-align: middle; +} + +.govuk-tabs { + margin-top: 5px; + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-tabs { + margin-bottom: 30px; + } +} + +.govuk-tabs__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + margin-bottom: 10px; +} +@media print { + .govuk-tabs__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-tabs__title { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-tabs__title { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-tabs__title { + color: #000000; + } +} + +.govuk-tabs__list { + margin: 0; + padding: 0; + list-style: none; + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .govuk-tabs__list { + margin-bottom: 30px; + } +} + +.govuk-tabs__list-item { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin-left: 25px; +} +@media print { + .govuk-tabs__list-item { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-tabs__list-item { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-tabs__list-item { + font-size: 14pt; + line-height: 1.15; + } +} +.govuk-tabs__list-item:before { + color: #0b0c0c; + content: "—"; + margin-left: -25px; + padding-right: 5px; +} +@media print { + .govuk-tabs__list-item:before { + color: #000000; + } +} + +.govuk-tabs__tab { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + display: inline-block; + margin-bottom: 10px; +} +@media print { + .govuk-tabs__tab { + font-family: sans-serif; + } +} +.govuk-tabs__tab:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.govuk-tabs__tab:link { + color: #1d70b8; +} +.govuk-tabs__tab:visited { + color: #4c2c92; +} +.govuk-tabs__tab:hover { + color: #003078; +} +.govuk-tabs__tab:active { + color: #0b0c0c; +} +.govuk-tabs__tab:focus { + color: #0b0c0c; +} + +.govuk-tabs__panel { + margin-bottom: 30px; +} +@media (min-width: 40.0625em) { + .govuk-tabs__panel { + margin-bottom: 50px; + } +} + +@media (min-width: 40.0625em) { + .js-enabled .govuk-tabs__list { + margin-bottom: 0; + border-bottom: 1px solid #b1b4b6; + } + .js-enabled .govuk-tabs__list:after { + content: ""; + display: block; + clear: both; + } + .js-enabled .govuk-tabs__title { + display: none; + } + .js-enabled .govuk-tabs__list-item { + position: relative; + margin-right: 5px; + margin-bottom: 0; + margin-left: 0; + padding: 10px 20px; + float: left; + background-color: #f3f2f1; + text-align: center; + } + .js-enabled .govuk-tabs__list-item:before { + content: none; + } + .js-enabled .govuk-tabs__list-item--selected { + position: relative; + margin-top: -5px; + margin-bottom: -1px; + padding-top: 14px; + padding-right: 19px; + padding-bottom: 16px; + padding-left: 19px; + border: 1px solid #b1b4b6; + border-bottom: 0; + background-color: #ffffff; + } + .js-enabled .govuk-tabs__list-item--selected .govuk-tabs__tab { + text-decoration: none; + } + .js-enabled .govuk-tabs__tab { + margin-bottom: 0; + } + .js-enabled .govuk-tabs__tab:link, .js-enabled .govuk-tabs__tab:visited { + color: #0b0c0c; + } +} +@media print and (min-width: 40.0625em) { + .js-enabled .govuk-tabs__tab:link, .js-enabled .govuk-tabs__tab:visited { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-tabs__tab:hover { + color: rgba(11, 12, 12, 0.99); + } + .js-enabled .govuk-tabs__tab:active, .js-enabled .govuk-tabs__tab:focus { + color: #0b0c0c; + } +} +@media print and (min-width: 40.0625em) { + .js-enabled .govuk-tabs__tab:active, .js-enabled .govuk-tabs__tab:focus { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .js-enabled .govuk-tabs__tab:after { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + .js-enabled .govuk-tabs__panel { + margin-bottom: 0; + padding: 30px 20px; + border: 1px solid #b1b4b6; + border-top: 0; + } + .js-enabled .govuk-tabs__panel > :last-child { + margin-bottom: 0; + } + .js-enabled .govuk-tabs__panel--hidden { + display: none; + } +} + +.govuk-radios__item { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: block; + position: relative; + min-height: 40px; + margin-bottom: 10px; + padding-left: 40px; + clear: left; +} +@media print { + .govuk-radios__item { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-radios__item { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-radios__item { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-radios__item:last-child, +.govuk-radios__item:last-of-type { + margin-bottom: 0; +} + +.govuk-radios__input { + cursor: pointer; + position: absolute; + z-index: 1; + top: -2px; + left: -2px; + width: 44px; + height: 44px; + margin: 0; + opacity: 0; +} + +.govuk-radios__label { + display: inline-block; + margin-bottom: 0; + padding: 8px 15px 5px; + cursor: pointer; + -ms-touch-action: manipulation; + touch-action: manipulation; +} + +.govuk-radios__label:before { + content: ""; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + width: 40px; + height: 40px; + border: 2px solid currentcolor; + border-radius: 50%; + background: transparent; +} + +.govuk-radios__label:after { + content: ""; + position: absolute; + top: 10px; + left: 10px; + width: 0; + height: 0; + border: 10px solid currentcolor; + border-radius: 50%; + opacity: 0; + background: currentcolor; +} + +.govuk-radios__hint { + display: block; + padding-right: 15px; + padding-left: 15px; +} + +.govuk-radios__input:focus + .govuk-radios__label:before { + border-width: 4px; + outline: 3px solid transparent; + outline-offset: 1px; + box-shadow: 0 0 0 4px #ffdd00; +} +@media screen and (forced-colors: active), (-ms-high-contrast: active) { + .govuk-radios__input:focus + .govuk-radios__label:before { + outline-color: Highlight; + } +} + +.govuk-radios__input:checked + .govuk-radios__label:after { + opacity: 1; +} + +.govuk-radios__input:disabled, +.govuk-radios__input:disabled + .govuk-radios__label { + cursor: not-allowed; +} + +.govuk-radios__input:disabled + .govuk-radios__label, +.govuk-radios__input:disabled ~ .govuk-hint { + opacity: 0.5; +} + +@media (min-width: 40.0625em) { + .govuk-radios--inline:after { + content: ""; + display: block; + clear: both; + } + .govuk-radios--inline .govuk-radios__item { + margin-right: 20px; + float: left; + clear: none; + } +} + +.govuk-radios__divider { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + width: 40px; + margin-bottom: 10px; + text-align: center; +} +@media print { + .govuk-radios__divider { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-radios__divider { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-radios__divider { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-radios__divider { + color: #000000; + } +} + +.govuk-radios__conditional { + margin-bottom: 15px; + margin-left: 18px; + padding-left: 33px; + border-left: 4px solid #b1b4b6; +} +@media (min-width: 40.0625em) { + .govuk-radios__conditional { + margin-bottom: 20px; + } +} +.js-enabled .govuk-radios__conditional--hidden { + display: none; +} +.govuk-radios__conditional > :last-child { + margin-bottom: 0; +} + +.govuk-radios--small .govuk-radios__item { + min-height: 0; + margin-bottom: 0; + padding-left: 34px; + float: left; +} +.govuk-radios--small .govuk-radios__item:after { + content: ""; + display: block; + clear: both; +} +.govuk-radios--small .govuk-radios__input { + left: -10px; +} +.govuk-radios--small .govuk-radios__label { + margin-top: -2px; + padding: 13px 15px 13px 1px; + float: left; +} +@media (min-width: 40.0625em) { + .govuk-radios--small .govuk-radios__label { + padding: 11px 15px 10px 1px; + } +} +.govuk-radios--small .govuk-radios__label:before { + top: 8px; + width: 24px; + height: 24px; +} +.govuk-radios--small .govuk-radios__label:after { + top: 15px; + left: 7px; + border-width: 5px; +} +.govuk-radios--small .govuk-radios__hint { + padding: 0; + clear: both; + pointer-events: none; +} +.govuk-radios--small .govuk-radios__conditional { + margin-left: 10px; + padding-left: 20px; + clear: both; +} +.govuk-radios--small .govuk-radios__divider { + width: 24px; + margin-bottom: 5px; +} +.govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:not(:disabled) + .govuk-radios__label:before { + box-shadow: 0 0 0 10px #b1b4b6; +} +.govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:focus + .govuk-radios__label:before { + box-shadow: 0 0 0 4px #ffdd00, 0 0 0 10px #b1b4b6; +} +@media (hover: none), (pointer: coarse) { + .govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:not(:disabled) + .govuk-radios__label:before { + box-shadow: initial; + } + .govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:focus + .govuk-radios__label:before { + box-shadow: 0 0 0 4px #ffdd00; + } +} + +.govuk-select { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + box-sizing: border-box; + min-width: 11.5em; + max-width: 100%; + height: 40px; + height: 2.5rem; + padding: 5px; + border: 2px solid #0b0c0c; + color: #0b0c0c; + background-color: #ffffff; +} +@media print { + .govuk-select { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-select { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.25; + } +} +@media print { + .govuk-select { + font-size: 14pt; + line-height: 1.25; + } +} +.govuk-select:focus { + outline: 3px solid #ffdd00; + outline-offset: 0; + box-shadow: inset 0 0 0 2px; +} +.govuk-select:disabled { + opacity: 0.5; + color: inherit; + cursor: not-allowed; +} + +.govuk-select option:active, +.govuk-select option:checked, +.govuk-select:focus::-ms-value { + color: #ffffff; + background-color: #1d70b8; +} + +.govuk-select--error { + border-color: #d4351c; +} +.govuk-select--error:focus { + border-color: #0b0c0c; +} + +.govuk-skip-link { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + white-space: nowrap !important; + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + display: block; + padding: 10px 15px; +} +.govuk-skip-link:active, .govuk-skip-link:focus { + position: static !important; + width: auto !important; + height: auto !important; + margin: inherit !important; + overflow: visible !important; + clip: auto !important; + -webkit-clip-path: none !important; + clip-path: none !important; + white-space: inherit !important; +} +@media print { + .govuk-skip-link { + font-family: sans-serif; + } +} +.govuk-skip-link:link, .govuk-skip-link:visited { + color: #0b0c0c; +} +@media print { + .govuk-skip-link:link, .govuk-skip-link:visited { + color: #000000; + } +} +.govuk-skip-link:hover { + color: rgba(11, 12, 12, 0.99); +} +.govuk-skip-link:active, .govuk-skip-link:focus { + color: #0b0c0c; +} +@media print { + .govuk-skip-link:active, .govuk-skip-link:focus { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-skip-link { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .govuk-skip-link { + font-size: 14pt; + line-height: 1.2; + } +} +@supports (padding: max(calc(0px))) { + .govuk-skip-link { + padding-right: max(15px, calc(15px + env(safe-area-inset-right))); + padding-left: max(15px, calc(15px + env(safe-area-inset-left))); + } +} +.govuk-skip-link:focus { + outline: 3px solid #ffdd00; + outline-offset: 0; + background-color: #ffdd00; + box-shadow: none; +} + +.govuk-skip-link-focused-element:focus { + outline: none; +} + +.govuk-summary-list { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + margin: 0; + margin-bottom: 20px; +} +@media print { + .govuk-summary-list { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-list { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-summary-list { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-summary-list { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-list { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: collapse; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-list { + margin-bottom: 30px; + } +} + +.govuk-summary-list__row { + border-bottom: 1px solid #b1b4b6; +} +@media (max-width: 40.0525em) { + .govuk-summary-list__row { + margin-bottom: 15px; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-list__row { + display: table-row; + } +} + +.govuk-summary-list__row:not(.govuk-summary-list__row--no-actions) > :last-child { + padding-right: 0; +} + +@media (min-width: 40.0625em) { + .govuk-summary-list__row--no-actions:after { + content: ""; + display: table-cell; + width: 20%; + } +} + +.govuk-summary-list__key, +.govuk-summary-list__value, +.govuk-summary-list__actions { + margin: 0; +} +@media (min-width: 40.0625em) { + .govuk-summary-list__key, + .govuk-summary-list__value, + .govuk-summary-list__actions { + display: table-cell; + padding-top: 10px; + padding-right: 20px; + padding-bottom: 10px; + } +} + +.govuk-summary-list__actions { + margin-bottom: 15px; +} +@media (min-width: 40.0625em) { + .govuk-summary-list__actions { + width: 20%; + padding-right: 0; + text-align: right; + } +} + +.govuk-summary-list__key, +.govuk-summary-list__value { + word-wrap: break-word; + overflow-wrap: break-word; +} + +.govuk-summary-list__key { + margin-bottom: 5px; + font-weight: 700; +} +@media (min-width: 40.0625em) { + .govuk-summary-list__key { + width: 30%; + } +} + +@media (max-width: 40.0525em) { + .govuk-summary-list__value { + margin-bottom: 15px; + } +} + +.govuk-summary-list__value > p { + margin-bottom: 10px; +} + +.govuk-summary-list__value > :last-child { + margin-bottom: 0; +} + +.govuk-summary-list__actions-list { + width: 100%; + margin: 0; + padding: 0; +} + +.govuk-summary-list__actions-list-item { + display: inline-block; +} + +@media (max-width: 40.0525em) { + .govuk-summary-list__actions-list-item { + margin-right: 10px; + padding-right: 10px; + } + .govuk-summary-list__actions-list-item:not(:last-child) { + border-right: 1px solid #b1b4b6; + } + .govuk-summary-list__actions-list-item:last-child { + margin-right: 0; + padding-right: 0; + border: 0; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-list__actions-list-item { + margin-left: 10px; + padding-left: 10px; + } + .govuk-summary-list__actions-list-item:not(:first-child) { + border-left: 1px solid #b1b4b6; + } + .govuk-summary-list__actions-list-item:first-child { + margin-left: 0; + padding-left: 0; + border: 0; + } +} +.govuk-summary-list--no-border .govuk-summary-list__row { + border: 0; +} +@media (min-width: 40.0625em) { + .govuk-summary-list--no-border .govuk-summary-list__key, + .govuk-summary-list--no-border .govuk-summary-list__value, + .govuk-summary-list--no-border .govuk-summary-list__actions { + padding-bottom: 11px; + } +} + +.govuk-summary-list__row--no-border { + border: 0; +} +@media (min-width: 40.0625em) { + .govuk-summary-list__row--no-border .govuk-summary-list__key, + .govuk-summary-list__row--no-border .govuk-summary-list__value, + .govuk-summary-list__row--no-border .govuk-summary-list__actions { + padding-bottom: 11px; + } +} + +.govuk-summary-card { + margin-bottom: 20px; + border: 1px solid #b1b4b6; +} +@media (min-width: 40.0625em) { + .govuk-summary-card { + margin-bottom: 30px; + } +} + +.govuk-summary-card__title-wrapper { + padding: 15px; + border-bottom: 1px solid transparent; + background-color: #f3f2f1; +} +@media (min-width: 40.0625em) { + .govuk-summary-card__title-wrapper { + display: -ms-flexbox; + display: flex; + -ms-flex-pack: justify; + justify-content: space-between; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + padding: 15px 20px; + } +} + +.govuk-summary-card__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin: 5px 20px 10px 0; +} +@media print { + .govuk-summary-card__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-card__title { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-summary-card__title { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-card__title { + margin-bottom: 5px; + } +} + +.govuk-summary-card__actions { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + row-gap: 10px; + margin: 5px 0; + padding: 0; + list-style: none; +} +@media print { + .govuk-summary-card__actions { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-card__actions { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-summary-card__actions { + font-size: 14pt; + line-height: 1.15; + } +} +@media (min-width: 40.0625em) { + .govuk-summary-card__actions { + -ms-flex-pack: right; + justify-content: right; + text-align: right; + } +} + +.govuk-summary-card__action { + display: inline; + margin: 0 10px 0 0; + padding-right: 10px; + border-right: 1px solid #b1b4b6; +} +@media (min-width: 40.0625em) { + .govuk-summary-card__action { + margin-right: 0; + } +} +@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + .govuk-summary-card__action { + margin-bottom: 5px; + } +} + +.govuk-summary-card__action:last-child { + margin: 0; + padding-right: 0; + border-right: none; +} +@media (min-width: 40.0625em) { + .govuk-summary-card__action:last-child { + padding-left: 10px; + } +} +@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + .govuk-summary-card__action:last-child { + margin-bottom: 0; + } +} + +.govuk-summary-card__content { + padding: 15px 15px 0; +} +@media (min-width: 40.0625em) { + .govuk-summary-card__content { + padding: 15px 20px; + } +} +.govuk-summary-card__content .govuk-summary-list { + margin-bottom: 0; +} +.govuk-summary-card__content .govuk-summary-list__row:last-of-type { + margin-bottom: 0; + border-bottom: none; +} + +.govuk-table { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + width: 100%; + margin-bottom: 20px; + border-spacing: 0; + border-collapse: collapse; +} +@media print { + .govuk-table { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-table { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-table { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-table { + color: #000000; + } +} +@media (min-width: 40.0625em) { + .govuk-table { + margin-bottom: 30px; + } +} + +.govuk-table__header { + font-weight: 700; +} + +.govuk-table__header, +.govuk-table__cell { + padding: 10px 20px 10px 0; + border-bottom: 1px solid #b1b4b6; + text-align: left; + vertical-align: top; +} + +.govuk-table__cell--numeric { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-font-feature-settings: "tnum" 1; + font-feature-settings: "tnum" 1; + font-weight: 400; +} +@media print { + .govuk-table__cell--numeric { + font-family: sans-serif; + } +} +@supports (font-variant-numeric: tabular-nums) { + .govuk-table__cell--numeric { + -webkit-font-feature-settings: normal; + font-feature-settings: normal; + font-variant-numeric: tabular-nums; + } +} + +.govuk-table__header--numeric, +.govuk-table__cell--numeric { + text-align: right; +} + +.govuk-table__header:last-child, +.govuk-table__cell:last-child { + padding-right: 0; +} + +.govuk-table__caption { + font-weight: 700; + display: table-caption; + text-align: left; +} + +.govuk-table__caption--xl { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; + margin-bottom: 15px; +} +@media print { + .govuk-table__caption--xl { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-table__caption--xl { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .govuk-table__caption--xl { + font-size: 32pt; + line-height: 1.15; + } +} + +.govuk-table__caption--l { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; + margin-bottom: 15px; +} +@media print { + .govuk-table__caption--l { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-table__caption--l { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .govuk-table__caption--l { + font-size: 24pt; + line-height: 1.05; + } +} + +.govuk-table__caption--m { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; + margin-bottom: 15px; +} +@media print { + .govuk-table__caption--m { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-table__caption--m { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .govuk-table__caption--m { + font-size: 18pt; + line-height: 1.15; + } +} + +.govuk-table__caption--s { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; +} +@media print { + .govuk-table__caption--s { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-table__caption--s { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-table__caption--s { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-warning-text { + position: relative; + margin-bottom: 20px; + padding: 10px 0; +} +@media (min-width: 40.0625em) { + .govuk-warning-text { + margin-bottom: 30px; + } +} + +.govuk-warning-text__assistive { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; +} +.govuk-warning-text__assistive:before { + content: " "; +} +.govuk-warning-text__assistive:after { + content: " "; +} + +.govuk-warning-text__icon { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + box-sizing: border-box; + display: inline-block; + position: absolute; + left: 0; + min-width: 35px; + min-height: 35px; + margin-top: -7px; + border: 3px solid #0b0c0c; + border-radius: 50%; + color: #ffffff; + background: #0b0c0c; + font-size: 30px; + line-height: 29px; + text-align: center; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + forced-color-adjust: none; +} +@media print { + .govuk-warning-text__icon { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-warning-text__icon { + margin-top: -5px; + } +} +@media screen and (forced-colors: active) { + .govuk-warning-text__icon { + border-color: windowText; + color: windowText; + background: transparent; + } +} + +.govuk-warning-text__text { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #0b0c0c; + display: block; + padding-left: 45px; +} +@media print { + .govuk-warning-text__text { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .govuk-warning-text__text { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .govuk-warning-text__text { + font-size: 14pt; + line-height: 1.15; + } +} +@media print { + .govuk-warning-text__text { + color: #000000; + } +} + +.govuk-clearfix:after { + content: ""; + display: block; + clear: both; +} + +.govuk-visually-hidden { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + border: 0 !important; + white-space: nowrap !important; +} +.govuk-visually-hidden:before { + content: " "; +} +.govuk-visually-hidden:after { + content: " "; +} + +.govuk-visually-hidden-focusable { + position: absolute !important; + width: 1px !important; + height: 1px !important; + margin: 0 !important; + overflow: hidden !important; + clip: rect(0 0 0 0) !important; + -webkit-clip-path: inset(50%) !important; + clip-path: inset(50%) !important; + white-space: nowrap !important; +} +.govuk-visually-hidden-focusable:active, .govuk-visually-hidden-focusable:focus { + position: static !important; + width: auto !important; + height: auto !important; + margin: inherit !important; + overflow: visible !important; + clip: auto !important; + -webkit-clip-path: none !important; + clip-path: none !important; + white-space: inherit !important; +} + +.govuk-\!-display-inline { + display: inline !important; +} + +.govuk-\!-display-inline-block { + display: inline-block !important; +} + +.govuk-\!-display-block { + display: block !important; +} + +.govuk-\!-display-none { + display: none !important; +} + +@media print { + .govuk-\!-display-none-print { + display: none !important; + } +} +.govuk-\!-margin-0 { + margin: 0 !important; +} + +.govuk-\!-margin-top-0 { + margin-top: 0 !important; +} + +.govuk-\!-margin-right-0 { + margin-right: 0 !important; +} + +.govuk-\!-margin-bottom-0 { + margin-bottom: 0 !important; +} + +.govuk-\!-margin-left-0 { + margin-left: 0 !important; +} + +.govuk-\!-margin-1 { + margin: 5px !important; +} + +.govuk-\!-margin-top-1 { + margin-top: 5px !important; +} + +.govuk-\!-margin-right-1 { + margin-right: 5px !important; +} + +.govuk-\!-margin-bottom-1 { + margin-bottom: 5px !important; +} + +.govuk-\!-margin-left-1 { + margin-left: 5px !important; +} + +.govuk-\!-margin-2 { + margin: 10px !important; +} + +.govuk-\!-margin-top-2 { + margin-top: 10px !important; +} + +.govuk-\!-margin-right-2 { + margin-right: 10px !important; +} + +.govuk-\!-margin-bottom-2 { + margin-bottom: 10px !important; +} + +.govuk-\!-margin-left-2 { + margin-left: 10px !important; +} + +.govuk-\!-margin-3 { + margin: 15px !important; +} + +.govuk-\!-margin-top-3 { + margin-top: 15px !important; +} + +.govuk-\!-margin-right-3 { + margin-right: 15px !important; +} + +.govuk-\!-margin-bottom-3 { + margin-bottom: 15px !important; +} + +.govuk-\!-margin-left-3 { + margin-left: 15px !important; +} + +.govuk-\!-margin-4 { + margin: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-4 { + margin: 20px !important; + } +} + +.govuk-\!-margin-top-4 { + margin-top: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-4 { + margin-top: 20px !important; + } +} + +.govuk-\!-margin-right-4 { + margin-right: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-4 { + margin-right: 20px !important; + } +} + +.govuk-\!-margin-bottom-4 { + margin-bottom: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-4 { + margin-bottom: 20px !important; + } +} + +.govuk-\!-margin-left-4 { + margin-left: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-4 { + margin-left: 20px !important; + } +} + +.govuk-\!-margin-5 { + margin: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-5 { + margin: 25px !important; + } +} + +.govuk-\!-margin-top-5 { + margin-top: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-5 { + margin-top: 25px !important; + } +} + +.govuk-\!-margin-right-5 { + margin-right: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-5 { + margin-right: 25px !important; + } +} + +.govuk-\!-margin-bottom-5 { + margin-bottom: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-5 { + margin-bottom: 25px !important; + } +} + +.govuk-\!-margin-left-5 { + margin-left: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-5 { + margin-left: 25px !important; + } +} + +.govuk-\!-margin-6 { + margin: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-6 { + margin: 30px !important; + } +} + +.govuk-\!-margin-top-6 { + margin-top: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-6 { + margin-top: 30px !important; + } +} + +.govuk-\!-margin-right-6 { + margin-right: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-6 { + margin-right: 30px !important; + } +} + +.govuk-\!-margin-bottom-6 { + margin-bottom: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-6 { + margin-bottom: 30px !important; + } +} + +.govuk-\!-margin-left-6 { + margin-left: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-6 { + margin-left: 30px !important; + } +} + +.govuk-\!-margin-7 { + margin: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-7 { + margin: 40px !important; + } +} + +.govuk-\!-margin-top-7 { + margin-top: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-7 { + margin-top: 40px !important; + } +} + +.govuk-\!-margin-right-7 { + margin-right: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-7 { + margin-right: 40px !important; + } +} + +.govuk-\!-margin-bottom-7 { + margin-bottom: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-7 { + margin-bottom: 40px !important; + } +} + +.govuk-\!-margin-left-7 { + margin-left: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-7 { + margin-left: 40px !important; + } +} + +.govuk-\!-margin-8 { + margin: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-8 { + margin: 50px !important; + } +} + +.govuk-\!-margin-top-8 { + margin-top: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-8 { + margin-top: 50px !important; + } +} + +.govuk-\!-margin-right-8 { + margin-right: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-8 { + margin-right: 50px !important; + } +} + +.govuk-\!-margin-bottom-8 { + margin-bottom: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-8 { + margin-bottom: 50px !important; + } +} + +.govuk-\!-margin-left-8 { + margin-left: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-8 { + margin-left: 50px !important; + } +} + +.govuk-\!-margin-9 { + margin: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-9 { + margin: 60px !important; + } +} + +.govuk-\!-margin-top-9 { + margin-top: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-top-9 { + margin-top: 60px !important; + } +} + +.govuk-\!-margin-right-9 { + margin-right: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-right-9 { + margin-right: 60px !important; + } +} + +.govuk-\!-margin-bottom-9 { + margin-bottom: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-bottom-9 { + margin-bottom: 60px !important; + } +} + +.govuk-\!-margin-left-9 { + margin-left: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-margin-left-9 { + margin-left: 60px !important; + } +} + +.govuk-\!-padding-0 { + padding: 0 !important; +} + +.govuk-\!-padding-top-0 { + padding-top: 0 !important; +} + +.govuk-\!-padding-right-0 { + padding-right: 0 !important; +} + +.govuk-\!-padding-bottom-0 { + padding-bottom: 0 !important; +} + +.govuk-\!-padding-left-0 { + padding-left: 0 !important; +} + +.govuk-\!-padding-1 { + padding: 5px !important; +} + +.govuk-\!-padding-top-1 { + padding-top: 5px !important; +} + +.govuk-\!-padding-right-1 { + padding-right: 5px !important; +} + +.govuk-\!-padding-bottom-1 { + padding-bottom: 5px !important; +} + +.govuk-\!-padding-left-1 { + padding-left: 5px !important; +} + +.govuk-\!-padding-2 { + padding: 10px !important; +} + +.govuk-\!-padding-top-2 { + padding-top: 10px !important; +} + +.govuk-\!-padding-right-2 { + padding-right: 10px !important; +} + +.govuk-\!-padding-bottom-2 { + padding-bottom: 10px !important; +} + +.govuk-\!-padding-left-2 { + padding-left: 10px !important; +} + +.govuk-\!-padding-3 { + padding: 15px !important; +} + +.govuk-\!-padding-top-3 { + padding-top: 15px !important; +} + +.govuk-\!-padding-right-3 { + padding-right: 15px !important; +} + +.govuk-\!-padding-bottom-3 { + padding-bottom: 15px !important; +} + +.govuk-\!-padding-left-3 { + padding-left: 15px !important; +} + +.govuk-\!-padding-4 { + padding: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-4 { + padding: 20px !important; + } +} + +.govuk-\!-padding-top-4 { + padding-top: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-4 { + padding-top: 20px !important; + } +} + +.govuk-\!-padding-right-4 { + padding-right: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-4 { + padding-right: 20px !important; + } +} + +.govuk-\!-padding-bottom-4 { + padding-bottom: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-4 { + padding-bottom: 20px !important; + } +} + +.govuk-\!-padding-left-4 { + padding-left: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-4 { + padding-left: 20px !important; + } +} + +.govuk-\!-padding-5 { + padding: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-5 { + padding: 25px !important; + } +} + +.govuk-\!-padding-top-5 { + padding-top: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-5 { + padding-top: 25px !important; + } +} + +.govuk-\!-padding-right-5 { + padding-right: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-5 { + padding-right: 25px !important; + } +} + +.govuk-\!-padding-bottom-5 { + padding-bottom: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-5 { + padding-bottom: 25px !important; + } +} + +.govuk-\!-padding-left-5 { + padding-left: 15px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-5 { + padding-left: 25px !important; + } +} + +.govuk-\!-padding-6 { + padding: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-6 { + padding: 30px !important; + } +} + +.govuk-\!-padding-top-6 { + padding-top: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-6 { + padding-top: 30px !important; + } +} + +.govuk-\!-padding-right-6 { + padding-right: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-6 { + padding-right: 30px !important; + } +} + +.govuk-\!-padding-bottom-6 { + padding-bottom: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-6 { + padding-bottom: 30px !important; + } +} + +.govuk-\!-padding-left-6 { + padding-left: 20px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-6 { + padding-left: 30px !important; + } +} + +.govuk-\!-padding-7 { + padding: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-7 { + padding: 40px !important; + } +} + +.govuk-\!-padding-top-7 { + padding-top: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-7 { + padding-top: 40px !important; + } +} + +.govuk-\!-padding-right-7 { + padding-right: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-7 { + padding-right: 40px !important; + } +} + +.govuk-\!-padding-bottom-7 { + padding-bottom: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-7 { + padding-bottom: 40px !important; + } +} + +.govuk-\!-padding-left-7 { + padding-left: 25px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-7 { + padding-left: 40px !important; + } +} + +.govuk-\!-padding-8 { + padding: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-8 { + padding: 50px !important; + } +} + +.govuk-\!-padding-top-8 { + padding-top: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-8 { + padding-top: 50px !important; + } +} + +.govuk-\!-padding-right-8 { + padding-right: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-8 { + padding-right: 50px !important; + } +} + +.govuk-\!-padding-bottom-8 { + padding-bottom: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-8 { + padding-bottom: 50px !important; + } +} + +.govuk-\!-padding-left-8 { + padding-left: 30px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-8 { + padding-left: 50px !important; + } +} + +.govuk-\!-padding-9 { + padding: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-9 { + padding: 60px !important; + } +} + +.govuk-\!-padding-top-9 { + padding-top: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-top-9 { + padding-top: 60px !important; + } +} + +.govuk-\!-padding-right-9 { + padding-right: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-right-9 { + padding-right: 60px !important; + } +} + +.govuk-\!-padding-bottom-9 { + padding-bottom: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-bottom-9 { + padding-bottom: 60px !important; + } +} + +.govuk-\!-padding-left-9 { + padding-left: 40px !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-padding-left-9 { + padding-left: 60px !important; + } +} + +.govuk-\!-margin-static-0, +.govuk-\!-static-margin-0 { + margin: 0 !important; +} + +.govuk-\!-margin-top-static-0, +.govuk-\!-static-margin-top-0 { + margin-top: 0 !important; +} + +.govuk-\!-margin-right-static-0, +.govuk-\!-static-margin-right-0 { + margin-right: 0 !important; +} + +.govuk-\!-margin-bottom-static-0, +.govuk-\!-static-margin-bottom-0 { + margin-bottom: 0 !important; +} + +.govuk-\!-margin-left-static-0, +.govuk-\!-static-margin-left-0 { + margin-left: 0 !important; +} + +.govuk-\!-margin-static-1, +.govuk-\!-static-margin-1 { + margin: 5px !important; +} + +.govuk-\!-margin-top-static-1, +.govuk-\!-static-margin-top-1 { + margin-top: 5px !important; +} + +.govuk-\!-margin-right-static-1, +.govuk-\!-static-margin-right-1 { + margin-right: 5px !important; +} + +.govuk-\!-margin-bottom-static-1, +.govuk-\!-static-margin-bottom-1 { + margin-bottom: 5px !important; +} + +.govuk-\!-margin-left-static-1, +.govuk-\!-static-margin-left-1 { + margin-left: 5px !important; +} + +.govuk-\!-margin-static-2, +.govuk-\!-static-margin-2 { + margin: 10px !important; +} + +.govuk-\!-margin-top-static-2, +.govuk-\!-static-margin-top-2 { + margin-top: 10px !important; +} + +.govuk-\!-margin-right-static-2, +.govuk-\!-static-margin-right-2 { + margin-right: 10px !important; +} + +.govuk-\!-margin-bottom-static-2, +.govuk-\!-static-margin-bottom-2 { + margin-bottom: 10px !important; +} + +.govuk-\!-margin-left-static-2, +.govuk-\!-static-margin-left-2 { + margin-left: 10px !important; +} + +.govuk-\!-margin-static-3, +.govuk-\!-static-margin-3 { + margin: 15px !important; +} + +.govuk-\!-margin-top-static-3, +.govuk-\!-static-margin-top-3 { + margin-top: 15px !important; +} + +.govuk-\!-margin-right-static-3, +.govuk-\!-static-margin-right-3 { + margin-right: 15px !important; +} + +.govuk-\!-margin-bottom-static-3, +.govuk-\!-static-margin-bottom-3 { + margin-bottom: 15px !important; +} + +.govuk-\!-margin-left-static-3, +.govuk-\!-static-margin-left-3 { + margin-left: 15px !important; +} + +.govuk-\!-margin-static-4, +.govuk-\!-static-margin-4 { + margin: 20px !important; +} + +.govuk-\!-margin-top-static-4, +.govuk-\!-static-margin-top-4 { + margin-top: 20px !important; +} + +.govuk-\!-margin-right-static-4, +.govuk-\!-static-margin-right-4 { + margin-right: 20px !important; +} + +.govuk-\!-margin-bottom-static-4, +.govuk-\!-static-margin-bottom-4 { + margin-bottom: 20px !important; +} + +.govuk-\!-margin-left-static-4, +.govuk-\!-static-margin-left-4 { + margin-left: 20px !important; +} + +.govuk-\!-margin-static-5, +.govuk-\!-static-margin-5 { + margin: 25px !important; +} + +.govuk-\!-margin-top-static-5, +.govuk-\!-static-margin-top-5 { + margin-top: 25px !important; +} + +.govuk-\!-margin-right-static-5, +.govuk-\!-static-margin-right-5 { + margin-right: 25px !important; +} + +.govuk-\!-margin-bottom-static-5, +.govuk-\!-static-margin-bottom-5 { + margin-bottom: 25px !important; +} + +.govuk-\!-margin-left-static-5, +.govuk-\!-static-margin-left-5 { + margin-left: 25px !important; +} + +.govuk-\!-margin-static-6, +.govuk-\!-static-margin-6 { + margin: 30px !important; +} + +.govuk-\!-margin-top-static-6, +.govuk-\!-static-margin-top-6 { + margin-top: 30px !important; +} + +.govuk-\!-margin-right-static-6, +.govuk-\!-static-margin-right-6 { + margin-right: 30px !important; +} + +.govuk-\!-margin-bottom-static-6, +.govuk-\!-static-margin-bottom-6 { + margin-bottom: 30px !important; +} + +.govuk-\!-margin-left-static-6, +.govuk-\!-static-margin-left-6 { + margin-left: 30px !important; +} + +.govuk-\!-margin-static-7, +.govuk-\!-static-margin-7 { + margin: 40px !important; +} + +.govuk-\!-margin-top-static-7, +.govuk-\!-static-margin-top-7 { + margin-top: 40px !important; +} + +.govuk-\!-margin-right-static-7, +.govuk-\!-static-margin-right-7 { + margin-right: 40px !important; +} + +.govuk-\!-margin-bottom-static-7, +.govuk-\!-static-margin-bottom-7 { + margin-bottom: 40px !important; +} + +.govuk-\!-margin-left-static-7, +.govuk-\!-static-margin-left-7 { + margin-left: 40px !important; +} + +.govuk-\!-margin-static-8, +.govuk-\!-static-margin-8 { + margin: 50px !important; +} + +.govuk-\!-margin-top-static-8, +.govuk-\!-static-margin-top-8 { + margin-top: 50px !important; +} + +.govuk-\!-margin-right-static-8, +.govuk-\!-static-margin-right-8 { + margin-right: 50px !important; +} + +.govuk-\!-margin-bottom-static-8, +.govuk-\!-static-margin-bottom-8 { + margin-bottom: 50px !important; +} + +.govuk-\!-margin-left-static-8, +.govuk-\!-static-margin-left-8 { + margin-left: 50px !important; +} + +.govuk-\!-margin-static-9, +.govuk-\!-static-margin-9 { + margin: 60px !important; +} + +.govuk-\!-margin-top-static-9, +.govuk-\!-static-margin-top-9 { + margin-top: 60px !important; +} + +.govuk-\!-margin-right-static-9, +.govuk-\!-static-margin-right-9 { + margin-right: 60px !important; +} + +.govuk-\!-margin-bottom-static-9, +.govuk-\!-static-margin-bottom-9 { + margin-bottom: 60px !important; +} + +.govuk-\!-margin-left-static-9, +.govuk-\!-static-margin-left-9 { + margin-left: 60px !important; +} + +.govuk-\!-padding-static-0, +.govuk-\!-static-padding-0 { + padding: 0 !important; +} + +.govuk-\!-padding-top-static-0, +.govuk-\!-static-padding-top-0 { + padding-top: 0 !important; +} + +.govuk-\!-padding-right-static-0, +.govuk-\!-static-padding-right-0 { + padding-right: 0 !important; +} + +.govuk-\!-padding-bottom-static-0, +.govuk-\!-static-padding-bottom-0 { + padding-bottom: 0 !important; +} + +.govuk-\!-padding-left-static-0, +.govuk-\!-static-padding-left-0 { + padding-left: 0 !important; +} + +.govuk-\!-padding-static-1, +.govuk-\!-static-padding-1 { + padding: 5px !important; +} + +.govuk-\!-padding-top-static-1, +.govuk-\!-static-padding-top-1 { + padding-top: 5px !important; +} + +.govuk-\!-padding-right-static-1, +.govuk-\!-static-padding-right-1 { + padding-right: 5px !important; +} + +.govuk-\!-padding-bottom-static-1, +.govuk-\!-static-padding-bottom-1 { + padding-bottom: 5px !important; +} + +.govuk-\!-padding-left-static-1, +.govuk-\!-static-padding-left-1 { + padding-left: 5px !important; +} + +.govuk-\!-padding-static-2, +.govuk-\!-static-padding-2 { + padding: 10px !important; +} + +.govuk-\!-padding-top-static-2, +.govuk-\!-static-padding-top-2 { + padding-top: 10px !important; +} + +.govuk-\!-padding-right-static-2, +.govuk-\!-static-padding-right-2 { + padding-right: 10px !important; +} + +.govuk-\!-padding-bottom-static-2, +.govuk-\!-static-padding-bottom-2 { + padding-bottom: 10px !important; +} + +.govuk-\!-padding-left-static-2, +.govuk-\!-static-padding-left-2 { + padding-left: 10px !important; +} + +.govuk-\!-padding-static-3, +.govuk-\!-static-padding-3 { + padding: 15px !important; +} + +.govuk-\!-padding-top-static-3, +.govuk-\!-static-padding-top-3 { + padding-top: 15px !important; +} + +.govuk-\!-padding-right-static-3, +.govuk-\!-static-padding-right-3 { + padding-right: 15px !important; +} + +.govuk-\!-padding-bottom-static-3, +.govuk-\!-static-padding-bottom-3 { + padding-bottom: 15px !important; +} + +.govuk-\!-padding-left-static-3, +.govuk-\!-static-padding-left-3 { + padding-left: 15px !important; +} + +.govuk-\!-padding-static-4, +.govuk-\!-static-padding-4 { + padding: 20px !important; +} + +.govuk-\!-padding-top-static-4, +.govuk-\!-static-padding-top-4 { + padding-top: 20px !important; +} + +.govuk-\!-padding-right-static-4, +.govuk-\!-static-padding-right-4 { + padding-right: 20px !important; +} + +.govuk-\!-padding-bottom-static-4, +.govuk-\!-static-padding-bottom-4 { + padding-bottom: 20px !important; +} + +.govuk-\!-padding-left-static-4, +.govuk-\!-static-padding-left-4 { + padding-left: 20px !important; +} + +.govuk-\!-padding-static-5, +.govuk-\!-static-padding-5 { + padding: 25px !important; +} + +.govuk-\!-padding-top-static-5, +.govuk-\!-static-padding-top-5 { + padding-top: 25px !important; +} + +.govuk-\!-padding-right-static-5, +.govuk-\!-static-padding-right-5 { + padding-right: 25px !important; +} + +.govuk-\!-padding-bottom-static-5, +.govuk-\!-static-padding-bottom-5 { + padding-bottom: 25px !important; +} + +.govuk-\!-padding-left-static-5, +.govuk-\!-static-padding-left-5 { + padding-left: 25px !important; +} + +.govuk-\!-padding-static-6, +.govuk-\!-static-padding-6 { + padding: 30px !important; +} + +.govuk-\!-padding-top-static-6, +.govuk-\!-static-padding-top-6 { + padding-top: 30px !important; +} + +.govuk-\!-padding-right-static-6, +.govuk-\!-static-padding-right-6 { + padding-right: 30px !important; +} + +.govuk-\!-padding-bottom-static-6, +.govuk-\!-static-padding-bottom-6 { + padding-bottom: 30px !important; +} + +.govuk-\!-padding-left-static-6, +.govuk-\!-static-padding-left-6 { + padding-left: 30px !important; +} + +.govuk-\!-padding-static-7, +.govuk-\!-static-padding-7 { + padding: 40px !important; +} + +.govuk-\!-padding-top-static-7, +.govuk-\!-static-padding-top-7 { + padding-top: 40px !important; +} + +.govuk-\!-padding-right-static-7, +.govuk-\!-static-padding-right-7 { + padding-right: 40px !important; +} + +.govuk-\!-padding-bottom-static-7, +.govuk-\!-static-padding-bottom-7 { + padding-bottom: 40px !important; +} + +.govuk-\!-padding-left-static-7, +.govuk-\!-static-padding-left-7 { + padding-left: 40px !important; +} + +.govuk-\!-padding-static-8, +.govuk-\!-static-padding-8 { + padding: 50px !important; +} + +.govuk-\!-padding-top-static-8, +.govuk-\!-static-padding-top-8 { + padding-top: 50px !important; +} + +.govuk-\!-padding-right-static-8, +.govuk-\!-static-padding-right-8 { + padding-right: 50px !important; +} + +.govuk-\!-padding-bottom-static-8, +.govuk-\!-static-padding-bottom-8 { + padding-bottom: 50px !important; +} + +.govuk-\!-padding-left-static-8, +.govuk-\!-static-padding-left-8 { + padding-left: 50px !important; +} + +.govuk-\!-padding-static-9, +.govuk-\!-static-padding-9 { + padding: 60px !important; +} + +.govuk-\!-padding-top-static-9, +.govuk-\!-static-padding-top-9 { + padding-top: 60px !important; +} + +.govuk-\!-padding-right-static-9, +.govuk-\!-static-padding-right-9 { + padding-right: 60px !important; +} + +.govuk-\!-padding-bottom-static-9, +.govuk-\!-static-padding-bottom-9 { + padding-bottom: 60px !important; +} + +.govuk-\!-padding-left-static-9, +.govuk-\!-static-padding-left-9 { + padding-left: 60px !important; +} + +.govuk-\!-text-align-left { + text-align: left !important; +} + +.govuk-\!-text-align-centre { + text-align: center !important; +} + +.govuk-\!-text-align-right { + text-align: right !important; +} + +.govuk-\!-font-size-80 { + font-size: 53px !important; + font-size: 3.3125rem !important; + line-height: 1.0377358491 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-80 { + font-size: 80px !important; + font-size: 5rem !important; + line-height: 1 !important; + } +} +@media print { + .govuk-\!-font-size-80 { + font-size: 53pt !important; + line-height: 1.1 !important; + } +} + +.govuk-\!-font-size-48 { + font-size: 32px !important; + font-size: 2rem !important; + line-height: 1.09375 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-48 { + font-size: 48px !important; + font-size: 3rem !important; + line-height: 1.0416666667 !important; + } +} +@media print { + .govuk-\!-font-size-48 { + font-size: 32pt !important; + line-height: 1.15 !important; + } +} + +.govuk-\!-font-size-36 { + font-size: 24px !important; + font-size: 1.5rem !important; + line-height: 1.0416666667 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-36 { + font-size: 36px !important; + font-size: 2.25rem !important; + line-height: 1.1111111111 !important; + } +} +@media print { + .govuk-\!-font-size-36 { + font-size: 24pt !important; + line-height: 1.05 !important; + } +} + +.govuk-\!-font-size-27 { + font-size: 18px !important; + font-size: 1.125rem !important; + line-height: 1.1111111111 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-27 { + font-size: 27px !important; + font-size: 1.6875rem !important; + line-height: 1.1111111111 !important; + } +} +@media print { + .govuk-\!-font-size-27 { + font-size: 18pt !important; + line-height: 1.15 !important; + } +} + +.govuk-\!-font-size-24 { + font-size: 18px !important; + font-size: 1.125rem !important; + line-height: 1.1111111111 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-24 { + font-size: 24px !important; + font-size: 1.5rem !important; + line-height: 1.25 !important; + } +} +@media print { + .govuk-\!-font-size-24 { + font-size: 18pt !important; + line-height: 1.15 !important; + } +} + +.govuk-\!-font-size-19 { + font-size: 16px !important; + font-size: 1rem !important; + line-height: 1.25 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-19 { + font-size: 19px !important; + font-size: 1.1875rem !important; + line-height: 1.3157894737 !important; + } +} +@media print { + .govuk-\!-font-size-19 { + font-size: 14pt !important; + line-height: 1.15 !important; + } +} + +.govuk-\!-font-size-16 { + font-size: 14px !important; + font-size: 0.875rem !important; + line-height: 1.1428571429 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-16 { + font-size: 16px !important; + font-size: 1rem !important; + line-height: 1.25 !important; + } +} +@media print { + .govuk-\!-font-size-16 { + font-size: 14pt !important; + line-height: 1.2 !important; + } +} + +.govuk-\!-font-size-14 { + font-size: 12px !important; + font-size: 0.75rem !important; + line-height: 1.25 !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-font-size-14 { + font-size: 14px !important; + font-size: 0.875rem !important; + line-height: 1.4285714286 !important; + } +} +@media print { + .govuk-\!-font-size-14 { + font-size: 12pt !important; + line-height: 1.2 !important; + } +} + +.govuk-\!-font-weight-regular { + font-weight: 400 !important; +} + +.govuk-\!-font-weight-bold { + font-weight: 700 !important; +} + +.govuk-\!-width-full { + width: 100% !important; +} + +.govuk-\!-width-three-quarters { + width: 100% !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-width-three-quarters { + width: 75% !important; + } +} + +.govuk-\!-width-two-thirds { + width: 100% !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-width-two-thirds { + width: 66.66% !important; + } +} + +.govuk-\!-width-one-half { + width: 100% !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-width-one-half { + width: 50% !important; + } +} + +.govuk-\!-width-one-third { + width: 100% !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-width-one-third { + width: 33.33% !important; + } +} + +.govuk-\!-width-one-quarter { + width: 100% !important; +} +@media (min-width: 40.0625em) { + .govuk-\!-width-one-quarter { + width: 25% !important; + } +} + +.autocomplete__wrapper { + position: relative; +} + +.autocomplete__hint, +.autocomplete__input { + -webkit-appearance: none; + border: 2px solid #0b0c0c; + border-radius: 0; /* Safari 10 on iOS adds implicit border rounding. */ + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + margin-bottom: 0; /* BUG: Safari 10 on macOS seems to add an implicit margin. */ + width: 100%; +} + +.autocomplete__input { + background-color: transparent; + position: relative; +} + +.autocomplete__hint { + color: #b1b4b6; + position: absolute; +} + +.autocomplete__input--default { + padding: 5px; +} + +.autocomplete__input--focused { + outline: 3px solid #fd0; + outline-offset: 0; + box-shadow: inset 0 0 0 2px; +} + +.autocomplete__input--show-all-values { + padding: 5px 34px 5px 5px; /* Space for arrow. Other padding should match .autocomplete__input--default. */ + cursor: pointer; +} + +.autocomplete__dropdown-arrow-down { + z-index: -1; + display: inline-block; + position: absolute; + right: 8px; + width: 24px; + height: 24px; + top: 10px; +} + +.autocomplete__menu { + background-color: #fff; + border: 2px solid #0B0C0C; + border-top: 0; + color: #0B0C0C; + margin: 0; + max-height: 342px; + overflow-x: hidden; + padding: 0; + width: 100%; + width: calc(100% - 4px); +} + +.autocomplete__menu--visible { + display: block; +} + +.autocomplete__menu--hidden { + display: none; +} + +.autocomplete__menu--overlay { + box-shadow: rgba(0, 0, 0, 0.256863) 0px 2px 6px; + left: 0; + position: absolute; + top: 100%; + z-index: 100; +} + +.autocomplete__menu--inline { + position: relative; +} + +.autocomplete__option { + border-bottom: solid #b1b4b6; + border-width: 1px 0; + cursor: pointer; + display: block; + position: relative; +} + +.autocomplete__option > * { + pointer-events: none; +} + +.autocomplete__option:first-of-type { + border-top-width: 0; +} + +.autocomplete__option:last-of-type { + border-bottom-width: 0; +} + +.autocomplete__option--odd { + background-color: #FAFAFA; +} + +.autocomplete__option--focused, +.autocomplete__option:hover { + background-color: #1d70b8; + border-color: #1d70b8; + color: white; + outline: none; +} + +@media (-ms-high-contrast: active), (forced-colors: active) { + .autocomplete__menu { + border-color: FieldText; + } + .autocomplete__option { + background-color: Field; + color: FieldText; + } + .autocomplete__option--focused, + .autocomplete__option:hover { + forced-color-adjust: none; /* prevent backplate from obscuring text */ + background-color: Highlight; + border-color: Highlight; + color: HighlightText; + /* Prefer SelectedItem / SelectedItemText in browsers that support it */ + background-color: SelectedItem; + border-color: SelectedItem; + color: SelectedItemText; + outline-color: SelectedItemText; + } +} +.autocomplete__option--no-results { + background-color: #FAFAFA; + color: #646b6f; + cursor: not-allowed; +} + +.autocomplete__hint, +.autocomplete__input, +.autocomplete__option { + font-size: 16px; + line-height: 1.25; +} + +.autocomplete__hint, +.autocomplete__option { + padding: 5px; +} + +@media (min-width: 641px) { + .autocomplete__hint, + .autocomplete__input, + .autocomplete__option { + font-size: 19px; + line-height: 1.31579; + } +} +.autocomplete__wrapper { + font-family: "GDS Transport", arial, sans-serif; +} + +.autocomplete__input { + font-family: inherit; +} + +.govuk-form-group--error .autocomplete__input { + border-color: #d4351c; +} +.govuk-form-group--error .autocomplete__input--focused { + border-color: #0b0c0c; +} + +.autocomplete__dropdown-arrow-down { + pointer-events: none; + z-index: 0; +} + +.x-govuk-breadcrumbs--inverse { + padding-bottom: 15px; + padding-top: 15px; + border-bottom: 1px solid #5694ca; + color: #ffffff; + margin-top: 0; +} +@media (min-width: 40.0625em) { + .x-govuk-breadcrumbs--inverse { + padding-top: 20px; + } +} +.x-govuk-breadcrumbs--inverse .govuk-breadcrumbs__list-item::before { + border-color: #ffffff; +} +.x-govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:not(:focus) { + color: inherit; +} + +.x-govuk-button--inverse, +.x-govuk-button--inverse:link, +.x-govuk-button--inverse:visited { + margin-top: 20px; + color: #1d70b8; + background-color: #ffffff; + box-shadow: 0 2px 0 #144e81; + margin-bottom: 0; +} +@media (min-width: 40.0625em) { + .x-govuk-button--inverse, + .x-govuk-button--inverse:link, + .x-govuk-button--inverse:visited { + margin-top: 30px; + } +} + +.x-govuk-button--inverse:hover { + color: #1d70b8; + background-color: #e8f1f8; +} + +.x-govuk-button--inverse:focus:not(:hover) { + color: #0b0c0c; + background-color: #ffdd00; +} + +.x-govuk-button--inverse:active, +.x-govuk-button--inverse:focus { + border-color: #ffdd00; + color: #1d70b8; + background-color: #e8f1f8; + box-shadow: inset 0 0 0 2px #ffdd00; +} + +.x-govuk-phase-banner--inverse { + border-bottom-color: #5694ca; +} +.x-govuk-phase-banner--inverse .govuk-phase-banner__content { + color: #ffffff; +} + +.x-govuk-tag--inverse { + color: #1d70b8; + background-color: #ffffff; +} + +.x-govuk-masthead { + padding-bottom: 25px; + padding-top: 0; + color: #ffffff; + background-color: #1d70b8; + margin-top: -10px; +} +@media (min-width: 40.0625em) { + .x-govuk-masthead { + padding-bottom: 40px; + } +} + +.x-govuk-masthead__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 24px; + font-size: 1.5rem; + line-height: 1.0416666667; + padding-top: 20px; + margin-top: 0; +} +@media print { + .x-govuk-masthead__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-masthead__title { + font-size: 36px; + font-size: 2.25rem; + line-height: 1.1111111111; + } +} +@media print { + .x-govuk-masthead__title { + font-size: 24pt; + line-height: 1.05; + } +} +@media (min-width: 40.0625em) { + .x-govuk-masthead__title { + padding-top: 30px; + } +} + +.x-govuk-masthead__description { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: inherit; + margin-bottom: 0; +} +@media print { + .x-govuk-masthead__description { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-masthead__description { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .x-govuk-masthead__description { + font-size: 14pt; + line-height: 1.15; + } +} +.x-govuk-masthead__description a:not(:focus) { + color: inherit; +} + +.x-govuk-masthead__image { + padding-top: 20px; +} +@media (min-width: 40.0625em) { + .x-govuk-masthead__image { + padding-top: 30px; + } +} +.x-govuk-masthead__image img { + max-width: 100%; +} +@media (max-width: 48.0525em) { + .x-govuk-masthead__image { + display: none; + } +} + +.x-govuk-masthead--large .x-govuk-masthead__title { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 32px; + font-size: 2rem; + line-height: 1.09375; +} +@media print { + .x-govuk-masthead--large .x-govuk-masthead__title { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-masthead--large .x-govuk-masthead__title { + font-size: 48px; + font-size: 3rem; + line-height: 1.0416666667; + } +} +@media print { + .x-govuk-masthead--large .x-govuk-masthead__title { + font-size: 32pt; + line-height: 1.15; + } +} +.x-govuk-masthead--large .x-govuk-masthead__description { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 18px; + font-size: 1.125rem; + line-height: 1.1111111111; +} +@media print { + .x-govuk-masthead--large .x-govuk-masthead__description { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-masthead--large .x-govuk-masthead__description { + font-size: 24px; + font-size: 1.5rem; + line-height: 1.25; + } +} +@media print { + .x-govuk-masthead--large .x-govuk-masthead__description { + font-size: 18pt; + line-height: 1.15; + } +} + +.x-govuk-primary-navigation { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + background-color: #f3f2f1; + border-bottom: 1px solid #b1b4b6; +} +@media print { + .x-govuk-primary-navigation { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-primary-navigation { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .x-govuk-primary-navigation { + font-size: 14pt; + line-height: 1.15; + } +} + +.govuk-phase-banner + .x-govuk-primary-navigation { + margin-top: -1px; +} + +.x-govuk-primary-navigation__list { + left: -15px; + list-style: none; + margin: 0; + padding: 0; + position: relative; + right: -15px; + width: calc(100% + 30px); +} +.x-govuk-primary-navigation__list:after { + content: ""; + display: block; + clear: both; +} + +.x-govuk-primary-navigation__item { + box-sizing: border-box; + display: block; + float: left; + line-height: 50px; + height: 50px; + padding: 0 15px; + position: relative; +} + +.x-govuk-primary-navigation__item--current { + border-bottom: 4px solid #1d70b8; +} +.x-govuk-primary-navigation__item--current:hover { + border-bottom-color: #003078; +} +.x-govuk-primary-navigation__item--current:active { + border-bottom-color: #0b0c0c; +} + +@media (min-width: 40.0625em) { + .x-govuk-primary-navigation__item--align-right { + float: right; + } +} + +.x-govuk-primary-navigation__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + font-weight: 700; +} +@media print { + .x-govuk-primary-navigation__link { + font-family: sans-serif; + } +} +.x-govuk-primary-navigation__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.x-govuk-primary-navigation__link:link { + color: #1d70b8; +} +.x-govuk-primary-navigation__link:visited { + color: #1d70b8; +} +.x-govuk-primary-navigation__link:hover { + color: #003078; +} +.x-govuk-primary-navigation__link:active { + color: #0b0c0c; +} +.x-govuk-primary-navigation__link:focus { + color: #0b0c0c; +} +.x-govuk-primary-navigation__link:not(:hover):not(:active) { + text-decoration: none; +} +.x-govuk-primary-navigation__link::after { + bottom: 0; + content: ""; + left: 0; + position: absolute; + right: 0; + top: 0; +} + +.x-govuk-related-navigation { + color: #0b0c0c; + border-top: 2px solid #1d70b8; +} +@media print { + .x-govuk-related-navigation { + color: #000000; + } +} + +.x-govuk-related-navigation__main-heading { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + margin-top: 15px; + margin-bottom: 10px; +} +@media print { + .x-govuk-related-navigation__main-heading { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-related-navigation__main-heading { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .x-govuk-related-navigation__main-heading { + font-size: 14pt; + line-height: 1.15; + } +} + +.x-govuk-related-navigation__sub-heading { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; + margin: 0; + padding-top: 15px; +} +@media print { + .x-govuk-related-navigation__sub-heading { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-related-navigation__sub-heading { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .x-govuk-related-navigation__sub-heading { + font-size: 14pt; + line-height: 1.2; + } +} + +.x-govuk-related-navigation__sub-heading--footer { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 700; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + border-top: 0; + padding-top: 0; + margin-top: 15px; + margin-bottom: 10px; +} +@media print { + .x-govuk-related-navigation__sub-heading--footer { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-related-navigation__sub-heading--footer { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .x-govuk-related-navigation__sub-heading--footer { + font-size: 14pt; + line-height: 1.15; + } +} + +.x-govuk-related-navigation__main-heading + .x-govuk-related-navigation__sub-heading { + border-top: 0; + padding-top: 0; +} + +.x-govuk-related-navigation__nav-section { + border-top: 1px solid #b1b4b6; + margin-bottom: 30px; +} +.x-govuk-related-navigation__nav-section:first-child { + border-top: none; +} + +.x-govuk-related-navigation__link-list { + padding: 0; + margin: 0; + list-style: none; + margin-bottom: 1.25em; +} + +.x-govuk-related-navigation__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.45; + list-style-type: none; + margin-top: 15px; +} +@media print { + .x-govuk-related-navigation__link { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-related-navigation__link { + font-size: 16px; + font-size: 1rem; + line-height: 1.45; + } +} +@media print { + .x-govuk-related-navigation__link { + font-size: 14pt; + line-height: 1.45; + } +} +@media (min-width: 40.0625em) { + .x-govuk-related-navigation__link { + line-height: 1.28; + } +} + +.x-govuk-related-navigation__section-link { + font-weight: bold; +} + +.x-govuk-related-navigation__section-link--other { + font-weight: normal; +} + +.x-govuk-sub-navigation { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 14px; + font-size: 0.875rem; + line-height: 1.1428571429; +} +@media print { + .x-govuk-sub-navigation { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-sub-navigation { + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + } +} +@media print { + .x-govuk-sub-navigation { + font-size: 14pt; + line-height: 1.2; + } +} + +.x-govuk-sub-navigation__section { + list-style-type: none; + margin: 0 0 20px; + padding: 0; +} + +.x-govuk-sub-navigation__link { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-decoration: underline; + padding-bottom: 5px; + padding-top: 5px; +} +@media print { + .x-govuk-sub-navigation__link { + font-family: sans-serif; + } +} +.x-govuk-sub-navigation__link:focus { + outline: 3px solid transparent; + color: #0b0c0c; + background-color: #ffdd00; + box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; + text-decoration: none; + -webkit-box-decoration-break: clone; + box-decoration-break: clone; +} +.x-govuk-sub-navigation__link:link { + color: #1d70b8; +} +.x-govuk-sub-navigation__link:visited { + color: #1d70b8; +} +.x-govuk-sub-navigation__link:hover { + color: #003078; +} +.x-govuk-sub-navigation__link:active { + color: #0b0c0c; +} +.x-govuk-sub-navigation__link:focus { + color: #0b0c0c; +} +.x-govuk-sub-navigation__link:not(:hover):not(:active) { + text-decoration: none; +} +.x-govuk-sub-navigation__link:not(:focus):hover { + color: #1d70b8; +} + +.x-govuk-sub-navigation__section-item { + margin-bottom: 5px; + padding-bottom: 5px; + padding-top: 5px; +} + +.x-govuk-sub-navigation__section-item--current { + background-color: #ffffff; + border-left: 4px solid #1d70b8; + margin-left: -14px; + padding-left: 10px; +} + +.x-govuk-sub-navigation__link[aria-current] { + font-weight: bold; +} + +.x-govuk-sub-navigation__section--nested { + margin-bottom: 0; + margin-top: 10px; + padding-left: 20px; +} + +.x-govuk-sub-navigation__section--nested .x-govuk-sub-navigation__section-item::before { + color: #505a5f; + content: "—"; + margin-left: -20px; +} + +.x-govuk-sub-navigation__theme { + font-family: "GDS Transport", arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 400; + font-size: 16px; + font-size: 1rem; + line-height: 1.25; + color: #505a5f; + margin: 0; + padding: 10px 15px 10px 0; +} +@media print { + .x-govuk-sub-navigation__theme { + font-family: sans-serif; + } +} +@media (min-width: 40.0625em) { + .x-govuk-sub-navigation__theme { + font-size: 19px; + font-size: 1.1875rem; + line-height: 1.3157894737; + } +} +@media print { + .x-govuk-sub-navigation__theme { + font-size: 14pt; + line-height: 1.15; + } +} + +.app-scrollable-container { + max-height: 500px; + margin-bottom: 20px; + padding-left: 15px; + padding-right: 15px; + overflow-x: auto; + border: 1px solid rgb(169, 169, 169); + background-image: linear-gradient(to right, white, white), linear-gradient(to right, white, white), linear-gradient(to right, rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0)), linear-gradient(to left, rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0)); + background-position: left center, right center, left center, right center; + background-repeat: no-repeat; + background-color: white; + background-size: 20px 100%, 20px 100%, 10px 100%, 10px 100%; + /* Opera doesn't support this in the shorthand */ + background-attachment: local, local, scroll, scroll; + scrollbar-width: thin; + scrollbar-color: #8A8A8A #DFE9EB; + /* Chrome, Edge and Safari */ +} +.app-scrollable-container table { + margin-bottom: 20px; +} +.app-scrollable-container table th, .app-scrollable-container table td { + white-space: nowrap; +} +.app-scrollable-container table td.app-wrap { + max-width: 500px; + overflow: hidden; + text-overflow: ellipsis; +} +.app-scrollable-container table td.app-wrap .app-inset-text__value { + overflow: hidden; + text-overflow: ellipsis; +} +@media (min-width: 40.0625em) { + .app-scrollable-container { + margin-bottom: 30px; + } +} +.app-scrollable-container::-webkit-scrollbar { + height: 10px; + width: 10px; +} +.app-scrollable-container::-webkit-scrollbar-track { + border-radius: 5px; + background-color: #e8e8e8; +} +.app-scrollable-container::-webkit-scrollbar-track:hover { + background-color: #B8C0C2; +} +.app-scrollable-container::-webkit-scrollbar-track:active { + background-color: #B8C0C2; +} +.app-scrollable-container::-webkit-scrollbar-thumb { + border-radius: 0px; + background-color: #b1b4b6; +} +.app-scrollable-container::-webkit-scrollbar-thumb:hover { + background-color: #5F5F5F; +} +.app-scrollable-container::-webkit-scrollbar-thumb:active { + background-color: #474D54; +} + +.app-inset-text---error { + border-left: 5px solid #d4351c; + padding: 5px 10px; + margin: 0; + width: 500px; +} +.app-inset-text---error .app-inset-text__value { + margin-bottom: 5px; +} +.app-inset-text---error .app-inset-text__error { + color: #d4351c; + font-weight: bold; + white-space: normal; + min-width: fit-content; +} + +.app-inset-text---warning { + border-left: 5px solid #1d70b8; + padding: 5px 10px; + margin: 0; +} +.app-inset-text---warning .app-inset-text__value { + margin-bottom: 5px; +} +.app-inset-text---warning .app-inset-text__warning { + color: #1d70b8; + font-weight: bold; +} + +.app-map { + height: 500px; + margin-bottom: 20px; +} +@media (min-width: 40.0625em) { + .app-map { + margin-bottom: 30px; + } +} + +/*# sourceMappingURL=index.css.map */ diff --git a/public/stylesheets/index.css.map b/public/stylesheets/index.css.map new file mode 100644 index 00000000..72f856b1 --- /dev/null +++ b/public/stylesheets/index.css.map @@ -0,0 +1 @@ +{"version":3,"sourceRoot":"","sources":["../../node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss","../../node_modules/govuk-frontend/govuk/core/_links.scss","../../node_modules/govuk-frontend/govuk/helpers/_typography.scss","../../node_modules/govuk-frontend/govuk/settings/_typography-font.scss","../../node_modules/govuk-frontend/govuk/helpers/_links.scss","../../node_modules/govuk-frontend/govuk/helpers/_font-faces.scss","../../node_modules/govuk-frontend/govuk/vendor/_sass-mq.scss","../../node_modules/govuk-frontend/govuk/helpers/_focused.scss","../../node_modules/govuk-frontend/govuk/settings/_colours-applied.scss","../../node_modules/govuk-frontend/govuk/core/_lists.scss","../../node_modules/govuk-frontend/govuk/helpers/_spacing.scss","../../node_modules/govuk-frontend/govuk/core/_typography.scss","../../node_modules/govuk-frontend/govuk/core/_section-break.scss","../../node_modules/govuk-frontend/govuk/objects/_button-group.scss","../../node_modules/govuk-frontend/govuk/objects/_form-group.scss","../../node_modules/govuk-frontend/govuk/helpers/_clearfix.scss","../../node_modules/govuk-frontend/govuk/objects/_grid.scss","../../node_modules/govuk-frontend/govuk/helpers/_grid.scss","../../node_modules/govuk-frontend/govuk/objects/_main-wrapper.scss","../../node_modules/govuk-frontend/govuk/objects/_template.scss","../../node_modules/govuk-frontend/govuk/objects/_width-container.scss","../../node_modules/govuk-frontend/govuk/settings/_measurements.scss","../../node_modules/govuk-frontend/govuk/components/accordion/_index.scss","../../node_modules/govuk-frontend/govuk/components/back-link/_index.scss","../../node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss","../../node_modules/govuk-frontend/govuk/components/button/_index.scss","../../node_modules/govuk-frontend/govuk/components/error-message/_index.scss","../../node_modules/govuk-frontend/govuk/components/fieldset/_index.scss","../../node_modules/govuk-frontend/govuk/components/hint/_index.scss","../../node_modules/govuk-frontend/govuk/components/label/_index.scss","../../node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss","../../node_modules/govuk-frontend/govuk/components/textarea/_index.scss","../../node_modules/govuk-frontend/govuk/components/character-count/_index.scss","../../node_modules/govuk-frontend/govuk/components/cookie-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/input/_index.scss","../../node_modules/govuk-frontend/govuk/components/date-input/_index.scss","../../node_modules/govuk-frontend/govuk/components/details/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_shape-arrow.scss","../../node_modules/govuk-frontend/govuk/components/error-summary/_index.scss","../../node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss","../../node_modules/govuk-frontend/govuk/components/file-upload/_index.scss","../../node_modules/govuk-frontend/govuk/components/footer/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_device-pixels.scss","../../node_modules/govuk-frontend/govuk/components/header/_index.scss","../../node_modules/govuk-frontend/govuk/settings/_links.scss","../../node_modules/govuk-frontend/govuk/components/inset-text/_index.scss","../../node_modules/govuk-frontend/govuk/components/notification-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/pagination/_index.scss","../../node_modules/govuk-frontend/govuk/components/panel/_index.scss","../../node_modules/govuk-frontend/govuk/components/tag/_index.scss","../../node_modules/govuk-frontend/govuk/components/phase-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/tabs/_index.scss","../../node_modules/govuk-frontend/govuk/components/radios/_index.scss","../../node_modules/govuk-frontend/govuk/components/select/_index.scss","../../node_modules/govuk-frontend/govuk/components/skip-link/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss","../../node_modules/govuk-frontend/govuk/components/summary-list/_index.scss","../../node_modules/govuk-frontend/govuk/components/table/_index.scss","../../node_modules/govuk-frontend/govuk/components/warning-text/_index.scss","../../node_modules/govuk-frontend/govuk/utilities/_visually-hidden.scss","../../node_modules/govuk-frontend/govuk/overrides/_display.scss","../../node_modules/govuk-frontend/govuk/overrides/_spacing.scss","../../node_modules/govuk-frontend/govuk/overrides/_text-align.scss","../../node_modules/govuk-frontend/govuk/overrides/_typography.scss","../../node_modules/govuk-frontend/govuk/overrides/_width.scss","../../node_modules/accessible-autocomplete/src/autocomplete.css","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/autocomplete/_autocomplete.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_breadcrumbs.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_masthead.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_button.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_phase-banner.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_tag.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/primary-navigation/_primary-navigation.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/related-navigation/_related-navigation.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/sub-navigation/_sub-navigation.scss","../../src/assets/scss/_scrollable-container.scss","../../src/assets/scss/index.scss"],"names":[],"mappings":";AAAA;EAGE;;;ACDA;ECaA,aCiCkB;EDhClB;EACA;EEaA;;ACbM;AACA;EACE;EACA;EACA;EACA,KACE;EAEF;;AAGF;EACE;EACA;EACA;EACA,KACE;EAEF;;ACiMF;ELlON;IC4BE,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AHgDR;EACE,OIqDgB;;AJlDlB;EACE,OIwDwB;;AJrD1B;EACE,OI2DsB;;AJxDxB;EACE,OI8DuB;;AJzDzB;EACE,OIrBsB;;AFuJlB;EF6LF;IACE;IACA;IAKA;;;;AAtMN;EAEE,OI3K0B;;AJ8K5B;EAEE,OInNgB;;AJwNlB;EACE,OIlKsB;;;AJgMxB;EFpOA,OMnBkB;;AF8MZ;EFyCN;IFjOE,OMIsB;;;AJoOxB;EAEI;;AAIJ;EFjPA,OMnBkB;;AF8MZ;EFsDN;IF9OE,OMIsB;;;;AJ0QxB;EAEE;;AAKF;EAEE;;AAGF;EACE,OI1PsB;;;AJmUxB;EACE;;;AAxCF;EACE,OIrOgB;;AJwOlB;EACE,OIzOgB;;AJ4OlB;EACE,OI/NsB;;AJkOxB;EACE,OI5NuB;;AJiOzB;EACE,OI/SsB;;;AC3ExB;EPaA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;ECjBhB;ECqGI;EDnGJ;EACA;;AH4NI;EGlON;IP4BE,aCqDsB;;;AGiJlB;EGlON;IP+JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EGlON;IP0JM,WAZQ;IAaR,aAXU;;;AIkFV;EGlON;IP0CE,OMIsB;;;AFoLlB;EGlON;IC+GQ;;;ADtGN;EACE;;;AAIJ;EAIE;;;AAOF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;AH6LI;EG/LN;AAAA;IAKI;;;;AAIJ;EACE;;AHqLI;EGtLN;IAII;;;;AE9CJ;ETqCA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES1Id;EAEA;EDgGI;;AJ0HA;EKhON;ITwCE,OMIsB;;;AFoLlB;EKhON;IT0BE,aCqDsB;;;AGiJlB;EKhON;IT6JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKhON;ITwJM,WAZQ;IAaR,aAXU;;;AIkFV;EKhON;ID6GQ;;;;AC/FR;ETuBA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES5Hd;EAEA;EDkFI;;AJ0HA;EKlNN;IT0BE,OMIsB;;;AFoLlB;EKlNN;ITYE,aCqDsB;;;AGiJlB;EKlNN;IT+IM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKlNN;IT0IM,WAZQ;IAaR,aAXU;;;AIkFV;EKlNN;ID+FQ;;;;ACjFR;ETSA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES9Gd;EAEA;EDoEI;;AJ0HA;EKpMN;ITYE,OMIsB;;;AFoLlB;EKpMN;ITFE,aCqDsB;;;AGiJlB;EKpMN;ITiIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKpMN;IT4HM,WAZQ;IAaR,aAXU;;;AIkFV;EKpMN;IDiFQ;;;;ACnER;ETLA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EShGd;EAEA;EDsDI;;AJ0HA;EKtLN;ITFE,OMIsB;;;AFoLlB;EKtLN;IThBE,aCqDsB;;;AGiJlB;EKtLN;ITmHM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKtLN;IT8GM,WAZQ;IAaR,aAXU;;;AIkFV;EKtLN;IDmEQ;;;;ACnDR;ET/CA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESjFd;EAEA;EAEA,OHZ0B;;AF2KtB;EKtKN;IThCE,aCqDsB;;;AGiJlB;EKtKN;ITmGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKtKN;IT8FM,WAZQ;IAaR,aAXU;;;;AS1EhB;ETzDA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESvEd;EAEA;EACA,OHrB0B;;AF2KtB;EK5JN;IT1CE,aCqDsB;;;AGiJlB;EK5JN;ITyFM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK5JN;IToFM,WAZQ;IAaR,aAXU;;;AIkFV;EK5JN;IASI;;;;AAIJ;ETtEA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ES1Dd;EAEA,OHjC0B;;AF2KtB;EK/IN;ITvDE,aCqDsB;;;AGiJlB;EK/IN;IT4EM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK/IN;ITuEM,WAZQ;IAaR,aAXU;;;;ASnDhB;ETtDA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ES/Cd;EDOI;;AJ0HA;EKrIN;ITnDE,OMIsB;;;AFoLlB;EKrIN;ITjEE,aCqDsB;;;AGiJlB;EKrIN;ITkEM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKrIN;IT6DM,WAZQ;IAaR,aAXU;;;AIkFV;EKrIN;IDkBQ;;;;ACNR;ETlEA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESnCd;EDLI;;AJ0HA;EKzHN;IT/DE,OMIsB;;;AFoLlB;EKzHN;IT7EE,aCqDsB;;;AGiJlB;EKzHN;ITsDM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKzHN;ITiDM,WAZQ;IAaR,aAXU;;;AIkFV;EKzHN;IDMQ;;;;ACMR;ET9EA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESvBd;EDjBI;;AJ0HA;EK7GN;IT3EE,OMIsB;;;AFoLlB;EK7GN;ITzFE,aCqDsB;;;AGiJlB;EK7GN;IT0CM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK7GN;ITqCM,WAZQ;IAaR,aAXU;;;AIkFV;EK7GN;IDNQ;;;;ACkBR;ET1FA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESXd;ED7BI;;AJ0HA;EKjGN;ITvFE,OMIsB;;;AFoLlB;EKjGN;ITrGE,aCqDsB;;;AGiJlB;EKjGN;IT8BM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKjGN;ITyBM,WAZQ;IAaR,aAXU;;;AIkFV;EKjGN;IDlBQ;;;;AC8CR;EACE;;ALoEI;EKrEN;IAII;;;;AAIJ;AAAA;AAAA;ED7DM;;AJ0HA;EK7DN;AAAA;AAAA;IDtDQ;;;;AC4DR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;ALiDI;EKvDN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;IASI;;;;ACpLJ;EACE;EACA;;;AAeF;EFuFM;EAAA;;AJ0HA;EMjNN;IF8FQ;;;AJmHF;EMjNN;IF8FQ;;;;AErFR;EF8EM;EAAA;;AJ0HA;EMxMN;IFqFQ;;;AJmHF;EMxMN;IFqFQ;;;;AE5ER;EFqEM;EAAA;;AJ0HA;EM/LN;IF4EQ;;;AJmHF;EM/LN;IF4EQ;;;;AEjER;EACE;;;ACtCF;EH+FM;EG3EJ;EACA;EACA;EACI;EACJ;EACI;;APgMA;EOzNN;IHsGQ;;;AGtEN;EX5BF,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EWrGZ;EAGA;EACA,YA9Ba;EA+Bb;EACA;;APiLE;EOzLJ;IXbA,aCqDsB;;;AGiJlB;EOzLJ;IXsHI,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EOzLJ;IXiHI,WAZQ;IAaR,aAXU;;;AW1Fd;EACE;;AP2KE;EOzNN;IAqDI;IAEA;IAEI;IACJ;IACI;IACJ;IACI;;EAEJ;AAAA;IAEE,cAhEa;;EAmEf;IACE;;;;AC7EN;EJuGM;;AKjGN;EACE;EACA;EACA;;ATwNI;EQjON;IJ8GQ;;;AI1GN;EACE;;;AAIJ;EACE;EACA;;AAEA;EAEE;EACA;;;AEhBJ;EAEE;EACA;;ADGF;EACE;EACA;EACA;;;ACFA;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AC1B7C;EAIE;EACA;EACA;;AZsMI;EY5MN;IAYI;IACA;;;;AAWJ;AAAA;ER0DM;;AJ0HA;EYpLN;AAAA;IRiEQ;;;;AS5GR;EAGE,kBXwB6B;EWpB7B;EACG;EACK;;AAcR;EAvBF;IAwBI;;EAEA;IACE;;;AboMA;Ea/NN;IAkCI;;;;AAKJ;EAGE;EAEA,kBXV2B;;;AYyC7B;EA1DA,WCTiB;EDYjB,cCgBkB;EDflB,aCekB;;ADZlB;EAmDA;IA7CE;IACA;;;AdgMI;EcpJN;IAvCE,cCPW;IDQX,aCRW;;EDWX;IAmCF;MA7BI;MACA;;;;AdgLE;EcpJN;IArBE;IACA;;EAIA;IAgBF;MAfI;MACA;;;;;AE5DJ;EZoGM;;AJ0HA;EgB9NN;IZ2GQ;;;;AYvGR;EACE;;;AAGF;EAEE;EACA;EAEA;EACA;;;AAGF;EpBRA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EcKhB;EACA;EACA;;AhBuMI;EgB7MN;IpBOE,aCqDsB;;;AGiJlB;EgB7MN;IpB0IM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EgB7MN;IpBqIM,WAZQ;IAaR,aAXU;;;AIkFV;EgB7MN;IpBqBE,OMIsB;;;;Ac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UN;E3CcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EqClBhB;EnCsGI;EAAA;EmChGJ;EAEA;;AvCwNI;EuCnON;I3C6BE,aCqDsB;;;AGiJlB;EuCnON;I3CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EuCnON;I3C2JM,WAZQ;IAaR,aAXU;;;AIkFV;EuCnON;I3C2CE,OMIsB;;;AFoLlB;EuCnON;InCgHQ;;;AJmHF;EuCnON;InCgHQ;;;AmCnGN;EACE;;AAGF;AAAA;EAEE;;;ACnBJ;E5CcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EQxCV;EoCrGJ;EAEA,kBtCQiB;;AFqNb;EwCnON;I5C6BE,aCqDsB;;;AGiJlB;EwCnON;I5CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwCnON;I5C2JM,WAZQ;IAaR,aAXU;;;AIkFV;EwCnON;IpCgHQ;;;AoCxGN;EACE;;;AAIJ;EACE;EAGA;;AxCkNI;EwCtNN;IAOI;;;;AAIJ;E5CVA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;E4CtHd;EAEA;EAEA;;AxCoMI;EwC3MN;I5CKE,aCqDsB;;;AGiJlB;EwC3MN;I5CwIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwC3MN;I5CmIM,WAZQ;IAaR,aAXU;;;;A4C/GhB;E5CMA,OMnBkB;EsCgBhB;EAEA,kBtCD2B;;AF6LvB;EwCjMN;I5CSE,OMIsB;;;AFoLlB;EwCjMN;IAQI,SAPe;;;AAYjB;EAGE;EAOA;;AAGF;EACE;;;AAIJ;E5CnDA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;E4C7Ed;EAEA;;AxC6JI;EwClKN;I5CpCE,aCqDsB;;;AGiJlB;EwClKN;I5C+FM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwClKN;I5C0FM,WAZQ;IAaR,aAXU;;;;A4CxEhB;E5C3DA,aCiCkB;EDhClB;EACA;EEaA;;AEsM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nDE;EAEA;EAEA;EACA;EAEA;EACA;EACA;EAQA;EACA;EAEA;EACA;EAEA;EACA;EAEA;EAIA;EACI;EACI;EAIR;;ApDkLI;EoDzNN;IxDmBE,aCqDsB;;;AGiJlB;EoDzNN;IAeI;;;AA0BF;EAzCF;IA0CI;IACA;IACA;;;;AAIJ;ExD5CA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EkDwChB;EACA;;ApDqKI;EoDzKN;IxD7BE,aCqDsB;;;AGiJlB;EoDzKN;IxDsGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EoDzKN;IxDiGM,WAZQ;IAaR,aAXU;;;AIkFV;EoDzKN;IxDfE,OMIsB;;;;AOvCxB;EACE;EACA;EACA;;;A4CXF;EJeA;EAcA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAKA;;AAzBA;EACE;;AAGF;EACE;;;AItBF;EJyDA;EAEA;EACA;EAGA;EAEA;EACA;EACA;EACQ;EAKR;;AAEA;EAEE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACQ;EAER;;;AK3FF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AtDqNI;EsDjNJ;IACE;;;ACuBF;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDhCN;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;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CE;AAAA;AAAA;IAGE;IACA;;;AChKJ;EACE,a/D4CkB;;;A+DzCpB;EACE;;;AAKA;EACE,c1DwEiB;;A0DrEnB;EACE,c1D+FwB;;;A0D3F5B;EAGE;EAEA;;;AC3BF;EzD0GQ;EAAA;EyDvGN;EACA,OCFwB;EDGxB;;A7D+NM;E6DpOR;IzDiHU;;;AyD1GR;EACE,cCNsB;;ADSxB;EACE;;;AERJ;AAAA;AAAA;E3DsGQ;E2DlGN,O7DOmB;E6DNnB,kBDPwB;ECQxB;EACA;;A/DyNM;E+DhOR;AAAA;AAAA;I3D6GU;;;;A2DnGV;EACE;EACA,kBAd+C;;;AAiBjD;EACE,O7DyDwB;E6DxDxB,kB7D8CmB;;;A6D3CrB;AAAA;EAEE,c7DyCmB;E6DxCnB,O7DZmB;E6DanB,kBA1B+C;EA2B/C;;;AC7BF;EACE;;AAEA;EACE,OFFsB;;;AGF1B;EACE,O/DcmB;E+DbnB;;;AHOF;E1DiGQ;E0D/FN;EACA,OAVwB;EAWxB,kB5DEmB;E4DDnB;;A9DsNM;E8D3NR;I1DwGU;;;;A0DhGV;ElEFE,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EQxCV;E0DtFN;;A9DgNM;E8DnNR;IlEaI,aCqDsB;;;AGiJlB;E8DnNR;IlEgJQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8DnNR;IlE2IQ,WAZQ;IAaR,aAXU;;;AIkFV;E8DnNR;I1DgGU;;;;A0D1FV;ElERE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EkEzHhB;EACA;;A9D0MM;E8D7MR;IlEOI,aCqDsB;;;AGiJlB;E8D7MR;IlE0IQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8D7MR;IlEqIQ,WAZQ;IAaR,aAXU;;;AkEtHhB;EACE;;;AAIJ;E1DyEQ;;AJ0HA;E8DnMR;I1DgFU;;;A0D7ER;EACE;;A9D+LI;E8DnMR;IAQI;;;;AAKF;ElE/BA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;E8DtLN;IlEhBE,aCqDsB;;;AGiJlB;E8D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","file":"index.css"} \ No newline at end of file diff --git a/src/filters/filters.js b/src/filters/filters.js new file mode 100644 index 00000000..7c71e85f --- /dev/null +++ b/src/filters/filters.js @@ -0,0 +1,9 @@ +import xGovFilters from '@x-govuk/govuk-prototype-filters' + +const { govukMarkdown } = xGovFilters + +const addFilters = (nunjucksEnv) => { + nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) +} + +export default addFilters diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index 3942e730..c4f9fa98 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,6 +1,8 @@ export default { '/start': { - + entryPoint: true, + resetJourney: true, + template: '../views/start.html', + noPost: true } - } diff --git a/src/serverSetup/middlewares.js b/src/serverSetup/middlewares.js new file mode 100644 index 00000000..65c76327 --- /dev/null +++ b/src/serverSetup/middlewares.js @@ -0,0 +1,34 @@ +import express from 'express' +import bodyParser from 'body-parser' +import cookieParser from 'cookie-parser' +// import logger from '../utils/logger.js' +// import hash from '../utils/hasher.js' +// import config from '../../config/index.js' + +export function setupMiddlewares (app) { + // app.use(async (req, res, next) => { + // logger.info({ + // type: 'Request', + // method: req.method, + // endpoint: req.originalUrl, + // message: `${req.method} request made to ${req.originalUrl}`, + // sessionId: await hash(req.sessionID) + // }) + // next() + // }) + + app.use('/assets', express.static('./node_modules/govuk-frontend/govuk/assets')) + app.use('/public', express.static('./public')) + + app.use(cookieParser()) + app.use(bodyParser.urlencoded({ extended: true })) + + // app.use((req, res, next) => { + // const serviceDown = config.maintenance.serviceUnavailable || false + // if (serviceDown) { + // res.status(503).render('errorPages/503', { upTime: config.maintenance.upTime }) + // } else { + // next() + // } + // }) +} diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js new file mode 100644 index 00000000..0b25f66f --- /dev/null +++ b/src/serverSetup/nunjucks.js @@ -0,0 +1,27 @@ +import nunjucks from 'nunjucks' +// import config from '../../config/index.js' +import addFilters from '../filters/filters.js' + +export function setupNunjucks (app) { + app.set('view engine', 'html') + const nunjucksEnv = nunjucks.configure([ + 'src/views', + 'node_modules/govuk-frontend/dist/', + 'node_modules/@x-govuk/govuk-prototype-components/' + ], { + express: app, + dev: true, + noCache: true, + watch: true + }) + + const globalValues = { + serviceName: 'Endpoint Submission Form',//config.serviceName, + feedbackLink: '#',//config.feedbackLink + } + + Object.keys(globalValues).forEach((key) => { + nunjucksEnv.addGlobal(key, globalValues[key]) + }) + addFilters(nunjucksEnv) +} diff --git a/src/serverSetup/setupSession.js b/src/serverSetup/setupSession.js new file mode 100644 index 00000000..e75f139a --- /dev/null +++ b/src/serverSetup/setupSession.js @@ -0,0 +1,32 @@ +import session from 'express-session' +// import { createClient } from 'redis' +// import RedisStore from 'connect-redis' +import cookieParser from 'cookie-parser' +// import config from '../../config/index.js' +// import logger from '../utils/logger.js' + +export function setupSession (app) { + app.use(cookieParser()) + let sessionStore + // if (config.redis) { + // const urlPrefix = `redis${config.redis.secure ? 's' : ''}` + // const redisClient = createClient({ + // url: `${urlPrefix}://${config.redis.host}:${config.redis.port}` + // }) + // redisClient.connect().catch(logger.error) + + // sessionStore = new RedisStore({ + // client: redisClient + // }) + // } + app.use(session({ + secret: process.env.SESSION_SECRET || 'keyboard cat', + resave: false, + saveUninitialized: false, + store: sessionStore, + cookie: { + secure: false, + maxAge: 1000 * 60 * 60 * 24 * 7 + } + })) +} diff --git a/src/views/layouts/main.html b/src/views/layouts/main.html new file mode 100644 index 00000000..17acfa65 --- /dev/null +++ b/src/views/layouts/main.html @@ -0,0 +1,75 @@ +{# +For guidance on how to use layouts see: +https://prototype-kit.service.gov.uk/docs/how-to-use-layouts +#} + +{% extends "govuk/template.njk" %} +{% from 'govuk/components/header/macro.njk' import govukHeader%} +{% from 'govuk/components/footer/macro.njk' import govukFooter%} +{% from 'govuk/components/phase-banner/macro.njk' import govukPhaseBanner%} +{% from 'govuk/components/back-link/macro.njk' import govukBackLink %} + +{% block pageTitle %} + {{ pageName }} - {{ serviceName }} +{% endblock %} + +{% block head %} + +{% endblock %} + +{% block header %} + {{ govukHeader({ + homepageUrl: "#", + serviceName: serviceName, + serviceUrl: "/" + }) }} + {{ govukPhaseBanner({ + tag: { + text: "Beta" + }, + html: 'This is a new service – your feedback will help us to improve it.', + classes: 'govuk-width-container' + }) }} + +{% endblock %} + +{% block beforeContent %} + {% if options.lastPage %} + {{ govukBackLink({ + text: "Back", + href: options.lastPage + }) }} + {% endif %} +{% endblock %} + +{% block footer %} +{% set footerHtml %} +

Get help

+ +

Email: digitalland@levellingup.gov.uk
+ You’ll get a response within 5 working days.

+ +
+ + {% endset %} + + {{ govukFooter({ + meta: { + html: footerHtml + } + }) }} +{% endblock %} + +{% block bodyEnd %} + {{ super()}} + {%block scripts %} + {{ super() }} + + {% endblock %} +{% endblock %} \ No newline at end of file diff --git a/src/views/start.html b/src/views/start.html index d8a3f634..0e32eefb 100644 --- a/src/views/start.html +++ b/src/views/start.html @@ -1,4 +1,6 @@ {% extends "layouts/main.html" %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "x-govuk/components/related-navigation/macro.njk" import xGovukRelatedNavigation %} {% set pageName = serviceName %} @@ -47,7 +49,7 @@

- {{content | govukMarkdown(headingsStartWith="l")}} + {{content | govukMarkdown(headingsStartWith="l") | safe}}
{{ xGovukRelatedNavigation({ From 90d445e1a4f454aa36bfd89ba4c90a9b2ab4c892 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 13:23:57 +0100 Subject: [PATCH 031/127] linting --- index.js | 1 - src/serverSetup/nunjucks.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 860e91aa..3d2780c2 100644 --- a/index.js +++ b/index.js @@ -12,7 +12,6 @@ setupRoutes(app) setupNunjucks(app) setupMiddlewares(app) - app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`) }) diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 0b25f66f..94a3467a 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -16,8 +16,8 @@ export function setupNunjucks (app) { }) const globalValues = { - serviceName: 'Endpoint Submission Form',//config.serviceName, - feedbackLink: '#',//config.feedbackLink + serviceName: 'Endpoint Submission Form', // config.serviceName, + feedbackLink: '#'// config.feedbackLink } Object.keys(globalValues).forEach((key) => { From 47971edcbf3ed395fe2fa96de66efbfd9fe55622 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 14:12:40 +0100 Subject: [PATCH 032/127] added the basics of all other pages --- index.js | 4 +- src/controllers/chooseDatasetController.js | 18 +++ src/controllers/pageController.js | 17 +++ src/routes/form-wizard/fields.js | 13 +- src/routes/form-wizard/steps.js | 35 ++++- src/utils/utils.js | 80 ++++++++++ src/views/check-answers.html | 169 +++++++++++++++++++++ src/views/choose-dataset.html | 44 ++++++ src/views/confirmation.html | 38 +++++ src/views/dataset-details.html | 79 ++++++++++ src/views/endpoint-submitted.html | 42 +++++ src/views/lpa-details.html | 73 +++++++++ src/views/start.html | 2 +- 13 files changed, 608 insertions(+), 6 deletions(-) create mode 100644 src/controllers/chooseDatasetController.js create mode 100644 src/controllers/pageController.js create mode 100644 src/utils/utils.js create mode 100644 src/views/check-answers.html create mode 100644 src/views/choose-dataset.html create mode 100644 src/views/confirmation.html create mode 100644 src/views/dataset-details.html create mode 100644 src/views/endpoint-submitted.html create mode 100644 src/views/lpa-details.html diff --git a/index.js b/index.js index 3d2780c2..c2d8ad43 100644 --- a/index.js +++ b/index.js @@ -7,10 +7,10 @@ import { setupMiddlewares } from './src/serverSetup/middlewares.js' const app = express() const port = 3000 +setupMiddlewares(app) setupSession(app) -setupRoutes(app) setupNunjucks(app) -setupMiddlewares(app) +setupRoutes(app) app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`) diff --git a/src/controllers/chooseDatasetController.js b/src/controllers/chooseDatasetController.js new file mode 100644 index 00000000..3e2d431a --- /dev/null +++ b/src/controllers/chooseDatasetController.js @@ -0,0 +1,18 @@ +import PageController from "./pageController.js"; + +import { dataSubjects } from "../utils/utils.js"; + +class ChooseDatasetController extends PageController { + locals (req, res, next) { + const availableDataSubjects = Object.values(dataSubjects).filter(dataSubject => dataSubject.available) + const dataSets = Object.values(availableDataSubjects).map(dataSubject => dataSubject.dataSets).flat() + const availableDatasets = dataSets.filter(dataSet => dataSet.available) + availableDatasets.sort((a, b) => a.text.localeCompare(b.text)) + + req.form.options.datasetItems = availableDatasets + + super.locals(req, res, next) + } +} + +export default ChooseDatasetController \ No newline at end of file diff --git a/src/controllers/pageController.js b/src/controllers/pageController.js new file mode 100644 index 00000000..21c53e38 --- /dev/null +++ b/src/controllers/pageController.js @@ -0,0 +1,17 @@ +import hmpoFormWizard from 'hmpo-form-wizard' +// import { logPageView } from '../utils/logging.js' +const { Controller } = hmpoFormWizard + +class PageController extends Controller { + configure (req, res, callback) { + req.form.options.lastPage = this.options.backLink ? this.options.backLink : undefined + super.configure(req, res, callback) + } + + get (req, res, next) { + // logPageView(this.options.route, req.sessionID, req.ip) + super.get(req, res, next) + } +} + +export default PageController diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index 03048022..05cab646 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -1,3 +1,14 @@ export default { - + 'lpa': { + // validate: ['required'], + }, + 'name': { + // validate: ['required'], + }, + 'email': { + // validate: ['required'], + }, + 'dataset': { + // validate: ['required'], + } } diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index c4f9fa98..b354840d 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,8 +1,39 @@ +import chooseDatasetController from '../../controllers/chooseDatasetController.js' + +const defaultParams = { + entryPoint: true // needs changing before production +} + export default { '/start': { + ...defaultParams, entryPoint: true, resetJourney: true, - template: '../views/start.html', - noPost: true + noPost: true, + next: 'lpa-details' + }, + '/lpa-details': { + ...defaultParams, + fields: ['lpa', 'name', 'email'], + next: 'choose-dataset' + }, + '/choose-dataset': { + ...defaultParams, + fields: ['dataset'], + next: 'dataset-details', + controller: chooseDatasetController + }, + '/dataset-details': { + ...defaultParams, + fields: ['endpoint-url', 'documentation-url', 'hasLicense'], + next: 'check-answers' + }, + '/check-answers': { + ...defaultParams, + next: 'confirmation' + }, + '/confirmation': { + ...defaultParams, + } } diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 00000000..3e4b00e4 --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,80 @@ +export const severityLevels = { + notice: 'notice', + informational: 'info', + warning: 'warning', + error: 'error' + } + + export const dataSubjects = { + 'article-4-direction': { + available: true, + dataSets: [ + { + value: 'article-4-direction', + text: 'Article 4 direction dataset', + available: true + }, + { + value: 'article-4-direction-area', + text: 'Article 4 direction area dataset', + available: true + } + ] + }, + 'conservation-area': { + available: true, + dataSets: [ + { + value: 'conservation-area', + text: 'Conservation area dataset', + available: true + }, + { + value: 'conservation-area-document', + text: 'Conservation area document dataset', + available: true + } + ] + }, + 'tree-preservation-order': { + available: true, + dataSets: [ + { + value: 'tree-preservation-order', + text: 'Tree preservation order dataset', + available: true + }, + { + value: 'tree-preservation-zone', + text: 'Tree preservation zone dataset', + available: true + }, + { + value: 'tree', + text: 'Tree dataset', + available: true, + requiresGeometryTypeSelection: true + } + ] + }, + 'listed-building': { + available: true, + dataSets: [ + { + value: 'listed-building', + text: 'Listed building', + available: false + }, + { + value: 'listed-building-outline', + text: 'Listed building outline', + available: true + }, + { + value: 'listed-building-grade', + text: 'Listed building grade', + available: false + } + ] + } + } \ No newline at end of file diff --git a/src/views/check-answers.html b/src/views/check-answers.html new file mode 100644 index 00000000..5ca56ee6 --- /dev/null +++ b/src/views/check-answers.html @@ -0,0 +1,169 @@ +{% extends "layouts/main.html" %} + +{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %} +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/back-link/macro.njk" import govukBackLink %} + +{% block pageTitle %} +Check your answers template – {{ serviceName }} – GOV.UK Prototype Kit +{% endblock %} + +{% block beforeContent %} +{{ govukBackLink({ + text: "Back", + href: "javascript:window.history.back()" +}) }} +{% endblock %} + +{% block content %} +
+
+ +

+ Check your answers before sending your application +

+ + {{ govukSummaryList({ + rows: [ + { + key: { + text: "Local planning authority" + }, + value: { + text: data['lpa'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/lpa-details", + text: "Change", + visuallyHiddenText: "local planning authority" + } + ] + } + }, + { + key: { + text: "Full name" + }, + value: { + text: data['fullName'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/lpa-details", + text: "Change", + visuallyHiddenText: "full name" + } + ] + } + }, + { + key: { + text: "Email address" + }, + value: { + text: data['emailAddress'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/lpa-details", + text: "Change", + visuallyHiddenText: "email address" + } + ] + } + }, + { + key: { + text: "Dataset" + }, + value: { + text: data['dataset'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/choose-dataset", + text: "Change", + visuallyHiddenText: "dataset" + } + ] + } + }, + { + key: { + text: "Dataset URL" + }, + value: { + text: data['datasetUrl'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/dataset-details", + text: "Change", + visuallyHiddenText: "dataset URL" + } + ] + } + }, + { + key: { + text: "Documentation URL" + }, + value: { + text: data['documentationUrl'] + }, + actions: { + items: [ + { + href: "/submit-endpoint/dataset-details", + text: "Change", + visuallyHiddenText: "documentation URL" + } + ] + } + }, + { + key: { + text: "Dataset provided under Open Government Licence?" + }, + value: { + text: "True" if data['licence'] == "true" else "False" + }, + actions: { + items: [ + { + href: "/submit-endpoint/choose-dataset", + text: "Change", + visuallyHiddenText: "dataset" + } + ] + } + } + + ] + }) }} + +

+ Submit your dataset +

+ +

+ Check everything above is correct and click below to submit your dataset. +

+ +
+ + {{ govukButton({ + text: "Submit dataset" + }) }} + + + +
+
+{% endblock %} \ No newline at end of file diff --git a/src/views/choose-dataset.html b/src/views/choose-dataset.html new file mode 100644 index 00000000..04b7f8a0 --- /dev/null +++ b/src/views/choose-dataset.html @@ -0,0 +1,44 @@ +{% extends "layouts/main.html" %} + +{% from "govuk/components/radios/macro.njk" import govukRadios %} +{% from "govuk/components/button/macro.njk" import govukButton %} + +{% set pageName = "Choose dataset" %} + +{% block beforeContent %} +{{ govukBackLink({ + text: "Back", + href: "javascript:window.history.back()" +}) }} +{% endblock %} + +{% block content %} + +
+
+ +
+ + {{ govukRadios({ + idPrefix: "dataset", + name: "dataset", + fieldset: { + legend: { + text: pageName, + isPageHeading: true, + classes: "govuk-fieldset__legend--l" + } + }, + items: options.datasetItems, + value: data.dataset + }) }} + + {{ govukButton({ + text: "Continue" + }) }} + + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/views/confirmation.html b/src/views/confirmation.html new file mode 100644 index 00000000..a410f2f8 --- /dev/null +++ b/src/views/confirmation.html @@ -0,0 +1,38 @@ +{% extends "layouts/main.html" %} + +{% from "govuk/components/panel/macro.njk" import govukPanel %} + +{% set pageName = data['dataset'] + " submitted" %} + +{% block content %} + +{% set content %} + +## What happens next + +We will process your submission and add your dataset to the [planning data platform](https://www.planning.data.gov.uk/). + +Your dataset should appear on the platform within 5 working days. + +If there are any issues processing your data will we contact you on the email address you provided. + +[Add another dataset](/submit-endpoint/start) + +## Give feedback + +[Give feedback about this service](/feedback) (takes 30 seconds). + +{% endset %} + +
+
+ {{ govukPanel({ + titleHtml: pageName + }) }} + + {{content | govukMarkdown(headingsStartWith="l") | safe}} + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/views/dataset-details.html b/src/views/dataset-details.html new file mode 100644 index 00000000..610c8d1f --- /dev/null +++ b/src/views/dataset-details.html @@ -0,0 +1,79 @@ +{% extends "layouts/main.html" %} + +{% from "govuk/components/input/macro.njk" import govukInput %} +{% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %} +{% from "govuk/components/button/macro.njk" import govukButton %} + +{% set pageName = data['dataset'] + " details" %} + +{% block beforeContent %} +{{ govukBackLink({ + text: "Back", + href: "javascript:window.history.back()" +}) }} +{% endblock %} + +{% block content %} + +
+
+ +

+ {{ pageName }} +

+ +
+ + {{ govukInput({ + label: { + text: "Endpoint URL", + classes: "govuk-label--m", + isPageHeading: false + }, + id: "endpoint-url", + name: "endpoint-url", + classes: "govuk-!-width-three-quarters" + }) }} + + {{ govukInput({ + label: { + text: "Documentation URL", + classes: "govuk-label--m", + isPageHeading: false + }, + hint: { + text: "Publicly accessible page on your website with information about the data" + }, + id: "documentation-url", + name: "documentation-url", + classes: "govuk-!-width-three-quarters" + }) }} + + {{ govukCheckboxes({ + name: "licence", + fieldset: { + legend: { + text: "Dataset licence", + isPageHeading: false, + classes: "govuk-fieldset__legend--m" + } + }, + items: [ + { + value: "true", + text: "I confirm this dataset is provided under the Open Government Licence", + name: "hasLicence" + } + ] + }) }} + + {{ govukButton({ + text: "Continue" + }) }} + + + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/views/endpoint-submitted.html b/src/views/endpoint-submitted.html new file mode 100644 index 00000000..8bd8f3f4 --- /dev/null +++ b/src/views/endpoint-submitted.html @@ -0,0 +1,42 @@ +{% extends "layouts/main.html" %} + +{% block pageTitle %} + Confirmation page template – {{ serviceName }} – GOV.UK Prototype Kit +{% endblock %} + +{% block content %} + +
+
+ + {{ govukPanel({ + titleText: "Application complete", + html: "Your reference number
HDJ2123F" + }) }} + +

+ We have sent you a confirmation email. +

+ +

+ What happens next +

+ +

+ We've sent your application to Hackney Electoral Register Office. +

+ +

+ They will contact you either to confirm your registration, or to ask for more information. +

+

+ + What did you think of this service? + (takes 30 seconds) +

+ + +
+
+ +{% endblock %} diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html new file mode 100644 index 00000000..657da0e9 --- /dev/null +++ b/src/views/lpa-details.html @@ -0,0 +1,73 @@ +{% extends "layouts/main.html" %} + +{% from "govuk/components/input/macro.njk" import govukInput %} +{% from "govuk/components/button/macro.njk" import govukButton %} + +{% block pageTitle %} +Question page template – {{ serviceName }} – GOV.UK Prototype Kit +{% endblock %} + +{% block beforeContent %} +{{ govukBackLink({ + text: "Back", + href: "javascript:window.history.back()" +}) }} +{% endblock %} + +{% block content %} + +
+
+ +

+ Which LPA are you submitting data for? +

+ +
+ + {{ + govukInput({ + label: { + text: "Local planning authority", + classes: "govuk-label--m", + isPageHeading: false + }, + id: "lpa", + name: "lpa", + classes: "govuk-!-width-three-quarters" + }) + }} + + {{ govukInput({ + label: { + text: "Full name", + classes: "govuk-label--m", + isPageHeading: false + }, + id: "name", + name: "name", + classes: "govuk-!-width-three-quarters" + }) }} + + + {{ govukInput({ + label: { + text: "Email address", + classes: "govuk-label--m", + isPageHeading: false + }, + id: "email", + name: "email", + classes: "govuk-!-width-three-quarters" + }) }} + + {{ govukButton({ + text: "Continue" + }) }} + + + +
+
+ +{% endblock %} \ No newline at end of file diff --git a/src/views/start.html b/src/views/start.html index 0e32eefb..5c6e6944 100644 --- a/src/views/start.html +++ b/src/views/start.html @@ -33,7 +33,7 @@ {{ govukButton({ text: "Start now", - href: "/submit-endpoint/lpa-details", + href: "lpa-details", isStartButton: true }) }} From 206bb543237b602f3cf95972ef70e763397d7e63 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 14:12:50 +0100 Subject: [PATCH 033/127] linting --- src/controllers/chooseDatasetController.js | 26 ++-- src/routes/form-wizard/fields.js | 24 ++-- src/routes/form-wizard/steps.js | 6 +- src/utils/utils.js | 156 ++++++++++----------- 4 files changed, 106 insertions(+), 106 deletions(-) diff --git a/src/controllers/chooseDatasetController.js b/src/controllers/chooseDatasetController.js index 3e2d431a..71480192 100644 --- a/src/controllers/chooseDatasetController.js +++ b/src/controllers/chooseDatasetController.js @@ -1,18 +1,18 @@ -import PageController from "./pageController.js"; +import PageController from './pageController.js' -import { dataSubjects } from "../utils/utils.js"; +import { dataSubjects } from '../utils/utils.js' class ChooseDatasetController extends PageController { - locals (req, res, next) { - const availableDataSubjects = Object.values(dataSubjects).filter(dataSubject => dataSubject.available) - const dataSets = Object.values(availableDataSubjects).map(dataSubject => dataSubject.dataSets).flat() - const availableDatasets = dataSets.filter(dataSet => dataSet.available) - availableDatasets.sort((a, b) => a.text.localeCompare(b.text)) - - req.form.options.datasetItems = availableDatasets - - super.locals(req, res, next) - } + locals (req, res, next) { + const availableDataSubjects = Object.values(dataSubjects).filter(dataSubject => dataSubject.available) + const dataSets = Object.values(availableDataSubjects).map(dataSubject => dataSubject.dataSets).flat() + const availableDatasets = dataSets.filter(dataSet => dataSet.available) + availableDatasets.sort((a, b) => a.text.localeCompare(b.text)) + + req.form.options.datasetItems = availableDatasets + + super.locals(req, res, next) + } } -export default ChooseDatasetController \ No newline at end of file +export default ChooseDatasetController diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index 05cab646..0fd7e639 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -1,14 +1,14 @@ export default { - 'lpa': { - // validate: ['required'], - }, - 'name': { - // validate: ['required'], - }, - 'email': { - // validate: ['required'], - }, - 'dataset': { - // validate: ['required'], - } + lpa: { + // validate: ['required'], + }, + name: { + // validate: ['required'], + }, + email: { + // validate: ['required'], + }, + dataset: { + // validate: ['required'], + } } diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index b354840d..98e0f8bb 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -11,7 +11,7 @@ export default { resetJourney: true, noPost: true, next: 'lpa-details' - }, + }, '/lpa-details': { ...defaultParams, fields: ['lpa', 'name', 'email'], @@ -33,7 +33,7 @@ export default { next: 'confirmation' }, '/confirmation': { - ...defaultParams, - + ...defaultParams + } } diff --git a/src/utils/utils.js b/src/utils/utils.js index 3e4b00e4..8dda1dc8 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -1,80 +1,80 @@ export const severityLevels = { - notice: 'notice', - informational: 'info', - warning: 'warning', - error: 'error' + notice: 'notice', + informational: 'info', + warning: 'warning', + error: 'error' +} + +export const dataSubjects = { + 'article-4-direction': { + available: true, + dataSets: [ + { + value: 'article-4-direction', + text: 'Article 4 direction dataset', + available: true + }, + { + value: 'article-4-direction-area', + text: 'Article 4 direction area dataset', + available: true + } + ] + }, + 'conservation-area': { + available: true, + dataSets: [ + { + value: 'conservation-area', + text: 'Conservation area dataset', + available: true + }, + { + value: 'conservation-area-document', + text: 'Conservation area document dataset', + available: true + } + ] + }, + 'tree-preservation-order': { + available: true, + dataSets: [ + { + value: 'tree-preservation-order', + text: 'Tree preservation order dataset', + available: true + }, + { + value: 'tree-preservation-zone', + text: 'Tree preservation zone dataset', + available: true + }, + { + value: 'tree', + text: 'Tree dataset', + available: true, + requiresGeometryTypeSelection: true + } + ] + }, + 'listed-building': { + available: true, + dataSets: [ + { + value: 'listed-building', + text: 'Listed building', + available: false + }, + { + value: 'listed-building-outline', + text: 'Listed building outline', + available: true + }, + { + value: 'listed-building-grade', + text: 'Listed building grade', + available: false + } + ] } - - export const dataSubjects = { - 'article-4-direction': { - available: true, - dataSets: [ - { - value: 'article-4-direction', - text: 'Article 4 direction dataset', - available: true - }, - { - value: 'article-4-direction-area', - text: 'Article 4 direction area dataset', - available: true - } - ] - }, - 'conservation-area': { - available: true, - dataSets: [ - { - value: 'conservation-area', - text: 'Conservation area dataset', - available: true - }, - { - value: 'conservation-area-document', - text: 'Conservation area document dataset', - available: true - } - ] - }, - 'tree-preservation-order': { - available: true, - dataSets: [ - { - value: 'tree-preservation-order', - text: 'Tree preservation order dataset', - available: true - }, - { - value: 'tree-preservation-zone', - text: 'Tree preservation zone dataset', - available: true - }, - { - value: 'tree', - text: 'Tree dataset', - available: true, - requiresGeometryTypeSelection: true - } - ] - }, - 'listed-building': { - available: true, - dataSets: [ - { - value: 'listed-building', - text: 'Listed building', - available: false - }, - { - value: 'listed-building-outline', - text: 'Listed building outline', - available: true - }, - { - value: 'listed-building-grade', - text: 'Listed building grade', - available: false - } - ] - } - } \ No newline at end of file +} From 6cc726e12ec16a648f637257c0165329020528a2 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 15:50:25 +0100 Subject: [PATCH 034/127] get the check-answers page showing the correct answers --- src/filters/filters.js | 17 +++++++++++++++++ src/routes/form-wizard/fields.js | 9 +++++++++ src/routes/form-wizard/steps.js | 4 ++-- src/views/check-answers.html | 14 +++++++------- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/filters/filters.js b/src/filters/filters.js index 7c71e85f..aed9f8ef 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -4,6 +4,23 @@ const { govukMarkdown } = xGovFilters const addFilters = (nunjucksEnv) => { nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) + + // some additional filters useful for debugging: + nunjucksEnv.addFilter('getkeys', function (object) { + if (Object.prototype.toString.call(object) === '[object Array]') { + let keys = []; + for (let i = object.length - 1; i >= 0; i--) { + keys.push(Object.keys(object[i])); + } + return keys; + } else { + return Object.keys(object); + } +}); + + nunjucksEnv.addGlobal('getContext', function () { + return this.ctx + }) } export default addFilters diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index 0fd7e639..2307642d 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -10,5 +10,14 @@ export default { }, dataset: { // validate: ['required'], + }, + 'endpoint-url': { + // validate: ['required'], + }, + 'documentation-url': { + // validate: ['required'], + }, + hasLicence: { + // validate: ['required'], } } diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index 98e0f8bb..3aee7a17 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,7 +1,7 @@ import chooseDatasetController from '../../controllers/chooseDatasetController.js' const defaultParams = { - entryPoint: true // needs changing before production + entryPoint: false // needs changing before production } export default { @@ -25,7 +25,7 @@ export default { }, '/dataset-details': { ...defaultParams, - fields: ['endpoint-url', 'documentation-url', 'hasLicense'], + fields: ['endpoint-url', 'documentation-url', 'hasLicence'], next: 'check-answers' }, '/check-answers': { diff --git a/src/views/check-answers.html b/src/views/check-answers.html index 5ca56ee6..61335321 100644 --- a/src/views/check-answers.html +++ b/src/views/check-answers.html @@ -30,7 +30,7 @@

text: "Local planning authority" }, value: { - text: data['lpa'] + text: values['lpa'] }, actions: { items: [ @@ -47,7 +47,7 @@

text: "Full name" }, value: { - text: data['fullName'] + text: values['name'] }, actions: { items: [ @@ -64,7 +64,7 @@

text: "Email address" }, value: { - text: data['emailAddress'] + text: values['email'] }, actions: { items: [ @@ -81,7 +81,7 @@

text: "Dataset" }, value: { - text: data['dataset'] + text: values['dataset'] }, actions: { items: [ @@ -98,7 +98,7 @@

text: "Dataset URL" }, value: { - text: data['datasetUrl'] + text: values['endpoint-url'] }, actions: { items: [ @@ -115,7 +115,7 @@

text: "Documentation URL" }, value: { - text: data['documentationUrl'] + text: values['documentation-url'] }, actions: { items: [ @@ -132,7 +132,7 @@

text: "Dataset provided under Open Government Licence?" }, value: { - text: "True" if data['licence'] == "true" else "False" + text: "True" if values['hasLicence'] == "true" else "False" }, actions: { items: [ From 23adfc6975748ebb038f5db5cc1118fa0a50b4a5 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 15:50:31 +0100 Subject: [PATCH 035/127] linting --- src/filters/filters.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/filters/filters.js b/src/filters/filters.js index aed9f8ef..7aa6f35d 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -6,17 +6,17 @@ const addFilters = (nunjucksEnv) => { nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) // some additional filters useful for debugging: - nunjucksEnv.addFilter('getkeys', function (object) { + nunjucksEnv.addFilter('getkeys', function (object) { if (Object.prototype.toString.call(object) === '[object Array]') { - let keys = []; - for (let i = object.length - 1; i >= 0; i--) { - keys.push(Object.keys(object[i])); - } - return keys; + const keys = [] + for (let i = object.length - 1; i >= 0; i--) { + keys.push(Object.keys(object[i])) + } + return keys } else { - return Object.keys(object); + return Object.keys(object) } -}); + }) nunjucksEnv.addGlobal('getContext', function () { return this.ctx From eb73d9745ba998a6dd834290b9e391732dad96b1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 15:54:22 +0100 Subject: [PATCH 036/127] updated the dataset details and confirmation pages so that they correctly show the dataset --- src/views/confirmation.html | 2 +- src/views/dataset-details.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/confirmation.html b/src/views/confirmation.html index a410f2f8..33ec005b 100644 --- a/src/views/confirmation.html +++ b/src/views/confirmation.html @@ -2,7 +2,7 @@ {% from "govuk/components/panel/macro.njk" import govukPanel %} -{% set pageName = data['dataset'] + " submitted" %} +{% set pageName = values['dataset'] + " submitted" %} {% block content %} diff --git a/src/views/dataset-details.html b/src/views/dataset-details.html index 610c8d1f..e9a3015c 100644 --- a/src/views/dataset-details.html +++ b/src/views/dataset-details.html @@ -4,7 +4,7 @@ {% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %} {% from "govuk/components/button/macro.njk" import govukButton %} -{% set pageName = data['dataset'] + " details" %} +{% set pageName = values['dataset'] + " details" %} {% block beforeContent %} {{ govukBackLink({ From 7ed23451b24cd8800db0c73a4879b55095f038be Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 15:57:46 +0100 Subject: [PATCH 037/127] make sure back links are setup --- src/routes/form-wizard/steps.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index 3aee7a17..b5ec2e10 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,7 +1,9 @@ import chooseDatasetController from '../../controllers/chooseDatasetController.js' +import PageController from '../../controllers/pageController.js' const defaultParams = { - entryPoint: false // needs changing before production + entryPoint: false, + controller: PageController } export default { @@ -15,25 +17,28 @@ export default { '/lpa-details': { ...defaultParams, fields: ['lpa', 'name', 'email'], - next: 'choose-dataset' + next: 'choose-dataset', + backLink: '/start' }, '/choose-dataset': { ...defaultParams, fields: ['dataset'], next: 'dataset-details', - controller: chooseDatasetController + controller: chooseDatasetController, + backLink: '/lpa-details' }, '/dataset-details': { ...defaultParams, fields: ['endpoint-url', 'documentation-url', 'hasLicence'], - next: 'check-answers' + next: 'check-answers', + backLink: '/choose-dataset' }, '/check-answers': { ...defaultParams, - next: 'confirmation' + next: 'confirmation', + backLink: '/dataset-details' }, '/confirmation': { ...defaultParams - } } From 74d71e1f32fa0b17bc8354f24f5c5ebdcf39d242 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 10 Jun 2024 16:16:33 +0100 Subject: [PATCH 038/127] add in the basic configuration file --- config/default.yaml | 9 +++++++++ config/index.js | 29 +++++++++++++++++++++++++++++ src/serverSetup/nunjucks.js | 6 +++--- src/views/check-answers.html | 2 +- 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 config/default.yaml create mode 100644 config/index.js diff --git a/config/default.yaml b/config/default.yaml new file mode 100644 index 00000000..32903f1c --- /dev/null +++ b/config/default.yaml @@ -0,0 +1,9 @@ +port: 3000 +maintenance: { + serviceUnavailable: false, + upTime: "9am on Monday 19 November 2024" +} +redis: false +url: '' +serviceName: 'Endpoint Submission Form' +feedbackLink: '#' \ No newline at end of file diff --git a/config/index.js b/config/index.js new file mode 100644 index 00000000..fd4442d7 --- /dev/null +++ b/config/index.js @@ -0,0 +1,29 @@ +import HmpoConfig from 'hmpo-config' +import yaml from 'js-yaml' +import fs from 'fs' +import _ from 'lodash' + +const readConfig = (config) => { + return yaml.load(fs.readFileSync(`./config/${config}.yaml`, 'utf8')) +} + +const getConfig = () => { + const defaultConfig = readConfig('default') + + const environment = process.env.NODE_ENV || process.env.ENVIRONMENT || 'production' + + console.log('USING CONFIG: ' + environment) + + const customConfig = readConfig(environment) + + const combinedConfig = _.merge({}, defaultConfig, customConfig) + + const config = new HmpoConfig() + config.addConfig(combinedConfig) + + const configJson = config.toJSON() + configJson.environment = environment + return configJson +} + +export default getConfig() diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 94a3467a..995f3064 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -1,5 +1,5 @@ import nunjucks from 'nunjucks' -// import config from '../../config/index.js' +import config from '../../config/index.js' import addFilters from '../filters/filters.js' export function setupNunjucks (app) { @@ -16,8 +16,8 @@ export function setupNunjucks (app) { }) const globalValues = { - serviceName: 'Endpoint Submission Form', // config.serviceName, - feedbackLink: '#'// config.feedbackLink + serviceName: config.serviceName, + feedbackLink: config.feedbackLink } Object.keys(globalValues).forEach((key) => { diff --git a/src/views/check-answers.html b/src/views/check-answers.html index 61335321..9504bad3 100644 --- a/src/views/check-answers.html +++ b/src/views/check-answers.html @@ -5,7 +5,7 @@ {% from "govuk/components/back-link/macro.njk" import govukBackLink %} {% block pageTitle %} -Check your answers template – {{ serviceName }} – GOV.UK Prototype Kit + Check your answers template – {{ serviceName }} – GOV.UK Prototype Kit {% endblock %} {% block beforeContent %} From 1f5f77f3621c33f6d9bb9442df2e0d3c86865a25 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 11 Jun 2024 14:12:36 +0100 Subject: [PATCH 039/127] started adding unit tests --- config/production.yaml | 0 config/test.yaml | 0 package.json | 8 +++-- src/serverSetup/nunjucks.js | 7 +++- src/utils/utils.js | 3 +- src/views/layouts/main.html | 2 +- src/views/lpa-details.html | 2 +- test/unit/chooseDatasetController.test.js | 41 +++++++++++++++++++++ test/unit/generic-page.js | 43 +++++++++++++++++++++++ test/unit/lpa-details.test.js | 16 +++++++++ 10 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 config/production.yaml create mode 100644 config/test.yaml create mode 100644 test/unit/chooseDatasetController.test.js create mode 100644 test/unit/generic-page.js create mode 100644 test/unit/lpa-details.test.js diff --git a/config/production.yaml b/config/production.yaml new file mode 100644 index 00000000..e69de29b diff --git a/config/test.yaml b/config/test.yaml new file mode 100644 index 00000000..e69de29b diff --git a/package.json b/package.json index 10fce164..80cfe4a6 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,18 @@ "type": "module", "scripts": { "prepare": "husky", - "test": "echo \"Error: no test specified\" && exit 1", "lint": "standard", "lint:fix": "standard --fix", - "start": "node index.js" + "start": "node index.js", + "test": "npm run test:unit", + "test:unit": "vitest run test/unit" }, "author": "", "license": "ISC", "devDependencies": { "husky": "^9.0.11", - "standard": "^17.1.0" + "standard": "^17.1.0", + "vitest": "^1.6.0" }, "dependencies": { "@x-govuk/govuk-prototype-components": "^3.0.5", diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 995f3064..6c2fce84 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -3,7 +3,10 @@ import config from '../../config/index.js' import addFilters from '../filters/filters.js' export function setupNunjucks (app) { - app.set('view engine', 'html') + if (app) { + app.set('view engine', 'html') + } + const nunjucksEnv = nunjucks.configure([ 'src/views', 'node_modules/govuk-frontend/dist/', @@ -24,4 +27,6 @@ export function setupNunjucks (app) { nunjucksEnv.addGlobal(key, globalValues[key]) }) addFilters(nunjucksEnv) + + return nunjucks } diff --git a/src/utils/utils.js b/src/utils/utils.js index 8dda1dc8..1aced3f9 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -52,8 +52,7 @@ export const dataSubjects = { { value: 'tree', text: 'Tree dataset', - available: true, - requiresGeometryTypeSelection: true + available: true } ] }, diff --git a/src/views/layouts/main.html b/src/views/layouts/main.html index 17acfa65..40ecb5f1 100644 --- a/src/views/layouts/main.html +++ b/src/views/layouts/main.html @@ -10,7 +10,7 @@ {% from 'govuk/components/back-link/macro.njk' import govukBackLink %} {% block pageTitle %} - {{ pageName }} - {{ serviceName }} +{{ pageName }} - {{ serviceName }} {% endblock %} {% block head %} diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 657da0e9..11165def 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -4,7 +4,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% block pageTitle %} -Question page template – {{ serviceName }} – GOV.UK Prototype Kit + Lpa details – {{ serviceName }} {% endblock %} {% block beforeContent %} diff --git a/test/unit/chooseDatasetController.test.js b/test/unit/chooseDatasetController.test.js new file mode 100644 index 00000000..1fd2c8d4 --- /dev/null +++ b/test/unit/chooseDatasetController.test.js @@ -0,0 +1,41 @@ +import ChooseDatasetController from '../../src/controllers/chooseDatasetController.js' + +import { describe, it, vi, expect, beforeEach } from 'vitest' + +describe('ChooseDatasetController', () => { + let chooseDatasetController + + beforeEach(() => { + chooseDatasetController = new ChooseDatasetController({ + route: '/dataset' + }) + + vi.mock('../../src/utils/utils.js', () => { + return { + dataSubjects: { + subject1: { available: true, dataSets: [{ available: true, text: 'B', value: 'B', requiresGeometryTypeSelection: true }, { available: false, text: 'A', value: 'A', requiresGeometryTypeSelection: false }] }, + subject2: { available: false, dataSets: [{ available: true, text: 'C', value: 'C', requiresGeometryTypeSelection: false }] }, + subject3: { available: true, dataSets: [{ available: true, text: 'A', value: 'A', requiresGeometryTypeSelection: true }] } + } + } + }) + }) + + it('locals correctly filters and sorts available datasets and assigns them to req.form.options.datasetItems', async () => { + // Mock dataSubjects + + // Mock req, res, next + const req = { form: { options: {} } } + const res = {} + const next = vi.fn() + + // Call locals function + chooseDatasetController.locals(req, res, next) + + // Check if the datasets are correctly filtered and sorted + expect(req.form.options.datasetItems).toEqual([{ available: true, text: 'A', value: 'A', requiresGeometryTypeSelection: true }, { available: true, text: 'B', value: 'B', requiresGeometryTypeSelection: true }]) + + // Check if next is called + expect(next).toHaveBeenCalled() + }) +}) diff --git a/test/unit/generic-page.js b/test/unit/generic-page.js new file mode 100644 index 00000000..2a18b401 --- /dev/null +++ b/test/unit/generic-page.js @@ -0,0 +1,43 @@ +// this file holds unit tests that apply to all pages + +import { it, expect } from 'vitest' + +/* + Params: + html: string + options: { + pageTitle: string, + serviceName: string + } +*/ +export const runGenericPageTests = (html, options) => { + html = stripWhitespace(html) + + it('should have the correct header', () => { + const govLogo = `` + + expect(html).toContain(stripWhitespace(govLogo)) + + const regex = new RegExp(``, 'g') + + expect(html).toMatch(regex) + }) + + if (options.pageTitle) { + it('should have the correct title', () => { + expect(html).toContain(stripWhitespace(` ${options.pageTitle} `)) + }) + } +} + +// this function strips out unnecessary whitespace from our html to make sure comparisons are accurate +const stripWhitespace = (str) => { + return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') +} diff --git a/test/unit/lpa-details.test.js b/test/unit/lpa-details.test.js new file mode 100644 index 00000000..b084f63e --- /dev/null +++ b/test/unit/lpa-details.test.js @@ -0,0 +1,16 @@ +import { describe } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' + +const nunjucks = setupNunjucks() + +describe('Lpa-details View', () => { + const params = {} + const html = nunjucks.render('lpa-details.html', params) + + runGenericPageTests(html, { + pageTitle: `Lpa details – ${config.serviceName}`, + serviceName: config.serviceName + }) +}) From 3a8706e800accabd88dca8e3f1ee4588363f0c93 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 11 Jun 2024 14:44:25 +0100 Subject: [PATCH 040/127] finished unit testing templates --- src/views/check-answers.html | 2 +- src/views/choose-dataset.html | 4 + src/views/dataset-details.html | 4 + src/views/start.html | 4 + test/unit/check-answers.test.js | 75 +++++++++++++++++++ test/unit/choose-datasetPage.test.js | 16 ++++ test/unit/confirmationPage.test.js | 28 +++++++ test/unit/dataset-details.test.html | 30 ++++++++ test/unit/generic-page.js | 6 +- ...etails.test.js => lpa-detailsPage.test.js} | 0 test/unit/startPage.test.js | 16 ++++ test/utils/stripWhiteSpace.js | 4 + 12 files changed, 183 insertions(+), 6 deletions(-) create mode 100644 test/unit/check-answers.test.js create mode 100644 test/unit/choose-datasetPage.test.js create mode 100644 test/unit/confirmationPage.test.js create mode 100644 test/unit/dataset-details.test.html rename test/unit/{lpa-details.test.js => lpa-detailsPage.test.js} (100%) create mode 100644 test/unit/startPage.test.js create mode 100644 test/utils/stripWhiteSpace.js diff --git a/src/views/check-answers.html b/src/views/check-answers.html index 9504bad3..f0305ba3 100644 --- a/src/views/check-answers.html +++ b/src/views/check-answers.html @@ -5,7 +5,7 @@ {% from "govuk/components/back-link/macro.njk" import govukBackLink %} {% block pageTitle %} - Check your answers template – {{ serviceName }} – GOV.UK Prototype Kit + Check your answers – {{ serviceName }} {% endblock %} {% block beforeContent %} diff --git a/src/views/choose-dataset.html b/src/views/choose-dataset.html index 04b7f8a0..c58e6451 100644 --- a/src/views/choose-dataset.html +++ b/src/views/choose-dataset.html @@ -5,6 +5,10 @@ {% set pageName = "Choose dataset" %} +{% block pageTitle %} + Choose dataset – {{ serviceName }} +{% endblock %} + {% block beforeContent %} {{ govukBackLink({ text: "Back", diff --git a/src/views/dataset-details.html b/src/views/dataset-details.html index e9a3015c..e9b5a1ba 100644 --- a/src/views/dataset-details.html +++ b/src/views/dataset-details.html @@ -6,6 +6,10 @@ {% set pageName = values['dataset'] + " details" %} +{% block pageTitle %} + {{ pageName }} – {{ serviceName }} +{% endblock %} + {% block beforeContent %} {{ govukBackLink({ text: "Back", diff --git a/src/views/start.html b/src/views/start.html index 5c6e6944..f4ce3146 100644 --- a/src/views/start.html +++ b/src/views/start.html @@ -4,6 +4,10 @@ {% set pageName = serviceName %} +{% block pageTitle %} + Start – {{ serviceName }} +{% endblock %} + {% block content %} {% set content %} diff --git a/test/unit/check-answers.test.js b/test/unit/check-answers.test.js new file mode 100644 index 00000000..1d338c5f --- /dev/null +++ b/test/unit/check-answers.test.js @@ -0,0 +1,75 @@ +/* eslint-disable prefer-regex-literals */ + +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' +import { stripWhitespace } from '../utils/stripWhiteSpace.js' + +const nunjucks = setupNunjucks() + +describe('check-answers View', () => { + const params = { + values: { + lpa: 'mockLpa', + name: 'mockName', + email: 'mockEmail', + dataset: 'mockDataset', + 'endpoint-url': 'mockEndpointUrl', + 'documentation-url': 'mockDocumentationUrl', + hasLicence: 'true' + } + } + const html = stripWhitespace(nunjucks.render('check-answers.html', params)) + + runGenericPageTests(html, { + pageTitle: `Check your answers – ${config.serviceName}`, + serviceName: config.serviceName + }) + + it('should render the lpa selected', () => { + const lpaRegex = new RegExp('
.*Local planning authority.*mockLpa.*Change.*
', 'g') + expect(html).toMatch(lpaRegex) + }) + + it('should render the name entered', () => { + const nameRegex = new RegExp('
.*Full name.*mockName.*Change.*
', 'g') + expect(html).toMatch(nameRegex) + }) + + it('should render the email entered', () => { + const emailRegex = new RegExp('
.*Email address.*mockEmail.*Change.*
', 'g') + expect(html).toMatch(emailRegex) + }) + + it('should render the dataset entered', () => { + const datasetRegex = new RegExp('
.*Dataset.*mockDataset.*Change.*
', 'g') + expect(html).toMatch(datasetRegex) + }) + + it('should render the endpoint url entered', () => { + const endpointUrlRegex = new RegExp('
.*Dataset URL.*mockEndpointUrl.*Change.*
', 'g') + expect(html).toMatch(endpointUrlRegex) + }) + + it('should render the documentation url entered', () => { + const documentationUrlRegex = new RegExp('
.*Documentation URL.*mockDocumentationUrl.*Change.*
', 'g') + expect(html).toMatch(documentationUrlRegex) + }) + + it('should render the licence selected as true if the licence has been confirmed', () => { + const hasLicenceRegex = new RegExp('
.*Licence.*True.*Change.*
', 'g') + expect(html).toMatch(hasLicenceRegex) + }) + + it('should render the licence selected as false if the licence has not been confirmed', () => { + const params = { + values: { + hasLicence: 'false' + } + } + const html = stripWhitespace(nunjucks.render('check-answers.html', params)) + const hasLicenceRegex = new RegExp('
.*Licence.*False.*Change.*
', 'g') + expect(html).toMatch(hasLicenceRegex) + }) +}) diff --git a/test/unit/choose-datasetPage.test.js b/test/unit/choose-datasetPage.test.js new file mode 100644 index 00000000..954943f6 --- /dev/null +++ b/test/unit/choose-datasetPage.test.js @@ -0,0 +1,16 @@ +import { describe } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' + +const nunjucks = setupNunjucks() + +describe('choose dataset View', () => { + const params = {} + const html = nunjucks.render('choose-dataset.html', params) + + runGenericPageTests(html, { + pageTitle: `Choose dataset – ${config.serviceName}`, + serviceName: config.serviceName + }) +}) diff --git a/test/unit/confirmationPage.test.js b/test/unit/confirmationPage.test.js new file mode 100644 index 00000000..4e4fbfe7 --- /dev/null +++ b/test/unit/confirmationPage.test.js @@ -0,0 +1,28 @@ +/* eslint-disable prefer-regex-literals */ + +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' +import { stripWhitespace } from '../utils/stripWhiteSpace.js' + +const nunjucks = setupNunjucks() + +describe('Confirmation View', () => { + const params = { + values: { + dataset: 'mockDataset' + } + } + const html = stripWhitespace(nunjucks.render('confirmation.html', params)) + + runGenericPageTests(html, { + pageTitle: `mockDataset submitted - ${config.serviceName}`, + serviceName: config.serviceName + }) + + it('should render the gov uk panel', () => { + const regex = new RegExp('

', 'g') + expect(html).toMatch(regex) + }) +}) diff --git a/test/unit/dataset-details.test.html b/test/unit/dataset-details.test.html new file mode 100644 index 00000000..0366bc03 --- /dev/null +++ b/test/unit/dataset-details.test.html @@ -0,0 +1,30 @@ +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' +import { stripWhitespace } from '../utils/stripWhiteSpace.js' + +const nunjucks = setupNunjucks() + +describe('dataset details View', () => { + const params = { + values: { + dataset: 'mockDataset' + } + } + const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) + + + runGenericPageTests(html, { + pageTitle: `mockDataset details – ${config.serviceName}`, + serviceName: config.serviceName + }) + + it('should render the correct header', () => { + expect(html).toMatch + + const regex = new RegExp(`

`, 'g') + + expect(html).toMatch(regex) + }) +}) diff --git a/test/unit/generic-page.js b/test/unit/generic-page.js index 2a18b401..281ca172 100644 --- a/test/unit/generic-page.js +++ b/test/unit/generic-page.js @@ -1,6 +1,7 @@ // this file holds unit tests that apply to all pages import { it, expect } from 'vitest' +import { stripWhitespace } from '../utils/stripWhiteSpace' /* Params: @@ -36,8 +37,3 @@ export const runGenericPageTests = (html, options) => { }) } } - -// this function strips out unnecessary whitespace from our html to make sure comparisons are accurate -const stripWhitespace = (str) => { - return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') -} diff --git a/test/unit/lpa-details.test.js b/test/unit/lpa-detailsPage.test.js similarity index 100% rename from test/unit/lpa-details.test.js rename to test/unit/lpa-detailsPage.test.js diff --git a/test/unit/startPage.test.js b/test/unit/startPage.test.js new file mode 100644 index 00000000..b8030609 --- /dev/null +++ b/test/unit/startPage.test.js @@ -0,0 +1,16 @@ +import { describe } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' + +const nunjucks = setupNunjucks() + +describe('Start View', () => { + const params = {} + const html = nunjucks.render('start.html', params) + + runGenericPageTests(html, { + pageTitle: `Start – ${config.serviceName}`, + serviceName: config.serviceName + }) +}) diff --git a/test/utils/stripWhiteSpace.js b/test/utils/stripWhiteSpace.js new file mode 100644 index 00000000..2aed5c5f --- /dev/null +++ b/test/utils/stripWhiteSpace.js @@ -0,0 +1,4 @@ +// this function strips out unnecessary whitespace from our html to make sure comparisons are accurate +export const stripWhitespace = (str) => { + return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') +} From 661d53afedb8cda9af0c97578c205559351e3ae9 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 11 Jun 2024 14:48:24 +0100 Subject: [PATCH 041/127] update github workflow so we dont need to commit package lock --- .github/workflows/lint_and_test_on_push.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint_and_test_on_push.yml b/.github/workflows/lint_and_test_on_push.yml index d5ffba6f..6db9a27d 100644 --- a/.github/workflows/lint_and_test_on_push.yml +++ b/.github/workflows/lint_and_test_on_push.yml @@ -6,7 +6,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: | - npm ci + npm i npm run lint test: @@ -14,6 +14,6 @@ jobs: steps: - uses: actions/checkout@v4 - run: | - npm ci + npm i npx playwright install --with-deps npm run test \ No newline at end of file From 928b153366f2acd8dc5f2c8991b4374c87720512 Mon Sep 17 00:00:00 2001 From: eveleighoj <35256612+eveleighoj@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:59:42 +0100 Subject: [PATCH 042/127] add Procfile for heroku --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..207d22f8 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: node app.js \ No newline at end of file From 7db15f6098dc777972f3ba28b4bc946dd099a169 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 25 Jun 2024 14:17:52 +0100 Subject: [PATCH 043/127] add geojson mime type --- src/utils/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/utils.js b/src/utils/utils.js index a9d3877a..5e429735 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -89,7 +89,7 @@ export const allowedFileTypes = { xls: ['application/vnd.ms-excel', 'application/octet-stream', 'binary/octet-stream'], xlsx: ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/octet-stream', 'binary/octet-stream'], json: ['application/json', 'application/octet-stream', 'binary/octet-stream'], - geojson: ['application/vnd.geo+json', 'application/octet-stream', 'binary/octet-stream'], + geojson: ['application/vnd.geo+json', 'application/octet-stream', 'binary/octet-stream', 'application/geo+json'], gml: ['application/gml+xml', 'application/octet-stream', 'binary/octet-stream'], gpkg: ['application/gpkg', 'application/octet-stream', 'binary/octet-stream'], sqlite: ['application/geopackage+sqlite3', 'application/octet-stream', 'binary/octet-stream'], From 29fdc6191a7ce728fa892ae96b185b56c87078e7 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 26 Jun 2024 10:00:14 +0100 Subject: [PATCH 044/127] update procfile --- Procfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Procfile b/Procfile index 207d22f8..5ec9cc2c 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: node app.js \ No newline at end of file +web: node index.js \ No newline at end of file From 8895b1dba035c9ea9c3ea77ea0c1a98a086ed14b Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 26 Jun 2024 14:34:19 +0100 Subject: [PATCH 045/127] make sure to get the port --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index c2d8ad43..662401c2 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ import { setupNunjucks } from './src/serverSetup/nunjucks.js' import { setupMiddlewares } from './src/serverSetup/middlewares.js' const app = express() -const port = 3000 +const port = process.env.PORT || 3000 setupMiddlewares(app) setupSession(app) From ca53e2b25bf188a7d518a656ec053f0fb66589af Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 26 Jun 2024 16:14:52 +0100 Subject: [PATCH 046/127] started adding logic to construct the emails --- src/controllers/CheckAnswersController.js | 66 +++++++++++++++++++++++ src/routes/form-wizard/steps.js | 2 + src/utils/emailTemplates.js | 26 +++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/controllers/CheckAnswersController.js create mode 100644 src/utils/emailTemplates.js diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js new file mode 100644 index 00000000..cc21adc2 --- /dev/null +++ b/src/controllers/CheckAnswersController.js @@ -0,0 +1,66 @@ +import PageController from './pageController.js' + +import { newRequestTemplate, requestAcknowledgedTemplate } from '../utils/emailTemplates.js' + +const dataManagementEmail = 'fakeymcfake@email.com' + +class CheckAnswersController extends PageController { + + + /** + * Handles the HTTP POST request for choosing a dataset. + * during this, we will perform a few actions + * firstly, we will email Jira causing the creation of a ticket (this will be implemented at a later date) + * secondly, we will email the management team to inform them of the request + * finally, we will email the LPA/organisation to inform them that their request has been acknowledged + * @param {Object} req - The HTTP request object. + * @param {Object} res - The HTTP response object. + * @param {Function} next - The next middleware function. + */ + post (req, res, next) { + + this.sendEmails(req, res, next) + + super.post(req, res, next) + } + + sendEmails (req, res, next) { + this.sendRequestEmail(req, res, next) + this.sendAcknowledgementEmail(req, res, next) + } + + sendAcknowledgementEmail (req, res, next) { + const name = req.sessionModel.get('name') + const dataset = req.sessionModel.get('dataset') + const email = req.sessionModel.get('email') + const emailTemplate = requestAcknowledgedTemplate + .replace('{name}', name) + .replace('{dataset}', dataset) + .replace('{email}', dataManagementEmail) + + this.sendEmail(email, 'Request Acknowledged', emailTemplate) + } + + sendRequestEmail (req, res, next) { + const name = req.sessionModel.get('name') + const email = req.sessionModel.get('email') + const organisation = req.sessionModel.get('organisation') + const dataset = req.sessionModel.get('dataset') + const emailTemplate = newRequestTemplate + .replace('{name}', name) + .replace('{dataset}', dataset) + .replace('{organisation}', organisation) + .replace('{email}', email) + + this.sendEmail(dataManagementEmail, 'New Request', emailTemplate) + } + + sendEmail (to, subject, body) { + // Send email + console.log('======') + console.log(`Sending email to ${to} with subject ${subject} and body:`) + console.log(body) + } +} + +export default CheckAnswersController diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index b5ec2e10..bd7773f3 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,5 +1,6 @@ import chooseDatasetController from '../../controllers/chooseDatasetController.js' import PageController from '../../controllers/pageController.js' +import CheckAnswersController from '../../controllers/CheckAnswersController.js' const defaultParams = { entryPoint: false, @@ -35,6 +36,7 @@ export default { }, '/check-answers': { ...defaultParams, + controller: CheckAnswersController, next: 'confirmation', backLink: '/dataset-details' }, diff --git a/src/utils/emailTemplates.js b/src/utils/emailTemplates.js new file mode 100644 index 00000000..06325173 --- /dev/null +++ b/src/utils/emailTemplates.js @@ -0,0 +1,26 @@ +export const newRequestTemplate = ` + Dear Data Management Team, + + A new request has been made to add a dataset to the data catalogue. The details of the request are as follows: + + Dataset: {dataset} + Requested by: {name} ({email}) + Organisation: {organisation} + + Please review the request and take the necessary actions. +` + +export const requestAcknowledgedTemplate = ` + Dear {name}, +
+
+ We are pleased to inform you that your request to add your {dataset} data has been acknowledged. +
+
+ If you have any questions please contact us at {email} +
+
+ Kind Regards, +
+ The data management team +` \ No newline at end of file From 290851036c6dcf78a6806a32fcc2d7b6ca81a32b Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 26 Jun 2024 16:15:00 +0100 Subject: [PATCH 047/127] linting --- src/controllers/CheckAnswersController.js | 3 --- src/utils/emailTemplates.js | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index cc21adc2..d0866d91 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -5,8 +5,6 @@ import { newRequestTemplate, requestAcknowledgedTemplate } from '../utils/emailT const dataManagementEmail = 'fakeymcfake@email.com' class CheckAnswersController extends PageController { - - /** * Handles the HTTP POST request for choosing a dataset. * during this, we will perform a few actions @@ -18,7 +16,6 @@ class CheckAnswersController extends PageController { * @param {Function} next - The next middleware function. */ post (req, res, next) { - this.sendEmails(req, res, next) super.post(req, res, next) diff --git a/src/utils/emailTemplates.js b/src/utils/emailTemplates.js index 06325173..f52c14b8 100644 --- a/src/utils/emailTemplates.js +++ b/src/utils/emailTemplates.js @@ -23,4 +23,4 @@ export const requestAcknowledgedTemplate = ` Kind Regards,
The data management team -` \ No newline at end of file +` From 492fa40c4acdd19f730fea8d485d1515568b6064 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 11:58:58 +0100 Subject: [PATCH 048/127] add in govuk notify --- .gitignore | 1 + config/default.yaml | 7 +++ index.js | 4 ++ package.json | 1 + src/controllers/CheckAnswersController.js | 60 ++++++++++------------- src/utils/emailTemplates.js | 26 ---------- src/utils/mailClient.js | 12 +++++ 7 files changed, 50 insertions(+), 61 deletions(-) delete mode 100644 src/utils/emailTemplates.js create mode 100644 src/utils/mailClient.js diff --git a/.gitignore b/.gitignore index a4accdd5..56e032a9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ package-lock.json node_modules/* +.env diff --git a/config/default.yaml b/config/default.yaml index 32903f1c..20c5c99e 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -3,6 +3,13 @@ maintenance: { serviceUnavailable: false, upTime: "9am on Monday 19 November 2024" } +email: { + templates: { + RequestTemplateId: 'fa1c2b51-3c91-4f9d-9a18-83639164d552', + AcknowledgementTemplateId: '2a4dff6d-78c4-4fea-a489-c97485453807' + }, + dataManagementEmail: 'fakeemail@fakemail.com' +} redis: false url: '' serviceName: 'Endpoint Submission Form' diff --git a/index.js b/index.js index 662401c2..cf67e225 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,13 @@ import express from 'express' + import { setupRoutes } from './src/serverSetup/routes.js' import { setupSession } from './src/serverSetup/setupSession.js' import { setupNunjucks } from './src/serverSetup/nunjucks.js' import { setupMiddlewares } from './src/serverSetup/middlewares.js' +import dotenv from 'dotenv' +dotenv.config() + const app = express() const port = process.env.PORT || 3000 diff --git a/package.json b/package.json index 80cfe4a6..e05a3a66 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", "hmpo-i18n": "^6.0.1", + "notifications-node-client": "^8.2.0", "nunjucks": "^3.2.4" } } diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index d0866d91..803d4f74 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -1,8 +1,8 @@ import PageController from './pageController.js' +import { sendEmail } from '../utils/mailClient.js' +import config from '../../config/index.js' -import { newRequestTemplate, requestAcknowledgedTemplate } from '../utils/emailTemplates.js' - -const dataManagementEmail = 'fakeymcfake@email.com' +const dataManagementEmail = config.email.dataManagementEmail class CheckAnswersController extends PageController { /** @@ -22,41 +22,31 @@ class CheckAnswersController extends PageController { } sendEmails (req, res, next) { - this.sendRequestEmail(req, res, next) - this.sendAcknowledgementEmail(req, res, next) - } - - sendAcknowledgementEmail (req, res, next) { - const name = req.sessionModel.get('name') - const dataset = req.sessionModel.get('dataset') - const email = req.sessionModel.get('email') - const emailTemplate = requestAcknowledgedTemplate - .replace('{name}', name) - .replace('{dataset}', dataset) - .replace('{email}', dataManagementEmail) - - this.sendEmail(email, 'Request Acknowledged', emailTemplate) - } - - sendRequestEmail (req, res, next) { const name = req.sessionModel.get('name') const email = req.sessionModel.get('email') - const organisation = req.sessionModel.get('organisation') + const organisation = req.sessionModel.get('lpa') const dataset = req.sessionModel.get('dataset') - const emailTemplate = newRequestTemplate - .replace('{name}', name) - .replace('{dataset}', dataset) - .replace('{organisation}', organisation) - .replace('{email}', email) - - this.sendEmail(dataManagementEmail, 'New Request', emailTemplate) - } - - sendEmail (to, subject, body) { - // Send email - console.log('======') - console.log(`Sending email to ${to} with subject ${subject} and body:`) - console.log(body) + const documentationUrl = req.sessionModel.get('documentation-url') + const endpoint = req.sessionModel.get('endpoint-url') + + const { RequestTemplateId, AcknowledgementTemplateId } = config.email.templates + + // send request email to data management team + sendEmail(dataManagementEmail, RequestTemplateId, { + name, + email, + organisation, + endpoint, + 'documentation-url': documentationUrl, + dataset + }) + + // send acknowledgement email to LPA + sendEmail(email, AcknowledgementTemplateId, { + name, + dataset, + email: dataManagementEmail + }) } } diff --git a/src/utils/emailTemplates.js b/src/utils/emailTemplates.js deleted file mode 100644 index f52c14b8..00000000 --- a/src/utils/emailTemplates.js +++ /dev/null @@ -1,26 +0,0 @@ -export const newRequestTemplate = ` - Dear Data Management Team, - - A new request has been made to add a dataset to the data catalogue. The details of the request are as follows: - - Dataset: {dataset} - Requested by: {name} ({email}) - Organisation: {organisation} - - Please review the request and take the necessary actions. -` - -export const requestAcknowledgedTemplate = ` - Dear {name}, -
-
- We are pleased to inform you that your request to add your {dataset} data has been acknowledged. -
-
- If you have any questions please contact us at {email} -
-
- Kind Regards, -
- The data management team -` diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js new file mode 100644 index 00000000..c98076c2 --- /dev/null +++ b/src/utils/mailClient.js @@ -0,0 +1,12 @@ +import { NotifyClient } from 'notifications-node-client' + +import dotenv from 'dotenv' +dotenv.config() + +const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY) + +export const sendEmail = async (emailAddress, templateId, personalisation) => { + notifyClient.sendEmail(templateId, emailAddress, { personalisation }) + .then(response => console.log(response)) + .catch(err => console.error(err)) +} From 0d3b71f07b5e7d29488d65760e059f60c71d3663 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 13:31:28 +0100 Subject: [PATCH 049/127] add additional params to acknowledged email --- src/controllers/CheckAnswersController.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index 803d4f74..699ed5f0 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -44,8 +44,11 @@ class CheckAnswersController extends PageController { // send acknowledgement email to LPA sendEmail(email, AcknowledgementTemplateId, { name, - dataset, - email: dataManagementEmail + email, + organisation, + endpoint, + 'documentation-url': documentationUrl, + dataset }) } } From e9c9e8e57a07ca6a9971881e85be36c51c374db6 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 13:36:31 +0100 Subject: [PATCH 050/127] added unit test for checkAnswersController --- test/unit/checkAnswersController.test.js | 75 ++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 test/unit/checkAnswersController.test.js diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js new file mode 100644 index 00000000..9d4747cb --- /dev/null +++ b/test/unit/checkAnswersController.test.js @@ -0,0 +1,75 @@ +import CheckAnswersController from '../../src/controllers/CheckAnswersController.js' + +import { describe, it, vi, expect, beforeEach } from 'vitest' +import config from '../../config/index.js' +import { sendEmail } from '../../src/utils/mailClient.js' + +vi.mock('../../src/utils/mailClient.js') + +describe('Check answers controller', () => { + let checkAnswersController + let sendEmailMock + + beforeEach(() => { + checkAnswersController = new CheckAnswersController({ + route: '/dataset' + }) + + sendEmailMock = vi.fn() + + sendEmail.mockImplementation(sendEmailMock) + + }) + + + describe('send emails', () => { + it('should get the values from the session model and then send the request and acknowledgement emails', () => { + // Mock req, res, next + const req = { + sessionModel: { + get: vi.fn().mockImplementation((key) => { + const values = { + name: 'John Doe', + email: 'JohnDoe@mail.com', + lpa: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + 'endpoint-url': 'Endpoint URL' + } + return values[key] + }) + } + } + + const res = {} + const next = vi.fn() + + checkAnswersController.sendEmails(req, res, next) + + expect(req.sessionModel.get).toHaveBeenCalledWith('name') + expect(req.sessionModel.get).toHaveBeenCalledWith('email') + expect(req.sessionModel.get).toHaveBeenCalledWith('lpa') + expect(req.sessionModel.get).toHaveBeenCalledWith('dataset') + expect(req.sessionModel.get).toHaveBeenCalledWith('documentation-url') + expect(req.sessionModel.get).toHaveBeenCalledWith('endpoint-url') + + expect(sendEmailMock).toHaveBeenCalledWith(config.email.dataManagementEmail, config.email.templates.RequestTemplateId, { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + endpoint: 'Endpoint URL' + }) + + expect(sendEmailMock).toHaveBeenCalledWith('JohnDoe@mail.com', config.email.templates.AcknowledgementTemplateId, { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + endpoint: 'Endpoint URL', + 'documentation-url': 'Documentation URL', + dataset: 'Dataset' + }) + }) + }) +}) From 627a00d968200b8999909889a91e72c7cc90d7a8 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 13:36:38 +0100 Subject: [PATCH 051/127] linting --- test/unit/checkAnswersController.test.js | 106 +++++++++++------------ 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js index 9d4747cb..d6f94b0c 100644 --- a/test/unit/checkAnswersController.test.js +++ b/test/unit/checkAnswersController.test.js @@ -7,69 +7,67 @@ import { sendEmail } from '../../src/utils/mailClient.js' vi.mock('../../src/utils/mailClient.js') describe('Check answers controller', () => { - let checkAnswersController - let sendEmailMock - - beforeEach(() => { - checkAnswersController = new CheckAnswersController({ - route: '/dataset' - }) - - sendEmailMock = vi.fn() - - sendEmail.mockImplementation(sendEmailMock) + let checkAnswersController + let sendEmailMock + beforeEach(() => { + checkAnswersController = new CheckAnswersController({ + route: '/dataset' }) + sendEmailMock = vi.fn() + + sendEmail.mockImplementation(sendEmailMock) + }) - describe('send emails', () => { - it('should get the values from the session model and then send the request and acknowledgement emails', () => { - // Mock req, res, next - const req = { - sessionModel: { - get: vi.fn().mockImplementation((key) => { - const values = { - name: 'John Doe', - email: 'JohnDoe@mail.com', - lpa: 'LPA', - dataset: 'Dataset', - 'documentation-url': 'Documentation URL', - 'endpoint-url': 'Endpoint URL' - } - return values[key] - }) - } + describe('send emails', () => { + it('should get the values from the session model and then send the request and acknowledgement emails', () => { + // Mock req, res, next + const req = { + sessionModel: { + get: vi.fn().mockImplementation((key) => { + const values = { + name: 'John Doe', + email: 'JohnDoe@mail.com', + lpa: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + 'endpoint-url': 'Endpoint URL' } + return values[key] + }) + } + } - const res = {} - const next = vi.fn() + const res = {} + const next = vi.fn() - checkAnswersController.sendEmails(req, res, next) + checkAnswersController.sendEmails(req, res, next) - expect(req.sessionModel.get).toHaveBeenCalledWith('name') - expect(req.sessionModel.get).toHaveBeenCalledWith('email') - expect(req.sessionModel.get).toHaveBeenCalledWith('lpa') - expect(req.sessionModel.get).toHaveBeenCalledWith('dataset') - expect(req.sessionModel.get).toHaveBeenCalledWith('documentation-url') - expect(req.sessionModel.get).toHaveBeenCalledWith('endpoint-url') + expect(req.sessionModel.get).toHaveBeenCalledWith('name') + expect(req.sessionModel.get).toHaveBeenCalledWith('email') + expect(req.sessionModel.get).toHaveBeenCalledWith('lpa') + expect(req.sessionModel.get).toHaveBeenCalledWith('dataset') + expect(req.sessionModel.get).toHaveBeenCalledWith('documentation-url') + expect(req.sessionModel.get).toHaveBeenCalledWith('endpoint-url') - expect(sendEmailMock).toHaveBeenCalledWith(config.email.dataManagementEmail, config.email.templates.RequestTemplateId, { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - dataset: 'Dataset', - 'documentation-url': 'Documentation URL', - endpoint: 'Endpoint URL' - }) + expect(sendEmailMock).toHaveBeenCalledWith(config.email.dataManagementEmail, config.email.templates.RequestTemplateId, { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + endpoint: 'Endpoint URL' + }) - expect(sendEmailMock).toHaveBeenCalledWith('JohnDoe@mail.com', config.email.templates.AcknowledgementTemplateId, { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - endpoint: 'Endpoint URL', - 'documentation-url': 'Documentation URL', - dataset: 'Dataset' - }) - }) + expect(sendEmailMock).toHaveBeenCalledWith('JohnDoe@mail.com', config.email.templates.AcknowledgementTemplateId, { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + endpoint: 'Endpoint URL', + 'documentation-url': 'Documentation URL', + dataset: 'Dataset' + }) }) + }) }) From 07ec78efa8d79fa8afa46f63916be37fd8a615fd Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 14:44:19 +0100 Subject: [PATCH 052/127] add some testing --- src/utils/mailClient.js | 2 +- test/unit/mailClient.test.js | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/unit/mailClient.test.js diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index c98076c2..49e95470 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -6,7 +6,7 @@ dotenv.config() const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY) export const sendEmail = async (emailAddress, templateId, personalisation) => { - notifyClient.sendEmail(templateId, emailAddress, { personalisation }) + return notifyClient.sendEmail(templateId, emailAddress, { personalisation }) .then(response => console.log(response)) .catch(err => console.error(err)) } diff --git a/test/unit/mailClient.test.js b/test/unit/mailClient.test.js new file mode 100644 index 00000000..0810d14f --- /dev/null +++ b/test/unit/mailClient.test.js @@ -0,0 +1,57 @@ +import { describe, expect, it, vi, beforeEach } from 'vitest' + +import { sendEmail } from '../../src/utils/mailClient' +import { NotifyClient } from 'notifications-node-client' + +// vi.mock('notifications-node-client', () => { +// return { +// NotifyClient: vi.fn().mockReturnValue( +// { +// sendEmail: vi.fn().mockResolvedValue({}) +// } +// ) +// } +// }); + +const sendEmailMock = vi.spyOn(NotifyClient.prototype, 'sendEmail') + +describe('sendEmail', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + + it('should call NotifyClient.sendEmail with correct parameters', async () => { + const emailAddress = 'test@example.com' + const templateId = 'template-id' + const personalisation = { name: 'John Doe' } + + await sendEmail(emailAddress, templateId, personalisation) + + expect(sendEmailMock).toHaveBeenCalledWith(templateId, emailAddress, { personalisation }) + }) + + it('should log the response on successful email send', async () => { + const consoleMock = vi.spyOn(global.console, 'log').mockImplementation(() => undefined) + + const response = { id: '12345', content: { body: 'Test email content', subject: 'Test' } } + sendEmailMock.mockResolvedValue(response) // Explicitly resolve with a response + + await sendEmail('test@example.com', 'template-id', { name: 'John Doe' }) + + expect(consoleMock).toHaveBeenCalledWith(response) + }) + + it('should log an error if email sending fails', async () => { + console.error = vi.fn() + const error = new Error('Failed to send email') + sendEmailMock.mockRejectedValue(error) // Explicitly reject with an error + + try { + await sendEmail('test@example.com', 'template-id', { name: 'John Doe' }) + } catch (e) { + // Catch the error to prevent the test from failing due to unhandled rejection + } + + expect(console.error).toHaveBeenCalledWith(error) + }) +}) From d6cc560844c7309e684d7cd618e70694c6f35ba5 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 27 Jun 2024 14:55:33 +0100 Subject: [PATCH 053/127] fix tests --- src/utils/mailClient.js | 2 +- test/unit/mailClient.test.js | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index 49e95470..5b12dc1a 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -3,7 +3,7 @@ import { NotifyClient } from 'notifications-node-client' import dotenv from 'dotenv' dotenv.config() -const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY) +const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') export const sendEmail = async (emailAddress, templateId, personalisation) => { return notifyClient.sendEmail(templateId, emailAddress, { personalisation }) diff --git a/test/unit/mailClient.test.js b/test/unit/mailClient.test.js index 0810d14f..2aab2969 100644 --- a/test/unit/mailClient.test.js +++ b/test/unit/mailClient.test.js @@ -3,16 +3,6 @@ import { describe, expect, it, vi, beforeEach } from 'vitest' import { sendEmail } from '../../src/utils/mailClient' import { NotifyClient } from 'notifications-node-client' -// vi.mock('notifications-node-client', () => { -// return { -// NotifyClient: vi.fn().mockReturnValue( -// { -// sendEmail: vi.fn().mockResolvedValue({}) -// } -// ) -// } -// }); - const sendEmailMock = vi.spyOn(NotifyClient.prototype, 'sendEmail') describe('sendEmail', () => { From 96bc6cd545d429e440ae01f06e981d088876b8a6 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 28 Jun 2024 11:34:36 +0100 Subject: [PATCH 054/127] add validators --- src/routes/form-wizard/fields.js | 29 ++++++++++++++++++++------- src/utils/validators.js | 9 +++++++++ test/unit/validators.test.js | 34 ++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 src/utils/validators.js create mode 100644 test/unit/validators.test.js diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index 2307642d..f23d13e6 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -1,23 +1,38 @@ +import { validUrl } from '../../utils/validators.js' + export default { lpa: { - // validate: ['required'], + validate: ['required'] }, name: { - // validate: ['required'], + validate: ['required'] }, email: { - // validate: ['required'], + validate: [ + 'required', + 'email' + ] }, dataset: { - // validate: ['required'], + validate: ['required'] }, 'endpoint-url': { - // validate: ['required'], + validate: [ + 'required', + { + type: 'validUrl', fn: validUrl + } + ] }, 'documentation-url': { - // validate: ['required'], + validate: [ + 'required', + { + type: 'validUrl', fn: validUrl + } + ] }, hasLicence: { - // validate: ['required'], + validate: ['required'] } } diff --git a/src/utils/validators.js b/src/utils/validators.js new file mode 100644 index 00000000..db48436f --- /dev/null +++ b/src/utils/validators.js @@ -0,0 +1,9 @@ +export const validUrl = (urlString) => { + let url + try { + url = new URL(urlString) + } catch (e) { + return false + } + return url.protocol === 'http:' || url.protocol === 'https:' +} diff --git a/test/unit/validators.test.js b/test/unit/validators.test.js new file mode 100644 index 00000000..b72efab1 --- /dev/null +++ b/test/unit/validators.test.js @@ -0,0 +1,34 @@ +import { describe, it, expect } from 'vitest' +import { validUrl } from '../../src/utils/validators' + +describe('validUrl', () => { + it('should return true for a valid URL', () => { + const url = 'https://www.example.com' + const result = validUrl(url) + expect(result).toBe(true) + }) + + it('should return false for an invalid URL', () => { + const url = 'example.com' + const result = validUrl(url) + expect(result).toBe(false) + }) + + it('should return false for an empty string', () => { + const url = '' + const result = validUrl(url) + expect(result).toBe(false) + }) + + it('should return false for a null value', () => { + const url = null + const result = validUrl(url) + expect(result).toBe(false) + }) + + it('should return false for an undefined value', () => { + const url = undefined + const result = validUrl(url) + expect(result).toBe(false) + }) +}) From 5e19c9effe34ecacca6da3bf11744748afed5a08 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 11:50:44 +0100 Subject: [PATCH 055/127] make sure id gets passed to the responseDetails class --- src/models/requestData.js | 2 +- src/models/responseDetails.js | 3 ++- test/unit/errorsPage.test.js | 2 +- test/unit/noErrorsPage.test.js | 2 +- test/unit/responseDetails.test.js | 36 +++++++++++++++---------------- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/models/requestData.js b/src/models/requestData.js index ece9f04f..dcbdd5ad 100644 --- a/src/models/requestData.js +++ b/src/models/requestData.js @@ -24,7 +24,7 @@ export default class RequestData { limit: request.headers['x-pagination-limit'] } - return new ResponseDetails(request.data, pagination, this.getColumnFieldLog()) + return new ResponseDetails(this.id, request.data, pagination, this.getColumnFieldLog()) } getErrorSummary () { diff --git a/src/models/responseDetails.js b/src/models/responseDetails.js index 440c62d2..d29b569f 100644 --- a/src/models/responseDetails.js +++ b/src/models/responseDetails.js @@ -2,7 +2,8 @@ import { getVerboseColumns } from '../utils/getVerboseColumns.js' import logger from '../utils/logger.js' export default class ResponseDetails { - constructor (response, pagination, columnFieldLog) { + constructor (id, response, pagination, columnFieldLog) { + this.id = id this.response = response this.pagination = pagination this.columnFieldLog = columnFieldLog diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index e4ca5dc0..8603f2b5 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -25,7 +25,7 @@ describe('errors page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - const responseDetails = new ResponseDetails(errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) + const responseDetails = new ResponseDetails('id', errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) requestData.response.pagination = { totalResults: 100, diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 3289ab8c..a44c41ec 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -24,7 +24,7 @@ addFilters(nunjucksEnv) describe('no Errors Page', () => { it('renders the correct number of errors', () => { const requestData = new RequestData(errorResponse) - const responseDetails = new ResponseDetails(errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) + const responseDetails = new ResponseDetails('id', errorResponseDetails, { totalResults: 3, offset: 0, limit: 50 }, requestData.getColumnFieldLog()) requestData.response.pagination = { totalResults: 100, diff --git a/test/unit/responseDetails.test.js b/test/unit/responseDetails.test.js index 1e8eda3a..791a6a47 100644 --- a/test/unit/responseDetails.test.js +++ b/test/unit/responseDetails.test.js @@ -78,13 +78,13 @@ describe('ResponseDetails', () => { describe('getRows', () => { it('returns the rows', () => { - const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getRows() expect(result).toBe(mockResponse) }) it('returns an empty array if there are no rows and logs an error', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getRows() expect(result).toStrictEqual([]) expect(loggerErrorSpy).toHaveBeenCalled() @@ -93,13 +93,13 @@ describe('ResponseDetails', () => { describe('getColumnFieldLog', () => { it('returns the column field log', () => { - const responseDetails = new ResponseDetails(undefined, undefined, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, mockColumnFieldLog) const result = responseDetails.getColumnFieldLog() expect(result).toStrictEqual(mockColumnFieldLog) }) it('returns an empty array if there is no column field log and logs an error', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getColumnFieldLog() expect(result).toStrictEqual([]) expect(loggerErrorSpy).toHaveBeenCalled() @@ -108,7 +108,7 @@ describe('ResponseDetails', () => { describe('getFields', () => { it('returns the unique fields from the column keys', () => { - const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getFields() const expected = ['ID', 'WKT', 'Name', 'Layer', 'Area', 'Geometry', 'Entry Date', 'Start Date', 'Documentation URL'] expect(result).toEqual(expected) @@ -117,21 +117,21 @@ describe('ResponseDetails', () => { describe('getColumns', () => { it('returns the columns', () => { - const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, mockPagination, mockColumnFieldLog) responseDetails.getFields = vi.fn(() => ['ID', 'WKT', 'Name', 'Layer', 'Area', 'Geometry', 'Entry Date', 'Start Date', 'Documentation URL']) const result = responseDetails.getColumns() expect(result).toEqual(['id', 'wkt', 'name', 'Layer', 'area(ha)', 'geometry', 'entry-date', 'start-date', 'documentation-url']) }) it('returns an empty array if there are no rows', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getColumns() expect(result).toStrictEqual([]) }) }) it('getFieldMappings', () => { - const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getFieldMappings() const expected = { ID: 'id', @@ -149,7 +149,7 @@ describe('ResponseDetails', () => { describe('getRowsWithVerboseColumns', () => { it('returns the rows with verbose columns', () => { - const responseDetails = new ResponseDetails(mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getRowsWithVerboseColumns() const expected = [ { @@ -191,7 +191,7 @@ describe('ResponseDetails', () => { ...mockResponse, errorRow ] - const responseDetails = new ResponseDetails(_mockResponse, mockPagination, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, _mockResponse, mockPagination, mockColumnFieldLog) const result = responseDetails.getRowsWithVerboseColumns(true) const expected = [ { @@ -204,7 +204,7 @@ describe('ResponseDetails', () => { }) it('returns an empty array if there are no rows and logs an error', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getRowsWithVerboseColumns() expect(result).toStrictEqual([]) expect(loggerErrorSpy).toHaveBeenCalled() @@ -213,7 +213,7 @@ describe('ResponseDetails', () => { describe('getGeometryKey', () => { it('returns the column for "point" field', () => { - const responseDetails = new ResponseDetails(undefined, undefined, [ + const responseDetails = new ResponseDetails(undefined, undefined, undefined, [ { column: 'id', field: 'ID' }, { column: 'wkt', field: 'WKT' }, { column: 'point', field: 'point' }, @@ -224,7 +224,7 @@ describe('ResponseDetails', () => { }) it('returns the column for "geometry" field', () => { - const responseDetails = new ResponseDetails(undefined, undefined, [ + const responseDetails = new ResponseDetails(undefined, undefined, undefined, [ { column: 'id', field: 'ID' }, { column: 'wkt', field: 'WKT' }, { column: 'geometry', field: 'geometry' }, @@ -235,13 +235,13 @@ describe('ResponseDetails', () => { }) it('returns null if columnFieldLog is undefined', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getGeometryKey() expect(result).toBeNull() }) it('returns null if no columnFieldEntry is found', () => { - const responseDetails = new ResponseDetails(undefined, undefined, [ + const responseDetails = new ResponseDetails(undefined, undefined, undefined, [ { column: 'id', field: 'ID' }, { column: 'wkt', field: 'WKT' }, { column: 'name', field: 'Name' } @@ -253,14 +253,14 @@ describe('ResponseDetails', () => { describe('getGeometries', () => { it('returns undefined and logs an error if there is no response', () => { - const responseDetails = new ResponseDetails(undefined, undefined, undefined) + const responseDetails = new ResponseDetails(undefined, undefined, undefined, undefined) const result = responseDetails.getGeometries() expect(result).toBeUndefined() expect(loggerErrorSpy).toHaveBeenCalled() }) it('returns null if there are no geometries', () => { - const responseDetails = new ResponseDetails([], undefined, undefined) + const responseDetails = new ResponseDetails(undefined, [], undefined, undefined) const result = responseDetails.getGeometries() expect(result).toBeNull() }) @@ -272,7 +272,7 @@ describe('ResponseDetails', () => { { column: 'geometry', field: 'geometry' }, { column: 'name', field: 'Name' } ] - const responseDetails = new ResponseDetails(mockResponse, undefined, mockColumnFieldLog) + const responseDetails = new ResponseDetails(undefined, mockResponse, undefined, mockColumnFieldLog) const result = responseDetails.getGeometries() const expected = [ 'POINT (423432.0000000000000000 564564.0000000000000000)', From 93b1c8feb20b3401680d83606de051136a9c0e4b Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 11:57:51 +0100 Subject: [PATCH 056/127] add new validation message filters and tidy filters code --- src/filters/debuggingFilters.js | 17 +++++++++++ src/filters/filters.js | 25 ++++++---------- src/filters/toErrorList.js | 14 +++++++++ src/filters/validationMessageLookup.js | 40 ++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/filters/debuggingFilters.js create mode 100644 src/filters/toErrorList.js create mode 100644 src/filters/validationMessageLookup.js diff --git a/src/filters/debuggingFilters.js b/src/filters/debuggingFilters.js new file mode 100644 index 00000000..77c857e4 --- /dev/null +++ b/src/filters/debuggingFilters.js @@ -0,0 +1,17 @@ + // some additional filters useful for debugging: + +export const getkeys = function (object) { + if (Object.prototype.toString.call(object) === '[object Array]') { + const keys = [] + for (let i = object.length - 1; i >= 0; i--) { + keys.push(Object.keys(object[i])) + } + return keys + } else { + return Object.keys(object) + } +} + +export const getContext = function () { + return this.ctx +} diff --git a/src/filters/filters.js b/src/filters/filters.js index 7aa6f35d..3d7ebcbc 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -1,26 +1,17 @@ +import { getkeys, getContext } from './debuggingFilters.js' +import toErrorList from './toErrorList.js' +import validationMessageLookup from './validationMessageLookup.js' import xGovFilters from '@x-govuk/govuk-prototype-filters' const { govukMarkdown } = xGovFilters + const addFilters = (nunjucksEnv) => { nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) - - // some additional filters useful for debugging: - nunjucksEnv.addFilter('getkeys', function (object) { - if (Object.prototype.toString.call(object) === '[object Array]') { - const keys = [] - for (let i = object.length - 1; i >= 0; i--) { - keys.push(Object.keys(object[i])) - } - return keys - } else { - return Object.keys(object) - } - }) - - nunjucksEnv.addGlobal('getContext', function () { - return this.ctx - }) + nunjucksEnv.addFilter('getkeys', getkeys) + nunjucksEnv.addFilter('getContext', getContext) + nunjucksEnv.addFilter('toErrorList', toErrorList) + nunjucksEnv.addFilter('validationMessageLookup', validationMessageLookup) } export default addFilters diff --git a/src/filters/toErrorList.js b/src/filters/toErrorList.js new file mode 100644 index 00000000..ef6c9962 --- /dev/null +++ b/src/filters/toErrorList.js @@ -0,0 +1,14 @@ +import validationMessageLookup from './validationMessageLookup.js' + +function toErrorList (errors) { + const errorList = [] + for (const [key, value] of Object.entries(errors)) { + errorList.push({ + text: validationMessageLookup(key, value.type), + href: `#${key}` + }) + } + return errorList +} + +export default toErrorList diff --git a/src/filters/validationMessageLookup.js b/src/filters/validationMessageLookup.js new file mode 100644 index 00000000..9b873d3f --- /dev/null +++ b/src/filters/validationMessageLookup.js @@ -0,0 +1,40 @@ +// import logger from '../utils/logger.js' + +const validationMessages = { + 'lpa': { + required: 'Enter the name of your local planning authority' + }, + 'name': { + required: 'Enter your full name' + }, + 'email': { + required: 'Enter an email address', + email: 'Enter an email address in the correct format' + }, + 'dataset': { + required: 'Select a dataset' + }, + 'endpoint-url': { + required: 'Enter a URL', + format: 'Enter a valid URL', + length: 'The URL must be less than 2048 characters' + }, + 'documentation-url': { + required: 'Enter a URL', + format: 'Enter a valid URL', + length: 'The URL must be less than 2048 characters' + }, + 'hasLicence': { + required: 'SYour data must be licensed under the Open Government Licence' + } +} + +function validationMessageLookup (field, type) { + if (!validationMessages[field] || !validationMessages[field][type]) { + // logger.error('No validation message found for field ' + field + ' and type ' + type) + return `An error occurred of type ${type} for field ${field}` + } + return validationMessages[field][type] +} + +export default validationMessageLookup From 7cf63864a2f373c4d3d53f04f68d70df36ab7cda Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 11:58:03 +0100 Subject: [PATCH 057/127] linting --- src/filters/debuggingFilters.js | 20 ++++++++++---------- src/filters/filters.js | 1 - src/filters/validationMessageLookup.js | 10 +++++----- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/filters/debuggingFilters.js b/src/filters/debuggingFilters.js index 77c857e4..219a227f 100644 --- a/src/filters/debuggingFilters.js +++ b/src/filters/debuggingFilters.js @@ -1,17 +1,17 @@ - // some additional filters useful for debugging: +// some additional filters useful for debugging: export const getkeys = function (object) { - if (Object.prototype.toString.call(object) === '[object Array]') { - const keys = [] - for (let i = object.length - 1; i >= 0; i--) { - keys.push(Object.keys(object[i])) - } - return keys - } else { - return Object.keys(object) + if (Object.prototype.toString.call(object) === '[object Array]') { + const keys = [] + for (let i = object.length - 1; i >= 0; i--) { + keys.push(Object.keys(object[i])) } + return keys + } else { + return Object.keys(object) + } } export const getContext = function () { - return this.ctx + return this.ctx } diff --git a/src/filters/filters.js b/src/filters/filters.js index 3d7ebcbc..ca5ef180 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -5,7 +5,6 @@ import xGovFilters from '@x-govuk/govuk-prototype-filters' const { govukMarkdown } = xGovFilters - const addFilters = (nunjucksEnv) => { nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) nunjucksEnv.addFilter('getkeys', getkeys) diff --git a/src/filters/validationMessageLookup.js b/src/filters/validationMessageLookup.js index 9b873d3f..c22a6e20 100644 --- a/src/filters/validationMessageLookup.js +++ b/src/filters/validationMessageLookup.js @@ -1,17 +1,17 @@ // import logger from '../utils/logger.js' const validationMessages = { - 'lpa': { + lpa: { required: 'Enter the name of your local planning authority' }, - 'name': { + name: { required: 'Enter your full name' }, - 'email': { + email: { required: 'Enter an email address', email: 'Enter an email address in the correct format' }, - 'dataset': { + dataset: { required: 'Select a dataset' }, 'endpoint-url': { @@ -24,7 +24,7 @@ const validationMessages = { format: 'Enter a valid URL', length: 'The URL must be less than 2048 characters' }, - 'hasLicence': { + hasLicence: { required: 'SYour data must be licensed under the Open Government Licence' } } From 8f43db1ae8c7ca65a7e510437ddc80b535198e6c Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 11:58:20 +0100 Subject: [PATCH 058/127] add length validation to endpoints --- src/routes/form-wizard/fields.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index f23d13e6..4cf460f5 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -19,17 +19,15 @@ export default { 'endpoint-url': { validate: [ 'required', - { - type: 'validUrl', fn: validUrl - } + { type: 'format', fn: validUrl }, + { type: 'length', max: 2048 } ] }, 'documentation-url': { validate: [ 'required', - { - type: 'validUrl', fn: validUrl - } + { type: 'format', fn: validUrl }, + { type: 'length', max: 2048 } ] }, hasLicence: { From 65003c1261c2a4eb17aa27130250c61b849a5fa9 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 11:58:51 +0100 Subject: [PATCH 059/127] add validation error messages to lpa details page --- src/views/lpa-details.html | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 11165def..722d0b6e 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -2,9 +2,16 @@ {% from "govuk/components/input/macro.njk" import govukInput %} {% from "govuk/components/button/macro.njk" import govukButton %} +{% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} + +{% set pageName = 'LPA details' %} {% block pageTitle %} - Lpa details – {{ serviceName }} + {% if errors | length %} + Error: {{super()}} + {% else %} + {{super()}} + {% endif %} {% endblock %} {% block beforeContent %} @@ -19,6 +26,13 @@
+ {% if errors | length %} + {{ govukErrorSummary({ + titleText: "There’s a problem", + errorList: errors | toErrorList + }) }} + {% endif %} +

Which LPA are you submitting data for?

@@ -34,7 +48,10 @@

}, id: "lpa", name: "lpa", - classes: "govuk-!-width-three-quarters" + classes: "govuk-!-width-three-quarters", + errorMessage: { + text: 'lpa' | validationMessageLookup(errors['lpa'].type) + } if 'lpa' in errors }) }} @@ -46,7 +63,10 @@

}, id: "name", name: "name", - classes: "govuk-!-width-three-quarters" + classes: "govuk-!-width-three-quarters", + errorMessage: { + text: 'name' | validationMessageLookup(errors['name'].type) + } if 'name' in errors }) }} @@ -58,7 +78,10 @@

}, id: "email", name: "email", - classes: "govuk-!-width-three-quarters" + classes: "govuk-!-width-three-quarters", + errorMessage: { + text: 'email' | validationMessageLookup(errors['email'].type) + } if 'email' in errors }) }} {{ govukButton({ From c6f7388c40d0733b7f8105a556814308e2a9ab29 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 14:05:06 +0100 Subject: [PATCH 060/127] make sure values are populated with any existing values --- src/views/lpa-details.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 722d0b6e..1ae67ad5 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -51,7 +51,8 @@

classes: "govuk-!-width-three-quarters", errorMessage: { text: 'lpa' | validationMessageLookup(errors['lpa'].type) - } if 'lpa' in errors + } if 'lpa' in errors, + value: values.lpa }) }} @@ -66,7 +67,8 @@

classes: "govuk-!-width-three-quarters", errorMessage: { text: 'name' | validationMessageLookup(errors['name'].type) - } if 'name' in errors + } if 'name' in errors, + value: values.name }) }} @@ -81,7 +83,8 @@

classes: "govuk-!-width-three-quarters", errorMessage: { text: 'email' | validationMessageLookup(errors['email'].type) - } if 'email' in errors + } if 'email' in errors, + value: values.email }) }} {{ govukButton({ From a3254af9b4d02e2cfb13277cf88d154bff1b21bc Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 14:06:05 +0100 Subject: [PATCH 061/127] add validation messages to choose-dataset page --- src/views/choose-dataset.html | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/views/choose-dataset.html b/src/views/choose-dataset.html index c58e6451..0808907a 100644 --- a/src/views/choose-dataset.html +++ b/src/views/choose-dataset.html @@ -2,11 +2,16 @@ {% from "govuk/components/radios/macro.njk" import govukRadios %} {% from "govuk/components/button/macro.njk" import govukButton %} +{% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} {% set pageName = "Choose dataset" %} {% block pageTitle %} - Choose dataset – {{ serviceName }} + {% if errors | length %} + Error: {{super()}} + {% else %} + {{super()}} + {% endif %} {% endblock %} {% block beforeContent %} @@ -23,6 +28,13 @@
+ {% if errors | length %} + {{ govukErrorSummary({ + titleText: "There’s a problem", + errorList: errors | toErrorList + }) }} + {% endif %} + {{ govukRadios({ idPrefix: "dataset", name: "dataset", @@ -34,7 +46,11 @@ } }, items: options.datasetItems, - value: data.dataset + value: data.dataset, + errorMessage: { + text: 'dataset' | validationMessageLookup(errors['dataset'].type) + } if 'dataset' in errors, + value: values.dataset }) }} {{ govukButton({ From e72efeb501ca13ae53e7325fa3d84e2d28e38bb3 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 14:12:43 +0100 Subject: [PATCH 062/127] add in error messages for dataset-details page --- src/views/dataset-details.html | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/views/dataset-details.html b/src/views/dataset-details.html index e9b5a1ba..44fcca37 100644 --- a/src/views/dataset-details.html +++ b/src/views/dataset-details.html @@ -3,11 +3,16 @@ {% from "govuk/components/input/macro.njk" import govukInput %} {% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %} {% from "govuk/components/button/macro.njk" import govukButton %} +{% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} {% set pageName = values['dataset'] + " details" %} {% block pageTitle %} - {{ pageName }} – {{ serviceName }} + {% if errors | length %} + Error: {{super()}} + {% else %} + {{super()}} + {% endif %} {% endblock %} {% block beforeContent %} @@ -28,6 +33,13 @@

+ {% if errors | length %} + {{ govukErrorSummary({ + titleText: "There’s a problem", + errorList: errors | toErrorList + }) }} + {% endif %} + {{ govukInput({ label: { text: "Endpoint URL", @@ -36,7 +48,11 @@

}, id: "endpoint-url", name: "endpoint-url", - classes: "govuk-!-width-three-quarters" + classes: "govuk-!-width-three-quarters", + errorMessage: { + text: 'endpoint-url' | validationMessageLookup(errors['endpoint-url'].type) + } if 'endpoint-url' in errors, + value: values['endpoint-url'] }) }} {{ govukInput({ @@ -50,7 +66,11 @@

}, id: "documentation-url", name: "documentation-url", - classes: "govuk-!-width-three-quarters" + classes: "govuk-!-width-three-quarters", + errorMessage: { + text: 'documentation-url' | validationMessageLookup(errors['documentation-url'].type) + } if 'documentation-url' in errors, + value: values['documentation-url'] }) }} {{ govukCheckboxes({ @@ -68,7 +88,10 @@

text: "I confirm this dataset is provided under the Open Government Licence", name: "hasLicence" } - ] + ], + errorMessage: { + text: 'hasLicence' | validationMessageLookup(errors['hasLicence'].type) + } if 'hasLicence' in errors }) }} {{ govukButton({ From 2ac9fecdf3a4533f3ff077cb75e1d6aa31876b30 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 14:12:55 +0100 Subject: [PATCH 063/127] improve validation error messages --- src/filters/validationMessageLookup.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/filters/validationMessageLookup.js b/src/filters/validationMessageLookup.js index c22a6e20..a5e5d0fa 100644 --- a/src/filters/validationMessageLookup.js +++ b/src/filters/validationMessageLookup.js @@ -15,17 +15,17 @@ const validationMessages = { required: 'Select a dataset' }, 'endpoint-url': { - required: 'Enter a URL', - format: 'Enter a valid URL', + required: 'Enter an endpoint URL', + format: 'Enter a valid endpoint URL', length: 'The URL must be less than 2048 characters' }, 'documentation-url': { - required: 'Enter a URL', - format: 'Enter a valid URL', + required: 'Enter a documentation URL', + format: 'Enter a valid documentation URL', length: 'The URL must be less than 2048 characters' }, hasLicence: { - required: 'SYour data must be licensed under the Open Government Licence' + required: 'Your data must be licensed under the Open Government Licence' } } From 3f4e23f2243d0d1f1a4296f1457674a41efae89e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 14:35:07 +0100 Subject: [PATCH 064/127] fix max length email validation --- src/filters/validationMessageLookup.js | 4 ++-- src/routes/form-wizard/fields.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/filters/validationMessageLookup.js b/src/filters/validationMessageLookup.js index a5e5d0fa..5bd571aa 100644 --- a/src/filters/validationMessageLookup.js +++ b/src/filters/validationMessageLookup.js @@ -17,12 +17,12 @@ const validationMessages = { 'endpoint-url': { required: 'Enter an endpoint URL', format: 'Enter a valid endpoint URL', - length: 'The URL must be less than 2048 characters' + maxlength: 'The URL must be less than 2048 characters' }, 'documentation-url': { required: 'Enter a documentation URL', format: 'Enter a valid documentation URL', - length: 'The URL must be less than 2048 characters' + maxlength: 'The URL must be less than 2048 characters' }, hasLicence: { required: 'Your data must be licensed under the Open Government Licence' diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js index 4cf460f5..aa640fcc 100644 --- a/src/routes/form-wizard/fields.js +++ b/src/routes/form-wizard/fields.js @@ -20,14 +20,14 @@ export default { validate: [ 'required', { type: 'format', fn: validUrl }, - { type: 'length', max: 2048 } + { type: 'maxlength', arguments: [2048] } ] }, 'documentation-url': { validate: [ 'required', { type: 'format', fn: validUrl }, - { type: 'length', max: 2048 } + { type: 'maxlength', arguments: [2048] } ] }, hasLicence: { From 32ce47e93b172cd6adce702c137afe72acf01e36 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 15:40:20 +0100 Subject: [PATCH 065/127] fix tests, rewrite generic tests to use jsdom and also add test function for validation exception messages --- package.json | 1 + test/unit/choose-datasetPage.test.js | 6 ++-- test/unit/dataset-details.test.html | 5 ++-- test/unit/generic-page.js | 23 ++++++---------- test/unit/lpa-detailsPage.test.js | 41 ++++++++++++++++++++++++---- test/unit/validation-tests.js | 22 +++++++++++++++ test/utils/stripWhiteSpace.js | 4 --- 7 files changed, 75 insertions(+), 27 deletions(-) create mode 100644 test/unit/validation-tests.js delete mode 100644 test/utils/stripWhiteSpace.js diff --git a/package.json b/package.json index e05a3a66..0d2f669c 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "license": "ISC", "devDependencies": { "husky": "^9.0.11", + "jsdom": "^24.1.0", "standard": "^17.1.0", "vitest": "^1.6.0" }, diff --git a/test/unit/choose-datasetPage.test.js b/test/unit/choose-datasetPage.test.js index 954943f6..348cd49f 100644 --- a/test/unit/choose-datasetPage.test.js +++ b/test/unit/choose-datasetPage.test.js @@ -6,11 +6,13 @@ import config from '../../config/index.js' const nunjucks = setupNunjucks() describe('choose dataset View', () => { - const params = {} + const params = { + errors: {} + } const html = nunjucks.render('choose-dataset.html', params) runGenericPageTests(html, { - pageTitle: `Choose dataset – ${config.serviceName}`, + pageTitle: `Choose dataset - ${config.serviceName}`, serviceName: config.serviceName }) }) diff --git a/test/unit/dataset-details.test.html b/test/unit/dataset-details.test.html index 0366bc03..ad65e926 100644 --- a/test/unit/dataset-details.test.html +++ b/test/unit/dataset-details.test.html @@ -10,13 +10,14 @@ const params = { values: { dataset: 'mockDataset' - } + }, + errors: {}, } const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) runGenericPageTests(html, { - pageTitle: `mockDataset details – ${config.serviceName}`, + pageTitle: `mockDataset details - ${config.serviceName}`, serviceName: config.serviceName }) diff --git a/test/unit/generic-page.js b/test/unit/generic-page.js index 281ca172..28814025 100644 --- a/test/unit/generic-page.js +++ b/test/unit/generic-page.js @@ -1,7 +1,7 @@ // this file holds unit tests that apply to all pages import { it, expect } from 'vitest' -import { stripWhitespace } from '../utils/stripWhiteSpace' +import jsdom from 'jsdom' /* Params: @@ -12,28 +12,23 @@ import { stripWhitespace } from '../utils/stripWhiteSpace' } */ export const runGenericPageTests = (html, options) => { - html = stripWhitespace(html) + const dom = new jsdom.JSDOM(html) + const document = dom.window.document it('should have the correct header', () => { - const govLogo = `` + const govLogo = document.querySelector('.govuk-header__logo') - expect(html).toContain(stripWhitespace(govLogo)) + expect(govLogo).not.toBeNull() - const regex = new RegExp(``, 'g') + const govLogoSvg = govLogo.querySelector('svg') - expect(html).toMatch(regex) + expect(govLogoSvg).not.toBeNull() + expect(govLogoSvg.getAttribute('aria-label')).toBe('GOV.UK') }) if (options.pageTitle) { it('should have the correct title', () => { - expect(html).toContain(stripWhitespace(` ${options.pageTitle} `)) + expect(document.title).toBe(options.pageTitle) }) } } diff --git a/test/unit/lpa-detailsPage.test.js b/test/unit/lpa-detailsPage.test.js index b084f63e..d330433f 100644 --- a/test/unit/lpa-detailsPage.test.js +++ b/test/unit/lpa-detailsPage.test.js @@ -1,16 +1,47 @@ -import { describe } from 'vitest' +import { describe, it } from 'vitest' import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' +import { testValidationErrorMessage } from './validation-tests.js' const nunjucks = setupNunjucks() describe('Lpa-details View', () => { - const params = {} - const html = nunjucks.render('lpa-details.html', params) + const params = { + errors: {} + } + const htmlNoErrors = nunjucks.render('lpa-details.html', params) - runGenericPageTests(html, { - pageTitle: `Lpa details – ${config.serviceName}`, + runGenericPageTests(htmlNoErrors, { + pageTitle: `LPA details - ${config.serviceName}`, serviceName: config.serviceName }) + + describe('validation errors', () => { + it('should display an error message when the lpa field is empty', () => { + const params = { + errors: { + lpa: { + type: 'required' + } + } + } + + const html = nunjucks.render('lpa-details.html', params) + + testValidationErrorMessage(html, 'lpa', 'Enter the name of your local planning authority') + }) + + // it('should display an error message when the name field is empty', () => { + + // }) + + // it('should display an error message when the email field is empty', () => { + + // }) + + // it('should display an error message when the email field is not a valid email', () => { + + // }) + }) }) diff --git a/test/unit/validation-tests.js b/test/unit/validation-tests.js new file mode 100644 index 00000000..c5b0875a --- /dev/null +++ b/test/unit/validation-tests.js @@ -0,0 +1,22 @@ +import { expect } from 'vitest' +import jsdom from 'jsdom' + +export const testValidationErrorMessage = (html, field, errorMessage) => { + const dom = new jsdom.JSDOM(html) + const document = dom.window.document + + const errorSummary = document.querySelector('.govuk-error-summary') + expect(errorSummary).not.toBeNull() + expect(errorSummary.textContent).toContain(errorMessage) + + const errorFields = document.querySelectorAll('.govuk-error-message') + expect(errorFields).not.toBeNull() + + let errorFieldExists = false + errorFields.forEach((errorField) => { + if (errorField.textContent.includes(errorMessage)) { + errorFieldExists = true + } + }) + expect(errorFieldExists).toBe(true) +} diff --git a/test/utils/stripWhiteSpace.js b/test/utils/stripWhiteSpace.js deleted file mode 100644 index 2aed5c5f..00000000 --- a/test/utils/stripWhiteSpace.js +++ /dev/null @@ -1,4 +0,0 @@ -// this function strips out unnecessary whitespace from our html to make sure comparisons are accurate -export const stripWhitespace = (str) => { - return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') -} From bd5a6239239ecf2351b4c4695ac15f002654afbe Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 15:43:40 +0100 Subject: [PATCH 066/127] add back in stripWhiteSpace utils function --- test/unit/utils/stripWhiteSpace.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 test/unit/utils/stripWhiteSpace.js diff --git a/test/unit/utils/stripWhiteSpace.js b/test/unit/utils/stripWhiteSpace.js new file mode 100644 index 00000000..93334417 --- /dev/null +++ b/test/unit/utils/stripWhiteSpace.js @@ -0,0 +1,5 @@ +// this function strips out unnecessary whitespace from our html to make sure comparisons are accurate +export const stripWhitespace = (str) => { + return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') + } + \ No newline at end of file From 55f11358ca616fd091a7dd8e8709c7a8beda8ec1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 15:43:48 +0100 Subject: [PATCH 067/127] linting --- test/unit/utils/stripWhiteSpace.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/unit/utils/stripWhiteSpace.js b/test/unit/utils/stripWhiteSpace.js index 93334417..2aed5c5f 100644 --- a/test/unit/utils/stripWhiteSpace.js +++ b/test/unit/utils/stripWhiteSpace.js @@ -1,5 +1,4 @@ // this function strips out unnecessary whitespace from our html to make sure comparisons are accurate export const stripWhitespace = (str) => { - return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') - } - \ No newline at end of file + return str.replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ').replace(/>\s+<').replace(/>\s+/g, '>').replace(/\s+/g, '>').replace(/<\s+/g, '<') +} From cf98f138abb230d0f33554042a2cf3f01fb5d9b0 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 15:44:16 +0100 Subject: [PATCH 068/127] move to correct location --- test/{unit => }/utils/stripWhiteSpace.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{unit => }/utils/stripWhiteSpace.js (100%) diff --git a/test/unit/utils/stripWhiteSpace.js b/test/utils/stripWhiteSpace.js similarity index 100% rename from test/unit/utils/stripWhiteSpace.js rename to test/utils/stripWhiteSpace.js From 3af4668964d05103f513f9ca57a0890bf3bb7742 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 15:44:42 +0100 Subject: [PATCH 069/127] add remaining validation tests for lpa-details page --- test/unit/lpa-detailsPage.test.js | 42 ++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/test/unit/lpa-detailsPage.test.js b/test/unit/lpa-detailsPage.test.js index d330433f..f1c5130c 100644 --- a/test/unit/lpa-detailsPage.test.js +++ b/test/unit/lpa-detailsPage.test.js @@ -32,16 +32,46 @@ describe('Lpa-details View', () => { testValidationErrorMessage(html, 'lpa', 'Enter the name of your local planning authority') }) - // it('should display an error message when the name field is empty', () => { + it('should display an error message when the name field is empty', () => { + const params = { + errors: { + name: { + type: 'required' + } + } + } + + const html = nunjucks.render('lpa-details.html', params) + + testValidationErrorMessage(html, 'name', 'Enter your full name') + }) + + it('should display an error message when the email field is empty', () => { + const params = { + errors: { + email: { + type: 'required' + } + } + } - // }) + const html = nunjucks.render('lpa-details.html', params) - // it('should display an error message when the email field is empty', () => { + testValidationErrorMessage(html, 'email', 'Enter an email address') + }) - // }) + it('should display an error message when the email field is not a valid email', () => { + const params = { + errors: { + email: { + type: 'email' + } + } + } - // it('should display an error message when the email field is not a valid email', () => { + const html = nunjucks.render('lpa-details.html', params) - // }) + testValidationErrorMessage(html, 'email', 'Enter an email address in the correct format') + }) }) }) From c83a4ef3bd35a673ed4370d965d6df14ec0f435b Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 2 Jul 2024 16:04:52 +0100 Subject: [PATCH 070/127] finish off the last fest tests and change file from .html to .js --- test/unit/choose-datasetPage.test.js | 17 +++- test/unit/dataset-details.test.html | 31 ------ test/unit/dataset-details.test.js | 137 +++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 32 deletions(-) delete mode 100644 test/unit/dataset-details.test.html create mode 100644 test/unit/dataset-details.test.js diff --git a/test/unit/choose-datasetPage.test.js b/test/unit/choose-datasetPage.test.js index 348cd49f..b9214817 100644 --- a/test/unit/choose-datasetPage.test.js +++ b/test/unit/choose-datasetPage.test.js @@ -1,7 +1,8 @@ -import { describe } from 'vitest' +import { describe, it } from 'vitest' import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' +import { testValidationErrorMessage } from './validation-tests.js' const nunjucks = setupNunjucks() @@ -15,4 +16,18 @@ describe('choose dataset View', () => { pageTitle: `Choose dataset - ${config.serviceName}`, serviceName: config.serviceName }) + + it('should display an error message when the dataset field is empty', () => { + const params = { + errors: { + dataset: { + type: 'required' + } + } + } + + const html = nunjucks.render('choose-dataset.html', params) + + testValidationErrorMessage(html, 'dataset', 'Select a dataset') + }) }) diff --git a/test/unit/dataset-details.test.html b/test/unit/dataset-details.test.html deleted file mode 100644 index ad65e926..00000000 --- a/test/unit/dataset-details.test.html +++ /dev/null @@ -1,31 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' -import { runGenericPageTests } from './generic-page.js' -import config from '../../config/index.js' -import { stripWhitespace } from '../utils/stripWhiteSpace.js' - -const nunjucks = setupNunjucks() - -describe('dataset details View', () => { - const params = { - values: { - dataset: 'mockDataset' - }, - errors: {}, - } - const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) - - - runGenericPageTests(html, { - pageTitle: `mockDataset details - ${config.serviceName}`, - serviceName: config.serviceName - }) - - it('should render the correct header', () => { - expect(html).toMatch - - const regex = new RegExp(`

`, 'g') - - expect(html).toMatch(regex) - }) -}) diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js new file mode 100644 index 00000000..dc180120 --- /dev/null +++ b/test/unit/dataset-details.test.js @@ -0,0 +1,137 @@ +/* eslint-disable prefer-regex-literals */ + +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from './generic-page.js' +import config from '../../config/index.js' +import { stripWhitespace } from '../utils/stripWhiteSpace.js' +import { testValidationErrorMessage } from './validation-tests.js' + +const nunjucks = setupNunjucks() + +describe('dataset details View', () => { + const params = { + values: { + dataset: 'mockDataset' + }, + errors: {} + } + const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) + + runGenericPageTests(html, { + pageTitle: `mockDataset details - ${config.serviceName}`, + serviceName: config.serviceName + }) + + it('should render the correct header', () => { + const regex = new RegExp('

', 'g') + + expect(html).toMatch(regex) + }) + + describe('validation error messages', () => { + describe('endpoint-url', () => { + it('should display an error message when the endpoint-url field is empty', () => { + const params = { + errors: { + 'endpoint-url': { + type: 'required' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'endpoint-url', 'Enter an endpoint URL') + }) + + it('should display an error message when the endpoint-url is not a valid URL', () => { + const params = { + errors: { + 'endpoint-url': { + type: 'format' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'endpoint-url', 'Enter a valid endpoint URL') + }) + + it('should display an error message when the endpoint-url is too long', () => { + const params = { + errors: { + 'endpoint-url': { + type: 'maxlength' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'endpoint-url', 'The URL must be less than 2048 characters') + }) + }) + + describe('documentation-url', () => { + it('should display an error message when the documentation-url field is empty', () => { + const params = { + errors: { + 'documentation-url': { + type: 'required' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'documentation-url', 'Enter a documentation URL') + }) + + it('should display an error message when the documentation-url is not a valid URL', () => { + const params = { + errors: { + 'documentation-url': { + type: 'format' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'documentation-url', 'Enter a valid documentation URL') + }) + + it('should display an error message when the documentation-url is too long', () => { + const params = { + errors: { + 'documentation-url': { + type: 'maxlength' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'documentation-url', 'The URL must be less than 2048 characters') + }) + }) + + describe('hasLicence', () => { + it('should display an error message when the hasLicence field is empty', () => { + const params = { + errors: { + hasLicence: { + type: 'required' + } + } + } + + const html = nunjucks.render('dataset-details.html', params) + + testValidationErrorMessage(html, 'hasLicence', 'Your data must be licensed under the Open Government Licence') + }) + }) + }) +}) From f385a1caf093ab699bbc944995934ef493cffd45 Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Tue, 2 Jul 2024 16:06:09 +0100 Subject: [PATCH 071/127] added missing dependencies --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index 80cfe4a6..25f0abab 100644 --- a/package.json +++ b/package.json @@ -22,12 +22,16 @@ "dependencies": { "@x-govuk/govuk-prototype-components": "^3.0.5", "@x-govuk/govuk-prototype-filters": "^1.4.0", + "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", + "express": "^4.19.2", "express-session": "^1.18.0", "govuk-frontend": "^5.4.0", "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", "hmpo-i18n": "^6.0.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", "nunjucks": "^3.2.4" } } From ef80c9988f5da66a3e99cc180ef4227d0c0f8ed8 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 14:48:18 +0100 Subject: [PATCH 072/127] remove needless assertions --- test/unit/checkAnswersController.test.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js index d6f94b0c..b972a595 100644 --- a/test/unit/checkAnswersController.test.js +++ b/test/unit/checkAnswersController.test.js @@ -44,13 +44,6 @@ describe('Check answers controller', () => { checkAnswersController.sendEmails(req, res, next) - expect(req.sessionModel.get).toHaveBeenCalledWith('name') - expect(req.sessionModel.get).toHaveBeenCalledWith('email') - expect(req.sessionModel.get).toHaveBeenCalledWith('lpa') - expect(req.sessionModel.get).toHaveBeenCalledWith('dataset') - expect(req.sessionModel.get).toHaveBeenCalledWith('documentation-url') - expect(req.sessionModel.get).toHaveBeenCalledWith('endpoint-url') - expect(sendEmailMock).toHaveBeenCalledWith(config.email.dataManagementEmail, config.email.templates.RequestTemplateId, { name: 'John Doe', email: 'JohnDoe@mail.com', From 047475efd3541ad9417a43aaa105fbf5ab31bb57 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 15:04:21 +0100 Subject: [PATCH 073/127] change mailClient to use a singleton instead of a wrapper function --- src/controllers/CheckAnswersController.js | 50 ++++++++++++++--------- src/utils/mailClient.js | 25 ++++++++---- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index 699ed5f0..97f40859 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -1,7 +1,8 @@ import PageController from './pageController.js' -import { sendEmail } from '../utils/mailClient.js' +import NotifyClientSingleton from './NotifyClientSingleton'; import config from '../../config/index.js' +const notifyClient = NotifyClientSingleton.getInstance(); const dataManagementEmail = config.email.dataManagementEmail class CheckAnswersController extends PageController { @@ -31,25 +32,36 @@ class CheckAnswersController extends PageController { const { RequestTemplateId, AcknowledgementTemplateId } = config.email.templates - // send request email to data management team - sendEmail(dataManagementEmail, RequestTemplateId, { - name, - email, - organisation, - endpoint, - 'documentation-url': documentationUrl, - dataset - }) - - // send acknowledgement email to LPA - sendEmail(email, AcknowledgementTemplateId, { - name, + // ToDo: handle errors when sending emails + notifyClient.sendEmail( + RequestTemplateId, + dataManagementEmail, + { + personalisation: { + name, + email, + organisation, + endpoint, + 'documentation-url': documentationUrl, + dataset + } + } + ) + + notifyClient.sendEmail( + AcknowledgementTemplateId, email, - organisation, - endpoint, - 'documentation-url': documentationUrl, - dataset - }) + { + personalisation: { + name, + email, + organisation, + endpoint, + 'documentation-url': documentationUrl, + dataset + } + } + ) } } diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index 5b12dc1a..b19891e8 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -1,12 +1,21 @@ -import { NotifyClient } from 'notifications-node-client' +import { NotifyClient } from 'notifications-node-client'; +import dotenv from 'dotenv'; -import dotenv from 'dotenv' -dotenv.config() +dotenv.config(); -const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') +class NotifyClientSingleton { + static instance; -export const sendEmail = async (emailAddress, templateId, personalisation) => { - return notifyClient.sendEmail(templateId, emailAddress, { personalisation }) - .then(response => console.log(response)) - .catch(err => console.error(err)) + constructor() { + throw new Error('Use NotifyClientSingleton.getInstance()'); + } + + static getInstance() { + if (!NotifyClientSingleton.instance) { + NotifyClientSingleton.instance = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key'); + } + return NotifyClientSingleton.instance; + } } + +export default NotifyClientSingleton; \ No newline at end of file From f3fc6c3a0fc8c9cec1152ededabbf92ee5887f75 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 15:04:28 +0100 Subject: [PATCH 074/127] linting --- src/controllers/CheckAnswersController.js | 12 ++++++------ src/utils/mailClient.js | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index 97f40859..7adcd86c 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -1,8 +1,8 @@ import PageController from './pageController.js' -import NotifyClientSingleton from './NotifyClientSingleton'; +import NotifyClientSingleton from './NotifyClientSingleton' import config from '../../config/index.js' -const notifyClient = NotifyClientSingleton.getInstance(); +const notifyClient = NotifyClientSingleton.getInstance() const dataManagementEmail = config.email.dataManagementEmail class CheckAnswersController extends PageController { @@ -34,9 +34,9 @@ class CheckAnswersController extends PageController { // ToDo: handle errors when sending emails notifyClient.sendEmail( - RequestTemplateId, - dataManagementEmail, - { + RequestTemplateId, + dataManagementEmail, + { personalisation: { name, email, @@ -44,7 +44,7 @@ class CheckAnswersController extends PageController { endpoint, 'documentation-url': documentationUrl, dataset - } + } } ) diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index b19891e8..3be03bfc 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -1,21 +1,21 @@ -import { NotifyClient } from 'notifications-node-client'; -import dotenv from 'dotenv'; +import { NotifyClient } from 'notifications-node-client' +import dotenv from 'dotenv' -dotenv.config(); +dotenv.config() class NotifyClientSingleton { - static instance; + static instance - constructor() { - throw new Error('Use NotifyClientSingleton.getInstance()'); + constructor () { + throw new Error('Use NotifyClientSingleton.getInstance()') } - static getInstance() { + static getInstance () { if (!NotifyClientSingleton.instance) { - NotifyClientSingleton.instance = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key'); + NotifyClientSingleton.instance = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') } - return NotifyClientSingleton.instance; + return NotifyClientSingleton.instance } } -export default NotifyClientSingleton; \ No newline at end of file +export default NotifyClientSingleton From 33434c59aad5bc9d742941d7d727093d4be1e6e7 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 15:52:47 +0100 Subject: [PATCH 075/127] import singleton from correct place --- src/controllers/CheckAnswersController.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index 7adcd86c..ab3b5cfe 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -1,5 +1,5 @@ import PageController from './pageController.js' -import NotifyClientSingleton from './NotifyClientSingleton' +import NotifyClientSingleton from '../utils/mailClient.js' import config from '../../config/index.js' const notifyClient = NotifyClientSingleton.getInstance() From 01c2a1094e449d59c4dfb1fddfa7c7b57f8e41c2 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 15:52:56 +0100 Subject: [PATCH 076/127] fixed tests --- test/unit/checkAnswersController.test.js | 69 +++++++++++++++--------- test/unit/mailClient.test.js | 52 ++++++------------ 2 files changed, 61 insertions(+), 60 deletions(-) diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js index b972a595..514a1f8e 100644 --- a/test/unit/checkAnswersController.test.js +++ b/test/unit/checkAnswersController.test.js @@ -1,23 +1,30 @@ -import CheckAnswersController from '../../src/controllers/CheckAnswersController.js' +/* eslint-disable new-cap */ import { describe, it, vi, expect, beforeEach } from 'vitest' +import NotifyClientSingleton from '../../src/utils/mailClient.js' import config from '../../config/index.js' -import { sendEmail } from '../../src/utils/mailClient.js' -vi.mock('../../src/utils/mailClient.js') +vi.mock('../../src/utils/mailClient.js', () => ({ + default: { + getInstance: vi.fn() + } +})) describe('Check answers controller', () => { + let CheckAnswersController let checkAnswersController let sendEmailMock - beforeEach(() => { - checkAnswersController = new CheckAnswersController({ + beforeEach(async () => { + // Setup a mock for sendEmail function + sendEmailMock = vi.fn() + NotifyClientSingleton.getInstance = vi.fn().mockReturnValue({ + sendEmail: sendEmailMock + }) + CheckAnswersController = await vi.importActual('../../src/controllers/CheckAnswersController.js') + checkAnswersController = new CheckAnswersController.default({ route: '/dataset' }) - - sendEmailMock = vi.fn() - - sendEmail.mockImplementation(sendEmailMock) }) describe('send emails', () => { @@ -44,23 +51,35 @@ describe('Check answers controller', () => { checkAnswersController.sendEmails(req, res, next) - expect(sendEmailMock).toHaveBeenCalledWith(config.email.dataManagementEmail, config.email.templates.RequestTemplateId, { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - dataset: 'Dataset', - 'documentation-url': 'Documentation URL', - endpoint: 'Endpoint URL' - }) + expect(sendEmailMock).toHaveBeenCalledWith( + config.email.templates.RequestTemplateId, + config.email.dataManagementEmail, + { + personalisation: { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + endpoint: 'Endpoint URL' + } + } + ) - expect(sendEmailMock).toHaveBeenCalledWith('JohnDoe@mail.com', config.email.templates.AcknowledgementTemplateId, { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - endpoint: 'Endpoint URL', - 'documentation-url': 'Documentation URL', - dataset: 'Dataset' - }) + expect(sendEmailMock).toHaveBeenCalledWith( + config.email.templates.AcknowledgementTemplateId, + 'JohnDoe@mail.com', + { + personalisation: { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + endpoint: 'Endpoint URL', + 'documentation-url': 'Documentation URL', + dataset: 'Dataset' + } + } + ) }) }) }) diff --git a/test/unit/mailClient.test.js b/test/unit/mailClient.test.js index 2aab2969..85dc54fa 100644 --- a/test/unit/mailClient.test.js +++ b/test/unit/mailClient.test.js @@ -1,47 +1,29 @@ -import { describe, expect, it, vi, beforeEach } from 'vitest' - -import { sendEmail } from '../../src/utils/mailClient' +import { describe, it, beforeEach, vi, expect } from 'vitest' +import NotifyClientSingleton from '../../src/utils/mailClient' import { NotifyClient } from 'notifications-node-client' -const sendEmailMock = vi.spyOn(NotifyClient.prototype, 'sendEmail') +vi.mock('notifications-node-client') -describe('sendEmail', () => { +describe('NotifyClientSingleton', () => { beforeEach(() => { - vi.clearAllMocks() + // Clear instance for isolation between tests + NotifyClientSingleton.instance = null + NotifyClient.mockClear() }) - it('should call NotifyClient.sendEmail with correct parameters', async () => { - const emailAddress = 'test@example.com' - const templateId = 'template-id' - const personalisation = { name: 'John Doe' } - - await sendEmail(emailAddress, templateId, personalisation) - - expect(sendEmailMock).toHaveBeenCalledWith(templateId, emailAddress, { personalisation }) + it('throws error when trying to instantiate directly', () => { + expect(() => new NotifyClientSingleton()).toThrow('Use NotifyClientSingleton.getInstance()') }) - it('should log the response on successful email send', async () => { - const consoleMock = vi.spyOn(global.console, 'log').mockImplementation(() => undefined) - - const response = { id: '12345', content: { body: 'Test email content', subject: 'Test' } } - sendEmailMock.mockResolvedValue(response) // Explicitly resolve with a response - - await sendEmail('test@example.com', 'template-id', { name: 'John Doe' }) - - expect(consoleMock).toHaveBeenCalledWith(response) + it('getInstance returns the same instance for multiple calls', () => { + const firstInstance = NotifyClientSingleton.getInstance() + const secondInstance = NotifyClientSingleton.getInstance() + expect(firstInstance).toBe(secondInstance) }) - it('should log an error if email sending fails', async () => { - console.error = vi.fn() - const error = new Error('Failed to send email') - sendEmailMock.mockRejectedValue(error) // Explicitly reject with an error - - try { - await sendEmail('test@example.com', 'template-id', { name: 'John Doe' }) - } catch (e) { - // Catch the error to prevent the test from failing due to unhandled rejection - } - - expect(console.error).toHaveBeenCalledWith(error) + it('getInstance creates an instance with the correct API key', () => { + process.env.GOVUK_NOTIFY_API_KEY = 'test-api-key' + NotifyClientSingleton.getInstance() + expect(NotifyClient).toHaveBeenCalledWith('test-api-key') }) }) From 894167f718c1ede46c1ba5c59cda0c20f57b5726 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 15:59:21 +0100 Subject: [PATCH 077/127] refactor code --- src/filters/debuggingFilters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filters/debuggingFilters.js b/src/filters/debuggingFilters.js index 219a227f..cfd2c443 100644 --- a/src/filters/debuggingFilters.js +++ b/src/filters/debuggingFilters.js @@ -1,7 +1,7 @@ // some additional filters useful for debugging: export const getkeys = function (object) { - if (Object.prototype.toString.call(object) === '[object Array]') { + if (Array.isArray(object)) { const keys = [] for (let i = object.length - 1; i >= 0; i--) { keys.push(Object.keys(object[i])) From 8ccf0ed8f7f1eb4e0d6cec8f29af5b992cc786ff Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 16:59:47 +0100 Subject: [PATCH 078/127] make sure path to assets is correct --- src/serverSetup/middlewares.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serverSetup/middlewares.js b/src/serverSetup/middlewares.js index 65c76327..1ce70d60 100644 --- a/src/serverSetup/middlewares.js +++ b/src/serverSetup/middlewares.js @@ -17,7 +17,7 @@ export function setupMiddlewares (app) { // next() // }) - app.use('/assets', express.static('./node_modules/govuk-frontend/govuk/assets')) + app.use('/assets', express.static('./node_modules/govuk-frontend/dist/govuk/assets')) app.use('/public', express.static('./public')) app.use(cookieParser()) From 0f1c27ea9b55f827288ddda17773f9c5eed70809 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 3 Jul 2024 17:00:01 +0100 Subject: [PATCH 079/127] remove hangover bundle script --- src/views/layouts/main.html | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/layouts/main.html b/src/views/layouts/main.html index 40ecb5f1..7dbc2881 100644 --- a/src/views/layouts/main.html +++ b/src/views/layouts/main.html @@ -70,6 +70,5 @@

Get help

{{ super()}} {%block scripts %} {{ super() }} - {% endblock %} {% endblock %} \ No newline at end of file From 8f9ee361c56a3b6df9fd0c695ad35927ba9207b2 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 13:56:51 +0100 Subject: [PATCH 080/127] addressing rolands comments --- src/controllers/CheckAnswersController.js | 3 +-- src/utils/mailClient.js | 16 ++----------- test/unit/checkAnswersController.test.js | 12 +++------- test/unit/mailClient.test.js | 29 ----------------------- 4 files changed, 6 insertions(+), 54 deletions(-) delete mode 100644 test/unit/mailClient.test.js diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index ab3b5cfe..23392f2f 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -1,8 +1,7 @@ import PageController from './pageController.js' -import NotifyClientSingleton from '../utils/mailClient.js' +import notifyClient from '../utils/mailClient.js' import config from '../../config/index.js' -const notifyClient = NotifyClientSingleton.getInstance() const dataManagementEmail = config.email.dataManagementEmail class CheckAnswersController extends PageController { diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index 3be03bfc..331b3824 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -3,19 +3,7 @@ import dotenv from 'dotenv' dotenv.config() -class NotifyClientSingleton { - static instance +const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') - constructor () { - throw new Error('Use NotifyClientSingleton.getInstance()') - } - static getInstance () { - if (!NotifyClientSingleton.instance) { - NotifyClientSingleton.instance = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') - } - return NotifyClientSingleton.instance - } -} - -export default NotifyClientSingleton +export default notifyClient diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js index 514a1f8e..9a6ae6b1 100644 --- a/test/unit/checkAnswersController.test.js +++ b/test/unit/checkAnswersController.test.js @@ -1,14 +1,10 @@ /* eslint-disable new-cap */ import { describe, it, vi, expect, beforeEach } from 'vitest' -import NotifyClientSingleton from '../../src/utils/mailClient.js' +import notifyClient from '../../src/utils/mailClient.js' import config from '../../config/index.js' -vi.mock('../../src/utils/mailClient.js', () => ({ - default: { - getInstance: vi.fn() - } -})) +vi.mock('../../src/utils/mailClient.js') describe('Check answers controller', () => { let CheckAnswersController @@ -18,9 +14,7 @@ describe('Check answers controller', () => { beforeEach(async () => { // Setup a mock for sendEmail function sendEmailMock = vi.fn() - NotifyClientSingleton.getInstance = vi.fn().mockReturnValue({ - sendEmail: sendEmailMock - }) + notifyClient.sendEmail = sendEmailMock CheckAnswersController = await vi.importActual('../../src/controllers/CheckAnswersController.js') checkAnswersController = new CheckAnswersController.default({ route: '/dataset' diff --git a/test/unit/mailClient.test.js b/test/unit/mailClient.test.js deleted file mode 100644 index 85dc54fa..00000000 --- a/test/unit/mailClient.test.js +++ /dev/null @@ -1,29 +0,0 @@ -import { describe, it, beforeEach, vi, expect } from 'vitest' -import NotifyClientSingleton from '../../src/utils/mailClient' -import { NotifyClient } from 'notifications-node-client' - -vi.mock('notifications-node-client') - -describe('NotifyClientSingleton', () => { - beforeEach(() => { - // Clear instance for isolation between tests - NotifyClientSingleton.instance = null - NotifyClient.mockClear() - }) - - it('throws error when trying to instantiate directly', () => { - expect(() => new NotifyClientSingleton()).toThrow('Use NotifyClientSingleton.getInstance()') - }) - - it('getInstance returns the same instance for multiple calls', () => { - const firstInstance = NotifyClientSingleton.getInstance() - const secondInstance = NotifyClientSingleton.getInstance() - expect(firstInstance).toBe(secondInstance) - }) - - it('getInstance creates an instance with the correct API key', () => { - process.env.GOVUK_NOTIFY_API_KEY = 'test-api-key' - NotifyClientSingleton.getInstance() - expect(NotifyClient).toHaveBeenCalledWith('test-api-key') - }) -}) From 49cded4d181492af976be0cf96059f5036b0a20c Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 13:56:57 +0100 Subject: [PATCH 081/127] linting --- src/utils/mailClient.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils/mailClient.js b/src/utils/mailClient.js index 331b3824..c9739167 100644 --- a/src/utils/mailClient.js +++ b/src/utils/mailClient.js @@ -5,5 +5,4 @@ dotenv.config() const notifyClient = new NotifyClient(process.env.GOVUK_NOTIFY_API_KEY || 'test-key') - export default notifyClient From a81ddb2b5ebdbddb22fcff62adf556e6f59ca1a1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 15:06:52 +0100 Subject: [PATCH 082/127] initial commit for alex to review --- package.json | 7 +++--- src/controllers/lpaDetailsController.js | 19 ++++++++++++++++ src/routes/form-wizard/steps.js | 2 ++ src/utils/fetchLocalAuthorities.js | 12 ++++++++++ src/views/lpa-details.html | 29 +++++++++++++++---------- 5 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 src/controllers/lpaDetailsController.js create mode 100644 src/utils/fetchLocalAuthorities.js diff --git a/package.json b/package.json index 25f0abab..a8908a72 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,14 @@ "vitest": "^1.6.0" }, "dependencies": { - "@x-govuk/govuk-prototype-components": "^3.0.5", - "@x-govuk/govuk-prototype-filters": "^1.4.0", + "@x-govuk/govuk-prototype-components": "^3.0.4", + "@x-govuk/govuk-prototype-filters": "1.3.1", + "axios": "^1.7.2", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", "express": "^4.19.2", "express-session": "^1.18.0", - "govuk-frontend": "^5.4.0", + "govuk-frontend": "5.3.0", "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", "hmpo-i18n": "^6.0.1", diff --git a/src/controllers/lpaDetailsController.js b/src/controllers/lpaDetailsController.js new file mode 100644 index 00000000..f9054c6f --- /dev/null +++ b/src/controllers/lpaDetailsController.js @@ -0,0 +1,19 @@ +import PageController from './pageController.js' +import fetchLocalAuthorities from '../utils/fetchLocalAuthorities.js' + +class lpaDetailsController extends PageController { + async locals (req, res, next) { + const localAuthorities = await fetchLocalAuthorities() + + const localAuthoritiesNames = localAuthorities.entities.map(lpa => ({ + text: lpa.name, + value: lpa.name + })) + + req.form.options.localAuthorities = localAuthoritiesNames + + super.locals(req, res, next) + } +} + +export default lpaDetailsController diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index b5ec2e10..f98ef8d9 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,4 +1,5 @@ import chooseDatasetController from '../../controllers/chooseDatasetController.js' +import lpaDetailsController from '../../controllers/lpaDetailsController.js' import PageController from '../../controllers/pageController.js' const defaultParams = { @@ -18,6 +19,7 @@ export default { ...defaultParams, fields: ['lpa', 'name', 'email'], next: 'choose-dataset', + controller: lpaDetailsController, backLink: '/start' }, '/choose-dataset': { diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js new file mode 100644 index 00000000..babfeac2 --- /dev/null +++ b/src/utils/fetchLocalAuthorities.js @@ -0,0 +1,12 @@ +import axios from 'axios'; + +export default async () => { + const url = "https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500"; + try { + const response = await axios.get(url); + return response.data; // Return the fetched data + } catch (error) { + console.error('Error fetching local authorities data:', error); + throw error; // Rethrow the error to be handled by the caller + } +} \ No newline at end of file diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 11165def..e9fc0d47 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -2,6 +2,11 @@ {% from "govuk/components/input/macro.njk" import govukInput %} {% from "govuk/components/button/macro.njk" import govukButton %} +{% from "x-govuk/components/autocomplete/macro.njk" import xGovukAutocomplete %} + +{% block headTitle %} + Lpa details – {{ serviceName }} +{% endblock %} {% block pageTitle %} Lpa details – {{ serviceName }} @@ -25,18 +30,18 @@

- {{ - govukInput({ - label: { - text: "Local planning authority", - classes: "govuk-label--m", - isPageHeading: false - }, - id: "lpa", - name: "lpa", - classes: "govuk-!-width-three-quarters" - }) - }} + {{ xGovukAutocomplete({ + id: "lpa", + name: "lpa", + allowEmpty: false, + label: { + classes: "govuk-label--m", + isPageHeading: false, + text: "Choose your local planning authority" + }, + items: options.localAuthorities + }) }} + {{ govukInput({ label: { From 251292be6e967122b5f4aa80441fbca8c165cee3 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 15:07:03 +0100 Subject: [PATCH 083/127] linting --- src/controllers/lpaDetailsController.js | 4 ++-- src/utils/fetchLocalAuthorities.js | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/controllers/lpaDetailsController.js b/src/controllers/lpaDetailsController.js index f9054c6f..1725b29d 100644 --- a/src/controllers/lpaDetailsController.js +++ b/src/controllers/lpaDetailsController.js @@ -6,8 +6,8 @@ class lpaDetailsController extends PageController { const localAuthorities = await fetchLocalAuthorities() const localAuthoritiesNames = localAuthorities.entities.map(lpa => ({ - text: lpa.name, - value: lpa.name + text: lpa.name, + value: lpa.name })) req.form.options.localAuthorities = localAuthoritiesNames diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index babfeac2..bd98bb86 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -1,12 +1,12 @@ -import axios from 'axios'; +import axios from 'axios' export default async () => { - const url = "https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500"; + const url = 'https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500' try { - const response = await axios.get(url); - return response.data; // Return the fetched data + const response = await axios.get(url) + return response.data // Return the fetched data } catch (error) { - console.error('Error fetching local authorities data:', error); - throw error; // Rethrow the error to be handled by the caller + console.error('Error fetching local authorities data:', error) + throw error // Rethrow the error to be handled by the caller } -} \ No newline at end of file +} From aa1f7ed9565eef9d1bf5a134707176c8ecef6015 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 15:12:16 +0100 Subject: [PATCH 084/127] add in missing package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 994a175d..0bf99be6 100644 --- a/package.json +++ b/package.json @@ -31,9 +31,9 @@ "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", "hmpo-i18n": "^6.0.1", - "notifications-node-client": "^8.2.0", "js-yaml": "^4.1.0", "lodash": "^4.17.21", + "notifications-node-client": "^8.2.0", "nunjucks": "^3.2.4" } } From f5014403cdda94cde57b5d85c97cd7a5b5b97476 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 16:15:54 +0100 Subject: [PATCH 085/127] include x-gov javascript file --- src/serverSetup/middlewares.js | 1 + src/views/layouts/main.html | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/serverSetup/middlewares.js b/src/serverSetup/middlewares.js index 1ce70d60..44fd46b2 100644 --- a/src/serverSetup/middlewares.js +++ b/src/serverSetup/middlewares.js @@ -18,6 +18,7 @@ export function setupMiddlewares (app) { // }) app.use('/assets', express.static('./node_modules/govuk-frontend/dist/govuk/assets')) + app.use('/assets', express.static('./node_modules/@x-govuk/govuk-prototype-components/x-govuk')) app.use('/public', express.static('./public')) app.use(cookieParser()) diff --git a/src/views/layouts/main.html b/src/views/layouts/main.html index 7dbc2881..7301ef0f 100644 --- a/src/views/layouts/main.html +++ b/src/views/layouts/main.html @@ -69,6 +69,13 @@

Get help

{% block bodyEnd %} {{ super()}} {%block scripts %} + + ... + + + {{ super() }} {% endblock %} {% endblock %} \ No newline at end of file From 9d662670a2c4554e9c04604db9c83703e487a909 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Thu, 4 Jul 2024 16:34:44 +0100 Subject: [PATCH 086/127] change endpoint to large list of orgs instead of just lpas --- src/controllers/lpaDetailsController.js | 10 +++++----- src/utils/fetchLocalAuthorities.js | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/controllers/lpaDetailsController.js b/src/controllers/lpaDetailsController.js index 1725b29d..9468040e 100644 --- a/src/controllers/lpaDetailsController.js +++ b/src/controllers/lpaDetailsController.js @@ -3,14 +3,14 @@ import fetchLocalAuthorities from '../utils/fetchLocalAuthorities.js' class lpaDetailsController extends PageController { async locals (req, res, next) { - const localAuthorities = await fetchLocalAuthorities() + const localAuthoritiesNames = await fetchLocalAuthorities() - const localAuthoritiesNames = localAuthorities.entities.map(lpa => ({ - text: lpa.name, - value: lpa.name + const listItems = localAuthoritiesNames.map(name => ({ + text: name, + value: name })) - req.form.options.localAuthorities = localAuthoritiesNames + req.form.options.localAuthorities = listItems super.locals(req, res, next) } diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index bd98bb86..69147ba7 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -1,10 +1,12 @@ import axios from 'axios' export default async () => { - const url = 'https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500' + // const url = 'https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500' + const url = 'https://datasette.planning.data.gov.uk/digital-land.json?sql=select%0D%0A++distinct+provision.organisation%2C%0D%0A++organisation.name%2C%0D%0A++organisation.dataset%0D%0Afrom%0D%0A++provision%2C%0D%0A++organisation%0D%0Awhere%0D%0A++provision.organisation+%3D+organisation.organisation%0D%0Aorder+by%0D%0A++provision.organisation' try { const response = await axios.get(url) - return response.data // Return the fetched data + const names = response.data.rows.map(row => row[1]) + return names // Return the fetched data } catch (error) { console.error('Error fetching local authorities data:', error) throw error // Rethrow the error to be handled by the caller From 3cfbd83e057f1d71416a155ddcad3391112aa32f Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 13:23:32 +0100 Subject: [PATCH 087/127] updated hasLicence validation message --- src/filters/validationMessageLookup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filters/validationMessageLookup.js b/src/filters/validationMessageLookup.js index 5bd571aa..ba90788b 100644 --- a/src/filters/validationMessageLookup.js +++ b/src/filters/validationMessageLookup.js @@ -25,7 +25,7 @@ const validationMessages = { maxlength: 'The URL must be less than 2048 characters' }, hasLicence: { - required: 'Your data must be licensed under the Open Government Licence' + required: 'You need to confirm this dataset is provided under the Open Government Licence' } } From 1941c72e23ac092724256dee260219df52338c89 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 13:30:05 +0100 Subject: [PATCH 088/127] fix test --- test/unit/dataset-details.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js index dc180120..fccb6e00 100644 --- a/test/unit/dataset-details.test.js +++ b/test/unit/dataset-details.test.js @@ -130,7 +130,7 @@ describe('dataset details View', () => { const html = nunjucks.render('dataset-details.html', params) - testValidationErrorMessage(html, 'hasLicence', 'Your data must be licensed under the Open Government Licence') + testValidationErrorMessage(html, 'hasLicence', 'You need to confirm this dataset is provided under the Open Government Licence') }) }) }) From efbe76cea78c480f24d899b653515b7a715c43c1 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 13:52:57 +0100 Subject: [PATCH 089/127] add jsdoc to fetch local authorities --- src/utils/fetchLocalAuthorities.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index 69147ba7..daa6afdb 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -1,5 +1,15 @@ import axios from 'axios' +/** + * Fetches a list of local authority names from a specified dataset. + * + * This function queries a dataset for local authorities, extracting a distinct list of names. + * It performs an HTTP GET request to retrieve the data, then processes the response to return + * only the names of the local authorities. + * + * @returns {Promise} A promise that resolves to an array of local authority names. + * @throws {Error} Throws an error if the HTTP request fails or data processing encounters an issue. + */ export default async () => { // const url = 'https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500' const url = 'https://datasette.planning.data.gov.uk/digital-land.json?sql=select%0D%0A++distinct+provision.organisation%2C%0D%0A++organisation.name%2C%0D%0A++organisation.dataset%0D%0Afrom%0D%0A++provision%2C%0D%0A++organisation%0D%0Awhere%0D%0A++provision.organisation+%3D+organisation.organisation%0D%0Aorder+by%0D%0A++provision.organisation' From bc5cd91c3a2939c9596a7a56587d096525c54e19 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 13:54:37 +0100 Subject: [PATCH 090/127] pull out sql --- src/utils/fetchLocalAuthorities.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index daa6afdb..1946995b 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -2,17 +2,28 @@ import axios from 'axios' /** * Fetches a list of local authority names from a specified dataset. - * + * * This function queries a dataset for local authorities, extracting a distinct list of names. * It performs an HTTP GET request to retrieve the data, then processes the response to return * only the names of the local authorities. - * + * * @returns {Promise} A promise that resolves to an array of local authority names. * @throws {Error} Throws an error if the HTTP request fails or data processing encounters an issue. */ export default async () => { - // const url = 'https://www.planning.data.gov.uk/entity.json?dataset=local-authority&limit=500' - const url = 'https://datasette.planning.data.gov.uk/digital-land.json?sql=select%0D%0A++distinct+provision.organisation%2C%0D%0A++organisation.name%2C%0D%0A++organisation.dataset%0D%0Afrom%0D%0A++provision%2C%0D%0A++organisation%0D%0Awhere%0D%0A++provision.organisation+%3D+organisation.organisation%0D%0Aorder+by%0D%0A++provision.organisation' + const sql = `select + distinct provision.organisation, + organisation.name, + organisation.dataset + from + provision, + organisation + where + provision.organisation = organisation.organisation + order by + provision.organisation`; + + const url = `https://datasette.planning.data.gov.uk/digital-land.json?sql=${encodeURIComponent(sql)}`; try { const response = await axios.get(url) const names = response.data.rows.map(row => row[1]) From 0cd3bc998c7a9bb756a2748070edbeff492bd0e6 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 13:54:50 +0100 Subject: [PATCH 091/127] linting --- src/utils/fetchLocalAuthorities.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index 1946995b..a6263968 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -21,9 +21,9 @@ export default async () => { where provision.organisation = organisation.organisation order by - provision.organisation`; + provision.organisation` - const url = `https://datasette.planning.data.gov.uk/digital-land.json?sql=${encodeURIComponent(sql)}`; + const url = `https://datasette.planning.data.gov.uk/digital-land.json?sql=${encodeURIComponent(sql)}` try { const response = await axios.get(url) const names = response.data.rows.map(row => row[1]) From 49e7195ea44e891babbafca103005cb16b0ed02a Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Wed, 3 Jul 2024 17:32:59 +0100 Subject: [PATCH 092/127] misc content changes ...and associated test changes, required --- config/default.yaml | 2 +- src/filters/filters.js | 26 +++++++++++++++++++++++++- src/serverSetup/nunjucks.js | 4 ++-- src/views/check-answers.html | 6 +++--- src/views/confirmation.html | 2 +- src/views/dataset-details.html | 2 +- src/views/lpa-details.html | 6 +++--- test/unit/check-answers.test.js | 11 ++++++----- test/unit/choose-datasetPage.test.js | 2 +- test/unit/confirmationPage.test.js | 7 ++++--- test/unit/data.js | 15 +++++++++++++++ test/unit/lpa-detailsPage.test.js | 7 ++++--- test/unit/startPage.test.js | 3 ++- 13 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 test/unit/data.js diff --git a/config/default.yaml b/config/default.yaml index 20c5c99e..2e2ff05c 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -12,5 +12,5 @@ email: { } redis: false url: '' -serviceName: 'Endpoint Submission Form' +serviceName: 'Submit your planning and housing data for England' feedbackLink: '#' \ No newline at end of file diff --git a/src/filters/filters.js b/src/filters/filters.js index ca5ef180..29d33a78 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -5,12 +5,36 @@ import xGovFilters from '@x-govuk/govuk-prototype-filters' const { govukMarkdown } = xGovFilters -const addFilters = (nunjucksEnv) => { +/** + * + * @param {*} dataSubjects + * @returns {Map} + */ +function createDatasetMapping (dataSubjects) { + const mapping = new Map() + for (const data of Object.values(dataSubjects)) { + for (const dataset of data.dataSets) { + mapping.set(dataset.value, dataset.text) + } + } + return mapping +} + +const addFilters = (nunjucksEnv, { dataSubjects }) => { nunjucksEnv.addFilter('govukMarkdown', govukMarkdown) nunjucksEnv.addFilter('getkeys', getkeys) nunjucksEnv.addFilter('getContext', getContext) nunjucksEnv.addFilter('toErrorList', toErrorList) nunjucksEnv.addFilter('validationMessageLookup', validationMessageLookup) + + const datasetNameMapping = createDatasetMapping(dataSubjects) + nunjucksEnv.addFilter('datasetSlugToReadableName', function (slug) { + const name = datasetNameMapping.get(slug) + if (!name) { + throw new Error(`Can't find a name for ${slug}`) + } + return name + }) } export default addFilters diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 6c2fce84..14667ec1 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -2,7 +2,7 @@ import nunjucks from 'nunjucks' import config from '../../config/index.js' import addFilters from '../filters/filters.js' -export function setupNunjucks (app) { +export function setupNunjucks ({ app, dataSubjects }) { if (app) { app.set('view engine', 'html') } @@ -26,7 +26,7 @@ export function setupNunjucks (app) { Object.keys(globalValues).forEach((key) => { nunjucksEnv.addGlobal(key, globalValues[key]) }) - addFilters(nunjucksEnv) + addFilters(nunjucksEnv, { dataSubjects }) return nunjucks } diff --git a/src/views/check-answers.html b/src/views/check-answers.html index f0305ba3..7e207957 100644 --- a/src/views/check-answers.html +++ b/src/views/check-answers.html @@ -20,7 +20,7 @@

- Check your answers before sending your application + Check your answers before submitting your dataset

{{ govukSummaryList({ @@ -81,7 +81,7 @@

text: "Dataset" }, value: { - text: values['dataset'] + text: values['dataset'] | datasetSlugToReadableName }, actions: { items: [ @@ -149,7 +149,7 @@

}) }}

- Submit your dataset + If this looks correct you can submit your dataset

diff --git a/src/views/confirmation.html b/src/views/confirmation.html index 33ec005b..03340830 100644 --- a/src/views/confirmation.html +++ b/src/views/confirmation.html @@ -2,7 +2,7 @@ {% from "govuk/components/panel/macro.njk" import govukPanel %} -{% set pageName = values['dataset'] + " submitted" %} +{% set pageName = (values['dataset'] | datasetSlugToReadableName) + " submitted" %} {% block content %} diff --git a/src/views/dataset-details.html b/src/views/dataset-details.html index 44fcca37..c1681105 100644 --- a/src/views/dataset-details.html +++ b/src/views/dataset-details.html @@ -5,7 +5,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} -{% set pageName = values['dataset'] + " details" %} +{% set pageName = "Enter " + (values['dataset'] | datasetSlugToReadableName | lower) + " details" %} {% block pageTitle %} {% if errors | length %} diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 1ae67ad5..470c3e28 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -4,7 +4,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} -{% set pageName = 'LPA details' %} +{% set pageName = 'Enter LPA details – {{ serviceName }}' %} {% block pageTitle %} {% if errors | length %} @@ -34,7 +34,7 @@ {% endif %}

- Which LPA are you submitting data for? + Enter LPA details

@@ -96,4 +96,4 @@

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/test/unit/check-answers.test.js b/test/unit/check-answers.test.js index 1d338c5f..35f855f7 100644 --- a/test/unit/check-answers.test.js +++ b/test/unit/check-answers.test.js @@ -5,8 +5,7 @@ import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' import { stripWhitespace } from '../utils/stripWhiteSpace.js' - -const nunjucks = setupNunjucks() +import { mockDataSubjects } from './data.js' describe('check-answers View', () => { const params = { @@ -20,6 +19,7 @@ describe('check-answers View', () => { hasLicence: 'true' } } + const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) const html = stripWhitespace(nunjucks.render('check-answers.html', params)) runGenericPageTests(html, { @@ -43,7 +43,7 @@ describe('check-answers View', () => { }) it('should render the dataset entered', () => { - const datasetRegex = new RegExp('
.*Dataset.*mockDataset.*Change.*
', 'g') + const datasetRegex = new RegExp('
.*Dataset.*A Mock dataset.*Change.*
', 'g') expect(html).toMatch(datasetRegex) }) @@ -63,12 +63,13 @@ describe('check-answers View', () => { }) it('should render the licence selected as false if the licence has not been confirmed', () => { - const params = { + const noLicenseParams = { values: { + ...params.values, hasLicence: 'false' } } - const html = stripWhitespace(nunjucks.render('check-answers.html', params)) + const html = stripWhitespace(nunjucks.render('check-answers.html', noLicenseParams)) const hasLicenceRegex = new RegExp('
.*Licence.*False.*Change.*
', 'g') expect(html).toMatch(hasLicenceRegex) }) diff --git a/test/unit/choose-datasetPage.test.js b/test/unit/choose-datasetPage.test.js index b9214817..f5e01514 100644 --- a/test/unit/choose-datasetPage.test.js +++ b/test/unit/choose-datasetPage.test.js @@ -4,7 +4,7 @@ import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' import { testValidationErrorMessage } from './validation-tests.js' -const nunjucks = setupNunjucks() +const nunjucks = setupNunjucks({ dataSubjects: {} }) describe('choose dataset View', () => { const params = { diff --git a/test/unit/confirmationPage.test.js b/test/unit/confirmationPage.test.js index 4e4fbfe7..ad480258 100644 --- a/test/unit/confirmationPage.test.js +++ b/test/unit/confirmationPage.test.js @@ -5,8 +5,9 @@ import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' import { stripWhitespace } from '../utils/stripWhiteSpace.js' +import { mockDataSubjects } from './data.js' -const nunjucks = setupNunjucks() +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) describe('Confirmation View', () => { const params = { @@ -17,12 +18,12 @@ describe('Confirmation View', () => { const html = stripWhitespace(nunjucks.render('confirmation.html', params)) runGenericPageTests(html, { - pageTitle: `mockDataset submitted - ${config.serviceName}`, + pageTitle: `A Mock dataset submitted - ${config.serviceName}`, serviceName: config.serviceName }) it('should render the gov uk panel', () => { - const regex = new RegExp('

', 'g') + const regex = new RegExp('

', 'g') expect(html).toMatch(regex) }) }) diff --git a/test/unit/data.js b/test/unit/data.js new file mode 100644 index 00000000..ce76c3fd --- /dev/null +++ b/test/unit/data.js @@ -0,0 +1,15 @@ +/** + * This value should have the same shape as dataSubjects in 'src/utils/utils.js' + */ +export const mockDataSubjects = { + mockDataset: { + available: true, + dataSets: [ + { + value: 'mockDataset', + text: 'A Mock dataset', + available: true + } + ] + } +} diff --git a/test/unit/lpa-detailsPage.test.js b/test/unit/lpa-detailsPage.test.js index f1c5130c..d47ee76b 100644 --- a/test/unit/lpa-detailsPage.test.js +++ b/test/unit/lpa-detailsPage.test.js @@ -3,8 +3,9 @@ import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' import { testValidationErrorMessage } from './validation-tests.js' +import { mockDataSubjects } from './data.js' -const nunjucks = setupNunjucks() +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) describe('Lpa-details View', () => { const params = { @@ -12,8 +13,8 @@ describe('Lpa-details View', () => { } const htmlNoErrors = nunjucks.render('lpa-details.html', params) - runGenericPageTests(htmlNoErrors, { - pageTitle: `LPA details - ${config.serviceName}`, + runGenericPageTests(html, { + pageTitle: `Enter LPA details – ${config.serviceName}`, serviceName: config.serviceName }) diff --git a/test/unit/startPage.test.js b/test/unit/startPage.test.js index b8030609..9b1a4969 100644 --- a/test/unit/startPage.test.js +++ b/test/unit/startPage.test.js @@ -2,8 +2,9 @@ import { describe } from 'vitest' import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' +import { mockDataSubjects } from './data.js' -const nunjucks = setupNunjucks() +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) describe('Start View', () => { const params = {} From ed2845ec56e1b02b855d23540a68a2337011fb2e Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Thu, 4 Jul 2024 10:26:43 +0100 Subject: [PATCH 093/127] fix: missing param --- index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index cf67e225..a8ef33b0 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ import { setupRoutes } from './src/serverSetup/routes.js' import { setupSession } from './src/serverSetup/setupSession.js' import { setupNunjucks } from './src/serverSetup/nunjucks.js' import { setupMiddlewares } from './src/serverSetup/middlewares.js' +import { dataSubjects } from './src/utils/utils.js' import dotenv from 'dotenv' dotenv.config() @@ -13,7 +14,7 @@ const port = process.env.PORT || 3000 setupMiddlewares(app) setupSession(app) -setupNunjucks(app) +setupNunjucks({app, dataSubjects}) setupRoutes(app) app.listen(port, () => { From a2f0a7ee313a2d68c91d8a12ef1ded185db7b89e Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Thu, 4 Jul 2024 11:12:03 +0100 Subject: [PATCH 094/127] fix: linter errors --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index a8ef33b0..e05dcca7 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,7 @@ const port = process.env.PORT || 3000 setupMiddlewares(app) setupSession(app) -setupNunjucks({app, dataSubjects}) +setupNunjucks({ app, dataSubjects }) setupRoutes(app) app.listen(port, () => { From c64f5b9a6a19148b05f09a795a8565c43411b4fd Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Thu, 4 Jul 2024 16:32:44 +0100 Subject: [PATCH 095/127] fix after updating main --- package.json | 1 + src/views/lpa-details.html | 2 +- test/unit/dataset-details.test.js | 199 +++++++++++++++--------------- test/unit/lpa-detailsPage.test.js | 4 +- 4 files changed, 104 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index 0bf99be6..d8cc32d4 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@x-govuk/govuk-prototype-filters": "^1.4.0", "body-parser": "^1.20.2", "cookie-parser": "^1.4.6", + "dotenv": "^16.4.5", "express": "^4.19.2", "express-session": "^1.18.0", "govuk-frontend": "^5.4.0", diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 470c3e28..2045ccea 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -4,7 +4,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} -{% set pageName = 'Enter LPA details – {{ serviceName }}' %} +{% set pageName = 'Enter LPA details' %} {% block pageTitle %} {% if errors | length %} diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js index fccb6e00..d4927aaa 100644 --- a/test/unit/dataset-details.test.js +++ b/test/unit/dataset-details.test.js @@ -6,8 +6,32 @@ import { runGenericPageTests } from './generic-page.js' import config from '../../config/index.js' import { stripWhitespace } from '../utils/stripWhiteSpace.js' import { testValidationErrorMessage } from './validation-tests.js' +import { mockDataSubjects } from './data.js' + +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) + +function erorTestFn ({ + params, + fieldId, + fieldType, + template = 'dataset-details.html', + message: expectedMessage +}) { + return () => { + const errorParams = { + values: params.values, + errors: { + [fieldId]: { + type: fieldType + } + } + } + + const html = nunjucks.render(template, errorParams) -const nunjucks = setupNunjucks() + testValidationErrorMessage(html, fieldId, expectedMessage) + } +} describe('dataset details View', () => { const params = { @@ -17,121 +41,98 @@ describe('dataset details View', () => { errors: {} } const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) - + const datasetName = mockDataSubjects.mockDataset.dataSets[0].text runGenericPageTests(html, { - pageTitle: `mockDataset details - ${config.serviceName}`, + pageTitle: `Enter ${datasetName.toLowerCase()} details - ${ + config.serviceName + }`, serviceName: config.serviceName }) it('should render the correct header', () => { - const regex = new RegExp('

', 'g') + const regex = new RegExp( + `

`, + 'g' + ) expect(html).toMatch(regex) }) describe('validation error messages', () => { describe('endpoint-url', () => { - it('should display an error message when the endpoint-url field is empty', () => { - const params = { - errors: { - 'endpoint-url': { - type: 'required' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'endpoint-url', 'Enter an endpoint URL') - }) - - it('should display an error message when the endpoint-url is not a valid URL', () => { - const params = { - errors: { - 'endpoint-url': { - type: 'format' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'endpoint-url', 'Enter a valid endpoint URL') - }) - - it('should display an error message when the endpoint-url is too long', () => { - const params = { - errors: { - 'endpoint-url': { - type: 'maxlength' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'endpoint-url', 'The URL must be less than 2048 characters') - }) + it( + 'should display an error message when the endpoint-url field is empty', + erorTestFn({ + params, + fieldId: 'endpoint-url', + fieldType: 'required', + message: 'Enter an endpoint URL' + }) + ) + + it( + 'should display an error message when the endpoint-url is not a valid URL', + erorTestFn({ + params, + fieldId: 'endpoint-url', + fieldType: 'format', + message: 'Enter a valid endpoint URL' + }) + ) + + it( + 'should display an error message when the endpoint-url is too long', + erorTestFn({ + params, + fieldId: 'endpoint-url', + fieldType: 'maxlength', + message: 'The URL must be less than 2048 characters' + }) + ) }) describe('documentation-url', () => { - it('should display an error message when the documentation-url field is empty', () => { - const params = { - errors: { - 'documentation-url': { - type: 'required' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'documentation-url', 'Enter a documentation URL') - }) - - it('should display an error message when the documentation-url is not a valid URL', () => { - const params = { - errors: { - 'documentation-url': { - type: 'format' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'documentation-url', 'Enter a valid documentation URL') - }) - - it('should display an error message when the documentation-url is too long', () => { - const params = { - errors: { - 'documentation-url': { - type: 'maxlength' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'documentation-url', 'The URL must be less than 2048 characters') - }) + it( + 'should display an error message when the documentation-url field is empty', + erorTestFn({ + params, + fieldId: 'documentation-url', + fieldType: 'required', + message: 'Enter a documentation URL' + }) + ) + + it( + 'should display an error message when the documentation-url is not a valid URL', + erorTestFn({ + params, + fieldId: 'documentation-url', + fieldType: 'format', + message: 'Enter a valid documentation URL' + }) + ) + + it( + 'should display an error message when the documentation-url is too long', + erorTestFn({ + params, + fieldId: 'documentation-url', + fieldType: 'maxlength', + message: 'The URL must be less than 2048 characters' + }) + ) }) describe('hasLicence', () => { - it('should display an error message when the hasLicence field is empty', () => { - const params = { - errors: { - hasLicence: { - type: 'required' - } - } - } - - const html = nunjucks.render('dataset-details.html', params) - - testValidationErrorMessage(html, 'hasLicence', 'You need to confirm this dataset is provided under the Open Government Licence') - }) + it( + 'should display an error message when the hasLicence field is empty', + erorTestFn({ + params, + fieldId: 'hasLicence', + fieldType: 'required', + message: 'You need to confirm this dataset is provided under the Open Government Licence' + }) + ) }) }) }) diff --git a/test/unit/lpa-detailsPage.test.js b/test/unit/lpa-detailsPage.test.js index d47ee76b..789acc19 100644 --- a/test/unit/lpa-detailsPage.test.js +++ b/test/unit/lpa-detailsPage.test.js @@ -13,8 +13,8 @@ describe('Lpa-details View', () => { } const htmlNoErrors = nunjucks.render('lpa-details.html', params) - runGenericPageTests(html, { - pageTitle: `Enter LPA details – ${config.serviceName}`, + runGenericPageTests(htmlNoErrors, { + pageTitle: `Enter LPA details - ${config.serviceName}`, serviceName: config.serviceName }) From 7a0f0b6d93c767b0191aadf6d69742168052b9fb Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Fri, 5 Jul 2024 15:32:59 +0100 Subject: [PATCH 096/127] fix typo --- test/unit/dataset-details.test.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js index d4927aaa..0026e7c3 100644 --- a/test/unit/dataset-details.test.js +++ b/test/unit/dataset-details.test.js @@ -10,7 +10,7 @@ import { mockDataSubjects } from './data.js' const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) -function erorTestFn ({ +function errorTestFn ({ params, fieldId, fieldType, @@ -62,7 +62,7 @@ describe('dataset details View', () => { describe('endpoint-url', () => { it( 'should display an error message when the endpoint-url field is empty', - erorTestFn({ + errorTestFn({ params, fieldId: 'endpoint-url', fieldType: 'required', @@ -72,7 +72,7 @@ describe('dataset details View', () => { it( 'should display an error message when the endpoint-url is not a valid URL', - erorTestFn({ + errorTestFn({ params, fieldId: 'endpoint-url', fieldType: 'format', @@ -82,7 +82,7 @@ describe('dataset details View', () => { it( 'should display an error message when the endpoint-url is too long', - erorTestFn({ + errorTestFn({ params, fieldId: 'endpoint-url', fieldType: 'maxlength', @@ -94,7 +94,7 @@ describe('dataset details View', () => { describe('documentation-url', () => { it( 'should display an error message when the documentation-url field is empty', - erorTestFn({ + errorTestFn({ params, fieldId: 'documentation-url', fieldType: 'required', @@ -104,7 +104,7 @@ describe('dataset details View', () => { it( 'should display an error message when the documentation-url is not a valid URL', - erorTestFn({ + errorTestFn({ params, fieldId: 'documentation-url', fieldType: 'format', @@ -114,7 +114,7 @@ describe('dataset details View', () => { it( 'should display an error message when the documentation-url is too long', - erorTestFn({ + errorTestFn({ params, fieldId: 'documentation-url', fieldType: 'maxlength', @@ -126,7 +126,7 @@ describe('dataset details View', () => { describe('hasLicence', () => { it( 'should display an error message when the hasLicence field is empty', - erorTestFn({ + errorTestFn({ params, fieldId: 'hasLicence', fieldType: 'required', From 8c8c26dd79e985fa643a134e0a1ec2dc72dfcfe5 Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Fri, 5 Jul 2024 15:33:29 +0100 Subject: [PATCH 097/127] use existing variable for header --- src/views/lpa-details.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/lpa-details.html b/src/views/lpa-details.html index 2045ccea..37ccb70b 100644 --- a/src/views/lpa-details.html +++ b/src/views/lpa-details.html @@ -34,7 +34,7 @@ {% endif %}

- Enter LPA details + {{pageName}}

From 5f509d46beb678954abda9cf267a05966da7ff0f Mon Sep 17 00:00:00 2001 From: George Goodall Date: Fri, 5 Jul 2024 16:19:31 +0100 Subject: [PATCH 098/127] get tests working --- src/controllers/lpaDetailsController.js | 6 +-- src/routes/form-wizard/steps.js | 4 +- src/utils/fetchLocalAuthorities.js | 11 ++++- test/unit/fetchLocalAuthorities.test.js | 41 ++++++++++++++++ test/unit/lpaDetailsController.test.js | 63 +++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 7 deletions(-) create mode 100644 test/unit/fetchLocalAuthorities.test.js create mode 100644 test/unit/lpaDetailsController.test.js diff --git a/src/controllers/lpaDetailsController.js b/src/controllers/lpaDetailsController.js index 9468040e..6301564a 100644 --- a/src/controllers/lpaDetailsController.js +++ b/src/controllers/lpaDetailsController.js @@ -1,7 +1,7 @@ import PageController from './pageController.js' -import fetchLocalAuthorities from '../utils/fetchLocalAuthorities.js' +import { fetchLocalAuthorities } from '../utils/fetchLocalAuthorities.js' -class lpaDetailsController extends PageController { +class LpaDetailsController extends PageController { async locals (req, res, next) { const localAuthoritiesNames = await fetchLocalAuthorities() @@ -16,4 +16,4 @@ class lpaDetailsController extends PageController { } } -export default lpaDetailsController +export default LpaDetailsController diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/steps.js index 7ae071c9..54047d73 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/steps.js @@ -1,5 +1,5 @@ import chooseDatasetController from '../../controllers/chooseDatasetController.js' -import lpaDetailsController from '../../controllers/lpaDetailsController.js' +import LpaDetailsController from '../../controllers/lpaDetailsController.js' import PageController from '../../controllers/pageController.js' import CheckAnswersController from '../../controllers/CheckAnswersController.js' @@ -20,7 +20,7 @@ export default { ...defaultParams, fields: ['lpa', 'name', 'email'], next: 'choose-dataset', - controller: lpaDetailsController, + controller: LpaDetailsController, backLink: '/start' }, '/choose-dataset': { diff --git a/src/utils/fetchLocalAuthorities.js b/src/utils/fetchLocalAuthorities.js index a6263968..5fb29790 100644 --- a/src/utils/fetchLocalAuthorities.js +++ b/src/utils/fetchLocalAuthorities.js @@ -10,7 +10,7 @@ import axios from 'axios' * @returns {Promise} A promise that resolves to an array of local authority names. * @throws {Error} Throws an error if the HTTP request fails or data processing encounters an issue. */ -export default async () => { +export const fetchLocalAuthorities = async () => { const sql = `select distinct provision.organisation, organisation.name, @@ -26,7 +26,14 @@ export default async () => { const url = `https://datasette.planning.data.gov.uk/digital-land.json?sql=${encodeURIComponent(sql)}` try { const response = await axios.get(url) - const names = response.data.rows.map(row => row[1]) + const names = response.data.rows.map(row => { + if (row[1] === null) { + console.log('Null value found in response:', row) + return null + } else { + return row[1] + } + }).filter(name => name !== null) // Filter out null values return names // Return the fetched data } catch (error) { console.error('Error fetching local authorities data:', error) diff --git a/test/unit/fetchLocalAuthorities.test.js b/test/unit/fetchLocalAuthorities.test.js new file mode 100644 index 00000000..9b3c73f2 --- /dev/null +++ b/test/unit/fetchLocalAuthorities.test.js @@ -0,0 +1,41 @@ +import axios from 'axios' +import { vi, it, describe, expect } from 'vitest' +import { fetchLocalAuthorities } from '../../src/utils/fetchLocalAuthorities' + +// Mock axios.get to return a fake response +vi.mock('axios') +axios.get.mockResolvedValue({ + data: { + rows: [ + [1, 'Local Authority 1'], + [2, 'Local Authority 2'], + [3, 'Local Authority 3'] + ] + } +}) + +describe('fetchLocalAuthorities', () => { + it('should fetch local authority names', async () => { + const result = await fetchLocalAuthorities() + expect(result).toEqual(['Local Authority 1', 'Local Authority 2', 'Local Authority 3']) + }) + + it('should throw an error if the HTTP request fails', async () => { + axios.get.mockRejectedValue(new Error('Failed to fetch data')) + await expect(fetchLocalAuthorities()).rejects.toThrow('Failed to fetch data') + }) + + it('should throw an error if data processing encounters an issue', async () => { + axios.get.mockResolvedValue({ + data: { + rows: [ + [1, 'Local Authority 1'], + [2, null], // Simulate null value in the response + [3, 'Local Authority 3'] + ] + } + }) + const result = await fetchLocalAuthorities() + expect(result).toEqual(['Local Authority 1', 'Local Authority 3']) + }) +}) diff --git a/test/unit/lpaDetailsController.test.js b/test/unit/lpaDetailsController.test.js new file mode 100644 index 00000000..d3bb2b80 --- /dev/null +++ b/test/unit/lpaDetailsController.test.js @@ -0,0 +1,63 @@ +/* eslint-disable no-import-assign */ + +import LpaDetailsController from '../../src/controllers/lpaDetailsController.js' +import { fetchLocalAuthorities } from '../../src/utils/fetchLocalAuthorities' +import PageController from '../../src/controllers/pageController.js' +import { vi, it, describe, expect, beforeEach, afterEach } from 'vitest' + +vi.mock('../../src/utils/fetchLocalAuthorities.js') + +describe('lpaDetailsController', () => { + let controller + + beforeEach(() => { + controller = new LpaDetailsController({ + route: '/lpa-details' + }) + }) + + afterEach(() => { + vi.restoreAllMocks() + }) + + describe('locals', () => { + it('should set localAuthorities options in the form', async () => { + const req = { + form: { + options: {} + } + } + const res = {} + const next = vi.fn() + + const localAuthoritiesNames = ['Authority 1', 'Authority 2'] + fetchLocalAuthorities = vi.fn().mockResolvedValue(localAuthoritiesNames) + + await controller.locals(req, res, next) + + expect(fetchLocalAuthorities).toHaveBeenCalled() + expect(req.form.options.localAuthorities).toEqual([ + { text: 'Authority 1', value: 'Authority 1' }, + { text: 'Authority 2', value: 'Authority 2' } + ]) + expect(next).toHaveBeenCalled() + }) + + it('should call super.locals', async () => { + const req = { + form: { + options: {} + } + } + const res = {} + const next = vi.fn() + + fetchLocalAuthorities = vi.fn().mockResolvedValue([]) + const superLocalsSpy = vi.spyOn(PageController.prototype, 'locals') + + await controller.locals(req, res, next) + + expect(superLocalsSpy).toHaveBeenCalledWith(req, res, next) + }) + }) +}) From 9d01207fc91c7c3519cd257bc90f16c55a0becab Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 11:49:07 +0100 Subject: [PATCH 099/127] Linting --- src/filters/filters.js | 2 -- src/serverSetup/middlewares.js | 1 - 2 files changed, 3 deletions(-) diff --git a/src/filters/filters.js b/src/filters/filters.js index 07810f46..f1f6cfab 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -6,7 +6,6 @@ import prettifyColumnName from './prettifyColumnName.js' const { govukMarkdown } = xGovFilters - /** * * @param {*} dataSubjects @@ -23,7 +22,6 @@ function createDatasetMapping (dataSubjects) { } const addFilters = (nunjucksEnv) => { - const datasetNameMapping = createDatasetMapping(dataSubjects) nunjucksEnv.addFilter('datasetSlugToReadableName', function (slug) { const name = datasetNameMapping.get(slug) diff --git a/src/serverSetup/middlewares.js b/src/serverSetup/middlewares.js index 6d6f0788..408b35ef 100644 --- a/src/serverSetup/middlewares.js +++ b/src/serverSetup/middlewares.js @@ -17,7 +17,6 @@ export function setupMiddlewares (app) { next() }) - app.use('/assets', express.static('./node_modules/govuk-frontend/dist/govuk/assets')) app.use('/public', express.static('./public')) From 3126db8da5f55c48e7a54d3b38bb139bf8b4a941 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 11:56:15 +0100 Subject: [PATCH 100/127] split up form wizards --- src/routes/form-wizard/check/fields.js | 26 ++++++++ src/routes/form-wizard/{ => check}/index.js | 0 src/routes/form-wizard/{ => check}/steps.js | 60 +++--------------- .../endpoint-submission-form/fields.js | 37 +++++++++++ .../endpoint-submission-form/index.js | 10 +++ .../endpoint-submission-form/steps.js | 47 ++++++++++++++ src/routes/form-wizard/fields.js | 62 ------------------- src/serverSetup/routes.js | 10 ++- 8 files changed, 131 insertions(+), 121 deletions(-) create mode 100644 src/routes/form-wizard/check/fields.js rename src/routes/form-wizard/{ => check}/index.js (100%) rename src/routes/form-wizard/{ => check}/steps.js (57%) create mode 100644 src/routes/form-wizard/endpoint-submission-form/fields.js create mode 100644 src/routes/form-wizard/endpoint-submission-form/index.js create mode 100644 src/routes/form-wizard/endpoint-submission-form/steps.js delete mode 100644 src/routes/form-wizard/fields.js diff --git a/src/routes/form-wizard/check/fields.js b/src/routes/form-wizard/check/fields.js new file mode 100644 index 00000000..9dfdf91c --- /dev/null +++ b/src/routes/form-wizard/check/fields.js @@ -0,0 +1,26 @@ +// ToDo: split this into two form wizards +export default { + 'data-subject': { + validate: 'required', + invalidates: ['dataset', 'upload-method', 'geomType'] + }, + dataset: { + validate: 'required', + invalidates: ['upload-method', 'geomType'] + }, + geomType: { + validate: 'required' + }, + 'upload-method': { + validate: 'required' + }, + datafile: { + validate: undefined // validation is done manually in the controller as we want to run it before the request is made to the backend + }, + url: { + validate: undefined // validation is done manually in the controller as we want to run it before the request is made to the backend + }, + dataLooksCorrect: { + validate: 'required' + } +} diff --git a/src/routes/form-wizard/index.js b/src/routes/form-wizard/check/index.js similarity index 100% rename from src/routes/form-wizard/index.js rename to src/routes/form-wizard/check/index.js diff --git a/src/routes/form-wizard/steps.js b/src/routes/form-wizard/check/steps.js similarity index 57% rename from src/routes/form-wizard/steps.js rename to src/routes/form-wizard/check/steps.js index 4bfb0fd1..fb089d0b 100644 --- a/src/routes/form-wizard/steps.js +++ b/src/routes/form-wizard/check/steps.js @@ -1,10 +1,10 @@ -<<<<<<< HEAD -import PageController from '../../controllers/pageController.js' -import datasetController from '../../controllers/datasetController.js' -import uploadFileController from '../../controllers/uploadFileController.js' -import submitUrlController from '../../controllers/submitUrlController.js' -import statusController from '../../controllers/statusController.js' -import resultsController from '../../controllers/resultsController.js' +// ToDo: Split this into two form wizards +import PageController from '../../../controllers/pageController.js' +import datasetController from '../../../controllers/datasetController.js' +import uploadFileController from '../../../controllers/uploadFileController.js' +import submitUrlController from '../../../controllers/submitUrlController.js' +import statusController from '../../../controllers/statusController.js' +import resultsController from '../../../controllers/resultsController.js' const baseSettings = { controller: PageController, @@ -89,51 +89,5 @@ export default { ...baseSettings, noPost: true, checkJourney: false // ToDo: it would be useful here if we make sure they have selected if their results are ok from the previous step -======= -import chooseDatasetController from '../../controllers/chooseDatasetController.js' -import PageController from '../../controllers/pageController.js' -import CheckAnswersController from '../../controllers/CheckAnswersController.js' - -const defaultParams = { - entryPoint: false, - controller: PageController -} - -export default { - '/start': { - ...defaultParams, - entryPoint: true, - resetJourney: true, - noPost: true, - next: 'lpa-details' - }, - '/lpa-details': { - ...defaultParams, - fields: ['lpa', 'name', 'email'], - next: 'choose-dataset', - backLink: '/start' - }, - '/choose-dataset': { - ...defaultParams, - fields: ['dataset'], - next: 'dataset-details', - controller: chooseDatasetController, - backLink: '/lpa-details' - }, - '/dataset-details': { - ...defaultParams, - fields: ['endpoint-url', 'documentation-url', 'hasLicence'], - next: 'check-answers', - backLink: '/choose-dataset' - }, - '/check-answers': { - ...defaultParams, - controller: CheckAnswersController, - next: 'confirmation', - backLink: '/dataset-details' - }, - '/confirmation': { - ...defaultParams ->>>>>>> endpoint-submission-form/main } } diff --git a/src/routes/form-wizard/endpoint-submission-form/fields.js b/src/routes/form-wizard/endpoint-submission-form/fields.js new file mode 100644 index 00000000..9b6e6106 --- /dev/null +++ b/src/routes/form-wizard/endpoint-submission-form/fields.js @@ -0,0 +1,37 @@ +// ToDo: split this into two form wizards +import { validUrl } from '../../utils/validators.js' + +export default { + lpa: { + validate: ['required'] + }, + name: { + validate: ['required'] + }, + email: { + validate: [ + 'required', + 'email' + ] + }, + dataset: { + validate: ['required'] + }, + 'endpoint-url': { + validate: [ + 'required', + { type: 'format', fn: validUrl }, + { type: 'maxlength', arguments: [2048] } + ] + }, + 'documentation-url': { + validate: [ + 'required', + { type: 'format', fn: validUrl }, + { type: 'maxlength', arguments: [2048] } + ] + }, + hasLicence: { + validate: ['required'] + } +} diff --git a/src/routes/form-wizard/endpoint-submission-form/index.js b/src/routes/form-wizard/endpoint-submission-form/index.js new file mode 100644 index 00000000..032b56fa --- /dev/null +++ b/src/routes/form-wizard/endpoint-submission-form/index.js @@ -0,0 +1,10 @@ +import { Router } from 'express' +import wizard from 'hmpo-form-wizard' +import steps from './steps.js' +import fields from './fields.js' + +const app = Router() + +app.use(wizard(steps, fields, { name: 'my-wizard', csrf: false })) + +export default app diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js new file mode 100644 index 00000000..cca0b098 --- /dev/null +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -0,0 +1,47 @@ +// ToDo: Split this into two form wizards +import chooseDatasetController from '../../controllers/chooseDatasetController.js' +import PageController from '../../controllers/pageController.js' +import CheckAnswersController from '../../controllers/CheckAnswersController.js' + +const defaultParams = { + entryPoint: false, + controller: PageController +} + +export default { + '/start': { + ...defaultParams, + entryPoint: true, + resetJourney: true, + noPost: true, + next: 'lpa-details' + }, + '/lpa-details': { + ...defaultParams, + fields: ['lpa', 'name', 'email'], + next: 'choose-dataset', + backLink: '/start' + }, + '/choose-dataset': { + ...defaultParams, + fields: ['dataset'], + next: 'dataset-details', + controller: chooseDatasetController, + backLink: '/lpa-details' + }, + '/dataset-details': { + ...defaultParams, + fields: ['endpoint-url', 'documentation-url', 'hasLicence'], + next: 'check-answers', + backLink: '/choose-dataset' + }, + '/check-answers': { + ...defaultParams, + controller: CheckAnswersController, + next: 'confirmation', + backLink: '/dataset-details' + }, + '/confirmation': { + ...defaultParams + } +} diff --git a/src/routes/form-wizard/fields.js b/src/routes/form-wizard/fields.js deleted file mode 100644 index 62601f69..00000000 --- a/src/routes/form-wizard/fields.js +++ /dev/null @@ -1,62 +0,0 @@ -<<<<<<< HEAD -export default { - 'data-subject': { - validate: 'required', - invalidates: ['dataset', 'upload-method', 'geomType'] - }, - dataset: { - validate: 'required', - invalidates: ['upload-method', 'geomType'] - }, - geomType: { - validate: 'required' - }, - 'upload-method': { - validate: 'required' - }, - datafile: { - validate: undefined // validation is done manually in the controller as we want to run it before the request is made to the backend - }, - url: { - validate: undefined // validation is done manually in the controller as we want to run it before the request is made to the backend - }, - dataLooksCorrect: { - validate: 'required' -======= -import { validUrl } from '../../utils/validators.js' - -export default { - lpa: { - validate: ['required'] - }, - name: { - validate: ['required'] - }, - email: { - validate: [ - 'required', - 'email' - ] - }, - dataset: { - validate: ['required'] - }, - 'endpoint-url': { - validate: [ - 'required', - { type: 'format', fn: validUrl }, - { type: 'maxlength', arguments: [2048] } - ] - }, - 'documentation-url': { - validate: [ - 'required', - { type: 'format', fn: validUrl }, - { type: 'maxlength', arguments: [2048] } - ] - }, - hasLicence: { - validate: ['required'] ->>>>>>> endpoint-submission-form/main - } -} diff --git a/src/serverSetup/routes.js b/src/serverSetup/routes.js index faf75088..7d56e5d3 100644 --- a/src/serverSetup/routes.js +++ b/src/serverSetup/routes.js @@ -1,14 +1,12 @@ -import formWizard from '../routes/form-wizard/index.js' +import checkFormWizard from '../routes/form-wizard/check/index.js' +import endpointSubmissionFormFormWisard from '../routes/form-wizard/endpoint-submission-form/index.js' import accessibility from '../routes/accessibility.js' import polling from '../routes/api.js' import health from '../routes/health.js' export function setupRoutes (app) { -<<<<<<< HEAD Need to setup two form wizard instances here to handle the two different form wizards - app.use('/', formWizard) -======= - app.use('/', formWizard) ->>>>>>> endpoint-submission-form/main + app.use('/', checkFormWizard) + app.use('/submit', endpointSubmissionFormFormWisard) app.use('/accessibility', accessibility) app.use('/api', polling) app.use('/health', health) From a155862568bdd664bcfca48d31d7a3d5dd32f6e4 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 11:56:33 +0100 Subject: [PATCH 101/127] add missing param to add filters method --- src/filters/filters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filters/filters.js b/src/filters/filters.js index f1f6cfab..5715c586 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -21,7 +21,7 @@ function createDatasetMapping (dataSubjects) { return mapping } -const addFilters = (nunjucksEnv) => { +const addFilters = ({ nunjucksEnv, dataSubjects }) => { const datasetNameMapping = createDatasetMapping(dataSubjects) nunjucksEnv.addFilter('datasetSlugToReadableName', function (slug) { const name = datasetNameMapping.get(slug) From d76e61b9b707bc1325e4b8eca383d7b3e093d5dc Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:19:54 +0100 Subject: [PATCH 102/127] remove unused package --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 3885b5d7..dacb3b4b 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "aws-sdk": "^2.1581.0", "axios": "^1.6.2", "connect-redis": "^7.1.1", - "email-validator": "^2.0.4", "fs": "^0.0.1-security", "@x-govuk/govuk-prototype-components": "^3.0.5", "@x-govuk/govuk-prototype-filters": "^1.4.0", From cb5049c020765af799994fa176b3fcfade631efe Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:20:08 +0100 Subject: [PATCH 103/127] fix add filters params --- src/filters/filters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filters/filters.js b/src/filters/filters.js index 5715c586..ba0db6bd 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -21,7 +21,7 @@ function createDatasetMapping (dataSubjects) { return mapping } -const addFilters = ({ nunjucksEnv, dataSubjects }) => { +const addFilters = (nunjucksEnv, { dataSubjects }) => { const datasetNameMapping = createDatasetMapping(dataSubjects) nunjucksEnv.addFilter('datasetSlugToReadableName', function (slug) { const name = datasetNameMapping.get(slug) From 9c0160977454f33b8f4db928164242d5443a6b50 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:20:21 +0100 Subject: [PATCH 104/127] rename wizards --- src/routes/form-wizard/check/index.js | 2 +- src/routes/form-wizard/endpoint-submission-form/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/form-wizard/check/index.js b/src/routes/form-wizard/check/index.js index 032b56fa..fee852ca 100644 --- a/src/routes/form-wizard/check/index.js +++ b/src/routes/form-wizard/check/index.js @@ -5,6 +5,6 @@ import fields from './fields.js' const app = Router() -app.use(wizard(steps, fields, { name: 'my-wizard', csrf: false })) +app.use(wizard(steps, fields, { name: 'check-wizard', csrf: false })) export default app diff --git a/src/routes/form-wizard/endpoint-submission-form/index.js b/src/routes/form-wizard/endpoint-submission-form/index.js index 032b56fa..2bfc0ac9 100644 --- a/src/routes/form-wizard/endpoint-submission-form/index.js +++ b/src/routes/form-wizard/endpoint-submission-form/index.js @@ -5,6 +5,6 @@ import fields from './fields.js' const app = Router() -app.use(wizard(steps, fields, { name: 'my-wizard', csrf: false })) +app.use(wizard(steps, fields, { name: 'endpoint-submission-form-wizard', csrf: false })) export default app From 8127060a488adc5da9e821ddd3dab1a140d55f93 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:26:15 +0100 Subject: [PATCH 105/127] add new folders to nunjucks configure --- src/serverSetup/nunjucks.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 14667ec1..458f8e04 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -9,6 +9,8 @@ export function setupNunjucks ({ app, dataSubjects }) { const nunjucksEnv = nunjucks.configure([ 'src/views', + 'src/views/checkPages', + 'src/views/endpointSubmissionFormPages', 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { From 42a332278cdf23c95528f3aa4344116ad4e9b1c9 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:26:37 +0100 Subject: [PATCH 106/127] update steps amd fields --- src/routes/form-wizard/check/steps.js | 2 +- .../form-wizard/endpoint-submission-form/fields.js | 2 +- .../form-wizard/endpoint-submission-form/steps.js | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/routes/form-wizard/check/steps.js b/src/routes/form-wizard/check/steps.js index fb089d0b..938356b9 100644 --- a/src/routes/form-wizard/check/steps.js +++ b/src/routes/form-wizard/check/steps.js @@ -17,7 +17,7 @@ export default { entryPoint: true, resetJourney: true, next: 'dataset', - template: '../views/start.html', + template: '../views/checkPages/start.html', noPost: true }, // '/data-subject': { diff --git a/src/routes/form-wizard/endpoint-submission-form/fields.js b/src/routes/form-wizard/endpoint-submission-form/fields.js index 9b6e6106..cd1504f5 100644 --- a/src/routes/form-wizard/endpoint-submission-form/fields.js +++ b/src/routes/form-wizard/endpoint-submission-form/fields.js @@ -1,5 +1,5 @@ // ToDo: split this into two form wizards -import { validUrl } from '../../utils/validators.js' +import { validUrl } from '../../../utils/validators.js' export default { lpa: { diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js index cca0b098..b2554485 100644 --- a/src/routes/form-wizard/endpoint-submission-form/steps.js +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -1,7 +1,7 @@ // ToDo: Split this into two form wizards -import chooseDatasetController from '../../controllers/chooseDatasetController.js' -import PageController from '../../controllers/pageController.js' -import CheckAnswersController from '../../controllers/CheckAnswersController.js' +import chooseDatasetController from '../../../controllers/chooseDatasetController.js' +import PageController from '../../../controllers/pageController.js' +import CheckAnswersController from '../../../controllers/CheckAnswersController.js' const defaultParams = { entryPoint: false, @@ -9,12 +9,13 @@ const defaultParams = { } export default { - '/start': { + '/': { ...defaultParams, entryPoint: true, resetJourney: true, noPost: true, - next: 'lpa-details' + template: '../views/endpointSubmissionFormPages/start.html', + next: '/submit/lpa-details' }, '/lpa-details': { ...defaultParams, From efa750faf283b1b110f6c036169fd19421fb2579 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:26:47 +0100 Subject: [PATCH 107/127] remove old file --- src/serverSetup/setupSession.js | 32 -------------------------------- 1 file changed, 32 deletions(-) delete mode 100644 src/serverSetup/setupSession.js diff --git a/src/serverSetup/setupSession.js b/src/serverSetup/setupSession.js deleted file mode 100644 index e75f139a..00000000 --- a/src/serverSetup/setupSession.js +++ /dev/null @@ -1,32 +0,0 @@ -import session from 'express-session' -// import { createClient } from 'redis' -// import RedisStore from 'connect-redis' -import cookieParser from 'cookie-parser' -// import config from '../../config/index.js' -// import logger from '../utils/logger.js' - -export function setupSession (app) { - app.use(cookieParser()) - let sessionStore - // if (config.redis) { - // const urlPrefix = `redis${config.redis.secure ? 's' : ''}` - // const redisClient = createClient({ - // url: `${urlPrefix}://${config.redis.host}:${config.redis.port}` - // }) - // redisClient.connect().catch(logger.error) - - // sessionStore = new RedisStore({ - // client: redisClient - // }) - // } - app.use(session({ - secret: process.env.SESSION_SECRET || 'keyboard cat', - resave: false, - saveUninitialized: false, - store: sessionStore, - cookie: { - secure: false, - maxAge: 1000 * 60 * 60 * 24 * 7 - } - })) -} From 600a3fecd54d02f9687c88000c2eb70ed1ca1f85 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 14:27:04 +0100 Subject: [PATCH 108/127] move templates to new folders --- src/views/{ => checkPages}/check-answers.html | 0 src/views/{ => checkPages}/confirmation.html | 35 +---------- src/views/{ => checkPages}/data-subject.html | 0 src/views/{ => checkPages}/dataset.html | 0 src/views/{ => checkPages}/geometry-type.html | 0 .../{ => checkPages}/results/errors.html | 0 .../results/failedFileRequest.html | 0 .../results/failedUrlRequest.html | 0 .../{ => checkPages}/results/no-errors.html | 0 src/views/checkPages/start.html | 56 +++++++++++++++++ .../statusPage/checkingFileMacro.html | 0 .../statusPage/fileCheckedMacro.html | 0 .../{ => checkPages}/statusPage/status.html | 0 src/views/{ => checkPages}/upload-method.html | 0 src/views/{ => checkPages}/upload.html | 0 src/views/{ => checkPages}/url.html | 0 .../check.html | 0 .../choose-dataset.html | 0 .../confirmation.html | 39 ++++++++++++ .../dataset-details.html | 0 .../lpa-details.html | 0 .../start.html | 61 +------------------ 22 files changed, 97 insertions(+), 94 deletions(-) rename src/views/{ => checkPages}/check-answers.html (100%) rename src/views/{ => checkPages}/confirmation.html (66%) rename src/views/{ => checkPages}/data-subject.html (100%) rename src/views/{ => checkPages}/dataset.html (100%) rename src/views/{ => checkPages}/geometry-type.html (100%) rename src/views/{ => checkPages}/results/errors.html (100%) rename src/views/{ => checkPages}/results/failedFileRequest.html (100%) rename src/views/{ => checkPages}/results/failedUrlRequest.html (100%) rename src/views/{ => checkPages}/results/no-errors.html (100%) create mode 100644 src/views/checkPages/start.html rename src/views/{ => checkPages}/statusPage/checkingFileMacro.html (100%) rename src/views/{ => checkPages}/statusPage/fileCheckedMacro.html (100%) rename src/views/{ => checkPages}/statusPage/status.html (100%) rename src/views/{ => checkPages}/upload-method.html (100%) rename src/views/{ => checkPages}/upload.html (100%) rename src/views/{ => checkPages}/url.html (100%) rename src/views/{ => endpointSubmissionFormPages}/check.html (100%) rename src/views/{ => endpointSubmissionFormPages}/choose-dataset.html (100%) create mode 100644 src/views/endpointSubmissionFormPages/confirmation.html rename src/views/{ => endpointSubmissionFormPages}/dataset-details.html (100%) rename src/views/{ => endpointSubmissionFormPages}/lpa-details.html (100%) rename src/views/{ => endpointSubmissionFormPages}/start.html (60%) diff --git a/src/views/check-answers.html b/src/views/checkPages/check-answers.html similarity index 100% rename from src/views/check-answers.html rename to src/views/checkPages/check-answers.html diff --git a/src/views/confirmation.html b/src/views/checkPages/confirmation.html similarity index 66% rename from src/views/confirmation.html rename to src/views/checkPages/confirmation.html index 26081b0c..90a287cb 100644 --- a/src/views/confirmation.html +++ b/src/views/checkPages/confirmation.html @@ -1,4 +1,4 @@ -<<<<<<< HEAD + {% from 'govuk/components/panel/macro.njk' import govukPanel %} {% from "govuk/components/details/macro.njk" import govukDetails %} @@ -51,31 +51,6 @@ ## Give feedback [Give feedback about this service]({{feedbackLink}}) (takes 30 seconds). -======= -{% extends "layouts/main.html" %} - -{% from "govuk/components/panel/macro.njk" import govukPanel %} - -{% set pageName = (values['dataset'] | datasetSlugToReadableName) + " submitted" %} - -{% block content %} - -{% set content %} - -## What happens next - -We will process your submission and add your dataset to the [planning data platform](https://www.planning.data.gov.uk/). - -Your dataset should appear on the platform within 5 working days. - -If there are any issues processing your data will we contact you on the email address you provided. - -[Add another dataset](/submit-endpoint/start) - -## Give feedback - -[Give feedback about this service](/feedback) (takes 30 seconds). ->>>>>>> endpoint-submission-form/main {% endset %} @@ -85,17 +60,9 @@ titleHtml: pageName }) }} -<<<<<<< HEAD {{content | govukMarkdown(headingsStartWith="l") | safe}} -======= - {{content | govukMarkdown(headingsStartWith="l") | safe}} ->>>>>>> endpoint-submission-form/main

-<<<<<<< HEAD -{% endblock %} -======= {% endblock %} ->>>>>>> endpoint-submission-form/main diff --git a/src/views/data-subject.html b/src/views/checkPages/data-subject.html similarity index 100% rename from src/views/data-subject.html rename to src/views/checkPages/data-subject.html diff --git a/src/views/dataset.html b/src/views/checkPages/dataset.html similarity index 100% rename from src/views/dataset.html rename to src/views/checkPages/dataset.html diff --git a/src/views/geometry-type.html b/src/views/checkPages/geometry-type.html similarity index 100% rename from src/views/geometry-type.html rename to src/views/checkPages/geometry-type.html diff --git a/src/views/results/errors.html b/src/views/checkPages/results/errors.html similarity index 100% rename from src/views/results/errors.html rename to src/views/checkPages/results/errors.html diff --git a/src/views/results/failedFileRequest.html b/src/views/checkPages/results/failedFileRequest.html similarity index 100% rename from src/views/results/failedFileRequest.html rename to src/views/checkPages/results/failedFileRequest.html diff --git a/src/views/results/failedUrlRequest.html b/src/views/checkPages/results/failedUrlRequest.html similarity index 100% rename from src/views/results/failedUrlRequest.html rename to src/views/checkPages/results/failedUrlRequest.html diff --git a/src/views/results/no-errors.html b/src/views/checkPages/results/no-errors.html similarity index 100% rename from src/views/results/no-errors.html rename to src/views/checkPages/results/no-errors.html diff --git a/src/views/checkPages/start.html b/src/views/checkPages/start.html new file mode 100644 index 00000000..f5b80352 --- /dev/null +++ b/src/views/checkPages/start.html @@ -0,0 +1,56 @@ +{% from "govuk/components/button/macro.njk" import govukButton %} +{% from "govuk/components/details/macro.njk" import govukDetails %} +{% from "x-govuk/components/related-navigation/macro.njk" import xGovukRelatedNavigation %} + +{% extends "layouts/main.html" %} + +{% set pageName = serviceName %} + +{% block content %} + + +{% set content %} + + Use this service to check your: + + - article 4 direction area data + - conservation area data + - listed building outline data + - tree preservation zone data + + ## Before you start + + Your data must follow the [data specification](https://www.planning.data.gov.uk/guidance/specifications/). + + Your data needs to be provided as either: + + - a CSV, GeoJSON, GML or GeoPackage file + - a URL + + + {{ govukButton({ + text: "Start now", + href: "/dataset", + isStartButton: true + }) }} + + +{% endset %} + +
+
+

+ {{serviceName}} +

+
+
+ +
+
+ {{content | govukMarkdown(headingsStartWith="l") | safe}} +
+
+ +
+
+{% endblock %} diff --git a/src/views/statusPage/checkingFileMacro.html b/src/views/checkPages/statusPage/checkingFileMacro.html similarity index 100% rename from src/views/statusPage/checkingFileMacro.html rename to src/views/checkPages/statusPage/checkingFileMacro.html diff --git a/src/views/statusPage/fileCheckedMacro.html b/src/views/checkPages/statusPage/fileCheckedMacro.html similarity index 100% rename from src/views/statusPage/fileCheckedMacro.html rename to src/views/checkPages/statusPage/fileCheckedMacro.html diff --git a/src/views/statusPage/status.html b/src/views/checkPages/statusPage/status.html similarity index 100% rename from src/views/statusPage/status.html rename to src/views/checkPages/statusPage/status.html diff --git a/src/views/upload-method.html b/src/views/checkPages/upload-method.html similarity index 100% rename from src/views/upload-method.html rename to src/views/checkPages/upload-method.html diff --git a/src/views/upload.html b/src/views/checkPages/upload.html similarity index 100% rename from src/views/upload.html rename to src/views/checkPages/upload.html diff --git a/src/views/url.html b/src/views/checkPages/url.html similarity index 100% rename from src/views/url.html rename to src/views/checkPages/url.html diff --git a/src/views/check.html b/src/views/endpointSubmissionFormPages/check.html similarity index 100% rename from src/views/check.html rename to src/views/endpointSubmissionFormPages/check.html diff --git a/src/views/choose-dataset.html b/src/views/endpointSubmissionFormPages/choose-dataset.html similarity index 100% rename from src/views/choose-dataset.html rename to src/views/endpointSubmissionFormPages/choose-dataset.html diff --git a/src/views/endpointSubmissionFormPages/confirmation.html b/src/views/endpointSubmissionFormPages/confirmation.html new file mode 100644 index 00000000..b050913e --- /dev/null +++ b/src/views/endpointSubmissionFormPages/confirmation.html @@ -0,0 +1,39 @@ + +{% extends "layouts/main.html" %} + +{% from "govuk/components/panel/macro.njk" import govukPanel %} + +{% set pageName = (values['dataset'] | datasetSlugToReadableName) + " submitted" %} + +{% block content %} + +{% set content %} + +## What happens next + +We will process your submission and add your dataset to the [planning data platform](https://www.planning.data.gov.uk/). + +Your dataset should appear on the platform within 5 working days. + +If there are any issues processing your data will we contact you on the email address you provided. + +[Add another dataset](/submit-endpoint/start) + +## Give feedback + +[Give feedback about this service](/feedback) (takes 30 seconds). + +{% endset %} + +
+
+ {{ govukPanel({ + titleHtml: pageName + }) }} + + {{content | govukMarkdown(headingsStartWith="l") | safe}} + +
+
+ +{% endblock %} diff --git a/src/views/dataset-details.html b/src/views/endpointSubmissionFormPages/dataset-details.html similarity index 100% rename from src/views/dataset-details.html rename to src/views/endpointSubmissionFormPages/dataset-details.html diff --git a/src/views/lpa-details.html b/src/views/endpointSubmissionFormPages/lpa-details.html similarity index 100% rename from src/views/lpa-details.html rename to src/views/endpointSubmissionFormPages/lpa-details.html diff --git a/src/views/start.html b/src/views/endpointSubmissionFormPages/start.html similarity index 60% rename from src/views/start.html rename to src/views/endpointSubmissionFormPages/start.html index e4c78ec9..7a2b3639 100644 --- a/src/views/start.html +++ b/src/views/endpointSubmissionFormPages/start.html @@ -1,61 +1,3 @@ -<<<<<<< HEAD -{% from "govuk/components/button/macro.njk" import govukButton %} -{% from "govuk/components/details/macro.njk" import govukDetails %} -{% from "x-govuk/components/related-navigation/macro.njk" import xGovukRelatedNavigation %} - -{% extends "layouts/main.html" %} - -{% set pageName = serviceName %} - -{% block content %} - - -{% set content %} - - Use this service to check your: - - - article 4 direction area data - - conservation area data - - listed building outline data - - tree preservation zone data - - ## Before you start - - Your data must follow the [data specification](https://www.planning.data.gov.uk/guidance/specifications/). - - Your data needs to be provided as either: - - - a CSV, GeoJSON, GML or GeoPackage file - - a URL - - - {{ govukButton({ - text: "Start now", - href: "/dataset", - isStartButton: true - }) }} - - -{% endset %} - -
-
-

- {{serviceName}} -

-
-
- -
-
- {{content | govukMarkdown(headingsStartWith="l") | safe}} -
-
- -
-
-{% endblock %} -======= {% extends "layouts/main.html" %} {% from "govuk/components/button/macro.njk" import govukButton %} {% from "x-govuk/components/related-navigation/macro.njk" import xGovukRelatedNavigation %} @@ -95,7 +37,7 @@

{{ govukButton({ text: "Start now", - href: "lpa-details", + href: "./submit/lpa-details", isStartButton: true }) }} @@ -138,4 +80,3 @@

{% endblock %} ->>>>>>> endpoint-submission-form/main From a03a0efe63c6966bdd1789800455f081dd2ec7a5 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 15:13:36 +0100 Subject: [PATCH 109/127] make sure page names and titles are correct --- src/filters/filters.js | 2 ++ src/filters/getFullServiceName.js | 7 +++++++ src/views/checkPages/check-answers.html | 5 ++--- src/views/checkPages/confirmation.html | 2 +- src/views/checkPages/data-subject.html | 2 +- src/views/checkPages/dataset.html | 1 + src/views/checkPages/geometry-type.html | 1 + src/views/checkPages/results/errors.html | 1 + src/views/checkPages/results/failedFileRequest.html | 1 + src/views/checkPages/results/failedUrlRequest.html | 1 + src/views/checkPages/results/no-errors.html | 2 +- src/views/checkPages/start.html | 3 ++- src/views/checkPages/statusPage/status.html | 2 +- src/views/checkPages/upload-method.html | 1 + src/views/checkPages/upload.html | 2 +- src/views/checkPages/url.html | 2 +- src/views/endpointSubmissionFormPages/check.html | 1 + .../endpointSubmissionFormPages/choose-dataset.html | 1 + src/views/endpointSubmissionFormPages/confirmation.html | 1 + .../endpointSubmissionFormPages/dataset-details.html | 1 + src/views/endpointSubmissionFormPages/lpa-details.html | 1 + src/views/endpointSubmissionFormPages/start.html | 9 +++------ src/views/layouts/main.html | 4 ++++ 23 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 src/filters/getFullServiceName.js diff --git a/src/filters/filters.js b/src/filters/filters.js index ba0db6bd..e9e8e5bd 100644 --- a/src/filters/filters.js +++ b/src/filters/filters.js @@ -3,6 +3,7 @@ import xGovFilters from '@x-govuk/govuk-prototype-filters' import validationMessageLookup from './validationMessageLookup.js' import toErrorList from './toErrorList.js' import prettifyColumnName from './prettifyColumnName.js' +import getFullServiceName from './getFullServiceName.js' const { govukMarkdown } = xGovFilters @@ -37,6 +38,7 @@ const addFilters = (nunjucksEnv, { dataSubjects }) => { nunjucksEnv.addFilter('validationMessageLookup', validationMessageLookup) nunjucksEnv.addFilter('toErrorList', toErrorList) nunjucksEnv.addFilter('prettifyColumnName', prettifyColumnName) + nunjucksEnv.addFilter('getFullServiceName', getFullServiceName) } export default addFilters diff --git a/src/filters/getFullServiceName.js b/src/filters/getFullServiceName.js new file mode 100644 index 00000000..1762b508 --- /dev/null +++ b/src/filters/getFullServiceName.js @@ -0,0 +1,7 @@ +import config from '../../config/index.js' + +export default (service) => { + const serviceName = config.serviceName + + return serviceName.replace('Provide', service) +} \ No newline at end of file diff --git a/src/views/checkPages/check-answers.html b/src/views/checkPages/check-answers.html index 7e207957..0a9dc403 100644 --- a/src/views/checkPages/check-answers.html +++ b/src/views/checkPages/check-answers.html @@ -4,9 +4,8 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from "govuk/components/back-link/macro.njk" import govukBackLink %} -{% block pageTitle %} - Check your answers – {{ serviceName }} -{% endblock %} +{% set serviceType = 'Check' %} +{% set pageName = 'Check your answers' %} {% block beforeContent %} {{ govukBackLink({ diff --git a/src/views/checkPages/confirmation.html b/src/views/checkPages/confirmation.html index 90a287cb..a378a2d5 100644 --- a/src/views/checkPages/confirmation.html +++ b/src/views/checkPages/confirmation.html @@ -4,7 +4,7 @@ {% extends "layouts/main.html" %} - +{% set serviceType = 'Check' %} {% set pageName = "Send us your data" %} {% block content %} diff --git a/src/views/checkPages/data-subject.html b/src/views/checkPages/data-subject.html index f7580126..c48ee947 100644 --- a/src/views/checkPages/data-subject.html +++ b/src/views/checkPages/data-subject.html @@ -7,7 +7,7 @@ {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} - +{% set serviceType = 'Check' %} {% set pageName = 'Data subject' %} {% set errorMessage = 'Select a data subject' %} diff --git a/src/views/checkPages/dataset.html b/src/views/checkPages/dataset.html index 0f25d3b5..5cc25fdd 100644 --- a/src/views/checkPages/dataset.html +++ b/src/views/checkPages/dataset.html @@ -4,6 +4,7 @@ {% from 'govuk/components/error-message/macro.njk' import govukErrorMessage %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} +{% set serviceType = 'Check' %} {% set pageName = 'Dataset' %} {% set errorMessage = 'Select a dataset' %} diff --git a/src/views/checkPages/geometry-type.html b/src/views/checkPages/geometry-type.html index 60b85b3f..24c8853b 100644 --- a/src/views/checkPages/geometry-type.html +++ b/src/views/checkPages/geometry-type.html @@ -5,6 +5,7 @@ {% extends "layouts/main.html" %} +{% set serviceType = 'Check' %} {% set pageName = 'Is your geometry data given as points or polygons?' %} {% set errorMessage = 'Select if your geometry data given as points or polygons' %} diff --git a/src/views/checkPages/results/errors.html b/src/views/checkPages/results/errors.html index d1e4d56a..a027829e 100644 --- a/src/views/checkPages/results/errors.html +++ b/src/views/checkPages/results/errors.html @@ -6,6 +6,7 @@ {% from "govuk/components/pagination/macro.njk" import govukPagination %} +{% set serviceType = 'Check' %} {% set pageName = 'Your data has errors' %} {% block pageTitle %} diff --git a/src/views/checkPages/results/failedFileRequest.html b/src/views/checkPages/results/failedFileRequest.html index 9cedf0fc..bd188817 100644 --- a/src/views/checkPages/results/failedFileRequest.html +++ b/src/views/checkPages/results/failedFileRequest.html @@ -1,5 +1,6 @@ {% extends "layouts/main.html" %} +{% set serviceType = 'Check' %} {% set pageName = 'Request Failed' %} {% set error = options.error %} diff --git a/src/views/checkPages/results/failedUrlRequest.html b/src/views/checkPages/results/failedUrlRequest.html index 85f26584..ea93f1ec 100644 --- a/src/views/checkPages/results/failedUrlRequest.html +++ b/src/views/checkPages/results/failedUrlRequest.html @@ -3,6 +3,7 @@ {% from 'govuk/components/button/macro.njk' import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} +{% set serviceType = 'Check' %} {% set pageName = 'Request Failed' %} {% set error = options.error %} diff --git a/src/views/checkPages/results/no-errors.html b/src/views/checkPages/results/no-errors.html index cfe0752c..079f8cb2 100644 --- a/src/views/checkPages/results/no-errors.html +++ b/src/views/checkPages/results/no-errors.html @@ -7,7 +7,7 @@ {% from "govuk/components/pagination/macro.njk" import govukPagination %} - +{% set serviceType = 'Check' %} {% set pageName = 'Check your data before you continue' %} {% set errorMessage = 'Select if your data looks ok' %} diff --git a/src/views/checkPages/start.html b/src/views/checkPages/start.html index f5b80352..90e844c5 100644 --- a/src/views/checkPages/start.html +++ b/src/views/checkPages/start.html @@ -4,7 +4,8 @@ {% extends "layouts/main.html" %} -{% set pageName = serviceName %} +{% set serviceType = 'Check' %} +{% set pageName = 'Start' %} {% block content %} diff --git a/src/views/checkPages/statusPage/status.html b/src/views/checkPages/statusPage/status.html index f28926ce..0ac2b69b 100644 --- a/src/views/checkPages/statusPage/status.html +++ b/src/views/checkPages/statusPage/status.html @@ -4,9 +4,9 @@ {% extends "layouts/main.html" %} +{% set serviceType = 'Check' %} {% set pageName = 'Status' %} - {% if options.processingComplete %} {% set pageContent = fileCheckedContent() %} {% set buttonText = "Continue" %} diff --git a/src/views/checkPages/upload-method.html b/src/views/checkPages/upload-method.html index 333a252b..d0b08f27 100644 --- a/src/views/checkPages/upload-method.html +++ b/src/views/checkPages/upload-method.html @@ -5,6 +5,7 @@ {% extends "layouts/main.html" %} +{% set serviceType = 'Check' %} {% set pageName = 'How do you want to provide your data?' %} {% set errorMessage = 'Select how you want to provide your data' %} diff --git a/src/views/checkPages/upload.html b/src/views/checkPages/upload.html index 27f158c0..67630bf4 100644 --- a/src/views/checkPages/upload.html +++ b/src/views/checkPages/upload.html @@ -5,7 +5,7 @@ {% from 'govuk/components/error-message/macro.njk' import govukErrorMessage %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} - +{% set serviceType = 'Check' %} {% set pageName = 'Upload data' %} {% if 'datafile' in errors %} diff --git a/src/views/checkPages/url.html b/src/views/checkPages/url.html index adfc686a..6f703517 100644 --- a/src/views/checkPages/url.html +++ b/src/views/checkPages/url.html @@ -5,7 +5,7 @@ {% from 'govuk/components/error-message/macro.njk' import govukErrorMessage %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} - +{% set serviceType = 'Check' %} {% set pageName = 'URL' %} {% set errorMessage = 'There\'s something wrong with your URL' %} diff --git a/src/views/endpointSubmissionFormPages/check.html b/src/views/endpointSubmissionFormPages/check.html index aeb843bd..f10ddbf9 100644 --- a/src/views/endpointSubmissionFormPages/check.html +++ b/src/views/endpointSubmissionFormPages/check.html @@ -1,5 +1,6 @@ {% extends "layouts/main.html" %} +{% set serviceType = 'Submit' %} {% set pageName = 'Check details and send your data' %} {% from 'govuk/components/button/macro.njk' import govukButton %} diff --git a/src/views/endpointSubmissionFormPages/choose-dataset.html b/src/views/endpointSubmissionFormPages/choose-dataset.html index 0808907a..b7acc4d2 100644 --- a/src/views/endpointSubmissionFormPages/choose-dataset.html +++ b/src/views/endpointSubmissionFormPages/choose-dataset.html @@ -4,6 +4,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} +{% set serviceType = 'Submit' %} {% set pageName = "Choose dataset" %} {% block pageTitle %} diff --git a/src/views/endpointSubmissionFormPages/confirmation.html b/src/views/endpointSubmissionFormPages/confirmation.html index b050913e..89c2b19a 100644 --- a/src/views/endpointSubmissionFormPages/confirmation.html +++ b/src/views/endpointSubmissionFormPages/confirmation.html @@ -3,6 +3,7 @@ {% from "govuk/components/panel/macro.njk" import govukPanel %} +{% set serviceType = 'Submit' %} {% set pageName = (values['dataset'] | datasetSlugToReadableName) + " submitted" %} {% block content %} diff --git a/src/views/endpointSubmissionFormPages/dataset-details.html b/src/views/endpointSubmissionFormPages/dataset-details.html index c1681105..087a3b4d 100644 --- a/src/views/endpointSubmissionFormPages/dataset-details.html +++ b/src/views/endpointSubmissionFormPages/dataset-details.html @@ -5,6 +5,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} +{% set serviceType = 'Submit' %} {% set pageName = "Enter " + (values['dataset'] | datasetSlugToReadableName | lower) + " details" %} {% block pageTitle %} diff --git a/src/views/endpointSubmissionFormPages/lpa-details.html b/src/views/endpointSubmissionFormPages/lpa-details.html index 37ccb70b..9d8585b7 100644 --- a/src/views/endpointSubmissionFormPages/lpa-details.html +++ b/src/views/endpointSubmissionFormPages/lpa-details.html @@ -4,6 +4,7 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from 'govuk/components/error-summary/macro.njk' import govukErrorSummary %} +{% set serviceType = 'Submit' %} {% set pageName = 'Enter LPA details' %} {% block pageTitle %} diff --git a/src/views/endpointSubmissionFormPages/start.html b/src/views/endpointSubmissionFormPages/start.html index 7a2b3639..e6147654 100644 --- a/src/views/endpointSubmissionFormPages/start.html +++ b/src/views/endpointSubmissionFormPages/start.html @@ -2,11 +2,8 @@ {% from "govuk/components/button/macro.njk" import govukButton %} {% from "x-govuk/components/related-navigation/macro.njk" import xGovukRelatedNavigation %} -{% set pageName = serviceName %} - -{% block pageTitle %} - Start – {{ serviceName }} -{% endblock %} +{% set serviceType = 'Submit' %} +{% set pageName = 'Start' %} {% block content %} @@ -46,7 +43,7 @@

- {{ pageName }} + {{ serviceName }}

diff --git a/src/views/layouts/main.html b/src/views/layouts/main.html index 17acfa65..697a331e 100644 --- a/src/views/layouts/main.html +++ b/src/views/layouts/main.html @@ -9,6 +9,10 @@ {% from 'govuk/components/phase-banner/macro.njk' import govukPhaseBanner%} {% from 'govuk/components/back-link/macro.njk' import govukBackLink %} +{% if serviceType %} + {% set serviceName = serviceType | getFullServiceName %} +{% endif %} + {% block pageTitle %} {{ pageName }} - {{ serviceName }} {% endblock %} From 78177582765f018c5f2fe3d832dfadb29fe0a574 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 16:00:46 +0100 Subject: [PATCH 110/127] linting --- src/filters/getFullServiceName.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/filters/getFullServiceName.js b/src/filters/getFullServiceName.js index 1762b508..b012e0af 100644 --- a/src/filters/getFullServiceName.js +++ b/src/filters/getFullServiceName.js @@ -1,7 +1,7 @@ import config from '../../config/index.js' export default (service) => { - const serviceName = config.serviceName + const serviceName = config.serviceName - return serviceName.replace('Provide', service) -} \ No newline at end of file + return serviceName.replace('Provide', service) +} From 0981ac5b95dc00a118affbdfdbfe4c947b1b1a72 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 16:00:59 +0100 Subject: [PATCH 111/127] started fixing unit tests --- test/unit/check-answers.test.js | 2 +- test/unit/choose-datasetPage.test.js | 2 +- test/unit/confirmationPage.test.js | 2 +- test/unit/dataset-details.test.js | 4 +--- test/unit/errorsPage.test.js | 6 ++++-- test/unit/lpa-detailsPage.test.js | 2 +- test/unit/noErrorsPage.test.js | 6 ++++-- test/unit/startPage.test.js | 4 +++- 8 files changed, 16 insertions(+), 12 deletions(-) diff --git a/test/unit/check-answers.test.js b/test/unit/check-answers.test.js index 35f855f7..75978127 100644 --- a/test/unit/check-answers.test.js +++ b/test/unit/check-answers.test.js @@ -23,7 +23,7 @@ describe('check-answers View', () => { const html = stripWhitespace(nunjucks.render('check-answers.html', params)) runGenericPageTests(html, { - pageTitle: `Check your answers – ${config.serviceName}`, + pageTitle: 'Check your answers - Check planning and housing data for England', serviceName: config.serviceName }) diff --git a/test/unit/choose-datasetPage.test.js b/test/unit/choose-datasetPage.test.js index f5e01514..13e07b3c 100644 --- a/test/unit/choose-datasetPage.test.js +++ b/test/unit/choose-datasetPage.test.js @@ -13,7 +13,7 @@ describe('choose dataset View', () => { const html = nunjucks.render('choose-dataset.html', params) runGenericPageTests(html, { - pageTitle: `Choose dataset - ${config.serviceName}`, + pageTitle: 'Choose dataset - Submit planning and housing data for England', serviceName: config.serviceName }) diff --git a/test/unit/confirmationPage.test.js b/test/unit/confirmationPage.test.js index ad480258..8db535e6 100644 --- a/test/unit/confirmationPage.test.js +++ b/test/unit/confirmationPage.test.js @@ -18,7 +18,7 @@ describe('Confirmation View', () => { const html = stripWhitespace(nunjucks.render('confirmation.html', params)) runGenericPageTests(html, { - pageTitle: `A Mock dataset submitted - ${config.serviceName}`, + pageTitle: 'A Mock dataset submitted - Check planning and housing data for England', serviceName: config.serviceName }) diff --git a/test/unit/dataset-details.test.js b/test/unit/dataset-details.test.js index 0026e7c3..ff5de20d 100644 --- a/test/unit/dataset-details.test.js +++ b/test/unit/dataset-details.test.js @@ -43,9 +43,7 @@ describe('dataset details View', () => { const html = stripWhitespace(nunjucks.render('dataset-details.html', params)) const datasetName = mockDataSubjects.mockDataset.dataSets[0].text runGenericPageTests(html, { - pageTitle: `Enter ${datasetName.toLowerCase()} details - ${ - config.serviceName - }`, + pageTitle: `Enter ${datasetName.toLowerCase()} details - Submit planning and housing data for England`, serviceName: config.serviceName }) diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index 8603f2b5..5f734df7 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -11,7 +11,9 @@ import paginationTemplateTests from './paginationTemplateTests.js' const nunjucksEnv = nunjucks.configure([ 'src/views', - 'node_modules/govuk-frontend/', + 'src/views/checkPages', + 'src/views/endpointSubmissionFormPages', + 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { dev: true, @@ -19,7 +21,7 @@ const nunjucksEnv = nunjucks.configure([ watch: true }) -addFilters(nunjucksEnv) +addFilters(nunjucksEnv, { dataSubjects: {} }) describe('errors page', () => { it('renders the correct number of errors', () => { diff --git a/test/unit/lpa-detailsPage.test.js b/test/unit/lpa-detailsPage.test.js index 789acc19..5055add1 100644 --- a/test/unit/lpa-detailsPage.test.js +++ b/test/unit/lpa-detailsPage.test.js @@ -14,7 +14,7 @@ describe('Lpa-details View', () => { const htmlNoErrors = nunjucks.render('lpa-details.html', params) runGenericPageTests(htmlNoErrors, { - pageTitle: `Enter LPA details - ${config.serviceName}`, + pageTitle: 'Enter LPA details - Submit planning and housing data for England', serviceName: config.serviceName }) diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index a44c41ec..79a59437 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -11,7 +11,9 @@ import paginationTemplateTests from './paginationTemplateTests.js' const nunjucksEnv = nunjucks.configure([ 'src/views', - 'node_modules/govuk-frontend/', + 'src/views/checkPages', + 'src/views/endpointSubmissionFormPages', + 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { dev: true, @@ -19,7 +21,7 @@ const nunjucksEnv = nunjucks.configure([ watch: true }) -addFilters(nunjucksEnv) +addFilters(nunjucksEnv, { dataSubjects: {} }) describe('no Errors Page', () => { it('renders the correct number of errors', () => { diff --git a/test/unit/startPage.test.js b/test/unit/startPage.test.js index 9b1a4969..be17d9f8 100644 --- a/test/unit/startPage.test.js +++ b/test/unit/startPage.test.js @@ -1,3 +1,5 @@ +// ToDo: need to duplicate this test for submit start page + import { describe } from 'vitest' import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' import { runGenericPageTests } from './generic-page.js' @@ -11,7 +13,7 @@ describe('Start View', () => { const html = nunjucks.render('start.html', params) runGenericPageTests(html, { - pageTitle: `Start – ${config.serviceName}`, + pageTitle: 'Start - Check planning and housing data for England', serviceName: config.serviceName }) }) From 9c0836e31b4ee8b652873312a13cae2259646611 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Mon, 8 Jul 2024 16:01:16 +0100 Subject: [PATCH 112/127] change service name --- config/default.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/default.yaml b/config/default.yaml index a6a604cb..1668607d 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -17,7 +17,7 @@ aws: { redis: false # ToDo: url and name might need updating url: 'https://check-planning.data.gov.uk' -serviceName: 'Check planning and housing data for England' +serviceName: 'Provide planning and housing data for England' feedbackLink: 'https://docs.google.com/forms/d/e/1FAIpQLSdYXqY0Aaket9XJBiGDhSL_CD_cxHZxgvQCFZZtdURdvvIY5A/viewform' email: { templates: { From 0736a5b0febfbbfd4c5eda1bfdcd6efadd4fbb26 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 10:10:36 +0100 Subject: [PATCH 113/127] rename templates folder --- src/routes/form-wizard/check/steps.js | 5 ++-- .../endpoint-submission-form/steps.js | 7 +++-- src/serverSetup/nunjucks.js | 4 +-- .../{checkPages => check}/check-answers.html | 0 .../{checkPages => check}/confirmation.html | 0 .../{checkPages => check}/data-subject.html | 0 src/views/{checkPages => check}/dataset.html | 0 .../{checkPages => check}/geometry-type.html | 0 .../{checkPages => check}/results/errors.html | 0 .../results/failedFileRequest.html | 0 .../results/failedUrlRequest.html | 0 .../results/no-errors.html | 0 src/views/{checkPages => check}/start.html | 0 .../statusPage/checkingFileMacro.html | 0 .../statusPage/fileCheckedMacro.html | 0 .../statusPage/status.html | 0 .../{checkPages => check}/upload-method.html | 0 src/views/{checkPages => check}/upload.html | 0 src/views/{checkPages => check}/url.html | 0 .../check.html | 0 .../choose-dataset.html | 0 .../confirmation.html | 0 .../dataset-details.html | 0 .../lpa-details.html | 0 .../start.html | 0 test/unit/check/confirmationPage.test.js | 29 +++++++++++++++++++ test/unit/confirmationPage.test.js | 29 ------------------- .../confirmationPage.test.js | 29 +++++++++++++++++++ test/unit/errorsPage.test.js | 4 +-- test/unit/noErrorsPage.test.js | 4 +-- 30 files changed, 71 insertions(+), 40 deletions(-) rename src/views/{checkPages => check}/check-answers.html (100%) rename src/views/{checkPages => check}/confirmation.html (100%) rename src/views/{checkPages => check}/data-subject.html (100%) rename src/views/{checkPages => check}/dataset.html (100%) rename src/views/{checkPages => check}/geometry-type.html (100%) rename src/views/{checkPages => check}/results/errors.html (100%) rename src/views/{checkPages => check}/results/failedFileRequest.html (100%) rename src/views/{checkPages => check}/results/failedUrlRequest.html (100%) rename src/views/{checkPages => check}/results/no-errors.html (100%) rename src/views/{checkPages => check}/start.html (100%) rename src/views/{checkPages => check}/statusPage/checkingFileMacro.html (100%) rename src/views/{checkPages => check}/statusPage/fileCheckedMacro.html (100%) rename src/views/{checkPages => check}/statusPage/status.html (100%) rename src/views/{checkPages => check}/upload-method.html (100%) rename src/views/{checkPages => check}/upload.html (100%) rename src/views/{checkPages => check}/url.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/check.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/choose-dataset.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/confirmation.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/dataset-details.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/lpa-details.html (100%) rename src/views/{endpointSubmissionFormPages => submit}/start.html (100%) create mode 100644 test/unit/check/confirmationPage.test.js delete mode 100644 test/unit/confirmationPage.test.js create mode 100644 test/unit/endpointSubmissionForm/confirmationPage.test.js diff --git a/src/routes/form-wizard/check/steps.js b/src/routes/form-wizard/check/steps.js index 938356b9..eee307c8 100644 --- a/src/routes/form-wizard/check/steps.js +++ b/src/routes/form-wizard/check/steps.js @@ -17,7 +17,7 @@ export default { entryPoint: true, resetJourney: true, next: 'dataset', - template: '../views/checkPages/start.html', + template: '../views/check/start.html', noPost: true }, // '/data-subject': { @@ -88,6 +88,7 @@ export default { '/confirmation': { ...baseSettings, noPost: true, - checkJourney: false // ToDo: it would be useful here if we make sure they have selected if their results are ok from the previous step + checkJourney: false, // ToDo: it would be useful here if we make sure they have selected if their results are ok from the previous step + template: 'check/confirmation.html' } } diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js index b2554485..edbf8cd6 100644 --- a/src/routes/form-wizard/endpoint-submission-form/steps.js +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -14,8 +14,8 @@ export default { entryPoint: true, resetJourney: true, noPost: true, - template: '../views/endpointSubmissionFormPages/start.html', - next: '/submit/lpa-details' + template: 'submit/start.html', + next: 'submit/lpa-details' }, '/lpa-details': { ...defaultParams, @@ -43,6 +43,7 @@ export default { backLink: '/dataset-details' }, '/confirmation': { - ...defaultParams + ...defaultParams, + template: 'submit/confirmation.html' } } diff --git a/src/serverSetup/nunjucks.js b/src/serverSetup/nunjucks.js index 458f8e04..5a7a20e8 100644 --- a/src/serverSetup/nunjucks.js +++ b/src/serverSetup/nunjucks.js @@ -9,8 +9,8 @@ export function setupNunjucks ({ app, dataSubjects }) { const nunjucksEnv = nunjucks.configure([ 'src/views', - 'src/views/checkPages', - 'src/views/endpointSubmissionFormPages', + 'src/views/check', + 'src/views/submit', 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { diff --git a/src/views/checkPages/check-answers.html b/src/views/check/check-answers.html similarity index 100% rename from src/views/checkPages/check-answers.html rename to src/views/check/check-answers.html diff --git a/src/views/checkPages/confirmation.html b/src/views/check/confirmation.html similarity index 100% rename from src/views/checkPages/confirmation.html rename to src/views/check/confirmation.html diff --git a/src/views/checkPages/data-subject.html b/src/views/check/data-subject.html similarity index 100% rename from src/views/checkPages/data-subject.html rename to src/views/check/data-subject.html diff --git a/src/views/checkPages/dataset.html b/src/views/check/dataset.html similarity index 100% rename from src/views/checkPages/dataset.html rename to src/views/check/dataset.html diff --git a/src/views/checkPages/geometry-type.html b/src/views/check/geometry-type.html similarity index 100% rename from src/views/checkPages/geometry-type.html rename to src/views/check/geometry-type.html diff --git a/src/views/checkPages/results/errors.html b/src/views/check/results/errors.html similarity index 100% rename from src/views/checkPages/results/errors.html rename to src/views/check/results/errors.html diff --git a/src/views/checkPages/results/failedFileRequest.html b/src/views/check/results/failedFileRequest.html similarity index 100% rename from src/views/checkPages/results/failedFileRequest.html rename to src/views/check/results/failedFileRequest.html diff --git a/src/views/checkPages/results/failedUrlRequest.html b/src/views/check/results/failedUrlRequest.html similarity index 100% rename from src/views/checkPages/results/failedUrlRequest.html rename to src/views/check/results/failedUrlRequest.html diff --git a/src/views/checkPages/results/no-errors.html b/src/views/check/results/no-errors.html similarity index 100% rename from src/views/checkPages/results/no-errors.html rename to src/views/check/results/no-errors.html diff --git a/src/views/checkPages/start.html b/src/views/check/start.html similarity index 100% rename from src/views/checkPages/start.html rename to src/views/check/start.html diff --git a/src/views/checkPages/statusPage/checkingFileMacro.html b/src/views/check/statusPage/checkingFileMacro.html similarity index 100% rename from src/views/checkPages/statusPage/checkingFileMacro.html rename to src/views/check/statusPage/checkingFileMacro.html diff --git a/src/views/checkPages/statusPage/fileCheckedMacro.html b/src/views/check/statusPage/fileCheckedMacro.html similarity index 100% rename from src/views/checkPages/statusPage/fileCheckedMacro.html rename to src/views/check/statusPage/fileCheckedMacro.html diff --git a/src/views/checkPages/statusPage/status.html b/src/views/check/statusPage/status.html similarity index 100% rename from src/views/checkPages/statusPage/status.html rename to src/views/check/statusPage/status.html diff --git a/src/views/checkPages/upload-method.html b/src/views/check/upload-method.html similarity index 100% rename from src/views/checkPages/upload-method.html rename to src/views/check/upload-method.html diff --git a/src/views/checkPages/upload.html b/src/views/check/upload.html similarity index 100% rename from src/views/checkPages/upload.html rename to src/views/check/upload.html diff --git a/src/views/checkPages/url.html b/src/views/check/url.html similarity index 100% rename from src/views/checkPages/url.html rename to src/views/check/url.html diff --git a/src/views/endpointSubmissionFormPages/check.html b/src/views/submit/check.html similarity index 100% rename from src/views/endpointSubmissionFormPages/check.html rename to src/views/submit/check.html diff --git a/src/views/endpointSubmissionFormPages/choose-dataset.html b/src/views/submit/choose-dataset.html similarity index 100% rename from src/views/endpointSubmissionFormPages/choose-dataset.html rename to src/views/submit/choose-dataset.html diff --git a/src/views/endpointSubmissionFormPages/confirmation.html b/src/views/submit/confirmation.html similarity index 100% rename from src/views/endpointSubmissionFormPages/confirmation.html rename to src/views/submit/confirmation.html diff --git a/src/views/endpointSubmissionFormPages/dataset-details.html b/src/views/submit/dataset-details.html similarity index 100% rename from src/views/endpointSubmissionFormPages/dataset-details.html rename to src/views/submit/dataset-details.html diff --git a/src/views/endpointSubmissionFormPages/lpa-details.html b/src/views/submit/lpa-details.html similarity index 100% rename from src/views/endpointSubmissionFormPages/lpa-details.html rename to src/views/submit/lpa-details.html diff --git a/src/views/endpointSubmissionFormPages/start.html b/src/views/submit/start.html similarity index 100% rename from src/views/endpointSubmissionFormPages/start.html rename to src/views/submit/start.html diff --git a/test/unit/check/confirmationPage.test.js b/test/unit/check/confirmationPage.test.js new file mode 100644 index 00000000..8a668ffa --- /dev/null +++ b/test/unit/check/confirmationPage.test.js @@ -0,0 +1,29 @@ +/* eslint-disable prefer-regex-literals */ + +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from '../generic-page.js' +import config from '../../../config/index.js' +import { stripWhitespace } from '../../utils/stripWhiteSpace.js' +import { mockDataSubjects } from '../data.js' + +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) + +describe('Check confirmation View', () => { + const params = { + values: { + dataset: 'mockDataset' + } + } + const html = stripWhitespace(nunjucks.render('submit/confirmation.html', params)) + + runGenericPageTests(html, { + pageTitle: 'A Mock dataset submitted - Submit planning and housing data for England', + serviceName: config.serviceName + }) + + it('should render the gov uk panel', () => { + const regex = new RegExp('

', 'g') + expect(html).toMatch(regex) + }) +}) diff --git a/test/unit/confirmationPage.test.js b/test/unit/confirmationPage.test.js deleted file mode 100644 index 8db535e6..00000000 --- a/test/unit/confirmationPage.test.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable prefer-regex-literals */ - -import { describe, expect, it } from 'vitest' -import { setupNunjucks } from '../../src/serverSetup/nunjucks.js' -import { runGenericPageTests } from './generic-page.js' -import config from '../../config/index.js' -import { stripWhitespace } from '../utils/stripWhiteSpace.js' -import { mockDataSubjects } from './data.js' - -const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) - -describe('Confirmation View', () => { - const params = { - values: { - dataset: 'mockDataset' - } - } - const html = stripWhitespace(nunjucks.render('confirmation.html', params)) - - runGenericPageTests(html, { - pageTitle: 'A Mock dataset submitted - Check planning and housing data for England', - serviceName: config.serviceName - }) - - it('should render the gov uk panel', () => { - const regex = new RegExp('

', 'g') - expect(html).toMatch(regex) - }) -}) diff --git a/test/unit/endpointSubmissionForm/confirmationPage.test.js b/test/unit/endpointSubmissionForm/confirmationPage.test.js new file mode 100644 index 00000000..cc624949 --- /dev/null +++ b/test/unit/endpointSubmissionForm/confirmationPage.test.js @@ -0,0 +1,29 @@ +/* eslint-disable prefer-regex-literals */ + +import { describe, expect, it } from 'vitest' +import { setupNunjucks } from '../../../src/serverSetup/nunjucks.js' +import { runGenericPageTests } from '../generic-page.js' +import config from '../../../config/index.js' +import { stripWhitespace } from '../../utils/stripWhiteSpace.js' +import { mockDataSubjects } from '../data.js' + +const nunjucks = setupNunjucks({ dataSubjects: mockDataSubjects }) + +describe('Submit confirmation View', () => { + const params = { + values: { + dataset: 'mockDataset' + } + } + const html = stripWhitespace(nunjucks.render('submit/confirmation.html', params)) + + runGenericPageTests(html, { + pageTitle: 'A Mock dataset submitted - Submit planning and housing data for England', + serviceName: config.serviceName + }) + + it('should render the gov uk panel', () => { + const regex = new RegExp('

', 'g') + expect(html).toMatch(regex) + }) +}) diff --git a/test/unit/errorsPage.test.js b/test/unit/errorsPage.test.js index 5f734df7..722e13b4 100644 --- a/test/unit/errorsPage.test.js +++ b/test/unit/errorsPage.test.js @@ -11,8 +11,8 @@ import paginationTemplateTests from './paginationTemplateTests.js' const nunjucksEnv = nunjucks.configure([ 'src/views', - 'src/views/checkPages', - 'src/views/endpointSubmissionFormPages', + 'src/views/check', + 'src/views/submit', 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { diff --git a/test/unit/noErrorsPage.test.js b/test/unit/noErrorsPage.test.js index 79a59437..87783c43 100644 --- a/test/unit/noErrorsPage.test.js +++ b/test/unit/noErrorsPage.test.js @@ -11,8 +11,8 @@ import paginationTemplateTests from './paginationTemplateTests.js' const nunjucksEnv = nunjucks.configure([ 'src/views', - 'src/views/checkPages', - 'src/views/endpointSubmissionFormPages', + 'src/views/check', + 'src/views/submit', 'node_modules/govuk-frontend/dist/', 'node_modules/@x-govuk/govuk-prototype-components/' ], { From 2ec52f5c81be5ea20df635580a8fb82eaf3cb54e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 10:18:56 +0100 Subject: [PATCH 114/127] fix some routing --- .../form-wizard/endpoint-submission-form/steps.js | 4 ++-- src/views/submit/start.html | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js index edbf8cd6..6295d0d2 100644 --- a/src/routes/form-wizard/endpoint-submission-form/steps.js +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -14,8 +14,8 @@ export default { entryPoint: true, resetJourney: true, noPost: true, - template: 'submit/start.html', - next: 'submit/lpa-details' + template: 'start.html', + next: '/submit/lpa-details' }, '/lpa-details': { ...defaultParams, diff --git a/src/views/submit/start.html b/src/views/submit/start.html index e6147654..01daeb65 100644 --- a/src/views/submit/start.html +++ b/src/views/submit/start.html @@ -31,13 +31,13 @@ - a summary of what the data is about - a statement that the data is provided under the Open Government Licence - -{{ govukButton({ - text: "Start now", - href: "./submit/lpa-details", - isStartButton: true - }) }} - + + {{ govukButton({ + text: "Start now", + isStartButton: true + }) }} + + {% endset %}
From 2dd62956fb6d094fe616fc6ab387644d1357584e Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 10:26:40 +0100 Subject: [PATCH 115/127] update dependencies --- package-lock.json | 718 ++++++++++++---------------------------------- package.json | 19 +- 2 files changed, 187 insertions(+), 550 deletions(-) diff --git a/package-lock.json b/package-lock.json index b01d01af..9087002a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,6 @@ "connect-redis": "^7.1.1", "cookie-parser": "^1.4.6", "dotenv": "^16.4.5", - "email-validator": "^2.0.4", "express": "^4.19.2", "express-session": "^1.18.0", "fs": "^0.0.1-security", @@ -44,7 +43,6 @@ "@playwright/test": "^1.39.0", "@testcontainers/localstack": "^10.7.2", "@types/node": "^20.8.9", - "@vitest/coverage-v8": "^0.34.6", "@wiremock/wiremock-testcontainers-node": "^0.0.1", "concurrently": "^8.2.2", "husky": "^9.0.11", @@ -52,7 +50,7 @@ "nodemon": "^3.0.1", "standard": "^17.1.0", "supertest": "^7.0.0", - "vitest": "^1.6.0", + "vitest": "^0.34.6", "webpack": "^5.90.3", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.2" @@ -70,19 +68,6 @@ "node": ">=0.10.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@aws-crypto/crc32": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", @@ -900,12 +885,6 @@ "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", "dev": true }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, "node_modules/@colors/colors": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", @@ -1569,15 +1548,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -2229,9 +2199,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", - "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", "cpu": [ "arm" ], @@ -2242,9 +2212,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", - "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", "cpu": [ "arm64" ], @@ -2255,9 +2225,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", - "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", "cpu": [ "arm64" ], @@ -2268,9 +2238,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", - "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", "cpu": [ "x64" ], @@ -2281,9 +2251,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", - "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", "cpu": [ "arm" ], @@ -2294,9 +2264,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", - "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", "cpu": [ "arm" ], @@ -2307,9 +2277,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", - "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", "cpu": [ "arm64" ], @@ -2320,9 +2290,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", - "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", "cpu": [ "arm64" ], @@ -2333,9 +2303,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", - "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", "cpu": [ "ppc64" ], @@ -2346,9 +2316,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", - "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", "cpu": [ "riscv64" ], @@ -2359,9 +2329,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", - "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", "cpu": [ "s390x" ], @@ -2372,9 +2342,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", - "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", "cpu": [ "x64" ], @@ -2385,9 +2355,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", - "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", "cpu": [ "x64" ], @@ -2398,9 +2368,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", - "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", "cpu": [ "arm64" ], @@ -2411,9 +2381,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", - "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", "cpu": [ "ia32" ], @@ -2424,9 +2394,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", - "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", "cpu": [ "x64" ], @@ -3270,6 +3240,21 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/chai": { + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", + "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.5.tgz", + "integrity": "sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/concat-stream": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", @@ -3439,12 +3424,6 @@ "@types/node": "*" } }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -3690,39 +3669,14 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, - "node_modules/@vitest/coverage-v8": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz", - "integrity": "sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@bcoe/v8-coverage": "^0.2.3", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.1.5", - "magic-string": "^0.30.1", - "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": ">=0.32.0 <1" - } - }, "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", "dev": true, "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", "chai": "^4.3.10" }, "funding": { @@ -3730,13 +3684,13 @@ } }, "node_modules/@vitest/runner": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", - "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", "dev": true, "dependencies": { - "@vitest/utils": "1.6.0", - "p-limit": "^5.0.0", + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", "pathe": "^1.1.1" }, "funding": { @@ -3744,15 +3698,15 @@ } }, "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3771,41 +3725,40 @@ } }, "node_modules/@vitest/snapshot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", - "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", "dev": true, "dependencies": { - "magic-string": "^0.30.5", + "magic-string": "^0.30.1", "pathe": "^1.1.1", - "pretty-format": "^29.7.0" + "pretty-format": "^29.5.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", "dev": true, "dependencies": { - "tinyspy": "^2.2.0" + "tinyspy": "^2.1.1" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", "dev": true, "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -4132,10 +4085,13 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", - "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", "dev": true, + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -5882,12 +5838,6 @@ "node": ">= 0.6" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", @@ -6637,14 +6587,6 @@ "integrity": "sha512-oJRPo82XEqtQAobHpJIR3zW5YO3sSRRkPz2an4yxi1UvqhsGm54vR/wzTFV74a3soDOJ8CKW7ajOOX5ESzddwg==", "dev": true }, - "node_modules/email-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", - "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==", - "engines": { - "node": ">4.0" - } - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -7651,15 +7593,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -8843,12 +8776,6 @@ } ] }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, "node_modules/http-basic": { "version": "8.1.3", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", @@ -9755,91 +9682,6 @@ "node": ">=0.10.0" } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/iterator.prototype": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", @@ -10282,14 +10124,10 @@ } }, "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", "dev": true, - "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" - }, "engines": { "node": ">=14" }, @@ -10484,21 +10322,6 @@ "node": ">=12" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/maplibre-gl": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.1.2.tgz", @@ -12631,9 +12454,9 @@ "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" }, "node_modules/rollup": { - "version": "4.18.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", - "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -12646,22 +12469,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.18.0", - "@rollup/rollup-android-arm64": "4.18.0", - "@rollup/rollup-darwin-arm64": "4.18.0", - "@rollup/rollup-darwin-x64": "4.18.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", - "@rollup/rollup-linux-arm-musleabihf": "4.18.0", - "@rollup/rollup-linux-arm64-gnu": "4.18.0", - "@rollup/rollup-linux-arm64-musl": "4.18.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", - "@rollup/rollup-linux-riscv64-gnu": "4.18.0", - "@rollup/rollup-linux-s390x-gnu": "4.18.0", - "@rollup/rollup-linux-x64-gnu": "4.18.0", - "@rollup/rollup-linux-x64-musl": "4.18.0", - "@rollup/rollup-win32-arm64-msvc": "4.18.0", - "@rollup/rollup-win32-ia32-msvc": "4.18.0", - "@rollup/rollup-win32-x64-msvc": "4.18.0", + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", "fsevents": "~2.3.2" } }, @@ -13879,23 +13702,17 @@ } }, "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", "dev": true, "dependencies": { - "js-tokens": "^9.0.0" + "acorn": "^8.10.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, "node_modules/strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", @@ -14121,62 +13938,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/testcontainers": { "version": "10.8.1", "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.8.1.tgz", @@ -14306,15 +14067,15 @@ "dev": true }, "node_modules/tinybench": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.6.0.tgz", - "integrity": "sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", + "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", "dev": true }, "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", + "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", "dev": true, "engines": { "node": ">=14.0.0" @@ -14840,20 +14601,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -14927,22 +14674,23 @@ } }, "node_modules/vite-node": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", - "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", "dev": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.4", + "mlly": "^1.4.0", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "vite": "^5.0.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=v14.18.0" }, "funding": { "url": "https://opencollective.com/vitest" @@ -14972,56 +14720,59 @@ "dev": true }, "node_modules/vitest": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", - "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", "dev": true, "dependencies": { - "@vitest/expect": "1.6.0", - "@vitest/runner": "1.6.0", - "@vitest/snapshot": "1.6.0", - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "acorn-walk": "^8.3.2", + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", "chai": "^4.3.10", "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.1", "pathe": "^1.1.1", "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.6.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.7.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", + "vite-node": "0.34.6", "why-is-node-running": "^2.2.2" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">=v14.18.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.0", - "@vitest/ui": "1.6.0", + "@vitest/browser": "*", + "@vitest/ui": "*", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, - "@types/node": { - "optional": true - }, "@vitest/browser": { "optional": true }, @@ -15033,13 +14784,22 @@ }, "jsdom": { "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true } } }, "node_modules/vitest/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -15053,134 +14813,12 @@ } } }, - "node_modules/vitest/node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/vitest/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/vitest/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/vitest/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/vitest/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/vitest/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/vt-pbf": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz", diff --git a/package.json b/package.json index dacb3b4b..5e2f70b1 100644 --- a/package.json +++ b/package.json @@ -39,43 +39,42 @@ "@playwright/test": "^1.39.0", "@testcontainers/localstack": "^10.7.2", "@types/node": "^20.8.9", - "@vitest/coverage-v8": "^0.34.6", "@wiremock/wiremock-testcontainers-node": "^0.0.1", "concurrently": "^8.2.2", + "husky": "^9.0.11", + "jsdom": "^24.1.0", "nodemon": "^3.0.1", "standard": "^17.1.0", "supertest": "^7.0.0", + "vitest": "^0.34.6", "webpack": "^5.90.3", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.2", - "husky": "^9.0.11", - "jsdom": "^24.1.0", - "vitest": "^1.6.0" + "webpack-dev-server": "^5.0.2" }, "dependencies": { "@aws-sdk/client-s3": "^3.537.0", "@sentry/node": "^8.7.0", "@sentry/profiling-node": "^8.7.0", - "aws-sdk": "^2.1581.0", - "axios": "^1.6.2", - "connect-redis": "^7.1.1", - "fs": "^0.0.1-security", "@x-govuk/govuk-prototype-components": "^3.0.5", "@x-govuk/govuk-prototype-filters": "^1.4.0", + "aws-sdk": "^2.1581.0", + "axios": "^1.6.2", "body-parser": "^1.20.2", + "connect-redis": "^7.1.1", "cookie-parser": "^1.4.6", "dotenv": "^16.4.5", "express": "^4.19.2", "express-session": "^1.18.0", + "fs": "^0.0.1-security", "govuk-frontend": "^5.4.0", "hmpo-config": "^3.0.0", "hmpo-form-wizard": "^13.0.0", "hmpo-i18n": "^6.0.1", "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "notifications-node-client": "^8.2.0", "maplibre-gl": "^4.1.0", "multer": "^1.4.5-lts.1", + "notifications-node-client": "^8.2.0", "nunjucks": "^3.2.4", "redis": "^4.6.13", "sass": "^1.69.4", From 8fbc637d17599eabe92f05eede6c7df810613069 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 10:39:56 +0100 Subject: [PATCH 116/127] fix scss import --- src/assets/scss/index.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/scss/index.scss b/src/assets/scss/index.scss index 44131930..7f667914 100644 --- a/src/assets/scss/index.scss +++ b/src/assets/scss/index.scss @@ -1,6 +1,6 @@ $govuk-global-styles: true; -@import "node_modules/govuk-frontend/govuk/all"; +@import "node_modules/govuk-frontend/dist/govuk/all"; @import "node_modules/@x-govuk/govuk-prototype-components/x-govuk/all"; @import "src/assets/scss/_scrollable-container.scss"; From 1dabbf35cc113945ac72f22b9972ce579fa62efb Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 10:41:53 +0100 Subject: [PATCH 117/127] remove ignored files --- public/stylesheets/index.css | 8391 ------------------------------ public/stylesheets/index.css.map | 1 - 2 files changed, 8392 deletions(-) delete mode 100644 public/stylesheets/index.css delete mode 100644 public/stylesheets/index.css.map diff --git a/public/stylesheets/index.css b/public/stylesheets/index.css deleted file mode 100644 index 8df6d862..00000000 --- a/public/stylesheets/index.css +++ /dev/null @@ -1,8391 +0,0 @@ -@charset "UTF-8"; -:root { - --govuk-frontend-version: "4.7.0"; -} - -a, .govuk-link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; -} -/*! Copyright (c) 2011 by Margaret Calvert & Henrik Kubel. All rights reserved. The font has been customised for exclusive use on gov.uk. This cut is not commercially available. */ /* stylelint-disable-line scss/comment-no-loud */ -@font-face { - font-family: "GDS Transport"; - font-style: normal; - font-weight: normal; - src: url("/assets/fonts/light-94a07e06a1-v2.woff2") format("woff2"), url("/assets/fonts/light-f591b13f7d-v2.woff") format("woff"); - font-display: fallback; -} -@font-face { - font-family: "GDS Transport"; - font-style: normal; - font-weight: bold; - src: url("/assets/fonts/bold-b542beb274-v2.woff2") format("woff2"), url("/assets/fonts/bold-affa96571d-v2.woff") format("woff"); - font-display: fallback; -} -@media print { - a, .govuk-link { - font-family: sans-serif; - } -} -a:focus, .govuk-link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -a:link, .govuk-link:link { - color: #1d70b8; -} -a:visited, .govuk-link:visited { - color: #4c2c92; -} -a:hover, .govuk-link:hover { - color: #003078; -} -a:active, .govuk-link:active { - color: #0b0c0c; -} -a:focus, .govuk-link:focus { - color: #0b0c0c; -} -@media print { - a[href^="/"]:after, [href^="/"].govuk-link:after, a[href^="http://"]:after, [href^="http://"].govuk-link:after, a[href^="https://"]:after, [href^="https://"].govuk-link:after { - content: " (" attr(href) ")"; - font-size: 90%; - word-wrap: break-word; - } -} - -.govuk-link--muted:link, .govuk-link--muted:visited { - color: #505a5f; -} -.govuk-link--muted:hover, .govuk-link--muted:active { - color: #0b0c0c; -} -.govuk-link--muted:focus { - color: #0b0c0c; -} - -.govuk-link--text-colour:link, .govuk-link--text-colour:visited { - color: #0b0c0c; -} -@media print { - .govuk-link--text-colour:link, .govuk-link--text-colour:visited { - color: #000000; - } -} -.govuk-link--text-colour:hover { - color: rgba(11, 12, 12, 0.99); -} -.govuk-link--text-colour:active, .govuk-link--text-colour:focus { - color: #0b0c0c; -} -@media print { - .govuk-link--text-colour:active, .govuk-link--text-colour:focus { - color: #000000; - } -} - -.govuk-link--inverse:link, .govuk-link--inverse:visited { - color: #ffffff; -} -.govuk-link--inverse:hover, .govuk-link--inverse:active { - color: rgba(255, 255, 255, 0.99); -} -.govuk-link--inverse:focus { - color: #0b0c0c; -} - -.govuk-link--no-underline:not(:hover):not(:active) { - text-decoration: none; -} - -.govuk-link--no-visited-state:link { - color: #1d70b8; -} -.govuk-link--no-visited-state:visited { - color: #1d70b8; -} -.govuk-link--no-visited-state:hover { - color: #003078; -} -.govuk-link--no-visited-state:active { - color: #0b0c0c; -} -.govuk-link--no-visited-state:focus { - color: #0b0c0c; -} - -.govuk-list { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - margin-top: 0; - margin-bottom: 15px; - padding-left: 0; - list-style-type: none; -} -@media print { - .govuk-list { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-list { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-list { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-list { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-list { - margin-bottom: 20px; - } -} -.govuk-list .govuk-list { - margin-top: 10px; -} - -.govuk-list > li { - margin-bottom: 5px; -} - -.govuk-list--bullet { - padding-left: 20px; - list-style-type: disc; -} - -.govuk-list--number { - padding-left: 20px; - list-style-type: decimal; -} - -.govuk-list--bullet > li, -.govuk-list--number > li { - margin-bottom: 0; -} -@media (min-width: 40.0625em) { - .govuk-list--bullet > li, - .govuk-list--number > li { - margin-bottom: 5px; - } -} - -.govuk-list--spaced > li { - margin-bottom: 10px; -} -@media (min-width: 40.0625em) { - .govuk-list--spaced > li { - margin-bottom: 15px; - } -} - -.govuk-heading-xl { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; - display: block; - margin-top: 0; - margin-bottom: 30px; -} -@media print { - .govuk-heading-xl { - color: #000000; - } -} -@media print { - .govuk-heading-xl { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-xl { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .govuk-heading-xl { - font-size: 32pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-xl { - margin-bottom: 50px; - } -} - -.govuk-heading-l { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; - display: block; - margin-top: 0; - margin-bottom: 20px; -} -@media print { - .govuk-heading-l { - color: #000000; - } -} -@media print { - .govuk-heading-l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-l { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-heading-l { - font-size: 24pt; - line-height: 1.05; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-l { - margin-bottom: 30px; - } -} - -.govuk-heading-m { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - display: block; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - .govuk-heading-m { - color: #000000; - } -} -@media print { - .govuk-heading-m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-m { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-heading-m { - font-size: 18pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-m { - margin-bottom: 20px; - } -} - -.govuk-heading-s { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: block; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - .govuk-heading-s { - color: #000000; - } -} -@media print { - .govuk-heading-s { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-s { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-heading-s { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-heading-s { - margin-bottom: 20px; - } -} - -.govuk-caption-xl { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - display: block; - margin-bottom: 5px; - color: #505a5f; -} -@media print { - .govuk-caption-xl { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-caption-xl { - font-size: 27px; - font-size: 1.6875rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-caption-xl { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-caption-l { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - display: block; - margin-bottom: 5px; - color: #505a5f; -} -@media print { - .govuk-caption-l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-caption-l { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-caption-l { - font-size: 18pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-caption-l { - margin-bottom: 0; - } -} - -.govuk-caption-m { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: block; - color: #505a5f; -} -@media print { - .govuk-caption-m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-caption-m { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-caption-m { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-body-lead, .govuk-body-l { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin-top: 0; - margin-bottom: 20px; -} -@media print { - .govuk-body-lead, .govuk-body-l { - color: #000000; - } -} -@media print { - .govuk-body-lead, .govuk-body-l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-body-lead, .govuk-body-l { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-body-lead, .govuk-body-l { - font-size: 18pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-body-lead, .govuk-body-l { - margin-bottom: 30px; - } -} - -p, .govuk-body, .govuk-body-m { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - p, .govuk-body, .govuk-body-m { - color: #000000; - } -} -@media print { - p, .govuk-body, .govuk-body-m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - p, .govuk-body, .govuk-body-m { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - p, .govuk-body, .govuk-body-m { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - p, .govuk-body, .govuk-body-m { - margin-bottom: 20px; - } -} - -.govuk-body-s { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - .govuk-body-s { - color: #000000; - } -} -@media print { - .govuk-body-s { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-body-s { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-body-s { - font-size: 14pt; - line-height: 1.2; - } -} -@media (min-width: 40.0625em) { - .govuk-body-s { - margin-bottom: 20px; - } -} - -.govuk-body-xs { - color: #0b0c0c; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 12px; - font-size: 0.75rem; - line-height: 1.25; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - .govuk-body-xs { - color: #000000; - } -} -@media print { - .govuk-body-xs { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-body-xs { - font-size: 14px; - font-size: 0.875rem; - line-height: 1.4285714286; - } -} -@media print { - .govuk-body-xs { - font-size: 12pt; - line-height: 1.2; - } -} -@media (min-width: 40.0625em) { - .govuk-body-xs { - margin-bottom: 20px; - } -} - -.govuk-body-l + .govuk-heading-l, .govuk-body-lead + .govuk-heading-l { - padding-top: 5px; -} -@media (min-width: 40.0625em) { - .govuk-body-l + .govuk-heading-l, .govuk-body-lead + .govuk-heading-l { - padding-top: 10px; - } -} - -p + .govuk-heading-l, .govuk-body-m + .govuk-heading-l, .govuk-body + .govuk-heading-l, -.govuk-body-s + .govuk-heading-l, -.govuk-list + .govuk-heading-l { - padding-top: 15px; -} -@media (min-width: 40.0625em) { - p + .govuk-heading-l, .govuk-body-m + .govuk-heading-l, .govuk-body + .govuk-heading-l, - .govuk-body-s + .govuk-heading-l, - .govuk-list + .govuk-heading-l { - padding-top: 20px; - } -} - -p + .govuk-heading-m, .govuk-body-m + .govuk-heading-m, .govuk-body + .govuk-heading-m, -.govuk-body-s + .govuk-heading-m, -.govuk-list + .govuk-heading-m, -p + .govuk-heading-s, -.govuk-body-m + .govuk-heading-s, -.govuk-body + .govuk-heading-s, -.govuk-body-s + .govuk-heading-s, -.govuk-list + .govuk-heading-s { - padding-top: 5px; -} -@media (min-width: 40.0625em) { - p + .govuk-heading-m, .govuk-body-m + .govuk-heading-m, .govuk-body + .govuk-heading-m, - .govuk-body-s + .govuk-heading-m, - .govuk-list + .govuk-heading-m, - p + .govuk-heading-s, - .govuk-body-m + .govuk-heading-s, - .govuk-body + .govuk-heading-s, - .govuk-body-s + .govuk-heading-s, - .govuk-list + .govuk-heading-s { - padding-top: 10px; - } -} - -.govuk-section-break { - margin: 0; - border: 0; -} - -.govuk-section-break--xl { - margin-top: 30px; - margin-bottom: 30px; -} -@media (min-width: 40.0625em) { - .govuk-section-break--xl { - margin-top: 50px; - } -} -@media (min-width: 40.0625em) { - .govuk-section-break--xl { - margin-bottom: 50px; - } -} - -.govuk-section-break--l { - margin-top: 20px; - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-section-break--l { - margin-top: 30px; - } -} -@media (min-width: 40.0625em) { - .govuk-section-break--l { - margin-bottom: 30px; - } -} - -.govuk-section-break--m { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 40.0625em) { - .govuk-section-break--m { - margin-top: 20px; - } -} -@media (min-width: 40.0625em) { - .govuk-section-break--m { - margin-bottom: 20px; - } -} - -.govuk-section-break--visible { - border-bottom: 1px solid #b1b4b6; -} - -.govuk-button-group { - margin-bottom: 5px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-align: center; - align-items: center; -} -@media (min-width: 40.0625em) { - .govuk-button-group { - margin-bottom: 15px; - } -} -.govuk-button-group .govuk-link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.1875; - display: inline-block; - max-width: 100%; - margin-top: 5px; - margin-bottom: 20px; - text-align: center; -} -@media print { - .govuk-button-group .govuk-link { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-button-group .govuk-link { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1; - } -} -@media print { - .govuk-button-group .govuk-link { - font-size: 14pt; - line-height: 19px; - } -} -.govuk-button-group .govuk-button { - margin-bottom: 17px; -} -@media (min-width: 40.0625em) { - .govuk-button-group { - margin-right: -15px; - -ms-flex-direction: row; - flex-direction: row; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-align: baseline; - align-items: baseline; - } - .govuk-button-group .govuk-button, - .govuk-button-group .govuk-link { - margin-right: 15px; - } - .govuk-button-group .govuk-link { - text-align: left; - } -} - -.govuk-form-group { - margin-bottom: 20px; -} -.govuk-form-group:after { - content: ""; - display: block; - clear: both; -} -@media (min-width: 40.0625em) { - .govuk-form-group { - margin-bottom: 30px; - } -} -.govuk-form-group .govuk-form-group:last-of-type { - margin-bottom: 0; -} - -.govuk-form-group--error { - padding-left: 15px; - border-left: 5px solid #d4351c; -} -.govuk-form-group--error .govuk-form-group { - padding: 0; - border: 0; -} - -.govuk-grid-row { - margin-right: -15px; - margin-left: -15px; -} -.govuk-grid-row:after { - content: ""; - display: block; - clear: both; -} - -.govuk-grid-column-one-quarter { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-one-quarter { - width: 25%; - float: left; - } -} - -.govuk-grid-column-one-third { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-one-third { - width: 33.3333333333%; - float: left; - } -} - -.govuk-grid-column-one-half { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-one-half { - width: 50%; - float: left; - } -} - -.govuk-grid-column-two-thirds { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-two-thirds { - width: 66.6666666667%; - float: left; - } -} - -.govuk-grid-column-three-quarters { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-three-quarters { - width: 75%; - float: left; - } -} - -.govuk-grid-column-full { - box-sizing: border-box; - width: 100%; - padding: 0 15px; -} -@media (min-width: 40.0625em) { - .govuk-grid-column-full { - width: 100%; - float: left; - } -} - -.govuk-grid-column-one-quarter-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-one-quarter-from-desktop { - width: 25%; - float: left; - } -} - -.govuk-grid-column-one-third-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-one-third-from-desktop { - width: 33.3333333333%; - float: left; - } -} - -.govuk-grid-column-one-half-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-one-half-from-desktop { - width: 50%; - float: left; - } -} - -.govuk-grid-column-two-thirds-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-two-thirds-from-desktop { - width: 66.6666666667%; - float: left; - } -} - -.govuk-grid-column-three-quarters-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-three-quarters-from-desktop { - width: 75%; - float: left; - } -} - -.govuk-grid-column-full-from-desktop { - box-sizing: border-box; - padding: 0 15px; -} -@media (min-width: 48.0625em) { - .govuk-grid-column-full-from-desktop { - width: 100%; - float: left; - } -} - -.govuk-main-wrapper { - display: block; - padding-top: 20px; - padding-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-main-wrapper { - padding-top: 40px; - padding-bottom: 40px; - } -} - -.govuk-main-wrapper--auto-spacing:first-child, -.govuk-main-wrapper--l { - padding-top: 30px; -} -@media (min-width: 40.0625em) { - .govuk-main-wrapper--auto-spacing:first-child, - .govuk-main-wrapper--l { - padding-top: 50px; - } -} - -.govuk-template { - background-color: #f3f2f1; - -webkit-text-size-adjust: 100%; - -moz-text-size-adjust: 100%; - text-size-adjust: 100%; -} -@supports (position: -webkit-sticky) or (position: sticky) { - .govuk-template { - scroll-padding-top: 60px; - } - .govuk-template:not(:has(.govuk-exit-this-page)) { - scroll-padding-top: 0; - } -} -@media screen { - .govuk-template { - overflow-y: scroll; - } -} - -.govuk-template__body { - margin: 0; - background-color: #ffffff; -} - -.govuk-width-container { - max-width: 960px; - margin-right: 15px; - margin-left: 15px; -} -@supports (margin: max(calc(0px))) { - .govuk-width-container { - margin-right: max(15px, calc(15px + env(safe-area-inset-right))); - margin-left: max(15px, calc(15px + env(safe-area-inset-left))); - } -} -@media (min-width: 40.0625em) { - .govuk-width-container { - margin-right: 30px; - margin-left: 30px; - } - @supports (margin: max(calc(0px))) { - .govuk-width-container { - margin-right: max(30px, calc(15px + env(safe-area-inset-right))); - margin-left: max(30px, calc(15px + env(safe-area-inset-left))); - } - } -} -@media (min-width: 1020px) { - .govuk-width-container { - margin-right: auto; - margin-left: auto; - } - @supports (margin: max(calc(0px))) { - .govuk-width-container { - margin-right: auto; - margin-left: auto; - } - } -} - -.govuk-accordion { - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-accordion { - margin-bottom: 30px; - } -} - -.govuk-accordion__section { - padding-top: 15px; -} - -.govuk-accordion__section-heading { - margin-top: 0; - margin-bottom: 0; - padding-top: 15px; - padding-bottom: 15px; -} - -.govuk-accordion__section-button { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - color: #0b0c0c; - display: block; - margin-bottom: 0; - padding-top: 15px; -} -@media print { - .govuk-accordion__section-button { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-accordion__section-button { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-accordion__section-button { - font-size: 18pt; - line-height: 1.15; - } -} -@media print { - .govuk-accordion__section-button { - color: #000000; - } -} - -.govuk-accordion__section-content > :last-child { - margin-bottom: 0; -} - -.js-enabled .govuk-accordion { - border-bottom: 1px solid #b1b4b6; -} -.js-enabled .govuk-accordion__section { - padding-top: 0; -} -.js-enabled .govuk-accordion__section-content { - display: none; - padding-top: 15px; - padding-bottom: 30px; -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__section-content { - padding-bottom: 50px; - } -} -.js-enabled .govuk-accordion__section-content[hidden] { - padding-top: 0; - padding-bottom: 0; -} -@supports (content-visibility: hidden) { - .js-enabled .govuk-accordion__section-content[hidden] { - content-visibility: hidden; - display: inherit; - } -} -.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-content { - display: block; -} -.js-enabled .govuk-accordion__show-all { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - position: relative; - z-index: 1; - margin-bottom: 9px; - padding: 5px 2px 5px 0; - border-width: 0; - color: #1d70b8; - background: none; - cursor: pointer; - -webkit-appearance: none; -} -@media print { - .js-enabled .govuk-accordion__show-all { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__show-all { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .js-enabled .govuk-accordion__show-all { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__show-all { - margin-bottom: 14px; - } -} -.js-enabled .govuk-accordion__show-all::-moz-focus-inner { - padding: 0; - border: 0; -} -.js-enabled .govuk-accordion__show-all:hover { - color: #0b0c0c; - background: #f3f2f1; - box-shadow: 0 -2px #f3f2f1, 0 4px #f3f2f1; -} -.js-enabled .govuk-accordion__show-all:hover .govuk-accordion__section-toggle-text { - color: #0b0c0c; -} -.js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron { - color: #0b0c0c; - background: #0b0c0c; -} -.js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron:after { - color: #f3f2f1; -} -.js-enabled .govuk-accordion__show-all:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron { - background: #0b0c0c; -} -.js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron:after { - color: #ffdd00; -} -.js-enabled .govuk-accordion__section-heading { - padding: 0; -} -.js-enabled .govuk-accordion-nav__chevron { - box-sizing: border-box; - display: inline-block; - position: relative; - width: 1.25rem; - height: 1.25rem; - border: 0.0625rem solid; - border-radius: 50%; - vertical-align: middle; -} -.js-enabled .govuk-accordion-nav__chevron:after { - content: ""; - box-sizing: border-box; - display: block; - position: absolute; - bottom: 0.3125rem; - left: 0.375rem; - width: 0.375rem; - height: 0.375rem; - -webkit-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - transform: rotate(-45deg); - border-top: 0.125rem solid; - border-right: 0.125rem solid; -} -.js-enabled .govuk-accordion-nav__chevron--down { - -webkit-transform: rotate(180deg); - -ms-transform: rotate(180deg); - transform: rotate(180deg); -} -.js-enabled .govuk-accordion__section-button { - width: 100%; - padding: 10px 0 0 0; - border: 0; - border-top: 1px solid #b1b4b6; - border-bottom: 10px solid transparent; - color: #0b0c0c; - background: none; - text-align: left; - cursor: pointer; - -webkit-appearance: none; -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__section-button { - padding-bottom: 10px; - } -} -.js-enabled .govuk-accordion__section-button:active { - color: #0b0c0c; - background: none; -} -.js-enabled .govuk-accordion__section-button:hover { - color: #0b0c0c; - background: #f3f2f1; -} -.js-enabled .govuk-accordion__section-button:hover .govuk-accordion__section-toggle-text { - color: #0b0c0c; -} -.js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron { - color: #0b0c0c; - background: #0b0c0c; -} -.js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron:after { - color: #f3f2f1; -} -.js-enabled .govuk-accordion__section-button:focus { - outline: 0; -} -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-heading-text-focus, -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-summary-focus, -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron { - color: #0b0c0c; - background: #0b0c0c; -} -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron:after { - color: #ffdd00; -} -.js-enabled .govuk-accordion__section-button::-moz-focus-inner { - padding: 0; - border: 0; -} -.js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-button { - padding-bottom: 15px; - border-bottom: 0; -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__section--expanded .govuk-accordion__section-button { - padding-bottom: 20px; - } -} -.js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { - padding-bottom: 3px; -} -@media (min-width: 48.0625em) { - .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus { - padding-bottom: 2px; - } -} -.js-enabled .govuk-accordion__section-toggle, -.js-enabled .govuk-accordion__section-heading-text, -.js-enabled .govuk-accordion__section-summary { - display: block; - margin-bottom: 13px; -} -.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-heading-text-focus, -.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-summary-focus, -.js-enabled .govuk-accordion__section-toggle .govuk-accordion__section-toggle-focus, -.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-heading-text-focus, -.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-summary-focus, -.js-enabled .govuk-accordion__section-heading-text .govuk-accordion__section-toggle-focus, -.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-heading-text-focus, -.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-summary-focus, -.js-enabled .govuk-accordion__section-summary .govuk-accordion__section-toggle-focus { - display: inline; -} -.js-enabled .govuk-accordion__section-toggle { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - font-weight: 400; - color: #1d70b8; -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-accordion__section-toggle { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .js-enabled .govuk-accordion__section-toggle { - font-size: 14pt; - line-height: 1.15; - } -} -.js-enabled .govuk-accordion__show-all-text, -.js-enabled .govuk-accordion__section-toggle-text { - margin-left: 5px; - vertical-align: middle; -} -@media screen and (forced-colors: active) { - .js-enabled .govuk-accordion__show-all:hover .govuk-accordion-nav__chevron, - .js-enabled .govuk-accordion__section-button:hover .govuk-accordion-nav__chevron { - background-color: transparent; - } - .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-heading-text-focus, - .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-summary-focus, - .js-enabled .govuk-accordion__show-all:focus .govuk-accordion__section-toggle-focus, - .js-enabled .govuk-accordion__show-all:focus .govuk-accordion-nav__chevron, - .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-heading-text-focus, - .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-summary-focus, - .js-enabled .govuk-accordion__section-button:focus .govuk-accordion__section-toggle-focus, - .js-enabled .govuk-accordion__section-button:focus .govuk-accordion-nav__chevron { - background: transparent; - background-color: transparent; - } -} -@media (hover: none) { - .js-enabled .govuk-accordion__section-header:hover { - border-top-color: #b1b4b6; - box-shadow: inset 0 3px 0 0 #1d70b8; - } - .js-enabled .govuk-accordion__section-header:hover .govuk-accordion__section-button { - border-top-color: #b1b4b6; - } -} - -.govuk-back-link { - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; - display: inline-block; - position: relative; - margin-top: 15px; - margin-bottom: 15px; - padding-left: 0.875em; -} -@media (min-width: 40.0625em) { - .govuk-back-link { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-back-link { - font-size: 14pt; - line-height: 1.2; - } -} -@media print { - .govuk-back-link { - font-family: sans-serif; - } -} -.govuk-back-link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-back-link:link, .govuk-back-link:visited { - color: #0b0c0c; -} -@media print { - .govuk-back-link:link, .govuk-back-link:visited { - color: #000000; - } -} -.govuk-back-link:hover { - color: rgba(11, 12, 12, 0.99); -} -.govuk-back-link:active, .govuk-back-link:focus { - color: #0b0c0c; -} -@media print { - .govuk-back-link:active, .govuk-back-link:focus { - color: #000000; - } -} - -.govuk-back-link:before { - content: ""; - display: block; - position: absolute; - top: 0; - bottom: 0; - left: 0.1875em; - width: 0.4375em; - height: 0.4375em; - margin: auto 0; - -webkit-transform: rotate(225deg); - -ms-transform: rotate(225deg); - transform: rotate(225deg); - border: solid; - border-width: 1px 1px 0 0; - border-color: #505a5f; -} -@supports (border-width: max(0px)) { - .govuk-back-link:before { - border-width: max(1px, 0.0625em) max(1px, 0.0625em) 0 0; - font-size: max(16px, 1em); - } -} - -.govuk-back-link:focus:before { - border-color: #0b0c0c; -} - -.govuk-back-link:after { - content: ""; - position: absolute; - top: -14px; - right: 0; - bottom: -14px; - left: 0; -} - -.govuk-back-link--inverse:link, .govuk-back-link--inverse:visited { - color: #ffffff; -} -.govuk-back-link--inverse:hover, .govuk-back-link--inverse:active { - color: rgba(255, 255, 255, 0.99); -} -.govuk-back-link--inverse:focus { - color: #0b0c0c; -} -.govuk-back-link--inverse:before { - border-color: currentcolor; -} - -.govuk-breadcrumbs { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - color: #0b0c0c; - margin-top: 15px; - margin-bottom: 10px; -} -@media print { - .govuk-breadcrumbs { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-breadcrumbs { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-breadcrumbs { - font-size: 14pt; - line-height: 1.2; - } -} -@media print { - .govuk-breadcrumbs { - color: #000000; - } -} - -.govuk-breadcrumbs__list { - margin: 0; - padding: 0; - list-style-type: none; -} -.govuk-breadcrumbs__list:after { - content: ""; - display: block; - clear: both; -} - -.govuk-breadcrumbs__list-item { - display: inline-block; - position: relative; - margin-bottom: 5px; - margin-left: 0.625em; - padding-left: 0.9784375em; - float: left; -} -.govuk-breadcrumbs__list-item:before { - content: ""; - display: block; - position: absolute; - top: 0; - bottom: 0; - left: -0.206875em; - width: 0.4375em; - height: 0.4375em; - margin: auto 0; - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); - border: solid; - border-width: 1px 1px 0 0; - border-color: #505a5f; -} -@supports (border-width: max(0px)) { - .govuk-breadcrumbs__list-item:before { - border-width: max(1px, 0.0625em) max(1px, 0.0625em) 0 0; - font-size: max(16px, 1em); - } -} -.govuk-breadcrumbs__list-item:first-child { - margin-left: 0; - padding-left: 0; -} -.govuk-breadcrumbs__list-item:first-child:before { - content: none; - display: none; -} - -.govuk-breadcrumbs__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; -} -@media print { - .govuk-breadcrumbs__link { - font-family: sans-serif; - } -} -.govuk-breadcrumbs__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-breadcrumbs__link:link, .govuk-breadcrumbs__link:visited { - color: #0b0c0c; -} -@media print { - .govuk-breadcrumbs__link:link, .govuk-breadcrumbs__link:visited { - color: #000000; - } -} -.govuk-breadcrumbs__link:hover { - color: rgba(11, 12, 12, 0.99); -} -.govuk-breadcrumbs__link:active, .govuk-breadcrumbs__link:focus { - color: #0b0c0c; -} -@media print { - .govuk-breadcrumbs__link:active, .govuk-breadcrumbs__link:focus { - color: #000000; - } -} - -@media (max-width: 40.0525em) { - .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item { - display: none; - } - .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:first-child, .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:last-child { - display: inline-block; - } - .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list-item:before { - top: 0.375em; - margin: 0; - } - .govuk-breadcrumbs--collapse-on-mobile .govuk-breadcrumbs__list { - display: -ms-flexbox; - display: flex; - } -} - -.govuk-breadcrumbs--inverse { - color: #ffffff; -} -.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:link, .govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:visited { - color: #ffffff; -} -.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:hover, .govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:active { - color: rgba(255, 255, 255, 0.99); -} -.govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:focus { - color: #0b0c0c; -} -.govuk-breadcrumbs--inverse .govuk-breadcrumbs__list-item:before { - border-color: currentcolor; -} - -.govuk-button { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.1875; - box-sizing: border-box; - display: inline-block; - position: relative; - width: 100%; - margin-top: 0; - margin-right: 0; - margin-left: 0; - margin-bottom: 22px; - padding: 8px 10px 7px; - border: 2px solid transparent; - border-radius: 0; - color: #ffffff; - background-color: #00703c; - box-shadow: 0 2px 0 #002d18; - text-align: center; - vertical-align: top; - cursor: pointer; - -webkit-appearance: none; -} -@media print { - .govuk-button { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-button { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1; - } -} -@media print { - .govuk-button { - font-size: 14pt; - line-height: 19px; - } -} -@media (min-width: 40.0625em) { - .govuk-button { - margin-bottom: 32px; - } -} -@media (min-width: 40.0625em) { - .govuk-button { - width: auto; - } -} -.govuk-button:link, .govuk-button:visited, .govuk-button:active, .govuk-button:hover { - color: #ffffff; - text-decoration: none; -} -.govuk-button::-moz-focus-inner { - padding: 0; - border: 0; -} -.govuk-button:hover { - background-color: #005a30; -} -.govuk-button:active { - top: 2px; -} -.govuk-button:focus { - border-color: #ffdd00; - outline: 3px solid transparent; - box-shadow: inset 0 0 0 1px #ffdd00; -} -.govuk-button:focus:not(:active):not(:hover) { - border-color: #ffdd00; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 2px 0 #0b0c0c; -} -.govuk-button:before { - content: ""; - display: block; - position: absolute; - top: -2px; - right: -2px; - bottom: -4px; - left: -2px; - background: transparent; -} -.govuk-button:active:before { - top: -4px; -} - -.govuk-button--disabled, -.govuk-button[disabled=disabled], -.govuk-button[disabled] { - opacity: 0.5; -} -.govuk-button--disabled:hover, -.govuk-button[disabled=disabled]:hover, -.govuk-button[disabled]:hover { - background-color: #00703c; - cursor: not-allowed; -} -.govuk-button--disabled:active, -.govuk-button[disabled=disabled]:active, -.govuk-button[disabled]:active { - top: 0; - box-shadow: 0 2px 0 #002d18; -} - -.govuk-button--secondary { - background-color: #f3f2f1; - box-shadow: 0 2px 0 #929191; -} -.govuk-button--secondary, .govuk-button--secondary:link, .govuk-button--secondary:visited, .govuk-button--secondary:active, .govuk-button--secondary:hover { - color: #0b0c0c; -} -.govuk-button--secondary:hover { - background-color: #dbdad9; -} -.govuk-button--secondary:hover[disabled] { - background-color: #f3f2f1; -} - -.govuk-button--warning { - background-color: #d4351c; - box-shadow: 0 2px 0 #55150b; -} -.govuk-button--warning, .govuk-button--warning:link, .govuk-button--warning:visited, .govuk-button--warning:active, .govuk-button--warning:hover { - color: #ffffff; -} -.govuk-button--warning:hover { - background-color: #aa2a16; -} -.govuk-button--warning:hover[disabled] { - background-color: #d4351c; -} - -.govuk-button--inverse { - background-color: #ffffff; - box-shadow: 0 2px 0 #144e81; -} -.govuk-button--inverse, .govuk-button--inverse:link, .govuk-button--inverse:visited, .govuk-button--inverse:active, .govuk-button--inverse:hover { - color: #1d70b8; -} -.govuk-button--inverse:hover { - background-color: #e8f1f8; -} -.govuk-button--inverse:hover[disabled] { - background-color: #ffffff; -} - -.govuk-button--start { - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1; - display: -ms-inline-flexbox; - display: inline-flex; - min-height: auto; - -ms-flex-pack: center; - justify-content: center; -} -@media (min-width: 40.0625em) { - .govuk-button--start { - font-size: 24px; - font-size: 1.5rem; - line-height: 1; - } -} -@media print { - .govuk-button--start { - font-size: 18pt; - line-height: 1; - } -} - -.govuk-button__start-icon { - margin-left: 5px; - vertical-align: middle; - -ms-flex-negative: 0; - flex-shrink: 0; - -ms-flex-item-align: center; - align-self: center; - forced-color-adjust: auto; -} -@media (min-width: 48.0625em) { - .govuk-button__start-icon { - margin-left: 10px; - } -} - -.govuk-error-message { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: block; - margin-top: 0; - margin-bottom: 15px; - clear: both; - color: #d4351c; -} -@media print { - .govuk-error-message { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-error-message { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-error-message { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-fieldset { - min-width: 0; - margin: 0; - padding: 0; - border: 0; -} -.govuk-fieldset:after { - content: ""; - display: block; - clear: both; -} - -@supports not (caret-color: auto) { - .govuk-fieldset, - x:-moz-any-link { - display: table-cell; - } -} -.govuk-fieldset__legend { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - box-sizing: border-box; - display: table; - max-width: 100%; - margin-bottom: 10px; - padding: 0; - white-space: normal; -} -@media print { - .govuk-fieldset__legend { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-fieldset__legend { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-fieldset__legend { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-fieldset__legend { - color: #000000; - } -} - -.govuk-fieldset__legend--xl { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; - margin-bottom: 15px; -} -@media print { - .govuk-fieldset__legend--xl { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-fieldset__legend--xl { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .govuk-fieldset__legend--xl { - font-size: 32pt; - line-height: 1.15; - } -} - -.govuk-fieldset__legend--l { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; - margin-bottom: 15px; -} -@media print { - .govuk-fieldset__legend--l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-fieldset__legend--l { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-fieldset__legend--l { - font-size: 24pt; - line-height: 1.05; - } -} - -.govuk-fieldset__legend--m { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin-bottom: 15px; -} -@media print { - .govuk-fieldset__legend--m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-fieldset__legend--m { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-fieldset__legend--m { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-fieldset__legend--s { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; -} -@media print { - .govuk-fieldset__legend--s { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-fieldset__legend--s { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-fieldset__legend--s { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-fieldset__heading { - margin: 0; - font-size: inherit; - font-weight: inherit; -} - -.govuk-hint { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin-bottom: 15px; - color: #505a5f; -} -@media print { - .govuk-hint { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-hint { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-hint { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-label:not(.govuk-label--m):not(.govuk-label--l):not(.govuk-label--xl) + .govuk-hint { - margin-bottom: 10px; -} - -.govuk-fieldset__legend:not(.govuk-fieldset__legend--m):not(.govuk-fieldset__legend--l):not(.govuk-fieldset__legend--xl) + .govuk-hint { - margin-bottom: 10px; -} - -.govuk-fieldset__legend + .govuk-hint { - margin-top: -5px; -} - -.govuk-label { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - display: block; - margin-bottom: 5px; -} -@media print { - .govuk-label { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-label { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-label { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-label { - color: #000000; - } -} - -.govuk-label--xl { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; - margin-bottom: 15px; -} -@media print { - .govuk-label--xl { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-label--xl { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .govuk-label--xl { - font-size: 32pt; - line-height: 1.15; - } -} - -.govuk-label--l { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; - margin-bottom: 15px; -} -@media print { - .govuk-label--l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-label--l { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-label--l { - font-size: 24pt; - line-height: 1.05; - } -} - -.govuk-label--m { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin-bottom: 10px; -} -@media print { - .govuk-label--m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-label--m { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-label--m { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-label--s { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; -} -@media print { - .govuk-label--s { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-label--s { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-label--s { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-label-wrapper { - margin: 0; -} - -.govuk-checkboxes__item { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: block; - position: relative; - min-height: 40px; - margin-bottom: 10px; - padding-left: 40px; - clear: left; -} -@media print { - .govuk-checkboxes__item { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-checkboxes__item { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-checkboxes__item { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-checkboxes__item:last-child, -.govuk-checkboxes__item:last-of-type { - margin-bottom: 0; -} - -.govuk-checkboxes__input { - cursor: pointer; - position: absolute; - z-index: 1; - top: -2px; - left: -2px; - width: 44px; - height: 44px; - margin: 0; - opacity: 0; -} - -.govuk-checkboxes__label { - display: inline-block; - margin-bottom: 0; - padding: 8px 15px 5px; - cursor: pointer; - -ms-touch-action: manipulation; - touch-action: manipulation; -} - -.govuk-checkboxes__label:before { - content: ""; - box-sizing: border-box; - position: absolute; - top: 0; - left: 0; - width: 40px; - height: 40px; - border: 2px solid currentcolor; - background: transparent; -} - -.govuk-checkboxes__label:after { - content: ""; - box-sizing: border-box; - position: absolute; - top: 11px; - left: 9px; - width: 23px; - height: 12px; - -webkit-transform: rotate(-45deg); - -ms-transform: rotate(-45deg); - transform: rotate(-45deg); - border: solid; - border-width: 0 0 5px 5px; - border-top-color: transparent; - opacity: 0; - background: transparent; -} - -.govuk-checkboxes__hint { - display: block; - padding-right: 15px; - padding-left: 15px; -} - -.govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { - border-width: 4px; - outline: 3px solid transparent; - outline-offset: 1px; - box-shadow: 0 0 0 3px #ffdd00; -} -@media screen and (forced-colors: active), (-ms-high-contrast: active) { - .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { - outline-color: Highlight; - } -} - -.govuk-checkboxes__input:checked + .govuk-checkboxes__label:after { - opacity: 1; -} - -.govuk-checkboxes__input:disabled, -.govuk-checkboxes__input:disabled + .govuk-checkboxes__label { - cursor: not-allowed; -} - -.govuk-checkboxes__input:disabled + .govuk-checkboxes__label, -.govuk-checkboxes__input:disabled ~ .govuk-hint { - opacity: 0.5; -} - -.govuk-checkboxes__divider { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - width: 40px; - margin-bottom: 10px; - text-align: center; -} -@media print { - .govuk-checkboxes__divider { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-checkboxes__divider { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-checkboxes__divider { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-checkboxes__divider { - color: #000000; - } -} - -.govuk-checkboxes__conditional { - margin-bottom: 15px; - margin-left: 18px; - padding-left: 33px; - border-left: 4px solid #b1b4b6; -} -@media (min-width: 40.0625em) { - .govuk-checkboxes__conditional { - margin-bottom: 20px; - } -} -.js-enabled .govuk-checkboxes__conditional--hidden { - display: none; -} -.govuk-checkboxes__conditional > :last-child { - margin-bottom: 0; -} - -.govuk-checkboxes--small .govuk-checkboxes__item { - min-height: 0; - margin-bottom: 0; - padding-left: 34px; - float: left; -} -.govuk-checkboxes--small .govuk-checkboxes__item:after { - content: ""; - display: block; - clear: both; -} -.govuk-checkboxes--small .govuk-checkboxes__input { - left: -10px; -} -.govuk-checkboxes--small .govuk-checkboxes__label { - margin-top: -2px; - padding: 13px 15px 13px 1px; - float: left; -} -@media (min-width: 40.0625em) { - .govuk-checkboxes--small .govuk-checkboxes__label { - padding: 11px 15px 10px 1px; - } -} -.govuk-checkboxes--small .govuk-checkboxes__label:before { - top: 8px; - width: 24px; - height: 24px; -} -.govuk-checkboxes--small .govuk-checkboxes__label:after { - top: 15px; - left: 6px; - width: 12px; - height: 6.5px; - border-width: 0 0 3px 3px; -} -.govuk-checkboxes--small .govuk-checkboxes__hint { - padding: 0; - clear: both; -} -.govuk-checkboxes--small .govuk-checkboxes__conditional { - margin-left: 10px; - padding-left: 20px; - clear: both; -} -.govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label:before { - box-shadow: 0 0 0 10px #b1b4b6; -} -.govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { - box-shadow: 0 0 0 3px #ffdd00, 0 0 0 10px #b1b4b6; -} -@media (hover: none), (pointer: coarse) { - .govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:not(:disabled) + .govuk-checkboxes__label:before { - box-shadow: initial; - } - .govuk-checkboxes--small .govuk-checkboxes__item:hover .govuk-checkboxes__input:focus + .govuk-checkboxes__label:before { - box-shadow: 0 0 0 3px #ffdd00; - } -} - -.govuk-textarea { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - display: block; - width: 100%; - min-height: 40px; - margin-bottom: 20px; - padding: 5px; - resize: vertical; - border: 2px solid #0b0c0c; - border-radius: 0; - -webkit-appearance: none; -} -@media print { - .govuk-textarea { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-textarea { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.25; - } -} -@media print { - .govuk-textarea { - font-size: 14pt; - line-height: 1.25; - } -} -@media (min-width: 40.0625em) { - .govuk-textarea { - margin-bottom: 30px; - } -} -.govuk-textarea:focus { - outline: 3px solid #ffdd00; - outline-offset: 0; - box-shadow: inset 0 0 0 2px; -} -.govuk-textarea:disabled { - opacity: 0.5; - color: inherit; - background-color: transparent; - cursor: not-allowed; -} - -.govuk-textarea--error { - border-color: #d4351c; -} -.govuk-textarea--error:focus { - border-color: #0b0c0c; -} - -.govuk-character-count { - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-character-count { - margin-bottom: 30px; - } -} -.govuk-character-count .govuk-form-group, -.govuk-character-count .govuk-textarea { - margin-bottom: 5px; -} - -.govuk-character-count__message { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-font-feature-settings: "tnum" 1; - font-feature-settings: "tnum" 1; - font-weight: 400; - margin-top: 0; - margin-bottom: 0; -} -@media print { - .govuk-character-count__message { - font-family: sans-serif; - } -} -@supports (font-variant-numeric: tabular-nums) { - .govuk-character-count__message { - -webkit-font-feature-settings: normal; - font-feature-settings: normal; - font-variant-numeric: tabular-nums; - } -} -.govuk-character-count__message:after { - content: "​"; -} - -.govuk-character-count__message--disabled { - visibility: hidden; -} - -.govuk-cookie-banner { - padding-top: 20px; - border-bottom: 10px solid transparent; - background-color: #f3f2f1; -} - -.govuk-cookie-banner[hidden] { - display: none; -} - -.govuk-cookie-banner__message { - margin-bottom: -10px; -} -.govuk-cookie-banner__message[hidden] { - display: none; -} -.govuk-cookie-banner__message:focus { - outline: none; -} - -.govuk-input { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - width: 100%; - height: 40px; - height: 2.5rem; - margin-top: 0; - padding: 5px; - border: 2px solid #0b0c0c; - border-radius: 0; - -webkit-appearance: none; - appearance: none; -} -@media print { - .govuk-input { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-input { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-input { - font-size: 14pt; - line-height: 1.15; - } -} -.govuk-input:focus { - outline: 3px solid #ffdd00; - outline-offset: 0; - box-shadow: inset 0 0 0 2px; -} -.govuk-input:disabled { - opacity: 0.5; - color: inherit; - background-color: transparent; - cursor: not-allowed; -} - -.govuk-input::-webkit-outer-spin-button, -.govuk-input::-webkit-inner-spin-button { - margin: 0; - -webkit-appearance: none; -} - -.govuk-input[type=number] { - -moz-appearance: textfield; -} - -.govuk-input--error { - border-color: #d4351c; -} -.govuk-input--error:focus { - border-color: #0b0c0c; -} - -.govuk-input--extra-letter-spacing { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-font-feature-settings: "tnum" 1; - font-feature-settings: "tnum" 1; - font-weight: 400; - letter-spacing: 0.05em; -} -@media print { - .govuk-input--extra-letter-spacing { - font-family: sans-serif; - } -} -@supports (font-variant-numeric: tabular-nums) { - .govuk-input--extra-letter-spacing { - -webkit-font-feature-settings: normal; - font-feature-settings: normal; - font-variant-numeric: tabular-nums; - } -} - -.govuk-input--width-30 { - max-width: 29.5em; -} - -.govuk-input--width-20 { - max-width: 20.5em; -} - -.govuk-input--width-10 { - max-width: 11.5em; -} - -.govuk-input--width-5 { - max-width: 5.5em; -} - -.govuk-input--width-4 { - max-width: 4.5em; -} - -.govuk-input--width-3 { - max-width: 3.75em; -} - -.govuk-input--width-2 { - max-width: 2.75em; -} - -.govuk-input__wrapper { - display: -ms-flexbox; - display: flex; -} -.govuk-input__wrapper .govuk-input { - -ms-flex: 0 1 auto; - flex: 0 1 auto; -} -.govuk-input__wrapper .govuk-input:focus { - z-index: 1; -} -@media (max-width: 19.99em) { - .govuk-input__wrapper { - display: block; - } - .govuk-input__wrapper .govuk-input { - max-width: 100%; - } -} - -.govuk-input__prefix, -.govuk-input__suffix { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - display: inline-block; - min-width: 40px; - min-width: 2.5rem; - height: 40px; - height: 2.5rem; - padding: 5px; - border: 2px solid #0b0c0c; - background-color: #f3f2f1; - text-align: center; - white-space: nowrap; - cursor: default; - -ms-flex: 0 0 auto; - flex: 0 0 auto; -} -@media print { - .govuk-input__prefix, - .govuk-input__suffix { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-input__prefix, - .govuk-input__suffix { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-input__prefix, - .govuk-input__suffix { - font-size: 14pt; - line-height: 1.15; - } -} -@media (max-width: 40.0525em) { - .govuk-input__prefix, - .govuk-input__suffix { - line-height: 1.6; - } -} -@media (max-width: 19.99em) { - .govuk-input__prefix, - .govuk-input__suffix { - display: block; - height: 100%; - white-space: normal; - } -} - -@media (max-width: 19.99em) { - .govuk-input__prefix { - border-bottom: 0; - } -} -@media (min-width: 20em) { - .govuk-input__prefix { - border-right: 0; - } -} - -@media (max-width: 19.99em) { - .govuk-input__suffix { - border-top: 0; - } -} -@media (min-width: 20em) { - .govuk-input__suffix { - border-left: 0; - } -} - -.govuk-date-input { - font-size: 0; -} -.govuk-date-input:after { - content: ""; - display: block; - clear: both; -} - -.govuk-date-input__item { - display: inline-block; - margin-right: 20px; - margin-bottom: 0; -} - -.govuk-date-input__label { - display: block; -} - -.govuk-date-input__input { - margin-bottom: 0; -} - -.govuk-details { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - margin-bottom: 20px; - display: block; -} -@media print { - .govuk-details { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-details { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-details { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-details { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-details { - margin-bottom: 30px; - } -} - -.govuk-details__summary { - display: inline-block; - position: relative; - margin-bottom: 5px; - padding-left: 25px; - color: #1d70b8; - cursor: pointer; -} -.govuk-details__summary:hover { - color: #003078; -} -.govuk-details__summary:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} - -.govuk-details__summary-text { - text-decoration: underline; -} - -.govuk-details__summary:focus .govuk-details__summary-text { - text-decoration: none; -} - -.govuk-details__summary::-webkit-details-marker { - display: none; -} - -.govuk-details__summary:before { - content: ""; - position: absolute; - top: -1px; - bottom: 0; - left: 0; - margin: auto; - display: block; - width: 0; - height: 0; - border-style: solid; - border-color: transparent; - -webkit-clip-path: polygon(0% 0%, 100% 50%, 0% 100%); - clip-path: polygon(0% 0%, 100% 50%, 0% 100%); - border-width: 7px 0 7px 12.124px; - border-left-color: inherit; -} -.govuk-details[open] > .govuk-details__summary:before { - display: block; - width: 0; - height: 0; - border-style: solid; - border-color: transparent; - -webkit-clip-path: polygon(0% 0%, 50% 100%, 100% 0%); - clip-path: polygon(0% 0%, 50% 100%, 100% 0%); - border-width: 12.124px 7px 0 7px; - border-top-color: inherit; -} - -.govuk-details__text { - padding-top: 15px; - padding-bottom: 15px; - padding-left: 20px; - border-left: 5px solid #b1b4b6; -} - -.govuk-details__text p { - margin-top: 0; - margin-bottom: 20px; -} - -.govuk-details__text > :last-child { - margin-bottom: 0; -} - -.govuk-error-summary { - color: #0b0c0c; - padding: 15px; - margin-bottom: 30px; - border: 5px solid #d4351c; -} -@media print { - .govuk-error-summary { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-error-summary { - padding: 20px; - } -} -@media (min-width: 40.0625em) { - .govuk-error-summary { - margin-bottom: 50px; - } -} -.govuk-error-summary:focus { - outline: 3px solid #ffdd00; -} - -.govuk-error-summary__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin-top: 0; - margin-bottom: 15px; -} -@media print { - .govuk-error-summary__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-error-summary__title { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-error-summary__title { - font-size: 18pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-error-summary__title { - margin-bottom: 20px; - } -} - -.govuk-error-summary__body { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; -} -@media print { - .govuk-error-summary__body { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-error-summary__body { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-error-summary__body { - font-size: 14pt; - line-height: 1.15; - } -} -.govuk-error-summary__body p { - margin-top: 0; - margin-bottom: 15px; -} -@media (min-width: 40.0625em) { - .govuk-error-summary__body p { - margin-bottom: 20px; - } -} - -.govuk-error-summary__list { - margin-top: 0; - margin-bottom: 0; -} - -.govuk-error-summary__list a { - font-weight: 700; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; -} -@media print { - .govuk-error-summary__list a { - font-family: sans-serif; - } -} -.govuk-error-summary__list a:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-error-summary__list a:link, .govuk-error-summary__list a:visited { - color: #d4351c; -} -.govuk-error-summary__list a:hover { - color: #942514; -} -.govuk-error-summary__list a:active { - color: #d4351c; -} -.govuk-error-summary__list a:focus { - color: #0b0c0c; -} - -.govuk-exit-this-page { - margin-bottom: 30px; - position: -webkit-sticky; - position: sticky; - z-index: 1000; - top: 0; - left: 0; - width: 100%; -} -@media (min-width: 40.0625em) { - .govuk-exit-this-page { - margin-bottom: 50px; - } -} -@media (min-width: 40.0625em) { - .govuk-exit-this-page { - display: inline-block; - right: 0; - left: auto; - width: auto; - float: right; - } -} - -.govuk-exit-this-page__button { - margin-bottom: 0; -} - -.govuk-exit-this-page__indicator { - padding: 10px; - display: none; - padding-bottom: 0; - color: inherit; - line-height: 0; - text-align: center; - pointer-events: none; -} - -.govuk-exit-this-page__indicator--visible { - display: block; -} - -.govuk-exit-this-page__indicator-light { - box-sizing: border-box; - display: inline-block; - width: 0.75em; - height: 0.75em; - margin: 0 0.125em; - border-width: 2px; - border-style: solid; - border-radius: 50%; - border-color: currentcolor; -} - -.govuk-exit-this-page__indicator-light--on { - border-width: 0.375em; -} - -@media only print { - .govuk-exit-this-page { - display: none; - } -} -.govuk-exit-this-page-overlay { - position: fixed; - z-index: 9999; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: #ffffff; -} - -.govuk-exit-this-page-hide-content * { - display: none !important; -} -.govuk-exit-this-page-hide-content .govuk-exit-this-page-overlay { - display: block !important; -} - -.govuk-file-upload { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - max-width: 100%; - margin-left: -5px; - padding: 5px; -} -@media print { - .govuk-file-upload { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-file-upload { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-file-upload { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-file-upload { - color: #000000; - } -} -.govuk-file-upload::-webkit-file-upload-button { - -webkit-appearance: button; - color: inherit; - font: inherit; -} -.govuk-file-upload:focus { - outline: 3px solid #ffdd00; - box-shadow: inset 0 0 0 4px #0b0c0c; -} -.govuk-file-upload:focus-within { - outline: 3px solid #ffdd00; - box-shadow: inset 0 0 0 4px #0b0c0c; -} -.govuk-file-upload:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.govuk-footer { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - padding-top: 25px; - padding-bottom: 15px; - border-top: 1px solid #b1b4b6; - color: #0b0c0c; - background: #f3f2f1; -} -@media print { - .govuk-footer { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-footer { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-footer { - font-size: 14pt; - line-height: 1.2; - } -} -@media (min-width: 40.0625em) { - .govuk-footer { - padding-top: 40px; - } -} -@media (min-width: 40.0625em) { - .govuk-footer { - padding-bottom: 25px; - } -} - -.govuk-footer__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; -} -@media print { - .govuk-footer__link { - font-family: sans-serif; - } -} -.govuk-footer__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-footer__link:link, .govuk-footer__link:visited { - color: #0b0c0c; -} -@media print { - .govuk-footer__link:link, .govuk-footer__link:visited { - color: #000000; - } -} -.govuk-footer__link:hover { - color: rgba(11, 12, 12, 0.99); -} -.govuk-footer__link:active, .govuk-footer__link:focus { - color: #0b0c0c; -} -@media print { - .govuk-footer__link:active, .govuk-footer__link:focus { - color: #000000; - } -} - -.govuk-footer__section-break { - margin: 0; - margin-bottom: 30px; - border: 0; - border-bottom: 1px solid #b1b4b6; -} -@media (min-width: 40.0625em) { - .govuk-footer__section-break { - margin-bottom: 50px; - } -} - -.govuk-footer__meta { - display: -ms-flexbox; - display: flex; - margin-right: -15px; - margin-left: -15px; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -ms-flex-align: end; - align-items: flex-end; - -ms-flex-pack: center; - justify-content: center; -} - -.govuk-footer__meta-item { - margin-right: 15px; - margin-bottom: 25px; - margin-left: 15px; -} - -.govuk-footer__meta-item--grow { - -ms-flex: 1; - flex: 1; -} -@media (max-width: 40.0525em) { - .govuk-footer__meta-item--grow { - -ms-flex-preferred-size: 320px; - flex-basis: 320px; - } -} - -.govuk-footer__licence-logo { - display: inline-block; - margin-right: 10px; - vertical-align: top; - forced-color-adjust: auto; -} -@media (max-width: 48.0525em) { - .govuk-footer__licence-logo { - margin-bottom: 15px; - } -} - -.govuk-footer__licence-description { - display: inline-block; -} - -.govuk-footer__copyright-logo { - display: inline-block; - min-width: 125px; - padding-top: 112px; - background-image: url("/assets/images/govuk-crest.png"); - background-repeat: no-repeat; - background-position: 50% 0%; - background-size: 125px 102px; - text-align: center; - white-space: nowrap; -} -@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) { - .govuk-footer__copyright-logo { - background-image: url("/assets/images/govuk-crest-2x.png"); - } -} - -.govuk-footer__inline-list { - margin-top: 0; - margin-bottom: 15px; - padding: 0; -} - -.govuk-footer__meta-custom { - margin-bottom: 20px; -} - -.govuk-footer__inline-list-item { - display: inline-block; - margin-right: 15px; - margin-bottom: 5px; -} - -.govuk-footer__heading { - margin-bottom: 30px; - padding-bottom: 20px; - border-bottom: 1px solid #b1b4b6; -} -@media (max-width: 40.0525em) { - .govuk-footer__heading { - padding-bottom: 10px; - } -} - -.govuk-footer__navigation { - margin-right: -15px; - margin-left: -15px; -} -.govuk-footer__navigation:after { - content: ""; - display: block; - clear: both; -} - -.govuk-footer__section { - display: inline-block; - margin-bottom: 30px; - vertical-align: top; -} - -.govuk-footer__list { - margin: 0; - padding: 0; - list-style: none; - -webkit-column-gap: 30px; - column-gap: 30px; -} - -@media (min-width: 48.0625em) { - .govuk-footer__list--columns-2 { - -webkit-column-count: 2; - column-count: 2; - } - .govuk-footer__list--columns-3 { - -webkit-column-count: 3; - column-count: 3; - } -} -.govuk-footer__list-item { - margin-bottom: 15px; -} -@media (min-width: 40.0625em) { - .govuk-footer__list-item { - margin-bottom: 20px; - } -} - -.govuk-footer__list-item:last-child { - margin-bottom: 0; -} - -.govuk-header { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - border-bottom: 10px solid #ffffff; - color: #ffffff; - background: #0b0c0c; -} -@media print { - .govuk-header { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-header { - font-size: 14pt; - line-height: 1.2; - } -} - -.govuk-header__container--full-width { - padding: 0 15px; - border-color: #1d70b8; -} -.govuk-header__container--full-width .govuk-header__menu-button { - right: 15px; -} - -.govuk-header__container { - position: relative; - margin-bottom: -10px; - padding-top: 10px; - border-bottom: 10px solid #1d70b8; -} -.govuk-header__container:after { - content: ""; - display: block; - clear: both; -} - -.govuk-header__logotype { - display: inline-block; - margin-right: 5px; -} -@media (forced-colors: active) { - .govuk-header__logotype { - forced-color-adjust: none; - color: linktext; - } -} -.govuk-header__logotype:last-child { - margin-right: 0; -} - -.govuk-header__logotype-crown { - position: relative; - top: -1px; - margin-right: 1px; - fill: currentcolor; - vertical-align: top; -} - -.govuk-header__logotype-crown-fallback-image { - width: 36px; - height: 32px; - border: 0; - vertical-align: bottom; -} - -.govuk-header__product-name { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 18px; - font-size: 1.125rem; - line-height: 1; - display: inline-table; -} -@media print { - .govuk-header__product-name { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header__product-name { - font-size: 24px; - font-size: 1.5rem; - line-height: 1; - } -} -@media print { - .govuk-header__product-name { - font-size: 18pt; - line-height: 1; - } -} - -.govuk-header__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: none; -} -@media print { - .govuk-header__link { - font-family: sans-serif; - } -} -.govuk-header__link:link, .govuk-header__link:visited { - color: #ffffff; -} -.govuk-header__link:hover, .govuk-header__link:active { - color: rgba(255, 255, 255, 0.99); -} -.govuk-header__link:focus { - color: #0b0c0c; -} -.govuk-header__link:hover { - text-decoration: underline; - text-decoration-thickness: 3px; - text-underline-offset: 0.1578em; -} -.govuk-header__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} - -.govuk-header__link--homepage { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - display: inline-block; - margin-right: 10px; - font-size: 30px; - line-height: 1; -} -@media print { - .govuk-header__link--homepage { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header__link--homepage { - display: inline; - } - .govuk-header__link--homepage:focus { - box-shadow: 0 0 #ffdd00; - } -} -.govuk-header__link--homepage:link, .govuk-header__link--homepage:visited { - text-decoration: none; -} -.govuk-header__link--homepage:hover, .govuk-header__link--homepage:active { - margin-bottom: -3px; - border-bottom: 3px solid; -} -.govuk-header__link--homepage:focus { - margin-bottom: 0; - border-bottom: 0; -} - -.govuk-header__service-name, -.govuk-header__link--service-name { - display: inline-block; - margin-bottom: 10px; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; -} -@media print { - .govuk-header__service-name, - .govuk-header__link--service-name { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header__service-name, - .govuk-header__link--service-name { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-header__service-name, - .govuk-header__link--service-name { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-header__logo, -.govuk-header__content { - box-sizing: border-box; -} - -.govuk-header__logo { - margin-bottom: 10px; - padding-right: 50px; -} -@media (min-width: 48.0625em) { - .govuk-header__logo { - width: 33.33%; - padding-right: 15px; - float: left; - vertical-align: top; - } -} - -@media (min-width: 48.0625em) { - .govuk-header__content { - width: 66.66%; - padding-left: 15px; - float: left; - } -} - -.govuk-header__menu-button { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - display: none; - position: absolute; - top: 20px; - right: 0; - margin: 0; - padding: 0; - border: 0; - color: #ffffff; - background: none; - cursor: pointer; -} -@media print { - .govuk-header__menu-button { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header__menu-button { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-header__menu-button { - font-size: 14pt; - line-height: 1.2; - } -} -.govuk-header__menu-button:hover { - -webkit-text-decoration: solid underline 3px; - text-decoration: solid underline 3px; - text-underline-offset: 0.1578em; -} -.govuk-header__menu-button:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-header__menu-button:after { - display: inline-block; - width: 0; - height: 0; - border-style: solid; - border-color: transparent; - -webkit-clip-path: polygon(0% 0%, 50% 100%, 100% 0%); - clip-path: polygon(0% 0%, 50% 100%, 100% 0%); - border-width: 8.66px 5px 0 5px; - border-top-color: inherit; - content: ""; - margin-left: 5px; -} -.govuk-header__menu-button[aria-expanded=true]:after { - display: inline-block; - width: 0; - height: 0; - border-style: solid; - border-color: transparent; - -webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%); - clip-path: polygon(50% 0%, 0% 100%, 100% 100%); - border-width: 0 5px 8.66px 5px; - border-bottom-color: inherit; -} -@media (min-width: 40.0625em) { - .govuk-header__menu-button { - top: 15px; - } -} -.js-enabled .govuk-header__menu-button { - display: block; -} -.govuk-header__menu-button[hidden], .js-enabled .govuk-header__menu-button[hidden] { - display: none; -} - -@media (min-width: 48.0625em) { - .govuk-header__navigation { - margin-bottom: 10px; - } -} - -.govuk-header__navigation-list { - margin: 0; - padding: 0; - list-style: none; -} -.govuk-header__navigation-list[hidden] { - display: none; -} - -@media (min-width: 48.0625em) { - .govuk-header__navigation--end { - margin: 0; - padding: 5px 0; - text-align: right; - } -} - -.govuk-header__navigation--no-service-name { - padding-top: 40px; -} - -.govuk-header__navigation-item { - padding: 10px 0; - border-bottom: 1px solid #2e3133; -} -@media (min-width: 48.0625em) { - .govuk-header__navigation-item { - display: inline-block; - margin-right: 15px; - padding: 5px 0; - border: 0; - } -} -.govuk-header__navigation-item a { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - white-space: nowrap; -} -@media print { - .govuk-header__navigation-item a { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-header__navigation-item a { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-header__navigation-item a { - font-size: 14pt; - line-height: 1.2; - } -} - -.govuk-header__navigation-item--active a:link, .govuk-header__navigation-item--active a:hover, .govuk-header__navigation-item--active a:visited { - color: #1d8feb; -} -@media print { - .govuk-header__navigation-item--active a { - color: #1d70b8; - } -} -.govuk-header__navigation-item--active a:focus { - color: #0b0c0c; -} - -.govuk-header__navigation-item:last-child { - margin-right: 0; - border-bottom: 0; -} - -@media print { - .govuk-header { - border-bottom-width: 0; - color: #0b0c0c; - background: transparent; - } - .govuk-header__logotype-crown-fallback-image { - display: none; - } - .govuk-header__link:link, .govuk-header__link:visited { - color: #0b0c0c; - } - .govuk-header__link:after { - display: none; - } -} -.govuk-inset-text { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - padding: 15px; - margin-top: 20px; - margin-bottom: 20px; - clear: both; - border-left: 10px solid #b1b4b6; -} -@media print { - .govuk-inset-text { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-inset-text { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-inset-text { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-inset-text { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-inset-text { - margin-top: 30px; - } -} -@media (min-width: 40.0625em) { - .govuk-inset-text { - margin-bottom: 30px; - } -} -.govuk-inset-text > :first-child { - margin-top: 0; -} -.govuk-inset-text > :only-child, -.govuk-inset-text > :last-child { - margin-bottom: 0; -} - -.govuk-notification-banner { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin-bottom: 30px; - border: 5px solid #1d70b8; - background-color: #1d70b8; -} -@media print { - .govuk-notification-banner { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-notification-banner { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-notification-banner { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-notification-banner { - margin-bottom: 50px; - } -} -.govuk-notification-banner:focus { - outline: 3px solid #ffdd00; -} - -.govuk-notification-banner__header { - padding: 2px 15px 5px; - border-bottom: 1px solid transparent; -} -@media (min-width: 40.0625em) { - .govuk-notification-banner__header { - padding: 2px 20px 5px; - } -} - -.govuk-notification-banner__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin: 0; - padding: 0; - color: #ffffff; -} -@media print { - .govuk-notification-banner__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-notification-banner__title { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-notification-banner__title { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-notification-banner__content { - color: #0b0c0c; - padding: 15px; - background-color: #ffffff; -} -@media print { - .govuk-notification-banner__content { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-notification-banner__content { - padding: 20px; - } -} -.govuk-notification-banner__content > * { - box-sizing: border-box; - max-width: 605px; -} -.govuk-notification-banner__content > :last-child { - margin-bottom: 0; -} - -.govuk-notification-banner__heading { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin: 0 0 15px 0; - padding: 0; -} -@media print { - .govuk-notification-banner__heading { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-notification-banner__heading { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-notification-banner__heading { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-notification-banner__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; -} -@media print { - .govuk-notification-banner__link { - font-family: sans-serif; - } -} -.govuk-notification-banner__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-notification-banner__link:link { - color: #1d70b8; -} -.govuk-notification-banner__link:visited { - color: #1d70b8; -} -.govuk-notification-banner__link:hover { - color: #003078; -} -.govuk-notification-banner__link:active { - color: #0b0c0c; -} -.govuk-notification-banner__link:focus { - color: #0b0c0c; -} - -.govuk-notification-banner--success { - border-color: #00703c; - background-color: #00703c; -} -.govuk-notification-banner--success .govuk-notification-banner__link:link, .govuk-notification-banner--success .govuk-notification-banner__link:visited { - color: #00703c; -} -.govuk-notification-banner--success .govuk-notification-banner__link:hover { - color: #004e2a; -} -.govuk-notification-banner--success .govuk-notification-banner__link:active { - color: #00703c; -} -.govuk-notification-banner--success .govuk-notification-banner__link:focus { - color: #0b0c0c; -} - -.govuk-pagination { - margin-bottom: 20px; - display: -ms-flexbox; - display: flex; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-align: center; - align-items: center; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} -@media (min-width: 40.0625em) { - .govuk-pagination { - margin-bottom: 30px; - } -} -@media (min-width: 40.0625em) { - .govuk-pagination { - -ms-flex-direction: row; - flex-direction: row; - -ms-flex-align: start; - align-items: flex-start; - } -} - -.govuk-pagination__list { - margin: 0; - padding: 0; - list-style: none; -} - -.govuk-pagination__item, -.govuk-pagination__next, -.govuk-pagination__prev { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - position: relative; - min-width: 45px; - min-height: 45px; - padding: 10px 15px; - float: left; -} -@media print { - .govuk-pagination__item, - .govuk-pagination__next, - .govuk-pagination__prev { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-pagination__item, - .govuk-pagination__next, - .govuk-pagination__prev { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-pagination__item, - .govuk-pagination__next, - .govuk-pagination__prev { - font-size: 14pt; - line-height: 1.15; - } -} -.govuk-pagination__item:hover, -.govuk-pagination__next:hover, -.govuk-pagination__prev:hover { - background-color: #f3f2f1; -} - -.govuk-pagination__item { - display: none; - text-align: center; -} -@media (min-width: 40.0625em) { - .govuk-pagination__item { - display: block; - } -} - -.govuk-pagination__prev, -.govuk-pagination__next { - font-weight: 700; -} -.govuk-pagination__prev .govuk-pagination__link, -.govuk-pagination__next .govuk-pagination__link { - display: -ms-flexbox; - display: flex; - -ms-flex-align: center; - align-items: center; -} - -.govuk-pagination__prev { - padding-left: 0; -} - -.govuk-pagination__next { - padding-right: 0; -} - -.govuk-pagination__item--current, -.govuk-pagination__item--ellipses, -.govuk-pagination__item:first-child, -.govuk-pagination__item:last-child { - display: block; -} - -.govuk-pagination__item--current { - font-weight: 700; - outline: 1px solid transparent; - background-color: #1d70b8; -} -.govuk-pagination__item--current:hover { - background-color: #1d70b8; -} -.govuk-pagination__item--current .govuk-pagination__link:link, .govuk-pagination__item--current .govuk-pagination__link:visited { - color: #ffffff; -} -.govuk-pagination__item--current .govuk-pagination__link:hover, .govuk-pagination__item--current .govuk-pagination__link:active { - color: rgba(255, 255, 255, 0.99); -} -.govuk-pagination__item--current .govuk-pagination__link:focus { - color: #0b0c0c; -} - -.govuk-pagination__item--ellipses { - font-weight: 700; - color: #505a5f; -} -.govuk-pagination__item--ellipses:hover { - background-color: transparent; -} - -.govuk-pagination__link { - display: block; - min-width: 15px; -} -@media screen { - .govuk-pagination__link:after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - } -} -.govuk-pagination__link:hover .govuk-pagination__link-title--decorated, .govuk-pagination__link:active .govuk-pagination__link-title--decorated { - text-decoration: underline; -} -.govuk-pagination__link:focus .govuk-pagination__icon { - color: #0b0c0c; -} -.govuk-pagination__link:focus .govuk-pagination__link-label { - text-decoration: none; -} -.govuk-pagination__link:focus .govuk-pagination__link-title--decorated { - text-decoration: none; -} - -.govuk-pagination__link-label { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - text-decoration: underline; - display: inline-block; - padding-left: 30px; -} -@media print { - .govuk-pagination__link-label { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-pagination__link-label { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-pagination__link-label { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-pagination__icon { - width: 0.9375rem; - height: 0.8125rem; - color: #505a5f; - fill: currentcolor; - forced-color-adjust: auto; -} - -.govuk-pagination__icon--prev { - margin-right: 15px; -} - -.govuk-pagination__icon--next { - margin-left: 15px; -} - -.govuk-pagination--block { - display: block; -} -.govuk-pagination--block .govuk-pagination__item { - padding: 15px; - float: none; -} -.govuk-pagination--block .govuk-pagination__next, -.govuk-pagination--block .govuk-pagination__prev { - padding-left: 0; - float: none; -} -.govuk-pagination--block .govuk-pagination__next { - padding-right: 15px; -} -.govuk-pagination--block .govuk-pagination__next .govuk-pagination__icon { - margin-left: 0; -} -.govuk-pagination--block .govuk-pagination__prev + .govuk-pagination__next { - border-top: 1px solid #b1b4b6; -} -.govuk-pagination--block .govuk-pagination__link, -.govuk-pagination--block .govuk-pagination__link-title { - display: inline; -} -.govuk-pagination--block .govuk-pagination__link-title:after { - content: ""; - display: block; -} -.govuk-pagination--block .govuk-pagination__link { - text-align: left; -} -.govuk-pagination--block .govuk-pagination__link:focus .govuk-pagination__link-label { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-pagination--block .govuk-pagination__link:not(:focus) { - text-decoration: none; -} -.govuk-pagination--block .govuk-pagination__icon { - margin-right: 10px; -} - -.govuk-panel { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - margin-bottom: 15px; - padding: 35px; - border: 5px solid transparent; - text-align: center; -} -@media print { - .govuk-panel { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-panel { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-panel { - font-size: 14pt; - line-height: 1.15; - } -} -@media (max-width: 40.0525em) { - .govuk-panel { - padding: 10px; - overflow-wrap: break-word; - word-wrap: break-word; - } -} - -.govuk-panel--confirmation { - color: #ffffff; - background: #00703c; -} -@media print { - .govuk-panel--confirmation { - border-color: currentcolor; - color: #000000; - background: none; - } -} - -.govuk-panel__title { - margin-top: 0; - margin-bottom: 30px; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; -} -@media print { - .govuk-panel__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-panel__title { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .govuk-panel__title { - font-size: 32pt; - line-height: 1.15; - } -} - -.govuk-panel__title:last-child { - margin-bottom: 0; -} - -.govuk-panel__body { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; -} -@media print { - .govuk-panel__body { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-panel__body { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-panel__body { - font-size: 24pt; - line-height: 1.05; - } -} - -.govuk-tag { - display: inline-block; - outline: 2px solid transparent; - outline-offset: -2px; - color: #ffffff; - background-color: #1d70b8; - letter-spacing: 1px; - text-decoration: none; - text-transform: uppercase; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 14px; - font-size: 0.875rem; - line-height: 1; - padding-top: 5px; - padding-right: 8px; - padding-bottom: 4px; - padding-left: 8px; -} -@media print { - .govuk-tag { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-tag { - font-size: 16px; - font-size: 1rem; - line-height: 1; - } -} -@media print { - .govuk-tag { - font-size: 14pt; - line-height: 1; - } -} - -.govuk-tag--grey { - color: #383f43; - background: #eeefef; -} - -.govuk-tag--purple { - color: #3d2375; - background: #dbd5e9; -} - -.govuk-tag--turquoise { - color: #10403c; - background: #bfe3e0; -} - -.govuk-tag--blue { - color: #144e81; - background: #d2e2f1; -} - -.govuk-tag--yellow { - color: #594d00; - background: #fff7bf; -} - -.govuk-tag--orange { - color: #6e3619; - background: #fcd6c3; -} - -.govuk-tag--red { - color: #942514; - background: #f6d7d2; -} - -.govuk-tag--pink { - color: #80224d; - background: #f7d7e6; -} - -.govuk-tag--green { - color: #005a30; - background: #cce2d8; -} - -.govuk-phase-banner { - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid #b1b4b6; -} - -.govuk-phase-banner__content { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - color: #0b0c0c; - display: table; - margin: 0; -} -@media print { - .govuk-phase-banner__content { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-phase-banner__content { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-phase-banner__content { - font-size: 14pt; - line-height: 1.2; - } -} -@media print { - .govuk-phase-banner__content { - color: #000000; - } -} - -.govuk-phase-banner__content__tag { - margin-right: 10px; -} - -.govuk-phase-banner__text { - display: table-cell; - vertical-align: middle; -} - -.govuk-tabs { - margin-top: 5px; - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-tabs { - margin-bottom: 30px; - } -} - -.govuk-tabs__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - margin-bottom: 10px; -} -@media print { - .govuk-tabs__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-tabs__title { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-tabs__title { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-tabs__title { - color: #000000; - } -} - -.govuk-tabs__list { - margin: 0; - padding: 0; - list-style: none; - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .govuk-tabs__list { - margin-bottom: 30px; - } -} - -.govuk-tabs__list-item { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin-left: 25px; -} -@media print { - .govuk-tabs__list-item { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-tabs__list-item { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-tabs__list-item { - font-size: 14pt; - line-height: 1.15; - } -} -.govuk-tabs__list-item:before { - color: #0b0c0c; - content: "—"; - margin-left: -25px; - padding-right: 5px; -} -@media print { - .govuk-tabs__list-item:before { - color: #000000; - } -} - -.govuk-tabs__tab { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; - display: inline-block; - margin-bottom: 10px; -} -@media print { - .govuk-tabs__tab { - font-family: sans-serif; - } -} -.govuk-tabs__tab:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.govuk-tabs__tab:link { - color: #1d70b8; -} -.govuk-tabs__tab:visited { - color: #4c2c92; -} -.govuk-tabs__tab:hover { - color: #003078; -} -.govuk-tabs__tab:active { - color: #0b0c0c; -} -.govuk-tabs__tab:focus { - color: #0b0c0c; -} - -.govuk-tabs__panel { - margin-bottom: 30px; -} -@media (min-width: 40.0625em) { - .govuk-tabs__panel { - margin-bottom: 50px; - } -} - -@media (min-width: 40.0625em) { - .js-enabled .govuk-tabs__list { - margin-bottom: 0; - border-bottom: 1px solid #b1b4b6; - } - .js-enabled .govuk-tabs__list:after { - content: ""; - display: block; - clear: both; - } - .js-enabled .govuk-tabs__title { - display: none; - } - .js-enabled .govuk-tabs__list-item { - position: relative; - margin-right: 5px; - margin-bottom: 0; - margin-left: 0; - padding: 10px 20px; - float: left; - background-color: #f3f2f1; - text-align: center; - } - .js-enabled .govuk-tabs__list-item:before { - content: none; - } - .js-enabled .govuk-tabs__list-item--selected { - position: relative; - margin-top: -5px; - margin-bottom: -1px; - padding-top: 14px; - padding-right: 19px; - padding-bottom: 16px; - padding-left: 19px; - border: 1px solid #b1b4b6; - border-bottom: 0; - background-color: #ffffff; - } - .js-enabled .govuk-tabs__list-item--selected .govuk-tabs__tab { - text-decoration: none; - } - .js-enabled .govuk-tabs__tab { - margin-bottom: 0; - } - .js-enabled .govuk-tabs__tab:link, .js-enabled .govuk-tabs__tab:visited { - color: #0b0c0c; - } -} -@media print and (min-width: 40.0625em) { - .js-enabled .govuk-tabs__tab:link, .js-enabled .govuk-tabs__tab:visited { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-tabs__tab:hover { - color: rgba(11, 12, 12, 0.99); - } - .js-enabled .govuk-tabs__tab:active, .js-enabled .govuk-tabs__tab:focus { - color: #0b0c0c; - } -} -@media print and (min-width: 40.0625em) { - .js-enabled .govuk-tabs__tab:active, .js-enabled .govuk-tabs__tab:focus { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .js-enabled .govuk-tabs__tab:after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - } - .js-enabled .govuk-tabs__panel { - margin-bottom: 0; - padding: 30px 20px; - border: 1px solid #b1b4b6; - border-top: 0; - } - .js-enabled .govuk-tabs__panel > :last-child { - margin-bottom: 0; - } - .js-enabled .govuk-tabs__panel--hidden { - display: none; - } -} - -.govuk-radios__item { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: block; - position: relative; - min-height: 40px; - margin-bottom: 10px; - padding-left: 40px; - clear: left; -} -@media print { - .govuk-radios__item { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-radios__item { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-radios__item { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-radios__item:last-child, -.govuk-radios__item:last-of-type { - margin-bottom: 0; -} - -.govuk-radios__input { - cursor: pointer; - position: absolute; - z-index: 1; - top: -2px; - left: -2px; - width: 44px; - height: 44px; - margin: 0; - opacity: 0; -} - -.govuk-radios__label { - display: inline-block; - margin-bottom: 0; - padding: 8px 15px 5px; - cursor: pointer; - -ms-touch-action: manipulation; - touch-action: manipulation; -} - -.govuk-radios__label:before { - content: ""; - box-sizing: border-box; - position: absolute; - top: 0; - left: 0; - width: 40px; - height: 40px; - border: 2px solid currentcolor; - border-radius: 50%; - background: transparent; -} - -.govuk-radios__label:after { - content: ""; - position: absolute; - top: 10px; - left: 10px; - width: 0; - height: 0; - border: 10px solid currentcolor; - border-radius: 50%; - opacity: 0; - background: currentcolor; -} - -.govuk-radios__hint { - display: block; - padding-right: 15px; - padding-left: 15px; -} - -.govuk-radios__input:focus + .govuk-radios__label:before { - border-width: 4px; - outline: 3px solid transparent; - outline-offset: 1px; - box-shadow: 0 0 0 4px #ffdd00; -} -@media screen and (forced-colors: active), (-ms-high-contrast: active) { - .govuk-radios__input:focus + .govuk-radios__label:before { - outline-color: Highlight; - } -} - -.govuk-radios__input:checked + .govuk-radios__label:after { - opacity: 1; -} - -.govuk-radios__input:disabled, -.govuk-radios__input:disabled + .govuk-radios__label { - cursor: not-allowed; -} - -.govuk-radios__input:disabled + .govuk-radios__label, -.govuk-radios__input:disabled ~ .govuk-hint { - opacity: 0.5; -} - -@media (min-width: 40.0625em) { - .govuk-radios--inline:after { - content: ""; - display: block; - clear: both; - } - .govuk-radios--inline .govuk-radios__item { - margin-right: 20px; - float: left; - clear: none; - } -} - -.govuk-radios__divider { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - width: 40px; - margin-bottom: 10px; - text-align: center; -} -@media print { - .govuk-radios__divider { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-radios__divider { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-radios__divider { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-radios__divider { - color: #000000; - } -} - -.govuk-radios__conditional { - margin-bottom: 15px; - margin-left: 18px; - padding-left: 33px; - border-left: 4px solid #b1b4b6; -} -@media (min-width: 40.0625em) { - .govuk-radios__conditional { - margin-bottom: 20px; - } -} -.js-enabled .govuk-radios__conditional--hidden { - display: none; -} -.govuk-radios__conditional > :last-child { - margin-bottom: 0; -} - -.govuk-radios--small .govuk-radios__item { - min-height: 0; - margin-bottom: 0; - padding-left: 34px; - float: left; -} -.govuk-radios--small .govuk-radios__item:after { - content: ""; - display: block; - clear: both; -} -.govuk-radios--small .govuk-radios__input { - left: -10px; -} -.govuk-radios--small .govuk-radios__label { - margin-top: -2px; - padding: 13px 15px 13px 1px; - float: left; -} -@media (min-width: 40.0625em) { - .govuk-radios--small .govuk-radios__label { - padding: 11px 15px 10px 1px; - } -} -.govuk-radios--small .govuk-radios__label:before { - top: 8px; - width: 24px; - height: 24px; -} -.govuk-radios--small .govuk-radios__label:after { - top: 15px; - left: 7px; - border-width: 5px; -} -.govuk-radios--small .govuk-radios__hint { - padding: 0; - clear: both; - pointer-events: none; -} -.govuk-radios--small .govuk-radios__conditional { - margin-left: 10px; - padding-left: 20px; - clear: both; -} -.govuk-radios--small .govuk-radios__divider { - width: 24px; - margin-bottom: 5px; -} -.govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:not(:disabled) + .govuk-radios__label:before { - box-shadow: 0 0 0 10px #b1b4b6; -} -.govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:focus + .govuk-radios__label:before { - box-shadow: 0 0 0 4px #ffdd00, 0 0 0 10px #b1b4b6; -} -@media (hover: none), (pointer: coarse) { - .govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:not(:disabled) + .govuk-radios__label:before { - box-shadow: initial; - } - .govuk-radios--small .govuk-radios__item:hover .govuk-radios__input:focus + .govuk-radios__label:before { - box-shadow: 0 0 0 4px #ffdd00; - } -} - -.govuk-select { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - box-sizing: border-box; - min-width: 11.5em; - max-width: 100%; - height: 40px; - height: 2.5rem; - padding: 5px; - border: 2px solid #0b0c0c; - color: #0b0c0c; - background-color: #ffffff; -} -@media print { - .govuk-select { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-select { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.25; - } -} -@media print { - .govuk-select { - font-size: 14pt; - line-height: 1.25; - } -} -.govuk-select:focus { - outline: 3px solid #ffdd00; - outline-offset: 0; - box-shadow: inset 0 0 0 2px; -} -.govuk-select:disabled { - opacity: 0.5; - color: inherit; - cursor: not-allowed; -} - -.govuk-select option:active, -.govuk-select option:checked, -.govuk-select:focus::-ms-value { - color: #ffffff; - background-color: #1d70b8; -} - -.govuk-select--error { - border-color: #d4351c; -} -.govuk-select--error:focus { - border-color: #0b0c0c; -} - -.govuk-skip-link { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - overflow: hidden !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(50%) !important; - clip-path: inset(50%) !important; - white-space: nowrap !important; - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - display: block; - padding: 10px 15px; -} -.govuk-skip-link:active, .govuk-skip-link:focus { - position: static !important; - width: auto !important; - height: auto !important; - margin: inherit !important; - overflow: visible !important; - clip: auto !important; - -webkit-clip-path: none !important; - clip-path: none !important; - white-space: inherit !important; -} -@media print { - .govuk-skip-link { - font-family: sans-serif; - } -} -.govuk-skip-link:link, .govuk-skip-link:visited { - color: #0b0c0c; -} -@media print { - .govuk-skip-link:link, .govuk-skip-link:visited { - color: #000000; - } -} -.govuk-skip-link:hover { - color: rgba(11, 12, 12, 0.99); -} -.govuk-skip-link:active, .govuk-skip-link:focus { - color: #0b0c0c; -} -@media print { - .govuk-skip-link:active, .govuk-skip-link:focus { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-skip-link { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .govuk-skip-link { - font-size: 14pt; - line-height: 1.2; - } -} -@supports (padding: max(calc(0px))) { - .govuk-skip-link { - padding-right: max(15px, calc(15px + env(safe-area-inset-right))); - padding-left: max(15px, calc(15px + env(safe-area-inset-left))); - } -} -.govuk-skip-link:focus { - outline: 3px solid #ffdd00; - outline-offset: 0; - background-color: #ffdd00; - box-shadow: none; -} - -.govuk-skip-link-focused-element:focus { - outline: none; -} - -.govuk-summary-list { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - margin: 0; - margin-bottom: 20px; -} -@media print { - .govuk-summary-list { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-list { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-summary-list { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-summary-list { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-list { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: collapse; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-list { - margin-bottom: 30px; - } -} - -.govuk-summary-list__row { - border-bottom: 1px solid #b1b4b6; -} -@media (max-width: 40.0525em) { - .govuk-summary-list__row { - margin-bottom: 15px; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-list__row { - display: table-row; - } -} - -.govuk-summary-list__row:not(.govuk-summary-list__row--no-actions) > :last-child { - padding-right: 0; -} - -@media (min-width: 40.0625em) { - .govuk-summary-list__row--no-actions:after { - content: ""; - display: table-cell; - width: 20%; - } -} - -.govuk-summary-list__key, -.govuk-summary-list__value, -.govuk-summary-list__actions { - margin: 0; -} -@media (min-width: 40.0625em) { - .govuk-summary-list__key, - .govuk-summary-list__value, - .govuk-summary-list__actions { - display: table-cell; - padding-top: 10px; - padding-right: 20px; - padding-bottom: 10px; - } -} - -.govuk-summary-list__actions { - margin-bottom: 15px; -} -@media (min-width: 40.0625em) { - .govuk-summary-list__actions { - width: 20%; - padding-right: 0; - text-align: right; - } -} - -.govuk-summary-list__key, -.govuk-summary-list__value { - word-wrap: break-word; - overflow-wrap: break-word; -} - -.govuk-summary-list__key { - margin-bottom: 5px; - font-weight: 700; -} -@media (min-width: 40.0625em) { - .govuk-summary-list__key { - width: 30%; - } -} - -@media (max-width: 40.0525em) { - .govuk-summary-list__value { - margin-bottom: 15px; - } -} - -.govuk-summary-list__value > p { - margin-bottom: 10px; -} - -.govuk-summary-list__value > :last-child { - margin-bottom: 0; -} - -.govuk-summary-list__actions-list { - width: 100%; - margin: 0; - padding: 0; -} - -.govuk-summary-list__actions-list-item { - display: inline-block; -} - -@media (max-width: 40.0525em) { - .govuk-summary-list__actions-list-item { - margin-right: 10px; - padding-right: 10px; - } - .govuk-summary-list__actions-list-item:not(:last-child) { - border-right: 1px solid #b1b4b6; - } - .govuk-summary-list__actions-list-item:last-child { - margin-right: 0; - padding-right: 0; - border: 0; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-list__actions-list-item { - margin-left: 10px; - padding-left: 10px; - } - .govuk-summary-list__actions-list-item:not(:first-child) { - border-left: 1px solid #b1b4b6; - } - .govuk-summary-list__actions-list-item:first-child { - margin-left: 0; - padding-left: 0; - border: 0; - } -} -.govuk-summary-list--no-border .govuk-summary-list__row { - border: 0; -} -@media (min-width: 40.0625em) { - .govuk-summary-list--no-border .govuk-summary-list__key, - .govuk-summary-list--no-border .govuk-summary-list__value, - .govuk-summary-list--no-border .govuk-summary-list__actions { - padding-bottom: 11px; - } -} - -.govuk-summary-list__row--no-border { - border: 0; -} -@media (min-width: 40.0625em) { - .govuk-summary-list__row--no-border .govuk-summary-list__key, - .govuk-summary-list__row--no-border .govuk-summary-list__value, - .govuk-summary-list__row--no-border .govuk-summary-list__actions { - padding-bottom: 11px; - } -} - -.govuk-summary-card { - margin-bottom: 20px; - border: 1px solid #b1b4b6; -} -@media (min-width: 40.0625em) { - .govuk-summary-card { - margin-bottom: 30px; - } -} - -.govuk-summary-card__title-wrapper { - padding: 15px; - border-bottom: 1px solid transparent; - background-color: #f3f2f1; -} -@media (min-width: 40.0625em) { - .govuk-summary-card__title-wrapper { - display: -ms-flexbox; - display: flex; - -ms-flex-pack: justify; - justify-content: space-between; - -ms-flex-wrap: nowrap; - flex-wrap: nowrap; - padding: 15px 20px; - } -} - -.govuk-summary-card__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin: 5px 20px 10px 0; -} -@media print { - .govuk-summary-card__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-card__title { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-summary-card__title { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-card__title { - margin-bottom: 5px; - } -} - -.govuk-summary-card__actions { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - row-gap: 10px; - margin: 5px 0; - padding: 0; - list-style: none; -} -@media print { - .govuk-summary-card__actions { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-card__actions { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-summary-card__actions { - font-size: 14pt; - line-height: 1.15; - } -} -@media (min-width: 40.0625em) { - .govuk-summary-card__actions { - -ms-flex-pack: right; - justify-content: right; - text-align: right; - } -} - -.govuk-summary-card__action { - display: inline; - margin: 0 10px 0 0; - padding-right: 10px; - border-right: 1px solid #b1b4b6; -} -@media (min-width: 40.0625em) { - .govuk-summary-card__action { - margin-right: 0; - } -} -@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { - .govuk-summary-card__action { - margin-bottom: 5px; - } -} - -.govuk-summary-card__action:last-child { - margin: 0; - padding-right: 0; - border-right: none; -} -@media (min-width: 40.0625em) { - .govuk-summary-card__action:last-child { - padding-left: 10px; - } -} -@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { - .govuk-summary-card__action:last-child { - margin-bottom: 0; - } -} - -.govuk-summary-card__content { - padding: 15px 15px 0; -} -@media (min-width: 40.0625em) { - .govuk-summary-card__content { - padding: 15px 20px; - } -} -.govuk-summary-card__content .govuk-summary-list { - margin-bottom: 0; -} -.govuk-summary-card__content .govuk-summary-list__row:last-of-type { - margin-bottom: 0; - border-bottom: none; -} - -.govuk-table { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - width: 100%; - margin-bottom: 20px; - border-spacing: 0; - border-collapse: collapse; -} -@media print { - .govuk-table { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-table { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-table { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-table { - color: #000000; - } -} -@media (min-width: 40.0625em) { - .govuk-table { - margin-bottom: 30px; - } -} - -.govuk-table__header { - font-weight: 700; -} - -.govuk-table__header, -.govuk-table__cell { - padding: 10px 20px 10px 0; - border-bottom: 1px solid #b1b4b6; - text-align: left; - vertical-align: top; -} - -.govuk-table__cell--numeric { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-font-feature-settings: "tnum" 1; - font-feature-settings: "tnum" 1; - font-weight: 400; -} -@media print { - .govuk-table__cell--numeric { - font-family: sans-serif; - } -} -@supports (font-variant-numeric: tabular-nums) { - .govuk-table__cell--numeric { - -webkit-font-feature-settings: normal; - font-feature-settings: normal; - font-variant-numeric: tabular-nums; - } -} - -.govuk-table__header--numeric, -.govuk-table__cell--numeric { - text-align: right; -} - -.govuk-table__header:last-child, -.govuk-table__cell:last-child { - padding-right: 0; -} - -.govuk-table__caption { - font-weight: 700; - display: table-caption; - text-align: left; -} - -.govuk-table__caption--xl { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; - margin-bottom: 15px; -} -@media print { - .govuk-table__caption--xl { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-table__caption--xl { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .govuk-table__caption--xl { - font-size: 32pt; - line-height: 1.15; - } -} - -.govuk-table__caption--l { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; - margin-bottom: 15px; -} -@media print { - .govuk-table__caption--l { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-table__caption--l { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .govuk-table__caption--l { - font-size: 24pt; - line-height: 1.05; - } -} - -.govuk-table__caption--m { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; - margin-bottom: 15px; -} -@media print { - .govuk-table__caption--m { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-table__caption--m { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .govuk-table__caption--m { - font-size: 18pt; - line-height: 1.15; - } -} - -.govuk-table__caption--s { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; -} -@media print { - .govuk-table__caption--s { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-table__caption--s { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-table__caption--s { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-warning-text { - position: relative; - margin-bottom: 20px; - padding: 10px 0; -} -@media (min-width: 40.0625em) { - .govuk-warning-text { - margin-bottom: 30px; - } -} - -.govuk-warning-text__assistive { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(50%) !important; - clip-path: inset(50%) !important; - border: 0 !important; - white-space: nowrap !important; -} -.govuk-warning-text__assistive:before { - content: " "; -} -.govuk-warning-text__assistive:after { - content: " "; -} - -.govuk-warning-text__icon { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - box-sizing: border-box; - display: inline-block; - position: absolute; - left: 0; - min-width: 35px; - min-height: 35px; - margin-top: -7px; - border: 3px solid #0b0c0c; - border-radius: 50%; - color: #ffffff; - background: #0b0c0c; - font-size: 30px; - line-height: 29px; - text-align: center; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; - forced-color-adjust: none; -} -@media print { - .govuk-warning-text__icon { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-warning-text__icon { - margin-top: -5px; - } -} -@media screen and (forced-colors: active) { - .govuk-warning-text__icon { - border-color: windowText; - color: windowText; - background: transparent; - } -} - -.govuk-warning-text__text { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #0b0c0c; - display: block; - padding-left: 45px; -} -@media print { - .govuk-warning-text__text { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .govuk-warning-text__text { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .govuk-warning-text__text { - font-size: 14pt; - line-height: 1.15; - } -} -@media print { - .govuk-warning-text__text { - color: #000000; - } -} - -.govuk-clearfix:after { - content: ""; - display: block; - clear: both; -} - -.govuk-visually-hidden { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - padding: 0 !important; - overflow: hidden !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(50%) !important; - clip-path: inset(50%) !important; - border: 0 !important; - white-space: nowrap !important; -} -.govuk-visually-hidden:before { - content: " "; -} -.govuk-visually-hidden:after { - content: " "; -} - -.govuk-visually-hidden-focusable { - position: absolute !important; - width: 1px !important; - height: 1px !important; - margin: 0 !important; - overflow: hidden !important; - clip: rect(0 0 0 0) !important; - -webkit-clip-path: inset(50%) !important; - clip-path: inset(50%) !important; - white-space: nowrap !important; -} -.govuk-visually-hidden-focusable:active, .govuk-visually-hidden-focusable:focus { - position: static !important; - width: auto !important; - height: auto !important; - margin: inherit !important; - overflow: visible !important; - clip: auto !important; - -webkit-clip-path: none !important; - clip-path: none !important; - white-space: inherit !important; -} - -.govuk-\!-display-inline { - display: inline !important; -} - -.govuk-\!-display-inline-block { - display: inline-block !important; -} - -.govuk-\!-display-block { - display: block !important; -} - -.govuk-\!-display-none { - display: none !important; -} - -@media print { - .govuk-\!-display-none-print { - display: none !important; - } -} -.govuk-\!-margin-0 { - margin: 0 !important; -} - -.govuk-\!-margin-top-0 { - margin-top: 0 !important; -} - -.govuk-\!-margin-right-0 { - margin-right: 0 !important; -} - -.govuk-\!-margin-bottom-0 { - margin-bottom: 0 !important; -} - -.govuk-\!-margin-left-0 { - margin-left: 0 !important; -} - -.govuk-\!-margin-1 { - margin: 5px !important; -} - -.govuk-\!-margin-top-1 { - margin-top: 5px !important; -} - -.govuk-\!-margin-right-1 { - margin-right: 5px !important; -} - -.govuk-\!-margin-bottom-1 { - margin-bottom: 5px !important; -} - -.govuk-\!-margin-left-1 { - margin-left: 5px !important; -} - -.govuk-\!-margin-2 { - margin: 10px !important; -} - -.govuk-\!-margin-top-2 { - margin-top: 10px !important; -} - -.govuk-\!-margin-right-2 { - margin-right: 10px !important; -} - -.govuk-\!-margin-bottom-2 { - margin-bottom: 10px !important; -} - -.govuk-\!-margin-left-2 { - margin-left: 10px !important; -} - -.govuk-\!-margin-3 { - margin: 15px !important; -} - -.govuk-\!-margin-top-3 { - margin-top: 15px !important; -} - -.govuk-\!-margin-right-3 { - margin-right: 15px !important; -} - -.govuk-\!-margin-bottom-3 { - margin-bottom: 15px !important; -} - -.govuk-\!-margin-left-3 { - margin-left: 15px !important; -} - -.govuk-\!-margin-4 { - margin: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-4 { - margin: 20px !important; - } -} - -.govuk-\!-margin-top-4 { - margin-top: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-4 { - margin-top: 20px !important; - } -} - -.govuk-\!-margin-right-4 { - margin-right: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-4 { - margin-right: 20px !important; - } -} - -.govuk-\!-margin-bottom-4 { - margin-bottom: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-4 { - margin-bottom: 20px !important; - } -} - -.govuk-\!-margin-left-4 { - margin-left: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-4 { - margin-left: 20px !important; - } -} - -.govuk-\!-margin-5 { - margin: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-5 { - margin: 25px !important; - } -} - -.govuk-\!-margin-top-5 { - margin-top: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-5 { - margin-top: 25px !important; - } -} - -.govuk-\!-margin-right-5 { - margin-right: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-5 { - margin-right: 25px !important; - } -} - -.govuk-\!-margin-bottom-5 { - margin-bottom: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-5 { - margin-bottom: 25px !important; - } -} - -.govuk-\!-margin-left-5 { - margin-left: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-5 { - margin-left: 25px !important; - } -} - -.govuk-\!-margin-6 { - margin: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-6 { - margin: 30px !important; - } -} - -.govuk-\!-margin-top-6 { - margin-top: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-6 { - margin-top: 30px !important; - } -} - -.govuk-\!-margin-right-6 { - margin-right: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-6 { - margin-right: 30px !important; - } -} - -.govuk-\!-margin-bottom-6 { - margin-bottom: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-6 { - margin-bottom: 30px !important; - } -} - -.govuk-\!-margin-left-6 { - margin-left: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-6 { - margin-left: 30px !important; - } -} - -.govuk-\!-margin-7 { - margin: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-7 { - margin: 40px !important; - } -} - -.govuk-\!-margin-top-7 { - margin-top: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-7 { - margin-top: 40px !important; - } -} - -.govuk-\!-margin-right-7 { - margin-right: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-7 { - margin-right: 40px !important; - } -} - -.govuk-\!-margin-bottom-7 { - margin-bottom: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-7 { - margin-bottom: 40px !important; - } -} - -.govuk-\!-margin-left-7 { - margin-left: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-7 { - margin-left: 40px !important; - } -} - -.govuk-\!-margin-8 { - margin: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-8 { - margin: 50px !important; - } -} - -.govuk-\!-margin-top-8 { - margin-top: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-8 { - margin-top: 50px !important; - } -} - -.govuk-\!-margin-right-8 { - margin-right: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-8 { - margin-right: 50px !important; - } -} - -.govuk-\!-margin-bottom-8 { - margin-bottom: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-8 { - margin-bottom: 50px !important; - } -} - -.govuk-\!-margin-left-8 { - margin-left: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-8 { - margin-left: 50px !important; - } -} - -.govuk-\!-margin-9 { - margin: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-9 { - margin: 60px !important; - } -} - -.govuk-\!-margin-top-9 { - margin-top: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-top-9 { - margin-top: 60px !important; - } -} - -.govuk-\!-margin-right-9 { - margin-right: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-right-9 { - margin-right: 60px !important; - } -} - -.govuk-\!-margin-bottom-9 { - margin-bottom: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-bottom-9 { - margin-bottom: 60px !important; - } -} - -.govuk-\!-margin-left-9 { - margin-left: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-margin-left-9 { - margin-left: 60px !important; - } -} - -.govuk-\!-padding-0 { - padding: 0 !important; -} - -.govuk-\!-padding-top-0 { - padding-top: 0 !important; -} - -.govuk-\!-padding-right-0 { - padding-right: 0 !important; -} - -.govuk-\!-padding-bottom-0 { - padding-bottom: 0 !important; -} - -.govuk-\!-padding-left-0 { - padding-left: 0 !important; -} - -.govuk-\!-padding-1 { - padding: 5px !important; -} - -.govuk-\!-padding-top-1 { - padding-top: 5px !important; -} - -.govuk-\!-padding-right-1 { - padding-right: 5px !important; -} - -.govuk-\!-padding-bottom-1 { - padding-bottom: 5px !important; -} - -.govuk-\!-padding-left-1 { - padding-left: 5px !important; -} - -.govuk-\!-padding-2 { - padding: 10px !important; -} - -.govuk-\!-padding-top-2 { - padding-top: 10px !important; -} - -.govuk-\!-padding-right-2 { - padding-right: 10px !important; -} - -.govuk-\!-padding-bottom-2 { - padding-bottom: 10px !important; -} - -.govuk-\!-padding-left-2 { - padding-left: 10px !important; -} - -.govuk-\!-padding-3 { - padding: 15px !important; -} - -.govuk-\!-padding-top-3 { - padding-top: 15px !important; -} - -.govuk-\!-padding-right-3 { - padding-right: 15px !important; -} - -.govuk-\!-padding-bottom-3 { - padding-bottom: 15px !important; -} - -.govuk-\!-padding-left-3 { - padding-left: 15px !important; -} - -.govuk-\!-padding-4 { - padding: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-4 { - padding: 20px !important; - } -} - -.govuk-\!-padding-top-4 { - padding-top: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-4 { - padding-top: 20px !important; - } -} - -.govuk-\!-padding-right-4 { - padding-right: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-4 { - padding-right: 20px !important; - } -} - -.govuk-\!-padding-bottom-4 { - padding-bottom: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-4 { - padding-bottom: 20px !important; - } -} - -.govuk-\!-padding-left-4 { - padding-left: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-4 { - padding-left: 20px !important; - } -} - -.govuk-\!-padding-5 { - padding: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-5 { - padding: 25px !important; - } -} - -.govuk-\!-padding-top-5 { - padding-top: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-5 { - padding-top: 25px !important; - } -} - -.govuk-\!-padding-right-5 { - padding-right: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-5 { - padding-right: 25px !important; - } -} - -.govuk-\!-padding-bottom-5 { - padding-bottom: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-5 { - padding-bottom: 25px !important; - } -} - -.govuk-\!-padding-left-5 { - padding-left: 15px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-5 { - padding-left: 25px !important; - } -} - -.govuk-\!-padding-6 { - padding: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-6 { - padding: 30px !important; - } -} - -.govuk-\!-padding-top-6 { - padding-top: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-6 { - padding-top: 30px !important; - } -} - -.govuk-\!-padding-right-6 { - padding-right: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-6 { - padding-right: 30px !important; - } -} - -.govuk-\!-padding-bottom-6 { - padding-bottom: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-6 { - padding-bottom: 30px !important; - } -} - -.govuk-\!-padding-left-6 { - padding-left: 20px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-6 { - padding-left: 30px !important; - } -} - -.govuk-\!-padding-7 { - padding: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-7 { - padding: 40px !important; - } -} - -.govuk-\!-padding-top-7 { - padding-top: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-7 { - padding-top: 40px !important; - } -} - -.govuk-\!-padding-right-7 { - padding-right: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-7 { - padding-right: 40px !important; - } -} - -.govuk-\!-padding-bottom-7 { - padding-bottom: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-7 { - padding-bottom: 40px !important; - } -} - -.govuk-\!-padding-left-7 { - padding-left: 25px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-7 { - padding-left: 40px !important; - } -} - -.govuk-\!-padding-8 { - padding: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-8 { - padding: 50px !important; - } -} - -.govuk-\!-padding-top-8 { - padding-top: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-8 { - padding-top: 50px !important; - } -} - -.govuk-\!-padding-right-8 { - padding-right: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-8 { - padding-right: 50px !important; - } -} - -.govuk-\!-padding-bottom-8 { - padding-bottom: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-8 { - padding-bottom: 50px !important; - } -} - -.govuk-\!-padding-left-8 { - padding-left: 30px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-8 { - padding-left: 50px !important; - } -} - -.govuk-\!-padding-9 { - padding: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-9 { - padding: 60px !important; - } -} - -.govuk-\!-padding-top-9 { - padding-top: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-top-9 { - padding-top: 60px !important; - } -} - -.govuk-\!-padding-right-9 { - padding-right: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-right-9 { - padding-right: 60px !important; - } -} - -.govuk-\!-padding-bottom-9 { - padding-bottom: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-bottom-9 { - padding-bottom: 60px !important; - } -} - -.govuk-\!-padding-left-9 { - padding-left: 40px !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-padding-left-9 { - padding-left: 60px !important; - } -} - -.govuk-\!-margin-static-0, -.govuk-\!-static-margin-0 { - margin: 0 !important; -} - -.govuk-\!-margin-top-static-0, -.govuk-\!-static-margin-top-0 { - margin-top: 0 !important; -} - -.govuk-\!-margin-right-static-0, -.govuk-\!-static-margin-right-0 { - margin-right: 0 !important; -} - -.govuk-\!-margin-bottom-static-0, -.govuk-\!-static-margin-bottom-0 { - margin-bottom: 0 !important; -} - -.govuk-\!-margin-left-static-0, -.govuk-\!-static-margin-left-0 { - margin-left: 0 !important; -} - -.govuk-\!-margin-static-1, -.govuk-\!-static-margin-1 { - margin: 5px !important; -} - -.govuk-\!-margin-top-static-1, -.govuk-\!-static-margin-top-1 { - margin-top: 5px !important; -} - -.govuk-\!-margin-right-static-1, -.govuk-\!-static-margin-right-1 { - margin-right: 5px !important; -} - -.govuk-\!-margin-bottom-static-1, -.govuk-\!-static-margin-bottom-1 { - margin-bottom: 5px !important; -} - -.govuk-\!-margin-left-static-1, -.govuk-\!-static-margin-left-1 { - margin-left: 5px !important; -} - -.govuk-\!-margin-static-2, -.govuk-\!-static-margin-2 { - margin: 10px !important; -} - -.govuk-\!-margin-top-static-2, -.govuk-\!-static-margin-top-2 { - margin-top: 10px !important; -} - -.govuk-\!-margin-right-static-2, -.govuk-\!-static-margin-right-2 { - margin-right: 10px !important; -} - -.govuk-\!-margin-bottom-static-2, -.govuk-\!-static-margin-bottom-2 { - margin-bottom: 10px !important; -} - -.govuk-\!-margin-left-static-2, -.govuk-\!-static-margin-left-2 { - margin-left: 10px !important; -} - -.govuk-\!-margin-static-3, -.govuk-\!-static-margin-3 { - margin: 15px !important; -} - -.govuk-\!-margin-top-static-3, -.govuk-\!-static-margin-top-3 { - margin-top: 15px !important; -} - -.govuk-\!-margin-right-static-3, -.govuk-\!-static-margin-right-3 { - margin-right: 15px !important; -} - -.govuk-\!-margin-bottom-static-3, -.govuk-\!-static-margin-bottom-3 { - margin-bottom: 15px !important; -} - -.govuk-\!-margin-left-static-3, -.govuk-\!-static-margin-left-3 { - margin-left: 15px !important; -} - -.govuk-\!-margin-static-4, -.govuk-\!-static-margin-4 { - margin: 20px !important; -} - -.govuk-\!-margin-top-static-4, -.govuk-\!-static-margin-top-4 { - margin-top: 20px !important; -} - -.govuk-\!-margin-right-static-4, -.govuk-\!-static-margin-right-4 { - margin-right: 20px !important; -} - -.govuk-\!-margin-bottom-static-4, -.govuk-\!-static-margin-bottom-4 { - margin-bottom: 20px !important; -} - -.govuk-\!-margin-left-static-4, -.govuk-\!-static-margin-left-4 { - margin-left: 20px !important; -} - -.govuk-\!-margin-static-5, -.govuk-\!-static-margin-5 { - margin: 25px !important; -} - -.govuk-\!-margin-top-static-5, -.govuk-\!-static-margin-top-5 { - margin-top: 25px !important; -} - -.govuk-\!-margin-right-static-5, -.govuk-\!-static-margin-right-5 { - margin-right: 25px !important; -} - -.govuk-\!-margin-bottom-static-5, -.govuk-\!-static-margin-bottom-5 { - margin-bottom: 25px !important; -} - -.govuk-\!-margin-left-static-5, -.govuk-\!-static-margin-left-5 { - margin-left: 25px !important; -} - -.govuk-\!-margin-static-6, -.govuk-\!-static-margin-6 { - margin: 30px !important; -} - -.govuk-\!-margin-top-static-6, -.govuk-\!-static-margin-top-6 { - margin-top: 30px !important; -} - -.govuk-\!-margin-right-static-6, -.govuk-\!-static-margin-right-6 { - margin-right: 30px !important; -} - -.govuk-\!-margin-bottom-static-6, -.govuk-\!-static-margin-bottom-6 { - margin-bottom: 30px !important; -} - -.govuk-\!-margin-left-static-6, -.govuk-\!-static-margin-left-6 { - margin-left: 30px !important; -} - -.govuk-\!-margin-static-7, -.govuk-\!-static-margin-7 { - margin: 40px !important; -} - -.govuk-\!-margin-top-static-7, -.govuk-\!-static-margin-top-7 { - margin-top: 40px !important; -} - -.govuk-\!-margin-right-static-7, -.govuk-\!-static-margin-right-7 { - margin-right: 40px !important; -} - -.govuk-\!-margin-bottom-static-7, -.govuk-\!-static-margin-bottom-7 { - margin-bottom: 40px !important; -} - -.govuk-\!-margin-left-static-7, -.govuk-\!-static-margin-left-7 { - margin-left: 40px !important; -} - -.govuk-\!-margin-static-8, -.govuk-\!-static-margin-8 { - margin: 50px !important; -} - -.govuk-\!-margin-top-static-8, -.govuk-\!-static-margin-top-8 { - margin-top: 50px !important; -} - -.govuk-\!-margin-right-static-8, -.govuk-\!-static-margin-right-8 { - margin-right: 50px !important; -} - -.govuk-\!-margin-bottom-static-8, -.govuk-\!-static-margin-bottom-8 { - margin-bottom: 50px !important; -} - -.govuk-\!-margin-left-static-8, -.govuk-\!-static-margin-left-8 { - margin-left: 50px !important; -} - -.govuk-\!-margin-static-9, -.govuk-\!-static-margin-9 { - margin: 60px !important; -} - -.govuk-\!-margin-top-static-9, -.govuk-\!-static-margin-top-9 { - margin-top: 60px !important; -} - -.govuk-\!-margin-right-static-9, -.govuk-\!-static-margin-right-9 { - margin-right: 60px !important; -} - -.govuk-\!-margin-bottom-static-9, -.govuk-\!-static-margin-bottom-9 { - margin-bottom: 60px !important; -} - -.govuk-\!-margin-left-static-9, -.govuk-\!-static-margin-left-9 { - margin-left: 60px !important; -} - -.govuk-\!-padding-static-0, -.govuk-\!-static-padding-0 { - padding: 0 !important; -} - -.govuk-\!-padding-top-static-0, -.govuk-\!-static-padding-top-0 { - padding-top: 0 !important; -} - -.govuk-\!-padding-right-static-0, -.govuk-\!-static-padding-right-0 { - padding-right: 0 !important; -} - -.govuk-\!-padding-bottom-static-0, -.govuk-\!-static-padding-bottom-0 { - padding-bottom: 0 !important; -} - -.govuk-\!-padding-left-static-0, -.govuk-\!-static-padding-left-0 { - padding-left: 0 !important; -} - -.govuk-\!-padding-static-1, -.govuk-\!-static-padding-1 { - padding: 5px !important; -} - -.govuk-\!-padding-top-static-1, -.govuk-\!-static-padding-top-1 { - padding-top: 5px !important; -} - -.govuk-\!-padding-right-static-1, -.govuk-\!-static-padding-right-1 { - padding-right: 5px !important; -} - -.govuk-\!-padding-bottom-static-1, -.govuk-\!-static-padding-bottom-1 { - padding-bottom: 5px !important; -} - -.govuk-\!-padding-left-static-1, -.govuk-\!-static-padding-left-1 { - padding-left: 5px !important; -} - -.govuk-\!-padding-static-2, -.govuk-\!-static-padding-2 { - padding: 10px !important; -} - -.govuk-\!-padding-top-static-2, -.govuk-\!-static-padding-top-2 { - padding-top: 10px !important; -} - -.govuk-\!-padding-right-static-2, -.govuk-\!-static-padding-right-2 { - padding-right: 10px !important; -} - -.govuk-\!-padding-bottom-static-2, -.govuk-\!-static-padding-bottom-2 { - padding-bottom: 10px !important; -} - -.govuk-\!-padding-left-static-2, -.govuk-\!-static-padding-left-2 { - padding-left: 10px !important; -} - -.govuk-\!-padding-static-3, -.govuk-\!-static-padding-3 { - padding: 15px !important; -} - -.govuk-\!-padding-top-static-3, -.govuk-\!-static-padding-top-3 { - padding-top: 15px !important; -} - -.govuk-\!-padding-right-static-3, -.govuk-\!-static-padding-right-3 { - padding-right: 15px !important; -} - -.govuk-\!-padding-bottom-static-3, -.govuk-\!-static-padding-bottom-3 { - padding-bottom: 15px !important; -} - -.govuk-\!-padding-left-static-3, -.govuk-\!-static-padding-left-3 { - padding-left: 15px !important; -} - -.govuk-\!-padding-static-4, -.govuk-\!-static-padding-4 { - padding: 20px !important; -} - -.govuk-\!-padding-top-static-4, -.govuk-\!-static-padding-top-4 { - padding-top: 20px !important; -} - -.govuk-\!-padding-right-static-4, -.govuk-\!-static-padding-right-4 { - padding-right: 20px !important; -} - -.govuk-\!-padding-bottom-static-4, -.govuk-\!-static-padding-bottom-4 { - padding-bottom: 20px !important; -} - -.govuk-\!-padding-left-static-4, -.govuk-\!-static-padding-left-4 { - padding-left: 20px !important; -} - -.govuk-\!-padding-static-5, -.govuk-\!-static-padding-5 { - padding: 25px !important; -} - -.govuk-\!-padding-top-static-5, -.govuk-\!-static-padding-top-5 { - padding-top: 25px !important; -} - -.govuk-\!-padding-right-static-5, -.govuk-\!-static-padding-right-5 { - padding-right: 25px !important; -} - -.govuk-\!-padding-bottom-static-5, -.govuk-\!-static-padding-bottom-5 { - padding-bottom: 25px !important; -} - -.govuk-\!-padding-left-static-5, -.govuk-\!-static-padding-left-5 { - padding-left: 25px !important; -} - -.govuk-\!-padding-static-6, -.govuk-\!-static-padding-6 { - padding: 30px !important; -} - -.govuk-\!-padding-top-static-6, -.govuk-\!-static-padding-top-6 { - padding-top: 30px !important; -} - -.govuk-\!-padding-right-static-6, -.govuk-\!-static-padding-right-6 { - padding-right: 30px !important; -} - -.govuk-\!-padding-bottom-static-6, -.govuk-\!-static-padding-bottom-6 { - padding-bottom: 30px !important; -} - -.govuk-\!-padding-left-static-6, -.govuk-\!-static-padding-left-6 { - padding-left: 30px !important; -} - -.govuk-\!-padding-static-7, -.govuk-\!-static-padding-7 { - padding: 40px !important; -} - -.govuk-\!-padding-top-static-7, -.govuk-\!-static-padding-top-7 { - padding-top: 40px !important; -} - -.govuk-\!-padding-right-static-7, -.govuk-\!-static-padding-right-7 { - padding-right: 40px !important; -} - -.govuk-\!-padding-bottom-static-7, -.govuk-\!-static-padding-bottom-7 { - padding-bottom: 40px !important; -} - -.govuk-\!-padding-left-static-7, -.govuk-\!-static-padding-left-7 { - padding-left: 40px !important; -} - -.govuk-\!-padding-static-8, -.govuk-\!-static-padding-8 { - padding: 50px !important; -} - -.govuk-\!-padding-top-static-8, -.govuk-\!-static-padding-top-8 { - padding-top: 50px !important; -} - -.govuk-\!-padding-right-static-8, -.govuk-\!-static-padding-right-8 { - padding-right: 50px !important; -} - -.govuk-\!-padding-bottom-static-8, -.govuk-\!-static-padding-bottom-8 { - padding-bottom: 50px !important; -} - -.govuk-\!-padding-left-static-8, -.govuk-\!-static-padding-left-8 { - padding-left: 50px !important; -} - -.govuk-\!-padding-static-9, -.govuk-\!-static-padding-9 { - padding: 60px !important; -} - -.govuk-\!-padding-top-static-9, -.govuk-\!-static-padding-top-9 { - padding-top: 60px !important; -} - -.govuk-\!-padding-right-static-9, -.govuk-\!-static-padding-right-9 { - padding-right: 60px !important; -} - -.govuk-\!-padding-bottom-static-9, -.govuk-\!-static-padding-bottom-9 { - padding-bottom: 60px !important; -} - -.govuk-\!-padding-left-static-9, -.govuk-\!-static-padding-left-9 { - padding-left: 60px !important; -} - -.govuk-\!-text-align-left { - text-align: left !important; -} - -.govuk-\!-text-align-centre { - text-align: center !important; -} - -.govuk-\!-text-align-right { - text-align: right !important; -} - -.govuk-\!-font-size-80 { - font-size: 53px !important; - font-size: 3.3125rem !important; - line-height: 1.0377358491 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-80 { - font-size: 80px !important; - font-size: 5rem !important; - line-height: 1 !important; - } -} -@media print { - .govuk-\!-font-size-80 { - font-size: 53pt !important; - line-height: 1.1 !important; - } -} - -.govuk-\!-font-size-48 { - font-size: 32px !important; - font-size: 2rem !important; - line-height: 1.09375 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-48 { - font-size: 48px !important; - font-size: 3rem !important; - line-height: 1.0416666667 !important; - } -} -@media print { - .govuk-\!-font-size-48 { - font-size: 32pt !important; - line-height: 1.15 !important; - } -} - -.govuk-\!-font-size-36 { - font-size: 24px !important; - font-size: 1.5rem !important; - line-height: 1.0416666667 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-36 { - font-size: 36px !important; - font-size: 2.25rem !important; - line-height: 1.1111111111 !important; - } -} -@media print { - .govuk-\!-font-size-36 { - font-size: 24pt !important; - line-height: 1.05 !important; - } -} - -.govuk-\!-font-size-27 { - font-size: 18px !important; - font-size: 1.125rem !important; - line-height: 1.1111111111 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-27 { - font-size: 27px !important; - font-size: 1.6875rem !important; - line-height: 1.1111111111 !important; - } -} -@media print { - .govuk-\!-font-size-27 { - font-size: 18pt !important; - line-height: 1.15 !important; - } -} - -.govuk-\!-font-size-24 { - font-size: 18px !important; - font-size: 1.125rem !important; - line-height: 1.1111111111 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-24 { - font-size: 24px !important; - font-size: 1.5rem !important; - line-height: 1.25 !important; - } -} -@media print { - .govuk-\!-font-size-24 { - font-size: 18pt !important; - line-height: 1.15 !important; - } -} - -.govuk-\!-font-size-19 { - font-size: 16px !important; - font-size: 1rem !important; - line-height: 1.25 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-19 { - font-size: 19px !important; - font-size: 1.1875rem !important; - line-height: 1.3157894737 !important; - } -} -@media print { - .govuk-\!-font-size-19 { - font-size: 14pt !important; - line-height: 1.15 !important; - } -} - -.govuk-\!-font-size-16 { - font-size: 14px !important; - font-size: 0.875rem !important; - line-height: 1.1428571429 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-16 { - font-size: 16px !important; - font-size: 1rem !important; - line-height: 1.25 !important; - } -} -@media print { - .govuk-\!-font-size-16 { - font-size: 14pt !important; - line-height: 1.2 !important; - } -} - -.govuk-\!-font-size-14 { - font-size: 12px !important; - font-size: 0.75rem !important; - line-height: 1.25 !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-font-size-14 { - font-size: 14px !important; - font-size: 0.875rem !important; - line-height: 1.4285714286 !important; - } -} -@media print { - .govuk-\!-font-size-14 { - font-size: 12pt !important; - line-height: 1.2 !important; - } -} - -.govuk-\!-font-weight-regular { - font-weight: 400 !important; -} - -.govuk-\!-font-weight-bold { - font-weight: 700 !important; -} - -.govuk-\!-width-full { - width: 100% !important; -} - -.govuk-\!-width-three-quarters { - width: 100% !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-width-three-quarters { - width: 75% !important; - } -} - -.govuk-\!-width-two-thirds { - width: 100% !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-width-two-thirds { - width: 66.66% !important; - } -} - -.govuk-\!-width-one-half { - width: 100% !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-width-one-half { - width: 50% !important; - } -} - -.govuk-\!-width-one-third { - width: 100% !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-width-one-third { - width: 33.33% !important; - } -} - -.govuk-\!-width-one-quarter { - width: 100% !important; -} -@media (min-width: 40.0625em) { - .govuk-\!-width-one-quarter { - width: 25% !important; - } -} - -.autocomplete__wrapper { - position: relative; -} - -.autocomplete__hint, -.autocomplete__input { - -webkit-appearance: none; - border: 2px solid #0b0c0c; - border-radius: 0; /* Safari 10 on iOS adds implicit border rounding. */ - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - margin-bottom: 0; /* BUG: Safari 10 on macOS seems to add an implicit margin. */ - width: 100%; -} - -.autocomplete__input { - background-color: transparent; - position: relative; -} - -.autocomplete__hint { - color: #b1b4b6; - position: absolute; -} - -.autocomplete__input--default { - padding: 5px; -} - -.autocomplete__input--focused { - outline: 3px solid #fd0; - outline-offset: 0; - box-shadow: inset 0 0 0 2px; -} - -.autocomplete__input--show-all-values { - padding: 5px 34px 5px 5px; /* Space for arrow. Other padding should match .autocomplete__input--default. */ - cursor: pointer; -} - -.autocomplete__dropdown-arrow-down { - z-index: -1; - display: inline-block; - position: absolute; - right: 8px; - width: 24px; - height: 24px; - top: 10px; -} - -.autocomplete__menu { - background-color: #fff; - border: 2px solid #0B0C0C; - border-top: 0; - color: #0B0C0C; - margin: 0; - max-height: 342px; - overflow-x: hidden; - padding: 0; - width: 100%; - width: calc(100% - 4px); -} - -.autocomplete__menu--visible { - display: block; -} - -.autocomplete__menu--hidden { - display: none; -} - -.autocomplete__menu--overlay { - box-shadow: rgba(0, 0, 0, 0.256863) 0px 2px 6px; - left: 0; - position: absolute; - top: 100%; - z-index: 100; -} - -.autocomplete__menu--inline { - position: relative; -} - -.autocomplete__option { - border-bottom: solid #b1b4b6; - border-width: 1px 0; - cursor: pointer; - display: block; - position: relative; -} - -.autocomplete__option > * { - pointer-events: none; -} - -.autocomplete__option:first-of-type { - border-top-width: 0; -} - -.autocomplete__option:last-of-type { - border-bottom-width: 0; -} - -.autocomplete__option--odd { - background-color: #FAFAFA; -} - -.autocomplete__option--focused, -.autocomplete__option:hover { - background-color: #1d70b8; - border-color: #1d70b8; - color: white; - outline: none; -} - -@media (-ms-high-contrast: active), (forced-colors: active) { - .autocomplete__menu { - border-color: FieldText; - } - .autocomplete__option { - background-color: Field; - color: FieldText; - } - .autocomplete__option--focused, - .autocomplete__option:hover { - forced-color-adjust: none; /* prevent backplate from obscuring text */ - background-color: Highlight; - border-color: Highlight; - color: HighlightText; - /* Prefer SelectedItem / SelectedItemText in browsers that support it */ - background-color: SelectedItem; - border-color: SelectedItem; - color: SelectedItemText; - outline-color: SelectedItemText; - } -} -.autocomplete__option--no-results { - background-color: #FAFAFA; - color: #646b6f; - cursor: not-allowed; -} - -.autocomplete__hint, -.autocomplete__input, -.autocomplete__option { - font-size: 16px; - line-height: 1.25; -} - -.autocomplete__hint, -.autocomplete__option { - padding: 5px; -} - -@media (min-width: 641px) { - .autocomplete__hint, - .autocomplete__input, - .autocomplete__option { - font-size: 19px; - line-height: 1.31579; - } -} -.autocomplete__wrapper { - font-family: "GDS Transport", arial, sans-serif; -} - -.autocomplete__input { - font-family: inherit; -} - -.govuk-form-group--error .autocomplete__input { - border-color: #d4351c; -} -.govuk-form-group--error .autocomplete__input--focused { - border-color: #0b0c0c; -} - -.autocomplete__dropdown-arrow-down { - pointer-events: none; - z-index: 0; -} - -.x-govuk-breadcrumbs--inverse { - padding-bottom: 15px; - padding-top: 15px; - border-bottom: 1px solid #5694ca; - color: #ffffff; - margin-top: 0; -} -@media (min-width: 40.0625em) { - .x-govuk-breadcrumbs--inverse { - padding-top: 20px; - } -} -.x-govuk-breadcrumbs--inverse .govuk-breadcrumbs__list-item::before { - border-color: #ffffff; -} -.x-govuk-breadcrumbs--inverse .govuk-breadcrumbs__link:not(:focus) { - color: inherit; -} - -.x-govuk-button--inverse, -.x-govuk-button--inverse:link, -.x-govuk-button--inverse:visited { - margin-top: 20px; - color: #1d70b8; - background-color: #ffffff; - box-shadow: 0 2px 0 #144e81; - margin-bottom: 0; -} -@media (min-width: 40.0625em) { - .x-govuk-button--inverse, - .x-govuk-button--inverse:link, - .x-govuk-button--inverse:visited { - margin-top: 30px; - } -} - -.x-govuk-button--inverse:hover { - color: #1d70b8; - background-color: #e8f1f8; -} - -.x-govuk-button--inverse:focus:not(:hover) { - color: #0b0c0c; - background-color: #ffdd00; -} - -.x-govuk-button--inverse:active, -.x-govuk-button--inverse:focus { - border-color: #ffdd00; - color: #1d70b8; - background-color: #e8f1f8; - box-shadow: inset 0 0 0 2px #ffdd00; -} - -.x-govuk-phase-banner--inverse { - border-bottom-color: #5694ca; -} -.x-govuk-phase-banner--inverse .govuk-phase-banner__content { - color: #ffffff; -} - -.x-govuk-tag--inverse { - color: #1d70b8; - background-color: #ffffff; -} - -.x-govuk-masthead { - padding-bottom: 25px; - padding-top: 0; - color: #ffffff; - background-color: #1d70b8; - margin-top: -10px; -} -@media (min-width: 40.0625em) { - .x-govuk-masthead { - padding-bottom: 40px; - } -} - -.x-govuk-masthead__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 24px; - font-size: 1.5rem; - line-height: 1.0416666667; - padding-top: 20px; - margin-top: 0; -} -@media print { - .x-govuk-masthead__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-masthead__title { - font-size: 36px; - font-size: 2.25rem; - line-height: 1.1111111111; - } -} -@media print { - .x-govuk-masthead__title { - font-size: 24pt; - line-height: 1.05; - } -} -@media (min-width: 40.0625em) { - .x-govuk-masthead__title { - padding-top: 30px; - } -} - -.x-govuk-masthead__description { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: inherit; - margin-bottom: 0; -} -@media print { - .x-govuk-masthead__description { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-masthead__description { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .x-govuk-masthead__description { - font-size: 14pt; - line-height: 1.15; - } -} -.x-govuk-masthead__description a:not(:focus) { - color: inherit; -} - -.x-govuk-masthead__image { - padding-top: 20px; -} -@media (min-width: 40.0625em) { - .x-govuk-masthead__image { - padding-top: 30px; - } -} -.x-govuk-masthead__image img { - max-width: 100%; -} -@media (max-width: 48.0525em) { - .x-govuk-masthead__image { - display: none; - } -} - -.x-govuk-masthead--large .x-govuk-masthead__title { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 32px; - font-size: 2rem; - line-height: 1.09375; -} -@media print { - .x-govuk-masthead--large .x-govuk-masthead__title { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-masthead--large .x-govuk-masthead__title { - font-size: 48px; - font-size: 3rem; - line-height: 1.0416666667; - } -} -@media print { - .x-govuk-masthead--large .x-govuk-masthead__title { - font-size: 32pt; - line-height: 1.15; - } -} -.x-govuk-masthead--large .x-govuk-masthead__description { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 18px; - font-size: 1.125rem; - line-height: 1.1111111111; -} -@media print { - .x-govuk-masthead--large .x-govuk-masthead__description { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-masthead--large .x-govuk-masthead__description { - font-size: 24px; - font-size: 1.5rem; - line-height: 1.25; - } -} -@media print { - .x-govuk-masthead--large .x-govuk-masthead__description { - font-size: 18pt; - line-height: 1.15; - } -} - -.x-govuk-primary-navigation { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - background-color: #f3f2f1; - border-bottom: 1px solid #b1b4b6; -} -@media print { - .x-govuk-primary-navigation { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-primary-navigation { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .x-govuk-primary-navigation { - font-size: 14pt; - line-height: 1.15; - } -} - -.govuk-phase-banner + .x-govuk-primary-navigation { - margin-top: -1px; -} - -.x-govuk-primary-navigation__list { - left: -15px; - list-style: none; - margin: 0; - padding: 0; - position: relative; - right: -15px; - width: calc(100% + 30px); -} -.x-govuk-primary-navigation__list:after { - content: ""; - display: block; - clear: both; -} - -.x-govuk-primary-navigation__item { - box-sizing: border-box; - display: block; - float: left; - line-height: 50px; - height: 50px; - padding: 0 15px; - position: relative; -} - -.x-govuk-primary-navigation__item--current { - border-bottom: 4px solid #1d70b8; -} -.x-govuk-primary-navigation__item--current:hover { - border-bottom-color: #003078; -} -.x-govuk-primary-navigation__item--current:active { - border-bottom-color: #0b0c0c; -} - -@media (min-width: 40.0625em) { - .x-govuk-primary-navigation__item--align-right { - float: right; - } -} - -.x-govuk-primary-navigation__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; - font-weight: 700; -} -@media print { - .x-govuk-primary-navigation__link { - font-family: sans-serif; - } -} -.x-govuk-primary-navigation__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.x-govuk-primary-navigation__link:link { - color: #1d70b8; -} -.x-govuk-primary-navigation__link:visited { - color: #1d70b8; -} -.x-govuk-primary-navigation__link:hover { - color: #003078; -} -.x-govuk-primary-navigation__link:active { - color: #0b0c0c; -} -.x-govuk-primary-navigation__link:focus { - color: #0b0c0c; -} -.x-govuk-primary-navigation__link:not(:hover):not(:active) { - text-decoration: none; -} -.x-govuk-primary-navigation__link::after { - bottom: 0; - content: ""; - left: 0; - position: absolute; - right: 0; - top: 0; -} - -.x-govuk-related-navigation { - color: #0b0c0c; - border-top: 2px solid #1d70b8; -} -@media print { - .x-govuk-related-navigation { - color: #000000; - } -} - -.x-govuk-related-navigation__main-heading { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - margin-top: 15px; - margin-bottom: 10px; -} -@media print { - .x-govuk-related-navigation__main-heading { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-related-navigation__main-heading { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .x-govuk-related-navigation__main-heading { - font-size: 14pt; - line-height: 1.15; - } -} - -.x-govuk-related-navigation__sub-heading { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; - margin: 0; - padding-top: 15px; -} -@media print { - .x-govuk-related-navigation__sub-heading { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-related-navigation__sub-heading { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .x-govuk-related-navigation__sub-heading { - font-size: 14pt; - line-height: 1.2; - } -} - -.x-govuk-related-navigation__sub-heading--footer { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 700; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - border-top: 0; - padding-top: 0; - margin-top: 15px; - margin-bottom: 10px; -} -@media print { - .x-govuk-related-navigation__sub-heading--footer { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-related-navigation__sub-heading--footer { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .x-govuk-related-navigation__sub-heading--footer { - font-size: 14pt; - line-height: 1.15; - } -} - -.x-govuk-related-navigation__main-heading + .x-govuk-related-navigation__sub-heading { - border-top: 0; - padding-top: 0; -} - -.x-govuk-related-navigation__nav-section { - border-top: 1px solid #b1b4b6; - margin-bottom: 30px; -} -.x-govuk-related-navigation__nav-section:first-child { - border-top: none; -} - -.x-govuk-related-navigation__link-list { - padding: 0; - margin: 0; - list-style: none; - margin-bottom: 1.25em; -} - -.x-govuk-related-navigation__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.45; - list-style-type: none; - margin-top: 15px; -} -@media print { - .x-govuk-related-navigation__link { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-related-navigation__link { - font-size: 16px; - font-size: 1rem; - line-height: 1.45; - } -} -@media print { - .x-govuk-related-navigation__link { - font-size: 14pt; - line-height: 1.45; - } -} -@media (min-width: 40.0625em) { - .x-govuk-related-navigation__link { - line-height: 1.28; - } -} - -.x-govuk-related-navigation__section-link { - font-weight: bold; -} - -.x-govuk-related-navigation__section-link--other { - font-weight: normal; -} - -.x-govuk-sub-navigation { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 14px; - font-size: 0.875rem; - line-height: 1.1428571429; -} -@media print { - .x-govuk-sub-navigation { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-sub-navigation { - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - } -} -@media print { - .x-govuk-sub-navigation { - font-size: 14pt; - line-height: 1.2; - } -} - -.x-govuk-sub-navigation__section { - list-style-type: none; - margin: 0 0 20px; - padding: 0; -} - -.x-govuk-sub-navigation__link { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-decoration: underline; - padding-bottom: 5px; - padding-top: 5px; -} -@media print { - .x-govuk-sub-navigation__link { - font-family: sans-serif; - } -} -.x-govuk-sub-navigation__link:focus { - outline: 3px solid transparent; - color: #0b0c0c; - background-color: #ffdd00; - box-shadow: 0 -2px #ffdd00, 0 4px #0b0c0c; - text-decoration: none; - -webkit-box-decoration-break: clone; - box-decoration-break: clone; -} -.x-govuk-sub-navigation__link:link { - color: #1d70b8; -} -.x-govuk-sub-navigation__link:visited { - color: #1d70b8; -} -.x-govuk-sub-navigation__link:hover { - color: #003078; -} -.x-govuk-sub-navigation__link:active { - color: #0b0c0c; -} -.x-govuk-sub-navigation__link:focus { - color: #0b0c0c; -} -.x-govuk-sub-navigation__link:not(:hover):not(:active) { - text-decoration: none; -} -.x-govuk-sub-navigation__link:not(:focus):hover { - color: #1d70b8; -} - -.x-govuk-sub-navigation__section-item { - margin-bottom: 5px; - padding-bottom: 5px; - padding-top: 5px; -} - -.x-govuk-sub-navigation__section-item--current { - background-color: #ffffff; - border-left: 4px solid #1d70b8; - margin-left: -14px; - padding-left: 10px; -} - -.x-govuk-sub-navigation__link[aria-current] { - font-weight: bold; -} - -.x-govuk-sub-navigation__section--nested { - margin-bottom: 0; - margin-top: 10px; - padding-left: 20px; -} - -.x-govuk-sub-navigation__section--nested .x-govuk-sub-navigation__section-item::before { - color: #505a5f; - content: "—"; - margin-left: -20px; -} - -.x-govuk-sub-navigation__theme { - font-family: "GDS Transport", arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - font-weight: 400; - font-size: 16px; - font-size: 1rem; - line-height: 1.25; - color: #505a5f; - margin: 0; - padding: 10px 15px 10px 0; -} -@media print { - .x-govuk-sub-navigation__theme { - font-family: sans-serif; - } -} -@media (min-width: 40.0625em) { - .x-govuk-sub-navigation__theme { - font-size: 19px; - font-size: 1.1875rem; - line-height: 1.3157894737; - } -} -@media print { - .x-govuk-sub-navigation__theme { - font-size: 14pt; - line-height: 1.15; - } -} - -.app-scrollable-container { - max-height: 500px; - margin-bottom: 20px; - padding-left: 15px; - padding-right: 15px; - overflow-x: auto; - border: 1px solid rgb(169, 169, 169); - background-image: linear-gradient(to right, white, white), linear-gradient(to right, white, white), linear-gradient(to right, rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0)), linear-gradient(to left, rgba(0, 0, 0, 0.25), rgba(255, 255, 255, 0)); - background-position: left center, right center, left center, right center; - background-repeat: no-repeat; - background-color: white; - background-size: 20px 100%, 20px 100%, 10px 100%, 10px 100%; - /* Opera doesn't support this in the shorthand */ - background-attachment: local, local, scroll, scroll; - scrollbar-width: thin; - scrollbar-color: #8A8A8A #DFE9EB; - /* Chrome, Edge and Safari */ -} -.app-scrollable-container table { - margin-bottom: 20px; -} -.app-scrollable-container table th, .app-scrollable-container table td { - white-space: nowrap; -} -.app-scrollable-container table td.app-wrap { - max-width: 500px; - overflow: hidden; - text-overflow: ellipsis; -} -.app-scrollable-container table td.app-wrap .app-inset-text__value { - overflow: hidden; - text-overflow: ellipsis; -} -@media (min-width: 40.0625em) { - .app-scrollable-container { - margin-bottom: 30px; - } -} -.app-scrollable-container::-webkit-scrollbar { - height: 10px; - width: 10px; -} -.app-scrollable-container::-webkit-scrollbar-track { - border-radius: 5px; - background-color: #e8e8e8; -} -.app-scrollable-container::-webkit-scrollbar-track:hover { - background-color: #B8C0C2; -} -.app-scrollable-container::-webkit-scrollbar-track:active { - background-color: #B8C0C2; -} -.app-scrollable-container::-webkit-scrollbar-thumb { - border-radius: 0px; - background-color: #b1b4b6; -} -.app-scrollable-container::-webkit-scrollbar-thumb:hover { - background-color: #5F5F5F; -} -.app-scrollable-container::-webkit-scrollbar-thumb:active { - background-color: #474D54; -} - -.app-inset-text---error { - border-left: 5px solid #d4351c; - padding: 5px 10px; - margin: 0; - width: 500px; -} -.app-inset-text---error .app-inset-text__value { - margin-bottom: 5px; -} -.app-inset-text---error .app-inset-text__error { - color: #d4351c; - font-weight: bold; - white-space: normal; - min-width: fit-content; -} - -.app-inset-text---warning { - border-left: 5px solid #1d70b8; - padding: 5px 10px; - margin: 0; -} -.app-inset-text---warning .app-inset-text__value { - margin-bottom: 5px; -} -.app-inset-text---warning .app-inset-text__warning { - color: #1d70b8; - font-weight: bold; -} - -.app-map { - height: 500px; - margin-bottom: 20px; -} -@media (min-width: 40.0625em) { - .app-map { - margin-bottom: 30px; - } -} - -/*# sourceMappingURL=index.css.map */ diff --git a/public/stylesheets/index.css.map b/public/stylesheets/index.css.map deleted file mode 100644 index 72f856b1..00000000 --- a/public/stylesheets/index.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sourceRoot":"","sources":["../../node_modules/govuk-frontend/govuk/core/_govuk-frontend-version.scss","../../node_modules/govuk-frontend/govuk/core/_links.scss","../../node_modules/govuk-frontend/govuk/helpers/_typography.scss","../../node_modules/govuk-frontend/govuk/settings/_typography-font.scss","../../node_modules/govuk-frontend/govuk/helpers/_links.scss","../../node_modules/govuk-frontend/govuk/helpers/_font-faces.scss","../../node_modules/govuk-frontend/govuk/vendor/_sass-mq.scss","../../node_modules/govuk-frontend/govuk/helpers/_focused.scss","../../node_modules/govuk-frontend/govuk/settings/_colours-applied.scss","../../node_modules/govuk-frontend/govuk/core/_lists.scss","../../node_modules/govuk-frontend/govuk/helpers/_spacing.scss","../../node_modules/govuk-frontend/govuk/core/_typography.scss","../../node_modules/govuk-frontend/govuk/core/_section-break.scss","../../node_modules/govuk-frontend/govuk/objects/_button-group.scss","../../node_modules/govuk-frontend/govuk/objects/_form-group.scss","../../node_modules/govuk-frontend/govuk/helpers/_clearfix.scss","../../node_modules/govuk-frontend/govuk/objects/_grid.scss","../../node_modules/govuk-frontend/govuk/helpers/_grid.scss","../../node_modules/govuk-frontend/govuk/objects/_main-wrapper.scss","../../node_modules/govuk-frontend/govuk/objects/_template.scss","../../node_modules/govuk-frontend/govuk/objects/_width-container.scss","../../node_modules/govuk-frontend/govuk/settings/_measurements.scss","../../node_modules/govuk-frontend/govuk/components/accordion/_index.scss","../../node_modules/govuk-frontend/govuk/components/back-link/_index.scss","../../node_modules/govuk-frontend/govuk/components/breadcrumbs/_index.scss","../../node_modules/govuk-frontend/govuk/components/button/_index.scss","../../node_modules/govuk-frontend/govuk/components/error-message/_index.scss","../../node_modules/govuk-frontend/govuk/components/fieldset/_index.scss","../../node_modules/govuk-frontend/govuk/components/hint/_index.scss","../../node_modules/govuk-frontend/govuk/components/label/_index.scss","../../node_modules/govuk-frontend/govuk/components/checkboxes/_index.scss","../../node_modules/govuk-frontend/govuk/components/textarea/_index.scss","../../node_modules/govuk-frontend/govuk/components/character-count/_index.scss","../../node_modules/govuk-frontend/govuk/components/cookie-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/input/_index.scss","../../node_modules/govuk-frontend/govuk/components/date-input/_index.scss","../../node_modules/govuk-frontend/govuk/components/details/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_shape-arrow.scss","../../node_modules/govuk-frontend/govuk/components/error-summary/_index.scss","../../node_modules/govuk-frontend/govuk/components/exit-this-page/_index.scss","../../node_modules/govuk-frontend/govuk/components/file-upload/_index.scss","../../node_modules/govuk-frontend/govuk/components/footer/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_device-pixels.scss","../../node_modules/govuk-frontend/govuk/components/header/_index.scss","../../node_modules/govuk-frontend/govuk/settings/_links.scss","../../node_modules/govuk-frontend/govuk/components/inset-text/_index.scss","../../node_modules/govuk-frontend/govuk/components/notification-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/pagination/_index.scss","../../node_modules/govuk-frontend/govuk/components/panel/_index.scss","../../node_modules/govuk-frontend/govuk/components/tag/_index.scss","../../node_modules/govuk-frontend/govuk/components/phase-banner/_index.scss","../../node_modules/govuk-frontend/govuk/components/tabs/_index.scss","../../node_modules/govuk-frontend/govuk/components/radios/_index.scss","../../node_modules/govuk-frontend/govuk/components/select/_index.scss","../../node_modules/govuk-frontend/govuk/components/skip-link/_index.scss","../../node_modules/govuk-frontend/govuk/helpers/_visually-hidden.scss","../../node_modules/govuk-frontend/govuk/components/summary-list/_index.scss","../../node_modules/govuk-frontend/govuk/components/table/_index.scss","../../node_modules/govuk-frontend/govuk/components/warning-text/_index.scss","../../node_modules/govuk-frontend/govuk/utilities/_visually-hidden.scss","../../node_modules/govuk-frontend/govuk/overrides/_display.scss","../../node_modules/govuk-frontend/govuk/overrides/_spacing.scss","../../node_modules/govuk-frontend/govuk/overrides/_text-align.scss","../../node_modules/govuk-frontend/govuk/overrides/_typography.scss","../../node_modules/govuk-frontend/govuk/overrides/_width.scss","../../node_modules/accessible-autocomplete/src/autocomplete.css","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/autocomplete/_autocomplete.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_breadcrumbs.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_masthead.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_button.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_phase-banner.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/masthead/_tag.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/primary-navigation/_primary-navigation.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/related-navigation/_related-navigation.scss","../../node_modules/@x-govuk/govuk-prototype-components/x-govuk/components/sub-navigation/_sub-navigation.scss","../../src/assets/scss/_scrollable-container.scss","../../src/assets/scss/index.scss"],"names":[],"mappings":";AAAA;EAGE;;;ACDA;ECaA,aCiCkB;EDhClB;EACA;EEaA;;ACbM;AACA;EACE;EACA;EACA;EACA,KACE;EAEF;;AAGF;EACE;EACA;EACA;EACA,KACE;EAEF;;ACiMF;ELlON;IC4BE,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AHgDR;EACE,OIqDgB;;AJlDlB;EACE,OIwDwB;;AJrD1B;EACE,OI2DsB;;AJxDxB;EACE,OI8DuB;;AJzDzB;EACE,OIrBsB;;AFuJlB;EF6LF;IACE;IACA;IAKA;;;;AAtMN;EAEE,OI3K0B;;AJ8K5B;EAEE,OInNgB;;AJwNlB;EACE,OIlKsB;;;AJgMxB;EFpOA,OMnBkB;;AF8MZ;EFyCN;IFjOE,OMIsB;;;AJoOxB;EAEI;;AAIJ;EFjPA,OMnBkB;;AF8MZ;EFsDN;IF9OE,OMIsB;;;;AJ0QxB;EAEE;;AAKF;EAEE;;AAGF;EACE,OI1PsB;;;AJmUxB;EACE;;;AAxCF;EACE,OIrOgB;;AJwOlB;EACE,OIzOgB;;AJ4OlB;EACE,OI/NsB;;AJkOxB;EACE,OI5NuB;;AJiOzB;EACE,OI/SsB;;;AC3ExB;EPaA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;ECjBhB;ECqGI;EDnGJ;EACA;;AH4NI;EGlON;IP4BE,aCqDsB;;;AGiJlB;EGlON;IP+JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EGlON;IP0JM,WAZQ;IAaR,aAXU;;;AIkFV;EGlON;IP0CE,OMIsB;;;AFoLlB;EGlON;IC+GQ;;;ADtGN;EACE;;;AAIJ;EAIE;;;AAOF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;AH6LI;EG/LN;AAAA;IAKI;;;;AAIJ;EACE;;AHqLI;EGtLN;IAII;;;;AE9CJ;ETqCA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES1Id;EAEA;EDgGI;;AJ0HA;EKhON;ITwCE,OMIsB;;;AFoLlB;EKhON;IT0BE,aCqDsB;;;AGiJlB;EKhON;IT6JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKhON;ITwJM,WAZQ;IAaR,aAXU;;;AIkFV;EKhON;ID6GQ;;;;AC/FR;ETuBA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES5Hd;EAEA;EDkFI;;AJ0HA;EKlNN;IT0BE,OMIsB;;;AFoLlB;EKlNN;ITYE,aCqDsB;;;AGiJlB;EKlNN;IT+IM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKlNN;IT0IM,WAZQ;IAaR,aAXU;;;AIkFV;EKlNN;ID+FQ;;;;ACjFR;ETSA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;ES9Gd;EAEA;EDoEI;;AJ0HA;EKpMN;ITYE,OMIsB;;;AFoLlB;EKpMN;ITFE,aCqDsB;;;AGiJlB;EKpMN;ITiIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKpMN;IT4HM,WAZQ;IAaR,aAXU;;;AIkFV;EKpMN;IDiFQ;;;;ACnER;ETLA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EShGd;EAEA;EDsDI;;AJ0HA;EKtLN;ITFE,OMIsB;;;AFoLlB;EKtLN;IThBE,aCqDsB;;;AGiJlB;EKtLN;ITmHM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKtLN;IT8GM,WAZQ;IAaR,aAXU;;;AIkFV;EKtLN;IDmEQ;;;;ACnDR;ET/CA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESjFd;EAEA;EAEA,OHZ0B;;AF2KtB;EKtKN;IThCE,aCqDsB;;;AGiJlB;EKtKN;ITmGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKtKN;IT8FM,WAZQ;IAaR,aAXU;;;;AS1EhB;ETzDA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESvEd;EAEA;EACA,OHrB0B;;AF2KtB;EK5JN;IT1CE,aCqDsB;;;AGiJlB;EK5JN;ITyFM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK5JN;IToFM,WAZQ;IAaR,aAXU;;;AIkFV;EK5JN;IASI;;;;AAIJ;ETtEA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ES1Dd;EAEA,OHjC0B;;AF2KtB;EK/IN;ITvDE,aCqDsB;;;AGiJlB;EK/IN;IT4EM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK/IN;ITuEM,WAZQ;IAaR,aAXU;;;;ASnDhB;ETtDA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ES/Cd;EDOI;;AJ0HA;EKrIN;ITnDE,OMIsB;;;AFoLlB;EKrIN;ITjEE,aCqDsB;;;AGiJlB;EKrIN;ITkEM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKrIN;IT6DM,WAZQ;IAaR,aAXU;;;AIkFV;EKrIN;IDkBQ;;;;ACNR;ETlEA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESnCd;EDLI;;AJ0HA;EKzHN;IT/DE,OMIsB;;;AFoLlB;EKzHN;IT7EE,aCqDsB;;;AGiJlB;EKzHN;ITsDM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKzHN;ITiDM,WAZQ;IAaR,aAXU;;;AIkFV;EKzHN;IDMQ;;;;ACMR;ET9EA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESvBd;EDjBI;;AJ0HA;EK7GN;IT3EE,OMIsB;;;AFoLlB;EK7GN;ITzFE,aCqDsB;;;AGiJlB;EK7GN;IT0CM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EK7GN;ITqCM,WAZQ;IAaR,aAXU;;;AIkFV;EK7GN;IDNQ;;;;ACkBR;ET1FA,OMnBkB;ENPlB,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;ESXd;ED7BI;;AJ0HA;EKjGN;ITvFE,OMIsB;;;AFoLlB;EKjGN;ITrGE,aCqDsB;;;AGiJlB;EKjGN;IT8BM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EKjGN;ITyBM,WAZQ;IAaR,aAXU;;;AIkFV;EKjGN;IDlBQ;;;;AC8CR;EACE;;ALoEI;EKrEN;IAII;;;;AAIJ;AAAA;AAAA;ED7DM;;AJ0HA;EK7DN;AAAA;AAAA;IDtDQ;;;;AC4DR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;;ALiDI;EKvDN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;IASI;;;;ACpLJ;EACE;EACA;;;AAeF;EFuFM;EAAA;;AJ0HA;EMjNN;IF8FQ;;;AJmHF;EMjNN;IF8FQ;;;;AErFR;EF8EM;EAAA;;AJ0HA;EMxMN;IFqFQ;;;AJmHF;EMxMN;IFqFQ;;;;AE5ER;EFqEM;EAAA;;AJ0HA;EM/LN;IF4EQ;;;AJmHF;EM/LN;IF4EQ;;;;AEjER;EACE;;;ACtCF;EH+FM;EG3EJ;EACA;EACA;EACI;EACJ;EACI;;APgMA;EOzNN;IHsGQ;;;AGtEN;EX5BF,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EWrGZ;EAGA;EACA,YA9Ba;EA+Bb;EACA;;APiLE;EOzLJ;IXbA,aCqDsB;;;AGiJlB;EOzLJ;IXsHI,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EOzLJ;IXiHI,WAZQ;IAaR,aAXU;;;AW1Fd;EACE;;AP2KE;EOzNN;IAqDI;IAEA;IAEI;IACJ;IACI;IACJ;IACI;;EAEJ;AAAA;IAEE,cAhEa;;EAmEf;IACE;;;;AC7EN;EJuGM;;AKjGN;EACE;EACA;EACA;;ATwNI;EQjON;IJ8GQ;;;AI1GN;EACE;;;AAIJ;EACE;EACA;;AAEA;EAEE;EACA;;;AEhBJ;EAEE;EACA;;ADGF;EACE;EACA;EACA;;;ACFA;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;ADxC3C;ECyCF;EAEE;EAEF;;AX6KM;EU1NJ;IC+CA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AD/B3C;ECgCF;EAIA;;AX6KM;EUjNJ;ICsCA;IACA,OAR2C;;;;AC1B7C;EAIE;EACA;EACA;;AZsMI;EY5MN;IAYI;IACA;;;;AAWJ;AAAA;ER0DM;;AJ0HA;EYpLN;AAAA;IRiEQ;;;;AS5GR;EAGE,kBXwB6B;EWpB7B;EACG;EACK;;AAcR;EAvBF;IAwBI;;EAEA;IACE;;;AboMA;Ea/NN;IAkCI;;;;AAKJ;EAGE;EAEA,kBXV2B;;;AYyC7B;EA1DA,WCTiB;EDYjB,cCgBkB;EDflB,aCekB;;ADZlB;EAmDA;IA7CE;IACA;;;AdgMI;EcpJN;IAvCE,cCPW;IDQX,aCRW;;EDWX;IAmCF;MA7BI;MACA;;;;AdgLE;EcpJN;IArBE;IACA;;EAIA;IAgBF;MAfI;MACA;;;;;AE5DJ;EZoGM;;AJ0HA;EgB9NN;IZ2GQ;;;;AYvGR;EACE;;;AAGF;EAEE;EACA;EAEA;EACA;;;AAGF;EpBRA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EcKhB;EACA;EACA;;AhBuMI;EgB7MN;IpBOE,aCqDsB;;;AGiJlB;EgB7MN;IpB0IM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EgB7MN;IpBqIM,WAZQ;IAaR,aAXU;;;AIkFV;EgB7MN;IpBqBE,OMIsB;;;;Ac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UN;E3CcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EqClBhB;EnCsGI;EAAA;EmChGJ;EAEA;;AvCwNI;EuCnON;I3C6BE,aCqDsB;;;AGiJlB;EuCnON;I3CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EuCnON;I3C2JM,WAZQ;IAaR,aAXU;;;AIkFV;EuCnON;I3C2CE,OMIsB;;;AFoLlB;EuCnON;InCgHQ;;;AJmHF;EuCnON;InCgHQ;;;AmCnGN;EACE;;AAGF;AAAA;EAEE;;;ACnBJ;E5CcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EQxCV;EoCrGJ;EAEA,kBtCQiB;;AFqNb;EwCnON;I5C6BE,aCqDsB;;;AGiJlB;EwCnON;I5CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwCnON;I5C2JM,WAZQ;IAaR,aAXU;;;AIkFV;EwCnON;IpCgHQ;;;AoCxGN;EACE;;;AAIJ;EACE;EAGA;;AxCkNI;EwCtNN;IAOI;;;;AAIJ;E5CVA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;E4CtHd;EAEA;EAEA;;AxCoMI;EwC3MN;I5CKE,aCqDsB;;;AGiJlB;EwC3MN;I5CwIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwC3MN;I5CmIM,WAZQ;IAaR,aAXU;;;;A4C/GhB;E5CMA,OMnBkB;EsCgBhB;EAEA,kBtCD2B;;AF6LvB;EwCjMN;I5CSE,OMIsB;;;AFoLlB;EwCjMN;IAQI,SAPe;;;AAYjB;EAGE;EAOA;;AAGF;EACE;;;AAIJ;E5CnDA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;E4C7Ed;EAEA;;AxC6JI;EwClKN;I5CpCE,aCqDsB;;;AGiJlB;EwClKN;I5C+FM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EwClKN;I5C0FM,WAZQ;IAaR,aAXU;;;;A4CxEhB;E5C3DA,aCiCkB;EDhClB;EACA;EEaA;;AEsMM;EwC1JN;I5C5CE,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AH0UR;EACE,OIrOgB;;AJwOlB;EACE,OIzOgB;;AJ4OlB;EACE,OI/NsB;;AJkOxB;EACE,OI5NuB;;AJiOzB;EACE,OI/SsB;;;AsCExB;EACE,ctCemB;EsCbnB,kBtCamB;;AJmFrB;EAEE,OIrFmB;;AJwFrB;EACE;;AAGF;EACE,OI7FmB;;AJkGrB;EACE,OIrHsB;;;AuC1ExB;ErCuGM;EqCrGJ;EACA;EACA;EACI;EACJ;EACI;EACJ;EACI;;AzCwNA;EyCjON;IrC8GQ;;;AJmHF;EyCjON;IAYI;IACI;IACJ;IACI;;;;AAIR;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;E7CbA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;E6ClHd;EACA;EACA;EACA;EACA;EACA;;AzC+LI;EyCxMN;AAAA;AAAA;I7CEE,aCqDsB;;;AGiJlB;EyCxMN;AAAA;AAAA;I7CqIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EyCxMN;AAAA;AAAA;I7CgIM,WAZQ;IAaR,aAXU;;;A6C3Gd;AAAA;AAAA;EACE;;;AAIJ;EAGE;EAIA;;AzCiLI;EyCxLN;IAUI;;;;AAIJ;AAAA;E7COA;;A6CDE;AAAA;EACE;EACA;EACA;EACI;;;AAIR;EACE;;;AAGF;EACE;;;AAIF;AAAA;AAAA;AAAA;EAIE;;;AAGF;E7CvBA;E6CyBE;EACA,kBvC0CgB;;AuCxChB;EACE,kBvCuCc;;AJqLlB;EAEE;;AAKF;EAEE;;AAGF;EACE,OI1PsB;;;AuCyBxB;E7CrCA;E6CuCE,OvC/C0B;;AuCkD1B;EACE;;;AAIJ;EACE;EACA;;AAGA;EACE;IACE;IACA;IACA;IACA;IACA;IACA;;;AAQF;E3CtGJ;;A2CiHI;EACE,OvCnEkB;;AuCsEpB;EACE;;AAGF;EACE;;;AAKN;E7C9IA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EEpHhB;E2CkIE;EACA;;AzCmEI;EyCvEN;I7C/HE,aCqDsB;;;AGiJlB;EyCvEN;I7CIM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EyCvEN;I7CDM,WAZQ;IAaR,aAXU;;;;A6CkBhB;EAEE;EACA;EACA,OvC/G0B;EuCgH1B;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAIF;EACE;;AAEA;EACE;EACA;;AAGF;AAAA;EAEE;EACA;;AAGF;EACE;;AAEA;EACE;;AAKJ;EACE;;AAKF;AAAA;EAEE;;AAOF;EACE;EACA;;AAGF;EACE;;AAME;ExCrNJ;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AwC8MJ;EACE;;AAIJ;EACE;;;AClPJ;E9CcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;E8C9Id;EAEA;EACA;EAEA;EAEA;;A1CyNI;E0CnON;I9C6BE,aCqDsB;;;AGiJlB;E0CnON;I9CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E0CnON;I9C2JM,WAZQ;IAaR,aAXU;;;AIkFV;E0CnON;IAaI;IAWA;IACA;;;;AAIJ;EACE;EACA;;A1CoMI;E0CtMN;IAKI;IACA,OxCYoB;IwCXpB;;;;AAIJ;EACE;EACA;E9C5BF,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;E0C3LN;I9CXE,aCqDsB;;;AGiJlB;E0C3LN;I9CwHM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E0C3LN;I9CmHM,WAZQ;IAaR,aAXU;;;;A8ClGhB;EACE;;;AAGF;E9CrCA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;E0ChLN;I9CtBE,aCqDsB;;;AGiJlB;E0ChLN;I9C6GM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E0ChLN;I9CwGM,WAZQ;IAaR,aAXU;;;;A+CjJhB;EAEE;EAKA;EACA;EAEA;EACA;EACA;EAEA;EACA;E/CDF,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;E+CrHZ;EACA;EACA;EACA;;A3CoME;E2CnON;I/C6BE,aCqDsB;;;AGiJlB;E2CnON;I/CgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E2CnON;I/C2JM,WAZQ;IAaR,aAXU;;;;A+C9GhB;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AC3EF;EACE;EACA;EAEA;;;AAGF;EhDKA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;E0CRhB;EACA;;A5CqNI;E4C1NN;IhDoBE,aCqDsB;;;AGiJlB;E4C1NN;IhDuJM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E4C1NN;IhDkJM,WAZQ;IAaR,aAXU;;;AIkFV;E4C1NN;IhDkCE,OMIsB;;;;A0C9BxB;EACE;;;AAGF;EACE;EACA;;;ACvBF;EzCyGM;EAAA;;AJ0HA;E6CnON;IzCgHQ;;;;AyC3GR;EjDSA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;E2CbhB;;A7C2NI;E6C9NN;IjDwBE,aCqDsB;;;AGiJlB;E6C9NN;IjD2JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E6C9NN;IjDsJM,WAZQ;IAaR,aAXU;;;AIkFV;E6C9NN;IjDsCE,OMIsB;;;;A2CpCxB;EACE;EACA;EACA;EzC2FI;;AJ0HA;E6CxNN;IzCqGQ;;;;AyC9FR;EjDJA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EiD7Hd;;A7C+MI;E6CjNN;IjDWE,aCqDsB;;;AGiJlB;E6CjNN;IjD8IM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E6CjNN;IjDyIM,WAZQ;IAaR,aAXU;;;AiD3Hd;EjDkBF,OMnBkB;E2CGd;EACA;EACA;;A7CyME;E6C7MJ;IjDqBA,OMIsB;;;;A2CjBxB;EjDhBA,aCiCkB;EDhClB;EACA;EEaA;E+CKE;EACA;;A7CgMI;E6CrMN;IjDDE,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AHgDR;EACE,OIqDgB;;AJlDlB;EACE,OIwDwB;;AJrD1B;EACE,OI2DsB;;AJxDxB;EACE,OI8DuB;;AJzDzB;EACE,OIrBsB;;;A2CtCxB;EzCmEM;;AJ0HA;E6C7LN;IzC0EQ;;;;AJmHF;E6CrLF;IAEE;IACA;;EpCzCN;IACE;IACA;IACA;;EoCyCE;IACE;;EAGF;IACE;IAEA;IACA;IACA;IACA;IAEA;IACA;IACA;;EAEA;IACE;;EAIJ;IAGE;IAEA;IAGA;IACA;IACA;IACA;IACA;IAEA;IACA;IAEA,kB3CpDuB;;E2CsDvB;IACE;;EAIJ;IAGE;;E/CwKN;IFpOA,OMnBkB;;;AF8MZ;EFyCN;IFjOE,OMIsB;;;AFoLlB;EFgDN;IAEI;;EAIJ;IFjPA,OMnBkB;;;AF8MZ;EFsDN;IF9OE,OMIsB;;;AFoLlB;E6C7HA;IACE;IACA;IACA;IACA;IACA;IACA;;EAIJ;IzCPE;IyCSA;IACA;IACA;;EAEA;IACE;;EAIJ;IACE;;;;AC9GN;ElDAA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EkDhId;EACA;EAEA,YAbkB;EAelB;EACA,cAhBkB;EAkBlB;;A9C0MI;E8CrNN;IlDeE,aCqDsB;;;AGiJlB;E8CrNN;IlDkJM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8CrNN;IlD6IM,WAZQ;IAaR,aAXU;;;;AkDrHhB;AAAA;EAEE;;;AAGF;EAGE;EAKE;EAEA;EACA;EACA;EAEA,OAzCsB;EA0CtB,QA1CsB;EA2CtB;EAEA;;;AAgBJ;EACE;EACA;EACA;EACA;EAEA;EACI;;;AAIN;EACE;EACA;EACA;EACA;EACA;EAEA,OA9EkB;EA+ElB,QA/EkB;EAiFlB;EACA;EACA;;;AAOF;EACE;EAEA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;;;AAGF;EACE;EACA,eA1GsC;EA2GtC,cA3GsC;;;AA+GxC;EACE;EAMA;EACA;EAQA;;AAJA;EAZF;IAaI;;;;AAOJ;EACE;;;AAIF;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;A9C2EI;ES3NN;IACE;IACA;IACA;;EqCwJE;IACE;IACA;IACA;;;;AASN;ElDjKA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;E4C8JhB,OA5KkB;EA6KlB;EACA;;A9C8CI;E8CpDN;IlDlJE,aCqDsB;;;AGiJlB;E8CpDN;IlDfM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8CpDN;IlDpBM,WAZQ;IAaR,aAXU;;;AIkFV;E8CpDN;IlDpIE,OMIsB;;;;A4CuJxB;E1C7FM;E0C+FJ,aAR2B;EAS3B,cALyB;EAMzB;;A9CyBI;E8C7BN;I1CtFQ;;;A0C4FN;EACE;;AAGF;EACE;;;AAaF;EAEE;EACA;EACA,cANa;EAOb;;ArC3NJ;EACE;EACA;EACA;;AqCoOA;EAEI;;AAaJ;EACE;EACA;EACA;;A9C9BE;E8C2BJ;IAMI;;;AAQJ;EACE;EACA,OAtQsB;EAuQtB,QAvQsB;;AA6QxB;EACE;EACA;EACA;;AAWF;EACE;EACA;EACA;;AAIF;EAEE,aADc;EAEd;EACA;;AAGF;EACE,OA1SsB;EA2StB;;AASF;EACE;;AAQF;EACE,YACE;;AAUJ;EACE;IACE;;EAGF;IACE;;;;ACnVN;EnDUA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EmD1Id;EAMA;EACA;EACA;EAEE;EAEF;EACA;EAIA,O7CHgB;E6CIhB;;A/C0MI;E+C/NN;InDyBE,aCqDsB;;;AGiJlB;E+C/NN;InD4JM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E+C/NN;InDuJM,WAZQ;IAaR,aAXU;;;AmDtHd;EACE;EAEA;EAIA;;AASF;EACE;EACA;EACA;;;AAIJ;AAAA;AAAA;EAGE;EACA;;;AAGF;EACE,c7C2BiB;;A6CzBjB;EACE,c7CmDsB;;;A8ChH1B;EC6DA;EAEA;EACA;EAGA;EAEA;EACA;EACA;EACQ;EAKR;ErD/DA,aCiCkB;EDhClB;EACA;EEaA;EFuHI,WALU;EAOR,WANY;EAQd,aAPY;EoD1Id;EACA;;ACuEF;EAEE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACQ;EAER;;AjDuII;EgDnON;IpD6BE,aCqDsB;;;AC0LxB;EFpOA,OMnBkB;;AF8MZ;EFyCN;IFjOE,OMIsB;;;AJoOxB;EAEI;;AAIJ;EFjPA,OMnBkB;;AF8MZ;EFsDN;IF9OE,OMIsB;;;AFoLlB;EgDnON;IpDgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EgDnON;IpD2JM,WAZQ;IAaR,aAXU;;;AoDtId;EAXF;IAiBI;IACA;;;AAGF;EACE;EACA;EACA,kB9C0Ce;E8CtCb;;;AAMJ;EAQE;;;AE1CJ;EtDcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EgDZhB;E9CgGI;;AJ0HA;EkDnON;ItD6BE,aCqDsB;;;AGiJlB;EkDnON;ItDgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EkDnON;ItD2JM,WAZQ;IAaR,aAXU;;;AIkFV;EkDnON;ItD2CE,OMIsB;;;AFoLlB;EkDnON;IAII;IACA;IACA;IACA;;;AlD4NE;EkDnON;I9CgHQ;;;;A8CnGR;EACE;;AlDqNI;EkDtNN;IAII;;;AlDkNE;EkDtNN;IAOI;;;;AAKJ;EACE;;;AlDyMI;EkDlMF;IACE;IACA;IACA;;;;AAKN;AAAA;AAAA;EAGE;;AlDuLI;EkD1LN;AAAA;AAAA;IAMI;IACA;IACA;IACA;;;;AAIJ;EACE;;AlD4KI;EkD7KN;IAGI;IACA;IACA;;;;AAIJ;AAAA;EAGE;EACA;;;AAGF;EACE;EtDPF;;AImKM;EkD7JN;IAII;;;;AlDyJE;EkDrJN;IAEI;;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AlDgII;EkD1HJ;IACE;IACA;;EAGF;IACE;;EAGF;IACE;IACA;IACA;;;AlD8GE;EkDzGJ;IACE;IACA;;EAGF;IACE;;EAGF;IACE;IACA;IACA;;;AAMF;EACE;;AlDsFE;EkDjFF;AAAA;AAAA;IAGE;;;;AAMN;EACE;;AlDuEI;EkDnEF;AAAA;AAAA;IAGE;;;;AAMN;E9ChEM;E8CkEJ;;AlDwDI;EkD1DN;I9CzDQ;;;;A8C8DR;EACE;EAGA;EACA;;AlDgDI;EkDrDN;IAQI;IACA;IACA;IACI;IACJ;IACI;IACJ;;;;AAIJ;EtDlLA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EsDiDd;;AlDiCI;EkDnCN;ItDnKE,aCqDsB;;;AGiJlB;EkDnCN;ItDhCM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EkDnCN;ItDrCM,WAZQ;IAaR,aAXU;;;AIkFV;EkDnCN;IAKI;;;;AAIJ;EtD3LA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EsD0Dd;EACA;EACA;EACI;EACJ;EACA;EACA;EACA;;AlDiBI;EkD1BN;ItD5KE,aCqDsB;;;AGiJlB;EkD1BN;ItDzCM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EkD1BN;ItD9CM,WAZQ;IAaR,aAXU;;;AIkFV;EkD1BN;IAYI;IACI;IACJ;;;;AAIJ;EACE;EACA;EACA;EACA;;AlDII;EkDRN;IAOI;;;AAYF;EAnBF;IAoBI;;;;AAIJ;EACE;EACA;EACA;;AlDnBI;EkDgBN;IAMI;;;AAIF;EAVF;IAWI;;;;AAIJ;EACE;;AlDhCI;EkD+BN;IAII;;;AAGF;EACE;;AAGF;EACE;EACA;;;AC/QJ;EvDcA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EiDlBhB;E/CsGI;E+CnGJ;EACA;;AnD4NI;EmDnON;IvD6BE,aCqDsB;;;AGiJlB;EmDnON;IvDgKM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmDnON;IvD2JM,WAZQ;IAaR,aAXU;;;AIkFV;EmDnON;IvD2CE,OMIsB;;;AFoLlB;EmDnON;I/CgHQ;;;;A+CtGR;EvDsDA;;;AuDlDA;AAAA;EAEE;EACA;EACA;EACA;;;AASF;EvDdA,aCiCkB;EDhClB;EACA;EA8KI;EACQ;EAzIZ;;AI6KM;EmDvMN;IvDCE,aCqDsB;;;AD+GpB;EuDrKJ;IvDsKM;IACQ;IACR;;;;AuDpKN;AAAA;EAEE;;;AAGF;AAAA;EAEE;;;AAGF;EvDsBA;EuDnBE;EACA;;;AAKF;EvDrCA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EuD5Fd;;AnD8KI;EmDhLN;IvDtBE,aCqDsB;;;AGiJlB;EmDhLN;IvD6GM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmDhLN;IvDwGM,WAZQ;IAaR,aAXU;;;;AuDzFhB;EvD1CA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EuDvFd;;AnDyKI;EmD3KN;IvD3BE,aCqDsB;;;AGiJlB;EmD3KN;IvDwGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmD3KN;IvDmGM,WAZQ;IAaR,aAXU;;;;AuDpFhB;EvD/CA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EuDlFd;;AnDoKI;EmDtKN;IvDhCE,aCqDsB;;;AGiJlB;EmDtKN;IvDmGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmDtKN;IvD8FM,WAZQ;IAaR,aAXU;;;;AuD/EhB;EvDpDA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;EmDjKN;IvDrCE,aCqDsB;;;AGiJlB;EmDjKN;IvD8FM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmDjKN;IvDyFM,WAZQ;IAaR,aAXU;;;;AwDjJhB;EACE;EhDwGI;EgDtGJ;;ApDgOI;EoDnON;IhDgHQ;;;;AgD1GR;EHSA;EAcA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAKA;;AAzBA;EACE;;AAGF;EACE;;;AGhBF;ExDIA,aCiCkB;EDhClB;EACA;EAgDA;EwDnDE;EAEA;EAEA;EACA;EAEA;EACA;EACA;EAQA;EACA;EAEA;EACA;EAEA;EACA;EAEA;EAIA;EACI;EACI;EAIR;;ApDkLI;EoDzNN;IxDmBE,aCqDsB;;;AGiJlB;EoDzNN;IAeI;;;AA0BF;EAzCF;IA0CI;IACA;IACA;;;;AAIJ;ExD5CA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EAzGhB,OMnBkB;EkDwChB;EACA;;ApDqKI;EoDzKN;IxD7BE,aCqDsB;;;AGiJlB;EoDzKN;IxDsGM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EoDzKN;IxDiGM,WAZQ;IAaR,aAXU;;;AIkFV;EoDzKN;IxDfE,OMIsB;;;;AOvCxB;EACE;EACA;EACA;;;A4CXF;EJeA;EAcA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACQ;EAER;EAKA;;AAzBA;EACE;;AAGF;EACE;;;AItBF;EJyDA;EAEA;EACA;EAGA;EAEA;EACA;EACA;EACQ;EAKR;;AAEA;EAEE;EAEA;EACA;EACA;EAEA;EACA;EACA;EACQ;EAER;;;AK3FF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AtDqNI;EsDjNJ;IACE;;;ACuBF;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;;AmDrDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmDvDF;EnDuDE;;;AmD/DJ;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDtEN;EnD6DI;;AJ4HA;EuDzLJ;InDoEM;;;;AmD5DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmD9DJ;EnDuDE;;AJ0HA;EuDjLF;InD8DI;;;;AmDhCN;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AARJ;AAAA;EAEE;;;AAIA;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;AAAA;EAEE;;;AAFF;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CE;AAAA;AAAA;IAGE;IACA;;;AChKJ;EACE,a/D4CkB;;;A+DzCpB;EACE;;;AAKA;EACE,c1DwEiB;;A0DrEnB;EACE,c1D+FwB;;;A0D3F5B;EAGE;EAEA;;;AC3BF;EzD0GQ;EAAA;EyDvGN;EACA,OCFwB;EDGxB;;A7D+NM;E6DpOR;IzDiHU;;;AyD1GR;EACE,cCNsB;;ADSxB;EACE;;;AERJ;AAAA;AAAA;E3DsGQ;E2DlGN,O7DOmB;E6DNnB,kBDPwB;ECQxB;EACA;;A/DyNM;E+DhOR;AAAA;AAAA;I3D6GU;;;;A2DnGV;EACE;EACA,kBAd+C;;;AAiBjD;EACE,O7DyDwB;E6DxDxB,kB7D8CmB;;;A6D3CrB;AAAA;EAEE,c7DyCmB;E6DxCnB,O7DZmB;E6DanB,kBA1B+C;EA2B/C;;;AC7BF;EACE;;AAEA;EACE,OFFsB;;;AGF1B;EACE,O/DcmB;E+DbnB;;;AHOF;E1DiGQ;E0D/FN;EACA,OAVwB;EAWxB,kB5DEmB;E4DDnB;;A9DsNM;E8D3NR;I1DwGU;;;;A0DhGV;ElEFE,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EQxCV;E0DtFN;;A9DgNM;E8DnNR;IlEaI,aCqDsB;;;AGiJlB;E8DnNR;IlEgJQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8DnNR;IlE2IQ,WAZQ;IAaR,aAXU;;;AIkFV;E8DnNR;I1DgGU;;;;A0D1FV;ElERE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EkEzHhB;EACA;;A9D0MM;E8D7MR;IlEOI,aCqDsB;;;AGiJlB;E8D7MR;IlE0IQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8D7MR;IlEqIQ,WAZQ;IAaR,aAXU;;;AkEtHhB;EACE;;;AAIJ;E1DyEQ;;AJ0HA;E8DnMR;I1DgFU;;;A0D7ER;EACE;;A9D+LI;E8DnMR;IAQI;;;;AAKF;ElE/BA,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;E8DtLN;IlEhBE,aCqDsB;;;AGiJlB;E8DtLN;IlEmHM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8DtLN;IlE8GM,WAZQ;IAaR,aAXU;;;AkEhGhB;ElEnCA,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;E8DlLN;IlEpBE,aCqDsB;;;AGiJlB;E8DlLN;IlE+GM,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;E8DlLN;IlE0GM,WAZQ;IAaR,aAXU;;;;AsElJlB;EtEeE,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EsEhJhB;EACA;;AlEiOM;EkEpOR;ItE8BI,aCqDsB;;;AGiJlB;EkEpOR;ItEiKQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EkEpOR;ItE4JQ,WAZQ;IAaR,aAXU;;;;AsE5IlB;EACE;;;AAGF;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;;AzDTA;EACE;EACA;EACA;;;AyDSJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;AAEA;EACE,qBhEgHsB;;AgE7GxB;EACE,qBhEmHuB;;;AF0EnB;EkEzLR;IAEI;;;;AAIJ;EtElCE,aCiCkB;EDhClB;EACA;EEaA;EFmCA;;AImKM;EkEnLR;ItEnBI,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AH0UR;EACE,OIrOgB;;AJwOlB;EACE,OIzOgB;;AJ4OlB;EACE,OI/NsB;;AJkOxB;EACE,OI5NuB;;AJiOzB;EACE,OI/SsB;;AJmUxB;EACE;;AoEzVF;EACE;EACA;EACA;EACA;EACA;EACA;;;AC9DJ;EvEyCE,OMnBkB;EiEpBlB;;AnEkOM;EmEpOR;IvE4CI,OMIsB;;;;AiE3C1B;EvEUE,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EuE3IhB;EACA;;AnE4NM;EmE/NR;IvEyBI,aCqDsB;;;AGiJlB;EmE/NR;IvE4JQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmE/NR;IvEuJQ,WAZQ;IAaR,aAXU;;;;AuEvIlB;EvEIE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EuErIhB;EACA;;AnEsNM;EmEzNR;IvEmBI,aCqDsB;;;AGiJlB;EmEzNR;IvEsJQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmEzNR;IvEiJQ,WAZQ;IAaR,aAXU;;;;AuEjIlB;EvEFE,aCiCkB;EDhClB;EACA;EAgDA;EAoFI,WALU;EAOR,WANY;EAQd,aAPY;EuE/HhB;EACA;EACA;EACA;;AnE8MM;EmEnNR;IvEaI,aCqDsB;;;AGiJlB;EmEnNR;IvEgJQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmEnNR;IvE2IQ,WAZQ;IAaR,aAXU;;;;AuEzHlB;EACE;EACA;;;AAGF;EACE;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EvE/BE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EuElGhB;EACA;;AnEmLM;EmEtLR;IvEhBI,aCqDsB;;;AGiJlB;EmEtLR;IvEmHQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EmEtLR;IvE8GQ,WAZQ;IAaR,aAXU;;;AIkFV;EmEtLR;IAMI;;;;AAIJ;EACE;;;AAGF;EACE;;;AC7DF;ExEeE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;;AIkFV;EoEpOR;IxE8BI,aCqDsB;;;AGiJlB;EoEpOR;IxEiKQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EoEpOR;IxE4JQ,WAZQ;IAaR,aAXU;;;;AwE9IlB;EACE;EACA;EACA;;;AAGF;ExEKE,aCiCkB;EDhClB;EACA;EEaA;EsEhBA;EACA;;ApEqNM;EoE1NR;IxEoBI,aCqDsB;;;ACjExB;EGCE;EAEF,OCwDwB;EDvDxB,kBC6CmB;ED5CnB;EAGA;EAIA;EACQ;;AH0UR;EACE,OIrOgB;;AJwOlB;EACE,OIzOgB;;AJ4OlB;EACE,OI/NsB;;AJkOxB;EACE,OI5NuB;;AJiOzB;EACE,OI/SsB;;AJmUxB;EACE;;AsEhYF;EACE,OlEmHgB;;;AkE/GpB;EACE;EACA;EACA;;;AAGF;EAEE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;ExErCE,aCiCkB;EDhClB;EACA;EAsCA;EA8FI,WALU;EAOR,WANY;EAQd,aAPY;EwE5FhB;EACA;EACA;;ApE4KM;EoEhLR;IxEtBI,aCqDsB;;;AGiJlB;EoEhLR;IxE6GQ,WAjBQ;IAmBN,WAlBU;IAoBZ,aAnBU;;;AIkFV;EoEhLR;IxEwGQ,WAZQ;IAaR,aAXU;;;;AyElJlB;EAqBE;EjEqFM;EiEnFN;EACA;EACA;EACA;EACA,kBAEE;EAOF;EACD;EACA;EACA;AAEA;EACA;EAEC;EACA;AAEA;;AA7CA;EACE;;AACA;EACE;;AAGF;EAEE;EACA;EACA;;AAEA;EACE;EACA;;ArEoNA;EqEpOR;IjEiHU;;;AiEjER;EACE;EACA;;AAEF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA,kBnEqCkB;;AmElCpB;EACE;;AAGF;EACE;;;ACrEJ;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;;;AAMJ;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;;AAKJ;EACE;ElE+DM;;AJ0HA;EsE1LR;IlEuEU","file":"index.css"} \ No newline at end of file From 5d50deb4be40137ea058e50f55514c8aa0898a9a Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 11:55:04 +0100 Subject: [PATCH 118/127] fix pagination tests and change to use jsdom --- test/unit/paginationTemplateTests.js | 69 +++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/test/unit/paginationTemplateTests.js b/test/unit/paginationTemplateTests.js index 67efea60..ee88082c 100644 --- a/test/unit/paginationTemplateTests.js +++ b/test/unit/paginationTemplateTests.js @@ -1,4 +1,5 @@ import { describe, it, expect } from 'vitest' +import jsdom from 'jsdom' const paginationTests = (template, nunjucks) => { describe('pagination', () => { @@ -20,14 +21,13 @@ const paginationTests = (template, nunjucks) => { const params = { options: { pagination, - verboseRows: [{}] + verboseRows: [{}], + id: 'test' }, errors: {} } - const html = nunjucks.render(template, params).replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ') - - expect(html).toContain('') + testPagination({ template, params, nunjucks }) }) it('correctly renders the pagination when viewing the first page', () => { @@ -46,14 +46,13 @@ const paginationTests = (template, nunjucks) => { const params = { options: { pagination, - verboseRows: [{}] + verboseRows: [{}], + id: 'test' }, errors: {} } - const html = nunjucks.render(template, params).replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ') - - expect(html).toContain('') + testPagination({ template, nunjucks, params }) }) it('correctly renders the pagination when viewing the last page', () => { @@ -72,16 +71,62 @@ const paginationTests = (template, nunjucks) => { const params = { options: { pagination, - verboseRows: [{}] + verboseRows: [{}], + id: 'test' }, errors: {} } - const html = nunjucks.render(template, params).replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ') - - expect(html).toContain('') + testPagination({ template, nunjucks, params }) }) }) } +const testPagination = ({ template, nunjucks, params }) => { + const html = nunjucks.render(template, params).replace(/(\r\n|\n|\r)/gm, '').replace(/\t/gm, '').replace(/\s+/g, ' ') + + const { id, pagination } = params.options + + const dom = new jsdom.JSDOM(html) + const document = dom.window.document + + const paginationNode = document.querySelector('nav.govuk-pagination') + const paginationChildren = paginationNode.children + + let currentPaginationChild = 0 + + // Previous link + if (pagination.previousPage) { + expect(paginationChildren[currentPaginationChild].children[0].href).toEqual(`/results/${id}/${pagination.previousPage}`) + currentPaginationChild++ + } + + // page numbers + const pageNumberNodes = paginationChildren[currentPaginationChild].children + expect(pageNumberNodes.length).toEqual(pagination.items.length) + + pagination.items.forEach((item, index) => { + if (item.ellipsis) { + expect(pageNumberNodes[index].textContent).toEqual(' ⋯ ') + } else { + expect(pageNumberNodes[index].children[0].href).toEqual(item.href) + expect(pageNumberNodes[index].children[0].textContent).toEqual(` ${item.number} `) + if (item.current) { + expect(pageNumberNodes[index].className).toContain('current') + } else { + expect(pageNumberNodes[index].className).not.toContain('current') + } + } + }) + currentPaginationChild++ + + // next link + if (pagination.nextPage) { + expect(paginationChildren[currentPaginationChild].children[0].href).toEqual(`/results/${id}/${pagination.nextPage}`) + currentPaginationChild++ + } + + expect(paginationChildren.length).toEqual(currentPaginationChild) +} + export default paginationTests From 2c9a3832be17f4261b7136f0eb506f1b1bbedd61 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 11:58:54 +0100 Subject: [PATCH 119/127] make sure submit is using the correct start template --- src/routes/form-wizard/check/steps.js | 2 +- src/routes/form-wizard/endpoint-submission-form/steps.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/form-wizard/check/steps.js b/src/routes/form-wizard/check/steps.js index eee307c8..99a0ed5c 100644 --- a/src/routes/form-wizard/check/steps.js +++ b/src/routes/form-wizard/check/steps.js @@ -17,7 +17,7 @@ export default { entryPoint: true, resetJourney: true, next: 'dataset', - template: '../views/check/start.html', + template: 'check/start.html', noPost: true }, // '/data-subject': { diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js index 6295d0d2..742e6c00 100644 --- a/src/routes/form-wizard/endpoint-submission-form/steps.js +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -14,7 +14,7 @@ export default { entryPoint: true, resetJourney: true, noPost: true, - template: 'start.html', + template: 'submit/start.html', next: '/submit/lpa-details' }, '/lpa-details': { From 58454207c970b3b07234bc38c6c7738bc1cc53b7 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 12:23:25 +0100 Subject: [PATCH 120/127] change start page to noPost --- src/routes/form-wizard/endpoint-submission-form/steps.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/form-wizard/endpoint-submission-form/steps.js b/src/routes/form-wizard/endpoint-submission-form/steps.js index 742e6c00..74639ed8 100644 --- a/src/routes/form-wizard/endpoint-submission-form/steps.js +++ b/src/routes/form-wizard/endpoint-submission-form/steps.js @@ -13,7 +13,6 @@ export default { ...defaultParams, entryPoint: true, resetJourney: true, - noPost: true, template: 'submit/start.html', next: '/submit/lpa-details' }, From 8fc9b8fe828393151ddef9720e848ed29e9168d0 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 12:23:39 +0100 Subject: [PATCH 121/127] add catch to error page render --- src/serverSetup/errorHandlers.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/serverSetup/errorHandlers.js b/src/serverSetup/errorHandlers.js index 03afe1cc..f0e89430 100644 --- a/src/serverSetup/errorHandlers.js +++ b/src/serverSetup/errorHandlers.js @@ -19,7 +19,11 @@ export function setupErrorHandlers (app) { } err.status = err.status || 500 - res.status(err.status).render(err.template, { err }) + try { + res.status(err.status).render(err.template, { err }) + } catch (e) { + res.status(err.status).render('errorPages/500', { err }) + } }) app.use((req, res, next) => { From e27b5b34b7828e5e3469531abc7e2c0027a6a784 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 15:43:13 +0100 Subject: [PATCH 122/127] update dev config --- config/development.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/development.yaml b/config/development.yaml index d3642e6c..a3e1f38a 100644 --- a/config/development.yaml +++ b/config/development.yaml @@ -1,5 +1,5 @@ asyncRequestApi: { - url: http://development-pub-async-api-lb-2117113766.eu-west-2.elb.amazonaws.com + url: http://development-pub-async-api-lb-69142969.eu-west-2.elb.amazonaws.com } aws: { region: eu-west-2, From 2efa0ed86d72249ceb95671842cedad9691320b8 Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 15:51:10 +0100 Subject: [PATCH 123/127] updated env example --- .env.example | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 19be47ec..2b017d22 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,4 @@ -SESSION_SECRET=your_secret \ No newline at end of file +SESSION_SECRET=your_secret +SENTRY_DSN=You_DSN +GOVUK_NOTIFY_API_KEY=your_api_key +DATA_MANAGEMENT_EMAIL=data_management_team_email_address \ No newline at end of file From 5962f67df0d3914bdd2667322b2a3c1981d9658a Mon Sep 17 00:00:00 2001 From: George Goodall Date: Tue, 9 Jul 2024 15:57:27 +0100 Subject: [PATCH 124/127] get email from environment --- .env.example | 2 +- src/controllers/CheckAnswersController.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 2b017d22..6e253a49 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ SESSION_SECRET=your_secret SENTRY_DSN=You_DSN GOVUK_NOTIFY_API_KEY=your_api_key -DATA_MANAGEMENT_EMAIL=data_management_team_email_address \ No newline at end of file +DATA_MANAGEMENT_EMAIL=data_management_team_email_address diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index 23392f2f..f47b7658 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -2,7 +2,7 @@ import PageController from './pageController.js' import notifyClient from '../utils/mailClient.js' import config from '../../config/index.js' -const dataManagementEmail = config.email.dataManagementEmail +const dataManagementEmail = process.env.DATA_MANAGEMENT_EMAIL || config.email.dataManagementEmail class CheckAnswersController extends PageController { /** From 035be4e6d1684b4bd1a62f3c81a843b8fd7b73ef Mon Sep 17 00:00:00 2001 From: George Goodall Date: Wed, 10 Jul 2024 11:38:19 +0100 Subject: [PATCH 125/127] fix unit tests --- test/unit/lpaDetailsController.test.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/test/unit/lpaDetailsController.test.js b/test/unit/lpaDetailsController.test.js index d3bb2b80..21355a83 100644 --- a/test/unit/lpaDetailsController.test.js +++ b/test/unit/lpaDetailsController.test.js @@ -1,17 +1,19 @@ /* eslint-disable no-import-assign */ +/* eslint-disable new-cap */ -import LpaDetailsController from '../../src/controllers/lpaDetailsController.js' -import { fetchLocalAuthorities } from '../../src/utils/fetchLocalAuthorities' import PageController from '../../src/controllers/pageController.js' import { vi, it, describe, expect, beforeEach, afterEach } from 'vitest' vi.mock('../../src/utils/fetchLocalAuthorities.js') -describe('lpaDetailsController', () => { +describe('lpaDetailsController', async () => { + let fetchLocalAuthorities let controller - beforeEach(() => { - controller = new LpaDetailsController({ + beforeEach(async () => { + fetchLocalAuthorities = await import('../../src/utils/fetchLocalAuthorities') + const LpaDetailsController = await import('../../src/controllers/lpaDetailsController.js') + controller = new LpaDetailsController.default({ route: '/lpa-details' }) }) @@ -31,11 +33,12 @@ describe('lpaDetailsController', () => { const next = vi.fn() const localAuthoritiesNames = ['Authority 1', 'Authority 2'] - fetchLocalAuthorities = vi.fn().mockResolvedValue(localAuthoritiesNames) + + fetchLocalAuthorities.fetchLocalAuthorities = vi.fn().mockResolvedValue(localAuthoritiesNames) await controller.locals(req, res, next) - expect(fetchLocalAuthorities).toHaveBeenCalled() + expect(fetchLocalAuthorities.fetchLocalAuthorities).toHaveBeenCalled() expect(req.form.options.localAuthorities).toEqual([ { text: 'Authority 1', value: 'Authority 1' }, { text: 'Authority 2', value: 'Authority 2' } @@ -52,7 +55,7 @@ describe('lpaDetailsController', () => { const res = {} const next = vi.fn() - fetchLocalAuthorities = vi.fn().mockResolvedValue([]) + fetchLocalAuthorities.fetchLocalAuthorities = vi.fn().mockResolvedValue([]) const superLocalsSpy = vi.spyOn(PageController.prototype, 'locals') await controller.locals(req, res, next) From b6e02a7be34f3e8b2e1f3fee422034ba5636d97b Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Wed, 10 Jul 2024 12:05:00 +0100 Subject: [PATCH 126/127] add vite (missing dev dep) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 5e2f70b1..3bf45e1b 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "nodemon": "^3.0.1", "standard": "^17.1.0", "supertest": "^7.0.0", + "vite": "^5.3.3", "vitest": "^0.34.6", "webpack": "^5.90.3", "webpack-cli": "^5.1.4", From afdd200e84f721c159cc6b32236bcb7652f8d848 Mon Sep 17 00:00:00 2001 From: Roland Sadowski Date: Wed, 10 Jul 2024 12:08:19 +0100 Subject: [PATCH 127/127] form submission: error handling and logging for email notifications --- src/controllers/CheckAnswersController.js | 92 ++++++++++++++--------- test/unit/check-answers.test.js | 2 +- test/unit/checkAnswersController.test.js | 88 ++++++++++++---------- 3 files changed, 108 insertions(+), 74 deletions(-) diff --git a/src/controllers/CheckAnswersController.js b/src/controllers/CheckAnswersController.js index f47b7658..22766cbe 100644 --- a/src/controllers/CheckAnswersController.js +++ b/src/controllers/CheckAnswersController.js @@ -14,14 +14,25 @@ class CheckAnswersController extends PageController { * @param {Object} req - The HTTP request object. * @param {Object} res - The HTTP response object. * @param {Function} next - The next middleware function. - */ - post (req, res, next) { - this.sendEmails(req, res, next) + */ + async post (req, res, next) { + const result = await this.sendEmails(req, res, next) + for (const err of (result.errors ?? [])) { + console.error(err) + } super.post(req, res, next) } - sendEmails (req, res, next) { + /** + * Attempts to send email notifications. + * + * @param {*} req + * @param {*} res + * @param {*} next + * @returns {Promise<{} | {errors: string[]}>} + */ + async sendEmails (req, res, next) { const name = req.sessionModel.get('name') const email = req.sessionModel.get('email') const organisation = req.sessionModel.get('lpa') @@ -29,39 +40,52 @@ class CheckAnswersController extends PageController { const documentationUrl = req.sessionModel.get('documentation-url') const endpoint = req.sessionModel.get('endpoint-url') - const { RequestTemplateId, AcknowledgementTemplateId } = config.email.templates - - // ToDo: handle errors when sending emails - notifyClient.sendEmail( - RequestTemplateId, - dataManagementEmail, - { - personalisation: { - name, - email, - organisation, - endpoint, - 'documentation-url': documentationUrl, - dataset - } - } - ) + const { RequestTemplateId, AcknowledgementTemplateId } = + config.email.templates - notifyClient.sendEmail( - AcknowledgementTemplateId, + const personalisation = { + name, email, - { - personalisation: { - name, - email, - organisation, - endpoint, - 'documentation-url': documentationUrl, - dataset - } - } - ) + organisation, + endpoint, + 'documentation-url': documentationUrl, + dataset + } + + const [reqResult, ackResult] = await Promise.allSettled([ + notifyClient.sendEmail(RequestTemplateId, dataManagementEmail, { + personalisation + }), + notifyClient.sendEmail(AcknowledgementTemplateId, email, { + personalisation + }) + ]) + + const errors = [] + if (reqResult.status === 'rejected') { + const msg = emailFailureMessage(RequestTemplateId, personalisation) + errors.push(msg) + } + if (ackResult.status === 'rejected') { + const msg = emailFailureMessage(AcknowledgementTemplateId, personalisation) + errors.push(msg) + } + + if (errors.length !== 0) { + return { errors } + } + return {} } } +/** + * + * @param {string} templateId + * @param {{organisation: string, name: string, email: string}} metadata + * @returns + */ +function emailFailureMessage (templateId, { organisation, name, email }) { + return `Failed to send email template=${templateId} to (org: ${organisation}, name: ${name}, email: ${email}):` +} + export default CheckAnswersController diff --git a/test/unit/check-answers.test.js b/test/unit/check-answers.test.js index 75978127..69f505dc 100644 --- a/test/unit/check-answers.test.js +++ b/test/unit/check-answers.test.js @@ -7,7 +7,7 @@ import config from '../../config/index.js' import { stripWhitespace } from '../utils/stripWhiteSpace.js' import { mockDataSubjects } from './data.js' -describe('check-answers View', () => { +describe('check-answers View', async () => { const params = { values: { lpa: 'mockLpa', diff --git a/test/unit/checkAnswersController.test.js b/test/unit/checkAnswersController.test.js index 9a6ae6b1..f0988183 100644 --- a/test/unit/checkAnswersController.test.js +++ b/test/unit/checkAnswersController.test.js @@ -6,7 +6,41 @@ import config from '../../config/index.js' vi.mock('../../src/utils/mailClient.js') -describe('Check answers controller', () => { +function makeRequest () { + return { + sessionModel: { + get: vi.fn().mockImplementation((key) => { + const values = { + name: 'John Doe', + email: 'JohnDoe@mail.com', + lpa: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + 'endpoint-url': 'Endpoint URL' + } + return values[key] + }) + } + } +} + +describe('Handle email notification handlers', async () => { + const CheckAnswersController = await vi.importActual('../../src/controllers/CheckAnswersController.js') + const sendEmailMock = vi.fn(() => Promise.reject(new Error('something went wrong'))) + notifyClient.sendEmail = sendEmailMock + + const controller = new CheckAnswersController.default({ route: '/dataset' }) + const req = makeRequest() + const res = {} + const next = vi.fn() + + it('should reuturn list of errors when failed to send email', async () => { + const result = await controller.sendEmails(req, res, next) + expect(result.errors.length).toBe(2) + }) +}) + +describe('Check answers controller', async () => { let CheckAnswersController let checkAnswersController let sendEmailMock @@ -22,57 +56,33 @@ describe('Check answers controller', () => { }) describe('send emails', () => { - it('should get the values from the session model and then send the request and acknowledgement emails', () => { + it('should get the values from the session model and then send the request and acknowledgement emails', async () => { // Mock req, res, next - const req = { - sessionModel: { - get: vi.fn().mockImplementation((key) => { - const values = { - name: 'John Doe', - email: 'JohnDoe@mail.com', - lpa: 'LPA', - dataset: 'Dataset', - 'documentation-url': 'Documentation URL', - 'endpoint-url': 'Endpoint URL' - } - return values[key] - }) - } - } - + const req = makeRequest() const res = {} const next = vi.fn() - checkAnswersController.sendEmails(req, res, next) + await checkAnswersController.sendEmails(req, res, next) + + const personalisation = { + name: 'John Doe', + email: 'JohnDoe@mail.com', + organisation: 'LPA', + dataset: 'Dataset', + 'documentation-url': 'Documentation URL', + endpoint: 'Endpoint URL' + } expect(sendEmailMock).toHaveBeenCalledWith( config.email.templates.RequestTemplateId, config.email.dataManagementEmail, - { - personalisation: { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - dataset: 'Dataset', - 'documentation-url': 'Documentation URL', - endpoint: 'Endpoint URL' - } - } + { personalisation } ) expect(sendEmailMock).toHaveBeenCalledWith( config.email.templates.AcknowledgementTemplateId, 'JohnDoe@mail.com', - { - personalisation: { - name: 'John Doe', - email: 'JohnDoe@mail.com', - organisation: 'LPA', - endpoint: 'Endpoint URL', - 'documentation-url': 'Documentation URL', - dataset: 'Dataset' - } - } + { personalisation } ) }) })

{{field}}{{column}}
id geometry name Layer area(ha) entry-date start-date documentation-url
id wkt name Layer area(ha) entry-date start-date documentation-url
4

POLYGON ((-0.2 4153471441223381 51.64678234555299,-0.24153451533341586 51.64678375436429,-0.24153402837267088 51.646785131884954,-0.24153328311827696 51.64678646057366,-0.2415322658196911 51.64678772223974,-0.24153100606519867 51.6467888993419,-0.24152951934469136 51.64678996513527,-0.24152782080019092 51.64679090186209,-0.241525953770536 51.646791710171776,-0.24152394853978726 51.646792354548786,-0.241521819206364 51.64679284419671,-0.24151960980486648 51.64679316179073,-0.241517349227872 51.646793307763815,-0.24151508116211567 51.64679327377821,-0.24151283450017486 51.64679306026688,-0.24151065223303 51.64679267686634,-0.24150856325325645 51.64679212400957,-0.2415066102039489 51.646791420320184,-0.24150480787927503 51.64679055702751,-0.24150318378028418 51.64678957051299,-0.24150178124580876 51.64678846142601,-0.2415006140263633 51.64678724795729,-0.24149969552458145 51.64678595728458,-0.24149905393724236 51.646784607815064,-0.2414986741222941 51.64678321730649,-0.24149859872278576 51.64678180438247,-0.24149878335623448 51.64678039535491,-0.24149927031780533 51.64677901783456,-0.24150001557289963 51.646777689146184,-0.24150103287201724 51.64677642748049,-0.24150229262683906 51.64677525037871,-0.24150377934745013 51.64677418458572,-0.24150547789181703 51.64677324785923,-0.24150734457324669 51.64677244853694,-0.24150935015132094 51.64677179517301,-0.24151147948402624 51.64677130552519,-0.2415136888846846 51.64677098793116,-0.24151594911289265 51.646770850945124,-0.2415182171777299 51.64677088493055,-0.24152046418667236 51.64677108945449,-0.24152264645304639 51.64677147285469,-0.24152473543219838 51.6467720257111,-0.24152668813319955 51.64677273838721,-0.24152849080553268 51.64677359269237,-0.2415301149045335 51.64677457920655,-0.24153151743925044 51.64677568829322,-0.2415326846591531 51.646776901761726,-0.24153360316157546 51.64677819243428,-0.24153424474969987 51.64677954190374,-0.24153462456552752 51.64678093241235,-0.24153471441223381 51.64678234555299))

Geometry must be in Well Known Text (WKT) format

South Jesmond Conservation Area 35.4

04/04/2025

Entry date must be today or in the past

04/04/2024

www. example.com

Documentation URL must be a real URL

id geometry name Layer area(ha) entry-date start-date documentation-url
id wkt name Layer area(ha) entry-date start-date documentation-url
4 POLYGON ((-0.2 4153471441223381 51.64678234555299,-0.24153451533341586 51.64678375436429,-0.24153402837267088 51.646785131884954,-0.24153328311827696 51.64678646057366,-0.2415322658196911 51.64678772223974,-0.24153100606519867 51.6467888993419,-0.24152951934469136 51.64678996513527,-0.24152782080019092 51.64679090186209,-0.241525953770536 51.646791710171776,-0.24152394853978726 51.646792354548786,-0.241521819206364 51.64679284419671,-0.24151960980486648 51.64679316179073,-0.241517349227872 51.646793307763815,-0.24151508116211567 51.64679327377821,-0.24151283450017486 51.64679306026688,-0.24151065223303 51.64679267686634,-0.24150856325325645 51.64679212400957,-0.2415066102039489 51.646791420320184,-0.24150480787927503 51.64679055702751,-0.24150318378028418 51.64678957051299,-0.24150178124580876 51.64678846142601,-0.2415006140263633 51.64678724795729,-0.24149969552458145 51.64678595728458,-0.24149905393724236 51.646784607815064,-0.2414986741222941 51.64678321730649,-0.24149859872278576 51.64678180438247,-0.24149878335623448 51.64678039535491,-0.24149927031780533 51.64677901783456,-0.24150001557289963 51.646777689146184,-0.24150103287201724 51.64677642748049,-0.24150229262683906 51.64677525037871,-0.24150377934745013 51.64677418458572,-0.24150547789181703 51.64677324785923,-0.24150734457324669 51.64677244853694,-0.24150935015132094 51.64677179517301,-0.24151147948402624 51.64677130552519,-0.2415136888846846 51.64677098793116,-0.24151594911289265 51.646770850945124,-0.2415182171777299 51.64677088493055,-0.24152046418667236 51.64677108945449,-0.24152264645304639 51.64677147285469,-0.24152473543219838 51.6467720257111,-0.24152668813319955 51.64677273838721,-0.24152849080553268 51.64677359269237,-0.2415301149045335 51.64677457920655,-0.24153151743925044 51.64677568829322,-0.2415326846591531 51.646776901761726,-0.24153360316157546 51.64677819243428,-0.24153424474969987 51.64677954190374,-0.24153462456552752 51.64678093241235,-0.24153471441223381 51.64678234555299)) South Jesmond Conservation Area 35.4 04/04/2025 04/04/2024 www. example.com
6 POLYGON ((-0.24153471441223381 51.64678234555299,-0.24153451533341586 51.64678375436429,-0.24153402837267088 51.646785131884954,-0.24153328311827696 51.64678646057366,-0.2415322658196911 51.64678772223974,-0.24153100606519867 51.6467888993419,-0.24152951934469136 51.64678996513527,-0.24152782080019092 51.64679090186209,-0.241525953770536 51.646791710171776,-0.24152394853978726 51.646792354548786,-0.241521819206364 51.64679284419671,-0.24151960980486648 51.64679316179073,-0.241517349227872 51.646793307763815,-0.24151508116211567 51.64679327377821,-0.24151283450017486 51.64679306026688,-0.24151065223303 51.64679267686634,-0.24150856325325645 51.64679212400957,-0.2415066102039489 51.646791420320184,-0.24150480787927503 51.64679055702751,-0.24150318378028418 51.64678957051299,-0.24150178124580876 51.64678846142601,-0.2415006140263633 51.64678724795729,-0.24149969552458145 51.64678595728458,-0.24149905393724236 51.646784607815064,-0.2414986741222941 51.64678321730649,-0.24149859872278576 51.64678180438247,-0.24149878335623448 51.64678039535491,-0.24149927031780533 51.64677901783456,-0.24150001557289963 51.646777689146184,-0.24150103287201724 51.64677642748049,-0.24150229262683906 51.64677525037871,-0.24150377934745013 51.64677418458572,-0.24150547789181703 51.64677324785923,-0.24150734457324669 51.64677244853694,-0.24150935015132094 51.64677179517301,-0.24151147948402624 51.64677130552519,-0.2415136888846846 51.64677098793116,-0.24151594911289265 51.646770850945124,-0.2415182171777299 51.64677088493055,-0.24152046418667236 51.64677108945449,-0.24152264645304639 51.64677147285469,-0.24152473543219838 51.6467720257111,-0.24152668813319955 51.64677273838721,-0.24152849080553268 51.64677359269237,-0.2415301149045335 51.64677457920655,-0.24153151743925044 51.64677568829322,-0.2415326846591531 51.646776901761726,-0.24153360316157546 51.64677819243428,-0.24153424474969987 51.64677954190374,-0.24153462456552752 51.64678093241235,-0.24153471441223381 51.64678234555299)) Northumberland Gardens Conservation Area 6.2 04/04/2024 https://www.newcastle.gov.uk/services/planning-building-and-development/historic-enviornment-and-urban-design/conservation-areas