// utils/setupPolylines.js import { findClosestPoints } from "./geometryUtils"; import handlePoiSelect from "./handlePoiSelect"; import { updateLocationInDatabase } from "../services/api/updateLocationInDatabase"; 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 "./redrawPolyline"; import { openInNewTab } from "./openInNewTab"; import { toast } from "react-toastify"; import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleSlice"; import { useRecoilValue } from "recoil"; import { store } from "../redux/store"; // Importiere den Store import { openAddPoiOnPolylineModal } from "../redux/slices/addPoiOnPolylineSlice"; import { openPolylineContextMenu, closePolylineContextMenu } from "../redux/slices/polylineContextMenuSlice"; // 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 { // Falls eine Polyline aktiv ist, entfernen if (window.selectedPolyline) { window.selectedPolyline.setStyle({ weight: 3 }); window.selectedPolyline = null; } // Überprüfen, ob das Kontextmenü existiert, bevor es geschlossen wird if (map && map.contextmenu && typeof map.contextmenu.hide === "function") { map.contextmenu.hide(); // Menü schließen } else { console.warn("Kontextmenü existiert nicht mehr oder wurde bereits entfernt."); } } catch (error) { console.error("Fehler beim Schließen des Kontextmenüs:", error); } // Lokale Speicherwerte zurücksetzen localStorage.removeItem("contextMenuCountdown"); localStorage.removeItem("contextMenuExpired"); } // Überprüft regelmäßig den Status in localStorage function monitorContextMenu(map) { function checkAndClose() { const isContextMenuExpired = localStorage.getItem("contextMenuExpired") === "true"; if (isContextMenuExpired) { if (map && map.contextmenu && typeof map.contextmenu.hide === "function") { closePolylineSelectionAndContextMenu(map); localStorage.removeItem("contextMenuExpired"); } else { console.warn("Kontextmenü war nicht verfügbar und konnte nicht geschlossen werden."); } } setTimeout(checkAndClose, 1000); // **Recursive Timeout statt Intervall** } checkAndClose(); } //------------------------------------------ store.subscribe(() => { const state = store.getState(); // Redux-Toolkit empfohlene Methode if (state.polylineContextMenu.forceClose) { console.log("🚀 Redux-Event erkannt - Kontextmenü wird geschlossen."); store.dispatch(closePolylineContextMenu()); if (window.map && window.map.contextmenu) { window.map.contextmenu.hide(); } } }); //-------------------------------------------- export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => { if (!polylineVisible) { console.warn("Polylines deaktiviert - keine Zeichnung"); return { markers: [], polylines: [] }; } 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) => { //console.log("LineData:", lineData.idLD, lineData.idModul); // **Fix: Sicherstellen, dass activeLines definiert ist und idLD existiert** 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 setup 1", { 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) => { store.dispatch(openAddPoiOnPolylineModal(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) => { store.dispatch(openAddPoiOnPolylineModal(e.latlng)); }, } */ ); } // Hier wird der Tooltip hinzugefügt polyline.bindTooltip(tooltipContents[`${lineData.idLD}-${lineData.idModul}`] || "Standard-Tooltip-Inhalt setup", { 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); }); */ // Event-Listener für Redux Store-Änderungen registrieren // Starte den Timer zum Schließen des Kontextmenüs nach 15 Sekunden polyline.on("contextmenu", (e) => { store.dispatch(closePolylineContextMenu()); setTimeout(() => { if (!map || !map.contextmenu) return; store.dispatch( openPolylineContextMenu({ position: { lat: e.latlng.lat, lng: e.latlng.lng }, polylineId: polyline.options.idLD, }) ); // Schließen nach 17 Sekunden setTimeout(() => { store.dispatch(closePolylineContextMenu()); if (map.contextmenu) { map.contextmenu.hide(); } }, 17000); }, 50); }); 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 }; };