first commit

This commit is contained in:
ISA
2024-04-15 10:37:53 +02:00
commit afee410333
736 changed files with 110561 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
//components/Kartenkomponente.js
import React, { useState, useEffect } from 'react';
import { MapContainer, TileLayer, Marker, Popup } from 'react-leaflet';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import dynamic from 'next/dynamic';
// Dynamischer Import mit SSR deaktiviert
const KartenKomponenteOhneSSR = dynamic(
() => import('../components/KartenKomponente'),
{ ssr: false }
);
const KartenKomponente = ({ locations, onAddLocation, onLocationUpdate }) => {
const [isOnline, setIsOnline] = useState(true); // Standardwert als fallback
const [aktuelleSchicht, setAktuelleSchicht] = useState({
url: "https://tile.openstreetmap.org/{z}/{x}/{y}.png", // Standardwert
options: {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
minZoom: 7,
maxZoom: 19,
crossOrigin: true,
},
});
useEffect(() => {
// Setzt den Zustand, basierend darauf, ob das Fensterobjekt existiert (Client-Seite)
if (typeof window !== "undefined") {
setIsOnline(navigator.onLine);
setAktuelleSchicht({
url: navigator.onLine ? "https://tile.openstreetmap.org/{z}/{x}/{y}.png" : "/mapTiles/{z}/{x}/{y}.png",
options: {
minZoom: 7,
maxZoom: navigator.onLine ? 19 : 14,
crossOrigin: true,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
},
});
const handleOnlineStatus = () => setIsOnline(navigator.onLine);
window.addEventListener("online", handleOnlineStatus);
window.addEventListener("offline", handleOnlineStatus);
return () => {
window.removeEventListener("online", handleOnlineStatus);
window.removeEventListener("offline", handleOnlineStatus);
};
}
}, []);
useEffect(() => {
setAktuelleSchicht({
url: isOnline ? "https://tile.openstreetmap.org/{z}/{x}/{y}.png" : "/mapTiles/{z}/{x}/{y}.png",
options: {
minZoom: 7,
maxZoom: isOnline ? 19 : 14,
crossOrigin: true,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
},
});
}, [isOnline]);
// Funktion, um auf Klick ein Popup für das Hinzufügen neuer Standorte zu zeigen
const addMarker = (e) => {
// Hier könnte eine Logik stehen, um ein Formular-Modal oder Popup zu öffnen, um die Daten für den neuen Standort zu sammeln
const newLocation = { lat: e.latlng.lat, lng: e.latlng.lng }; // Beispiel für neue Standortdaten
onAddLocation(newLocation); // Rufe die übergebene onAddLocation-Funktion mit den neuen Standortdaten auf
};
return (
<MapContainer center={[51.505, -0.09]} zoom={13} style={{ height: "100vh", width: "100%" }} whenCreated={map => map.on('click', addMarker)}>
<TileLayer url={aktuelleSchicht.url} {...aktuelleSchicht.options} />
{locations.map((location, index) => (
<Marker
key={index}
position={[location.lat, location.lng]}
draggable={true}
eventHandlers={{
dragend: (e) => {
const newLat = e.target.getLatLng().lat;
const newLng = e.target.getLatLng().lng;
onLocationUpdate(location.id, newLat, newLng); // Aktualisiere die Position des Standorts, nachdem der Marker verschoben wurde
},
}}
>
<Popup>{location.name}</Popup>
</Marker>
))}
</MapContainer>
);
};
export default KartenKomponente;

View File

@@ -0,0 +1,349 @@
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 osm = 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) },
{ text: "Rauszoomen", callback: (e) => zoomOut(e) },
{
text: "Hier zentrieren",
callback: (e) => centerMap(e, osm),
},
"-", // 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
? "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
: "../TileMap/mapTiles/{z}/{x}/{y}.png",
{
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
minZoom: 7,
maxZoom: 19,
}
);
tileLayer.addTo(osm);
setMap(osm);
// Cleanup function
return () => {
osm.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
? "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
: "../TileMap/mapTiles/{z}/{x}/{y}.png",
{
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 in zoomIn.");
return;
}
map.flyTo(e.latlng, 12);
};
const zoomOut = (e) => {
if (!map) {
console.error("Karte ist noch nicht initialisiert in zoomOut.");
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;

View File

@@ -0,0 +1,511 @@
// ./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 © <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]);
// 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 © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> 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:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> 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 `<b>${location.description || "Unbekannt"}</b><br>Type: ${
location.idPoiTyp || "N/A"
}<br>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 = `
<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;

View File

@@ -0,0 +1,309 @@
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;

View File

@@ -0,0 +1,47 @@
import React, { useEffect, useRef, useState } from "react";
import L from "leaflet";
import "leaflet/dist/leaflet.css";
const MapComponent = () => {
const mapRef = useRef(null);
const [map, setMap] = useState(null);
useEffect(() => {
if (mapRef.current && !map) {
const initialMap = L.map(mapRef.current, {
center: [53.111111, 8.4625],
zoom: 10,
});
initialMap.on("contextmenu", (event) => {
L.popup()
.setLatLng(event.latlng)
.setContent(
'<p>Right-click menu<br/><button onclick="zoomIn()">Zoom in</button></p>'
)
.openOn(initialMap);
});
window.zoomIn = () => {
initialMap.zoomIn();
};
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(initialMap);
setMap(initialMap);
}
}, [mapRef, map]);
return (
<div
id="map"
ref={mapRef}
style={{ height: "100vh", width: "100vw", overflow: "hidden" }}
></div>
);
};
export default MapComponent;