@defra/forms-engine-plugin 4.7.3 → 4.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.public/javascripts/shared.min.js +1 -1
- package/.public/javascripts/shared.min.js.map +1 -1
- package/.server/client/javascripts/map.d.ts +4 -0
- package/.server/client/javascripts/map.js +9 -1
- package/.server/client/javascripts/map.js.map +1 -1
- package/.server/server/forms/payment-v2-test.yaml +341 -0
- package/.server/server/plugins/engine/components/PaymentField.d.ts +7 -0
- package/.server/server/plugins/engine/components/PaymentField.js +58 -6
- package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.d.ts +2 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js +2 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +24 -2
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.d.ts +10 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +57 -13
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/errors.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/errors.js +2 -2
- package/.server/server/plugins/engine/pageControllers/errors.js.map +1 -1
- package/.server/server/plugins/engine/routes/index.js +5 -2
- package/.server/server/plugins/engine/routes/index.js.map +1 -1
- package/.server/server/plugins/engine/routes/payment.js +6 -1
- package/.server/server/plugins/engine/routes/payment.js.map +1 -1
- package/.server/server/plugins/engine/routes/payment.test.js +3 -3
- package/.server/server/plugins/engine/routes/payment.test.js.map +1 -1
- package/.server/server/plugins/engine/services/localFormsService.js +6 -0
- package/.server/server/plugins/engine/services/localFormsService.js.map +1 -1
- package/.server/server/plugins/engine/views/summary.html +2 -1
- package/.server/server/plugins/map/routes/vts/esri-aerial.json +23 -0
- package/.server/server/plugins/payment/service.d.ts +2 -1
- package/.server/server/plugins/payment/service.js +11 -3
- package/.server/server/plugins/payment/service.js.map +1 -1
- package/.server/server/plugins/payment/types.d.ts +4 -0
- package/.server/server/plugins/payment/types.js +1 -0
- package/.server/server/plugins/payment/types.js.map +1 -1
- package/package.json +2 -2
- package/src/client/javascripts/map.js +10 -1
- package/src/server/forms/payment-v2-test.yaml +341 -0
- package/src/server/plugins/engine/components/PaymentField.ts +70 -6
- package/src/server/plugins/engine/models/SummaryViewModel.ts +2 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +32 -1
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +99 -17
- package/src/server/plugins/engine/pageControllers/errors.ts +2 -2
- package/src/server/plugins/engine/routes/index.ts +9 -2
- package/src/server/plugins/engine/routes/payment.js +7 -1
- package/src/server/plugins/engine/services/localFormsService.js +7 -0
- package/src/server/plugins/engine/views/summary.html +2 -1
- package/src/server/plugins/map/routes/vts/esri-aerial.json +23 -0
- package/src/server/plugins/payment/service.js +13 -3
- package/src/server/plugins/payment/types.js +1 -0
|
@@ -11,7 +11,8 @@ const COMPANY_SYMBOL_CODE = 169;
|
|
|
11
11
|
const defaultData = {
|
|
12
12
|
VTS_OUTDOOR_URL: '/api/maps/vts/OS_VTS_3857_Outdoor.json',
|
|
13
13
|
VTS_DARK_URL: '/api/maps/vts/OS_VTS_3857_Dark.json',
|
|
14
|
-
VTS_BLACK_AND_WHITE_URL: '/api/maps/vts/OS_VTS_3857_Black_and_White.json'
|
|
14
|
+
VTS_BLACK_AND_WHITE_URL: '/api/maps/vts/OS_VTS_3857_Black_and_White.json',
|
|
15
|
+
VTS_AERIAL_URL: '/api/maps/vts/esri-aerial.json'
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -315,6 +316,12 @@ export function createMap(mapId, initConfig, mapsConfig) {
|
|
|
315
316
|
logo: `${assetPath}/interactive-map/assets/images/os-logo-black.svg`,
|
|
316
317
|
logoAltText,
|
|
317
318
|
attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`
|
|
319
|
+
}, {
|
|
320
|
+
id: 'aerial',
|
|
321
|
+
label: 'Aerial',
|
|
322
|
+
url: data.VTS_AERIAL_URL,
|
|
323
|
+
thumbnail: `${assetPath}/interactive-map/assets/images/aerial-map-thumb.jpg`,
|
|
324
|
+
attribution: `Tiles ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Esri — Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community ${new Date().getFullYear()}`
|
|
318
325
|
}]
|
|
319
326
|
}), interactPlugin, defra.searchPlugin({
|
|
320
327
|
transformRequest: transformGeocodeRequest,
|
|
@@ -382,6 +389,7 @@ export function centerMap(map, mapProvider, center) {
|
|
|
382
389
|
* @property {string} VTS_OUTDOOR_URL - the outdoor tile URL
|
|
383
390
|
* @property {string} VTS_DARK_URL - the dark tile URL
|
|
384
391
|
* @property {string} VTS_BLACK_AND_WHITE_URL - the black and white tile URL
|
|
392
|
+
* @property {string} VTS_AERIAL_URL - the aerial tile URL
|
|
385
393
|
*/
|
|
386
394
|
|
|
387
395
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.js","names":["centroid","OsGridRef","LatLon","processGeospatial","processLocation","DEFAULT_LAT","DEFAULT_LONG","COMPANY_SYMBOL_CODE","defaultData","VTS_OUTDOOR_URL","VTS_DARK_URL","VTS_BLACK_AND_WHITE_URL","latLongToEastingNorthing","lat","long","point","toOsGrid","eastingNorthingToLatLong","easting","northing","latLong","toLatLon","latitude","longitude","latLongToOsGridRef","toString","osGridRefToLatLong","osGridRef","parse","getCoordinateGridRef","feature","geometry","type","coordinates","getCentroidGridRef","centre","defaultConfig","zoom","center","EVENTS","mapReady","interactMarkerChange","drawReady","drawCreated","drawEdited","drawCancelled","formSubmitFactory","buttons","onFormSubmit","e","submitter","HTMLButtonElement","includes","preventDefault","initMaps","config","assetPath","apiPath","data","locations","document","querySelectorAll","geospatials","length","form","closest","Array","from","addEventListener","forEach","location","index","geospatial","makeTileRequestTransformer","transformTileRequest","url","resourceType","startsWith","replace","window","origin","headers","encodeURIComponent","spritesPath","path","substring","transformGeocodeRequest","request","URL","Request","options","createMap","mapId","initConfig","mapsConfig","logoAltText","defra","interactPlugin","markerColor","outdoor","dark","interactionMode","multiSelect","map","InteractiveMap","enableFullscreen","autoColorScheme","mapProvider","maplibreProvider","reverseGeocodeProvider","openNamesProvider","behaviour","minZoom","maxZoom","containerHeight","enableZoomControls","transformRequest","plugins","mapStylesPlugin","mapStyles","id","label","thumbnail","logo","attribution","String","fromCodePoint","Date","getFullYear","backgroundColor","mapColorScheme","appColorScheme","searchPlugin","osNamesURL","width","showMarker","scaleBarPlugin","units","centerMap","addMarker","flyTo","essential"],"sources":["../../../src/client/javascripts/map.js"],"sourcesContent":["import { centroid } from '@turf/centroid'\n// @ts-expect-error - no types\nimport OsGridRef, { LatLon } from 'geodesy/osgridref.js'\n\nimport { processGeospatial } from '~/src/client/javascripts/geospatial-map.js'\nimport { processLocation } from '~/src/client/javascripts/location-map.js'\n\n// Center of UK\nconst DEFAULT_LAT = 53.825564\nconst DEFAULT_LONG = -2.421975\nconst COMPANY_SYMBOL_CODE = 169\n\nconst defaultData = {\n VTS_OUTDOOR_URL: '/api/maps/vts/OS_VTS_3857_Outdoor.json',\n VTS_DARK_URL: '/api/maps/vts/OS_VTS_3857_Dark.json',\n VTS_BLACK_AND_WHITE_URL: '/api/maps/vts/OS_VTS_3857_Black_and_White.json'\n}\n\n/**\n * Converts lat long to easting and northing\n * @param {object} param\n * @param {number} param.lat\n * @param {number} param.long\n * @returns {{ easting: number, northing: number }}\n */\nexport function latLongToEastingNorthing({ lat, long }) {\n const point = new LatLon(lat, long)\n\n return point.toOsGrid()\n}\n\n/**\n * Converts easting and northing to lat long\n * @param {object} param\n * @param {number} param.easting\n * @param {number} param.northing\n * @returns {{ lat: number, long: number }}\n */\nexport function eastingNorthingToLatLong({ easting, northing }) {\n const point = new OsGridRef(easting, northing)\n const latLong = point.toLatLon()\n\n return { lat: latLong.latitude, long: latLong.longitude }\n}\n\n/**\n * Converts lat long to an ordnance survey grid reference\n * @param {object} param\n * @param {number} param.lat\n * @param {number} param.long\n * @returns {string}\n */\nexport function latLongToOsGridRef({ lat, long }) {\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n}\n\n/**\n * Converts an ordnance survey grid reference to lat long\n * @param {string} osGridRef\n * @returns {{ lat: number, long: number }}\n */\nexport function osGridRefToLatLong(osGridRef) {\n const point = OsGridRef.parse(osGridRef)\n const latLong = point.toLatLon()\n\n return { lat: latLong.latitude, long: latLong.longitude }\n}\n\n/**\n * Get the grid ref from the first coordinate of a long/lat feature\n * @param {Feature} feature\n */\nexport function getCoordinateGridRef(feature) {\n if (feature.geometry.type === 'Point') {\n const [long, lat] = feature.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else if (feature.geometry.type === 'LineString') {\n const [long, lat] = feature.geometry.coordinates[0]\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else {\n const [long, lat] = feature.geometry.coordinates[0][0]\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n }\n}\n\n/**\n * Get the centroid grid ref from a long/lat feature\n * @param {Feature} feature\n */\nexport function getCentroidGridRef(feature) {\n if (feature.geometry.type === 'Point') {\n const [long, lat] = feature.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else {\n const centre = centroid(feature)\n const [long, lat] = centre.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n }\n}\n\n/** @type {InteractiveMapInitConfig} */\nexport const defaultConfig = {\n zoom: '6',\n center: [DEFAULT_LONG, DEFAULT_LAT]\n}\n\nexport const EVENTS = {\n mapReady: 'map:ready',\n interactMarkerChange: 'interact:markerchange',\n drawReady: 'draw:ready',\n drawCreated: 'draw:created',\n drawEdited: 'draw:edited',\n drawCancelled: 'draw:cancelled'\n}\n\n/**\n * Make a form submit handler that only allows submissions from allowed buttons\n * @param {HTMLButtonElement[]} buttons - the form buttons to allow submissions\n */\nexport function formSubmitFactory(buttons) {\n /**\n * The submit handler\n * @param {SubmitEvent} e\n */\n const onFormSubmit = function (e) {\n if (\n !(e.submitter instanceof HTMLButtonElement) ||\n !buttons.includes(e.submitter)\n ) {\n e.preventDefault()\n }\n }\n\n return onFormSubmit\n}\n\n/**\n * Initialise location maps\n * @param {Partial<MapsEnvironmentConfig>} config - the map configuration\n */\nexport function initMaps(config = {}) {\n const {\n assetPath = '/assets',\n apiPath = '/form/api',\n data = defaultData\n } = config\n const locations = document.querySelectorAll('.app-location-field')\n const geospatials = document.querySelectorAll('.app-geospatial-field')\n\n // TODO: Fix this in `interactive-map`\n // If there are location components on the page fix up the main form submit\n // handler so it doesn't fire when using the integrated map search feature\n if (locations.length) {\n const form = locations[0].closest('form')\n\n if (form === null) {\n return\n }\n\n const buttons = Array.from(form.querySelectorAll('button'))\n form.addEventListener('submit', formSubmitFactory(buttons), false)\n }\n\n if (geospatials.length) {\n const form = geospatials[0].closest('form')\n\n if (form === null) {\n return\n }\n\n const buttons = Array.from(form.querySelectorAll('button'))\n form.addEventListener('submit', formSubmitFactory(buttons), false)\n }\n\n locations.forEach((location, index) => {\n processLocation({ assetPath, apiPath, data }, location, index)\n })\n\n geospatials.forEach((geospatial, index) => {\n processGeospatial({ assetPath, apiPath, data }, geospatial, index)\n })\n}\n\n/**\n * OS API request proxy factory\n * @param {string} apiPath - the root API path\n */\nexport function makeTileRequestTransformer(apiPath) {\n /**\n * Proxy OS API requests via our server\n * @param {string} url - the request URL\n * @param {string} resourceType - the resource type\n */\n return function transformTileRequest(url, resourceType) {\n if (url.startsWith('https://api.os.uk')) {\n if (resourceType === 'Tile') {\n return {\n url: url.replace(\n 'https://api.os.uk/maps/vector/v1/vts',\n `${window.location.origin}${apiPath}`\n ),\n headers: {}\n }\n }\n\n if (resourceType !== 'Style') {\n return {\n url: `${apiPath}/map-proxy?url=${encodeURIComponent(url)}`,\n headers: {}\n }\n }\n }\n\n const spritesPath =\n 'https://raw.githubusercontent.com/OrdnanceSurvey/OS-Vector-Tile-API-Stylesheets/main'\n\n // Proxy sprite requests\n if (url.startsWith(spritesPath)) {\n const path = url.substring(spritesPath.length)\n return {\n url: `${apiPath}/maps/vts${path}`,\n headers: {}\n }\n }\n\n return { url, headers: {} }\n }\n}\n\n/**\n * Temporary transform request function to transform geocode requests. Fixed in v0.0.18 of interactive map so this is not needed when we upgrade.\n * @param {object} request\n * @param {string} request.url\n * @param {{ method: 'get' }} request.options\n * @returns {Request}\n */\nexport const transformGeocodeRequest = (request) => {\n const url = new URL(request.url, window.location.origin)\n return new Request(url.toString(), request.options)\n}\n\n/**\n * Create a Defra map instance\n * @param {string} mapId - the map id\n * @param {InteractiveMapInitConfig} initConfig - the map initial configuration\n * @param {MapsEnvironmentConfig} mapsConfig - the map environment params\n */\nexport function createMap(mapId, initConfig, mapsConfig) {\n const { assetPath, apiPath, data = defaultData } = mapsConfig\n const logoAltText = 'Ordnance survey logo'\n\n // @ts-expect-error - Defra namespace currently comes from UMD support files\n const defra = window.defra\n\n const interactPlugin = defra.interactPlugin({\n markerColor: { outdoor: '#ff0000', dark: '#00ff00' },\n interactionMode: 'marker',\n multiSelect: false\n })\n\n /** @type {InteractiveMap} */\n const map = new defra.InteractiveMap(mapId, {\n enableFullscreen: true,\n autoColorScheme: false,\n mapProvider: defra.maplibreProvider(),\n reverseGeocodeProvider: defra.openNamesProvider({\n url: `${apiPath}/reverse-geocode-proxy?easting={easting}&northing={northing}`\n }),\n behaviour: 'inline',\n minZoom: 6,\n maxZoom: 18,\n containerHeight: '400px',\n enableZoomControls: true,\n transformRequest: makeTileRequestTransformer(apiPath),\n ...initConfig,\n plugins: [\n defra.mapStylesPlugin({\n mapStyles: [\n {\n id: 'outdoor',\n label: 'Outdoor',\n url: data.VTS_OUTDOOR_URL,\n thumbnail: `${assetPath}/interactive-map/assets/images/outdoor-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`,\n backgroundColor: '#f5f5f0'\n },\n {\n id: 'dark',\n label: 'Dark',\n url: data.VTS_DARK_URL,\n mapColorScheme: 'dark',\n appColorScheme: 'dark',\n thumbnail: `${assetPath}/interactive-map/assets/images/dark-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo-white.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`\n },\n {\n id: 'black-and-white',\n label: 'Black/White',\n url: data.VTS_BLACK_AND_WHITE_URL,\n thumbnail: `${assetPath}/interactive-map/assets/images/black-and-white-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo-black.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`\n }\n ]\n }),\n interactPlugin,\n defra.searchPlugin({\n transformRequest: transformGeocodeRequest,\n osNamesURL: `${apiPath}/geocode-proxy?query={query}`,\n width: '300px',\n showMarker: false\n }),\n defra.scaleBarPlugin({\n units: 'metric'\n }),\n ...(initConfig.plugins ?? [])\n ]\n })\n\n return { map, interactPlugin }\n}\n\n/**\n * Updates the marker position and moves the map view port the new location\n * @param {InteractiveMap} map - the map component instance (of InteractiveMap)\n * @param {MapLibreMap} mapProvider - the map provider instance (of MapLibreMap)\n * @param {MapCenter} center - the point\n */\nexport function centerMap(map, mapProvider, center) {\n // Move the 'location' marker to the new point\n map.addMarker('location', center)\n\n // Pan & zoom the map to the new valid location\n mapProvider.flyTo({\n center,\n zoom: 14,\n essential: true\n })\n}\n\n/**\n * @typedef {object} InteractiveMap - an instance of a InteractiveMap\n * @property {Function} on - register callback listeners to map events\n * @property {Function} addPanel - adds a new panel to the map\n * @property {Function} addMarker - adds/updates a marker\n * @property {Function} removeMarker - removes a marker\n * @property {Function} addButton - adds/updates a button\n * @property {Function} toggleButtonState - toggle the state of a button\n */\n\n/**\n * @typedef {object} MapLibreMap\n * @property {Function} flyTo - pans/zooms to a new location\n * @property {Function} fitBounds - fits the my to the new bounds\n */\n\n/**\n * @typedef {[number, number]} MapCenter - Map center point as [long, lat]\n */\n\n/**\n * @typedef {object} InteractiveMapInitConfig - additional config that can be provided to InteractiveMap\n * @property {string} zoom - the zoom level of the map\n * @property {MapCenter} center - the center point of the map\n * @property {{ id: string, coords: MapCenter }[]} [markers] - the markers to add to the map\n * @property {any[]} [plugins] - additional plugins\n */\n\n/**\n * @typedef {object} TileData\n * @property {string} VTS_OUTDOOR_URL - the outdoor tile URL\n * @property {string} VTS_DARK_URL - the dark tile URL\n * @property {string} VTS_BLACK_AND_WHITE_URL - the black and white tile URL\n */\n\n/**\n * @typedef {object} MapsEnvironmentConfig\n * @property {string} assetPath - the root asset path\n * @property {string} apiPath - the root API path\n * @property {TileData} data - the tile data config\n */\n\n/**\n * @import { Feature } from '~/src/server/plugins/engine/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"map.js","names":["centroid","OsGridRef","LatLon","processGeospatial","processLocation","DEFAULT_LAT","DEFAULT_LONG","COMPANY_SYMBOL_CODE","defaultData","VTS_OUTDOOR_URL","VTS_DARK_URL","VTS_BLACK_AND_WHITE_URL","VTS_AERIAL_URL","latLongToEastingNorthing","lat","long","point","toOsGrid","eastingNorthingToLatLong","easting","northing","latLong","toLatLon","latitude","longitude","latLongToOsGridRef","toString","osGridRefToLatLong","osGridRef","parse","getCoordinateGridRef","feature","geometry","type","coordinates","getCentroidGridRef","centre","defaultConfig","zoom","center","EVENTS","mapReady","interactMarkerChange","drawReady","drawCreated","drawEdited","drawCancelled","formSubmitFactory","buttons","onFormSubmit","e","submitter","HTMLButtonElement","includes","preventDefault","initMaps","config","assetPath","apiPath","data","locations","document","querySelectorAll","geospatials","length","form","closest","Array","from","addEventListener","forEach","location","index","geospatial","makeTileRequestTransformer","transformTileRequest","url","resourceType","startsWith","replace","window","origin","headers","encodeURIComponent","spritesPath","path","substring","transformGeocodeRequest","request","URL","Request","options","createMap","mapId","initConfig","mapsConfig","logoAltText","defra","interactPlugin","markerColor","outdoor","dark","interactionMode","multiSelect","map","InteractiveMap","enableFullscreen","autoColorScheme","mapProvider","maplibreProvider","reverseGeocodeProvider","openNamesProvider","behaviour","minZoom","maxZoom","containerHeight","enableZoomControls","transformRequest","plugins","mapStylesPlugin","mapStyles","id","label","thumbnail","logo","attribution","String","fromCodePoint","Date","getFullYear","backgroundColor","mapColorScheme","appColorScheme","searchPlugin","osNamesURL","width","showMarker","scaleBarPlugin","units","centerMap","addMarker","flyTo","essential"],"sources":["../../../src/client/javascripts/map.js"],"sourcesContent":["import { centroid } from '@turf/centroid'\n// @ts-expect-error - no types\nimport OsGridRef, { LatLon } from 'geodesy/osgridref.js'\n\nimport { processGeospatial } from '~/src/client/javascripts/geospatial-map.js'\nimport { processLocation } from '~/src/client/javascripts/location-map.js'\n\n// Center of UK\nconst DEFAULT_LAT = 53.825564\nconst DEFAULT_LONG = -2.421975\nconst COMPANY_SYMBOL_CODE = 169\n\nconst defaultData = {\n VTS_OUTDOOR_URL: '/api/maps/vts/OS_VTS_3857_Outdoor.json',\n VTS_DARK_URL: '/api/maps/vts/OS_VTS_3857_Dark.json',\n VTS_BLACK_AND_WHITE_URL: '/api/maps/vts/OS_VTS_3857_Black_and_White.json',\n VTS_AERIAL_URL: '/api/maps/vts/esri-aerial.json'\n}\n\n/**\n * Converts lat long to easting and northing\n * @param {object} param\n * @param {number} param.lat\n * @param {number} param.long\n * @returns {{ easting: number, northing: number }}\n */\nexport function latLongToEastingNorthing({ lat, long }) {\n const point = new LatLon(lat, long)\n\n return point.toOsGrid()\n}\n\n/**\n * Converts easting and northing to lat long\n * @param {object} param\n * @param {number} param.easting\n * @param {number} param.northing\n * @returns {{ lat: number, long: number }}\n */\nexport function eastingNorthingToLatLong({ easting, northing }) {\n const point = new OsGridRef(easting, northing)\n const latLong = point.toLatLon()\n\n return { lat: latLong.latitude, long: latLong.longitude }\n}\n\n/**\n * Converts lat long to an ordnance survey grid reference\n * @param {object} param\n * @param {number} param.lat\n * @param {number} param.long\n * @returns {string}\n */\nexport function latLongToOsGridRef({ lat, long }) {\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n}\n\n/**\n * Converts an ordnance survey grid reference to lat long\n * @param {string} osGridRef\n * @returns {{ lat: number, long: number }}\n */\nexport function osGridRefToLatLong(osGridRef) {\n const point = OsGridRef.parse(osGridRef)\n const latLong = point.toLatLon()\n\n return { lat: latLong.latitude, long: latLong.longitude }\n}\n\n/**\n * Get the grid ref from the first coordinate of a long/lat feature\n * @param {Feature} feature\n */\nexport function getCoordinateGridRef(feature) {\n if (feature.geometry.type === 'Point') {\n const [long, lat] = feature.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else if (feature.geometry.type === 'LineString') {\n const [long, lat] = feature.geometry.coordinates[0]\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else {\n const [long, lat] = feature.geometry.coordinates[0][0]\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n }\n}\n\n/**\n * Get the centroid grid ref from a long/lat feature\n * @param {Feature} feature\n */\nexport function getCentroidGridRef(feature) {\n if (feature.geometry.type === 'Point') {\n const [long, lat] = feature.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n } else {\n const centre = centroid(feature)\n const [long, lat] = centre.geometry.coordinates\n const point = new LatLon(lat, long)\n\n return point.toOsGrid().toString()\n }\n}\n\n/** @type {InteractiveMapInitConfig} */\nexport const defaultConfig = {\n zoom: '6',\n center: [DEFAULT_LONG, DEFAULT_LAT]\n}\n\nexport const EVENTS = {\n mapReady: 'map:ready',\n interactMarkerChange: 'interact:markerchange',\n drawReady: 'draw:ready',\n drawCreated: 'draw:created',\n drawEdited: 'draw:edited',\n drawCancelled: 'draw:cancelled'\n}\n\n/**\n * Make a form submit handler that only allows submissions from allowed buttons\n * @param {HTMLButtonElement[]} buttons - the form buttons to allow submissions\n */\nexport function formSubmitFactory(buttons) {\n /**\n * The submit handler\n * @param {SubmitEvent} e\n */\n const onFormSubmit = function (e) {\n if (\n !(e.submitter instanceof HTMLButtonElement) ||\n !buttons.includes(e.submitter)\n ) {\n e.preventDefault()\n }\n }\n\n return onFormSubmit\n}\n\n/**\n * Initialise location maps\n * @param {Partial<MapsEnvironmentConfig>} config - the map configuration\n */\nexport function initMaps(config = {}) {\n const {\n assetPath = '/assets',\n apiPath = '/form/api',\n data = defaultData\n } = config\n const locations = document.querySelectorAll('.app-location-field')\n const geospatials = document.querySelectorAll('.app-geospatial-field')\n\n // TODO: Fix this in `interactive-map`\n // If there are location components on the page fix up the main form submit\n // handler so it doesn't fire when using the integrated map search feature\n if (locations.length) {\n const form = locations[0].closest('form')\n\n if (form === null) {\n return\n }\n\n const buttons = Array.from(form.querySelectorAll('button'))\n form.addEventListener('submit', formSubmitFactory(buttons), false)\n }\n\n if (geospatials.length) {\n const form = geospatials[0].closest('form')\n\n if (form === null) {\n return\n }\n\n const buttons = Array.from(form.querySelectorAll('button'))\n form.addEventListener('submit', formSubmitFactory(buttons), false)\n }\n\n locations.forEach((location, index) => {\n processLocation({ assetPath, apiPath, data }, location, index)\n })\n\n geospatials.forEach((geospatial, index) => {\n processGeospatial({ assetPath, apiPath, data }, geospatial, index)\n })\n}\n\n/**\n * OS API request proxy factory\n * @param {string} apiPath - the root API path\n */\nexport function makeTileRequestTransformer(apiPath) {\n /**\n * Proxy OS API requests via our server\n * @param {string} url - the request URL\n * @param {string} resourceType - the resource type\n */\n return function transformTileRequest(url, resourceType) {\n if (url.startsWith('https://api.os.uk')) {\n if (resourceType === 'Tile') {\n return {\n url: url.replace(\n 'https://api.os.uk/maps/vector/v1/vts',\n `${window.location.origin}${apiPath}`\n ),\n headers: {}\n }\n }\n\n if (resourceType !== 'Style') {\n return {\n url: `${apiPath}/map-proxy?url=${encodeURIComponent(url)}`,\n headers: {}\n }\n }\n }\n\n const spritesPath =\n 'https://raw.githubusercontent.com/OrdnanceSurvey/OS-Vector-Tile-API-Stylesheets/main'\n\n // Proxy sprite requests\n if (url.startsWith(spritesPath)) {\n const path = url.substring(spritesPath.length)\n return {\n url: `${apiPath}/maps/vts${path}`,\n headers: {}\n }\n }\n\n return { url, headers: {} }\n }\n}\n\n/**\n * Temporary transform request function to transform geocode requests. Fixed in v0.0.18 of interactive map so this is not needed when we upgrade.\n * @param {object} request\n * @param {string} request.url\n * @param {{ method: 'get' }} request.options\n * @returns {Request}\n */\nexport const transformGeocodeRequest = (request) => {\n const url = new URL(request.url, window.location.origin)\n return new Request(url.toString(), request.options)\n}\n\n/**\n * Create a Defra map instance\n * @param {string} mapId - the map id\n * @param {InteractiveMapInitConfig} initConfig - the map initial configuration\n * @param {MapsEnvironmentConfig} mapsConfig - the map environment params\n */\nexport function createMap(mapId, initConfig, mapsConfig) {\n const { assetPath, apiPath, data = defaultData } = mapsConfig\n const logoAltText = 'Ordnance survey logo'\n\n // @ts-expect-error - Defra namespace currently comes from UMD support files\n const defra = window.defra\n\n const interactPlugin = defra.interactPlugin({\n markerColor: { outdoor: '#ff0000', dark: '#00ff00' },\n interactionMode: 'marker',\n multiSelect: false\n })\n\n /** @type {InteractiveMap} */\n const map = new defra.InteractiveMap(mapId, {\n enableFullscreen: true,\n autoColorScheme: false,\n mapProvider: defra.maplibreProvider(),\n reverseGeocodeProvider: defra.openNamesProvider({\n url: `${apiPath}/reverse-geocode-proxy?easting={easting}&northing={northing}`\n }),\n behaviour: 'inline',\n minZoom: 6,\n maxZoom: 18,\n containerHeight: '400px',\n enableZoomControls: true,\n transformRequest: makeTileRequestTransformer(apiPath),\n ...initConfig,\n plugins: [\n defra.mapStylesPlugin({\n mapStyles: [\n {\n id: 'outdoor',\n label: 'Outdoor',\n url: data.VTS_OUTDOOR_URL,\n thumbnail: `${assetPath}/interactive-map/assets/images/outdoor-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`,\n backgroundColor: '#f5f5f0'\n },\n {\n id: 'dark',\n label: 'Dark',\n url: data.VTS_DARK_URL,\n mapColorScheme: 'dark',\n appColorScheme: 'dark',\n thumbnail: `${assetPath}/interactive-map/assets/images/dark-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo-white.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`\n },\n {\n id: 'black-and-white',\n label: 'Black/White',\n url: data.VTS_BLACK_AND_WHITE_URL,\n thumbnail: `${assetPath}/interactive-map/assets/images/black-and-white-map-thumb.jpg`,\n logo: `${assetPath}/interactive-map/assets/images/os-logo-black.svg`,\n logoAltText,\n attribution: `Contains OS data ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Crown copyright and database rights ${new Date().getFullYear()}`\n },\n {\n id: 'aerial',\n label: 'Aerial',\n url: data.VTS_AERIAL_URL,\n thumbnail: `${assetPath}/interactive-map/assets/images/aerial-map-thumb.jpg`,\n attribution: `Tiles ${String.fromCodePoint(COMPANY_SYMBOL_CODE)} Esri — Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community ${new Date().getFullYear()}`\n }\n ]\n }),\n interactPlugin,\n defra.searchPlugin({\n transformRequest: transformGeocodeRequest,\n osNamesURL: `${apiPath}/geocode-proxy?query={query}`,\n width: '300px',\n showMarker: false\n }),\n defra.scaleBarPlugin({\n units: 'metric'\n }),\n ...(initConfig.plugins ?? [])\n ]\n })\n\n return { map, interactPlugin }\n}\n\n/**\n * Updates the marker position and moves the map view port the new location\n * @param {InteractiveMap} map - the map component instance (of InteractiveMap)\n * @param {MapLibreMap} mapProvider - the map provider instance (of MapLibreMap)\n * @param {MapCenter} center - the point\n */\nexport function centerMap(map, mapProvider, center) {\n // Move the 'location' marker to the new point\n map.addMarker('location', center)\n\n // Pan & zoom the map to the new valid location\n mapProvider.flyTo({\n center,\n zoom: 14,\n essential: true\n })\n}\n\n/**\n * @typedef {object} InteractiveMap - an instance of a InteractiveMap\n * @property {Function} on - register callback listeners to map events\n * @property {Function} addPanel - adds a new panel to the map\n * @property {Function} addMarker - adds/updates a marker\n * @property {Function} removeMarker - removes a marker\n * @property {Function} addButton - adds/updates a button\n * @property {Function} toggleButtonState - toggle the state of a button\n */\n\n/**\n * @typedef {object} MapLibreMap\n * @property {Function} flyTo - pans/zooms to a new location\n * @property {Function} fitBounds - fits the my to the new bounds\n */\n\n/**\n * @typedef {[number, number]} MapCenter - Map center point as [long, lat]\n */\n\n/**\n * @typedef {object} InteractiveMapInitConfig - additional config that can be provided to InteractiveMap\n * @property {string} zoom - the zoom level of the map\n * @property {MapCenter} center - the center point of the map\n * @property {{ id: string, coords: MapCenter }[]} [markers] - the markers to add to the map\n * @property {any[]} [plugins] - additional plugins\n */\n\n/**\n * @typedef {object} TileData\n * @property {string} VTS_OUTDOOR_URL - the outdoor tile URL\n * @property {string} VTS_DARK_URL - the dark tile URL\n * @property {string} VTS_BLACK_AND_WHITE_URL - the black and white tile URL\n * @property {string} VTS_AERIAL_URL - the aerial tile URL\n */\n\n/**\n * @typedef {object} MapsEnvironmentConfig\n * @property {string} assetPath - the root asset path\n * @property {string} apiPath - the root API path\n * @property {TileData} data - the tile data config\n */\n\n/**\n * @import { Feature } from '~/src/server/plugins/engine/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Based on "Apply for a lock and weir fishing permit" production form.
|
|
3
|
+
# Extended with duration and site access to demonstrate complex compound conditions.
|
|
4
|
+
# Pricing matrix: duration x permit type x site access
|
|
5
|
+
schema: 2
|
|
6
|
+
name: Apply for a lock and weir fishing permit (v2 payment test)
|
|
7
|
+
engine: V2
|
|
8
|
+
declaration: I apply for permission to fish at the sites listed on this application for the duration of the permit, subject to the normal closed seasons.
|
|
9
|
+
startPage: '/fishing-sites'
|
|
10
|
+
options:
|
|
11
|
+
showReferenceNumber: true
|
|
12
|
+
pages:
|
|
13
|
+
- title: Fishing sites
|
|
14
|
+
path: '/fishing-sites'
|
|
15
|
+
components:
|
|
16
|
+
- id: '1fb84634-86f2-477b-affa-c7ace61aec26'
|
|
17
|
+
type: Markdown
|
|
18
|
+
content: "The fishing sites include:\n\n* Buscot\n* Grafton\n* Rushey\n* Sandford\n* Abingdon\n* Benson\n* Goring\n* Hurley\n* Bell Weir\n* Molesey"
|
|
19
|
+
options: {}
|
|
20
|
+
schema: {}
|
|
21
|
+
name: fishingSites
|
|
22
|
+
next: []
|
|
23
|
+
- title: Contact details
|
|
24
|
+
path: '/contact-details'
|
|
25
|
+
components:
|
|
26
|
+
- id: '3598ed25-1b9a-4ce6-8432-5676063b96ec'
|
|
27
|
+
type: TextField
|
|
28
|
+
title: What is your full name?
|
|
29
|
+
name: fullName
|
|
30
|
+
shortDescription: Full name
|
|
31
|
+
options:
|
|
32
|
+
required: true
|
|
33
|
+
schema: {}
|
|
34
|
+
- id: '9c4f0158-8f87-4cbd-a3a1-960166f015e4'
|
|
35
|
+
type: TelephoneNumberField
|
|
36
|
+
title: What is your phone number?
|
|
37
|
+
name: phoneNumber
|
|
38
|
+
shortDescription: Phone number
|
|
39
|
+
options:
|
|
40
|
+
required: true
|
|
41
|
+
schema: {}
|
|
42
|
+
- id: '9b83dc1e-e385-4cd3-b642-dcc247f3fc89'
|
|
43
|
+
type: EmailAddressField
|
|
44
|
+
title: What is your email address?
|
|
45
|
+
name: emailAddress
|
|
46
|
+
shortDescription: Email address
|
|
47
|
+
options:
|
|
48
|
+
required: true
|
|
49
|
+
next: []
|
|
50
|
+
- title: ''
|
|
51
|
+
path: '/rod-licence-number'
|
|
52
|
+
components:
|
|
53
|
+
- id: '22405838-becd-48ab-b984-c3c886822412'
|
|
54
|
+
type: TextField
|
|
55
|
+
title: What is your rod licence number (current or previous)?
|
|
56
|
+
name: rodLicenceNumber
|
|
57
|
+
shortDescription: Rod licence number
|
|
58
|
+
hint: The permit must be used in conjunction with a valid rod licence.
|
|
59
|
+
options:
|
|
60
|
+
required: true
|
|
61
|
+
schema: {}
|
|
62
|
+
next: []
|
|
63
|
+
- title: ''
|
|
64
|
+
path: '/permit-duration'
|
|
65
|
+
components:
|
|
66
|
+
- id: 'a1a1a1a1-1111-4aaa-aaaa-000000000001'
|
|
67
|
+
type: RadiosField
|
|
68
|
+
title: What duration of permit do you need?
|
|
69
|
+
name: permitDuration
|
|
70
|
+
shortDescription: Permit duration
|
|
71
|
+
options:
|
|
72
|
+
required: true
|
|
73
|
+
list: 'b1b1b1b1-1111-4bbb-bbbb-000000000001'
|
|
74
|
+
next: []
|
|
75
|
+
- title: ''
|
|
76
|
+
path: '/what-kind-of-permit-do-you-require'
|
|
77
|
+
components:
|
|
78
|
+
- id: 'f7663ac4-61e7-4b64-a157-70f002818493'
|
|
79
|
+
type: RadiosField
|
|
80
|
+
title: What kind of permit do you require?
|
|
81
|
+
name: permitType
|
|
82
|
+
shortDescription: Permit type
|
|
83
|
+
options:
|
|
84
|
+
required: true
|
|
85
|
+
list: 'aac4ee00-fb82-4a37-88ad-b9e10ded92e9'
|
|
86
|
+
next: []
|
|
87
|
+
- title: ''
|
|
88
|
+
path: '/site-access'
|
|
89
|
+
condition: 'c1c1c1c1-6666-4ccc-cccc-000000000005'
|
|
90
|
+
components:
|
|
91
|
+
- id: 'a1a1a1a1-1111-4aaa-aaaa-000000000003'
|
|
92
|
+
type: RadiosField
|
|
93
|
+
title: Which site access do you need?
|
|
94
|
+
name: siteAccess
|
|
95
|
+
shortDescription: Site access
|
|
96
|
+
hint: Single site permits are valid for one named site only.
|
|
97
|
+
options:
|
|
98
|
+
required: true
|
|
99
|
+
list: 'b1b1b1b1-1111-4bbb-bbbb-000000000002'
|
|
100
|
+
next: []
|
|
101
|
+
- title: ''
|
|
102
|
+
path: '/payment-required'
|
|
103
|
+
components:
|
|
104
|
+
- id: '6522e3f7-f414-42e5-9dbf-84e5868fbbd3'
|
|
105
|
+
type: PaymentField
|
|
106
|
+
title: Payment required
|
|
107
|
+
name: fishingPermitPayment
|
|
108
|
+
options:
|
|
109
|
+
required: true
|
|
110
|
+
amount: 0
|
|
111
|
+
description: Lock and weir fishing permit
|
|
112
|
+
emailField: emailAddress
|
|
113
|
+
conditionalAmounts:
|
|
114
|
+
# === 3-way: 12-month + type + site (most specific first) ===
|
|
115
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000001'
|
|
116
|
+
amount: 38
|
|
117
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000002'
|
|
118
|
+
amount: 25
|
|
119
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000003'
|
|
120
|
+
amount: 24
|
|
121
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000004'
|
|
122
|
+
amount: 16
|
|
123
|
+
# === 2-way: 8-day + type (site doesn't matter) ===
|
|
124
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000005'
|
|
125
|
+
amount: 12
|
|
126
|
+
- condition: 'd1d1d1d1-8888-4ddd-dddd-000000000006'
|
|
127
|
+
amount: 8
|
|
128
|
+
# === Simple: 1-day flat rate ===
|
|
129
|
+
- condition: 'c1c1c1c1-6666-4ccc-cccc-000000000003'
|
|
130
|
+
amount: 5
|
|
131
|
+
# === Simple: Junior free ===
|
|
132
|
+
- condition: 'c1c1c1c1-6666-4ccc-cccc-000000000004'
|
|
133
|
+
amount: 0
|
|
134
|
+
next: []
|
|
135
|
+
- title: ''
|
|
136
|
+
path: '/summary'
|
|
137
|
+
controller: SummaryPageController
|
|
138
|
+
conditions:
|
|
139
|
+
# =================================================================
|
|
140
|
+
# Simple atomic conditions
|
|
141
|
+
# =================================================================
|
|
142
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000001'
|
|
143
|
+
displayName: Is 12-month permit
|
|
144
|
+
items:
|
|
145
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000001'
|
|
146
|
+
componentId: 'a1a1a1a1-1111-4aaa-aaaa-000000000001'
|
|
147
|
+
operator: is
|
|
148
|
+
type: ListItemRef
|
|
149
|
+
value:
|
|
150
|
+
itemId: 'f1f1f1f1-1111-4fff-ffff-000000000001'
|
|
151
|
+
listId: 'b1b1b1b1-1111-4bbb-bbbb-000000000001'
|
|
152
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000002'
|
|
153
|
+
displayName: Is 8-day permit
|
|
154
|
+
items:
|
|
155
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000002'
|
|
156
|
+
componentId: 'a1a1a1a1-1111-4aaa-aaaa-000000000001'
|
|
157
|
+
operator: is
|
|
158
|
+
type: ListItemRef
|
|
159
|
+
value:
|
|
160
|
+
itemId: 'f1f1f1f1-1111-4fff-ffff-000000000002'
|
|
161
|
+
listId: 'b1b1b1b1-1111-4bbb-bbbb-000000000001'
|
|
162
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000003'
|
|
163
|
+
displayName: Is 1-day permit
|
|
164
|
+
items:
|
|
165
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000003'
|
|
166
|
+
componentId: 'a1a1a1a1-1111-4aaa-aaaa-000000000001'
|
|
167
|
+
operator: is
|
|
168
|
+
type: ListItemRef
|
|
169
|
+
value:
|
|
170
|
+
itemId: 'f1f1f1f1-1111-4fff-ffff-000000000003'
|
|
171
|
+
listId: 'b1b1b1b1-1111-4bbb-bbbb-000000000001'
|
|
172
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000004'
|
|
173
|
+
displayName: Is Junior permit type
|
|
174
|
+
items:
|
|
175
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000004'
|
|
176
|
+
componentId: 'f7663ac4-61e7-4b64-a157-70f002818493'
|
|
177
|
+
operator: is
|
|
178
|
+
type: ListItemRef
|
|
179
|
+
value:
|
|
180
|
+
itemId: 'f1f1f1f1-2222-4fff-ffff-000000000003'
|
|
181
|
+
listId: 'aac4ee00-fb82-4a37-88ad-b9e10ded92e9'
|
|
182
|
+
- id: 'dcaa3b3d-5cbc-4be9-b5ce-b2be5c72ccd1'
|
|
183
|
+
displayName: Is Adult permit type
|
|
184
|
+
items:
|
|
185
|
+
- id: '13b5e86b-2eb5-4a6c-8ab6-9fdc35907f18'
|
|
186
|
+
componentId: 'f7663ac4-61e7-4b64-a157-70f002818493'
|
|
187
|
+
operator: is
|
|
188
|
+
type: ListItemRef
|
|
189
|
+
value:
|
|
190
|
+
itemId: 'b6034236-63cf-44af-bb6c-d5d4d3825973'
|
|
191
|
+
listId: 'aac4ee00-fb82-4a37-88ad-b9e10ded92e9'
|
|
192
|
+
- id: 'c5177318-61ec-44ec-b5c2-18c1be1f1e42'
|
|
193
|
+
displayName: Is Concession permit type
|
|
194
|
+
items:
|
|
195
|
+
- id: 'fb75f1be-d471-4020-ac13-f7a2246078bb'
|
|
196
|
+
componentId: 'f7663ac4-61e7-4b64-a157-70f002818493'
|
|
197
|
+
operator: is
|
|
198
|
+
type: ListItemRef
|
|
199
|
+
value:
|
|
200
|
+
itemId: '86baf02e-0db7-4fad-8fce-fa9a30c1b7f0'
|
|
201
|
+
listId: 'aac4ee00-fb82-4a37-88ad-b9e10ded92e9'
|
|
202
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000007'
|
|
203
|
+
displayName: Is all sites access
|
|
204
|
+
items:
|
|
205
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000007'
|
|
206
|
+
componentId: 'a1a1a1a1-1111-4aaa-aaaa-000000000003'
|
|
207
|
+
operator: is
|
|
208
|
+
type: ListItemRef
|
|
209
|
+
value:
|
|
210
|
+
itemId: 'f1f1f1f1-3333-4fff-ffff-000000000001'
|
|
211
|
+
listId: 'b1b1b1b1-1111-4bbb-bbbb-000000000002'
|
|
212
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000008'
|
|
213
|
+
displayName: Is single site access
|
|
214
|
+
items:
|
|
215
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000008'
|
|
216
|
+
componentId: 'a1a1a1a1-1111-4aaa-aaaa-000000000003'
|
|
217
|
+
operator: is
|
|
218
|
+
type: ListItemRef
|
|
219
|
+
value:
|
|
220
|
+
itemId: 'f1f1f1f1-3333-4fff-ffff-000000000002'
|
|
221
|
+
listId: 'b1b1b1b1-1111-4bbb-bbbb-000000000002'
|
|
222
|
+
# =================================================================
|
|
223
|
+
# Page visibility: site access only shown for 12-month permits
|
|
224
|
+
# =================================================================
|
|
225
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000005'
|
|
226
|
+
displayName: Is 12-month (show site access page)
|
|
227
|
+
items:
|
|
228
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000005'
|
|
229
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000001'
|
|
230
|
+
# =================================================================
|
|
231
|
+
# 2-way compound AND: duration + type
|
|
232
|
+
# =================================================================
|
|
233
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000010'
|
|
234
|
+
displayName: 12-month AND Adult
|
|
235
|
+
coordinator: and
|
|
236
|
+
items:
|
|
237
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000010'
|
|
238
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000001'
|
|
239
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000011'
|
|
240
|
+
conditionId: 'dcaa3b3d-5cbc-4be9-b5ce-b2be5c72ccd1'
|
|
241
|
+
- id: 'c1c1c1c1-6666-4ccc-cccc-000000000011'
|
|
242
|
+
displayName: 12-month AND Concession
|
|
243
|
+
coordinator: and
|
|
244
|
+
items:
|
|
245
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000012'
|
|
246
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000001'
|
|
247
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000013'
|
|
248
|
+
conditionId: 'c5177318-61ec-44ec-b5c2-18c1be1f1e42'
|
|
249
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000005'
|
|
250
|
+
displayName: 8-day AND Adult
|
|
251
|
+
coordinator: and
|
|
252
|
+
items:
|
|
253
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000014'
|
|
254
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000002'
|
|
255
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000015'
|
|
256
|
+
conditionId: 'dcaa3b3d-5cbc-4be9-b5ce-b2be5c72ccd1'
|
|
257
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000006'
|
|
258
|
+
displayName: 8-day AND Concession
|
|
259
|
+
coordinator: and
|
|
260
|
+
items:
|
|
261
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000016'
|
|
262
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000002'
|
|
263
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000017'
|
|
264
|
+
conditionId: 'c5177318-61ec-44ec-b5c2-18c1be1f1e42'
|
|
265
|
+
# =================================================================
|
|
266
|
+
# 3-way compound AND: duration + type + site (chains 2-way refs)
|
|
267
|
+
# Same pattern as "Bats chargeable use" in protected species form
|
|
268
|
+
# =================================================================
|
|
269
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000001'
|
|
270
|
+
displayName: 12-month AND Adult AND All sites
|
|
271
|
+
coordinator: and
|
|
272
|
+
items:
|
|
273
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000020'
|
|
274
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000010'
|
|
275
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000021'
|
|
276
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000007'
|
|
277
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000002'
|
|
278
|
+
displayName: 12-month AND Adult AND Single site
|
|
279
|
+
coordinator: and
|
|
280
|
+
items:
|
|
281
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000022'
|
|
282
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000010'
|
|
283
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000023'
|
|
284
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000008'
|
|
285
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000003'
|
|
286
|
+
displayName: 12-month AND Concession AND All sites
|
|
287
|
+
coordinator: and
|
|
288
|
+
items:
|
|
289
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000024'
|
|
290
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000011'
|
|
291
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000025'
|
|
292
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000007'
|
|
293
|
+
- id: 'd1d1d1d1-8888-4ddd-dddd-000000000004'
|
|
294
|
+
displayName: 12-month AND Concession AND Single site
|
|
295
|
+
coordinator: and
|
|
296
|
+
items:
|
|
297
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000026'
|
|
298
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000011'
|
|
299
|
+
- id: 'e1e1e1e1-7777-4eee-eeee-000000000027'
|
|
300
|
+
conditionId: 'c1c1c1c1-6666-4ccc-cccc-000000000008'
|
|
301
|
+
sections: []
|
|
302
|
+
lists:
|
|
303
|
+
- id: 'b1b1b1b1-1111-4bbb-bbbb-000000000001'
|
|
304
|
+
title: Permit durations
|
|
305
|
+
name: permitDurations
|
|
306
|
+
type: string
|
|
307
|
+
items:
|
|
308
|
+
- id: 'f1f1f1f1-1111-4fff-ffff-000000000001'
|
|
309
|
+
text: 12-month permit
|
|
310
|
+
value: 12-month
|
|
311
|
+
- id: 'f1f1f1f1-1111-4fff-ffff-000000000002'
|
|
312
|
+
text: 8-day permit
|
|
313
|
+
value: 8-day
|
|
314
|
+
- id: 'f1f1f1f1-1111-4fff-ffff-000000000003'
|
|
315
|
+
text: 1-day permit
|
|
316
|
+
value: 1-day
|
|
317
|
+
- id: 'aac4ee00-fb82-4a37-88ad-b9e10ded92e9'
|
|
318
|
+
title: Permit types
|
|
319
|
+
name: permitTypes
|
|
320
|
+
type: string
|
|
321
|
+
items:
|
|
322
|
+
- id: 'b6034236-63cf-44af-bb6c-d5d4d3825973'
|
|
323
|
+
text: Adult
|
|
324
|
+
value: Adult
|
|
325
|
+
- id: '86baf02e-0db7-4fad-8fce-fa9a30c1b7f0'
|
|
326
|
+
text: Concession (65+ or disabled)
|
|
327
|
+
value: Concession
|
|
328
|
+
- id: 'f1f1f1f1-2222-4fff-ffff-000000000003'
|
|
329
|
+
text: Junior (13-16 years)
|
|
330
|
+
value: Junior
|
|
331
|
+
- id: 'b1b1b1b1-1111-4bbb-bbbb-000000000002'
|
|
332
|
+
title: Site access
|
|
333
|
+
name: siteAccess
|
|
334
|
+
type: string
|
|
335
|
+
items:
|
|
336
|
+
- id: 'f1f1f1f1-3333-4fff-ffff-000000000001'
|
|
337
|
+
text: All sites
|
|
338
|
+
value: all-sites
|
|
339
|
+
- id: 'f1f1f1f1-3333-4fff-ffff-000000000002'
|
|
340
|
+
text: Single site
|
|
341
|
+
value: single-site
|
|
@@ -2,6 +2,7 @@ import { type FormMetadata, type PaymentFieldComponent } from '@defra/forms-mode
|
|
|
2
2
|
import { type ObjectSchema } from 'joi';
|
|
3
3
|
import { FormComponent } from '../../../../server/plugins/engine/components/FormComponent.js';
|
|
4
4
|
import { type PaymentState } from '../../../../server/plugins/engine/components/PaymentField.types.js';
|
|
5
|
+
import { type FormModel } from '../../../../server/plugins/engine/models/index.js';
|
|
5
6
|
import { type FormContext, type FormRequestPayload, type FormResponseToolkit } from '../../../../server/plugins/engine/types/index.js';
|
|
6
7
|
import { type ErrorMessageTemplateList, type FormPayload, type FormState, type FormStateValue, type FormSubmissionError, type FormSubmissionState, type PaymentExternalArgs } from '../../../../server/plugins/engine/types.js';
|
|
7
8
|
export declare class PaymentField extends FormComponent {
|
|
@@ -89,6 +90,12 @@ export declare class PaymentField extends FormComponent {
|
|
|
89
90
|
* Static version of getAllPossibleErrors that doesn't require a component instance.
|
|
90
91
|
*/
|
|
91
92
|
static getAllPossibleErrors(): ErrorMessageTemplateList;
|
|
93
|
+
/**
|
|
94
|
+
* Resolves the payment amount from conditional amounts configuration.
|
|
95
|
+
* Evaluates conditions in order; first true condition wins.
|
|
96
|
+
* Falls back to the default options.amount.
|
|
97
|
+
*/
|
|
98
|
+
static resolveAmount(options: PaymentFieldComponent['options'], model: FormModel, state: FormState): number;
|
|
92
99
|
/**
|
|
93
100
|
* Dispatcher for external redirect to GOV.UK Pay
|
|
94
101
|
*/
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { StatusCodes } from 'http-status-codes';
|
|
3
3
|
import joi from 'joi';
|
|
4
|
+
import { createLogger } from "../../../common/helpers/logging/logger.js";
|
|
4
5
|
import { COMPONENT_STATE_ERROR } from "../../../constants.js";
|
|
5
6
|
import { FormComponent } from "./FormComponent.js";
|
|
6
7
|
import { createError, getPluginOptions } from "../helpers.js";
|
|
7
8
|
import { PaymentErrorTypes, PaymentPreAuthError, PaymentSubmissionError } from "../pageControllers/errors.js";
|
|
8
9
|
import { createPaymentService, formatCurrency } from "../../payment/helper.js";
|
|
10
|
+
const logger = createLogger();
|
|
9
11
|
export class PaymentField extends FormComponent {
|
|
10
12
|
isAppendageStateSingleObject = true;
|
|
11
13
|
constructor(def, props) {
|
|
@@ -51,7 +53,9 @@ export class PaymentField extends FormComponent {
|
|
|
51
53
|
// Payload is pre-populated from state if a payment has already been made
|
|
52
54
|
const paymentState = this.isPaymentState(payload[this.name]) ? payload[this.name] : undefined;
|
|
53
55
|
|
|
54
|
-
//
|
|
56
|
+
// Use payment state amount if pre-authorized, otherwise use default.
|
|
57
|
+
// The page controller overrides this with the resolved conditional amount
|
|
58
|
+
// using the full form state (which getViewModel doesn't have access to).
|
|
55
59
|
const amount = paymentState?.amount ?? this.options.amount;
|
|
56
60
|
return {
|
|
57
61
|
...viewModel,
|
|
@@ -112,6 +116,33 @@ export class PaymentField extends FormComponent {
|
|
|
112
116
|
};
|
|
113
117
|
}
|
|
114
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Resolves the payment amount from conditional amounts configuration.
|
|
121
|
+
* Evaluates conditions in order; first true condition wins.
|
|
122
|
+
* Falls back to the default options.amount.
|
|
123
|
+
*/
|
|
124
|
+
static resolveAmount(options, model, state) {
|
|
125
|
+
const {
|
|
126
|
+
conditionalAmounts
|
|
127
|
+
} = options;
|
|
128
|
+
if (!conditionalAmounts?.length) {
|
|
129
|
+
return options.amount;
|
|
130
|
+
}
|
|
131
|
+
for (const {
|
|
132
|
+
condition,
|
|
133
|
+
amount
|
|
134
|
+
} of conditionalAmounts) {
|
|
135
|
+
if (!model.conditions[condition]) {
|
|
136
|
+
logger.warn(`[payment] Condition '${condition}' not found in form conditions. Skipping.`);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (model.conditions[condition].fn(state)) {
|
|
140
|
+
return amount;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return options.amount;
|
|
144
|
+
}
|
|
145
|
+
|
|
115
146
|
/**
|
|
116
147
|
* Dispatcher for external redirect to GOV.UK Pay
|
|
117
148
|
*/
|
|
@@ -138,16 +169,32 @@ export class PaymentField extends FormComponent {
|
|
|
138
169
|
const paymentService = await createPaymentService(isLivePayment, formId, formsService);
|
|
139
170
|
const uuid = randomUUID();
|
|
140
171
|
const reference = state.$$__referenceNumber;
|
|
141
|
-
const
|
|
172
|
+
const resolvedAmount = PaymentField.resolveAmount(options, model, state);
|
|
173
|
+
|
|
174
|
+
// Zero-amount safety net (page skip should prevent this, but defensive)
|
|
175
|
+
if (resolvedAmount === 0) {
|
|
176
|
+
return h.redirect(summaryUrl).code(StatusCodes.SEE_OTHER);
|
|
177
|
+
}
|
|
142
178
|
const description = options.description;
|
|
143
179
|
const slug = `/${model.basePath}`;
|
|
144
180
|
const payCallbackUrl = `${baseUrl}/payment-callback?uuid=${uuid}`;
|
|
145
181
|
const paymentPageUrl = args.sourceUrl;
|
|
146
|
-
|
|
182
|
+
|
|
183
|
+
// Prepopulate GOV.UK Pay email if emailField is configured.
|
|
184
|
+
// The referenced EmailAddressField validates with joi.string().email()
|
|
185
|
+
// at input time, so the value in state is already validated.
|
|
186
|
+
let prefilledEmail;
|
|
187
|
+
if (options.emailField) {
|
|
188
|
+
const emailValue = state[options.emailField];
|
|
189
|
+
if (typeof emailValue === 'string' && emailValue) {
|
|
190
|
+
prefilledEmail = emailValue;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const amountInPence = Math.round(resolvedAmount * 100);
|
|
147
194
|
const payment = await paymentService.createPayment(amountInPence, description, payCallbackUrl, reference, isLivePayment, {
|
|
148
195
|
formId,
|
|
149
196
|
slug
|
|
150
|
-
});
|
|
197
|
+
}, prefilledEmail);
|
|
151
198
|
if (!payment) {
|
|
152
199
|
const message = isLivePayment ? 'There is a problem and we cannot take a payment. Contact us (details in the footer of this form) or save your progress and return to the form later.' : 'Add a valid test API key before you can preview the payment journey.';
|
|
153
200
|
const govukError = createError(componentName, message);
|
|
@@ -158,7 +205,7 @@ export class PaymentField extends FormComponent {
|
|
|
158
205
|
uuid,
|
|
159
206
|
formId,
|
|
160
207
|
reference,
|
|
161
|
-
amount,
|
|
208
|
+
amount: resolvedAmount,
|
|
162
209
|
description,
|
|
163
210
|
paymentId: payment.paymentId,
|
|
164
211
|
componentName,
|
|
@@ -175,6 +222,11 @@ export class PaymentField extends FormComponent {
|
|
|
175
222
|
* @see https://docs.payments.service.gov.uk/delayed_capture/#delay-taking-a-payment
|
|
176
223
|
*/
|
|
177
224
|
async onSubmit(request, _metadata, context) {
|
|
225
|
+
// Zero-amount bypass — no capture needed
|
|
226
|
+
const resolvedAmount = PaymentField.resolveAmount(this.options, this.model, context.state);
|
|
227
|
+
if (resolvedAmount === 0) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
178
230
|
const paymentState = this.getPaymentStateFromState(context.state);
|
|
179
231
|
if (!paymentState) {
|
|
180
232
|
throw new PaymentPreAuthError(this, 'Complete the payment to continue', true, PaymentErrorTypes.PaymentIncomplete);
|
|
@@ -194,7 +246,7 @@ export class PaymentField extends FormComponent {
|
|
|
194
246
|
* @see https://docs.payments.service.gov.uk/api_reference/#payment-status-lifecycle
|
|
195
247
|
*/
|
|
196
248
|
const status = await paymentService.getPaymentStatus(paymentId, isLivePayment);
|
|
197
|
-
PaymentSubmissionError.checkPaymentAmount(status.amount,
|
|
249
|
+
PaymentSubmissionError.checkPaymentAmount(status.amount, resolvedAmount, this);
|
|
198
250
|
if (status.state.status === 'success') {
|
|
199
251
|
await this.markPaymentCaptured(request, paymentState);
|
|
200
252
|
return;
|