diff --git a/src/app/api/proxy/map/route.ts b/src/app/api/proxy/map/route.ts
index 6eebf4f5b..b8001b827 100644
--- a/src/app/api/proxy/map/route.ts
+++ b/src/app/api/proxy/map/route.ts
@@ -1,38 +1,70 @@
import assert from 'assert'
-import { NextResponse } from 'next/server'
+import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'
-export const dynamic = 'force-dynamic'
+import { MapTileProvider } from '@/app/types'
-// TODO: Update infra env vars to use generic naming.
-const clientUrl = process.env.ESRI_CLIENT_URL
-const clientId = process.env.ESRI_CLIENT_KEY
-const clientSecret = process.env.ESRI_CLIENT_SECRET
+export const dynamic = 'force-dynamic'
-const clientResponseSchema = z.object({
+const osmClientResponseSchema = z.object({
access_token: z.string(),
expires_in: z.string(),
issued_at: z.string(),
token_type: z.string(),
})
-export async function POST() {
+const esriClientResponseSchema = z.object({
+ access_token: z.string(),
+ expires_in: z.coerce.string(),
+})
+
+export async function POST(request: NextRequest) {
+ const body = await request.json()
+
+ let clientUrl
+ let clientId
+ let clientSecret
+
+ const provider: MapTileProvider = body.provider
+
+ if (provider === 'ArcGISEsri') {
+ clientUrl = process.env.ESRI_CLIENT_URL
+ clientId = process.env.ESRI_CLIENT_KEY
+ clientSecret = process.env.ESRI_CLIENT_SECRET
+ }
+
+ if (provider === 'OrdinanceSurveyMaps') {
+ clientUrl = process.env.OSM_CLIENT_URL
+ clientId = process.env.OSM_CLIENT_KEY
+ clientSecret = process.env.OSM_CLIENT_SECRET
+ }
+
assert(clientUrl)
assert(clientId)
assert(clientSecret)
- const basicAuth = btoa(`${clientId}:${clientSecret}`)
+ const osmBasicAuth = { Authorization: `Basic ${btoa(`${clientId}:${clientSecret}`)}` }
+ const esriAuth = { client_id: clientId, client_secret: clientSecret }
const req = await fetch(clientUrl, {
method: 'POST',
- headers: { Authorization: `Basic ${basicAuth}`, 'Content-Type': 'application/x-www-form-urlencoded' },
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ ...(provider === 'OrdinanceSurveyMaps' && osmBasicAuth),
+ },
body: new URLSearchParams({
+ ...(provider === 'ArcGISEsri' && esriAuth),
grant_type: 'client_credentials',
+ expiration: '5',
}),
})
const json = await req.json()
- const { access_token: token, expires_in: expiresIn } = clientResponseSchema.parse(json)
+
+ console.log('json', json)
+ const parser = provider === 'ArcGISEsri' ? esriClientResponseSchema : osmClientResponseSchema
+
+ const { access_token: token, expires_in: expiresIn } = parser.parse(json)
return NextResponse.json({
token,
diff --git a/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapDialog.tsx b/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapDialog.tsx
index 8774bd4e4..76b28d5d0 100644
--- a/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapDialog.tsx
+++ b/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapDialog.tsx
@@ -22,7 +22,7 @@ import useWeatherHealthAlertList from '@/app/hooks/queries/useWeatherHealthAlert
import { useTranslation } from '@/app/i18n/client'
import { MapTileProvider } from '@/app/types'
-const { Map, BaseLayer, BaseLayerOSM, ChoroplethLayer, HealthAlertControl } = {
+const { Map, BaseLayer, BaseLayerOSM, BaseLayerEsri, ChoroplethLayer, HealthAlertControl } = {
Map: dynamic(() => import('@/app/components/ui/ukhsa/Map/Map'), {
ssr: false,
loading: () => ,
@@ -33,6 +33,9 @@ const { Map, BaseLayer, BaseLayerOSM, ChoroplethLayer, HealthAlertControl } = {
BaseLayerOSM: dynamic(() => import('@/app/components/ui/ukhsa/Map/shared/layers/BaseLayerOSM'), {
ssr: false,
}),
+ BaseLayerEsri: dynamic(() => import('@/app/components/ui/ukhsa/Map/shared/layers/BaseLayerEsri'), {
+ ssr: false,
+ }),
ChoroplethLayer: dynamic(() => import('@/app/components/ui/ukhsa/Map/shared/layers/ChoroplethLayer'), {
ssr: false,
}),
@@ -62,8 +65,12 @@ export default function HealthAlertsMapDialog({ featureCollection, mapTileProvid
const alertsQuery = useWeatherHealthAlertList({ type })
const baseLayer = useMemo(() => {
+ console.log('mapTileProvider', mapTileProvider)
if (mapTileProvider === 'OrdinanceSurveyMaps') {
- return
+ return
+ }
+ if (mapTileProvider === 'ArcGISEsri') {
+ return
}
return
}, [mapTileProvider])
diff --git a/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapWrapper.tsx b/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapWrapper.tsx
index 0f4193fc2..92814546e 100644
--- a/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapWrapper.tsx
+++ b/src/app/components/ui/ukhsa/Map/health-alerts/HealthAlertsMapWrapper.tsx
@@ -20,6 +20,8 @@ export async function HealthAlertsMapWrapper() {
{mapTileProvider === 'OrdinanceSurveyMaps' ? (
+ ) : mapTileProvider === 'ArcGISEsri' ? (
+
) : (
)}
diff --git a/src/app/components/ui/ukhsa/Map/shared/layers/BaseLayerEsri.tsx b/src/app/components/ui/ukhsa/Map/shared/layers/BaseLayerEsri.tsx
index e1e01ab01..c03c16515 100644
--- a/src/app/components/ui/ukhsa/Map/shared/layers/BaseLayerEsri.tsx
+++ b/src/app/components/ui/ukhsa/Map/shared/layers/BaseLayerEsri.tsx
@@ -9,6 +9,7 @@ import { ComponentProps } from 'react'
import VectorBasemapLayer from 'react-esri-leaflet/plugins/VectorBasemapLayer'
import useMapAuthToken from '@/app/hooks/queries/useMapAuthToken'
+import { MapTileProvider } from '@/app/types'
import { useBaseLayerEsri } from '../hooks/useBaseLayerEsri'
@@ -16,13 +17,14 @@ type EsriProps = ComponentProps
interface BaseLayerEsriProps extends Omit {
name?: EsriProps['name']
+ provider: MapTileProvider
}
-const BaseLayerEsri = ({ name = 'ArcGIS:Navigation', ...rest }: BaseLayerEsriProps) => {
+const BaseLayerEsri = ({ name = 'ArcGIS:Navigation', provider, ...rest }: BaseLayerEsriProps) => {
useBaseLayerEsri()
const {
data: { token },
- } = useMapAuthToken()
+ } = useMapAuthToken(provider)
if (!token) return null
return (
{}
+interface BaseLayerProps extends Partial {
+ provider: MapTileProvider
+}
const attribution = `\n\n© Crown copyright ${new Date().getFullYear()} OS ${ordinanceSurveyMapsLicense}. Use of this data is subject to terms and conditions.\n
You are granted a non-exclusive, royalty free revocable licence solely to view the licensed data for non-commercial purposes for the period during which UKHSA makes it available; You are not permitted to copy, sub-license, distribute, sell or otherwise make available the licensed data to third parties in any form; and Third party rights to enforce the terms of this licence shall be reserved to OS.\n
Ⓗ Hawlfraint y Goron ${new Date().getFullYear()} Arolwg Ordnans ${ordinanceSurveyMapsLicense}. Defnyddio data hwn yn amodol ar delerau ac amodau.\nRhoddir trwydded ddirymiadwy, anghyfyngedig a heb freindal i chi i weld y data trwyddedig at ddibenion anfasnachol am y cyfnod y mae ar gael gan UKHSA. Ni chewch gopïo, is-drwyddedu, dosbarthu na gwerthu unrhyw ran o’r data hwn i drydydd partïon mewn unrhyw ffurf; ac. Yr Arolwg Ordnans fydd yn cadw’r hawlio trydydd parti i orfodi amodau’r drwydded hon.
`
-const BaseLayerOSM = ({ ...rest }: BaseLayerProps) => {
+const BaseLayerOSM = ({ provider, ...rest }: BaseLayerProps) => {
const {
data: { token },
- } = useMapAuthToken()
+ } = useMapAuthToken(provider)
return (
getToken(provider),
retry: RETRY_ATTEMPTS,
refetchInterval: (query) => {
// Extract the token expiration time (in seconds) and set the query refetch interval