refactor: Polyline-Sichtbarkeit auf Redux umgestellt (ersetzt Recoil)

- Sichtbarkeitsstatus für Kabelstrecken/Polylines wird jetzt zentral im Redux-Store verwaltet.
- Initialer Zustand wird aus localStorage gelesen und direkt in Redux gesetzt.
- DataSheet-Checkbox steuert Redux-Status und synchronisiert mit localStorage.
- MapComponent.js verwendet Redux-State direkt zur Steuerung von setupPolylines.
- setupPolylines.js ist jetzt komplett "dumm" und bekommt den Sichtbarkeitsstatus nur noch als Parameter.
- Konsistente Lösung für Initial-Laden, Checkbox-Wechsel und Map-Neuladen umgesetzt.
This commit is contained in:
Ismail Ali
2025-03-06 19:54:29 +01:00
parent 335b88d449
commit a837291048
9 changed files with 59 additions and 184 deletions

View File

@@ -7,7 +7,7 @@ DB_NAME=talas_v5
DB_PORT=3306 DB_PORT=3306
# Public Settings (Client braucht IP/Domain) # Public Settings (Client braucht IP/Domain)
NEXT_PUBLIC_SERVER_URL="http://10.10.0.70" # oder evtl. später https://nodemap.firma.de NEXT_PUBLIC_SERVER_URL="http://192.168.10.33" # oder evtl. später https://nodemap.firma.de
NEXT_PUBLIC_ENABLE_GEOCODER=true NEXT_PUBLIC_ENABLE_GEOCODER=true
NEXT_PUBLIC_USE_MOCK_API=true NEXT_PUBLIC_USE_MOCK_API=true
NEXT_PUBLIC_DEBUG_LOG=true

View File

@@ -9,8 +9,9 @@ import { zoomTriggerState } from "../redux/slices/zoomTriggerSlice.js";
import { poiLayerVisibleState } from "../redux/slices/poiLayerVisibleSlice"; import { poiLayerVisibleState } from "../redux/slices/poiLayerVisibleSlice";
import EditModeToggle from "./EditModeToggle"; import EditModeToggle from "./EditModeToggle";
import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleSlice"; // Import für Polyline-Visibility import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleSlice"; // Import für Polyline-Visibility
import { useSelector } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { selectGisStationsStaticDistrict } from "../redux/slices/gisStationsStaticDistrictSlice"; import { selectGisStationsStaticDistrict } from "../redux/slices/gisStationsStaticDistrictSlice";
import { selectPolylineVisible, setPolylineVisible } from "../redux/slices/polylineLayerVisibleSlice";
function DataSheet() { function DataSheet() {
const [editMode, setEditMode] = useState(false); // Zustand für editMode const [editMode, setEditMode] = useState(false); // Zustand für editMode
@@ -23,7 +24,15 @@ function DataSheet() {
const GisStationsStaticDistrict = useSelector(selectGisStationsStaticDistrict); const GisStationsStaticDistrict = useSelector(selectGisStationsStaticDistrict);
const GisSystemStatic = useRecoilValue(gisSystemStaticState); const GisSystemStatic = useRecoilValue(gisSystemStaticState);
const setZoomTrigger = useSetRecoilState(zoomTriggerState); const setZoomTrigger = useSetRecoilState(zoomTriggerState);
const [polylineVisible, setPolylineVisible] = useRecoilState(polylineLayerVisibleState); // Zustand für Polylines const dispatch = useDispatch();
const polylineVisible = useSelector(selectPolylineVisible);
const handlePolylineCheckboxChange = (event) => {
const checked = event.target.checked;
dispatch(setPolylineVisible(checked));
localStorage.setItem("polylineVisible", checked);
};
const [bereicheVisible, setBereicheVisible] = useState(false); // NEU: Bereiche-Status const [bereicheVisible, setBereicheVisible] = useState(false); // NEU: Bereiche-Status
const [standordVisible, setStandorteVisible] = useState(false); // NEU: Standorte-Status const [standordVisible, setStandorteVisible] = useState(false); // NEU: Standorte-Status
useEffect(() => { useEffect(() => {
@@ -34,7 +43,7 @@ function DataSheet() {
} }
const storedPolylineVisible = localStorage.getItem("polylineVisible"); const storedPolylineVisible = localStorage.getItem("polylineVisible");
if (storedPolylineVisible !== null) { if (storedPolylineVisible !== null) {
setPolylineVisible(storedPolylineVisible === "true"); dispatch(setPolylineVisible(storedPolylineVisible === "true"));
} }
const storedMapLayersVisibility = localStorage.getItem("mapLayersVisibility"); const storedMapLayersVisibility = localStorage.getItem("mapLayersVisibility");
@@ -128,25 +137,6 @@ function DataSheet() {
setSelectedArea("Station wählen"); setSelectedArea("Station wählen");
setZoomTrigger((current) => current + 1); setZoomTrigger((current) => current + 1);
}; };
const handlePolylineCheckboxChange = (event) => {
const { checked } = event.target;
// Setze den Zustand von Kabelstrecken
setPolylineVisible(checked);
localStorage.setItem("polylineVisible", checked);
// Wenn Kabelstrecken aktiviert werden, aktiviere TALAS
if (checked) {
setMapLayersVisibility((prev) => {
const newState = {
...prev,
TALAS: true,
};
localStorage.setItem("mapLayersVisibility", JSON.stringify(newState));
return newState;
});
}
};
//--------------------------- //---------------------------
const handleBereicheCheckboxChange = (event) => { const handleBereicheCheckboxChange = (event) => {
@@ -161,6 +151,7 @@ function DataSheet() {
setStandorteVisible(checked); setStandorteVisible(checked);
localStorage.setItem("standorteVisible", checked); localStorage.setItem("standorteVisible", checked);
}; };
//------------------------------
//--------------------------- //---------------------------
return ( return (

View File

@@ -67,12 +67,14 @@ import { fetchGisStationsStatusDistrict } from "../services/api/fetchGisStations
import { fetchGisStationsMeasurements } from "../services/api/fetchGisStationsMeasurements.js"; import { fetchGisStationsMeasurements } from "../services/api/fetchGisStationsMeasurements.js";
import { fetchGisSystemStatic } from "../services/api/fetchGisSystemStatic.js"; import { fetchGisSystemStatic } from "../services/api/fetchGisSystemStatic.js";
import { usePolylineTooltipLayer } from "../hooks/usePolylineTooltipLayer";
import { selectPolylineVisible, setPolylineVisible } from "../redux/slices/polylineLayerVisibleSlice";
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const currentPoi = useSelector(selectCurrentPoi); const currentPoi = useSelector(selectCurrentPoi);
//const setCurrentPoi = useSetRecoilState(currentPoiState); //const setCurrentPoi = useSetRecoilState(currentPoiState);
const polylineVisible = useRecoilValue(polylineLayerVisibleState); const polylineVisible = useSelector(selectPolylineVisible);
const [editMode, setEditMode] = useState(false); // editMode Zustand const [editMode, setEditMode] = useState(false); // editMode Zustand
const { deviceName, setDeviceName } = useMapComponentState(); const { deviceName, setDeviceName } = useMapComponentState();
const { poiTypData, isPoiTypLoaded } = usePoiTypData("/api/talas_v5_DB/poiTyp/readPoiTyp"); const { poiTypData, isPoiTypLoaded } = usePoiTypData("/api/talas_v5_DB/poiTyp/readPoiTyp");
@@ -558,7 +560,17 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
polylines.forEach((polyline) => polyline.remove()); polylines.forEach((polyline) => polyline.remove());
// Setze neue Marker und Polylinien mit den aktuellen Daten // Setze neue Marker und Polylinien mit den aktuellen Daten
const { markers: newMarkers, polylines: newPolylines } = setupPolylines(map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, polylineVisible); const { markers: newMarkers, polylines: newPolylines } = setupPolylines(
map,
linePositions,
lineColors,
tooltipContents,
setNewCoords,
tempMarker,
currentZoom,
currentCenter,
polylineVisible // kommt aus Redux
);
newPolylines.forEach((polyline, index) => { newPolylines.forEach((polyline, index) => {
console.log("polyline: ", polyline); console.log("polyline: ", polyline);
@@ -992,6 +1004,11 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
} }
}, [map, menuItemAdded]); }, [map, menuItemAdded]);
//-------------------------------------------- //--------------------------------------------
// Beim ersten Client-Render den Wert aus localStorage laden
useEffect(() => {
const storedPolylineVisible = localStorage.getItem("polylineVisible") === "true";
dispatch(setPolylineVisible(storedPolylineVisible));
}, [dispatch]);
//---------------------------------------------- //----------------------------------------------

View File

@@ -1,2 +1,2 @@
// /config/appVersion // /config/appVersion
export const APP_VERSION = "1.1.11"; export const APP_VERSION = "1.1.12";

View File

@@ -1,132 +0,0 @@
// hooks/useLineData.js //fix v1.0.8.1
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
import { SERVER_URL } from "../config/urls";
import { useDispatch, useSelector } from "react-redux";
const useLineData = (webserviceGisLinesStatusUrl, setLineStatusData) => {
const dispatch = useDispatch();
const messages = useSelector((state) => state.messages);
const [lineColors, setLineColors] = useState({});
const [tooltipContents, setTooltipContents] = useState({});
useEffect(() => {
let isCancelled = false;
const fetchData = async () => {
try {
const response1 = await fetch(webserviceGisLinesStatusUrl);
if (!response1.ok) throw new Error("Fehler bei GIS-Linienstatus");
const data1 = await response1.json();
const response2 = await fetch(`${SERVER_URL}:3000/api/talas_v5_DB/gisLines/readGisLines`);
if (!response2.ok) throw new Error("Fehler beim Abrufen der GIS-Linien");
const data2 = await response2.json();
const response3 = await fetch(`${SERVER_URL}:3000/api/talas_v5_DB/device/getAllStationsNames`);
if (!response3.ok) throw new Error("Fehler beim Abrufen der Stationsnamen");
const namesData = await response3.json();
if (!isCancelled) {
if (!data1.Statis || data1.Statis.length === 0) {
toast.warn("Keine Linienstatus-Daten verfügbar!", { position: "top-center", autoClose: 5000 });
setLineStatusData([]);
return;
}
const colorsByModule = {};
const newTooltipContents = {};
const valueMap = {};
const sortedStatis = [...data1.Statis].sort((a, b) => a.Level - b.Level);
sortedStatis.forEach((statis) => {
const key = `${statis.IdLD}-${statis.Modul}`;
if (!valueMap[key]) {
valueMap[key] = {
messages: [],
messwert: undefined,
schleifenwert: undefined,
};
}
if (statis.DpName.endsWith("_Messwert") && statis.Value !== "True" && !valueMap[key].messwert) {
valueMap[key].messwert = statis.Value;
}
if (statis.DpName.endsWith("_Schleifenwert") && !valueMap[key].schleifenwert) {
valueMap[key].schleifenwert = statis.Value;
}
if (statis.Message && statis.Message !== "?") {
valueMap[key].messages.push({
message: statis.Message,
prioColor: statis.PrioColor && statis.PrioColor !== "#ffffff" ? statis.PrioColor : "green",
});
}
});
sortedStatis.forEach((statis) => {
const key = `${statis.IdLD}-${statis.Modul}`;
const matchingLine = data2.find((item) => item.idLD === statis.IdLD && item.idModul === statis.Modul);
if (matchingLine) {
const values = valueMap[key];
const messageDisplay = values.messages.map((msg) => `<span class="inline-block text-gray-800"><span class="inline-block w-2 h-2 rounded-full mr-2" style="background-color: ${msg.prioColor};"></span>${msg.message}</span><br>`).join("");
colorsByModule[key] = values.messages.length > 0 ? values.messages[0].prioColor : "green";
newTooltipContents[key] = `
<div class="bg-white rounded-lg m-0 p-2 w-[210px]">
<span class="text-lg font-semibold text-gray-900">${statis.ModulName || "Unknown"}</span>
<br>
<span class="text-md font-bold text-gray-800">${statis.ModulTyp || "N/A"}</span>
<br>
<span class="text-md font-bold text-gray-800">Slot: ${statis.Modul || "N/A"}</span>
<br>
<span class="text-md font-bold text-gray-800">Station: ${namesData[matchingLine.idLD] || "N/A"}</span>
<br>
<div style="max-width: 100%; overflow-wrap: break-word; word-break: break-word; white-space: normal;">
${messageDisplay}
</div>
<br>
${values.messwert ? `<span class="inline-block text-gray-800">Messwert: ${values.messwert}</span><br>` : ""}
${values.schleifenwert ? `<span class="inline-block text-gray-800">Schleifenwert: ${values.schleifenwert}</span>` : ""}
</div>
`;
}
});
setLineColors(colorsByModule);
setTooltipContents(newTooltipContents);
setLineStatusData(data1.Statis);
}
} catch (error) {
//console.error("Fehler beim Abrufen der Daten in useLineData.js:", error);
// toast.error("Fehler beim Abrufen der Linienstatus-Daten!", { position: "top-center", autoClose: 5000 });
console.warn("Fehler beim Abrufen der Linienstatus-Daten in useLineData.js ");
}
};
const scheduleNextFetch = () => {
if (!isCancelled) {
fetchData();
setTimeout(scheduleNextFetch, 30000);
}
};
fetchData();
scheduleNextFetch();
return () => {
isCancelled = true;
localStorage.removeItem("contextMenuExpired");
};
}, [webserviceGisLinesStatusUrl, setLineStatusData]);
return { lineColors, tooltipContents };
};
export default useLineData;

View File

@@ -1,7 +1,22 @@
// /redux/slices/polylineLayerVisibleSlice.js // /redux/slices/polylineLayerVisibleSlice.js
import { atom } from "recoil"; // redux/slices/polylineLayerVisibleSlice.js
import { createSlice } from "@reduxjs/toolkit";
export const polylineLayerVisibleState = atom({ const initialState = {
key: "polylineLayerVisibleState", visible: false, // oder Standardwert
default: true, // Standardmäßig auf sichtbar setzen };
const polylineLayerVisibleSlice = createSlice({
name: "polylineLayerVisible",
initialState,
reducers: {
setPolylineVisible: (state, action) => {
state.visible = action.payload;
localStorage.setItem("polylineVisible", action.payload);
},
},
}); });
export const { setPolylineVisible } = polylineLayerVisibleSlice.actions;
export const selectPolylineVisible = (state) => state.polylineLayerVisible.visible;
export default polylineLayerVisibleSlice.reducer;

View File

@@ -2,11 +2,13 @@ import { configureStore } from "@reduxjs/toolkit";
import lineVisibilityReducer from "./slices/lineVisibilitySlice"; import lineVisibilityReducer from "./slices/lineVisibilitySlice";
import currentPoiReducer from "./slices/currentPoiSlice"; import currentPoiReducer from "./slices/currentPoiSlice";
import gisStationsStaticDistrictReducer from "./slices/gisStationsStaticDistrictSlice"; import gisStationsStaticDistrictReducer from "./slices/gisStationsStaticDistrictSlice";
import polylineLayerVisibleReducer from "./slices/polylineLayerVisibleSlice";
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
lineVisibility: lineVisibilityReducer, lineVisibility: lineVisibilityReducer,
currentPoi: currentPoiReducer, currentPoi: currentPoiReducer,
gisStationsStaticDistrict: gisStationsStaticDistrictReducer, gisStationsStaticDistrict: gisStationsStaticDistrictReducer,
polylineLayerVisible: polylineLayerVisibleReducer,
}, },
}); });

View File

@@ -59,7 +59,7 @@ export const createAndSetDevices = async (systemId, setMarkersFunction, GisSyste
return { idLD: station.IdLD, active: station.Active }; return { idLD: station.IdLD, active: station.Active };
}); });
console.log("🔄 Alle Linien gespeichert:", allLines); //console.log("🔄 Alle Linien gespeichert:", allLines);
const activeStations = staticDistrictData.Points.filter((station) => station.System === systemId && station.Active === 1); const activeStations = staticDistrictData.Points.filter((station) => station.System === systemId && station.Active === 1);

View File

@@ -84,22 +84,11 @@ function monitorContextMenu(map) {
} }
export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => { export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => {
// Hole activeLines direkt aus Redux if (!polylineVisible) {
const state = store.getState(); // Hole den gesamten Zustand console.warn("Polylines deaktiviert - keine Zeichnung");
const activeLines = state.lineVisibility.activeLines; // Zugriff auf activeLines
if (!activeLines) {
console.warn("activeLines ist undefined oder null.");
return { markers: [], polylines: [] }; return { markers: [], polylines: [] };
} }
if (localStorage.getItem("polylineVisible") === null) {
localStorage.setItem("polylineVisible", "true"); // Standardwert setzen
polylineVisible = true; // Wert in der Funktion initialisieren
} else {
polylineVisible = localStorage.getItem("polylineVisible") === "true";
}
if (!polylineVisible) { if (!polylineVisible) {
// Entferne alle Polylinien, wenn sie ausgeblendet werden sollen // Entferne alle Polylinien, wenn sie ausgeblendet werden sollen
if (window.polylines) { if (window.polylines) {
@@ -117,15 +106,8 @@ export const setupPolylines = (map, linePositions, lineColors, tooltipContents,
linePositions.forEach((lineData, lineIndex) => { linePositions.forEach((lineData, lineIndex) => {
console.log("LineData:", lineData.idLD, lineData.idModul); console.log("LineData:", lineData.idLD, lineData.idModul);
console.log("ActiveLines:", activeLines);
// **Fix: Sicherstellen, dass activeLines definiert ist und idLD existiert** // **Fix: Sicherstellen, dass activeLines definiert ist und idLD existiert**
const isActive = activeLines && lineData.idLD && activeLines[String(lineData.idLD)] === 1;
if (!isActive) {
console.warn(`Linie mit idLD ${lineData.idLD} wird ausgeblendet.`);
return;
}
const lineMarkers = []; const lineMarkers = [];