feat: Geräte-Daten aus Redux-Store in POI-Bearbeiten-Modal integriert

- Geräte-Liste wird jetzt direkt aus dem Redux-Store (locationDevicesFromDB) verwendet.
- Dropdown-Menü zeigt alle verfügbaren Geräte aus der Datenbank.
- Beim Öffnen des Modals wird der vorher zugewiesene Gerätname automatisch ausgewählt (Pre-Selection).
- Cleanup und Optimierung: Keine separaten API-Calls mehr im Modal.
- Struktur verbessert durch Auslagerung der Lade-Logik in useInitLocationDevices Hook.
This commit is contained in:
Ismail Ali
2025-03-07 20:52:00 +01:00
parent 5a27bc5d75
commit c57ae7717a
11 changed files with 145 additions and 97 deletions

View File

@@ -1,11 +1,15 @@
// pages/api/poiUpdateModal.js
//
// /components/PoiUpdateModal.js
import React, { useState, useEffect } from "react";
import { useRecoilValue } from "recoil";
import { selectedPoiState } from "../redux/slices/selectedPoiSlice";
import { currentPoiState } from "../redux/slices/currentPoiSlice";
import { fetchLocationDevicesFromDB } from "../redux/slices/db/locationDevicesFromDBSlice";
import { useDispatch, useSelector } from "react-redux";
const PoiUpdateModal = ({ onClose, poiData }) => {
const dispatch = useDispatch();
const devices = useSelector((state) => state.locationDevicesFromDB.devices);
const currentPoi = useRecoilValue(currentPoiState);
const selectedPoi = useRecoilValue(selectedPoiState);
const [poiId, setPoiId] = useState(poiData ? poiData.idPoi : "");
@@ -19,6 +23,10 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
const [description, setDescription] = useState(poiData ? poiData.description : "");
useEffect(() => {
dispatch(fetchLocationDevicesFromDB());
}, [dispatch]);
// Log the initial POI data
useEffect(() => {
if (poiData) {
@@ -117,28 +125,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
fetchPoiTypData();
}, [selectedPoi]);
// Fetch device data um den Gerät Namen in den dropdown menu anzuzeigen also erstmal die Liste der Geräte abrufen
useEffect(() => {
const fetchData = async () => {
try {
// const response = await fetch("/api/talas_v5/location_device"); //"/api/talas_v5_DB/locationDevice/location_device"
const response = await fetch("/api/talas_v5_DB/locationDevice/locationDevices");
const data = await response.json();
//console.log("Standort- und Gerätedaten:", data);
setLocationDeviceData(data);
console.log("Standort- und Gerätedaten poiData:", poiData);
if (poiData && poiData.idLD) {
const selectedDevice = data.find((device) => device.id === poiData.idLD);
setDeviceName(selectedDevice ? selectedDevice.id : data[0].id); // Hier wird die ID als initialer Zustand gesetzt
console.log("Selected Device:", selectedDevice);
console.log("Selected devciceName:", deviceName);
}
} catch (error) {
console.error("Fehler beim Abrufen der Standort- und Gerätedaten:", error);
}
};
fetchData();
}, []);
//--------------------------------------------------------------------------------------------
// Fetch device name basierend auf der Geräte-ID

View File

@@ -4,71 +4,72 @@ import L from "leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
import "leaflet-contextmenu";
import * as config from "../config/config.js";
import * as config from "../../config/config.js";
import "leaflet.smooth_marker_bouncing";
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet"; //sieht deaktiviert aber ist das nicht so und wird benötigt
import "react-toastify/dist/ReactToastify.css";
import DataSheet from "./DataSheet.js";
import DataSheet from "../DataSheet.js";
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
import AddPoiModalWindow from "./pois/AddPoiModalWindow.js";
import AddPoiModalWindow from "../pois/AddPoiModalWindow.js";
import { InformationCircleIcon } from "@heroicons/react/20/solid";
import PoiUpdateModal from "./pois/PoiUpdateModal.js";
import PoiUpdateModal from "../pois/PoiUpdateModal.js";
import { ToastContainer, toast } from "react-toastify";
import plusRoundIcon from "./PlusRoundIcon.js";
import { createAndSetDevices } from "../utils/createAndSetDevices.js";
import { restoreMapSettings, checkOverlappingMarkers } from "../utils/mapUtils.js";
import { APP_VERSION } from "../config/appVersion";
import * as layers from "../config/layers.js";
import { initializeMap } from "../utils/initializeMap.js";
import addItemsToMapContextMenu from "./useMapContextMenu.js";
import useGmaMarkersLayer from "../hooks/layers/useGmaMarkersLayer.js"; // Import the custom hook
import useSmsfunkmodemMarkersLayer from "../hooks/layers/useSmsfunkmodemMarkersLayer.js";
import useBereicheMarkersLayer from "../hooks/layers/useBereicheMarkersLayer.js";
import { setupPolylines } from "../utils/setupPolylines.js";
import { setupPOIs } from "../utils/setupPOIs.js";
import VersionInfoModal from "./VersionInfoModal.js";
import useDrawLines from "../hooks/layers/useDrawLines";
import useFetchPoiData from "../hooks/useFetchPoiData";
import usePoiTypData from "../hooks/usePoiTypData";
import useLayerVisibility from "../hooks/useLayerVisibility";
import useLineData from "../hooks/useLineData.js";
import plusRoundIcon from "../PlusRoundIcon.js";
import { createAndSetDevices } from "../../utils/createAndSetDevices.js";
import { restoreMapSettings, checkOverlappingMarkers } from "../../utils/mapUtils.js";
import { APP_VERSION } from "../../config/appVersion.js";
import * as layers from "../../config/layers.js";
import { initializeMap } from "../../utils/initializeMap.js";
import addItemsToMapContextMenu from "../useMapContextMenu.js";
import useGmaMarkersLayer from "../../hooks/layers/useGmaMarkersLayer.js"; // Import the custom hook
import useSmsfunkmodemMarkersLayer from "../../hooks/layers/useSmsfunkmodemMarkersLayer.js";
import useBereicheMarkersLayer from "../../hooks/layers/useBereicheMarkersLayer.js";
import { setupPolylines } from "../../utils/setupPolylines.js";
import { setupPOIs } from "../../utils/setupPOIs.js";
import VersionInfoModal from "../VersionInfoModal.js";
import useDrawLines from "../../hooks/layers/useDrawLines.js";
import useFetchPoiData from "../../hooks/useFetchPoiData.js";
import usePoiTypData from "../../hooks/usePoiTypData.js";
import useLayerVisibility from "../../hooks/useLayerVisibility.js";
import useLineData from "../../hooks/useLineData.js";
//import { useCreateAndSetDevices } from "../hooks/useCreateAndSetDevices";
import { useMapComponentState } from "../hooks/useMapComponentState";
import { disablePolylineEvents, enablePolylineEvents } from "../utils/setupPolylines";
import { updateLocation } from "../utils/updateBereichUtil";
import { initGeocoderFeature } from "../components/features/GeocoderFeature";
import { useMapComponentState } from "../../hooks/useMapComponentState.js";
import { disablePolylineEvents, enablePolylineEvents } from "../../utils/setupPolylines.js";
import { updateLocation } from "../../utils/updateBereichUtil.js";
import { initGeocoderFeature } from "../features/GeocoderFeature.js";
//--------------------------------------------
//import { currentPoiState } from "../redux/slices/currentPoiSlice.js";
import { selectGisStationsStaticDistrict, setGisStationsStaticDistrict } from "../redux/slices/webService/gisStationsStaticDistrictSlice";
import { mapIdState, userIdState } from "../redux/slices/urlParameterSlice.js";
import { poiLayerVisibleState } from "../redux/slices/poiLayerVisibleSlice.js";
import { selectedPoiState } from "../redux/slices/selectedPoiSlice.js";
import { poiReadFromDbTriggerAtom } from "../redux/slices/poiReadFromDbTriggerSlice";
import { gisStationsStaticDistrictState } from "../redux/slices/webService/gisStationsStaticDistrictSlice";
import { gisSystemStaticState } from "../redux/slices/webService/gisSystemStaticSlice";
import { mapLayersState } from "../redux/slices/mapLayersSlice";
import { selectedAreaState } from "../redux/slices/selectedAreaSlice";
import { zoomTriggerState } from "../redux/slices/zoomTriggerSlice.js";
import { polylineEventsDisabledState } from "../redux/slices/polylineEventsDisabledSlice";
import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleSlice";
import { selectGisStationsStaticDistrict, setGisStationsStaticDistrict } from "../../redux/slices/webService/gisStationsStaticDistrictSlice.js";
import { mapIdState, userIdState } from "../../redux/slices/urlParameterSlice.js";
import { poiLayerVisibleState } from "../../redux/slices/poiLayerVisibleSlice.js";
import { selectedPoiState } from "../../redux/slices/selectedPoiSlice.js";
import { poiReadFromDbTriggerAtom } from "../../redux/slices/poiReadFromDbTriggerSlice.js";
import { gisStationsStaticDistrictState } from "../../redux/slices/webService/gisStationsStaticDistrictSlice.js";
import { gisSystemStaticState } from "../../redux/slices/webService/gisSystemStaticSlice.js";
import { mapLayersState } from "../../redux/slices/mapLayersSlice.js";
import { selectedAreaState } from "../../redux/slices/selectedAreaSlice.js";
import { zoomTriggerState } from "../../redux/slices/zoomTriggerSlice.js";
import { polylineEventsDisabledState } from "../../redux/slices/polylineEventsDisabledSlice.js";
import { polylineLayerVisibleState } from "../../redux/slices/polylineLayerVisibleSlice.js";
//--------------------------------------------
import { useSelector, useDispatch } from "react-redux";
import { selectCurrentPoi, setCurrentPoi, clearCurrentPoi } from "../redux/slices/currentPoiSlice";
import CoordinateInput from "./CoordinateInput";
import CoordinateModal from "./CoordinateModal";
import CoordinatePopup from "./CoordinatePopup";
import { selectCurrentPoi, setCurrentPoi, clearCurrentPoi } from "../../redux/slices/currentPoiSlice.js";
import CoordinateInput from "../CoordinateInput.js";
import CoordinateModal from "../CoordinateModal.js";
import CoordinatePopup from "../CoordinatePopup.js";
//------------------------Daten aus API--------------------
import { fetchUserRights } from "../services/api/fetchUserRights.js";
import { fetchPoiData } from "../services/api/fetchPoiData.js";
import { fetchGisStationsStaticDistrict } from "../services/api/fetchGisStationsStaticDistrict.js";
import { fetchUserRights } from "../../services/api/fetchUserRights.js";
import { fetchPoiData } from "../../services/api/fetchPoiData.js";
import { fetchGisStationsStaticDistrict } from "../../services/api/fetchGisStationsStaticDistrict.js";
import { fetchGisStationsStatusDistrict } from "../services/api/fetchGisStationsStatusDistrict.js";
import { fetchGisStationsStatusDistrict } from "../../services/api/fetchGisStationsStatusDistrict.js";
import { fetchGisStationsMeasurements } from "../services/api/fetchGisStationsMeasurements.js";
import { fetchGisSystemStatic } from "../services/api/fetchGisSystemStatic.js";
import { usePolylineTooltipLayer } from "../hooks/usePolylineTooltipLayer";
import { selectPolylineVisible, setPolylineVisible } from "../redux/slices/polylineLayerVisibleSlice";
import { fetchGisStationsMeasurements } from "../../services/api/fetchGisStationsMeasurements.js";
import { fetchGisSystemStatic } from "../../services/api/fetchGisSystemStatic.js";
import { usePolylineTooltipLayer } from "../../hooks/usePolylineTooltipLayer.js";
import { selectPolylineVisible, setPolylineVisible } from "../../redux/slices/polylineLayerVisibleSlice.js";
import { useInitLocationDevices } from "./hooks/useInitLocationDevices";
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const dispatch = useDispatch();
@@ -996,6 +997,9 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}, [dispatch]);
//----------------------------------------------
// speichere location devices in redux store
useInitLocationDevices();
//--------------------------------------
return (
<>

View File

@@ -0,0 +1,11 @@
import { useEffect } from "react";
import { useDispatch } from "react-redux";
import { fetchLocationDevicesFromDB } from "../../../redux/slices/db/locationDevicesFromDBSlice";
export const useInitLocationDevices = () => {
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchLocationDevicesFromDB());
}, [dispatch]);
};

View File

@@ -5,10 +5,13 @@ import { useRecoilState } from "recoil";
import { selectedPoiState } from "../../redux/slices/selectedPoiSlice";
import { currentPoiState } from "../../redux/slices/currentPoiSlice";
import { mapLayersState } from "../../redux/slices/mapLayersSlice";
import { useSelector } from "react-redux";
import { selectCurrentPoi } from "../../redux/slices/currentPoiSlice";
import { fetchLocationDevicesFromDB } from "../../redux/slices/db/locationDevicesFromDBSlice";
import { useSelector, useDispatch } from "react-redux";
const PoiUpdateModal = ({ onClose, poiData, onSubmit }) => {
const dispatch = useDispatch();
const currentPoi = useSelector(selectCurrentPoi);
const selectedPoi = useRecoilState(selectedPoiState);
const [mapLayersVisibility] = useRecoilState(mapLayersState);
@@ -43,6 +46,12 @@ const PoiUpdateModal = ({ onClose, poiData, onSubmit }) => {
Basisgerät: 200,
};
const devices = useSelector((state) => state.locationDevicesFromDB.devices);
useEffect(() => {
dispatch(fetchLocationDevicesFromDB());
}, [dispatch]);
useEffect(() => {
if (poiData) {
setPoiId(poiData.idPoi);
@@ -86,23 +95,10 @@ const PoiUpdateModal = ({ onClose, poiData, onSubmit }) => {
// Fetch location devices and pre-select the current device
useEffect(() => {
const fetchLocationDevices = async () => {
try {
const response = await fetch("/api/talas5/location_device");
const data = await response.json();
setLocationDeviceData(data);
filterDevices(data);
if (poiData && poiData.idLD) {
const selectedDevice = data.find((device) => device.idLD === poiData.idLD);
setDeviceName(selectedDevice ? { value: selectedDevice.name, label: selectedDevice.name } : null);
}
} catch (error) {
console.error("Fehler beim Abrufen der Standort- und Gerätedaten:", error);
}
};
fetchLocationDevices();
}, [poiData]);
if (devices.length > 0) {
filterDevices(devices); // <-- Filter direkt die Redux-Devices
}
}, [devices]);
// Funktion zum Filtern der Geräte basierend auf den aktiven Systemen (Layern)
const filterDevices = (devices) => {
@@ -177,10 +173,18 @@ const PoiUpdateModal = ({ onClose, poiData, onSubmit }) => {
}))
: []; // Falls kein Array, dann leeres Array zurückgeben
const deviceOptions = filteredDevices.map((device) => ({
value: device.name,
label: device.name,
const deviceOptions = devices.map((device) => ({
value: device.idLD, // idLD ist die eindeutige ID des Geräts
label: device.name, // name ist der Anzeigename im Dropdown
}));
useEffect(() => {
if (poiData && devices.length > 0) {
const selectedDevice = devices.find((device) => device.idLD === poiData.idLD);
if (selectedDevice) {
setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.name });
}
}
}, [poiData, devices]);
// Custom styles for react-select
const customStyles = {

View File

@@ -1,2 +1,2 @@
// /config/appVersion
export const APP_VERSION = "1.1.22";
export const APP_VERSION = "1.1.23";

View File

@@ -5,7 +5,7 @@ import { useRecoilState, useRecoilValue } from "recoil";
import { readPoiMarkersStore } from "../redux/slices/readPoiMarkersStoreSlice.js";
import { poiReadFromDbTriggerAtom } from "../redux/slices/poiReadFromDbTriggerSlice";
const MapComponentWithNoSSR = dynamic(() => import("../components/MapComponent"), { ssr: false });
const MapComponentWithNoSSR = dynamic(() => import("../components/mainComponent/MapComponent"), { ssr: false });
const TestScriptWithNoSSR = dynamic(() => import("../components/TestScript"), { ssr: false });
export default function Home() {

View File

@@ -0,0 +1,8 @@
// /redux/api/fromDB/locationDevicesLoader.js
export const fetchLocationDevices = async () => {
const response = await fetch("/api/talas_v5_DB/locationDevice/locationDevices");
if (!response.ok) {
throw new Error("Geräteliste konnte nicht geladen werden");
}
return await response.json();
};

View File

View File

@@ -0,0 +1,33 @@
// /redux/slices/db/locationDevicesFromDBSlice.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { fetchLocationDevices } from "../../api/fromDB/locationDevicesLoader";
export const fetchLocationDevicesFromDB = createAsyncThunk("locationDevicesFromDB/fetchLocationDevicesFromDB", async () => {
return fetchLocationDevices();
});
const locationDevicesFromDBSlice = createSlice({
name: "locationDevicesFromDB",
initialState: {
devices: [],
status: "idle",
error: null,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchLocationDevicesFromDB.pending, (state) => {
state.status = "loading";
})
.addCase(fetchLocationDevicesFromDB.fulfilled, (state, action) => {
state.status = "succeeded";
state.devices = action.payload; // <-- Hier landen die Daten
})
.addCase(fetchLocationDevicesFromDB.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
});
},
});
export default locationDevicesFromDBSlice.reducer;

View File

@@ -3,6 +3,7 @@ import lineVisibilityReducer from "./slices/lineVisibilitySlice";
import currentPoiReducer from "./slices/currentPoiSlice";
import gisStationsStaticDistrictReducer from "./slices/webService/gisStationsStaticDistrictSlice";
import polylineLayerVisibleReducer from "./slices/polylineLayerVisibleSlice";
import locationDevicesFromDBReducer from "./slices/db/locationDevicesFromDBSlice";
export const store = configureStore({
reducer: {
@@ -10,5 +11,6 @@ export const store = configureStore({
currentPoi: currentPoiReducer,
gisStationsStaticDistrict: gisStationsStaticDistrictReducer,
polylineLayerVisible: polylineLayerVisibleReducer,
locationDevicesFromDB: locationDevicesFromDBReducer,
},
});