From a9f75d9cb08c1d69b6f6e727dc55d31e89aedb4f Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 3 Feb 2025 10:28:50 +0000 Subject: [PATCH 1/5] serve test page from express server at /test route --- README.md | 2 +- test.html => src/pages/test.html | 0 src/routes.ts | 5 ++++- src/server.ts | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) rename test.html => src/pages/test.html (100%) diff --git a/README.md b/README.md index b2d348c..39ec8d4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Run unit and integration tests with `npm run test` Run tests with coverage using `npm run coverage` -Manual testing can be done by viewing [test.html](test.html) in the browser. Here you can choose to view any available dataset on +Manual testing can be done by viewing [test.html](src/pages/test.html) in the browser. Here you can choose to view any available dataset on either a local grout server, or deployed to mrcdata. # Lint diff --git a/test.html b/src/pages/test.html similarity index 100% rename from test.html rename to src/pages/test.html diff --git a/src/routes.ts b/src/routes.ts index 875166a..99beb2f 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -4,11 +4,14 @@ import { TileController } from "./controllers/tileController"; import notFound from "./errors/notFound"; import { MetadataController } from "./controllers/metadataController"; -export const registerRoutes = () => { +export const registerRoutes = (rootDir: string) => { const router = Router(); router.get("/", IndexController.getIndex); router.get("/metadata", MetadataController.getMetadata); router.get("/tile/:dataset/:level/:z/:x/:y", TileController.getTile); + router.get("/test", (_, res) => { + res.sendFile(`${rootDir}/pages/test.html`); + }); // provide an endpoint we can use to test 500 response behaviour by throwing an "unexpected error" - but only if we // are running in a non-production mode indicated by an env var diff --git a/src/server.ts b/src/server.ts index f7f1a5a..5154ef8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -39,7 +39,7 @@ Object.assign(app.locals, { }); Object.freeze(app.locals); // We don't expect anything else to modify app.locals -app.use("/", registerRoutes()); +app.use("/", registerRoutes(__dirname)); app.use(handleError); if (import.meta.env.PROD) { From e052f46d657217ba98bd5e4fd5d3545f4f88f4e9 Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 3 Feb 2025 17:04:59 +0000 Subject: [PATCH 2/5] load test page from corect location in docker, tidy-ups in test page --- README.md | 4 +-- docker/Dockerfile | 1 + src/controllers/testPageController.ts | 9 +++++ src/routes.ts | 7 ++-- src/server.ts | 5 +-- {src/pages => static}/test.html | 47 +++++++++++++++------------ 6 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 src/controllers/testPageController.ts rename {src/pages => static}/test.html (82%) diff --git a/README.md b/README.md index 39ec8d4..65c9868 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ Run unit and integration tests with `npm run test` Run tests with coverage using `npm run coverage` -Manual testing can be done by viewing [test.html](src/pages/test.html) in the browser. Here you can choose to view any available dataset on -either a local grout server, or deployed to mrcdata. +Manual testing can be done by viewing [test.html](static/test.html) in the browser. Here you can choose to view any available dataset on +either a local grout server, or deployed to mrcdata. The page is available at the `/test` route of any running server. # Lint diff --git a/docker/Dockerfile b/docker/Dockerfile index a4c4857..376e5fd 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,7 @@ FROM node:22 COPY src /src COPY config /config +COPY static /static COPY package.json package-lock.json tsconfig.json vite.config.mts ./ RUN npm ci RUN npm run build diff --git a/src/controllers/testPageController.ts b/src/controllers/testPageController.ts new file mode 100644 index 0000000..5f1c405 --- /dev/null +++ b/src/controllers/testPageController.ts @@ -0,0 +1,9 @@ +import { Request, Response } from "express"; +import {AppLocals} from "../types/app.js"; + +export class TestPageController { + static getTestPage = (req: Request, res: Response) => { + const { rootDir } = req.app.locals as AppLocals; + res.sendFile(`${rootDir}/static/test.html`); + } +} \ No newline at end of file diff --git a/src/routes.ts b/src/routes.ts index 99beb2f..af20fc5 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -3,15 +3,14 @@ import { IndexController } from "./controllers/indexController"; import { TileController } from "./controllers/tileController"; import notFound from "./errors/notFound"; import { MetadataController } from "./controllers/metadataController"; +import {TestPageController} from "./controllers/testPageController.js"; -export const registerRoutes = (rootDir: string) => { +export const registerRoutes = () => { const router = Router(); router.get("/", IndexController.getIndex); router.get("/metadata", MetadataController.getMetadata); router.get("/tile/:dataset/:level/:z/:x/:y", TileController.getTile); - router.get("/test", (_, res) => { - res.sendFile(`${rootDir}/pages/test.html`); - }); + router.get("/test", TestPageController.getTestPage); // provide an endpoint we can use to test 500 response behaviour by throwing an "unexpected error" - but only if we // are running in a non-production mode indicated by an env var diff --git a/src/server.ts b/src/server.ts index 5154ef8..b53cd62 100644 --- a/src/server.ts +++ b/src/server.ts @@ -35,11 +35,12 @@ const metadata = buildMetadata(tileDatasets); Object.assign(app.locals, { tileDatasets, - metadata + metadata, + rootDir }); Object.freeze(app.locals); // We don't expect anything else to modify app.locals -app.use("/", registerRoutes(__dirname)); +app.use("/", registerRoutes()); app.use(handleError); if (import.meta.env.PROD) { diff --git a/src/pages/test.html b/static/test.html similarity index 82% rename from src/pages/test.html rename to static/test.html index 4f69458..bdf8697 100644 --- a/src/pages/test.html +++ b/static/test.html @@ -60,7 +60,7 @@

GROUT Test Page

-
+
@@ -71,7 +71,7 @@

GROUT Test Page

const map = L.map("map").setView({lon: 0, lat: 0}, 3); map.options.minZoom = 3; - const nameProp = "NAME_1"; + //const nameProp = "NAME_1"; const groutServers = { "local": "http://localhost:5000", "mrcdata": "https://mrcdata.dide.ic.ac.uk/grout" @@ -91,20 +91,6 @@

GROUT Test Page

tms: true, // y values are inverted without this! }; - // Region layer options - assign shade of blue based on first letter of name! - const regionOptions = { - style: (feature, layerName) => { - const shade = Math.min((feature.properties[nameProp].charCodeAt(0) - 65)/26, 1) * 255; - return { - fillColor: `rgb(${shade}, ${shade}, 255)`, - fillOpacity: 0.5, - color: "#cccccc", - weight: 1 - } - }, - ...options - }; - // Country layer options const countryOptions = { style: { @@ -118,13 +104,28 @@

GROUT Test Page

let regionLayer = null; let countryLayer = null; - const { createApp, ref, onMounted, watch } = Vue; + const { createApp, ref, onMounted, watch, computed } = Vue; createApp({ setup() { - // Dict of friendly name to { url, dataset } + // Dict of friendly name to { url, dataset, admin2Enabled } const datasets = ref(null); const selectedDatasetName = ref(""); const adminLevel = ref(1); + const nameProp = computed(() => `NAME_${adminLevel.value}`); + + // Region layer options - assign shade of blue based on first letter of name! + const regionOptions = computed(() => ({ + style: (feature, layerName) => { + const shade = Math.min((feature.properties[nameProp.value].charCodeAt(0) - 65)/26, 1) * 255; + return { + fillColor: `rgb(${shade}, ${shade}, 255)`, + fillOpacity: 0.5, + color: "#cccccc", + weight: 1 + } + }, + ...options + })); onMounted(async () => { // Populate drop down with available datasets from both servers @@ -137,7 +138,8 @@

GROUT Test Page

if (metadata.status === "success") { const datasetNames = Object.keys(metadata.data.datasets.tile); datasetNames.forEach((dataset) => { - fetchedDatasets[`${server}: ${dataset}`] = {url, dataset}; + const admin2Enabled = metadata.data.datasets.tile[dataset].levels.includes("admin2"); + fetchedDatasets[`${server}: ${dataset}`] = {url, dataset, admin2Enabled}; }); } } @@ -152,6 +154,9 @@

GROUT Test Page

}); watch([selectedDatasetName, adminLevel], () => { + if (!datasets.value[selectedDatasetName.value].admin2Enabled) { + adminLevel.value = 1; + } updateMap(); }); @@ -166,10 +171,10 @@

GROUT Test Page

const { url, dataset } = datasets.value[selectedDatasetName.value]; const level = adminLevel.value; - regionLayer = VectorTileLayer(`${url}/tile/${dataset}/admin${level}/{z}/{x}/{-y}`, regionOptions) + regionLayer = VectorTileLayer(`${url}/tile/${dataset}/admin${level}/{z}/{x}/{-y}`, regionOptions.value) .on('mouseover', function (e) { // show a tooltip - const name = e.layer.properties[nameProp]; + const name = e.layer.properties[nameProp.value]; L.popup() .setContent(name) .setLatLng(e.latlng) From 655e37669938960df1be6402abe1780e535fdea9 Mon Sep 17 00:00:00 2001 From: Emma Date: Mon, 3 Feb 2025 17:18:04 +0000 Subject: [PATCH 3/5] prevent panning outside original map boundaries --- static/test.html | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/test.html b/static/test.html index bdf8697..cf24a6c 100644 --- a/static/test.html +++ b/static/test.html @@ -68,8 +68,12 @@

GROUT Test Page