Files
nodeMap/components/MapComponent.backup2.js
2024-04-15 10:37:53 +02:00

310 lines
9.6 KiB
JavaScript

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 mapRef = useRef(null);
const [online, setOnline] = useState(navigator.onLine);
const offlineTileLayer = "../TileMap/mapTiles/{z}/{x}/{y}.png";
const onlineTileLayer = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
// Funktionen zur Überwachung der Internetverbindung
const checkInternet = () => {
console.log("Checking internet connectivity...");
fetch("https://tile.openstreetmap.org/1/1/1.png", { method: "HEAD" })
.then(response => setOnline(response.ok))
.catch(() => setOnline(false));
};
// Initialize map
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: showAddStationPopup },
{ text: "Station öffnen (Tab)", icon: "img/screen_new.png", callback: newLink },
{ text: "Station öffnen", icon: "img/screen_same.png", callback: sameLink },
"-", // Divider
{ text: "Reinzoomen", callback: (e) => zoomIn(e, initializedMap) },
{ text: "Rauszoomen", callback: (e) => zoomOut(e, initializedMap) },
{ text: "Hier zentrieren", callback: (e) => centerMap(e, initializedMap) },
"-", // Divider
{ text: "Koordinaten", icon: "img/not_listed_location.png", callback: showCoordinates },
{ text: "Get Data to Console", icon: "img/not_listed_location.png", callback: showData }
]
});
// Adding initial tile layer
const tileLayer = L.tileLayer(online ? onlineTileLayer : offlineTileLayer, {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
minZoom: 7,
maxZoom: 19
});
tileLayer.addTo(initializedMap);
setMap(initializedMap);
// Cleanup function
return () => {
initializedMap.remove();
};
}
}, [mapRef, online]); // React only on online changes for initialization
// Handle online/offline status
useEffect(() => {
window.addEventListener("online", checkInternet);
window.addEventListener("offline", checkInternet);
return () => {
window.removeEventListener("online", checkInternet);
window.removeEventListener("offline", checkInternet);
};
}, []);
// Update map layers based on online status
useEffect(() => {
if (map) {
const newLayer = L.tileLayer(online ? onlineTileLayer : offlineTileLayer, {
minZoom: 7,
maxZoom: online ? 19 : 14,
attribution: 'Map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
});
map.eachLayer(layer => {
if (layer instanceof L.TileLayer) {
map.removeLayer(layer);
}
});
newLayer.addTo(map);
}
}, [online, map]);
// Marker handling
useEffect(() => {
// Remove old markers
if (map) {
map.eachLayer(layer => {
if (layer instanceof L.Marker) {
map.removeLayer(layer);
}
});
// Add new markers
locations.forEach(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
});
marker.bindPopup(`<b>${location.description || "Unbekannt"}</b><br>Type: ${location.idPoiTyp || "N/A"}<br>Lat: ${latitude.toFixed(5)}, Lng: ${longitude.toFixed(5)}`);
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);
});
});
marker.addTo(map);
});
}
}, [map, locations, onLocationUpdate]);
//------------------------------------------
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
}
}
//----------------------------------
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);
};
//-----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, map.getZoom() + 1);
};
const zoomOut = (e) => {
if (!map) {
console.error("Karte ist noch nicht initialisiert.");
return;
}
// Annahme: Du willst beim Rauszoomen die aktuelle Position halten
// und nur den Zoom-Level ändern. Hier reduzieren wir den Zoom-Level um 1.
const currentZoom = map.getZoom();
map.flyTo(e.latlng, map.getZoom() - 1);
};
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------------
const showAddStationPopup = (e, map) => {
const popupContent = `
<form id="addStationForm" class="m-0 p-2 w-full">
<div class="flex items-center mb-4">
<label for="name" class="block mr-2 flex-none">Name:</label>
<input
type="text"
id="name"
name="name"
placeholder="Name der Station"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="type" class="block mr-3 flex-none">Type:</label>
<input
type="text"
id="type"
name="type"
placeholder="Typ der Station"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="lat" class="block mr-2 flex-none">Breitengrad:</label>
<input
type="text"
id="lat"
name="lat"
value="${e.latlng.lat.toFixed(5)}"
readonly
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="lng" class="block mr-2 flex-none">Längengrad:</label>
<input
type="text"
id="lng"
name="lng"
value="${e.latlng.lng.toFixed(5)}"
readonly
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<button
type="submit"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"
>
Station hinzufügen
</button>
</form>
`;
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 <div id="map" ref={mapRef} className="h-screen"></div>;
};
export default MapComponent;