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:
20
CHANGELOG.md
20
CHANGELOG.md
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
7
bugs.md
7
bugs.md
@@ -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
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// /config/appVersion
|
// /config/appVersion
|
||||||
export const APP_VERSION = "1.1.209";
|
export const APP_VERSION = "1.1.210";
|
||||||
|
|||||||
18
docs/architecture/device-layer-connection.md
Normal file
18
docs/architecture/device-layer-connection.md
Normal 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
|
||||||
|
```
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user