From b467ff38359dd6b253191bc4fc4102059fc7a341 Mon Sep 17 00:00:00 2001 From: ISA Date: Tue, 4 Feb 2025 09:27:42 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Linienanzeige=20abh=C3=A4ngig=20vom=20S?= =?UTF-8?q?tatus=20der=20Stationen=20(CPLs)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Polylinien werden nur angezeigt, wenn die zugehörigen Stationen (CPLs) aktiv sind - Redux speichert den Status der Stationen (1 = aktiv, 0 = inaktiv) - setupPolylines.js überprüft jetzt direkt in Redux, ob eine Linie gezeichnet werden soll - Entfernt den unnötigen activeLines-Parameter in MapComponent.js für eine bessere Struktur - Optimierte Performance: Linien ändern sich dynamisch ohne Seiten-Reload --- .env.local | 10 +- components/MapComponent.js | 20 +- config/settings.js | 5 +- utils/setupPolylines copy.js | 423 +++++++++++++++++++++++++++++++++++ utils/setupPolylines.js | 9 +- 5 files changed, 443 insertions(+), 24 deletions(-) create mode 100644 utils/setupPolylines copy.js diff --git a/.env.local b/.env.local index 328c5ab2b..b8b7b1bba 100644 --- a/.env.local +++ b/.env.local @@ -1,17 +1,17 @@ #.env.local #je nach dem Mysql Server, ob localhost freigegeben ist oder die IP Adresse des Servers, manchmal die beide und manchmal nur eine -DB_HOST=192.168.10.33 +DB_HOST=10.10.0.70 DB_USER=root DB_PASSWORD="root#$" DB_NAME=talas_v5 DB_PORT=3306 ######################### -NEXT_PUBLIC_BASE_URL="http://192.168.10.33/talas5/devices/" -NEXT_PUBLIC_SERVER_URL="http://192.168.10.33" -NEXT_PUBLIC_PROXY_TARGET="http://192.168.10.33" -NEXT_PUBLIC_ONLINE_TILE_LAYER="http://192.168.10.33/talas5/TileMap/mapTiles/{z}/{x}/{y}.png" +NEXT_PUBLIC_BASE_URL="http://10.10.0.70/talas5/devices/" +NEXT_PUBLIC_SERVER_URL="http://10.10.0.70" +NEXT_PUBLIC_PROXY_TARGET="http://10.10.0.70" +NEXT_PUBLIC_ONLINE_TILE_LAYER="http://10.10.0.70/talas5/TileMap/mapTiles/{z}/{x}/{y}.png" ######################### diff --git a/components/MapComponent.js b/components/MapComponent.js index ff2ea61c9..609ea8cfa 100644 --- a/components/MapComponent.js +++ b/components/MapComponent.js @@ -81,9 +81,8 @@ import { useSelector } from "react-redux"; const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { // **Hole nur die aktiven idLDs aus Redux** - const activeLines = useSelector((state) => state.lineVisibility.activeLines); - console.log("activeLines in MapComponent:", activeLines); - const activeIds = Object.keys(activeLines).filter((id) => activeLines[id] === 1); + //const activeLines = useSelector((state) => state.lineVisibility.activeLines); + //const activeIds = Object.keys(activeLines).filter((id) => activeLines[id] === 1); const polylineVisible = useRecoilValue(polylineLayerVisibleState); const [editMode, setEditMode] = useState(false); // editMode Zustand const { deviceName, setDeviceName } = useMapComponentState(); @@ -523,6 +522,7 @@ await fetchGisStationsStatusDistrict(mapGisStationsStatusDistrictUrl, setGisStat fetchData(); }, []); //-------------------------------------------- + //Tooltip an mouse position anzeigen für die Linien useEffect(() => { if (!map) return; @@ -532,19 +532,11 @@ await fetchGisStationsStatusDistrict(mapGisStationsStatusDistrictUrl, setGisStat polylines.forEach((polyline) => polyline.remove()); // Setze neue Marker und Polylinien mit den aktuellen Daten - const { markers: newMarkers, polylines: newPolylines } = setupPolylines( - map, - linePositions, - lineColors, - tooltipContents, - setNewCoords, - tempMarker, - polylineVisible, // polylineVisible wird jetzt korrekt übergeben - activeLines - ); + const { markers: newMarkers, polylines: newPolylines } = setupPolylines(map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, polylineVisible); newPolylines.forEach((polyline, index) => { - const tooltipContent = tooltipContents[`${linePositions[index].idLD}-${linePositions[index].idModul}`] || `idLD: ${linePositions[index].idLD} in DB gis_lines aber in WebService GisLinesStatus nicht gefunden`; + console.log("polyline: ", polyline); + const tooltipContent = tooltipContents[`${linePositions[index].idLD}-${linePositions[index].idModul}`] || "Standard-Tooltip-Inhalt"; polyline.bindTooltip(tooltipContent, { permanent: false, diff --git a/config/settings.js b/config/settings.js index 7ef891a7c..e48bd655d 100644 --- a/config/settings.js +++ b/config/settings.js @@ -1,5 +1,2 @@ // /config/settings.js -// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte -export const MAP_VERSION = "1.0.8.1"; -//export const STANDARD_SIDE_MENU = true; -//export const FULL_SIDE_MENU = false; +export const MAP_VERSION = "1.0.8.2"; diff --git a/utils/setupPolylines copy.js b/utils/setupPolylines copy.js new file mode 100644 index 000000000..7e28edeeb --- /dev/null +++ b/utils/setupPolylines copy.js @@ -0,0 +1,423 @@ +// utils/setupPolylines.js +import { findClosestPoints } from "./geometryUtils"; +import handlePoiSelect from "./handlePoiSelect"; +import { updateLocationInDatabase } from "../services/apiService"; +import { handleEditPoi, insertNewPOI, removePOI } from "./poiUtils"; +import { parsePoint } from "./geometryUtils"; +import circleIcon from "../components/gisPolylines/icons/CircleIcon"; +import startIcon from "../components/gisPolylines/icons/StartIcon"; +import endIcon from "../components/gisPolylines/icons/EndIcon"; +import { redrawPolyline } from "./mapUtils"; +import { openInNewTab } from "./openInNewTab"; +import { toast } from "react-toastify"; +import { polylineLayerVisibleState } from "../store/atoms/polylineLayerVisibleState"; +import { useRecoilValue } from "recoil"; + +// Funktion zum Deaktivieren der Polyline-Ereignisse +export function disablePolylineEvents(polylines) { + polylines.forEach((polyline) => { + polyline.off("mouseover"); + polyline.off("mouseout"); + }); +} + +// Funktion zum Aktivieren der Polyline-Ereignisse +export function enablePolylineEvents(polylines, lineColors) { + // Überprüfe, ob polylines definiert ist und ob es Elemente enthält + if (!polylines || polylines.length === 0) { + //console.warn("Keine Polylinien vorhanden oder polylines ist undefined."); + return; + } + + // Falls Polylinien vorhanden sind, wende die Events an + polylines.forEach((polyline) => { + polyline.on("mouseover", (e) => { + //console.log("Mouseover on polyline", polyline.options); + polyline.setStyle({ weight: 14 }); + const link = `${process.env.NEXT_PUBLIC_BASE_URL}cpl.aspx?id=${polyline.options.idLD}`; + //localStorage.setItem("lastElementType", "polyline"); + //localStorage.setItem("polylineLink", link); + }); + + polyline.on("mouseout", (e) => { + //console.log("Mouseout from polyline", polyline.options); + polyline.setStyle({ weight: 3 }); + }); + }); +} +// Funktion zum Schließen des Kontextmenüs und Entfernen der Markierung +function closePolylineSelectionAndContextMenu(map) { + try { + // Entferne alle markierten Polylinien + if (window.selectedPolyline) { + window.selectedPolyline.setStyle({ weight: 3 }); // Originalstil wiederherstellen + window.selectedPolyline = null; + } + + // Überprüfe, ob map und map.contextmenu definiert sind + if (map && map.contextmenu) { + map.contextmenu.hide(); // Kontextmenü schließen + } else { + console.warn("Kontextmenü ist nicht verfügbar."); + } + } catch (error) { + console.error("Fehler beim Schließen des Kontextmenüs:", error); + window.location.reload(); + } + + // Countdown-Status zurücksetzen + localStorage.removeItem("contextMenuCountdown"); + localStorage.removeItem("contextMenuExpired"); +} + +// Überprüft regelmäßig den Status in localStorage +function monitorContextMenu(map) { + setInterval(() => { + const isContextMenuExpired = localStorage.getItem("contextMenuExpired") === "true"; + if (isContextMenuExpired) { + closePolylineSelectionAndContextMenu(map); + localStorage.removeItem("contextMenuExpired"); // Flagge entfernen, um wiederverwendbar zu sein + } + }, 1000); // Alle 1 Sekunde überprüfen +} + +export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => { + 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) { + // Entferne alle Polylinien, wenn sie ausgeblendet werden sollen + if (window.polylines) { + window.polylines.forEach((polyline) => { + if (map.hasLayer(polyline)) { + map.removeLayer(polyline); + } + }); + } + return { markers: [], polylines: [] }; + } + const markers = []; + const polylines = []; + const editMode = localStorage.getItem("editMode") === "true"; // Prüfen, ob der Bearbeitungsmodus aktiv ist + + linePositions.forEach((lineData, lineIndex) => { + const lineMarkers = []; + + lineData.coordinates.forEach((coord, index) => { + let icon = circleIcon; + if (index === 0) { + icon = startIcon; + } else if (index === lineData.coordinates.length - 1) { + icon = endIcon; + } + + // Nur Marker mit circleIcon ausblenden, wenn Bearbeitungsmodus deaktiviert ist + if (icon !== circleIcon || editMode) { + const marker = L.marker(coord, { + icon: icon, + draggable: editMode, // Nur verschiebbar, wenn Bearbeitungsmodus aktiv ist + contextmenu: true, + contextmenuInheritItems: false, + contextmenuItems: [], + }).addTo(map); + + marker.on("dragend", () => { + console.log("Marker wurde verschoben in setupPolylines.js"); + if (editMode) { + const newCoords = marker.getLatLng(); + setNewCoords(newCoords); + const newCoordinates = [...lineData.coordinates]; + newCoordinates[index] = [newCoords.lat, newCoords.lng]; + + const updatedPolyline = L.polyline(newCoordinates, { + color: lineColors[`${lineData.idLD}-${lineData.idModul}`] || "#000000", + }).addTo(map); + + updatedPolyline.bindTooltip(tooltipContents[`${lineData.idLD}-${lineData.idModul}`] || "Standard-Tooltip-Inhalt", { + permanent: false, + direction: "auto", + }); + + updatedPolyline.on("mouseover", () => { + updatedPolyline.setStyle({ weight: 20 }); + updatedPolyline.bringToFront(); + }); + + updatedPolyline.on("mouseout", () => { + updatedPolyline.setStyle({ weight: 3 }); + }); + + polylines[lineIndex].remove(); + polylines[lineIndex] = updatedPolyline; + lineData.coordinates = newCoordinates; + + const requestData = { + idModul: lineData.idModul, + idLD: lineData.idLD, + newCoordinates, + }; + + fetch("/api/talas_v5_DB/gisLines/updateLineCoordinates", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(requestData), + }) + .then((response) => { + if (!response.ok) { + return response.json().then((data) => { + throw new Error(data.error || "Unbekannter Fehler"); + }); + } + return response.json(); + }) + .then((data) => { + console.log("Koordinaten erfolgreich aktualisiert:", data); + }) + .catch((error) => { + console.error("Fehler beim Aktualisieren der Koordinaten:", error.message); + }); + } else { + toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", { + position: "top-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + } + }); + + marker.on("mouseover", function () { + this.bindContextMenu({ + contextmenuItems: [ + { + text: "Stützpunkt entfernen", + icon: "/img/icons/gisLines/remove-support-point.svg", + callback: () => { + if (editMode) { + const newCoords = marker.getLatLng(); + const newCoordinates = [...lineData.coordinates]; + newCoordinates[index] = [newCoords.lat, newCoords.lng]; + + removePOI(marker, lineData, currentZoom, currentCenter); + polylines[lineIndex].remove(); + lineData.coordinates = newCoordinates; + } else { + toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", { + position: "top-center", + autoClose: 5000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + progress: undefined, + }); + } + }, + }, + ], + }); + }); + + marker.on("mouseout", function () { + this.unbindContextMenu(); + }); + + lineMarkers.push(marker); + } + }); + + const polyline = L.polyline(lineData.coordinates, { + color: lineColors[`${lineData.idLD}-${lineData.idModul}`] || "#000000", + weight: 3, + contextmenu: true, + contextmenuInheritItems: false, // Standard-Kontextmenü deaktivieren + contextmenuItems: [], + }).addTo(map); + + // Füge "Stützpunkt hinzufügen" nur hinzu, wenn editMode aktiv ist + if (editMode) { + polyline.options.contextmenuItems.push( + { + text: "Station öffnen (Tab)", + icon: "/img/screen_new.png", + callback: (e) => { + const link = `${process.env.NEXT_PUBLIC_BASE_URL}cpl.aspx?ver=35&kue=24&id=${lineData.idLD}`; + window.open(link, "_blank"); + }, + }, + { separator: true }, + + { + text: "Koordinaten anzeigen", + icon: "/img/not_listed_location.png", + callback: (e) => { + alert("Breitengrad: " + e.latlng.lat.toFixed(5) + "\nLängengrad: " + e.latlng.lng.toFixed(5)); + }, + }, + { separator: true }, + { + text: "Reinzoomen", + icon: "/img/zoom_in.png", + callback: (e) => map.zoomIn(), + }, + { + text: "Rauszoomen", + icon: "/img/zoom_out.png", + callback: (e) => map.zoomOut(), + }, + { + text: "Hier zentrieren", + icon: "/img/center_focus.png", + callback: (e) => map.panTo(e.latlng), + }, + { separator: true }, + { + text: "POI hinzufügen", + icon: "/img/add_station.png", + callback: (e) => { + // Hier kannst du die Logik für das Hinzufügen eines POIs implementieren + alert("POI hinzufügen an: " + e.latlng); + }, + }, + { + text: "Stützpunkt hinzufügen", + icon: "/img/icons/gisLines/add-support-point.svg", + callback: (e) => { + if (tempMarker) { + tempMarker.remove(); + } + const newPoint = e.latlng; + const closestPoints = findClosestPoints(lineData.coordinates, newPoint, map); + insertNewPOI(closestPoints, newPoint, lineData, map); + redrawPolyline(lineData, lineColors, tooltipContents, map); + window.location.reload(); + }, + } + ); + } else { + polyline.options.contextmenuItems.push( + { + text: "Station öffnen (Tab)", + icon: "/img/screen_new.png", + callback: (e) => { + const link = `${process.env.NEXT_PUBLIC_BASE_URL}cpl.aspx?ver=35&kue=24&id=${lineData.idLD}`; + window.open(link, "_blank"); + }, + }, + { separator: true }, + + { + text: "Koordinaten anzeigen", + icon: "/img/not_listed_location.png", + callback: (e) => { + alert("Breitengrad: " + e.latlng.lat.toFixed(5) + "\nLängengrad: " + e.latlng.lng.toFixed(5)); + }, + }, + { separator: true }, + { + text: "Reinzoomen", + icon: "/img/zoom_in.png", + callback: (e) => map.zoomIn(), + }, + { + text: "Rauszoomen", + icon: "/img/zoom_out.png", + callback: (e) => map.zoomOut(), + }, + + { + text: "Hier zentrieren", + icon: "/img/center_focus.png", + callback: (e) => map.panTo(e.latlng), + }, + { separator: true }, + { + text: "POI hinzufügen", + icon: "/img/add_station.png", + callback: (e) => { + // Hier kannst du die Logik für das Hinzufügen eines POIs implementieren + alert("POI hinzufügen an: " + e.latlng); + }, + } + ); + } + + // Hier wird der Tooltip hinzugefügt + polyline.bindTooltip(tooltipContents[`${lineData.idLD}-${lineData.idModul}`] || "Standard-Tooltip-Inhalt", { + permanent: false, + direction: "auto", + }); + + polyline.on("mouseover", (e) => { + const startTime = Date.now(); // Startzeit erfassen + localStorage.setItem("contextMenuStartTime", startTime); // Speichern in localStorage + + // Starte einen Intervall-Timer, um die Differenz zu berechnen + /* const countdownInterval = setInterval(() => { + const currentTime = Date.now(); + const elapsedTime = (currentTime - startTime) / 1000; // Differenz in Sekunden + + // Speichern der abgelaufenen Zeit in localStorage + localStorage.setItem("contextMenuCountdown", elapsedTime); + + // Wenn die Zeit 17 Sekunden erreicht, schließe das Menü + if (elapsedTime >= 17) { + clearInterval(countdownInterval); + const contextMenu = map.contextmenu; // Zugriff auf das Kontextmenü + contextMenu.hide(); // Kontextmenü schließen + } + }, 1000); */ + // Jede Sekunde + //console.log("Mouseover on polyline", lineData); + polyline.setStyle({ weight: 14 }); + const link = `${process.env.NEXT_PUBLIC_BASE_URL}cpl.aspx?ver=35&kue=24&id=${lineData.idLD}`; + console.log("Link der Linie:", link); + //localStorage.setItem("lastElementType", "polyline"); + //localStorage.setItem("polylineLink", link); + }); + + polyline.on("mouseout", (e) => { + // console.log("Mouseout from polyline", lineData); + polyline.setStyle({ weight: 3 }); + // Setze den Countdown auf 0, wenn mouseout ausgelöst wird + localStorage.setItem("contextMenuCountdown", 0); + }); + // Speichere den Link bei einem Rechtsklick (Kontextmenü) + /* + polyline.on("contextmenu", (e) => { + const link = `${process.env.NEXT_PUBLIC_BASE_URL}cpl.aspx?ver=35&kue=24&id=${lineData.idLD}`; + console.log("Link der Linie (via Rechtsklick):", link); + localStorage.setItem("lastElementType", "polyline"); + localStorage.setItem("polylineLink", link); + }); + */ + // Starte den Timer zum Schließen des Kontextmenüs nach 15 Sekunden + polyline.on("contextmenu", function (e) { + const contextMenu = this._map.contextmenu; // Zugriff auf das Kontextmenü + const closeMenu = () => contextMenu.hide(); // Funktion zum Schließen des Menüs + + const countdown = parseInt(localStorage.getItem("contextMenuCountdown"), 30); + if (countdown >= 28) { + closeMenu(); + } + }); + + polylines.push(polyline); + markers.push(...lineMarkers); + }); + + // Speichere Polylines und LineColors global für den Zugriff in anderen Funktionen + window.polylines = polylines; + window.lineColors = lineColors; + monitorContextMenu(map); + return { markers, polylines }; +}; diff --git a/utils/setupPolylines.js b/utils/setupPolylines.js index 968017890..75366d6c8 100644 --- a/utils/setupPolylines.js +++ b/utils/setupPolylines.js @@ -12,6 +12,7 @@ import { openInNewTab } from "./openInNewTab"; import { toast } from "react-toastify"; import { polylineLayerVisibleState } from "../store/atoms/polylineLayerVisibleState"; import { useRecoilValue } from "recoil"; +import { store } from "../redux/store"; // Importiere den Store // Funktion zum Deaktivieren der Polyline-Ereignisse export function disablePolylineEvents(polylines) { @@ -81,11 +82,16 @@ function monitorContextMenu(map) { }, 1000); // Alle 1 Sekunde überprüfen } -export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible, activeLines) => { +export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => { + // Hole activeLines direkt aus Redux + const state = store.getState(); // Hole den gesamten Zustand + const activeLines = state.lineVisibility.activeLines; // Zugriff auf activeLines + if (!activeLines) { console.warn("activeLines ist undefined oder null."); return { markers: [], polylines: [] }; } + if (localStorage.getItem("polylineVisible") === null) { localStorage.setItem("polylineVisible", "true"); // Standardwert setzen polylineVisible = true; // Wert in der Funktion initialisieren @@ -114,6 +120,7 @@ export const setupPolylines = (map, linePositions, lineColors, tooltipContents, // **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;