contextmenu, manchmal geht manchmal nicht, Timing Problem

This commit is contained in:
Ismail Ali
2025-03-10 22:01:22 +01:00
parent 8ab1c53996
commit cc716eb4e7
15 changed files with 197 additions and 197 deletions

View File

@@ -7,12 +7,12 @@ DB_NAME=talas_v5
DB_PORT=3306
# Public Settings (Client braucht IP/Domain)
NEXT_PUBLIC_SERVER_URL="http://10.10.0.70" # oder evtl. später https://nodemap.firma.de
NEXT_PUBLIC_SERVER_URL="http://192.168.10.33" # oder evtl. später https://nodemap.firma.de
NEXT_PUBLIC_ENABLE_GEOCODER=true
NEXT_PUBLIC_USE_MOCK_API=false
NEXT_PUBLIC_DEBUG_LOG=true
# für Polylines/kabelstecken -> in Konextmenü "Station öffnen" "
NEXT_PUBLIC_BASE_URL=http://10.10.0.70/talas5/devices/
NEXT_PUBLIC_API_BASE_URL=http://10.10.0.70/talas5/ClientData/WebServiceMap.asmx
NEXT_PUBLIC_API_PORT_3000=http://10.10.0.70:3000
NEXT_PUBLIC_BASE_URL=http://192.168.10.33/talas5/devices/
NEXT_PUBLIC_API_BASE_URL=http://192.168.10.33/talas5/ClientData/WebServiceMap.asmx
NEXT_PUBLIC_API_PORT_3000=http://192.168.10.33:3000

View File

@@ -1,6 +1,6 @@
// components/TestScript.js
import { useEffect } from "react";
import setupPolylinesCode from "!!raw-loader!../utils/setupPolylines.js"; // Lädt die gesamte setupPolylines.js als Text
import setupPolylinesCode from "!!raw-loader!../utils/polylines/setupPolylines.js"; // Lädt die gesamte setupPolylines.js als Text
export default function TestScript() {
useEffect(() => {

View File

@@ -24,7 +24,7 @@ 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 { setupPolylines } from "../../utils/polylines/setupPolylines.js";
import { setupPOIs } from "../../utils/setupPOIs.js";
import VersionInfoModal from "../VersionInfoModal.js";
import useDrawLines from "../../hooks/layers/useDrawLines.js";
@@ -35,7 +35,6 @@ import useLineData from "../../hooks/useLineData.js";
//import { useCreateAndSetDevices } from "../hooks/useCreateAndSetDevices";
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";
//--------------------------------------------
@@ -79,12 +78,14 @@ import ShowAddStationPopup from "../AddPOIModal.js";
import { useInitGisStationsStatic } from "../mainComponent/hooks/useInitGisStationsStatic";
import { closeAddPoiModal } from "../../redux/slices/addPoiOnPolylineSlice.js";
import AddPOIOnPolyline from "../AddPOIOnPolyline";
import { closePolylineContextMenu } from "../../redux/slices/polylineContextMenuSlice";
import { forceCloseContextMenu } from "../../redux/slices/polylineContextMenuSlice";
import { enablePolylineEvents, disablePolylineEvents } from "../../utils/polylines/eventHandlers";
import { updateCountdown, closePolylineContextMenu, forceCloseContextMenu } from "../../redux/slices/polylineContextMenuSlice";
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const dispatch = useDispatch();
const isPolylineContextMenuOpen = useSelector((state) => state.polylineContextMenu.isOpen);
const countdown = useSelector((state) => state.polylineContextMenu.countdown);
const contextMenuState = useSelector((state) => state.polylineContextMenu);
const polylinePosition = contextMenuState.position ? L.latLng(contextMenuState.position.lat, contextMenuState.position.lng) : null;
@@ -1063,6 +1064,40 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
useInitGisStationsStatic();
//--------------------------------------
useEffect(() => {
if (isPolylineContextMenuOpen) {
console.log("🔄 Starte Redux-Countdown für Kontextmenü!");
const interval = setInterval(() => {
dispatch(updateCountdown());
console.log(`⏳ Redux Countdown: ${countdown} Sekunden`);
if (countdown <= 2) {
console.log("🚀 Kontextmenü wird wegen Countdown < 2 geschlossen.");
dispatch(closePolylineContextMenu());
if (window.map?.contextmenu) {
window.map.contextmenu.hide();
}
clearInterval(interval);
}
}, 1000);
return () => {
clearInterval(interval);
};
}
}, [isPolylineContextMenuOpen, countdown, dispatch, window.map]);
//----------------------------------
useEffect(() => {
if (map) {
window.map = map;
console.log("✅ window.map wurde gesetzt:", window.map);
}
}, [map]);
//---------------------------------------

View File

@@ -1,2 +1,2 @@
// /config/appVersion
export const APP_VERSION = "1.1.42";
export const APP_VERSION = "1.1.43";

View File

@@ -1,24 +1,10 @@
// hooks/usePolylineTooltipLayer.js
import { useEffect } from "react";
import L from "leaflet";
import { setupPolylines } from "../utils/setupPolylines";
import { setupPolylines } from "../utils/polylines/setupPolylines";
//Tooltip an mouse position anzeigen für die Linien
export const usePolylineTooltipLayer = (
map,
markers,
polylines,
setMarkers,
setPolylines,
linePositions,
lineColors,
tooltipContents,
setNewCoords,
tempMarker,
polylineVisible,
newPoint,
newCoords
) => {
//Tooltip an mouse position anzeigen für die Linien
export const usePolylineTooltipLayer = (map, markers, polylines, setMarkers, setPolylines, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, polylineVisible, newPoint, newCoords) => {
useEffect(() => {
if (!map) return;
@@ -81,4 +67,4 @@ export const usePolylineTooltipLayer = (
setMarkers(newMarkers);
setPolylines(newPolylines);
}, [map, linePositions, lineColors, tooltipContents, newPoint, newCoords, tempMarker, polylineVisible]);
};
};

View File

@@ -3,8 +3,10 @@ import { createSlice } from "@reduxjs/toolkit";
const initialState = {
isOpen: false,
position: null, // Serialisierbarer Wert { lat, lng }
forceClose: false, // Neuer State, um das Schließen zu erzwingen
position: null,
forceClose: false,
timerStart: null,
countdown: 20,
};
const polylineContextMenuSlice = createSlice({
@@ -14,19 +16,31 @@ const polylineContextMenuSlice = createSlice({
openPolylineContextMenu: (state, action) => {
state.isOpen = true;
state.position = { lat: action.payload.position.lat, lng: action.payload.position.lng };
state.forceClose = false; // Beim Öffnen zurücksetzen
state.forceClose = false;
state.timerStart = Date.now();
state.countdown = 20;
},
closePolylineContextMenu: (state) => {
state.isOpen = false;
state.position = null;
state.timerStart = null;
state.countdown = 0;
},
updateCountdown: (state) => {
if (state.timerStart) {
const elapsedTime = (Date.now() - state.timerStart) / 1000;
state.countdown = Math.max(20 - elapsedTime, 0);
}
},
forceCloseContextMenu: (state) => {
state.isOpen = false;
state.position = null;
state.forceClose = true; // Setzt Flagge, um Schließen zu signalisieren
state.forceClose = true;
state.timerStart = null;
state.countdown = 0;
},
},
});
export const { openPolylineContextMenu, closePolylineContextMenu, forceCloseContextMenu } = polylineContextMenuSlice.actions;
export const { openPolylineContextMenu, closePolylineContextMenu, updateCountdown, forceCloseContextMenu } = polylineContextMenuSlice.actions;
export default polylineContextMenuSlice.reducer;

View File

@@ -3,7 +3,7 @@ import L from "leaflet";
import "leaflet.smooth_marker_bouncing";
import { toast } from "react-toastify";
import * as config from "../config/config.js";
import { disablePolylineEvents, enablePolylineEvents } from "./setupPolylines";
import { disablePolylineEvents, enablePolylineEvents } from "./polylines/setupPolylines.js";
import { store } from "../redux/store";
import { updateLineStatus } from "../redux/slices/lineVisibilitySlice";

View File

@@ -1,7 +1,7 @@
// /utils/poiUtils.js
import circleIcon from "../components/gisPolylines/icons/CircleIcon.js";
import { saveLineData } from "./mapUtils.js";
import { redrawPolyline } from "./redrawPolyline.js";
import { redrawPolyline } from "./polylines/redrawPolyline.js";
import L from "leaflet";
import "leaflet.smooth_marker_bouncing";
import { toast } from "react-toastify";

View File

@@ -0,0 +1,29 @@
// /utils/polylines/contextMenu.js
export function closePolylineSelectionAndContextMenu(map) {
try {
if (window.selectedPolyline) {
window.selectedPolyline.setStyle({ weight: 3 });
window.selectedPolyline = null;
}
if (map?.contextmenu?.hide) {
map.contextmenu.hide();
}
} catch (error) {
console.error("Fehler beim Schließen des Kontextmenüs:", error);
}
localStorage.removeItem("contextMenuCountdown");
localStorage.removeItem("contextMenuExpired");
}
export function monitorContextMenu(map) {
function checkAndClose() {
if (localStorage.getItem("contextMenuExpired") === "true") {
closePolylineSelectionAndContextMenu(map);
localStorage.removeItem("contextMenuExpired");
}
setTimeout(checkAndClose, 1000);
}
checkAndClose();
}

View File

@@ -0,0 +1,19 @@
// /utils/polylines/eventHandlers.js
export function enablePolylineEvents(polylines, lineColors) {
if (!polylines || polylines.length === 0) {
console.warn("Keine Polylinien vorhanden oder polylines ist undefined.");
return;
}
polylines.forEach((polyline) => {
polyline.on("mouseover", () => polyline.setStyle({ weight: 14 }));
polyline.on("mouseout", () => polyline.setStyle({ weight: 3 }));
});
}
export function disablePolylineEvents(polylines) {
polylines.forEach((polyline) => {
polyline.off("mouseover");
polyline.off("mouseout");
});
}

View File

@@ -0,0 +1,21 @@
// utils/polylines/monitorContextMenu.js
import { closePolylineSelectionAndContextMenu } from "./contextMenu";
export 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();
}

View File

@@ -0,0 +1,17 @@
// utils/polylines/polylineSubscription.js
import { store } from "../../redux/store";
import { closePolylineContextMenu } from "../../redux/slices/polylineContextMenuSlice";
export function subscribeToPolylineContextMenu() {
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();
}
}
});
}

View File

@@ -1,109 +1,24 @@
// 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";
// utils/polylines/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 { 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();
}
}
});
import { polylineLayerVisibleState } from "../../redux/slices/polylineLayerVisibleSlice";
import { store } from "../../redux/store"; // Importiere den Store
import { openAddPoiOnPolylineModal } from "../../redux/slices/addPoiOnPolylineSlice";
import { openPolylineContextMenu, closePolylineContextMenu } from "../../redux/slices/polylineContextMenuSlice";
import { enablePolylineEvents, disablePolylineEvents } from "./eventHandlers";
import { closePolylineSelectionAndContextMenu } from "./contextMenu";
import { monitorContextMenu } from "./monitorContextMenu";
import { subscribeToPolylineContextMenu } from "./polylineSubscription";
import { forceCloseContextMenu } from "../../redux/slices/polylineContextMenuSlice";
//--------------------------------------------
export const setupPolylines = (map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter, polylineVisible) => {
@@ -385,73 +300,37 @@ export const setupPolylines = (map, linePositions, lineColors, tooltipContents,
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);
});
*/
console.log("🚀 Maus hat die Polyline verlassen - Warten auf Klick außerhalb des Menüs.");
// 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(() => {
document.addEventListener("click", function handleOutsideClick(event) {
if (!event.target.closest(".leaflet-contextmenu")) {
console.log("🛑 Klick außerhalb des Kontextmenüs erkannt - Schließe Menü.");
store.dispatch(closePolylineContextMenu());
if (map.contextmenu) {
map.contextmenu.hide();
store.dispatch(forceCloseContextMenu());
if (window.map?.contextmenu) {
window.map.contextmenu.hide();
}
}, 17000);
}, 50);
document.removeEventListener("click", handleOutsideClick);
}
});
});
polyline.on("contextmenu", (e) => {
store.dispatch(
openPolylineContextMenu({
position: { lat: e.latlng.lat, lng: e.latlng.lng },
polylineId: polyline.options.idLD,
})
);
});
polylines.push(polyline);

View File

@@ -7,9 +7,9 @@ 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 { redrawPolyline } from "./polylines/redrawPolyline";
import { openInNewTab } from "../utils/openInNewTab";
import { disablePolylineEvents, enablePolylineEvents } from "./setupPolylines"; // Importiere die Funktionen
import { disablePolylineEvents, enablePolylineEvents } from "./polylines/setupPolylines"; // Importiere die Funktionen
export const setupPOIs = async (
map,