From ce8d1f5a1988abda427ed2279cff72d6dd7ea8ec Mon Sep 17 00:00:00 2001 From: ISA Date: Sun, 5 May 2024 13:14:09 +0200 Subject: [PATCH] Fix: Sicherstellen, dass MapComponent innerhalb des RecoilRoot-Kontexts liegt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Entfernt redundanten `RecoilRoot` aus `MapComponent`, um Probleme mit verschachtelten Wurzeln zu vermeiden. - Sichergestellt, dass `MapComponent` immer innerhalb des zentralen `RecoilRoot` gerendert wird, der in `_app.js` definiert ist. - Das Problem "Diese Komponente muss innerhalb einer ``-Komponente verwendet werden" durch Platzieren aller Recoil-States im korrekten Kontext behoben. - `ShowAddStationPopup` direkt als JSX-Element innerhalb von `MapComponent` zur besseren Übersicht verwendet. --- components/MapComponent.js | 104 ++++++++++++++++------ components/ShowAddStationPopup.js | 71 ++++++++++----- config/config.js | 8 +- pages/api/[...path].js | 4 +- pages/index copy.js | 98 --------------------- pages/index.js | 110 +++++++++++------------- store/atoms/poiReadFromDbTriggerAtom.js | 7 ++ store/selectors/readPoiMarkersStore.js | 14 ++- 8 files changed, 193 insertions(+), 223 deletions(-) delete mode 100644 pages/index copy.js create mode 100644 store/atoms/poiReadFromDbTriggerAtom.js diff --git a/components/MapComponent.js b/components/MapComponent.js index d83bc13f0..7c5ec6695 100644 --- a/components/MapComponent.js +++ b/components/MapComponent.js @@ -1,6 +1,6 @@ // components/MapComponent.js import React, { useEffect, useRef, useState } from "react"; -import ReactDOM from "react-dom/client"; // Import from 'react-dom/client' +//import ReactDOM from "react-dom/client"; // Import from 'react-dom/client' import L, { marker } from "leaflet"; import "leaflet/dist/leaflet.css"; import "leaflet-contextmenu/dist/leaflet.contextmenu.css"; @@ -10,7 +10,7 @@ import dynamic from "next/dynamic"; import "leaflet.smooth_marker_bouncing"; import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet"; import DataSheet from "./DataSheet.js"; -import { useRecoilState, useRecoilValue, RecoilRoot } from "recoil"; +import { useRecoilState, useRecoilValue } from "recoil"; import { gisStationsStaticDistrictState } from "../store/atoms/gisStationState.js"; import { gisSystemStaticState } from "../store/atoms/gisSystemState.js"; import { mapLayersState } from "../store/atoms/mapLayersState.js"; @@ -18,9 +18,23 @@ import { selectedAreaState } from "../store/atoms/selectedAreaState.js"; import { zoomTriggerState } from "../store/atoms/zoomTriggerState.js"; import { poiTypState } from "../store/atoms/poiTypState.js"; import ShowAddStationPopup from "./ShowAddStationPopup"; +import { poiReadFromDbTriggerAtom } from '../store/atoms/poiReadFromDbTriggerAtom'; //import { createRoot } from "react-dom/client"; const MapComponent = ({ locations, onLocationUpdate }) => { + + const [showPopup, setShowPopup] = useState(false); + + const openPopup = () => setShowPopup(true); + const closePopup = () => setShowPopup(false); + + const handleAddStation = (stationData) => { + // Station-Daten speichern oder API-Aufruf durchführen + console.log("Neue Station:", stationData); + closePopup(); // Schließt das Popup nach dem Hinzufügen + }; + + const poiReadTrigger = useRecoilValue(poiReadFromDbTriggerAtom); const [poiTypData, setPoiTypData] = useState(poiTypState); // Recoil State verwenden const poiLayerRef = useRef(null); // Referenz auf die Layer-Gruppe für Datenbank-Marker const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte @@ -257,7 +271,7 @@ const MapComponent = ({ locations, onLocationUpdate }) => { zoomControl: false, contextmenu: true, contextmenuItems: [ - { text: "Station hinzufügen", callback: showAddStationPopup }, + { text: "Station hinzufügen"}, { text: "Station öffnen (Tab)", icon: "img/screen_new.png", @@ -307,7 +321,8 @@ const MapComponent = ({ locations, onLocationUpdate }) => { // Rufe hier Funktionen auf, die eine initialisierte Karte benötigen. }); } - }, [mapRef, map]); // Prüfe die Abhängigkeiten sorgfältig + console.log("trigger in MapComponent.js:", poiReadTrigger); + }, [mapRef, map, poiReadTrigger]); // Prüfe die Abhängigkeiten sorgfältig //------------------------------------------ function parsePoint(pointString) { @@ -339,7 +354,7 @@ const MapComponent = ({ locations, onLocationUpdate }) => { console.error("Fehler beim Abrufen der poiTyp Daten:", error); } }; - + console.log("trigger in MapComponent.js in fetchPoiTypData:", poiReadTrigger); fetchPoiTypData(); }, []); @@ -409,16 +424,16 @@ const MapComponent = ({ locations, onLocationUpdate }) => { }; //-----Kontextmenu----ende------------ // Ensure this function is only called when map is initialized and available - const showAddStationPopup = (e, map) => { - const container = L.DomUtil.create("div"); +/* const showAddStationPopup = (e, map) => { + const container = L.DomUtil.create("div"); // Create a root container for the React component inside the popup const root = ReactDOM.createRoot(container); root.render( - + - + ); // Create and configure the popup @@ -428,22 +443,22 @@ const MapComponent = ({ locations, onLocationUpdate }) => { initMap.on("popupclose", () => { root.unmount(); // Use unmount method from the root }); - }; + }; */ // Inside your ShowAddStationPopup component - useEffect(() => { +/* useEffect(() => { // Cleanup function to unmount React component return () => { if (container._reactRoot) { container._reactRoot.unmount(); } }; - }, []); + }, []); */ //------------------------------------------ // Hinzufügen eines neuen Standorts (Marker) in MySQL-DB-Tabelle (poi) - async function handleSubmit(event) { +/* async function handleSubmit(event) { event.preventDefault(); const form = event.target; @@ -478,7 +493,7 @@ const MapComponent = ({ locations, onLocationUpdate }) => { console.error("Fehler beim Hinzufügen der Station"); // Fehlerbehandlung } - } + } */ //--------------------------------------- @@ -547,17 +562,25 @@ const MapComponent = ({ locations, onLocationUpdate }) => { if (map && poiLayerRef.current) { // Entfernen der dbLayer bei Unmount map.removeLayer(poiLayerRef.current); - poiLayerRef.current = null; + poiLayerRef.current = new L.LayerGroup().addTo(map); } + locations.forEach((location) => { + // Fügen Sie hier die Logik hinzu, um Marker zu erstellen und zu konfigurieren + }); }; - }, [map]); // Dieser Effekt läuft nur, wenn sich `map` ändert + console.log("trigger in MapComponent.js:", poiReadTrigger); + }, [map,locations, poiReadTrigger]); // Dieser Effekt läuft nur, wenn sich `map` ändert //------------------------------------------ + // poiLayerRef + //-------------------------------------------- + useEffect(() => { if (map && poiLayerRef.current) { - // Sicherstellen, dass die alte dbLayer entfernt wird + // Entfernen Sie die bestehende Ebene und erstellen Sie eine neue map.removeLayer(poiLayerRef.current); poiLayerRef.current = new L.LayerGroup().addTo(map); - + + // Fügen Sie die aktualisierten Marker hinzu locations.forEach((location) => { const { latitude, longitude } = parsePoint(location.position); const marker = L.marker([latitude, longitude], { @@ -570,34 +593,39 @@ const MapComponent = ({ locations, onLocationUpdate }) => { draggable: true, id: location.idPoi, }); - - // Popup binden, aber nicht automatisch öffnen + + // Popup konfigurieren marker.bindPopup( - //N/A oder location.idPoiTyp=0 hier soll der Name von poiTyp Tabelle kommen, also foreign key - `${location.description || "Unbekannt"}
Type: ${location.idPoiTyp || "N/A oder location.idPoiTyp=0"}
Lat: ${latitude.toFixed(5)}, Lng: ${longitude.toFixed(5)}` + `${location.description || "Unbekannt"}
Type: ${ + location.idPoiTyp || "N/A" + }
Lat: ${latitude.toFixed(5)}, Lng: ${longitude.toFixed(5)}` ); - - // Event-Handler für Mouseover und Mouseout hinzufügen + + // Event-Handler hinzufügen marker.on("mouseover", function () { this.openPopup(); }); marker.on("mouseout", function () { this.closePopup(); }); - - marker.on("dragend", function (e) { + + marker.on("dragend", (e) => { const newLat = e.target.getLatLng().lat; const newLng = e.target.getLatLng().lng; const markerId = e.target.options.id; updateLocationInDatabase(markerId, newLat, newLng).then(() => { onLocationUpdate(markerId, newLat, newLng); + console.log("trigger in MapComponent.js:", poiReadTrigger); }); }); - + marker.addTo(poiLayerRef.current); }); } - }, [map, locations, onLocationUpdate]); // Dieser Effekt läuft, wenn `map`, `locations` oder `onLocationUpdate` sich ändern + + }, [map, locations, onLocationUpdate,poiReadTrigger]); + + //------------------------------------------ function parsePoint(position) { const [longitude, latitude] = position.slice(6, -1).split(" "); @@ -1476,10 +1504,30 @@ const MapComponent = ({ locations, onLocationUpdate }) => { } }, [map, zoomTrigger]); + //--------------------------------------------------------- + useEffect(() => { + console.log("Aktualisierung in MapComponent.js:", poiReadTrigger); + + // Logik zur Aktualisierung der Map hier hinzufügen + // Beispiel: Daten neu laden oder aktualisieren + +}, [poiReadTrigger]); //--------------------------------------------------------- return ( <> +
+ + + {/* Direkt als JSX verwenden */} + {showPopup && ( + + )} +
{ - const loadData = useRecoilValue(readPoiMarkersStore); + const [poiTypData2, setPoiTypData2] = useState(); // Recoil State verwenden const [name, setName] = useState(""); const [poiTypeId, setPoiTypeId] = useState(""); // Initialize as string const [latitude] = useState(latlng.lat.toFixed(5)); const [longitude] = useState(latlng.lng.toFixed(5)); + const setLoadData = useSetRecoilState(readPoiMarkersStore); + const setTrigger = useSetRecoilState(poiReadFromDbTriggerAtom); + +/* useEffect(() => { + if (map && loadData) { + + console.log("Map and loadData are defined in ShowAddStationPopup.js", map); + console.log("loadData object in ShowAddStationPopup.js:", loadData); + // Your code here + }else{ + console.log("Map and loadData are not defined in ShowAddStationPopup.js"); + } + }, [map, loadData]); */ + +// In Kontextmenü-Formular Typen anzeigen useEffect(() => { const fetchPoiTypData2 = async () => { try { @@ -32,32 +49,40 @@ const ShowAddStationPopup = ({ map, latlng }) => { fetchPoiTypData2(); }, []); - const handleSubmit = async (event) => { - event.preventDefault(); - const formData = { - name, // Name der Station - poiTypeId, // Typ der Station, logged as idPoiTyp - latitude, // Breitengrad - longitude, // Längengrad - }; +//-----------------handleSubmit------------------- +const handleSubmit = async (event) => { + event.preventDefault(); + const formData = { + name, + poiTypeId, + latitude, + longitude, + }; - fetch("/api/addLocation", { + const response = await fetch("/api/addLocation", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(formData), - }) - .then((response) => response.json()) - .then((data) => console.log(data)) // Handle the response data - .catch((error) => console.error(error)); // Handle any errors - await loadData(); + }); - // Check if map is not undefined and call closePopup - if (map && typeof map.closePopup === "function") { + if (response.ok) { + setTrigger((trigger) => { + console.log("Aktueller Trigger-Wert:", trigger); // Vorheriger Wert + const newTrigger = trigger + 1; + console.log("Neuer Trigger-Wert:", newTrigger); // Aktualisierter Wert + return newTrigger; + }); + } else { + console.error("Fehler beim Hinzufügen des POI"); + } + + if (map && typeof map.closePopup === "function") { map.closePopup(); - } else { - console.error("Map object is undefined or closePopup is not a function"); - } - }; + } +}; + + + return (
diff --git a/config/config.js b/config/config.js index 8f777e4fc..a466755ed 100644 --- a/config/config.js +++ b/config/config.js @@ -23,17 +23,17 @@ if (typeof window !== "undefined") { user = url.searchParams.get("u") || "484"; // Ein weiterer Parameter aus der URL, Standardwert ist '484 admin zu testen von Stationen ausblenden und einblenden in der Card' // Konstruktion von URLs, die auf spezifische Ressourcen auf dem Server zeigen - mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict?idMap=${c}&idUser=${user}`; //idMap: 10, idUser: 484 + /* mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict?idMap=${c}&idUser=${user}`; //idMap: 10, idUser: 484 mapGisStationsStatusDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStatusDistrict?idMap=${c}&idUser=${user}`; mapGisStationsMeasurementsUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsMeasurements?idMap=${c}`; mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${c}&idUser=${user}`; - mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; + mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; */ - /* mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict`; + mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict`; mapGisStationsStatusDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStatusDistrict`; mapGisStationsMeasurementsUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsMeasurements`; mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic`; - mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; */ + mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; } // Export der definierten Variablen und URLs, damit sie in anderen Teilen der Anwendung verwendet werden können diff --git a/pages/api/[...path].js b/pages/api/[...path].js index 299b2253b..49efc5183 100644 --- a/pages/api/[...path].js +++ b/pages/api/[...path].js @@ -2,8 +2,8 @@ import { createProxyMiddleware } from "http-proxy-middleware"; export default createProxyMiddleware({ - target: "http://10.10.0.13", // Ziel-URL des Proxys - //target: "http://192.168.10.187:3000", // Ziel-URL des Proxys + //target: "http://10.10.0.13", // Ziel-URL des Proxys + target: "http://192.168.10.187:3000", // Ziel-URL des Proxys changeOrigin: true, pathRewrite: { "^/api": "/", // Optional: Entfernt /api aus dem Pfad, wenn das Backend dies nicht erfordert diff --git a/pages/index copy.js b/pages/index copy.js deleted file mode 100644 index cff585c3a..000000000 --- a/pages/index copy.js +++ /dev/null @@ -1,98 +0,0 @@ -// pages/index.js -import { useEffect, useState } from "react"; -import dynamic from "next/dynamic"; -import { useSetRecoilState } from "recoil"; -import { readPoiMarkersStore } from "../store/selectors/readPoiMarkersStore"; -const MapComponentWithNoSSR = dynamic( - () => import("../components/MapComponent"), - { ssr: false } -); - -export default function Home() { - const setLoadData = useSetRecoilState(readPoiMarkersStore); - const [mParam, setMParam] = useState([""]); - const [uParam, setUParam] = useState([""]); - - const [locations, setLocations] = useState([]); - const [formData, setFormData] = useState({ - name: "", - longitude: "", - latitude: "", - type: "", - }); - - const loadData = async () => { - const response = await fetch("/api/readLocations"); - const data = await response.json(); - setLocations(data); - }; - useEffect(() => { - setLoadData(async () => { - const response = await fetch("/api/readLocations"); - const data = await response.json(); - setLocations(data); // Überlegungen für setLocations beachten - }); - }, []); - - useEffect(() => { - // Funktion, um URL-Parameter zu holen - function getURLParameter(name) { - // Nutze URLSearchParams, eine Web API für die Arbeit mit Query-Strings - const params = new URLSearchParams(window.location.search); - return params.get(name); // Holt den Wert des Parameternamens - } - - // Hole die Parameter 'm' und 'u' - setMParam(getURLParameter("m")); - setUParam(getURLParameter("u")); - - // Logge die Werte in der Konsole - console.log(`Parameter m: ${mParam}, Parameter u: ${uParam}`); - loadData(); - }, []); - const handleAddLocation = async (name, type, lat, lng) => { - const response = await fetch("/api/addLocation", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - name, - type, - latitude: lat, - longitude: lng, - }), - }); - - if (response.ok) { - console.log("Standort erfolgreich hinzugefügt"); - setFormData({ name: "", longitude: "", latitude: "", type: "" }); // Formular zurücksetzen - loadData(); // Daten erneut laden - } else { - console.error("Fehler beim Hinzufügen des Standorts"); - } - }; - - const handleLocationUpdate = (id, newLatitude, newLongitude) => { - setLocations((prevLocations) => { - return prevLocations.map((location) => { - if (location.idPoi === id) { - return { - ...location, - // Hier musst du ggf. die Formatierung anpassen, je nachdem wie du die Koordinaten speicherst - position: `POINT(${newLongitude} ${newLatitude})`, - }; - } - return location; - }); - }); - }; - return ( -
- {/* Ihr Formular */} - -
- ); -} diff --git a/pages/index.js b/pages/index.js index cff585c3a..7a94377e1 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,93 +1,85 @@ // pages/index.js import { useEffect, useState } from "react"; import dynamic from "next/dynamic"; -import { useSetRecoilState } from "recoil"; -import { readPoiMarkersStore } from "../store/selectors/readPoiMarkersStore"; +import { useRecoilState , useRecoilValue} from "recoil"; +import { readPoiMarkersStore } from "../store/selectors/readPoiMarkersStore"; // Aktualisiert mit atom +import { poiReadFromDbTriggerAtom } from '../store/atoms/poiReadFromDbTriggerAtom'; + const MapComponentWithNoSSR = dynamic( () => import("../components/MapComponent"), { ssr: false } ); export default function Home() { - const setLoadData = useSetRecoilState(readPoiMarkersStore); - const [mParam, setMParam] = useState([""]); - const [uParam, setUParam] = useState([""]); - - const [locations, setLocations] = useState([]); - const [formData, setFormData] = useState({ - name: "", - longitude: "", - latitude: "", - type: "", - }); + const poiReadTrigger = useRecoilValue(poiReadFromDbTriggerAtom); + const [locations, setLocations] = useRecoilState(readPoiMarkersStore); + const [mParam, setMParam] = useState(""); + const [uParam, setUParam] = useState(""); const loadData = async () => { - const response = await fetch("/api/readLocations"); - const data = await response.json(); - setLocations(data); - }; - useEffect(() => { - setLoadData(async () => { + try { const response = await fetch("/api/readLocations"); + if (!response.ok) { + throw new Error("Fehler beim Laden der Standortdaten"); + } const data = await response.json(); - setLocations(data); // Überlegungen für setLocations beachten - }); - }, []); + setLocations(data); + console.log("Geladene Daten in Home.js:", data); + } catch (error) { + console.error(error.message); + } + }; useEffect(() => { - // Funktion, um URL-Parameter zu holen + // URL-Parameter abfragen function getURLParameter(name) { - // Nutze URLSearchParams, eine Web API für die Arbeit mit Query-Strings const params = new URLSearchParams(window.location.search); - return params.get(name); // Holt den Wert des Parameternamens + return params.get(name); } - - // Hole die Parameter 'm' und 'u' setMParam(getURLParameter("m")); setUParam(getURLParameter("u")); - // Logge die Werte in der Konsole - console.log(`Parameter m: ${mParam}, Parameter u: ${uParam}`); + // Daten beim Laden der Seite holen loadData(); - }, []); - const handleAddLocation = async (name, type, lat, lng) => { - const response = await fetch("/api/addLocation", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - name, - type, - latitude: lat, - longitude: lng, - }), - }); + console.log("poiReadTrigger in Home.js:", poiReadTrigger); + }, [poiReadTrigger]); - if (response.ok) { + const handleAddLocation = async (name, type, lat, lng) => { + try { + const response = await fetch("/api/addLocation", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ name, type, latitude: lat, longitude: lng }), + }); + if (!response.ok) { + throw new Error("Fehler beim Hinzufügen des Standorts"); + } console.log("Standort erfolgreich hinzugefügt"); - setFormData({ name: "", longitude: "", latitude: "", type: "" }); // Formular zurücksetzen - loadData(); // Daten erneut laden - } else { - console.error("Fehler beim Hinzufügen des Standorts"); + loadData(); // Aktualisiere die Daten nach dem Hinzufügen + console.log("poiReadTrigger in Home.js:", poiReadTrigger); + } catch (error) { + console.error(error.message); } }; const handleLocationUpdate = (id, newLatitude, newLongitude) => { - setLocations((prevLocations) => { - return prevLocations.map((location) => { - if (location.idPoi === id) { - return { - ...location, - // Hier musst du ggf. die Formatierung anpassen, je nachdem wie du die Koordinaten speicherst - position: `POINT(${newLongitude} ${newLatitude})`, - }; - } - return location; - }); - }); + setLocations((prevLocations) => + prevLocations.map((location) => + location.idPoi === id + ? { ...location, position: `POINT(${newLongitude} ${newLatitude})` } + : location + ) + ); }; +//------------------------------------ + // Daten beim Laden der Seite holen + useEffect(() => { + loadData(); + console.log("poiReadTrigger in Home.js:", poiReadTrigger); + }, [poiReadTrigger]); +//------------------------------------ return (
- {/* Ihr Formular */} { - const response = await fetch("/api/readLocations"); - const data = await response.json(); - return data; - }, -}); + key: 'readPoiMarkersStore', + default: [], +}); \ No newline at end of file