diff --git a/.env.development b/.env.development index 85ec8a3ad..65ecc5b74 100644 --- a/.env.development +++ b/.env.development @@ -25,4 +25,4 @@ NEXT_PUBLIC_USE_MOCKS=true NEXT_PUBLIC_BASE_PATH=/talas5 # Oder leer lassen für direkten Zugriff -> NEXT_PUBLIC_BASE_PATH= # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.1.307 +NEXT_PUBLIC_APP_VERSION=1.1.309 diff --git a/.env.production b/.env.production index 44a446fd8..26a705de6 100644 --- a/.env.production +++ b/.env.production @@ -26,4 +26,4 @@ NEXT_PUBLIC_BASE_PATH=/talas5 # Oder leer lassen für direkten Zugriff -> NEXT_PUBLIC_BASE_PATH= # App-Versionsnummer -NEXT_PUBLIC_APP_VERSION=1.1.307 \ No newline at end of file +NEXT_PUBLIC_APP_VERSION=1.1.309 diff --git a/components/devices/hooks/useDynamicDeviceLayers.js b/components/devices/hooks/useDynamicDeviceLayers.js index c60612a8e..32f452ee3 100644 --- a/components/devices/hooks/useDynamicDeviceLayers.js +++ b/components/devices/hooks/useDynamicDeviceLayers.js @@ -70,7 +70,7 @@ const useDynamicDeviceLayers = (map, GisSystemStatic, mapLayersVisibility, prior const editMode = localStorage.getItem("editMode") === "true"; Object.entries(markerStates).forEach(([key, markers]) => { - const isVisible = mapLayersVisibility[key]; + const isVisible = mapLayersVisibility[key] ?? true; // undefined = true markers.forEach(marker => { const hasLayer = map.hasLayer(marker); diff --git a/components/hooks/useStationCache.js b/components/hooks/useStationCache.js new file mode 100644 index 000000000..e69de29bb diff --git a/components/mainComponent/MapComponent.js b/components/mainComponent/MapComponent.js index 84e3c200f..2ef0eb14c 100644 --- a/components/mainComponent/MapComponent.js +++ b/components/mainComponent/MapComponent.js @@ -834,30 +834,6 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { } }, [poiIconsData, poiIconsStatus]); //----------------------------------------------------------------- - useEffect(() => { - if (!map) return; - - const editMode = localStorage.getItem("editMode") === "true"; - - Object.entries(markerStates).forEach(([systemName, markers]) => { - const isVisible = mapLayersVisibility[systemName]; - markers.forEach(marker => { - const hasLayer = map.hasLayer(marker); - if (editMode || !isVisible) { - if (hasLayer) map.removeLayer(marker); - } else { - if (!hasLayer) marker.addTo(map); - } - }); - }); - - // optional für alle zusammen - const allMarkers = Object.values(markerStates) - .filter(entry => Array.isArray(entry)) - .flat(); - - checkOverlappingMarkers(map, allMarkers, plusRoundIcon); - }, [map, markerStates, mapLayersVisibility]); //---------------------------------------------- useEffect(() => { @@ -933,6 +909,21 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { }, [GisStationsStaticDistrict]); const { Points = [] } = useSelector(selectGisStationsStaticDistrict); useEffect(() => {}, [triggerUpdate]); + //-------------------------------------------------------------------------------- + useEffect(() => { + console.log("📊 GisSystemStatic:", GisSystemStatic); + }, [GisSystemStatic]); + useEffect(() => { + if (Array.isArray(GisSystemStatic)) { + GisSystemStatic.forEach(system => { + const key = `system-${system.IdSystem}`; + if (!(key in mapLayersVisibility)) { + dispatch(setLayerVisibility({ key, value: true })); // Sichtbarkeit aktivieren + } + }); + } + }, [GisSystemStatic, mapLayersVisibility, dispatch]); + //--------------------------------------------- //-------------------------------------------- return ( diff --git a/nodemap-1.1.305.zip b/nodemap-1.1.305.zip deleted file mode 100644 index d653fb146..000000000 Binary files a/nodemap-1.1.305.zip and /dev/null differ diff --git a/package-lock.json b/package-lock.json index 7e1b6b93a..d90ff1e9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nodemap", - "version": "1.1.307", + "version": "1.1.309", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nodemap", - "version": "1.1.307", + "version": "1.1.309", "dependencies": { "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", diff --git a/package.json b/package.json index 2129913ad..8fb4dd1da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodemap", - "version": "1.1.307", + "version": "1.1.309", "dependencies": { "@emotion/react": "^11.13.3", "@emotion/styled": "^11.13.0", diff --git a/server.js b/server.js index 066b7e840..740073e99 100644 --- a/server.js +++ b/server.js @@ -33,10 +33,15 @@ app.prepare().then(() => { const io = new Server(server); + // ✅ Globaler Cache für alle aktuellen Daten + const globalDataCache = new Map(); + io.on("connection", socket => { const { m: idMap, u: idUser } = socket.handshake.query; console.log(`🔌 WebSocket verbunden (idMap=${idMap}, idUser=${idUser})`); + const cacheKey = `${idMap}_${idUser}`; + const endpoints = [ { name: "GisLinesStatus", @@ -69,6 +74,22 @@ app.prepare().then(() => { const lastDataMap = {}; + // ✅ Funktion um sofort alle verfügbaren Daten zu senden (für Browser-Reload) + const sendAllCurrentData = () => { + const cachedData = globalDataCache.get(cacheKey); + if (cachedData && Object.keys(cachedData).length > 0) { + console.log( + `📦 Sending all current data to client (${Object.keys(cachedData).length} endpoints)` + ); + Object.entries(cachedData).forEach(([name, data]) => { + socket.emit(`${name}Updated`, data); + console.log(`🔄 Browser-Reload: ${name} data sent`); + }); + } else { + console.log(`📭 No cached data available for ${cacheKey}, will fetch fresh data`); + } + }; + const fetchData = async () => { for (const { name, getUrl, mock } of endpoints) { try { @@ -99,6 +120,14 @@ app.prepare().then(() => { } const newDataStr = JSON.stringify(statis); + + // ✅ Cache aktualisieren + if (!globalDataCache.has(cacheKey)) { + globalDataCache.set(cacheKey, {}); + } + globalDataCache.get(cacheKey)[name] = statis; + + // ✅ Nur bei Änderungen senden (setInterval-Logik) if (newDataStr !== lastDataMap[name]) { lastDataMap[name] = newDataStr; socket.emit(`${name}Updated`, statis); @@ -113,9 +142,15 @@ app.prepare().then(() => { } }; - // fetchData immer ausführen – unabhängig vom Modus + // ✅ Beim Connect: Sofort alle aktuellen Daten senden (für Browser-Reload) + sendAllCurrentData(); + + // ✅ Dann erste Datenabfrage durchführen fetchData(); + + // ✅ setInterval für regelmäßige Updates (nur bei Änderungen) const interval = setInterval(fetchData, 5000); // 5 Sekunden ,TALAS.web nutzt 12 Sekunden + socket.on("disconnect", () => { clearInterval(interval); console.log("❌ WebSocket getrennt"); diff --git a/services/localStorage/stationCacheService.js b/services/localStorage/stationCacheService.js new file mode 100644 index 000000000..e69de29bb diff --git a/services/webservice/idsystemTypFilterService.js b/services/webservice/idsystemTypFilterService.js new file mode 100644 index 000000000..e69de29bb diff --git a/utils/devices/createAndSetDevices.js b/utils/devices/createAndSetDevices.js index ffd8a06f0..daa0240c4 100644 --- a/utils/devices/createAndSetDevices.js +++ b/utils/devices/createAndSetDevices.js @@ -30,7 +30,8 @@ export const createAndSetDevices = async ( const systemConfig = Array.isArray(GisSystemStatic) ? GisSystemStatic.find(sys => sys.IdSystem === systemId) : null; - if (!systemConfig || systemConfig.Allow !== 1) { + if (!systemConfig) { + console.warn(`🚫 Kein Marker für System ${systemId}, Allow = ${systemConfig?.Allow}`); setMarkersFunction([]); return; } @@ -42,7 +43,8 @@ export const createAndSetDevices = async ( const statusDistrictData = selectGisStationsStatusDistrict(state); const measurementData = selectGisStationsMeasurements(state); - if (!staticDistrictData?.Points?.length || !statusDistrictData?.length) return; + if (!staticDistrictData?.Points?.length) return; + const hasStatus = Array.isArray(statusDistrictData) && statusDistrictData.length > 0; const statisMap = new Map(statusDistrictData.map(s => [s.IdLD, s])); const measurementsMap = new Map(); diff --git a/utils/filters/idsystemTypFilter.js b/utils/filters/idsystemTypFilter.js new file mode 100644 index 000000000..e69de29bb