From cede717994151631374a85209fcd38c9c70b3963 Mon Sep 17 00:00:00 2001 From: Julio Cesar Date: Wed, 20 Aug 2025 16:14:36 +0200 Subject: [PATCH] fixing deployment errors --- src/components/map/RawMapLibre.vue | 67 ++++++++++++++++++++++-------- src/composables/useMeters.ts | 3 +- src/views/MapView.vue | 6 +-- test-backend/package.json | 5 +-- test-backend/tsconfig.json | 3 +- 5 files changed, 58 insertions(+), 26 deletions(-) diff --git a/src/components/map/RawMapLibre.vue b/src/components/map/RawMapLibre.vue index 5657163..f359e8f 100644 --- a/src/components/map/RawMapLibre.vue +++ b/src/components/map/RawMapLibre.vue @@ -34,6 +34,8 @@ const emit = defineEmits<{ const mapContainer = useTemplateRef("mapContainer") let map: Map | null = null +// Hold geojson updates that arrive before the source is available. +let pendingGeojson: GeoJSON.FeatureCollection | null = null // A simple function to generate a large dummy GeoJSON dataset in Saudi Arabia for demonstration. // In a real application, this data would be passed in via props, likely streamed @@ -77,14 +79,30 @@ const addLayersAndSources = () => { } // Add a new source from the GeoJSON data with clustering enabled. + // Use latest available data: prefer the incoming prop, then any pending update, + // then the initial mapData fallback. + const initialData = props.geojson || pendingGeojson || mapData + map.addSource("meters", { type: "geojson", - data: mapData, + data: initialData, cluster: true, clusterMaxZoom: 14, // Max zoom to cluster points on clusterRadius: 50, // Radius of each cluster in pixels }) + // If updates arrived before the source existed, apply them now. + if (pendingGeojson) { + const src = map.getSource("meters") as GeoJSONSource + try { + src.setData(pendingGeojson) + pendingGeojson = null + } catch (e) { + // ignore if source isn't ready for some reason; watcher will retry + console.warn("Failed to apply pending geojson to source:", e) + } + } + // Add the 'clusters' layer for the cluster circles. map.addLayer({ id: "clusters", @@ -224,19 +242,19 @@ onMounted(() => { if (!map?.hasImage("meter-icon")) { map?.addImage("meter-icon", image) } - - // Wait for the map to load before adding the source and layers. - map?.on("load", () => { - addLayersAndSources() - - // Emit center updates to support v-model:center when the map finishes moving. - map?.on("moveend", () => { - if (!map) return - const centerArray = map.getCenter().toArray() as LngLatLike - emit("update:center", centerArray) - }) - }) } + + // Wait for the map to load before adding the source and layers. + map.on("load", () => { + addLayersAndSources() + + // Emit center updates to support v-model:center when the map finishes moving. + map?.on("moveend", () => { + if (!map) return + const centerArray = map.getCenter().toArray() as LngLatLike + emit("update:center", centerArray) + }) + }) }) onUnmounted(() => { @@ -250,11 +268,26 @@ onUnmounted(() => { watch( () => props.geojson, (newGeojson) => { - if (map && map.isSourceLoaded("meters") && newGeojson) { + if (!newGeojson) return + + // If the map isn't ready or the source doesn't exist yet, store it as pending + // so it can be applied once the source is added. + if (!map || !map.getSource("meters")) { + pendingGeojson = newGeojson + return + } + + // Safe update when the source exists. + try { const source = map.getSource("meters") as GeoJSONSource - if (source) { - source.setData(newGeojson) - } + source.setData(newGeojson) + } catch (e) { + // Fallback to pending if setData fails for timing reasons. + console.warn( + "Failed to set data on 'meters' source, queuing pending update:", + e + ) + pendingGeojson = newGeojson } }, { deep: true } diff --git a/src/composables/useMeters.ts b/src/composables/useMeters.ts index 25970ca..d28a25c 100644 --- a/src/composables/useMeters.ts +++ b/src/composables/useMeters.ts @@ -1,8 +1,7 @@ import { ref, type Ref } from "vue" import { type MetersCollection, type MeterFeature } from "shared-types/meters" -const API_BASE_URL = - import.meta.env.VITE_API_BASE_URL || "http://localhost:3001/api" +const API_BASE_URL = import.meta.env.VITE_API_URL || "http://localhost:3001/api" /** * Composable for managing meter data from the backend API diff --git a/src/views/MapView.vue b/src/views/MapView.vue index f759625..cac28ed 100644 --- a/src/views/MapView.vue +++ b/src/views/MapView.vue @@ -28,10 +28,10 @@ const zoom = ref(8) // Default zoom level // Use the meters composable const { metersData, - isLoading: metersLoading, - error: metersError, + // isLoading: metersLoading, + // error: metersError, fetchMeters, - currentMeter, + // currentMeter, } = useMeters() function getLocation() { diff --git a/test-backend/package.json b/test-backend/package.json index 7c74efd..ec7df5f 100644 --- a/test-backend/package.json +++ b/test-backend/package.json @@ -5,11 +5,10 @@ "description": "Express server for serving saudi_meters.json", "main": "app.ts", "scripts": { - "start": "node dist/app.js", + "start": "node dist/test-backend/app.js", "dev": "tsx app.ts", "build": "tsc", - "generate": "node generate_meters.js", - "validate": "node validate_borders.js" + "generate": "node generate_meters.js" }, "dependencies": { "cors": "2.8.5", diff --git a/test-backend/tsconfig.json b/test-backend/tsconfig.json index c3a42b9..d8760b3 100644 --- a/test-backend/tsconfig.json +++ b/test-backend/tsconfig.json @@ -25,7 +25,8 @@ }, "include": [ "*.ts", - "../types/**/*.ts" + "../types/**/*.ts", + "saudi_meters.json" ], "exclude": [ "node_modules",