Card in z-index=50 (Dropdown menu) und map z-index=0 mit Tailwind
This commit is contained in:
95
components/DataSheet.js
Normal file
95
components/DataSheet.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
|
function DataSheet() {
|
||||||
|
const stationListing = [
|
||||||
|
{ id: 1, name: "Ammersricht BZR (FGN)" },
|
||||||
|
{ id: 2, name: "Bad-Bentheim" },
|
||||||
|
{ id: 3, name: "Gevelsberg" },
|
||||||
|
{ id: 4, name: "Köln" },
|
||||||
|
{ id: 5, name: "Olfen-Selm" },
|
||||||
|
{ id: 6, name: "Plettenberg" },
|
||||||
|
{ id: 7, name: "Renzenhof (RG)" },
|
||||||
|
{ id: 8, name: "Schlüchtern II" },
|
||||||
|
{ id: 9, name: "Wuppertal" },
|
||||||
|
// Füge hier weitere Stationen hinzu, falls nötig
|
||||||
|
];
|
||||||
|
|
||||||
|
// Initialisiere den Zustand mit allen Stationen als nicht gecheckt (false)
|
||||||
|
const [checkedStations, setCheckedStations] = useState(
|
||||||
|
stationListing.reduce((acc, station) => {
|
||||||
|
acc[station.id] = false;
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleCheckboxChange = (id) => {
|
||||||
|
setCheckedStations((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[id]: !prev[id],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStationChange = (event) => {
|
||||||
|
console.log("Station selected:", event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resetView = () => {
|
||||||
|
console.log("View has been reset");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
id="mainDataSheet"
|
||||||
|
className="absolute top-12 right-3 w-1/6 min-w-[300px] z-10 bg-gray-100 border border-gray-300"
|
||||||
|
>
|
||||||
|
<div className="bg-white shadow rounded-lg overflow-hidden">
|
||||||
|
<div className="bg-gray-200 border-b border-gray-300 p-3">
|
||||||
|
<form>
|
||||||
|
<select
|
||||||
|
onChange={handleStationChange}
|
||||||
|
id="stationListing"
|
||||||
|
className="w-full border-none p-2 rounded"
|
||||||
|
>
|
||||||
|
<option>Station wählen</option>
|
||||||
|
{stationListing.map((station) => (
|
||||||
|
<option key={station.id} value={station.id}>
|
||||||
|
{station.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
<div className="text-right">
|
||||||
|
<button onClick={resetView} className="p-1 focus:outline-none">
|
||||||
|
<i
|
||||||
|
className="fi-arrows-out text-gray-800 text-lg"
|
||||||
|
title="Ansicht zurücksetzen"
|
||||||
|
></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col p-4 gap-2">
|
||||||
|
{stationListing.map((station) => (
|
||||||
|
<div key={station.id} className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={`box-${station.id}`}
|
||||||
|
className="accent-blue-500 checked:bg-blue-500"
|
||||||
|
checked={checkedStations[station.id]}
|
||||||
|
onChange={() => handleCheckboxChange(station.id)}
|
||||||
|
// Wenn du möchtest, dass die Checkboxen nicht veränderbar sind, entferne den onChange-Handler und setze `readOnly`
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor={`box-${station.id}`}
|
||||||
|
className="text-sm font-bold ml-2"
|
||||||
|
>
|
||||||
|
{station.name}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DataSheet;
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
//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: '© <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: '© <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: '© <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;
|
|
||||||
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
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:
|
|
||||||
'© <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) => {
|
|
||||||
//popupContent Station hinzufügen
|
|
||||||
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;
|
|
||||||
@@ -1,511 +0,0 @@
|
|||||||
// ./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:
|
|
||||||
'© <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;
|
|
||||||
@@ -1,309 +0,0 @@
|
|||||||
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: '© <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;
|
|
||||||
@@ -10,6 +10,7 @@ import "leaflet.smooth_marker_bouncing";
|
|||||||
//import { OverlappingMarkerSpiderfier } from "../lib/OverlappingMarkerSpiderfier.js";
|
//import { OverlappingMarkerSpiderfier } from "../lib/OverlappingMarkerSpiderfier.js";
|
||||||
//import { OverlappingMarkerSpiderfier } from "../public/js/OverlappingMarkerSpiderfier.js";
|
//import { OverlappingMarkerSpiderfier } from "../public/js/OverlappingMarkerSpiderfier.js";
|
||||||
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet";
|
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet";
|
||||||
|
import DataSheet from "../components/DataSheet";
|
||||||
|
|
||||||
const MapComponent = ({ locations, onLocationUpdate }) => {
|
const MapComponent = ({ locations, onLocationUpdate }) => {
|
||||||
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
|
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
|
||||||
@@ -635,17 +636,77 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
|
|||||||
${station.Location_Short} (${station.Location_Name})<br>
|
${station.Location_Short} (${station.Location_Name})<br>
|
||||||
${statusInfo}<br>
|
${statusInfo}<br>
|
||||||
`);
|
`);
|
||||||
|
let LocID = station.IdLocation;
|
||||||
|
marker
|
||||||
|
.bindTooltip(
|
||||||
|
`<div class="bg-white text-black p-2 border border-gray-300 rounded shadow">${LocID}</div>`,
|
||||||
|
{
|
||||||
|
permanent: true,
|
||||||
|
direction: "right",
|
||||||
|
opacity: 0,
|
||||||
|
offset: L.point({ x: 10, y: 0 }),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.addTo(GMA);
|
||||||
});
|
});
|
||||||
}, [map, oms, GisStationsStaticDistrict, GisStationsStatusDistrict]);
|
}, [map, oms, GisStationsStaticDistrict, GisStationsStatusDistrict]);
|
||||||
|
|
||||||
|
//------------------------------------------
|
||||||
|
let uniqueIdLDsData = [];
|
||||||
|
let Tooltip = [];
|
||||||
|
|
||||||
|
for (let index = 0; index < uniqueIdLDsData.length; index++) {
|
||||||
|
let element = uniqueIdLDsData[index].split(",");
|
||||||
|
let lat = element[0];
|
||||||
|
let lng = element[1];
|
||||||
|
let ID = element[2];
|
||||||
|
let IdLD = element[3];
|
||||||
|
let LocID = element[4];
|
||||||
|
|
||||||
|
Tooltip[LocID] = L.marker([lat, lng], { icon: invisibleMarker })
|
||||||
|
.bindTooltip(
|
||||||
|
'<div id="tip-' +
|
||||||
|
LocID +
|
||||||
|
'">' +
|
||||||
|
'<div id="areaname' +
|
||||||
|
LocID +
|
||||||
|
'" style="font-weight:700;font-size:0.9rem">---</div>' +
|
||||||
|
'<div id="value1-' +
|
||||||
|
LocID +
|
||||||
|
'" style="font-weight:700;color:blue">---</div>' +
|
||||||
|
'<div id="value2-' +
|
||||||
|
LocID +
|
||||||
|
'" style="font-weight:700;color:red">---</div>' +
|
||||||
|
'<div id="value3-' +
|
||||||
|
LocID +
|
||||||
|
'" style="font-weight:700;color:#ECC5C0">---</div>' +
|
||||||
|
'<div id="value4-' +
|
||||||
|
LocID +
|
||||||
|
'" style="font-weight:700;color:green">---</div>' +
|
||||||
|
"</div>",
|
||||||
|
{
|
||||||
|
permanent: true,
|
||||||
|
direction: "right",
|
||||||
|
opacity: 0,
|
||||||
|
offset: L.point({ x: 10, y: 0 }),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.openTooltip()
|
||||||
|
.addTo(GMA);
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------
|
//------------------------------------------
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<DataSheet className="z-50" />
|
||||||
<div
|
<div
|
||||||
id="map"
|
id="map"
|
||||||
ref={mapRef}
|
ref={mapRef}
|
||||||
style={{ height: "100vh", width: "100vw", overflow: "hidden" }}
|
className="z-0"
|
||||||
|
style={{ height: "100vh", width: "100vw" }}
|
||||||
></div>
|
></div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,15 @@ module.exports = {
|
|||||||
purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
|
purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
|
||||||
content: [],
|
content: [],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
zIndex: {
|
||||||
|
60: "60",
|
||||||
|
70: "70",
|
||||||
|
80: "80",
|
||||||
|
90: "90",
|
||||||
|
100: "100",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user