// ./components/MapComponent.js import { useEffect, useRef, useState } from "react"; import L from "leaflet"; import "leaflet/dist/leaflet.css"; import "leaflet-contextmenu/dist/leaflet.contextmenu.css"; import "leaflet-contextmenu"; const MapComponent = ({ locations, onAddLocation, onLocationUpdate, dataStatic, mapData, }) => { const [map, setMap] = useState(null); const [markers, setMarkers] = useState([]); const mapRef = useRef(null); const [mapLayers, setMapLayers] = useState({}); const [online, setOnline] = useState(navigator.onLine); // Define tile layers const offlineTileLayer = "../TileMap/mapTiles/{z}/{x}/{y}.png"; const onlineTileLayer = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"; // Ensure all usage of `map` checks that it is initialized useEffect(() => { if (map) { const layerUrl = online ? onlineTileLayer : offlineTileLayer; const newLayer = L.tileLayer(layerUrl, { minZoom: 7, maxZoom: online ? 19 : 14, attribution: 'Map data © OpenStreetMap contributors', }); map.eachLayer((layer) => { if (layer instanceof L.TileLayer) { map.removeLayer(layer); } }); newLayer.addTo(map); } }, [online, map]); // Funktion zum Wechseln der Kartenlayer const switchLayer = () => { console.log("Attempting to switch layers..."); if (!map) { console.log("Map is not initialized yet."); return; } const layerUrl = online ? onlineTileLayer : offlineTileLayer; console.log(`Switching layers: ${online ? "Online" : "Offline"}`); const newLayer = L.tileLayer(layerUrl, { minZoom: 7, maxZoom: online ? 19 : 14, attribution: 'Map data © OpenStreetMap contributors', }); map.eachLayer((layer) => { if (layer instanceof L.TileLayer) { console.log("Removing layer:", layer); map.removeLayer(layer); } }); newLayer.addTo(map); console.log("Layer added to map."); }; // Online-/Offline-Status überwachen useEffect(() => { // Funktion zur Überprüfung der Internetverbindung const checkInternet = () => { console.log("Checking internet connectivity..."); fetch("https://tile.openstreetmap.org/1/1/1.png", { method: "HEAD" }) .then((response) => { const newOnlineStatus = response.ok; console.log( `Internet status checked: ${newOnlineStatus ? "Online" : "Offline"}` ); setOnline(newOnlineStatus); }) .catch((error) => { console.log("Error checking internet status:", error.message); setOnline(false); }); }; window.addEventListener("online", checkInternet); window.addEventListener("offline", checkInternet); return () => { window.removeEventListener("online", checkInternet); window.removeEventListener("offline", checkInternet); }; }, []); const centerMap = (e) => { if (!map) { console.error("Die Karte wurde noch nicht initialisiert."); return; } if (!e || !e.latlng) { console.error("Fehlerhafte Event-Daten: ", e); return; } console.log("Zentrierung auf: ", e.latlng); map.panTo(e.latlng); }; // Karte nur einmal initialisieren useEffect(() => { if (mapRef.current && !map) { console.log("Initializing map..."); const initializedMap = L.map(mapRef.current, { center: [53.111111, 8.4625], zoom: 10, contextmenu: true, contextmenuWidth: 140, contextmenuItems: [ { text: "Station hinzufügen", callback: (e) => showAddStationPopup(e, initializedMap), }, { text: "Station öffnen (Tab)", icon: "img/screen_new.png", callback: newLink, }, { text: "Station öffnen", icon: "img/screen_same.png", callback: sameLink, }, "-", { text: "Reinzoomen", icon: "img/zoom_in.png", callback: zoomIn, }, { text: "Rauszoomen", icon: "img/zoom_out.png", callback: zoomOut, }, { text: "Hier zentrieren", icon: "img/center_focus.png", callback: centerMap, }, "-", { text: "Koordinaten", icon: "img/not_listed_location.png", callback: showCoordinates, }, { text: "Get Data to Console", icon: "img/not_listed_location.png", callback: showData, }, { text: "Show Talas", icon: "img/not_listed_location.png", callback: showTalas, }, { text: "Hide Talas", icon: "img/not_listed_location.png", callback: hideTalas, }, { text: "Show GMA", icon: "img/not_listed_location.png", callback: showGSM, }, { text: "Hide GMA", icon: "img/not_listed_location.png", callback: hideGSM, }, ], }); const tileLayer = L.tileLayer( online ? onlineTileLayer : offlineTileLayer, { attribution: '© OpenStreetMap contributors', minZoom: 7, maxZoom: 19, } ); tileLayer.addTo(initializedMap); setMap(initializedMap); return () => initializedMap.remove(); // Cleanup } }, [mapRef, online]); // Abhängigkeit von online hinzugefügt // Layer wechseln, wenn Online-Status sich ändert useEffect(() => { switchLayer(online); }, [online, map]); // Erstellen von Refs für jede LayerGroup const TALAS = useRef(null); const ECI = useRef(null); const ULAF = useRef(null); const GSMModem = useRef(null); const CiscoRouter = useRef(null); const WAGO = useRef(null); const Siemens = useRef(null); const OTDR = useRef(null); const WDM = useRef(null); const GMA = useRef(null); const Sonstige = useRef(null); const TALASICL = useRef(null); const flyToStation = (stationValue) => { let x = 51.41321407879154; let y = 7.739617925303934; let zoom = 14; const stationData = dataStatic.find( (station) => station.Area_Name === stationValue ); if (stationData) { x = stationData.X; y = stationData.Y; } else { zoom = 8; // default zoom if not found } map.flyTo([x, y], zoom); mapData.forEach((datum) => { const loc = new L.LatLng(datum.lat, datum.lon); const marker = new L.Marker(loc, { title: datum.d }); marker.bindPopup(datum.d); map.addLayer(marker); }); }; //-----Kontextmenu---------------- const newLink = (e) => { try { if (!e.relatedTarget || !e.relatedTarget.options) { throw new Error("relatedTarget or options not defined"); } alert("Neues Fenster: " + e.relatedTarget.options.test); window .open(`../devices/${e.relatedTarget.options.test}`, "_blank") .focus(); } catch (error) { console.error("Failed in newLink function:", error); } }; const sameLink = (e) => { alert(e.relatedTarget.options.test); window .open("../devices/" + e.relatedTarget.options.test, "_parent") .focus(); }; const zoomIn = (e) => { if (!map) { console.error("Karte ist noch nicht initialisiert."); return; } map.flyTo(e.latlng, 12); }; const zoomOut = (e) => { fly(); }; const showCoordinates = (e) => { alert("Breitengrad: " + e.latlng.lat + "\nLängengrad: " + e.latlng.lng); }; const showData = (e) => { console.log(e); }; const showTalas = (e) => { map.addLayer(TALAS); loadData(); }; const hideTalas = (e) => { map.removeLayer(TALAS); loadData(); }; const showGSM = (e) => { map.addLayer(GMA); loadData(); }; const hideGSM = (e) => { map.removeLayer(GMA); loadData(); }; //-----Kontextmenu----ende------------ function parsePoint(pointString) { const match = pointString.match( /POINT\s*\((\d+(\.\d+)?)\s+(\d+(\.\d+)?)\)/ ); if (match) { return { longitude: parseFloat(match[1]), latitude: parseFloat(match[3]), // Achtung: Index 3 für die zweite Koordinate, wegen der Gruppe (\.\d+)? }; } else { // Handle the error or return a default/fallback value console.error("Invalid POINT format:", pointString); return null; // Oder eine sinnvolle Standardantwort } } // Beispiel einer Funktion zum Aktualisieren der Position in der Datenbank const updateLocationInDatabase = async (id, newLatitude, newLongitude) => { const response = await fetch("/api/updateLocation", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id, latitude: newLatitude, longitude: newLongitude, }), }); if (response.ok) { console.log("Position erfolgreich aktualisiert"); //schreib die neue Kooridnaten in die Console console.log("Latitude: " + newLatitude); console.log("Longitude: " + newLongitude); console.log("ID: " + id); console.log("Response: " + response); //akuellisiere die Position in der Datenbank mit den neuen Koordinaten mit updateLocation mit SQL Anweisung UPDATE } else { console.error("Fehler beim Aktualisieren der Position"); } }; //------------------------------------- //------------------- loadData ---------------// /* const loadData = () => { if (!dataStatic || !map) return; console.log("Initialisiere Marker"); dataStatic.forEach(gisStatic => { if (filterSystems.includes(gisStatic.System)) { const markerOptions = { icon: getIcon(gisStatic.Icon), test: gisStatic.Link, device: gisStatic.Device, system: gisStatic.System, IdLD: gisStatic.IdLD, IdLocation: gisStatic.IdLocation, contextmenu: true, }; const marker = L.marker([gisStatic.X, gisStatic.Y], markerOptions); marker.addTo(map); // Speichern der Markerreferenz in einem Ref-Objekt markersRef.current[gisStatic.IdLD] = marker; // Popup und Event-Listener hinzufügen marker.bindPopup(createPopupContent(gisStatic)); marker.on('click', () => { console.log('Marker clicked:', gisStatic.IdLD); }); } }); }; useEffect(() => { loadData(); }, [dataStatic, filterSystems, map]); // Abhängigkeiten, die den Neuladevorgang auslösen */ //------------------- loadData end---------------// useEffect(() => { // Entferne alte Marker markers.forEach((marker) => map.removeLayer(marker)); if (map) { const newMarkers = locations.map((location) => { const { latitude, longitude } = parsePoint(location.position); const marker = L.marker([latitude, longitude], { icon: L.icon({ iconUrl: "/location.svg", iconSize: [34, 34], iconAnchor: [17, 34], popupAnchor: [0, -34], }), draggable: true, id: location.idPoi, }); // Erstellt einen Popup-Inhalt basierend auf den aktuellen Marker-Daten const createPopupContent = () => { return `${location.description || "Unbekannt"}
Type: ${ location.idPoiTyp || "N/A" }
Lat: ${latitude.toFixed(5)}, Lng: ${longitude.toFixed(5)}`; }; // Bindet das Popup mit dem initialen Inhalt marker.bindPopup(createPopupContent()); marker.on("dragend", function (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); }); }); // Fügt den Marker der Karte hinzu marker.addTo(map); return () => { if (map) { map.remove(); } }; return marker; }); // Aktualisiere die Marker-Liste im State setMarkers(newMarkers); } }, [map, locations, onLocationUpdate]); const showAddStationPopup = (e, map) => { const popupContent = `
`; L.popup().setLatLng(e.latlng).setContent(popupContent).openOn(map); // Verzögerung hinzufügen, um sicherzustellen, dass das Formular im DOM verfügbar ist setTimeout(() => { const form = document.getElementById("addStationForm"); if (form) { form.addEventListener("submit", async (event) => { event.preventDefault(); const name = event.target.name.value; const type = event.target.type.value; const lat = event.target.lat.value; const lng = event.target.lng.value; // Hier wird `onAddLocation` mit den Werten aufgerufen, die aus dem Formular gesammelt wurden await onAddLocation(name, type, lat, lng); map.closePopup(); }); } }, 10); }; return
; }; export default MapComponent;