From 4c6386edea1c74e74a2094cf7c7890b7d844ac49 Mon Sep 17 00:00:00 2001 From: ISA Date: Tue, 27 May 2025 08:33:02 +0200 Subject: [PATCH] refactor(utils): saveLineData entfernt und durch Redux-Thunk ersetzt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - updatePolylineCoordinatesThunk in markerUtils.js und poiUtils.js eingebunden - zentrale Hilfsfunktion savePolylineRedux erstellt - fetch() entfernt, Version auf 1.1.183 erhöht --- CHANGELOG.md | 37 ++++++ config/appVersion.js | 2 +- .../locationDevice/locationDevicesSlice.js | 41 ++++++ .../fetchLocationDevicesThunk.js | 8 ++ .../fetchLocationDevicesService.js | 12 ++ utils/handlePoiSelect.js | 37 ------ utils/mapUtils.js | 25 ---- utils/markerUtils.js | 85 ++++-------- utils/poiUtils.js | 122 +++++------------- 9 files changed, 157 insertions(+), 212 deletions(-) create mode 100644 redux/slices/database/locationDevice/locationDevicesSlice.js create mode 100644 redux/thunks/database/locationDevice/fetchLocationDevicesThunk.js create mode 100644 services/database/locationDevice/fetchLocationDevicesService.js delete mode 100644 utils/handlePoiSelect.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 59de6a2cc..a9b98058a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,43 @@ Alle bedeutenden Änderungen an diesem Projekt werden in dieser Datei dokumentie --- +📦 [1.1.183] – 2025-05-27 +♻️ Refactor +Die Hilfsfunktion saveLineData() wurde vollständig entfernt: + +In markerUtils.js und poiUtils.js ersetzt durch updatePolylineCoordinatesThunk via Redux + +Zentrale Dispatch-Hilfsfunktion savePolylineRedux() erstellt für alle Linienaktionen (Einfügen, Verschieben, Entfernen) + +Einheitliche Verwendung des Redux-Dispatch in Utility-Dateien: + +Kein direktes fetch() mehr + +Fehlerbehandlung über .unwrap().catch(...) integriert + +Map-Utilities und POI-Utilities sind nun Redux-kompatibel und testbar + +✅ Clean +saveLineData aus mapUtils.js gelöscht + +Alle Marker-Operationen speichern ihre Koordinaten ausschließlich über Redux + +🧠 Architektur +Redux-Toolkit Standardstruktur umgesetzt: + +updatePolylineCoordinatesService.js + +updatePolylineCoordinatesThunk.js + +Nutzung außerhalb React-Komponenten über store.dispatch(...) + +Leaflet-Logik (z. B. marker.setLatLng(), map.removeLayer()) bleibt in Utility-Dateien – Redux kümmert sich nur um Daten + +🔧 Version +📦 Version erhöht auf 1.1.183 + +--- + ## [1.1.182] – 2025-05-27 ### ♻️ Refactor diff --git a/config/appVersion.js b/config/appVersion.js index a668d587c..0dbebcc21 100644 --- a/config/appVersion.js +++ b/config/appVersion.js @@ -1,2 +1,2 @@ // /config/appVersion -export const APP_VERSION = "1.1.183"; +export const APP_VERSION = "1.1.184"; diff --git a/redux/slices/database/locationDevice/locationDevicesSlice.js b/redux/slices/database/locationDevice/locationDevicesSlice.js new file mode 100644 index 000000000..9b22f04b5 --- /dev/null +++ b/redux/slices/database/locationDevice/locationDevicesSlice.js @@ -0,0 +1,41 @@ +// /redux/slices/database/locationDevice/locationDevicesSlice.js + +import { createSlice } from "@reduxjs/toolkit"; +import { fetchLocationDevicesThunk } from "../../../thunks/database/locationDevice/fetchLocationDevicesThunk"; + +const locationDevicesSlice = createSlice({ + name: "locationDevices", + initialState: { + data: [], + status: "idle", + error: null, + }, + reducers: { + clearLocationDevices: (state) => { + state.data = []; + state.status = "idle"; + state.error = null; + }, + }, + extraReducers: (builder) => { + builder + .addCase(fetchLocationDevicesThunk.pending, (state) => { + state.status = "loading"; + }) + .addCase(fetchLocationDevicesThunk.fulfilled, (state, action) => { + state.status = "succeeded"; + state.data = action.payload; + }) + .addCase(fetchLocationDevicesThunk.rejected, (state, action) => { + state.status = "failed"; + state.error = action.error.message; + }); + }, +}); + +export const { clearLocationDevices } = locationDevicesSlice.actions; + +export const selectLocationDevices = (state) => state.locationDevices.data; +export const selectLocationDeviceStatus = (state) => state.locationDevices.status; + +export default locationDevicesSlice.reducer; diff --git a/redux/thunks/database/locationDevice/fetchLocationDevicesThunk.js b/redux/thunks/database/locationDevice/fetchLocationDevicesThunk.js new file mode 100644 index 000000000..e797f4545 --- /dev/null +++ b/redux/thunks/database/locationDevice/fetchLocationDevicesThunk.js @@ -0,0 +1,8 @@ +// /redux/thunks/database/locationDevice/fetchLocationDevicesThunk.js + +import { createAsyncThunk } from "@reduxjs/toolkit"; +import { fetchLocationDevicesService } from "../../../services/database/locationDevice/fetchLocationDevicesService"; + +export const fetchLocationDevicesThunk = createAsyncThunk("locationDevices/fetchAll", async () => { + return await fetchLocationDevicesService(); +}); diff --git a/services/database/locationDevice/fetchLocationDevicesService.js b/services/database/locationDevice/fetchLocationDevicesService.js new file mode 100644 index 000000000..d93dae642 --- /dev/null +++ b/services/database/locationDevice/fetchLocationDevicesService.js @@ -0,0 +1,12 @@ +// /services/database/locationDevice/fetchLocationDevicesService.js + +export const fetchLocationDevicesService = async () => { + const response = await fetch("/api/talas_v5_DB/locationDevice/locationDevices"); + + if (!response.ok) { + const error = await response.json(); + throw new Error(error.message || "Fehler beim Abrufen der Gerätedaten"); + } + + return await response.json(); +}; diff --git a/utils/handlePoiSelect.js b/utils/handlePoiSelect.js deleted file mode 100644 index 46252b236..000000000 --- a/utils/handlePoiSelect.js +++ /dev/null @@ -1,37 +0,0 @@ -// utils/handlePoiSelect.js -const handlePoiSelect = async (poiData, setSelectedPoi, setLocationDeviceData, setDeviceName, poiLayerRef, poiTypMap) => { - setSelectedPoi(poiData); // Setzt das ausgewählte POI - - try { - const response = await fetch("/api/talas_v5_DB/locationDevice/locationDevices"); - const data = await response.json(); - setLocationDeviceData(data); - - const currentDevice = data.find((device) => device.idLD === poiData.deviceId); - if (currentDevice) { - setDeviceName(currentDevice.name); - - // Hier speichern wir den POI-Typ im localStorage - const poiTypeName = poiTypMap.get(poiData.idPoiTyp); - localStorage.setItem("selectedPoiType", poiTypeName); - - // Optional: Update des Markers mit dem POI-Typ - const marker = poiLayerRef.current.getLayers().find((m) => m.options.id === poiData.id); - if (marker) { - marker.setPopupContent(` -
- ${poiData.description || "Unbekannt"}
- ${currentDevice.name}
- ${poiTypeName || "Unbekannt"}
-
- `); - marker.openPopup(); - } - } - } catch (error) { - console.error("Fehler beim Abrufen der Gerätedaten:", error); - setLocationDeviceData([]); - } -}; - -export default handlePoiSelect; diff --git a/utils/mapUtils.js b/utils/mapUtils.js index 89d13493b..cdab9e214 100644 --- a/utils/mapUtils.js +++ b/utils/mapUtils.js @@ -1,31 +1,6 @@ // /utils/mapUtils.js import L from "leaflet"; -export const saveLineData = (lineData) => { - fetch("/api/talas_v5_DB/gisLines/updateLineCoordinates", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - idModul: lineData.idModul, - idLD: lineData.idLD, - newCoordinates: lineData.coordinates, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error("Fehler beim Speichern der Linienänderungen"); - } - return response.json(); - }) - .then((data) => { - //console.log("Linienänderungen gespeichert:", data); - }) - .catch((error) => { - console.error("Fehler beim Speichern der Linienänderungen:", error); - }); -}; // Call this function on page load to restore zoom and center export const restoreMapSettings = (map) => { const savedZoom = localStorage.getItem("mapZoom"); diff --git a/utils/markerUtils.js b/utils/markerUtils.js index ea3bd062b..114a6de27 100644 --- a/utils/markerUtils.js +++ b/utils/markerUtils.js @@ -1,107 +1,75 @@ // /utils/markerUtils.js -import circleIcon from "../components/CircleIcon"; -import { saveLineData } from "./mapUtils"; -import { redrawPolyline } from "./mapUtils"; import L from "leaflet"; import { toast } from "react-toastify"; +import circleIcon from "../components/CircleIcon"; +import { store } from "../redux/store"; +import { updatePolylineCoordinatesThunk } from "../redux/thunks/database/polylines/updatePolylineCoordinatesThunk"; +import { redrawPolyline } from "./mapUtils"; + +const savePolylineRedux = (lineData) => { + return store + .dispatch( + updatePolylineCoordinatesThunk({ + idModul: lineData.idModul, + idLD: lineData.idLD, + newCoordinates: lineData.coordinates, + }) + ) + .unwrap() + .catch((error) => { + console.error("Fehler beim Speichern der Linienkoordinaten:", error.message); + }); +}; export const insertNewMarker = (closestPoints, newPoint, lineData, map) => { const newMarker = L.marker(newPoint, { icon: circleIcon, draggable: true, }).addTo(map); + lineData.coordinates.splice(closestPoints[2], 0, [newPoint.lat, newPoint.lng]); - - // Hier direkt speichern nach Einfügen - saveLineData(lineData); - + savePolylineRedux(lineData); // ✅ Nutzung der Hilfsfunktion redrawPolyline(lineData); - // Event-Listener für das Verschieben des Markers hinzufügen newMarker.on("dragend", () => { const newCoords = newMarker.getLatLng(); - setNewCoords(newCoords); const newCoordinates = [...lineData.coordinates]; newCoordinates[closestPoints[2]] = [newCoords.lat, newCoords.lng]; lineData.coordinates = newCoordinates; - redrawPolyline(lineData); + redrawPolyline(lineData); updateMarkerPosition(newMarker.getLatLng(), lineData, newMarker); - saveLineData(lineData); // Speichern der neuen Koordinaten nach dem Verschieben + savePolylineRedux(lineData); // ✅ Wiederverwendung }); }; export const removeMarker = (marker, lineData, currentZoom, currentCenter) => { - // Save zoom and center to localStorage - //localStorage.setItem("mapZoom", currentZoom); - //localStorage.setItem("mapCenter", JSON.stringify(currentCenter)); - - // Find the index of the coordinate that matches the marker's position const index = lineData.coordinates.findIndex((coord) => L.latLng(coord[0], coord[1]).equals(marker.getLatLng())); if (index !== -1) { - // Remove the coordinate from the line data lineData.coordinates.splice(index, 1); - - // Redraw the polyline with the updated coordinates redrawPolyline(lineData); - - // Remove the marker from the map marker.remove(); - - // Save the updated line data - saveLineData(lineData); - - // Refresh the browser + savePolylineRedux(lineData); // ✅ Wiederverwendung window.location.reload(); } }; -export const handleEditPoi = ( - marker, - userRights, - setCurrentPoiData, - setShowPoiUpdateModal, - fetchPoiData, - toast // Hier toast als Parameter erhalten -) => { - console.log("Selected Marker ID (idPoi):", marker.options.id); - console.log("Selected Marker Description:", marker.options.description); - console.log("User Rights:", userRights); - - // Sicherstellen, dass userRights ein Array ist +export const handleEditPoi = (marker, userRights, setCurrentPoiData, setShowPoiUpdateModal, fetchPoiData, toast) => { if (!Array.isArray(userRights)) { - console.error("User Rights is not an array:", userRights); toast.error("Benutzerrechte sind ungültig.", { position: "top-center", autoClose: 5000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, }); return; } - console.log( - "User Rights include 56:", - userRights.some((r) => r.IdRight === 56) - ); - - // Prüfung, ob der Benutzer die notwendigen Rechte hat if (!userRights.some((r) => r.IdRight === 56)) { toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", { position: "top-center", autoClose: 5000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, }); - console.log("Benutzer hat keine Berechtigung zum Bearbeiten."); - return; // Beendet die Funktion frühzeitig, wenn keine Berechtigung vorliegt + return; } setCurrentPoiData({ @@ -111,6 +79,5 @@ export const handleEditPoi = ( }); fetchPoiData(marker.options.id); - setShowPoiUpdateModal(true); }; diff --git a/utils/poiUtils.js b/utils/poiUtils.js index beedf88da..08e76ee39 100644 --- a/utils/poiUtils.js +++ b/utils/poiUtils.js @@ -1,124 +1,66 @@ // /utils/poiUtils.js -import circleIcon from "../components/gisPolylines/icons/CircleIcon.js"; -import { saveLineData } from "./mapUtils.js"; -import { redrawPolyline } from "./polylines/redrawPolyline.js"; import L from "leaflet"; -import "leaflet.smooth_marker_bouncing"; import { toast } from "react-toastify"; +import circleIcon from "../components/gisPolylines/icons/CircleIcon.js"; +import { redrawPolyline } from "./polylines/redrawPolyline.js"; + +import { store } from "../redux/store"; +import { updatePolylineCoordinatesThunk } from "../redux/thunks/database/polylines/updatePolylineCoordinatesThunk"; + +// 🧠 Zentrale Redux-Dispatch-Hilfsfunktion +const savePolylineRedux = (lineData) => { + return store + .dispatch( + updatePolylineCoordinatesThunk({ + idModul: lineData.idModul, + idLD: lineData.idLD, + newCoordinates: lineData.coordinates, + }) + ) + .unwrap() + .catch((error) => { + console.error("Fehler beim Speichern der Linienkoordinaten:", error.message); + }); +}; export const insertNewPOI = (closestPoints, newPoint, lineData, map) => { const newMarker = L.marker(newPoint, { icon: circleIcon, draggable: true, }).addTo(map); + + // Stützpunkt in Koordinatenliste einfügen lineData.coordinates.splice(closestPoints[2], 0, [newPoint.lat, newPoint.lng]); - // Hier direkt speichern nach Einfügen - saveLineData(lineData); - + // Redux: Speichern der neuen Koordinaten + savePolylineRedux(lineData); redrawPolyline(lineData); - // Event-Listener für das Verschieben des Markers hinzufügen newMarker.on("dragend", () => { - console.log("Marker wurde verschoben in insertNewPOI"); const newCoords = newMarker.getLatLng(); - setNewCoords(newCoords); const newCoordinates = [...lineData.coordinates]; newCoordinates[closestPoints[2]] = [newCoords.lat, newCoords.lng]; lineData.coordinates = newCoordinates; - redrawPolyline(lineData); - updateMarkerPosition(newMarker.getLatLng(), lineData, newMarker); - saveLineData(lineData); // Speichern der neuen Koordinaten nach dem Verschieben + redrawPolyline(lineData); + updateMarkerPosition(newCoords, lineData, newMarker); + savePolylineRedux(lineData); }); }; export const removePOI = (marker, lineData, currentZoom, currentCenter) => { - // Save zoom and center to localStorage - //localStorage.setItem("mapZoom", currentZoom); - //localStorage.setItem("mapCenter", JSON.stringify(currentCenter)); - - // Find the index of the coordinate that matches the marker's position const index = lineData.coordinates.findIndex((coord) => L.latLng(coord[0], coord[1]).equals(marker.getLatLng())); if (index !== -1) { - // Remove the coordinate from the line data lineData.coordinates.splice(index, 1); - - // Redraw the polyline with the updated coordinates redrawPolyline(lineData); - - // Remove the marker from the map marker.remove(); - - // Save the updated line data - saveLineData(lineData); - - // Refresh the browser + savePolylineRedux(lineData); window.location.reload(); } }; -export const handleEditPoi = ( - marker, - userRights, - setCurrentPoiData, - setShowPoiUpdateModal, - fetchPoiData, - toast // Hier toast als Parameter erhalten -) => { - const editMode = localStorage.getItem("editMode") === "true"; - userRights = editMode ? userRights : undefined; - //console.log("Selected Marker ID (idPoi):", marker.options.id); - //console.log("Selected Marker Description:", marker.options.description); - //console.log("User Rights:", userRights); - - // Sicherstellen, dass userRights ein Array ist - if (!userRights.some((r) => r.IdRight === 56)) { - console.error("User Rights is not an array:", userRights); - toast.error("Benutzerrechte sind ungültig.", { - position: "top-center", - autoClose: 5000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - }); - return; - } - - console.log( - "User Rights include 56:", - userRights.some((r) => r.IdRight === 56) - ); - - // Prüfung, ob der Benutzer die notwendigen Rechte hat - if (!userRights.some((r) => r.IdRight === 56)) { - toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", { - position: "top-center", - autoClose: 5000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - }); - console.log("Benutzer hat keine Berechtigung zum Bearbeiten."); - return; // Beendet die Funktion frühzeitig, wenn keine Berechtigung vorliegt - } - - setCurrentPoiData({ - idPoi: marker.options.id, - name: marker.options.name, - description: marker.options.description, - idLD: marker.options.idLD, - idPoiTyp: marker.options.idPoiTyp, - }); - - fetchPoiData(marker.options.id); - - setShowPoiUpdateModal(true); - console.log("POI option idPoiTyp:", marker.options.idPoiTyp); +export const updateMarkerPosition = (newCoords, lineData, marker) => { + if (!marker) return; + marker.setLatLng([newCoords.lat, newCoords.lng]); }; -//-------------------------------------------------------------------