From 8d8b293961a24154b75105bf6d3333891953a022 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Fri, 16 May 2025 14:06:14 +0000 Subject: [PATCH 1/8] prepare json file with types and api call --- data/inputLayer.json | 68 ++++++++++++++++++++++ pages/index.vue | 8 ++- server/api/opendataInputLayer/index.get.ts | 6 ++ server/prepareInputLayer.ts | 51 ++++++++++++++++ 4 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 data/inputLayer.json create mode 100644 server/api/opendataInputLayer/index.get.ts create mode 100644 server/prepareInputLayer.ts diff --git a/data/inputLayer.json b/data/inputLayer.json new file mode 100644 index 0000000..7ccee90 --- /dev/null +++ b/data/inputLayer.json @@ -0,0 +1,68 @@ +{ + "datasets": [ + { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-stammdaten-2025-04-01", "resource_id": "d4534d43-e378-40c8-9466-5bf1bff76794", "title": "Badegewässer Stammdaten" }, + { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-einstufung", "resource_id": "bd51a0a3-ffb2-41a3-aa6c-a15df0cb64bd", "title": "Badegewässer Einstufung" }, + { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-messungen", "resource_id": "a5fca440-849b-404d-a39e-fb87c48c692e", "title": "Badegewässer Messungen" }, + { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-saisondauer", "resource_id": "a8a8ba9b-541b-4e14-b44c-eb771c61a2cf", "title": "Badegewässer Saisondauer" }, + { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-infrastruktur-aktuell", "resource_id": "097e0aa7-c867-4897-a7d5-80332f5dfc76", "title": "Badegewässer Infrastruktur" }, + { "host": "opendata.schleswig-holstein.de", "id": "see-wasserkorper", "resource_id": "a0f4d2d4-5768-4b03-b92c-875cd349a775", "title": "See-Wasserkörper" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "resource_id": "304586f1-c51f-49e0-ba2a-ef449824d6e6", "title": "Wasserstand Pegel Hemmelsdorfer See - Hemmelsdorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-hemmelmarker-see", "resource_id": "3fe50159-6c0a-4c5d-88a3-b43d56be01ee", "title": "Wasserstand Pegel Hemmelmarker See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-kellersee-kellersee1", "resource_id": "a5da2f8b-e192-4957-9821-5d4c4f35ba23", "title": "Wasserstand Pegel Kellersee - Kellersee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-postsee-postsee1", "resource_id": "c22b636f-2b2c-4621-9f6a-6082e25c392a", "title": "Wasserstand Pegel Postsee - Postsee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "resource_id": "1d984bc3-e9fd-4199-aa99-7c5130d2c2ca", "title": "Wasserstand Pegel Arenholzer See - Arenholzer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-barkauer-see-barkauer-see1", "resource_id": "77c978b2-63bc-483c-b2f4-af4689dc5258", "title": "Wasserstand Pegel Barkauer See - Barkauer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "resource_id": "0301fa08-ebcf-49aa-80c0-778b6c2e18df", "title": "Wasserstand Pegel Behlendorfer See - Behlendorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-behler-see-behler-see1", "resource_id": "1132ef82-401b-4013-b58d-771625f610ad", "title": "Wasserstand Pegel Behler See - Behler See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-belauer-see-belauer-see1", "resource_id": "a810983e-0530-4cad-83a7-97b252b1358f", "title": "Wasserstand Pegel Belauer See - Belauer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-bistensee-bistensee1", "resource_id": "f9bfcbe9-8a4b-492b-b2c8-08f30851ace7", "title": "Wasserstand Pegel Bistensee - Bistensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "resource_id": "1f314490-77b9-4399-b37d-eb3e067aaeaf", "title": "Wasserstand Pegel Bordesholmer See - Bordesholmer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "resource_id": "af33f464-7585-489c-be4d-82f525f644ed", "title": "Wasserstand Pegel Bornhöveder See - Bornhöveder See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-bottschlotter-see", "resource_id": "a1fe3fcc-ca08-467d-b4ce-85d13cb88b07", "title": "Wasserstand Pegel Bottschlotter See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-brahmsee", "resource_id": "758c147d-42d6-42e5-8805-59fc3d86bec2", "title": "Wasserstand Pegel Brahmsee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-dieksee-dieksee1", "resource_id": "be59631a-aa88-4475-9ed3-50a13a680dd9", "title": "Wasserstand Pegel Dieksee - Dieksee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "resource_id": "84d13768-4ad3-4ab2-abca-28033e4f2e28", "title": "Wasserstand Pegel Dobersdorfer See - Dobersdorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-drusensee-drusensee1", "resource_id": "2ac64064-c517-4974-b7d6-c6b7b008ea16", "title": "Wasserstand Pegel Drüsensee - Drüsensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-einfelder-see-einfelder-see1", "resource_id": "f4f4f1dd-a404-4076-93bf-8238a9359870", "title": "Wasserstand Pegel Einfelder See - Einfelder See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-grossensee-grossensee1", "resource_id": "edb6ce71-2ed6-4187-b527-4681a29c4561", "title": "Wasserstand Pegel Großensee - Großensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "resource_id": "6f848e76-84df-4364-ab7c-ea6472bb3ce6", "title": "Wasserstand Pegel Kl.Plöner See - Kl.Plöner See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "resource_id": "e317f2e0-075c-4fb0-8a01-4b5142854e3c", "title": "Wasserstand Pegel Kl.Pönitzer See - Kl.Pönitzer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "resource_id": "60d78992-037b-4918-b4d1-0a9f1765f56f", "title": "Wasserstand Pegel Ratzeburger See - Ratzeburger See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "resource_id": "17126965-8349-4ccc-ae76-86ca59cd7eec", "title": "Wasserstand Pegel Gr.Segeberger See - Segeberger See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-gudower-see-gudower-see1", "resource_id": "ae4a7fe2-deef-4bd0-90be-f8fce0122d4d", "title": "Wasserstand Pegel Gudower See - Gudower See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-hohner-see-hohner-see1", "resource_id": "3e0d38a4-4a9e-4f87-888e-97f11c036d16", "title": "Wasserstand Pegel Hohner See - Hohner See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "resource_id": "4910bd0b-8cae-42b1-8545-425e78f156a7", "title": "Wasserstand Pegel Langsee (Süderfahrenstedt) - Langsee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-mozener-see-mozener-see1", "resource_id": "336803b8-07d2-4804-83e7-a33930ee27a0", "title": "Wasserstand Pegel Mözener See - Mözener See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-neustadter-binnenwasser1", "resource_id": "875a0110-b29e-4083-b4f9-a11f7d5df62e", "title": "Wasserstand Pegel Neustädter Binnenwasser" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "resource_id": "3023dd36-de72-4913-82f5-455ce0679a3a", "title": "Wasserstand Pegel Neversdorfer See - Neversdorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-passader-see-passader-see1", "resource_id": "428ecb06-1093-458e-8bfe-017c8eac55ba", "title": "Wasserstand Pegel Passader See - Passader See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "resource_id": "a2760c42-24b9-4a22-adc6-ea442d397775", "title": "Wasserstand Pegel Rantumdammsiel - Rantumbecken" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-schluensee-schluensee1", "resource_id": "d3bfcae6-a844-403f-94f9-49f7a6eb2dc0", "title": "Wasserstand Pegel Schluensee - Schluensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-schohsee1", "resource_id": "b2b50d48-f94b-4703-bdfb-923963a67a12", "title": "Wasserstand Pegel Schöhsee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "resource_id": "36177bf0-5231-4c8c-b646-38860a516234", "title": "Wasserstand Pegel Schwansener See (FP) Schöpfwerk" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-seedorfer-see", "resource_id": "a20b8e5c-109a-40f4-9146-1080cd0bc97b", "title": "Wasserstand Pegel Seedorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "resource_id": "2a9097ee-f564-488c-ba01-e5ca4e65bd24", "title": "Wasserstand Pegel Sibbersdorfer See - Sibbersdorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "resource_id": "14d872ab-35b8-42f4-a392-7695a33eb0e7", "title": "Wasserstand Pegel Stendorfer See - Stendorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-stocksee-stocksee1", "resource_id": "233595ef-9a43-4891-924b-ab259a702be1", "title": "Wasserstand Pegel Stocksee - Stocksee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-stolper-see-stolper-see1", "resource_id": "42b7ff56-947a-4870-a09f-1d6fcbbd2d27", "title": "Wasserstand Pegel Stolper See - Stolper See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-sudensee-sudensee1", "resource_id": "b08d106a-3bdd-4046-b592-317dc6335b7f", "title": "Wasserstand Pegel Südensee - Südensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-suseler-see", "resource_id": "8f4cb123-3773-421e-9c8b-371f3149fbaa", "title": "Wasserstand Pegel Süseler See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-suhrer-see1", "resource_id": "4107018b-c54e-4d25-81df-00fe3e060c30", "title": "Wasserstand Pegel Suhrer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-trammer-see1", "resource_id": "5d155970-aeb3-4868-9864-5292bb77e24e", "title": "Wasserstand Pegel Trammer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-tresdorfer-see1", "resource_id": "dc7cec9a-2d55-43af-a752-cae6a4c97edd", "title": "Wasserstand Pegel Tresdorfer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-vierer-see", "resource_id": "f9a650ca-d81d-4273-a4d8-da58a655d6ec", "title": "Wasserstand Pegel Vierer See" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-westensee-westensee1", "resource_id": "63dedd32-0858-471a-9377-dc9e1fe743ff", "title": "Wasserstand Pegel Westensee - Westensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-windebyer-noor1", "resource_id": "c00f6db8-ccfb-4591-b5a5-e9d9f574be3c", "title": "Wasserstand Pegel Windebyer Noor" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-wittensee-wittensee1", "resource_id": "c7a457cf-93bd-4cec-b100-2587bf212a23", "title": "Wasserstand Pegel Wittensee - Wittensee" }, + { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-meldorf-kronenloch", "resource_id": "1dc05082-71a6-4408-a944-106683dff2d0", "title": "Wasserstand Pegel Meldorf-Kronenloch" } + ], + "mappings": [ + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, + { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" } + ] +} diff --git a/pages/index.vue b/pages/index.vue index 43e031c..8d55b91 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -148,7 +148,13 @@ import type { LakeDepth, MergedData } from '~/composables/useFetchOpenData'; import { computed, ref, watch } from 'vue'; import MyLeafletMap from '~/components/MyLeafletMap.vue'; import { fetchBathData, fetchBusStopData, fetchLakesData } from '~/composables/useFetchOpenData'; -// import layout from '/layout.json'; + +const { data: response, status } = useLazyFetch('/api/opendataInputLayer'); +watch(status, () => { + if (status.value !== 'pending') { + console.warn(response.value); + } +}); const { t, locale, setLocale } = useI18n(); diff --git a/server/api/opendataInputLayer/index.get.ts b/server/api/opendataInputLayer/index.get.ts new file mode 100644 index 0000000..7d3ec2a --- /dev/null +++ b/server/api/opendataInputLayer/index.get.ts @@ -0,0 +1,6 @@ +import { input } from '~/server/prepareInputLayer'; + +export default defineEventHandler(async () => { + console.warn(input); + return input; +}); diff --git a/server/prepareInputLayer.ts b/server/prepareInputLayer.ts new file mode 100644 index 0000000..071d96b --- /dev/null +++ b/server/prepareInputLayer.ts @@ -0,0 +1,51 @@ +import inputJson from '~/data/inputLayer.json'; + +interface Dataset { + host: string + id: string + resource_id: string + title: string +} + +interface Mappings { + source_db_id: string + source_db_field: string + condition: string + target_db_id: string + target_db_field: string +} + +interface InputJSON { + datasets: Dataset[] + mappings: Mappings[] +} +/* interface StructuredDataset { + name: string + datasets: Dataset + mappings: Record // or you can define a proper structure here +} */ + +/* async function fetchDatasetData(dataset: Dataset): Promise { + const url = `https://${dataset.host}/api/3/action/datastore_search?resource_id=${dataset.resource_id}`; + + try { + const res = await fetch(url); + const data = await res.json(); + + return { + name: dataset.title, + datasets: dataset, + mappings: inferMappings(data), // Optional: define a helper to map structure + }; + } + catch (error) { + console.error(`Error fetching ${dataset.title}:`, error); + return { + name: dataset.title, + datasets: dataset, + mappings: {}, + }; + } +} */ + +export const input: InputJSON = inputJson; From ad0db271955a58f8de9200cd8909adb80f63a588 Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Mon, 19 May 2025 14:57:43 +0000 Subject: [PATCH 2/8] fetch data and files content api calls and files. prepare data based on input layer and mappings --- data/bathingWaterInputLayer.json | 106 ++++++++++ .../{inputLayer.json => lakesInputLayer.json} | 61 ++++-- pages/index.vue | 23 +-- server/api/fetchDataFromFiles/fetch-csv.ts | 29 +++ server/api/fetchDataFromFiles/fetch-json.ts | 28 +++ server/api/fetchDataFromFiles/fetch-zip.ts | 41 ++++ server/api/opendataInputLayer/index.get.ts | 14 +- server/fetchData.ts | 193 ++++++++++++++++++ server/prepareInput.ts | 42 ++++ server/prepareInputLayer.ts | 51 ----- 10 files changed, 505 insertions(+), 83 deletions(-) create mode 100644 data/bathingWaterInputLayer.json rename data/{inputLayer.json => lakesInputLayer.json} (53%) create mode 100644 server/api/fetchDataFromFiles/fetch-csv.ts create mode 100644 server/api/fetchDataFromFiles/fetch-json.ts create mode 100644 server/api/fetchDataFromFiles/fetch-zip.ts create mode 100644 server/fetchData.ts create mode 100644 server/prepareInput.ts delete mode 100644 server/prepareInputLayer.ts diff --git a/data/bathingWaterInputLayer.json b/data/bathingWaterInputLayer.json new file mode 100644 index 0000000..a9047a3 --- /dev/null +++ b/data/bathingWaterInputLayer.json @@ -0,0 +1,106 @@ +{ + "datasets": [ + { + "host": "opendata.schleswig-holstein.de", + "id": "badegewasser-stammdaten-2025-04-01", + "resource_id": "d4534d43-e378-40c8-9466-5bf1bff76794", + "title": "Badegewässer Stammdaten", + "headers": [ + "BADEGEWAESSERID", + "BADEGEWAESSERNAME", + "KURZNAME", + "ALLGEMEIN_GEBRAEUCHL_NAME", + "GEWAESSERKATEGORIE", + "KUESTENGEWAESSER", + "BADEGEWAESSERTYP", + "WEITEREBESCHREIBUNG", + "BADESTELLENLAENGE", + "EUANMELDUNG", + "EUABMELDUNG", + "FLUSSGEBIETSEINHEITID", + "FLUSSGEBIETSEINHEITNAME", + "WASSERKOERPERID", + "WASSERKOERPERNAME", + "NATWASSERKOERPERID", + "NATWASSERKOERPERNAME", + "SCHLUESSELWOERTER", + "KREISNR", + "KREIS", + "GEMEINDENR", + "GEMEINDE", + "UTM_OST", + "UTM_NORD", + "GEOGR_LAENGE", + "GEOGR_BREITE", + "BADESTELLENINFORMATION", + "AUSWIRKUNGEN_AUF_BADEGEWAESSER", + "MOEGLICHEBELASTUNGEN" + ] + }, + { + "host": "opendata.schleswig-holstein.de", + "id": "badegewasser-einstufung", + "resource_id": "bd51a0a3-ffb2-41a3-aa6c-a15df0cb64bd", + "title": "Badegewässer Einstufung", + "headers": [ + "BADEGEWAESSERID", + "BEURTEILUNGSZEITRAUM_VON", + "BEURTEILUNGSZEITRAUM_BIS", + "EINSTUFUNG_ODER_VORABBEWERTUNG" + ] + }, + { + "host": "opendata.schleswig-holstein.de", + "id": "badegewasser-messungen", + "resource_id": "a5fca440-849b-404d-a39e-fb87c48c692e", + "title": "Badegewässer Messungen", + "headers": [ + "BADEGEWAESSERID", + "MESSSTELLENNAME", + "MESSSTELLENID", + "UEBERWACHUNGSARTID", + "UEBERWASCHUNGSARTTEXT", + "GEWAESSERKATEGORIE", + "KUESTENGEWAESSER", + "PROBEID", + "DATUMMESSUNG", + "PROBENART", + "ECOLI", + "INTEST_ENTEROKOKKEN", + "WASSERTEMP", + "LUFTTEMP", + "SICHTTIEFE", + "BEMERKUNG" + ] + }, + { + "host": "opendata.schleswig-holstein.de", + "id": "badegewasser-saisondauer", + "resource_id": "a8a8ba9b-541b-4e14-b44c-eb771c61a2cf", + "title": "Badegewässer Saisondauer", + "headers": [ + "BADEGEWAESSERID", + "SAISONBEGINN", + "SAISONENDE", + "GESCHLOSSEN" + ] + }, + { + "host": "opendata.schleswig-holstein.de", + "id": "badegewasser-infrastruktur-aktuell", + "resource_id": "097e0aa7-c867-4897-a7d5-80332f5dfc76", + "title": "Badegewässer Infrastruktur", + "headers": [ + "BADEGEWAESSERID", + "INFRASTRUKTURID", + "INFRASTRUKTUR" + ] + } + ], + "mappings": [ + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-einstufung", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-messungen", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-saisondauer", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-infrastruktur-aktuell", "target_db_field": "BADEGEWAESSERID" } + ] +} diff --git a/data/inputLayer.json b/data/lakesInputLayer.json similarity index 53% rename from data/inputLayer.json rename to data/lakesInputLayer.json index 7ccee90..a5c2762 100644 --- a/data/inputLayer.json +++ b/data/lakesInputLayer.json @@ -1,10 +1,5 @@ { "datasets": [ - { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-stammdaten-2025-04-01", "resource_id": "d4534d43-e378-40c8-9466-5bf1bff76794", "title": "Badegewässer Stammdaten" }, - { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-einstufung", "resource_id": "bd51a0a3-ffb2-41a3-aa6c-a15df0cb64bd", "title": "Badegewässer Einstufung" }, - { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-messungen", "resource_id": "a5fca440-849b-404d-a39e-fb87c48c692e", "title": "Badegewässer Messungen" }, - { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-saisondauer", "resource_id": "a8a8ba9b-541b-4e14-b44c-eb771c61a2cf", "title": "Badegewässer Saisondauer" }, - { "host": "opendata.schleswig-holstein.de", "id": "badegewasser-infrastruktur-aktuell", "resource_id": "097e0aa7-c867-4897-a7d5-80332f5dfc76", "title": "Badegewässer Infrastruktur" }, { "host": "opendata.schleswig-holstein.de", "id": "see-wasserkorper", "resource_id": "a0f4d2d4-5768-4b03-b92c-875cd349a775", "title": "See-Wasserkörper" }, { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "resource_id": "304586f1-c51f-49e0-ba2a-ef449824d6e6", "title": "Wasserstand Pegel Hemmelsdorfer See - Hemmelsdorfer See" }, { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-hemmelmarker-see", "resource_id": "3fe50159-6c0a-4c5d-88a3-b43d56be01ee", "title": "Wasserstand Pegel Hemmelmarker See" }, @@ -53,16 +48,56 @@ { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-vierer-see", "resource_id": "f9a650ca-d81d-4273-a4d8-da58a655d6ec", "title": "Wasserstand Pegel Vierer See" }, { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-westensee-westensee1", "resource_id": "63dedd32-0858-471a-9377-dc9e1fe743ff", "title": "Wasserstand Pegel Westensee - Westensee" }, { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-windebyer-noor1", "resource_id": "c00f6db8-ccfb-4591-b5a5-e9d9f574be3c", "title": "Wasserstand Pegel Windebyer Noor" }, - { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-wittensee-wittensee1", "resource_id": "c7a457cf-93bd-4cec-b100-2587bf212a23", "title": "Wasserstand Pegel Wittensee - Wittensee" }, { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-meldorf-kronenloch", "resource_id": "1dc05082-71a6-4408-a944-106683dff2d0", "title": "Wasserstand Pegel Meldorf-Kronenloch" } ], "mappings": [ - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" }, - { "source_db_id": "", "source_db_field": "", "condition": "=", "target_db_id": "", "target_db_field": "" } + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "target_db_field": "hemmelsdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelmarker-see", "target_db_field": "hemmelmarker" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kellersee-kellersee1", "target_db_field": "kellersee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-postsee-postsee1", "target_db_field": "postsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "target_db_field": "Arenholzer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-barkauer-see-barkauer-see1", "target_db_field": "Barkauer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "target_db_field": "Behlendorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behler-see-behler-see1", "target_db_field": "Behler" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-belauer-see-belauer-see1", "target_db_field": "Belauer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bistensee-bistensee1", "target_db_field": "Bistensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "target_db_field": "Bordesholmer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "target_db_field": "Bornhöveder" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bottschlotter-see", "target_db_field": "Bottschloter" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-brahmsee", "target_db_field": "Brahmsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dieksee-dieksee1", "target_db_field": "Dieksee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "target_db_field": "Dobersdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-drusensee-drusensee1", "target_db_field": "Drüsensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-einfelder-see-einfelder-see1", "target_db_field": "Einfelder" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-grossensee-grossensee1", "target_db_field": "Großensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "target_db_field": "Plöner" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "target_db_field": "Pönitzer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "target_db_field": "Ratzeburger" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "target_db_field": "Segeberger" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gudower-see-gudower-see1", "target_db_field": "Gudower" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hohner-see-hohner-see1", "target_db_field": "Hohner" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "target_db_field": "Süderfahrenstedt" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-mozener-see-mozener-see1", "target_db_field": "Mözener" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neustadter-binnenwasser1", "target_db_field": "Neustadt" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "target_db_field": "Neversdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-passader-see-passader-see1", "target_db_field": "Passader" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "target_db_field": "Rantumdammsiel" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schluensee-schluensee1", "target_db_field": "Schluensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schohsee1", "target_db_field": "Schöhsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "target_db_field": "Schwansener" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-seedorfer-see", "target_db_field": "Seedorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "target_db_field": "Sibbersdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "target_db_field": "Stendorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stocksee-stocksee1", "target_db_field": "Stocksee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stolper-see-stolper-see1", "target_db_field": "Stolper" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sudensee-sudensee1", "target_db_field": "Südensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suseler-see", "target_db_field": "Süseler" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suhrer-see1", "target_db_field": "Suhrer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-trammer-see1", "target_db_field": "Trammer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-tresdorfer-see1", "target_db_field": "Tresdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-vierer-see", "target_db_field": "Vierer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-westensee-westensee1", "target_db_field": "Westensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-windebyer-noor1", "target_db_field": "Windebyer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-meldorf-kronenloch", "target_db_field": "Meldorf-Kronenloch" } ] } diff --git a/pages/index.vue b/pages/index.vue index 8d55b91..a3fd946 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -49,13 +49,6 @@ > {{ t('bathingWater') }} -
  • - {{ t('BusStopData') }} -
  • { - if (status.value !== 'pending') { - console.warn(response.value); - } -}); - const { t, locale, setLocale } = useI18n(); const isSmallScreen = computed(() => { @@ -306,8 +292,15 @@ watch(selectedLakeDateIndex, async (newIndex) => { }); watch(feature, async () => { if (feature.value === 'bathing') { + const { data: response, status } = useLazyFetch(`/api/opendataInputLayer?feature=${encodeURIComponent(feature.value)}`); + watch(status, () => { + if (status.value !== 'pending') { + console.warn(response.value); + bathingWaterData.value = response.value; + } + }); selectedIndex.value = dateOptions.length - 1; - bathingWaterData.value = await fetchBathData(selectedDate.value); + // bathingWaterData.value = await fetchBathData(selectedDate.value); } else if (feature.value === 'busStops') { busStopsData.value = await fetchBusStopData(); diff --git a/server/api/fetchDataFromFiles/fetch-csv.ts b/server/api/fetchDataFromFiles/fetch-csv.ts new file mode 100644 index 0000000..04a1e98 --- /dev/null +++ b/server/api/fetchDataFromFiles/fetch-csv.ts @@ -0,0 +1,29 @@ +import { createError } from 'h3'; + +export async function fetchCsvFromUrl(url: string): Promise { + if (!url) { + throw createError({ + statusCode: 400, + statusMessage: 'Missing URL parameter', + }); + } + + const response = await fetch(url); + if (!response.ok) { + throw createError({ + statusCode: response.status, + statusMessage: `Failed to fetch resource: ${response.statusText}`, + }); + } + + const lowerUrl = url.toLowerCase(); + if (lowerUrl.endsWith('.csv') || response.headers.get('content-type')?.includes('text/csv')) { + const buffer = await response.arrayBuffer(); + return new Uint8Array(buffer); + } + + throw createError({ + statusCode: 415, + statusMessage: 'Unsupported file format.', + }); +} diff --git a/server/api/fetchDataFromFiles/fetch-json.ts b/server/api/fetchDataFromFiles/fetch-json.ts new file mode 100644 index 0000000..2248c11 --- /dev/null +++ b/server/api/fetchDataFromFiles/fetch-json.ts @@ -0,0 +1,28 @@ +import { createError, getQuery } from 'h3'; + +export async function fetchJsonFromUrl(url: string): Promise { + if (!url) { + throw createError({ + statusCode: 400, + statusMessage: 'Missing URL parameter', + }); + } + + const response = await fetch(url); + if (!response.ok) { + throw createError({ + statusCode: response.status, + statusMessage: `Failed to fetch resource: ${response.statusText}`, + }); + } + + const lowerUrl = url.toLowerCase(); + if (lowerUrl.endsWith('json')) { + return await response.json(); + } + + throw createError({ + statusCode: 415, + statusMessage: 'Unsupported file format.', + }); +} diff --git a/server/api/fetchDataFromFiles/fetch-zip.ts b/server/api/fetchDataFromFiles/fetch-zip.ts new file mode 100644 index 0000000..f21d7a2 --- /dev/null +++ b/server/api/fetchDataFromFiles/fetch-zip.ts @@ -0,0 +1,41 @@ +import { createError, getQuery } from 'h3'; +import shp from 'shpjs'; + +export async function fetchZipFromUrl(url: string): Promise { + if (!url) { + throw createError({ + statusCode: 400, + statusMessage: 'Missing URL parameter', + }); + } + + const response = await fetch(url); + if (!response.ok) { + throw createError({ + statusCode: response.status, + statusMessage: `Failed to fetch resource: ${response.statusText}`, + }); + } + + const lowerUrl = url.toLowerCase(); + if (lowerUrl.endsWith('.zip')) { + const zipBuffer = await response.arrayBuffer(); + try { + const geojson = await shp(zipBuffer); + const jsonString = JSON.stringify(geojson); + const uint8Array = new TextEncoder().encode(jsonString); + return uint8Array; + } + catch (err) { + throw createError({ + statusCode: 422, + statusMessage: `Failed to convert shapefile to GeoJSON.${err}`, + }); + } + } + + throw createError({ + statusCode: 415, + statusMessage: 'Unsupported file format.', + }); +} diff --git a/server/api/opendataInputLayer/index.get.ts b/server/api/opendataInputLayer/index.get.ts index 7d3ec2a..647ef65 100644 --- a/server/api/opendataInputLayer/index.get.ts +++ b/server/api/opendataInputLayer/index.get.ts @@ -1,6 +1,12 @@ -import { input } from '~/server/prepareInputLayer'; +import { getData } from '~/server/prepareInput'; -export default defineEventHandler(async () => { - console.warn(input); - return input; +export default defineEventHandler(async (event) => { + const feature = getQuery(event).feature as string; + if (!feature) { + throw createError({ + statusCode: 400, + statusMessage: 'Missing feature', + }); + } + return await getData(feature); }); diff --git a/server/fetchData.ts b/server/fetchData.ts new file mode 100644 index 0000000..4161cdd --- /dev/null +++ b/server/fetchData.ts @@ -0,0 +1,193 @@ +import type { Dataset, InputJSON, StructuredDataset } from '~/server/prepareInput'; +import proj4 from 'proj4'; +import { fetchCsvFromUrl } from '~/server/api/fetchDataFromFiles/fetch-csv'; +import { fetchJsonFromUrl } from '~/server/api/fetchDataFromFiles/fetch-json'; +import { fetchZipFromUrl } from '~/server/api/fetchDataFromFiles/fetch-zip'; + +proj4.defs('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs'); +const fromProjection = 'EPSG:25832'; +const toProjection = 'WGS84'; + +const ALLOWED_HOSTS = [ + 'opendata.schleswig-holstein.de', + 'efi2.schleswig-holstein.de', + 'geoservice.norderstedt.de', + 'hsi-sh.de', +]; + +export async function fetchData(datasets: InputJSON) { + try { + const data = await Promise.all( + datasets.datasets.map(async (dataset: any) => { + if (!ALLOWED_HOSTS.includes(dataset.host)) { + throw createError({ + statusCode: 403, + statusMessage: 'Access to this URL is not allowed', + }); + } + + const url = `https://${dataset.host}/api/action/package_show?id=${dataset.id}`; + const response = await fetch(url); + const res = await response.json(); + + if (res.success) { + const resource = res.result.resources.find( + (r: any) => r.id === dataset.resource_id, + ); + + if (resource) { + if (resource.url) { + resource.url = resource.url.replace(/^http:/, 'https:'); + } + if (resource.format === 'CSV') { + return { id: dataset.id, data: await fetchAndParseCsv(resource.url, dataset?.headers) }; + } + else if (['JSON', 'SHP'].includes(resource.format)) { + return { id: dataset.id, data: await fetchAndParseJson(resource.url) }; + } + } + } + }), + ); + return data; + } + catch (error) { + console.error(`Error fetching`, error); + throw error; + } +} + +export async function fetchBathingMappings(data: any[], datasets: InputJSON) { + try { + // Find the base dataset once (you assume it's the "source" in every mapping) + const baseDatasetId = datasets.mappings[0].source_db_id; + const baseDataset = data.find((d: any) => d.id === baseDatasetId); + if (!baseDataset) + throw new Error('Base dataset not found'); + + const merged = baseDataset.data.map((baseRow: any) => { + const mergedRow = { ...baseRow }; + + // Loop over each mapping and try to find matching rows from other datasets + datasets.mappings.forEach((m: any) => { + const targetDataset = data.find((d: any) => d.id === m.target_db_id); + if (!targetDataset) + return; + + // Find matching row(s) in the target dataset + const match = targetDataset.data.find((row: any) => + row[m.target_db_field] === baseRow[m.source_db_field], + ); + + if (match) { + // Optionally prefix fields from target to avoid collision + Object.entries(match).forEach(([key, value]) => { + mergedRow[`${m.target_db_id}_${key}`] = value; + }); + } + }); + + return mergedRow; + }); + console.warn(merged); + return merged; + } + catch (error) { + console.error('Error fetching Mappings', error); + throw error; + } +} + +export async function fetchLakesMappings(data: any, datasets: InputJSON) { + try { + const mappingData = await Promise.all( + datasets.mappings.map((m: any) => { + const source = data.find((d: any) => d.id === m.source_db_id); + const target = data.find((d: any) => d.id === m.target_db_id); + if (m.condition === '=') { + // content + } + }), + ); + } + catch (error) { + console.error('Error fetching Mappings', error); + throw error; + } +} + +async function fetchAndParseCsv(csvUrl: string, headers?: string[]): Promise { + const response = await fetchCsvFromUrl(csvUrl); + const decoder = new TextDecoder('iso-8859-1'); + const csvText = decoder.decode(response); + + const rows = csvText.trim().split('\n'); + if (headers) { + return rows.map((line) => { + const values = line.split('|').map(v => v.replace(/^"|"$/g, '').trim()); + const entry: Record = {}; + headers.forEach((key, i) => { + entry[key] = values[i] ?? ''; + }); + return entry as D; + }); + } + else { + const headerLine = rows.shift(); + if (!headerLine) + return []; + + const detectedHeaders = headerLine.split(';').map(v => v.replace(/^"|"$/g, '').trim()); + + return rows.map((line) => { + const values = line.split(';').map(v => v.replace(/^"|"$/g, '').trim()); + const entry: Record = {}; + detectedHeaders.forEach((key, i) => { + entry[key] = values[i] ?? ''; + }); + return entry as D; + }); + } +} + +async function fetchAndParseJson(geoJsonUrl: string): Promise> { + if (geoJsonUrl.toLowerCase().endsWith('.zip')) { + const response = await fetchZipFromUrl(geoJsonUrl); + const data = JSON.parse(new TextDecoder().decode(response)); + return data as GeoJSON.FeatureCollection; + } + const response = await fetchJsonFromUrl(geoJsonUrl); + const data = JSON.parse(new TextDecoder().decode(response)); + const reprojectedCoordinatesData = reprojectGeoJSON(data); + return reprojectedCoordinatesData; +} + +function reprojectGeoJSON(geojson: GeoJSON.FeatureCollection): GeoJSON.FeatureCollection { + return { + ...geojson, + features: geojson.features.map((feature) => { + if (feature.geometry.type !== 'Point') { + return feature; + } + const [x, y] = feature.geometry.coordinates; + const [lon, lat] = proj4(fromProjection, toProjection, [x, y]); + + let newBbox = feature.bbox; + if (feature.bbox && feature.bbox.length === 4) { + const [minX, minY, maxX, maxY] = feature.bbox; + const [minLon, minLat] = proj4(fromProjection, toProjection, [minX, minY]); + const [maxLon, maxLat] = proj4(fromProjection, toProjection, [maxX, maxY]); + newBbox = [minLon, minLat, maxLon, maxLat]; + } + + return { + ...feature, + geometry: { + ...feature.geometry, + coordinates: [lon, lat], + }, + bbox: newBbox, + }; + }), + }; +} diff --git a/server/prepareInput.ts b/server/prepareInput.ts new file mode 100644 index 0000000..1e95b78 --- /dev/null +++ b/server/prepareInput.ts @@ -0,0 +1,42 @@ +import bathingJson from '~/data/bathingWaterInputLayer.json'; +import lakesJson from '~/data/lakesInputLayer.json'; +import { fetchBathingMappings, fetchData, fetchLakesMappings } from '~/server/fetchData'; + +export interface Dataset { + host: string + id: string + resource_id: string + title: string +} + +export interface Mappings { + source_db_id: string + source_db_field: string + condition: string + target_db_id: string + target_db_field: string +} + +export interface InputJSON { + datasets: Dataset[] + mappings: Mappings[] +} +export interface StructuredDataset { + id: string + data: [] + // mappings: Record +} + +export async function getData(feature: string) { + if (feature === 'bathing') { + const fetchedData = await fetchData(bathingJson as InputJSON); + return await fetchBathingMappings(fetchedData, bathingJson as InputJSON); + } + else if (feature === 'lakes') { + const fetchedData = await fetchData(lakesJson as InputJSON); + return await fetchLakesMappings(fetchedData, bathingJson as InputJSON); + } + else { + return 'Unavailable Feature Requested!'; + } +} diff --git a/server/prepareInputLayer.ts b/server/prepareInputLayer.ts deleted file mode 100644 index 071d96b..0000000 --- a/server/prepareInputLayer.ts +++ /dev/null @@ -1,51 +0,0 @@ -import inputJson from '~/data/inputLayer.json'; - -interface Dataset { - host: string - id: string - resource_id: string - title: string -} - -interface Mappings { - source_db_id: string - source_db_field: string - condition: string - target_db_id: string - target_db_field: string -} - -interface InputJSON { - datasets: Dataset[] - mappings: Mappings[] -} -/* interface StructuredDataset { - name: string - datasets: Dataset - mappings: Record // or you can define a proper structure here -} */ - -/* async function fetchDatasetData(dataset: Dataset): Promise { - const url = `https://${dataset.host}/api/3/action/datastore_search?resource_id=${dataset.resource_id}`; - - try { - const res = await fetch(url); - const data = await res.json(); - - return { - name: dataset.title, - datasets: dataset, - mappings: inferMappings(data), // Optional: define a helper to map structure - }; - } - catch (error) { - console.error(`Error fetching ${dataset.title}:`, error); - return { - name: dataset.title, - datasets: dataset, - mappings: {}, - }; - } -} */ - -export const input: InputJSON = inputJson; From 1cb3160cd23b716463960a97ceb598d425ded7eb Mon Sep 17 00:00:00 2001 From: Ali Farooq Date: Tue, 20 May 2025 14:24:01 +0000 Subject: [PATCH 3/8] updated generalized front-end display with geojson --- components/MyLeafletMap.vue | 261 ++++++++++--------------------- data/bathingWaterInputLayer.json | 8 +- data/lakesInputLayer.json | 96 ++++++------ package.json | 1 + pages/index.vue | 185 +++++----------------- pnpm-lock.yaml | 3 + server/api/proxy-csv.ts | 65 -------- server/fetchData.ts | 85 +++++++--- server/prepareInput.ts | 5 +- 9 files changed, 246 insertions(+), 463 deletions(-) delete mode 100644 server/api/proxy-csv.ts diff --git a/components/MyLeafletMap.vue b/components/MyLeafletMap.vue index b38a67a..db14632 100644 --- a/components/MyLeafletMap.vue +++ b/components/MyLeafletMap.vue @@ -3,6 +3,7 @@ diff --git a/data/bathingWaterInputLayer.json b/data/bathingWaterInputLayer.json index a9047a3..108bb8a 100644 --- a/data/bathingWaterInputLayer.json +++ b/data/bathingWaterInputLayer.json @@ -98,9 +98,9 @@ } ], "mappings": [ - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-einstufung", "target_db_field": "BADEGEWAESSERID" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-messungen", "target_db_field": "BADEGEWAESSERID" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-saisondauer", "target_db_field": "BADEGEWAESSERID" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-infrastruktur-aktuell", "target_db_field": "BADEGEWAESSERID" } + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-einstufung", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-messungen", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-saisondauer", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, + { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-infrastruktur-aktuell", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" } ] } diff --git a/data/lakesInputLayer.json b/data/lakesInputLayer.json index a5c2762..2c9c6ad 100644 --- a/data/lakesInputLayer.json +++ b/data/lakesInputLayer.json @@ -51,53 +51,53 @@ { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-meldorf-kronenloch", "resource_id": "1dc05082-71a6-4408-a944-106683dff2d0", "title": "Wasserstand Pegel Meldorf-Kronenloch" } ], "mappings": [ - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "target_db_field": "hemmelsdorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelmarker-see", "target_db_field": "hemmelmarker" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kellersee-kellersee1", "target_db_field": "kellersee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-postsee-postsee1", "target_db_field": "postsee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "target_db_field": "Arenholzer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-barkauer-see-barkauer-see1", "target_db_field": "Barkauer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "target_db_field": "Behlendorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behler-see-behler-see1", "target_db_field": "Behler" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-belauer-see-belauer-see1", "target_db_field": "Belauer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bistensee-bistensee1", "target_db_field": "Bistensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "target_db_field": "Bordesholmer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "target_db_field": "Bornhöveder" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bottschlotter-see", "target_db_field": "Bottschloter" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-brahmsee", "target_db_field": "Brahmsee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dieksee-dieksee1", "target_db_field": "Dieksee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "target_db_field": "Dobersdorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-drusensee-drusensee1", "target_db_field": "Drüsensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-einfelder-see-einfelder-see1", "target_db_field": "Einfelder" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-grossensee-grossensee1", "target_db_field": "Großensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "target_db_field": "Plöner" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "target_db_field": "Pönitzer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "target_db_field": "Ratzeburger" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "target_db_field": "Segeberger" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gudower-see-gudower-see1", "target_db_field": "Gudower" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hohner-see-hohner-see1", "target_db_field": "Hohner" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "target_db_field": "Süderfahrenstedt" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-mozener-see-mozener-see1", "target_db_field": "Mözener" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neustadter-binnenwasser1", "target_db_field": "Neustadt" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "target_db_field": "Neversdorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-passader-see-passader-see1", "target_db_field": "Passader" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "target_db_field": "Rantumdammsiel" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schluensee-schluensee1", "target_db_field": "Schluensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schohsee1", "target_db_field": "Schöhsee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "target_db_field": "Schwansener" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-seedorfer-see", "target_db_field": "Seedorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "target_db_field": "Sibbersdorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "target_db_field": "Stendorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stocksee-stocksee1", "target_db_field": "Stocksee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stolper-see-stolper-see1", "target_db_field": "Stolper" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sudensee-sudensee1", "target_db_field": "Südensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suseler-see", "target_db_field": "Süseler" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suhrer-see1", "target_db_field": "Suhrer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-trammer-see1", "target_db_field": "Trammer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-tresdorfer-see1", "target_db_field": "Tresdorfer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-vierer-see", "target_db_field": "Vierer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-westensee-westensee1", "target_db_field": "Westensee" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-windebyer-noor1", "target_db_field": "Windebyer" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-meldorf-kronenloch", "target_db_field": "Meldorf-Kronenloch" } + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "target_db_field": "hemmelsdorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelmarker-see", "target_db_field": "hemmelmarker", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kellersee-kellersee1", "target_db_field": "kellersee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-postsee-postsee1", "target_db_field": "postsee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "target_db_field": "Arenholzer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-barkauer-see-barkauer-see1", "target_db_field": "Barkauer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "target_db_field": "Behlendorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behler-see-behler-see1", "target_db_field": "Behler", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-belauer-see-belauer-see1", "target_db_field": "Belauer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bistensee-bistensee1", "target_db_field": "Bistensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "target_db_field": "Bordesholmer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "target_db_field": "Bornhöveder", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bottschlotter-see", "target_db_field": "Bottschloter", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-brahmsee", "target_db_field": "Brahmsee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dieksee-dieksee1", "target_db_field": "Dieksee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "target_db_field": "Dobersdorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-drusensee-drusensee1", "target_db_field": "Drüsensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-einfelder-see-einfelder-see1", "target_db_field": "Einfelder", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-grossensee-grossensee1", "target_db_field": "Großensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "target_db_field": "Plöner", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "target_db_field": "Pönitzer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "target_db_field": "Ratzeburger", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "target_db_field": "Segeberger", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gudower-see-gudower-see1", "target_db_field": "Gudower", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hohner-see-hohner-see1", "target_db_field": "Hohner", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "target_db_field": "Süderfahrenstedt", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-mozener-see-mozener-see1", "target_db_field": "Mözener", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neustadter-binnenwasser1", "target_db_field": "Neustadt", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "target_db_field": "Neversdorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-passader-see-passader-see1", "target_db_field": "Passader", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "target_db_field": "Rantumdammsiel", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schluensee-schluensee1", "target_db_field": "Schluensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schohsee1", "target_db_field": "Schöhsee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "target_db_field": "Schwansener", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-seedorfer-see", "target_db_field": "Seedorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "target_db_field": "Sibbersdorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "target_db_field": "Stendorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stocksee-stocksee1", "target_db_field": "Stocksee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stolper-see-stolper-see1", "target_db_field": "Stolper", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sudensee-sudensee1", "target_db_field": "Südensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suseler-see", "target_db_field": "Süseler", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suhrer-see1", "target_db_field": "Suhrer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-trammer-see1", "target_db_field": "Trammer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-tresdorfer-see1", "target_db_field": "Tresdorfer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-vierer-see", "target_db_field": "Vierer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-westensee-westensee1", "target_db_field": "Westensee", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-windebyer-noor1", "target_db_field": "Windebyer", "label_option": "Wasserstand" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-meldorf-kronenloch", "target_db_field": "Meldorf-Kronenloch", "label_option": "Wasserstand" } ] } diff --git a/package.json b/package.json index e60a32c..e4c4149 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "@antfu/eslint-config": "4.12.0", "@cspell/dict-de-de": "4.1.0", "@types/chroma-js": "^3.1.1", + "@types/geojson": "^7946.0.16", "@types/leaflet": "^1.9.17", "@types/proj4": "^2.5.6", "@types/shpjs": "^3.4.7", diff --git a/pages/index.vue b/pages/index.vue index a3fd946..252540a 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -60,75 +60,25 @@
    - -
    -
    -
    -
    - -
    - - {{ group.year }} - -
    -
    - {{ t('selectedDate') }}: {{ selectedDate }} -
    -
    -
    - -
    - {{ t('selectedDate') }}: {{ selectedLakeDate }} -
    -
    +

    - {{ selectedItem.bathing.BADEGEWAESSERNAME }} + {{ selectedItem.properties.BADEGEWAESSERNAME }}

      -
    • {{ t('quality') }}: {{ selectedItem.classification?.EINSTUFUNG_ODER_VORABBEWERTUNG || 'N/A' }}
    • -
    • {{ t('category') }}: {{ selectedItem.measurements?.GEWAESSERKATEGORIE || 'N/A' }}
    • -
    • {{ t('depth') }}: {{ selectedItem.measurements?.SICHTTIEFE || 'N/A' }}
    • -
    • {{ t('seasonal') }}: {{ selectedItem.seasonal?.SAISONBEGINN }} - {{ selectedItem.seasonal?.SAISONENDE }} {{ selectedItem.seasonal?.GESCHLOSSEN || 'N/A' }}
    • -
    • {{ t('infrastructure') }}: {{ selectedItem.infrastructure?.INFRASTRUKTUR || 'N/A' }}
    • +
    • {{ t('quality') }}: {{ selectedItem.properties?.EINSTUFUNG_ODER_VORABBEWERTUNG || 'N/A' }}
    • +
    • {{ t('category') }}: {{ selectedItem.properties?.GEWAESSERKATEGORIE || 'N/A' }}
    • +
    • {{ t('depth') }}: {{ selectedItem.properties?.SICHTTIEFE || 'N/A' }} m
    • +
    • {{ t('seasonal') }}: {{ selectedItem.properties?.SAISONBEGINN }} - {{ selectedItem.properties?.SAISONENDE }} {{ selectedItem.properties?.GESCHLOSSEN || 'N/A' }}
    • +
    • {{ t('infrastructure') }}: {{ selectedItem.properties?.INFRASTRUKTUR || 'N/A' }}
    @@ -137,23 +87,19 @@ diff --git a/components/MyLeafletMap.vue b/components/MyLeafletMap.vue index db14632..0348abb 100644 --- a/components/MyLeafletMap.vue +++ b/components/MyLeafletMap.vue @@ -4,24 +4,21 @@ diff --git a/components/PopupInfo.vue b/components/PopupInfo.vue new file mode 100644 index 0000000..ba8e234 --- /dev/null +++ b/components/PopupInfo.vue @@ -0,0 +1,29 @@ + + + diff --git a/components/Slider.vue b/components/Slider.vue new file mode 100644 index 0000000..6e65345 --- /dev/null +++ b/components/Slider.vue @@ -0,0 +1,58 @@ + + + diff --git a/composables/useSliderDates.ts b/composables/useSliderDates.ts index 9c801cc..b6f1660 100644 --- a/composables/useSliderDates.ts +++ b/composables/useSliderDates.ts @@ -1,60 +1,33 @@ -let globalMinDate: Date | null = null; -let globalMaxDate: Date | null = null; -export const selectedLakeDateIndex = ref(0); -export const selectedLakeDate = ref(''); -export const lakeDateOptions = ref([]); +const yearColors = ['#3B82F6', '#10B981', '#8B5CF6', '#F59E0B', '#EF4444']; -export function setLakeDepth() { - if (!lakeData.value) { - return; - } - lakeData.value.forEach((feature) => { - if (Array.isArray(feature.properties.lakeDepth) && feature.properties.lakeDepth.length > 0) { - const dates = feature.properties.lakeDepth - .map((entry) => { - const [datePart] = entry.Zeit.split(' '); - const parsedDate = new Date(datePart); - return parsedDate.getTime(); - }); - if (dates.length > 0) { - const minDate = new Date(Math.min(...dates)); - const maxDate = new Date(Math.max(...dates)); - if (!globalMinDate || minDate < globalMinDate) - globalMinDate = minDate; - if (!globalMaxDate || maxDate > globalMaxDate) - globalMaxDate = maxDate; +export function getDatesGroups(fetchedData: any) { + const groupedDates = computed(() => { + const yearGroups = new Map(); + fetchedData.forEach((date: any) => { + const year = date.date.slice(0, 4); + if (!yearGroups.has(year)) { + yearGroups.set(year, []); } - } + yearGroups.get(year)!.push(date.date); + }); + const total = fetchedData.length; + let offset = 0; + return Array.from(yearGroups.entries()).map(([year, dates], i) => { + const width = (dates.length / total) * 100; + const group = { + year, + width: width.toFixed(2), + offset: offset.toFixed(2), + color: yearColors[i % yearColors.length], + }; + offset += width; + return group; + }); }); - // globalMinDate.setFullYear(globalMinDate.getFullYear() + 1); - // globalMinDate.setDate(globalMinDate.getDate() + 1); - // globalMaxDate.setDate(globalMaxDate.getDate() + 1); - // console.log(globalMinDate,globalMaxDate) - if (globalMinDate && globalMaxDate) { - const dates = []; - const min = new Date( - globalMinDate.getFullYear(), - globalMinDate.getMonth(), - globalMinDate.getDate(), - ); + return groupedDates; +} - const max = new Date( - globalMaxDate.getFullYear(), - globalMaxDate.getMonth(), - globalMaxDate.getDate(), - ); - const current = new Date(min); - // eslint-disable-next-line no-unmodified-loop-condition - while (current <= max) { - dates.push(new Date(current.getFullYear(), current.getMonth(), current.getDate())); - current.setDate(current.getDate() + 1); - } - lakeDateOptions.value = dates; - selectedLakeDateIndex.value = dates.length - 1; - } - else { - lakeDateOptions.value = []; - selectedLakeDateIndex.value = 0; - } - selectedLakeDate.value = lakeDateOptions.value[selectedLakeDateIndex.value]?.toLocaleDateString('en-CA') || ''; +export function getDateOptions(fetchedData: any) { + const options = fetchedData.map((o: any) => o.date); + return options; } diff --git a/data/bathingWaterInputLayer.json b/data/bathingWaterInputLayer.json index 108bb8a..9d1bd69 100644 --- a/data/bathingWaterInputLayer.json +++ b/data/bathingWaterInputLayer.json @@ -2,7 +2,7 @@ "datasets": [ { "host": "opendata.schleswig-holstein.de", - "id": "badegewasser-stammdaten-2025-04-01", + "id": "badegewasser-stammdaten", "resource_id": "d4534d43-e378-40c8-9466-5bf1bff76794", "title": "Badegewässer Stammdaten", "headers": [ @@ -98,9 +98,11 @@ } ], "mappings": [ - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-einstufung", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-messungen", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-saisondauer", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" }, - { "source_db_id": "badegewasser-stammdaten-2025-04-01", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-infrastruktur-aktuell", "target_db_field": "BADEGEWAESSERID", "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG" } - ] + { "source_db_id": "badegewasser-stammdaten", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-einstufung", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-messungen", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-saisondauer", "target_db_field": "BADEGEWAESSERID" }, + { "source_db_id": "badegewasser-stammdaten", "source_db_field": "BADEGEWAESSERID", "condition": "=", "target_db_id": "badegewasser-infrastruktur-aktuell", "target_db_field": "BADEGEWAESSERID" } + ], + "options": + { "label_option": "EINSTUFUNG_ODER_VORABBEWERTUNG", "legend_option": "default" } } diff --git a/data/lakesInputLayer.json b/data/lakesInputLayer.json index 2c9c6ad..8d9e3d7 100644 --- a/data/lakesInputLayer.json +++ b/data/lakesInputLayer.json @@ -51,53 +51,55 @@ { "host": "opendata.schleswig-holstein.de", "id": "wasserstand-pegel-meldorf-kronenloch", "resource_id": "1dc05082-71a6-4408-a944-106683dff2d0", "title": "Wasserstand Pegel Meldorf-Kronenloch" } ], "mappings": [ - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "target_db_field": "hemmelsdorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelmarker-see", "target_db_field": "hemmelmarker", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kellersee-kellersee1", "target_db_field": "kellersee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-postsee-postsee1", "target_db_field": "postsee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "target_db_field": "Arenholzer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-barkauer-see-barkauer-see1", "target_db_field": "Barkauer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "target_db_field": "Behlendorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behler-see-behler-see1", "target_db_field": "Behler", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-belauer-see-belauer-see1", "target_db_field": "Belauer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bistensee-bistensee1", "target_db_field": "Bistensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "target_db_field": "Bordesholmer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "target_db_field": "Bornhöveder", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bottschlotter-see", "target_db_field": "Bottschloter", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-brahmsee", "target_db_field": "Brahmsee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dieksee-dieksee1", "target_db_field": "Dieksee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "target_db_field": "Dobersdorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-drusensee-drusensee1", "target_db_field": "Drüsensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-einfelder-see-einfelder-see1", "target_db_field": "Einfelder", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-grossensee-grossensee1", "target_db_field": "Großensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "target_db_field": "Plöner", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "target_db_field": "Pönitzer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "target_db_field": "Ratzeburger", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "target_db_field": "Segeberger", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gudower-see-gudower-see1", "target_db_field": "Gudower", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hohner-see-hohner-see1", "target_db_field": "Hohner", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "target_db_field": "Süderfahrenstedt", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-mozener-see-mozener-see1", "target_db_field": "Mözener", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neustadter-binnenwasser1", "target_db_field": "Neustadt", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "target_db_field": "Neversdorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-passader-see-passader-see1", "target_db_field": "Passader", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "target_db_field": "Rantumdammsiel", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schluensee-schluensee1", "target_db_field": "Schluensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schohsee1", "target_db_field": "Schöhsee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "target_db_field": "Schwansener", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-seedorfer-see", "target_db_field": "Seedorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "target_db_field": "Sibbersdorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "target_db_field": "Stendorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stocksee-stocksee1", "target_db_field": "Stocksee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stolper-see-stolper-see1", "target_db_field": "Stolper", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sudensee-sudensee1", "target_db_field": "Südensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suseler-see", "target_db_field": "Süseler", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suhrer-see1", "target_db_field": "Suhrer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-trammer-see1", "target_db_field": "Trammer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-tresdorfer-see1", "target_db_field": "Tresdorfer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-vierer-see", "target_db_field": "Vierer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-westensee-westensee1", "target_db_field": "Westensee", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-windebyer-noor1", "target_db_field": "Windebyer", "label_option": "Wasserstand" }, - { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-meldorf-kronenloch", "target_db_field": "Meldorf-Kronenloch", "label_option": "Wasserstand" } - ] + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelsdorfer-see-hemmelsdorfer-see1", "target_db_field": "hemmelsdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hemmelmarker-see", "target_db_field": "hemmelmarker" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kellersee-kellersee1", "target_db_field": "kellersee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-postsee-postsee1", "target_db_field": "postsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-arenholzer-see-arenholzer-see", "target_db_field": "Arenholzer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-barkauer-see-barkauer-see1", "target_db_field": "Barkauer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behlendorfer-see-behlendorfer-see1", "target_db_field": "Behlendorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-behler-see-behler-see1", "target_db_field": "Behler" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-belauer-see-belauer-see1", "target_db_field": "Belauer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bistensee-bistensee1", "target_db_field": "Bistensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bordesholmer-see-bordesholmer-see1", "target_db_field": "Bordesholmer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bornhoveder-see-bornhoveder-see1", "target_db_field": "Bornhöveder" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-bottschlotter-see", "target_db_field": "Bottschloter" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-brahmsee", "target_db_field": "Brahmsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dieksee-dieksee1", "target_db_field": "Dieksee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-dobersdorfer-see-dobersdorfer-see1", "target_db_field": "Dobersdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-drusensee-drusensee1", "target_db_field": "Drüsensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-einfelder-see-einfelder-see1", "target_db_field": "Einfelder" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-grossensee-grossensee1", "target_db_field": "Großensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ploner-see-kl-ploner-see1", "target_db_field": "Plöner" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-kl-ponitzer-see-kl-ponitzer-see", "target_db_field": "Pönitzer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-ratzeburger-see-ratzeburger-see1", "target_db_field": "Ratzeburger" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gr-segeberger-see-segeberger-see1", "target_db_field": "Segeberger" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-gudower-see-gudower-see1", "target_db_field": "Gudower" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-hohner-see-hohner-see1", "target_db_field": "Hohner" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-langsee-suderfahrenstedt-langsee1", "target_db_field": "Süderfahrenstedt" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-mozener-see-mozener-see1", "target_db_field": "Mözener" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neustadter-binnenwasser1", "target_db_field": "Neustadt" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-neversdorfer-see-neversdorfer-see1", "target_db_field": "Neversdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-passader-see-passader-see1", "target_db_field": "Passader" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-rantumdammsiel-rantumbecken1", "target_db_field": "Rantumdammsiel" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schluensee-schluensee1", "target_db_field": "Schluensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schohsee1", "target_db_field": "Schöhsee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-schwansener-see-fp-schopfwerk1", "target_db_field": "Schwansener" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-seedorfer-see", "target_db_field": "Seedorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sibbersdorfer-see-sibbersdorfer-see", "target_db_field": "Sibbersdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stendorfer-see-stendorfer-see1", "target_db_field": "Stendorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stocksee-stocksee1", "target_db_field": "Stocksee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-stolper-see-stolper-see1", "target_db_field": "Stolper" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-sudensee-sudensee1", "target_db_field": "Südensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suseler-see", "target_db_field": "Süseler" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-suhrer-see1", "target_db_field": "Suhrer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-trammer-see1", "target_db_field": "Trammer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-tresdorfer-see1", "target_db_field": "Tresdorfer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-vierer-see", "target_db_field": "Vierer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-westensee-westensee1", "target_db_field": "Westensee" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-windebyer-noor1", "target_db_field": "Windebyer" }, + { "source_db_id": "see-wasserkorper", "source_db_field": "WK_NAME", "condition": "=", "target_db_id": "wasserstand-pegel-meldorf-kronenloch", "target_db_field": "Meldorf-Kronenloch" } + ], + "options": + { "label_option": "average_depth", "legend_option": "colorVarient" } } diff --git a/package.json b/package.json index e4c4149..db87782 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@heroicons/vue": "^2.2.0", "@nuxt/ui": "3.1.0", "@nuxtjs/i18n": "9.5.4", + "chart.js": "^4.4.9", "chroma-js": "^3.1.2", "leaflet": "^1.9.4", "leaflet-defaulticon-compatibility": "^0.1.2", @@ -27,6 +28,7 @@ "proj4": "^2.15.0", "shpjs": "^6.1.0", "tailwindcss": "4.1.5", + "vue-chartjs": "^5.3.2", "zod": "^3.24.4" }, "devDependencies": { diff --git a/pages/index.vue b/pages/index.vue index 252540a..c8bcefa 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -60,26 +60,26 @@
    - + + +
    -
    -

    - {{ selectedItem.properties.BADEGEWAESSERNAME }} -

    - -
    -
      -
    • {{ t('quality') }}: {{ selectedItem.properties?.EINSTUFUNG_ODER_VORABBEWERTUNG || 'N/A' }}
    • -
    • {{ t('category') }}: {{ selectedItem.properties?.GEWAESSERKATEGORIE || 'N/A' }}
    • -
    • {{ t('depth') }}: {{ selectedItem.properties?.SICHTTIEFE || 'N/A' }} m
    • -
    • {{ t('seasonal') }}: {{ selectedItem.properties?.SAISONBEGINN }} - {{ selectedItem.properties?.SAISONENDE }} {{ selectedItem.properties?.GESCHLOSSEN || 'N/A' }}
    • -
    • {{ t('infrastructure') }}: {{ selectedItem.properties?.INFRASTRUKTUR || 'N/A' }}
    • -
    +
    @@ -88,96 +88,49 @@ diff --git a/components/MyLeafletMap.vue b/components/MyLeafletMap.vue index 0348abb..b2f7452 100644 --- a/components/MyLeafletMap.vue +++ b/components/MyLeafletMap.vue @@ -60,13 +60,19 @@ function generateLabels(data: typeof props.fetchedData) { legend.onAdd = function () { const div = L.DomUtil.create('div', 'info legend'); + div.setAttribute( + 'style', + 'background: white; padding: 8px; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.2);', + ); + uniqueValues.forEach((value) => { const color = colorMap.get(value); div.innerHTML += ` -
    - ${value} -
    `; +
    + ${value} +
    `; }); + return div; }; } @@ -107,14 +113,20 @@ function generateLabels(data: typeof props.fetchedData) { legend.onAdd = function () { const div = L.DomUtil.create('div', 'info legend'); + div.setAttribute( + 'style', + 'background: white; padding: 8px; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.2);', + ); + bins.forEach(([start, end]) => { const label = `${start.toFixed(1)} - ${end.toFixed(1)}`; const color = colorMap.get(label); div.innerHTML += ` -
    - ${label} -
    `; +
    + ${label} +
    `; }); + return div; }; @@ -137,14 +149,14 @@ function generateColor(index: number, total: number): string { } function renderMarkers(data: typeof props.fetchedData) { - if (!data) { + if (!data) return; - } clearMarkers(); clearLegend(); const colorMap = generateLabels(data); + const originalMarkerStyleMap = new Map(); data.features.forEach((feature: any) => { const legendOption = feature.properties.options.legend_option; @@ -166,36 +178,40 @@ function renderMarkers(data: typeof props.fetchedData) { fillOpacity: 0.7, }), pointToLayer: (feature, latlng) => { - return L.circleMarker(latlng, { + const style = { radius: 6, color, fillColor: color, fillOpacity: 0.8, weight: 1, - }); + }; + + const marker = L.circleMarker(latlng, style); + originalMarkerStyleMap.set(marker, style); + return marker; }, onEachFeature: (feature, layer) => { layer.on('click', () => { - if (selectedMarker instanceof L.Path && 'setStyle' in selectedMarker) { - selectedMarker.setStyle({ - weight: 1, - color: '#999999', - }); + if (selectedMarker instanceof L.CircleMarker && originalMarkerStyleMap.has(selectedMarker)) { + selectedMarker.setStyle(originalMarkerStyleMap.get(selectedMarker)); } - if (layer instanceof L.CircleMarker) { layer.setStyle({ radius: 10, weight: 3, color: '#0f172b', + fillColor: '#0f172b', + fillOpacity: 1, }); } + selectedMarker = layer; // eslint-disable-next-line vue/custom-event-name-casing emit('marker-click', feature); }); }, }); + geoJsonLayer.addTo(leafletMap as L.Map); geoJsonLayers.push(geoJsonLayer); }); diff --git a/i18n/locales/de.json b/i18n/locales/de.json index c70af58..424c1a1 100644 --- a/i18n/locales/de.json +++ b/i18n/locales/de.json @@ -12,5 +12,11 @@ "selectedDate": "Gewähltes Datum", "waterLevelOfLake": "Wasserpegel des Sees", "waterLevel": "Wasserpegel", - "notAvailable": "Nicht verfügbar" + "notAvailable": "Nicht verfügbar", + "loadingText": "Laden der Daten, bitte warten...", + "chartX": "Datum", + "chartY": "Tiefe (m)", + "chartTitle": "Tiefe für", + "chartLegend": "Tiefe im Zeitverlauf", + "chartEmpty": "Es sind keine Tiefenangaben verfügbar für" } diff --git a/i18n/locales/en.json b/i18n/locales/en.json index ab531dc..659e703 100644 --- a/i18n/locales/en.json +++ b/i18n/locales/en.json @@ -12,5 +12,11 @@ "selectedDate": "Selected Date", "waterLevelOfLake": "Water level of lake", "waterLevel": "Water level", - "notAvailable": "Not Available" + "notAvailable": "Not Available", + "loadingText": "Loading data, please wait...", + "chartX": "Date", + "chartY": "Depth (m)", + "chartTitle": "Depth for", + "chartLegend": "Depth Over Time", + "chartEmpty": "No recorded depths are available for" } diff --git a/pages/index.vue b/pages/index.vue index c8bcefa..f34c0a3 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -60,6 +60,13 @@
    +
    + +
    +