wip: Dynamische Layers /Geräte Gruppen Erkennung , overlapping funktioniert es noch nicht

This commit is contained in:
ISA
2025-05-28 13:57:34 +02:00
parent d66727e531
commit 85924e575f
7 changed files with 190 additions and 245 deletions

View File

@@ -16,12 +16,11 @@ import { restoreMapSettings, checkOverlappingMarkers } from "../../utils/mapUtil
import { APP_VERSION } from "../../config/appVersion.js"; import { APP_VERSION } from "../../config/appVersion.js";
import * as layers from "../../config/layers.js"; import * as layers from "../../config/layers.js";
import addItemsToMapContextMenu from "../contextmenu/useMapContextMenu.js"; import addItemsToMapContextMenu from "../contextmenu/useMapContextMenu.js";
import useGmaMarkersLayer from "../../hooks/layers/useGmaMarkersLayer.js";
import useSmsfunkmodemMarkersLayer from "../../hooks/layers/useSmsfunkmodemMarkersLayer.js";
import useAreaMarkersLayer from "../../hooks/layers/useAreaMarkersLayer.js"; import useAreaMarkersLayer from "../../hooks/layers/useAreaMarkersLayer.js";
import { setupPolylines } from "../../utils/polylines/setupPolylines.js"; import { setupPolylines } from "../../utils/polylines/setupPolylines.js";
import { setupPOIs } from "../../utils/setupPOIs.js"; import { setupPOIs } from "../../utils/setupPOIs.js";
import useLayerVisibility from "../../hooks/useLayerVisibility.js";
import useLineData from "../../hooks/useLineData.js"; import useLineData from "../../hooks/useLineData.js";
import { useMapComponentState } from "../../hooks/useMapComponentState.js"; import { useMapComponentState } from "../../hooks/useMapComponentState.js";
@@ -69,10 +68,12 @@ import { fetchPoiIconsDataThunk } from "../../redux/thunks/database/pois/fetchPo
import { fetchPoiTypThunk } from "../../redux/thunks/database/pois/fetchPoiTypThunk.js"; import { fetchPoiTypThunk } from "../../redux/thunks/database/pois/fetchPoiTypThunk.js";
import { updateAreaThunk } from "../../redux/thunks/database/area/updateAreaThunk"; import { updateAreaThunk } from "../../redux/thunks/database/area/updateAreaThunk";
import useDynamicDeviceLayers from "../../hooks/layers/useDynamicDeviceLayers";
//----------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
//------------------------------- //-------------------------------
const dispatch = useDispatch(); const dispatch = useDispatch();
const countdown = useSelector((state) => state.polylineContextMenu.countdown); const countdown = useSelector((state) => state.polylineContextMenu.countdown);
const countdownActive = useSelector((state) => state.polylineContextMenu.countdownActive); const countdownActive = useSelector((state) => state.polylineContextMenu.countdownActive);
const isPolylineContextMenuOpen = useSelector((state) => state.polylineContextMenu.isOpen); const isPolylineContextMenuOpen = useSelector((state) => state.polylineContextMenu.isOpen);
@@ -109,7 +110,6 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const [isPopupOpen, setIsPopupOpen] = useState(false); const [isPopupOpen, setIsPopupOpen] = useState(false);
const closePopup = () => setIsPopupOpen(false); const closePopup = () => setIsPopupOpen(false);
const [currentCoordinates, setCurrentCoordinates] = useState(""); const [currentCoordinates, setCurrentCoordinates] = useState("");
const [AddPoiModalWindowState, setAddPoiModalWindowState] = useState(false);
const [showPoiUpdateModal, setShowPoiUpdateModal] = useState(false); const [showPoiUpdateModal, setShowPoiUpdateModal] = useState(false);
const [currentPoiData, setCurrentPoiData] = useState(null); const [currentPoiData, setCurrentPoiData] = useState(null);
const [showVersionInfoModal, setShowVersionInfoModal] = useState(false); const [showVersionInfoModal, setShowVersionInfoModal] = useState(false);
@@ -119,7 +119,7 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
const [map, setMap] = useState(null); // Zustand der Karteninstanz const [map, setMap] = useState(null); // Zustand der Karteninstanz
const [oms, setOms] = useState(null); // State für OMS-Instanz const [oms, setOms] = useState(null); // State für OMS-Instanz
const [GisStationsMeasurements, setGisStationsMeasurements] = useState([]); // Zustand für Messdaten
//-----userRights---------------- //-----userRights----------------
const isRightsLoaded = useSelector((state) => state.gisUserRightsFromWebservice.status === "succeeded"); const isRightsLoaded = useSelector((state) => state.gisUserRightsFromWebservice.status === "succeeded");
const userRights = useSelector(selectGisUserRightsFromWebservice); const userRights = useSelector(selectGisUserRightsFromWebservice);
@@ -137,24 +137,6 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
//console.log("priorityConfig in MapComponent1: ", priorityConfig); //console.log("priorityConfig in MapComponent1: ", priorityConfig);
//----------------------------------------- //-----------------------------------------
const [gmaMarkers, setGmaMarkers] = useState([]); //--------------------station.System === 11 alle sind untetschiedlich Nummern
const [talasMarkers, setTalasMarkers] = useState([]);
const [eciMarkers, setEciMarkers] = useState([]);
const [lteModemMarkers, setlteModemMarkers] = useState([]);
const [ciscoRouterMarkers, setCiscoRouterMarkers] = useState([]);
const [wagoMarkers, setWagoMarkers] = useState([]);
const [siemensMarkers, setSiemensMarkers] = useState([]);
const [otdrMarkers, setOtdrMarkers] = useState([]);
const [wdmMarkers, setWdmMarkers] = useState([]);
const [messstellenMarkers, setMessstellenMarkers] = useState([]);
const [talasiclMarkers, setTalasiclMarkers] = useState([]);
const [dauzMarkers, setDauzMarkers] = useState([]);
const [smsfunkmodemMarkers, setSmsfunkmodemMarkers] = useState([]);
const [ulafMarkers, setUlafMarkers] = useState([]);
const [sonstigeMarkers, setSonstigeMarkers] = useState([]);
const [tkComponentsMarkers, setTkComponentsMarkers] = useState([]);
//--------------------------------------------
const [linePositions, setLinePositions] = useState([]); const [linePositions, setLinePositions] = useState([]);
const { lineColors, tooltipContents } = useLineData(); const { lineColors, tooltipContents } = useLineData();
const [polylines, setPolylines] = useState([]); const [polylines, setPolylines] = useState([]);
@@ -166,6 +148,7 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const [showCoordinatesModal, setShowCoordinatesModal] = useState(false); const [showCoordinatesModal, setShowCoordinatesModal] = useState(false);
const [popupCoordinates, setPopupCoordinates] = useState(null); const [popupCoordinates, setPopupCoordinates] = useState(null);
const [popupVisible, setPopupVisible] = useState(false); const [popupVisible, setPopupVisible] = useState(false);
const [poiData, setPoiData] = useState([]);
const openVersionInfoModal = () => { const openVersionInfoModal = () => {
setShowVersionInfoModal(true); setShowVersionInfoModal(true);
@@ -187,43 +170,6 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
} }
}); });
const allMarkers = [
...talasMarkers,
...eciMarkers,
...lteModemMarkers,
...ciscoRouterMarkers,
...wagoMarkers,
...siemensMarkers,
...otdrMarkers,
...wdmMarkers,
...gmaMarkers,
...messstellenMarkers,
...talasiclMarkers,
...dauzMarkers,
...smsfunkmodemMarkers,
...sonstigeMarkers,
...tkComponentsMarkers,
...ulafMarkers,
];
//--------------------------------------------
const gmaLayerRef = useRef(null);
const talasLayerRef = useRef(null);
const eciMarkersLayerRef = useRef(null);
const lteModemMarkersLayerRef = useRef(null);
const ciscoRouterMarkersLayerRef = useRef(null);
const wagoMarkersLayerRef = useRef(null);
const siemensMarkersLayerRef = useRef(null);
const otdrMarkersLayerRef = useRef(null);
const wdmMarkersLayerRef = useRef(null);
const messstellenMarkersLayerRef = useRef(null);
const talasiclMarkersLayerRef = useRef(null);
const dauzMarkersLayerRef = useRef(null);
const smsfunkmodemMarkersLayerRef = useRef(null);
const ulafMarkersLayerRef = useRef(null);
const sonstigeMarkersLayerRef = useRef(null);
const tkComponentsMarkersRef = useRef(null);
//------------------------------
const [poiData, setPoiData] = useState([]);
//-------------------------------------------- //--------------------------------------------
const handleCoordinatesSubmit = (coords) => { const handleCoordinatesSubmit = (coords) => {
@@ -234,7 +180,7 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}; };
//-----------------------------Map Initialisierung---------------- //-----------------------------Map Initialisierung----------------
useInitializeMap(map, mapRef, setMap, setOms, setMenuItemAdded, addItemsToMapContextMenu, hasRights, (value) => dispatch(setDisabled(value))); useInitializeMap(map, mapRef, setMap, setOms, setMenuItemAdded, addItemsToMapContextMenu, hasRights, (value) => dispatch(setDisabled(value)));
//--------------------------------------------------------------------
//-------------------------React Hooks-------------------------------- //-------------------------React Hooks--------------------------------
useEffect(() => { useEffect(() => {
if (linesData && Array.isArray(linesData)) { if (linesData && Array.isArray(linesData)) {
@@ -316,51 +262,6 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
} }
}, [map, zoomTrigger]); }, [map, zoomTrigger]);
//-------------------------------------------- //--------------------------------------------
useEffect(() => {
if (map) {
// Sammle alle Marker in einer einzigen Liste
const editMode = localStorage.getItem("editMode") === "true"; // EditMode prüfen
const visibility = mapLayersVisibility || {};
allMarkers.forEach((marker) => {
const layerKey = marker.options?.layerKey; // Layer-Key aus den Marker-Optionen
const isVisible = visibility[layerKey]; // Sichtbarkeitsstatus prüfen
if (!layerKey || isVisible === undefined) return;
if (editMode || !isVisible) {
// Entferne Marker, wenn EditMode aktiv ist oder Layer unsichtbar
if (map.hasLayer(marker)) map.removeLayer(marker);
} else {
// Füge Marker hinzu, wenn EditMode deaktiviert ist und Layer sichtbar
if (!map.hasLayer(marker)) marker.addTo(map);
}
});
// Überprüfe überlappende Marker und füge das "Plus"-Icon hinzu
checkOverlappingMarkers(map, allMarkers, plusRoundIcon);
}
}, [
map,
talasMarkers,
eciMarkers,
lteModemMarkers,
ciscoRouterMarkers,
wagoMarkers,
siemensMarkers,
otdrMarkers,
wdmMarkers,
gmaMarkers,
messstellenMarkers,
talasiclMarkers,
dauzMarkers,
smsfunkmodemMarkers,
sonstigeMarkers,
tkComponentsMarkers,
ulafMarkers,
mapLayersVisibility, // Neu: Abhängigkeit für Sichtbarkeitsstatus
]);
//----------------------------------------------------------------- //-----------------------------------------------------------------
//Tooltip an mouse position anzeigen für die Linien //Tooltip an mouse position anzeigen für die Linien
@@ -534,128 +435,9 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
initializeContextMenu(); initializeContextMenu();
}, [map]); }, [map]);
//--------------hooks-------------------------------------------
useGmaMarkersLayer(
map,
gmaMarkers,
GisStationsMeasurements,
layers.MAP_LAYERS.GMA,
oms,
mapLayersVisibility.GMA // Übergebe die Sichtbarkeitsbedingung als Parameter
);
//--------------------------------------------
//useCreateAndSetDevices(1, talasMarkers, GisSystemStatic, priorityConfig);
useLayerVisibility(map, talasMarkers, mapLayersVisibility, "TALAS", oms);
useLayerVisibility(map, eciMarkers, mapLayersVisibility, "ECI", oms);
useLayerVisibility(map, lteModemMarkers, mapLayersVisibility, "LTEModem", oms);
useLayerVisibility(map, ciscoRouterMarkers, mapLayersVisibility, "CiscoRouter", oms);
//useLayerVisibility(map, lteModemMarkers, mapLayersVisibility, "LTEModem", oms);
useLayerVisibility(map, wagoMarkers, mapLayersVisibility, "WAGO", oms);
useLayerVisibility(map, siemensMarkers, mapLayersVisibility, "Siemens", oms);
useLayerVisibility(map, otdrMarkers, mapLayersVisibility, "OTDR", oms);
useLayerVisibility(map, wdmMarkers, mapLayersVisibility, "WDM", oms);
useLayerVisibility(map, gmaMarkers, mapLayersVisibility, "GMA", oms);
useLayerVisibility(map, sonstigeMarkers, mapLayersVisibility, "Sonstige", oms);
useLayerVisibility(map, tkComponentsMarkers, mapLayersVisibility, "TKKomponenten", oms);
useLayerVisibility(map, talasiclMarkers, mapLayersVisibility, "TALASICL", oms);
useLayerVisibility(map, dauzMarkers, mapLayersVisibility, "DAUZ", oms);
useLayerVisibility(map, smsfunkmodemMarkers, mapLayersVisibility, "SMSModem", oms);
useLayerVisibility(map, messstellenMarkers, mapLayersVisibility, "Messstellen", oms);
useLayerVisibility(map, ulafMarkers, mapLayersVisibility, "ULAF", oms);
//--------------------------------------------
useEffect(() => {
if (gisSystemStaticStatus !== "succeeded" || !map) return;
const layerGroups = [
{ ref: gmaLayerRef, id: 11, setState: setGmaMarkers },
{ ref: talasLayerRef, id: 1, setState: setTalasMarkers },
{ ref: eciMarkersLayerRef, id: 2, setState: setEciMarkers },
{ ref: lteModemMarkersLayerRef, id: 5, setState: setlteModemMarkers },
{ ref: ciscoRouterMarkersLayerRef, id: 6, setState: setCiscoRouterMarkers },
{ ref: wagoMarkersLayerRef, id: 7, setState: setWagoMarkers },
{ ref: siemensMarkersLayerRef, id: 8, setState: setSiemensMarkers },
{ ref: otdrMarkersLayerRef, id: 9, setState: setOtdrMarkers },
{ ref: wdmMarkersLayerRef, id: 10, setState: setWdmMarkers },
{ ref: messstellenMarkersLayerRef, id: 13, setState: setMessstellenMarkers },
{ ref: talasiclMarkersLayerRef, id: 100, setState: setTalasiclMarkers },
{ ref: dauzMarkersLayerRef, id: 110, setState: setDauzMarkers },
{ ref: smsfunkmodemMarkersLayerRef, id: 111, setState: setSmsfunkmodemMarkers },
{ ref: ulafMarkersLayerRef, id: 0, setState: setUlafMarkers },
{ ref: sonstigeMarkersLayerRef, id: 200, setState: setSonstigeMarkers },
{ ref: tkComponentsMarkersRef, id: 30, setState: setTkComponentsMarkers },
];
// Initialisiere LayerGroups nur einmal
layerGroups.forEach(({ ref }) => {
if (!ref.current) {
ref.current = new L.LayerGroup().addTo(map);
}
});
//--------------------------------------------
const updateMarkers = ({ ref, id, setState }) => {
if (ref.current) {
ref.current.clearLayers(); // Entferne alte Marker
}
// Erstelle und füge neue Marker hinzu
createAndSetDevices(
id,
(newMarkers) => {
setState(newMarkers); // Zustand aktualisieren
newMarkers.forEach((marker) => ref.current.addLayer(marker)); // Marker zur LayerGroup hinzufügen
// Überprüfe auf überlappende Marker und füge das Plus-Icon hinzu
checkOverlappingMarkers(map, newMarkers, plusRoundIcon);
},
GisSystemStatic,
priorityConfig
);
};
// Aktualisiere alle Marker-Gruppen
const updateAllMarkers = () => {
layerGroups.forEach(updateMarkers);
};
// Initiales Update
updateAllMarkers();
// Setze ein Intervall für regelmäßige Updates
const intervalId = setInterval(() => {
updateAllMarkers();
if (map) {
// console.log("🔥 Automatischer Klick-Event ausgelöst, um Spiderfy zu aktualisieren.");
map.fire("click");
}
if (isPolylineContextMenuOpen) {
dispatch(closePolylineContextMenu()); // Schließe das Kontextmenü, bevor das nächste Update passiert
}
if (map) {
// console.log("🔥 nochmal klick.");
map.fire("click");
}
}, 20000);
// Aufräumen bei Komponentenentladung
return () => {
clearInterval(intervalId); // Entferne Intervall
// LayerGroups leeren
layerGroups.forEach(({ ref }) => {
if (ref.current) {
ref.current.clearLayers();
}
});
};
}, [map, GisSystemStatic, priorityConfig]);
//--------------------------------------- //---------------------------------------
// Initialisiere Leaflet-Karte // Initialisiere Leaflet-Karte
// Rufe useAreaMarkersLayer direkt auf // Rufe useAreaMarkersLayer direkt auf
//const [areaUrl, setAreaUrl] = useState(null);
const urlParams = new URLSearchParams(window.location.search); // URL-Parameter parsen const urlParams = new URLSearchParams(window.location.search); // URL-Parameter parsen
const mValue = urlParams.get("m"); // Wert von "m" holen const mValue = urlParams.get("m"); // Wert von "m" holen
const hostname = window.location.hostname; // Dynamischer Hostname const hostname = window.location.hostname; // Dynamischer Hostname
@@ -706,18 +488,21 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}, [areaMarkers, map]); }, [areaMarkers, map]);
//---------------------------------- //----------------------------------
const { markerStates, layerRefs } = useDynamicDeviceLayers(map, GisSystemStatic, mapLayersVisibility, priorityConfig);
useEffect(() => { useEffect(() => {
const handleVisibilityChange = () => { const handleVisibilityChange = () => {
// Erneut die Marker-Überprüfung auslösen if (!map) return;
const allMarkers = Object.values(markerStates).filter(Array.isArray).flat();
checkOverlappingMarkers(map, allMarkers, plusRoundIcon); checkOverlappingMarkers(map, allMarkers, plusRoundIcon);
}; };
window.addEventListener("visibilityChanged", handleVisibilityChange); window.addEventListener("visibilityChanged", handleVisibilityChange);
return () => { return () => {
window.removeEventListener("visibilityChanged", handleVisibilityChange); window.removeEventListener("visibilityChanged", handleVisibilityChange);
}; };
}, [map, allMarkers]); }, [map, markerStates]);
//--------------------------------------- //---------------------------------------
useEffect(() => { useEffect(() => {
@@ -881,6 +666,35 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
setPoiData(poiIconsData); setPoiData(poiIconsData);
} }
}, [poiIconsData, poiIconsStatus]); }, [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]);
//--------------------------------------------- //---------------------------------------------
//-------------------------------------------- //--------------------------------------------

View File

@@ -1,2 +1,2 @@
// /config/appVersion // /config/appVersion
export const APP_VERSION = "1.1.201"; export const APP_VERSION = "1.1.202";

View File

@@ -0,0 +1,20 @@
// /config/devicesGroupLayers.js
export const devicesGroupLayers = [
{ id: 1, name: "TALAS", ref: talasLayerRef, setState: setTalasMarkers },
{ id: 2, name: "ECI", ref: eciLayerRef, setState: setEciMarkers },
{ id: 3, name: "ULAF", ref: ulafLayerRef, setState: setUlafMarkers },
{ id: 5, name: "LTE Modem", ref: lteModemLayerRef, setState: setLteModemMarkers },
{ id: 6, name: "Cisco Router", ref: ciscoRouterLayerRef, setState: setCiscoRouterMarkers },
{ id: 7, name: "WAGO", ref: wagoLayerRef, setState: setWagoMarkers },
{ id: 8, name: "Siemens", ref: siemensLayerRef, setState: setSiemensMarkers },
{ id: 9, name: "OTDR", ref: otdrLayerRef, setState: setOtdrMarkers },
{ id: 10, name: "WDM", ref: wdmLayerRef, setState: setWdmMarkers },
{ id: 11, name: "GMA", ref: gmaLayerRef, setState: setGmaMarkers },
{ id: 13, name: "Messstellen", ref: messstellenLayerRef, setState: setMessstellenMarkers },
{ id: 30, name: "TK-Komponenten", ref: tkKomponentenLayerRef, setState: setTkKomponentenMarkers },
{ id: 100, name: "TALAS ICL", ref: talasiclLayerRef, setState: setTalasiclMarkers },
{ id: 110, name: "DAUZ", ref: dauzLayerRef, setState: setDauzMarkers },
{ id: 111, name: "SMS Modem", ref: smsModemLayerRef, setState: setSmsModemMarkers },
{ id: 200, name: "Sonstige", ref: sonLayerRef, setState: setSonMarkers },
];

View File

@@ -88,3 +88,53 @@ Dieses Dokument beschreibt die technische Gesamtarchitektur des Projekts **NodeM
- [`env.local.schema.md`](./env.local.schema.md) - [`env.local.schema.md`](./env.local.schema.md)
- [`redux/slices/`](./redux/slices/) - [`redux/slices/`](./redux/slices/)
- [`services/webservice/`](./services/webservice/) - [`services/webservice/`](./services/webservice/)
---
## Dynamische Layer-Verwaltung mit Redux
```mermaid
flowchart TD
%% Webservice
subgraph Webservice
A1[GisSystemStatic API]
A2[GisStationsStaticDistrict API]
end
%% Redux
subgraph Redux
B1[fetchGisSystemStaticThunk]
B2[fetchGisStationsStaticDistrictThunk]
C1["gisSystemStaticSlice → selectGisSystemStatic"]
C2["gisStationsStaticDistrictSlice → selectGisStationsStaticDistrict"]
C3["mapLayersSlice → mapLayersVisibility"]
end
%% React
subgraph React-Komponente
D1[MapComponent.js]
D2["useEffect: dynamische Layer"]
D3["createAndSetDevices"]
D4["layerRefs (useRef)"]
D5["markerStates (useState)"]
D6["useEffect: Sichtbarkeit prüfen"]
D7["Map aktualisieren / add/remove"]
D8["checkOverlappingMarkers"]
end
%% Datenfluss
A1 --> B1 --> C1 --> D2
A2 --> B2 --> C2 --> D3
C3 --> D6
D2 --> D3
D3 --> D4
D3 --> D5
D5 --> D6
D6 --> D7
D6 --> D8
D7 --> D1
```

View File

@@ -0,0 +1,68 @@
import { useEffect, useRef, useState } from "react";
import L from "leaflet";
import { createAndSetDevices } from "../../utils/devices/createAndSetDevices";
import { checkOverlappingMarkers } from "../../utils/mapUtils";
import plusRoundIcon from "../../components/icons/devices/overlapping/PlusRoundIcon";
/**
* Dynamisch GIS-System-Marker erstellen & Sichtbarkeit steuern.
* @param {object} map - Leaflet Map-Instanz
* @param {Array} GisSystemStatic - Liste der Systeme aus Webservice
* @param {object} mapLayersVisibility - Redux-Objekt mit Layer-Sichtbarkeiten
* @param {object} priorityConfig - Konfig für Prioritäten
* @returns {{ markerStates, layerRefs }} Alle Marker und Referenzen
*/
const useDynamicDeviceLayers = (map, GisSystemStatic, mapLayersVisibility, priorityConfig) => {
const [markerStates, setMarkerStates] = useState({});
const layerRefs = useRef({});
// Marker initialisieren
useEffect(() => {
if (!map || GisSystemStatic.length === 0) return;
GisSystemStatic.forEach(({ Name, IdSystem }) => {
if (!layerRefs.current[Name]) {
layerRefs.current[Name] = new L.LayerGroup().addTo(map);
}
createAndSetDevices(
IdSystem,
(newMarkers) => {
setMarkerStates((prev) => ({ ...prev, [Name]: newMarkers }));
newMarkers.forEach((m) => layerRefs.current[Name].addLayer(m));
checkOverlappingMarkers(map, newMarkers, plusRoundIcon);
},
GisSystemStatic,
priorityConfig
);
});
}, [map, GisSystemStatic, priorityConfig]);
// Sichtbarkeit aktualisieren
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);
}
});
});
const allMarkers = Object.values(markerStates)
.filter(Array.isArray) // nur Arrays zulassen
.flat();
checkOverlappingMarkers(map, allMarkers, plusRoundIcon);
}, [map, markerStates, mapLayersVisibility]);
return { markerStates, layerRefs };
};
export default useDynamicDeviceLayers;

View File

@@ -161,6 +161,6 @@ export const createAndSetDevices = async (systemId, setMarkersFunction, GisSyste
setMarkersFunction(markersData); setMarkersFunction(markersData);
} catch (error) { } catch (error) {
console.error("❌ Fehler in createAndSetDevices.js (Redux-Version):", error); console.error("❌ Fehler in createAndSetDevices.js (Redux-Version):", error.message, error.stack);
} }
}; };

View File

@@ -22,12 +22,15 @@ export const restoreMapSettings = (map) => {
let plusMarkers = []; let plusMarkers = [];
export const checkOverlappingMarkers = (map, markers, plusIcon) => { export const checkOverlappingMarkers = (map, markers, plusIcon) => {
if (!Array.isArray(markers)) {
console.warn("⚠️ checkOverlappingMarkers erwartet ein Array, aber erhielt:", markers);
return;
}
const overlappingGroups = {}; const overlappingGroups = {};
// Gruppiere Marker basierend auf ihrer Position
markers.forEach((marker) => { markers.forEach((marker) => {
if (map.hasLayer(marker)) { if (map.hasLayer(marker)) {
// Überprüfen, ob der Marker sichtbar ist
const latlngStr = marker.getLatLng().toString(); const latlngStr = marker.getLatLng().toString();
if (overlappingGroups[latlngStr]) { if (overlappingGroups[latlngStr]) {
overlappingGroups[latlngStr].push(marker); overlappingGroups[latlngStr].push(marker);
@@ -37,37 +40,27 @@ export const checkOverlappingMarkers = (map, markers, plusIcon) => {
} }
}); });
// Entferne alte Plus-Icons // alte PlusIcons entfernen
plusMarkers.forEach((plusMarker) => map.removeLayer(plusMarker)); plusMarkers.forEach((plusMarker) => map.removeLayer(plusMarker));
plusMarkers = []; plusMarkers = [];
// Füge Plus-Icons für überlappende Marker hinzu // neue PlusIcons hinzufügen
for (const coords in overlappingGroups) { for (const coords in overlappingGroups) {
if (overlappingGroups[coords].length > 1) { if (overlappingGroups[coords].length > 1) {
const latLng = L.latLng(coords.match(/[-.\d]+/g).map(Number)); const latLng = L.latLng(coords.match(/[-.\d]+/g).map(Number));
const plusMarker = L.marker(latLng, { icon: plusIcon }).addTo(map); const plusMarker = L.marker(latLng, { icon: plusIcon }).addTo(map);
plusMarkers.push(plusMarker); // Speichere das Plus-Icon plusMarkers.push(plusMarker);
plusMarker.on("click", (e) => { plusMarker.on("click", (e) => {
const clickedLatLng = e.latlng; const clickedLatLng = e.latlng;
// Finde nahegelegene Marker (50 Pixel als Beispielradius)
const nearbyMarkers = markers.filter((marker) => map.distance(marker.getLatLng(), clickedLatLng) < 50); const nearbyMarkers = markers.filter((marker) => map.distance(marker.getLatLng(), clickedLatLng) < 50);
console.log("Nearby Markers for Plus Icon:", nearbyMarkers);
if (nearbyMarkers.length > 0) { if (nearbyMarkers.length > 0) {
// Simuliere einen Klick nur auf den ersten Marker
nearbyMarkers[0].fire("click"); nearbyMarkers[0].fire("click");
console.log("Clicked on nearby Marker[0]:", nearbyMarkers[0]);
} else {
console.log("Keine Marker gefunden.");
} }
}); });
} }
} }
// Entferne alle Plus-Icons, wenn keine Marker sichtbar sind
if (Object.keys(overlappingGroups).length === 0) { if (Object.keys(overlappingGroups).length === 0) {
plusMarkers.forEach((plusMarker) => map.removeLayer(plusMarker)); plusMarkers.forEach((plusMarker) => map.removeLayer(plusMarker));
plusMarkers = []; plusMarkers = [];