git commit -m "refactor: Gerätelayer dynamisch über IdSystem initialisiert

BREAKING CHANGE: Sichtbarkeit der Gerätegruppen basiert nun auf 'system-<IdSystem>' statt auf Namen wie 'SMSFunkmodem'. Statische Layer-Konfiguration im Redux-Slice entfernt."
This commit is contained in:
ISA
2025-06-02 09:00:49 +02:00
parent fda7476872
commit be2da8414c
12 changed files with 76 additions and 33 deletions

View File

@@ -4,6 +4,26 @@ Alle bedeutenden Änderungen an diesem Projekt werden in dieser Datei dokumentie
--- ---
## [1.1.209] 2025-06-02
### Added
- Dynamische Initialisierung aller Gerätegruppen-Layer (system-<IdSystem>) über GIS-Systemdaten.
- Automatische Sichtbarkeitssteuerung in `mapLayersSlice` basierend auf `IdSystem`.
- Mermaid-Diagramm zur Dokumentation der Architektur in `/docs/architecture/device-layer-connection-final.md`.
### Changed
- Vergleichslogik zwischen `gisStationsStaticDistrict[].System` und `gisSystemStatic[].IdSystem` von `Name` auf `IdSystem` umgestellt.
- `MapLayersControlPanel` verwendet jetzt konsistent `system-<IdSystem>` als Key.
- `useDynamicDeviceLayers` baut Layer-Gruppen und Marker-Zuordnung ebenfalls über `IdSystem` auf.
### Removed
- Veraltete statische Layer-Namen (`TALAS`, `SMSFunkmodem`, etc.) aus `mapLayersSlice`.
---
## [1.1.191] 2025-05-27 ## [1.1.191] 2025-05-27
### 🐞 Fixed ### 🐞 Fixed

View File

@@ -6,7 +6,7 @@ export const mockGisStationsStaticDistrict = {
IdMap: "12", IdMap: "12",
Points: [ Points: [
{ {
LD_Name: "CPL Ismael", LD_Name: "CPL Ismail",
IdLD: 50922, IdLD: 50922,
Device: "CPL V3.5 mit 24 Kü", Device: "CPL V3.5 mit 24 Kü",
Link: "cpl.aspx?ver=35&kue=24&id=50922", Link: "cpl.aspx?ver=35&kue=24&id=50922",

View File

@@ -79,7 +79,7 @@ export const mockGisSystemStatic = {
IdSystem: 13, IdSystem: 13,
Name: "Messstellen", Name: "Messstellen",
Longname: "Messstellen", Longname: "Messstellen",
Allow: 0, Allow: 1,
Icon: 13, Icon: 13,
}, },
{ {

View File

@@ -15,3 +15,10 @@
- [x] Wird cleanup in `useMapContextMenu` korrekt durchgeführt? - [x] Wird cleanup in `useMapContextMenu` korrekt durchgeführt?
- [x] Test: `Rechtsklick > Station öffnen Tab` - [x] Test: `Rechtsklick > Station öffnen Tab`
- ✅ Gelöst am 27.05.2025 in Version 1.1.191 (`createAndSetDevices.js`) - ✅ Gelöst am 27.05.2025 in Version 1.1.191 (`createAndSetDevices.js`)
### 2. Kontextmenü wird bei Geräten nicht angezeigt
- [ ] Kontextmenü anzeigen
- [ ] Station öffnen (Tab) anzeigen
- [ ] Station öffnen (Tab) Link prüfen
- [ ] SMS Modem in control panel passt nicht zu station static und status

View File

@@ -555,6 +555,9 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
dispatch(fetchGisSystemStaticThunk()); dispatch(fetchGisSystemStaticThunk());
} }
}, [statusSystem, dispatch]); }, [statusSystem, dispatch]);
useEffect(() => {
dispatch(fetchGisSystemStaticThunk());
}, [dispatch]);
useEffect(() => { useEffect(() => {
dispatch(fetchLocationDevicesThunk()); dispatch(fetchLocationDevicesThunk());

View File

@@ -101,7 +101,7 @@ function MapLayersControlPanel() {
filteredSystems.map((system, index) => ({ filteredSystems.map((system, index) => ({
id: index + 1, id: index + 1,
name: system.Name, // Verwende den Originalnamen für die Anzeige name: system.Name, // Verwende den Originalnamen für die Anzeige
key: system.Name.replace(/[\s\-]+/g, ""), // Internen Schlüssel für die MapLayersVisibility-Logik key: `system-${system.IdSystem}`, // Internen Schlüssel für die MapLayersVisibility-Logik
})) }))
); );
}, [GisStationsStaticDistrict, GisSystemStatic]); }, [GisStationsStaticDistrict, GisSystemStatic]);

View File

@@ -1,2 +1,2 @@
// /config/appVersion // /config/appVersion
export const APP_VERSION = "1.1.209"; export const APP_VERSION = "1.1.210";

View File

@@ -0,0 +1,18 @@
# 📡 Architektur: Verbindung GIS-System & GIS-Station
Dieses Diagramm zeigt den Ablauf, wie Geräte (Marker) auf der Karte über die ID (System gegen IdSystem) korrekt geladen und sichtbar gemacht werden.
```mermaid
flowchart TD
A[Stationen aus GIS Stations District mit System ID zum Beispiel 111] --> B[useDynamicDeviceLayers.js]
B --> C[Filter und Gruppierung nach System ID]
C --> D[createAndSetDevices.js erzeugt Marker]
D --> E[MapComponent.js zeigt Marker auf Karte]
subgraph Redux
F[fetchGisSystemStaticService.js liefert Systeme mit IdSystem]
F --> G[fetchGisSystemStaticThunk.js]
G --> H[setInitialLayers mit system-IdSystem]
H --> I[mapLayersSlice.js speichert Sichtbarkeit]
end
I -->|Sichtbarkeit steuert Anzeige| E
```

View File

@@ -22,17 +22,19 @@ const useDynamicDeviceLayers = (map, GisSystemStatic, mapLayersVisibility, prior
if (!map || GisSystemStatic.length === 0) return; if (!map || GisSystemStatic.length === 0) return;
GisSystemStatic.forEach(({ Name, IdSystem }) => { GisSystemStatic.forEach(({ Name, IdSystem }) => {
if (!layerRefs.current[Name]) { const key = `system-${IdSystem}`; // ✅ Einheitlicher Key
layerRefs.current[Name] = new L.LayerGroup().addTo(map);
if (!layerRefs.current[key]) {
layerRefs.current[key] = new L.LayerGroup().addTo(map);
} }
createAndSetDevices( createAndSetDevices(
IdSystem, IdSystem,
(newMarkers) => { (newMarkers) => {
setMarkerStates((prev) => ({ ...prev, [Name]: newMarkers })); setMarkerStates((prev) => ({ ...prev, [key]: newMarkers }));
newMarkers.forEach((m) => { newMarkers.forEach((m) => {
layerRefs.current[Name].addLayer(m); layerRefs.current[key].addLayer(m);
if (oms) oms.addMarker(m); // ✅ Marker bei OMS registrieren if (oms) oms.addMarker(m);
}); });
checkOverlappingMarkers(map, newMarkers, plusRoundIcon, oms); checkOverlappingMarkers(map, newMarkers, plusRoundIcon, oms);
}, },
@@ -47,8 +49,8 @@ const useDynamicDeviceLayers = (map, GisSystemStatic, mapLayersVisibility, prior
if (!map) return; if (!map) return;
const editMode = localStorage.getItem("editMode") === "true"; const editMode = localStorage.getItem("editMode") === "true";
Object.entries(markerStates).forEach(([systemName, markers]) => { Object.entries(markerStates).forEach(([key, markers]) => {
const isVisible = mapLayersVisibility[systemName]; const isVisible = mapLayersVisibility[key];
markers.forEach((marker) => { markers.forEach((marker) => {
const hasLayer = map.hasLayer(marker); const hasLayer = map.hasLayer(marker);
if (editMode || !isVisible) { if (editMode || !isVisible) {

View File

@@ -1,7 +1,7 @@
// /hooks/useCreateAndSetDevices.js // /hooks/useCreateAndSetDevices.js
import { useEffect } from "react"; import { useEffect } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { createAndSetDevices } from "../utils/createAndSetDevices"; import { createAndSetDevices } from "../utils/devices/createAndSetDevices";
import { selectGisStationsMeasurements } from "../redux/slices/webservice/gisStationsMeasurementsSlice"; import { selectGisStationsMeasurements } from "../redux/slices/webservice/gisStationsMeasurementsSlice";
const useCreateAndSetDevices = (systemId, setMarkersFunction, GisSystemStatic, priorityConfig) => { const useCreateAndSetDevices = (systemId, setMarkersFunction, GisSystemStatic, priorityConfig) => {

View File

@@ -1,24 +1,7 @@
// redux/slices/mapLayersSlice.js // redux/slices/mapLayersSlice.js
import { createSlice } from "@reduxjs/toolkit"; import { createSlice } from "@reduxjs/toolkit";
const initialState = { const initialState = {};
TALAS: true,
ECI: true,
ULAF: true,
GSMModem: true,
CiscoRouter: true,
WAGO: true,
Siemens: true,
OTDR: true,
WDM: true,
GMA: true,
Messstellen: true,
TALASICL: true,
DAUZ: true,
SMSFunkmodem: true, // ✅ Hier sicherstellen, dass es existiert
TKKomponenten: true, // ✅ Hier sicherstellen, dass es existiert
Sonstige: true,
};
const mapLayersSlice = createSlice({ const mapLayersSlice = createSlice({
name: "mapLayers", name: "mapLayers",
@@ -36,9 +19,16 @@ const mapLayersSlice = createSlice({
state[layer] = visibility; state[layer] = visibility;
} }
}, },
setInitialLayers: (state, action) => {
const systems = action.payload; // Array of GisSystem
systems.forEach((system) => {
const key = `system-${system.IdSystem}`;
state[key] = true; // oder false, je nach Default
});
},
}, },
}); });
export const { toggleLayer, setLayerVisibility } = mapLayersSlice.actions; export const { toggleLayer, setLayerVisibility, setInitialLayers } = mapLayersSlice.actions;
export const selectMapLayersState = (state) => state.mapLayers || initialState; export const selectMapLayersState = (state) => state.mapLayers || initialState;
export default mapLayersSlice.reducer; export default mapLayersSlice.reducer;

View File

@@ -2,10 +2,13 @@
import { createAsyncThunk } from "@reduxjs/toolkit"; import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchGisSystemStaticService } from "../../../services/webservice/fetchGisSystemStaticService"; import { fetchGisSystemStaticService } from "../../../services/webservice/fetchGisSystemStaticService";
import { setInitialLayers } from "../../slices/mapLayersSlice"; // Importiere die Action Creator
/** /**
* Redux-Thunk für fetchGisSystemStatic * Redux-Thunk für fetchGisSystemStatic
*/ */
export const fetchGisSystemStaticThunk = createAsyncThunk("gisSystemStatic/fetch", async () => { export const fetchGisSystemStaticThunk = createAsyncThunk("gisSystemStatic/fetch", async (_, { dispatch }) => {
return await fetchGisSystemStaticService(); const systems = await fetchGisSystemStaticService();
dispatch(setInitialLayers(systems)); // ✅ jetzt funktioniert!
return systems;
}); });