Gängige Praxis: *Slice.js Verwendung: Wenn du Redux Toolkit und createSlice nutzt, ist der Postfix Slice gängiger. Begründung: createSlice ist ein Begriff aus Redux Toolkit. Der Name vermittelt, dass die Datei nicht nur den Reducer enthält, sondern auch Aktionen und den initialen Zustand. Häufig in modernen Projekten verwendet.
866 lines
33 KiB
JavaScript
866 lines
33 KiB
JavaScript
// components/MapComponent.js
|
|
import React, { useEffect, useRef, useState, useCallback } from "react";
|
|
import L from "leaflet";
|
|
import "leaflet/dist/leaflet.css";
|
|
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
|
|
import "leaflet-contextmenu";
|
|
import * as config from "../config/config.js";
|
|
import "leaflet.smooth_marker_bouncing";
|
|
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet";
|
|
import DataSheet from "./DataSheet.js";
|
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from "recoil";
|
|
import { gisStationsStaticDistrictState } from "../redux/slices/gisStationsStaticDistrictSlice";
|
|
import { gisSystemStaticState } from "../redux/slices/gisSystemStaticSlice";
|
|
import { mapLayersState } from "../redux/slices/mapLayersSlice";
|
|
import { selectedAreaState } from "../redux/slices/selectedAreaSlice";
|
|
import { zoomTriggerState } from "../redux/slices/zoomTriggerSlice.js";
|
|
import AddPoiModalWindow from "./pois/AddPoiModalWindow.js";
|
|
import { poiReadFromDbTriggerAtom } from "../redux/slices/poiReadFromDbTriggerSlice";
|
|
import { InformationCircleIcon } from "@heroicons/react/20/solid"; // oder 'outline'
|
|
import PoiUpdateModal from "./pois/PoiUpdateModal.js";
|
|
import { selectedPoiState } from "../redux/slices/selectedPoiSlice.js";
|
|
import { currentPoiState } from "../redux/slices/currentPoiSlice.js";
|
|
import { ToastContainer, toast } from "react-toastify";
|
|
import "react-toastify/dist/ReactToastify.css";
|
|
import { mapIdState, userIdState } from "../redux/slices/urlParameterSlice.js";
|
|
import { poiLayerVisibleState } from "../redux/slices/poiLayerVisibleStateSlice.js";
|
|
import plusRoundIcon from "./PlusRoundIcon.js";
|
|
import { createAndSetDevices } from "../utils/createAndSetDevices.js";
|
|
import { restoreMapSettings, checkOverlappingMarkers } from "../utils/mapUtils.js";
|
|
import { fetchPoiData, fetchUserRights } from "../services/apiService.js";
|
|
import { APP_VERSION } from "../config/appVersion";
|
|
import * as layers from "../config/layers.js";
|
|
import { initializeMap } from "../utils/initializeMap.js";
|
|
import { addItemsToMapContextMenu } from "./useMapContextMenu.js";
|
|
import useGmaMarkersLayer from "../hooks/layers/useGmaMarkersLayer.js"; // Import the custom hook
|
|
import useSmsfunkmodemMarkersLayer from "../hooks/layers/useSmsfunkmodemMarkersLayer.js";
|
|
import useBereicheMarkersLayer from "../hooks/layers/useBereicheMarkersLayer.js";
|
|
import { fetchGisStationsStaticDistrict, fetchGisStationsStatusDistrict, fetchGisStationsMeasurements, fetchGisSystemStatic } from "../services/fetchData.js";
|
|
import { setupPolylines } from "../utils/setupPolylines.js";
|
|
import { setupPOIs } from "../utils/setupPOIs.js";
|
|
import VersionInfoModal from "./VersionInfoModal.js";
|
|
//--------------------------------------------
|
|
|
|
import useFetchPoiData from "../hooks/useFetchPoiData";
|
|
import usePoiTypData from "../hooks/usePoiTypData";
|
|
import useLayerVisibility from "../hooks/useLayerVisibility";
|
|
import useLineData from "../hooks/useLineData.js";
|
|
|
|
//import { useCreateAndSetDevices } from "../hooks/useCreateAndSetDevices";
|
|
import { useMapComponentState } from "../hooks/useMapComponentState";
|
|
import { polylineEventsDisabledState } from "../redux/slices/polylineEventsDisabledSlice";
|
|
import { disablePolylineEvents, enablePolylineEvents } from "../utils/setupPolylines";
|
|
import { polylineLayerVisibleState } from "../redux/slices/polylineLayerVisibleSlice";
|
|
|
|
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
|
const polylineVisible = useRecoilValue(polylineLayerVisibleState);
|
|
const [editMode, setEditMode] = useState(false); // editMode Zustand
|
|
const { deviceName, setDeviceName } = useMapComponentState();
|
|
const { poiTypData, isPoiTypLoaded } = usePoiTypData("/api/talas_v5_DB/poiTyp/readPoiTyp");
|
|
//const [deviceName, setDeviceName] = useState("");
|
|
const [locationDeviceData, setLocationDeviceData] = useState([]);
|
|
const [priorityConfig, setPriorityConfig] = useState([]);
|
|
const [menuItemAdded, setMenuItemAdded] = useState(false);
|
|
const poiLayerVisible = useRecoilValue(poiLayerVisibleState);
|
|
const [isRightsLoaded, setIsRightsLoaded] = useState(false);
|
|
const [hasRights, setHasRights] = useState(false);
|
|
const [mapId, setMapId] = useRecoilState(mapIdState);
|
|
const [userId, setUserId] = useRecoilState(userIdState);
|
|
const [AddPoiModalWindowState, setAddPoiModalWindowState] = useState(false);
|
|
const [userRights, setUserRights] = useState(null);
|
|
const setSelectedPoi = useSetRecoilState(selectedPoiState);
|
|
const [showPoiUpdateModal, setShowPoiUpdateModal] = useState(false);
|
|
const [currentPoiData, setCurrentPoiData] = useState(null);
|
|
const setCurrentPoi = useSetRecoilState(currentPoiState);
|
|
const [showVersionInfoModal, setShowVersionInfoModal] = useState(false);
|
|
const zoomTrigger = useRecoilValue(zoomTriggerState);
|
|
const [gisSystemStaticLoaded, setGisSystemStaticLoaded] = useState(false);
|
|
const [poiTypMap, setPoiTypMap] = useState(new Map());
|
|
const [showPopup, setShowPopup] = useState(false);
|
|
const poiReadTrigger = useRecoilValue(poiReadFromDbTriggerAtom);
|
|
const poiLayerRef = useRef(null); // Referenz auf die Layer-Gruppe für Datenbank-Marker
|
|
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
|
|
const [map, setMap] = useState(null); // Zustand der Karteninstanz
|
|
const [oms, setOms] = useState(null); // State für OMS-Instanz
|
|
const [GisStationsStaticDistrict, setGisStationsStaticDistrict] = useRecoilState(gisStationsStaticDistrictState);
|
|
const [GisStationsStatusDistrict, setGisStationsStatusDistrict] = useState([]); // Zustand für Statusdaten
|
|
const [GisStationsMeasurements, setGisStationsMeasurements] = useState([]); // Zustand für Messdaten
|
|
const [GisSystemStatic, setGisSystemStatic] = useRecoilState(gisSystemStaticState); // Zustand für Systemdaten
|
|
// Konstanten für die URLs
|
|
const mapGisStationsStaticDistrictUrl = config.mapGisStationsStaticDistrictUrl;
|
|
const mapGisStationsStatusDistrictUrl = config.mapGisStationsStatusDistrictUrl;
|
|
const mapGisStationsMeasurementsUrl = config.mapGisStationsMeasurementsUrl;
|
|
const mapGisSystemStaticUrl = config.mapGisSystemStaticUrl;
|
|
const webserviceGisLinesStatusUrl = config.webserviceGisLinesStatusUrl;
|
|
//console.log("priorityConfig in MapComponent1: ", priorityConfig);
|
|
|
|
const [gmaMarkers, setGmaMarkers] = useState([]); //--------------------station.System === 11 alle sind untetschiedlich Nummern
|
|
const [talasMarkers, setTalasMarkers] = useState([]);
|
|
const [eciMarkers, setEciMarkers] = useState([]);
|
|
const [gsmModemMarkers, setGsmModemMarkers] = useState([]);
|
|
const [ciscoRouterMarkers, setCiscoRouterMarkers] = useState([]);
|
|
const [wagoMarkers, setWagoMarkers] = useState([]);
|
|
const [siemensMarkers, setSiemensMarkers] = useState([]);
|
|
const [otdrMarkers, setOtdrMarkers] = useState([]);
|
|
const [wdmMarkers, setWdmMarkers] = useState([]);
|
|
const [messstellenMarkers, setMessstellenMarkers] = useState([]);
|
|
const [talasiclMarkers, setTalasiclMarkers] = useState([]);
|
|
const [dauzMarkers, setDauzMarkers] = useState([]);
|
|
const [smsfunkmodemMarkers, setSmsfunkmodemMarkers] = useState([]);
|
|
const [ulafMarkers, setUlafMarkers] = useState([]);
|
|
const [sonstigeMarkers, setSonstigeMarkers] = useState([]);
|
|
const [tkComponentsMarkers, setTkComponentsMarkers] = useState([]);
|
|
|
|
//const [lteModemMarkers, setLteModemMarkers] = useState([]);
|
|
|
|
const [lineStatusData, setLineStatusData] = useState([]);
|
|
const [linesData, setLinesData] = useState([]);
|
|
const mapLayersVisibility = useRecoilValue(mapLayersState);
|
|
const selectedArea = useRecoilValue(selectedAreaState);
|
|
const poiData = useFetchPoiData("/api/talas_v5_DB/pois/poi-icons");
|
|
const [linePositions, setLinePositions] = useState([]);
|
|
const { lineColors, tooltipContents } = useLineData(webserviceGisLinesStatusUrl, setLineStatusData);
|
|
const [polylines, setPolylines] = useState([]);
|
|
const [markers, setMarkers] = useState([]);
|
|
const closePopup = () => setShowPopup(false);
|
|
const [newPoint, setNewPoint] = useState(null);
|
|
const [newCoords, setNewCoords] = useState(null);
|
|
const [tempMarker, setTempMarker] = useState(null);
|
|
|
|
const [popupCoordinates, setPopupCoordinates] = useState({
|
|
lat: 52.52,
|
|
lng: 13.405,
|
|
});
|
|
|
|
const handleAddStation = (stationData) => {
|
|
setAddPoiModalWindowState(false);
|
|
closePopup(); // Schließt das Popup nach dem Hinzufügen
|
|
};
|
|
|
|
const openVersionInfoModal = () => {
|
|
setShowVersionInfoModal(true);
|
|
};
|
|
|
|
const closeVersionInfoModal = () => {
|
|
setShowVersionInfoModal(false);
|
|
};
|
|
|
|
const [currentZoom, setCurrentZoom] = useState(() => {
|
|
const storedZoom = localStorage.getItem("mapZoom");
|
|
return storedZoom ? parseInt(storedZoom, 10) : 12;
|
|
});
|
|
|
|
const [currentCenter, setCurrentCenter] = useState(() => {
|
|
const storedCenter = localStorage.getItem("mapCenter");
|
|
try {
|
|
return storedCenter ? JSON.parse(storedCenter) : [53.111111, 8.4625];
|
|
} catch (e) {
|
|
console.error("Error parsing stored map center:", e);
|
|
return [53.111111, 8.4625];
|
|
}
|
|
});
|
|
const [polylineEventsDisabled, setPolylineEventsDisabled] = useRecoilState(polylineEventsDisabledState); // Recoil State
|
|
|
|
//---------------------------------------------------------------
|
|
|
|
/* useEffect(() => {
|
|
fetchGisStatusStations(12, 484); // Beispielaufruf mit idMap = 10 und idUser = 484
|
|
}, []); */
|
|
|
|
useEffect(() => {
|
|
const params = new URL(window.location.href).searchParams;
|
|
setMapId(params.get("m"));
|
|
setUserId(params.get("u"));
|
|
}, [setMapId, setUserId]);
|
|
|
|
useEffect(() => {
|
|
if (map && poiLayerRef.current && isPoiTypLoaded && !menuItemAdded && isRightsLoaded) {
|
|
//console.log("Überprüfung der Berechtigung vor addItemsToMapContextMenu: ", hasRights);
|
|
addItemsToMapContextMenu(hasRights);
|
|
}
|
|
}, [
|
|
map,
|
|
poiLayerRef,
|
|
isPoiTypLoaded,
|
|
menuItemAdded, // Hinzufügen zu den Abhängigkeiten, um den Effekt korrekt zu steuern
|
|
hasRights, // Sicherstellen, dass hasRights berücksichtigt wird
|
|
isRightsLoaded, // Überprüfung, ob die Rechte geladen sind
|
|
]);
|
|
|
|
useEffect(() => {
|
|
const fetchAndSetUserRights = async () => {
|
|
const rights = await fetchUserRights();
|
|
setUserRights(rights);
|
|
setIsRightsLoaded(true);
|
|
|
|
// Sicherstellen, dass `rights` ein Array ist, bevor `.includes()` aufgerufen wird
|
|
setHasRights(localStorage.getItem("editMode") && Array.isArray(rights) && rights.includes(56));
|
|
};
|
|
|
|
fetchAndSetUserRights();
|
|
}, []);
|
|
|
|
useGmaMarkersLayer(
|
|
map,
|
|
gmaMarkers,
|
|
GisStationsMeasurements,
|
|
layers.MAP_LAYERS.GMA,
|
|
oms,
|
|
mapLayersVisibility.GMA // Übergebe die Sichtbarkeitsbedingung als Parameter
|
|
);
|
|
|
|
useSmsfunkmodemMarkersLayer(
|
|
map,
|
|
oms,
|
|
GisSystemStatic,
|
|
priorityConfig,
|
|
mapLayersVisibility.SMSFunkmodem // Sichtbarkeitsstatus aus dem State
|
|
);
|
|
|
|
useEffect(() => {
|
|
const fetchWebServiceMap = async () => {
|
|
try {
|
|
// Zähler für externe API-Aufrufe in localStorage speichern
|
|
let requestCount = localStorage.getItem("fetchWebServiceMap") || 0;
|
|
requestCount = parseInt(requestCount, 10);
|
|
|
|
const fetchOptions = {
|
|
method: "GET",
|
|
headers: {
|
|
Connection: "close", // Keep-Alive-Header hinzufügen
|
|
},
|
|
};
|
|
|
|
/*
|
|
await fetchGisStationsStaticDistrict(mapGisStationsStaticDistrictUrl, setGisStationsStaticDistrict, fetchOptions);
|
|
await fetchGisStationsStatusDistrict(mapGisStationsStatusDistrictUrl, setGisStationsStatusDistrict, fetchOptions);
|
|
await fetchGisStationsMeasurements(mapGisStationsMeasurementsUrl, setGisStationsMeasurements, fetchOptions);
|
|
await fetchGisSystemStatic(mapGisSystemStaticUrl, setGisSystemStatic, setGisSystemStaticLoaded, fetchOptions);
|
|
*/
|
|
// Fetch GIS Stations Static District
|
|
await fetchGisStationsStaticDistrict(mapGisStationsStaticDistrictUrl, setGisStationsStaticDistrict, fetchOptions);
|
|
requestCount++; // Zähler erhöhen
|
|
localStorage.setItem("fetchWebServiceMap", requestCount);
|
|
//console.log(`fetchWebServiceMap in MapComponent wurde ${requestCount} Mal aufgerufen.`);
|
|
|
|
// Fetch GIS Stations Status District
|
|
await fetchGisStationsStatusDistrict(mapGisStationsStatusDistrictUrl, setGisStationsStatusDistrict, fetchOptions);
|
|
requestCount++; // Zähler erhöhen
|
|
localStorage.setItem("fetchWebServiceMap", requestCount);
|
|
//console.log(`fetchWebServiceMap in MapComponent wurde ${requestCount} Mal aufgerufen.`);
|
|
|
|
// Fetch GIS Stations Measurements
|
|
await fetchGisStationsMeasurements(mapGisStationsMeasurementsUrl, setGisStationsMeasurements, fetchOptions);
|
|
requestCount++; // Zähler erhöhen
|
|
localStorage.setItem("fetchWebServiceMap", requestCount);
|
|
//console.log(`fetchWebServiceMap in MapComponent wurde ${requestCount} Mal aufgerufen.`);
|
|
|
|
// Fetch GIS System Static
|
|
await fetchGisSystemStatic(mapGisSystemStaticUrl, setGisSystemStatic, setGisSystemStaticLoaded, fetchOptions);
|
|
requestCount++; // Zähler erhöhen
|
|
localStorage.setItem("fetchWebServiceMap", requestCount);
|
|
//console.log(`fetchWebServiceMap in MapComponent wurde ${requestCount} Mal aufgerufen.`);
|
|
} catch (error) {
|
|
console.error("Error fetching data:", error);
|
|
}
|
|
};
|
|
|
|
fetchWebServiceMap();
|
|
}, []);
|
|
|
|
//--------------------------------------------------------
|
|
useEffect(() => {
|
|
const endpoint = "/api/talas_v5_DB/gisLines/readGisLines";
|
|
//const endpoint = "http://localhost/talas5/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=10";
|
|
fetch(endpoint)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then((data) => {
|
|
const newLinePositions = data.map((item) => {
|
|
//console.log("item.idLD", item.idLD);
|
|
//console.log("item.idModul", item.idModul);
|
|
|
|
if (item.points && Array.isArray(item.points)) {
|
|
return {
|
|
coordinates: item.points.map((point) => [point.x, point.y]),
|
|
idModul: item.idModul,
|
|
idLD: item.idLD,
|
|
};
|
|
} else {
|
|
throw new Error("Points missing or not an array");
|
|
}
|
|
});
|
|
setLinePositions(newLinePositions);
|
|
})
|
|
.catch((error) => {
|
|
console.error("Error fetching data:", error.message);
|
|
});
|
|
}, []);
|
|
//--------------------------------------------
|
|
useEffect(() => {
|
|
const fetchPoiTypData = async () => {
|
|
try {
|
|
const response = await fetch("/api/talas_v5_DB/poiTyp/readPoiTyp");
|
|
const data = await response.json();
|
|
const map = new Map();
|
|
data.forEach((item) => map.set(item.idPoiTyp, item.name));
|
|
setPoiTypMap(map);
|
|
} catch (error) {
|
|
console.error("Fehler beim Abrufen der poiTyp-Daten-1:", error);
|
|
}
|
|
};
|
|
//--------------------------------------------
|
|
const fetchPoiData = async () => {
|
|
try {
|
|
const response = await fetch("/api/talas_v5_DB/pois/poi-icons");
|
|
if (!response.ok) {
|
|
throw new Error("Network response was not ok");
|
|
}
|
|
const data = await response.json();
|
|
} catch (error) {
|
|
console.error("Fehler beim Abrufen der poiData-2:", error);
|
|
}
|
|
};
|
|
//--------------------------------------------
|
|
|
|
fetchPoiTypData();
|
|
fetchPoiData();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
const dbLayer = new L.LayerGroup().addTo(map); // Define dbLayer here
|
|
|
|
return () => {
|
|
dbLayer.remove();
|
|
};
|
|
}
|
|
}, [map]);
|
|
|
|
useEffect(() => {
|
|
if (map && !poiLayerRef.current) {
|
|
poiLayerRef.current = new L.LayerGroup().addTo(map);
|
|
}
|
|
|
|
return () => {
|
|
if (map && poiLayerRef.current) {
|
|
map.removeLayer(poiLayerRef.current);
|
|
poiLayerRef.current = new L.LayerGroup().addTo(map);
|
|
}
|
|
locations.forEach((location) => {});
|
|
};
|
|
//console.log("trigger in MapComponent.js:", poiReadTrigger);
|
|
}, [map, locations, poiReadTrigger]);
|
|
|
|
//--------------------------------------------
|
|
useEffect(() => {
|
|
if (poiData.length === 0) return;
|
|
|
|
setupPOIs(map, locations, poiData, poiTypMap, userRights, poiLayerRef, setSelectedPoi, setLocationDeviceData, setDeviceName, setCurrentPoi, poiLayerVisible, fetchPoiData, toast, setShowPoiUpdateModal, setCurrentPoiData, deviceName);
|
|
}, [map, locations, onLocationUpdate, poiReadTrigger, isPoiTypLoaded, userRights, poiLayerVisible, poiData, poiTypMap]);
|
|
|
|
//---------------------------------------------
|
|
//console.log("priorityConfig in MapComponent2: ", priorityConfig);
|
|
useEffect(() => {
|
|
if (gisSystemStaticLoaded && map) {
|
|
}
|
|
}, [gisSystemStaticLoaded, map, GisSystemStatic, priorityConfig]);
|
|
|
|
//useCreateAndSetDevices(1, talasMarkers, GisSystemStatic, priorityConfig);
|
|
|
|
useLayerVisibility(map, talasMarkers, mapLayersVisibility, "TALAS", oms);
|
|
useLayerVisibility(map, eciMarkers, mapLayersVisibility, "ECI", oms);
|
|
useLayerVisibility(map, gsmModemMarkers, mapLayersVisibility, "GSMModem", oms);
|
|
useLayerVisibility(map, ciscoRouterMarkers, mapLayersVisibility, "CiscoRouter", oms);
|
|
//useLayerVisibility(map, lteModemMarkers, mapLayersVisibility, "LTEModem", oms);
|
|
|
|
useLayerVisibility(map, wagoMarkers, mapLayersVisibility, "WAGO", oms);
|
|
useLayerVisibility(map, siemensMarkers, mapLayersVisibility, "Siemens", oms);
|
|
useLayerVisibility(map, otdrMarkers, mapLayersVisibility, "OTDR", oms);
|
|
useLayerVisibility(map, wdmMarkers, mapLayersVisibility, "WDM", oms);
|
|
useLayerVisibility(map, gmaMarkers, mapLayersVisibility, "GMA", oms);
|
|
useLayerVisibility(map, sonstigeMarkers, mapLayersVisibility, "Sonstige", oms);
|
|
useLayerVisibility(map, tkComponentsMarkers, mapLayersVisibility, "TKKomponenten", oms);
|
|
useLayerVisibility(map, talasiclMarkers, mapLayersVisibility, "TALASICL", oms);
|
|
useLayerVisibility(map, dauzMarkers, mapLayersVisibility, "DAUZ", oms);
|
|
useLayerVisibility(map, smsfunkmodemMarkers, mapLayersVisibility, "SMSModem", oms);
|
|
useLayerVisibility(map, messstellenMarkers, mapLayersVisibility, "Messstellen", oms);
|
|
useLayerVisibility(map, ulafMarkers, mapLayersVisibility, "ULAF", oms);
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
var x = 51.41321407879154;
|
|
var y = 7.739617925303934;
|
|
var zoom = 7;
|
|
|
|
if (map && map.flyTo) {
|
|
map.flyTo([x, y], zoom);
|
|
} else {
|
|
console.error("Map object is not ready or does not have flyTo method");
|
|
}
|
|
}
|
|
}, [map, zoomTrigger]);
|
|
//--------------------------------------------
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
// Sammle alle Marker in einer einzigen Liste
|
|
const allMarkers = [
|
|
...talasMarkers,
|
|
...eciMarkers,
|
|
...gsmModemMarkers,
|
|
...ciscoRouterMarkers,
|
|
...wagoMarkers,
|
|
...siemensMarkers,
|
|
...otdrMarkers,
|
|
...wdmMarkers,
|
|
...gmaMarkers,
|
|
...messstellenMarkers,
|
|
...talasiclMarkers,
|
|
...dauzMarkers,
|
|
...smsfunkmodemMarkers,
|
|
...sonstigeMarkers,
|
|
...tkComponentsMarkers,
|
|
...ulafMarkers,
|
|
];
|
|
|
|
const editMode = localStorage.getItem("editMode") === "true"; // EditMode prüfen
|
|
|
|
if (editMode) {
|
|
// Alle Marker entfernen, wenn EditMode aktiv ist
|
|
allMarkers.forEach((marker) => {
|
|
if (map.hasLayer(marker)) {
|
|
map.removeLayer(marker);
|
|
}
|
|
});
|
|
} else {
|
|
// Marker wieder hinzufügen, falls EditMode deaktiviert ist
|
|
allMarkers.forEach((marker) => {
|
|
if (!map.hasLayer(marker)) {
|
|
marker.addTo(map);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Überprüfe überlappende Marker und füge das "Plus"-Icon hinzu
|
|
checkOverlappingMarkers(map, allMarkers, plusRoundIcon);
|
|
}
|
|
}, [
|
|
map,
|
|
talasMarkers,
|
|
eciMarkers,
|
|
gsmModemMarkers,
|
|
ciscoRouterMarkers,
|
|
wagoMarkers,
|
|
siemensMarkers,
|
|
otdrMarkers,
|
|
wdmMarkers,
|
|
gmaMarkers,
|
|
messstellenMarkers,
|
|
talasiclMarkers,
|
|
dauzMarkers,
|
|
smsfunkmodemMarkers,
|
|
sonstigeMarkers,
|
|
tkComponentsMarkers,
|
|
ulafMarkers,
|
|
]);
|
|
|
|
//--------------------------------------------
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
try {
|
|
const response1 = await fetch(webserviceGisLinesStatusUrl);
|
|
const data1 = await response1.json();
|
|
//console.log("data1.Statis", data1.Statis);
|
|
const reversedData = data1.Statis.reverse();
|
|
setLineStatusData(reversedData);
|
|
|
|
const response2 = await fetch("/api/talas_v5_DB/gisLines/readGisLines");
|
|
const data2 = await response2.json();
|
|
|
|
const colorsByModule = {};
|
|
reversedData.forEach((stat) => {
|
|
const matchingLine = data2.find((item) => item.idLD === stat.IdLD && item.idModul === stat.Modul);
|
|
if (matchingLine) {
|
|
colorsByModule[matchingLine.idModul] = stat.PrioColor;
|
|
//console.log("Übereinstimmung gefunden für: ", stat);
|
|
setLinesData(matchingLine);
|
|
}
|
|
});
|
|
//setLineColors(colorsByModule);
|
|
} catch (error) {
|
|
console.error("Error fetching data:", error);
|
|
}
|
|
};
|
|
fetchData();
|
|
}, []);
|
|
//--------------------------------------------
|
|
//Tooltip an mouse position anzeigen für die Linien
|
|
useEffect(() => {
|
|
if (!map) return;
|
|
|
|
// Entferne alte Marker und Polylinien
|
|
markers.forEach((marker) => marker.remove());
|
|
polylines.forEach((polyline) => polyline.remove());
|
|
|
|
// Setze neue Marker und Polylinien mit den aktuellen Daten
|
|
const { markers: newMarkers, polylines: newPolylines } = setupPolylines(
|
|
map,
|
|
linePositions,
|
|
lineColors,
|
|
tooltipContents,
|
|
setNewCoords,
|
|
tempMarker,
|
|
polylineVisible // polylineVisible wird jetzt korrekt übergeben
|
|
);
|
|
|
|
newPolylines.forEach((polyline, index) => {
|
|
const tooltipContent = tooltipContents[`${linePositions[index].idLD}-${linePositions[index].idModul}`] || "Standard-Tooltip-Inhalt";
|
|
|
|
polyline.bindTooltip(tooltipContent, {
|
|
permanent: false,
|
|
direction: "auto",
|
|
sticky: true,
|
|
offset: [20, 0],
|
|
pane: "tooltipPane",
|
|
});
|
|
|
|
polyline.on("mouseover", (e) => {
|
|
const tooltip = polyline.getTooltip();
|
|
if (tooltip) {
|
|
const mousePos = e.containerPoint;
|
|
const mapSize = map.getSize();
|
|
|
|
let direction = "right";
|
|
|
|
if (mousePos.x > mapSize.x - 100) {
|
|
direction = "left";
|
|
} else if (mousePos.x < 100) {
|
|
direction = "right";
|
|
}
|
|
|
|
if (mousePos.y > mapSize.y - 100) {
|
|
direction = "top";
|
|
} else if (mousePos.y < 100) {
|
|
direction = "bottom";
|
|
}
|
|
|
|
tooltip.options.direction = direction;
|
|
polyline.openTooltip(e.latlng);
|
|
}
|
|
});
|
|
|
|
polyline.on("mouseout", () => {
|
|
polyline.closeTooltip();
|
|
});
|
|
});
|
|
|
|
setMarkers(newMarkers);
|
|
setPolylines(newPolylines);
|
|
}, [map, linePositions, lineColors, tooltipContents, newPoint, newCoords, tempMarker, polylineVisible]);
|
|
|
|
//--------------------------------------------
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
restoreMapSettings(map);
|
|
}
|
|
}, [map]);
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
const handleMapMoveEnd = (event) => {
|
|
const newCenter = map.getCenter();
|
|
const newZoom = map.getZoom();
|
|
|
|
setCurrentCenter([newCenter.lat, newCenter.lng]);
|
|
setCurrentZoom(newZoom);
|
|
|
|
localStorage.setItem("mapCenter", JSON.stringify([newCenter.lat, newCenter.lng]));
|
|
localStorage.setItem("mapZoom", newZoom);
|
|
};
|
|
|
|
map.on("moveend", handleMapMoveEnd);
|
|
map.on("zoomend", handleMapMoveEnd);
|
|
|
|
return () => {
|
|
map.off("moveend", handleMapMoveEnd);
|
|
map.off("zoomend", handleMapMoveEnd);
|
|
};
|
|
}
|
|
}, [map]);
|
|
//--------------------------------------------
|
|
|
|
useEffect(() => {
|
|
if (selectedArea && map) {
|
|
const station = GisStationsStaticDistrict.find((s) => s.Area_Name === selectedArea);
|
|
if (station) {
|
|
map.flyTo([station.X, station.Y], 14);
|
|
}
|
|
}
|
|
}, [selectedArea, map, GisStationsStaticDistrict]);
|
|
|
|
useEffect(() => {
|
|
if (zoomTrigger && map) {
|
|
map.flyTo([51.41321407879154, 7.739617925303934], 7);
|
|
}
|
|
}, [zoomTrigger, map]);
|
|
|
|
useEffect(() => {
|
|
if (map && poiLayerRef.current && isPoiTypLoaded && !menuItemAdded && isRightsLoaded) {
|
|
addItemsToMapContextMenu(map, menuItemAdded, setMenuItemAdded, hasRights, setShowPopup, setPopupCoordinates);
|
|
}
|
|
}, [map, poiLayerRef, isPoiTypLoaded, menuItemAdded, hasRights, isRightsLoaded]);
|
|
//--------------------------------------------
|
|
// rote Marker ganz oben wenn überlappen sind
|
|
useEffect(() => {
|
|
const fetchPriorityConfig = async () => {
|
|
try {
|
|
const res = await fetch("/api/talas_v5_DB/priorityConfig");
|
|
if (!res.ok) {
|
|
throw new Error(`HTTP error! status: ${res.status}`);
|
|
}
|
|
const data = await res.json();
|
|
setPriorityConfig(data);
|
|
} catch (error) {
|
|
console.error("Failed to load priority configuration:", error);
|
|
}
|
|
};
|
|
|
|
fetchPriorityConfig();
|
|
}, []);
|
|
//--------------------------------------------
|
|
useEffect(() => {
|
|
if (mapRef.current && !map) {
|
|
initializeMap(mapRef, setMap, setOms, setMenuItemAdded, addItemsToMapContextMenu, hasRights, setPolylineEventsDisabled);
|
|
}
|
|
}, [mapRef, map, hasRights, setPolylineEventsDisabled]);
|
|
|
|
useEffect(() => {
|
|
if (map) {
|
|
if (polylineEventsDisabled) {
|
|
disablePolylineEvents(window.polylines);
|
|
} else {
|
|
enablePolylineEvents(window.polylines, window.lineColors);
|
|
}
|
|
}
|
|
}, [map, polylineEventsDisabled]);
|
|
useEffect(() => {
|
|
if (map) {
|
|
console.log("6- Karteninstanz (map) wurde jetzt erfolgreich initialisiert");
|
|
|
|
// Setze die Karteninstanz in den Recoil-Atom
|
|
}
|
|
}, [map]);
|
|
//--------------------------------------------
|
|
useEffect(() => {
|
|
const initializeContextMenu = () => {
|
|
if (map) {
|
|
map.whenReady(() => {
|
|
setTimeout(() => {
|
|
if (map.contextmenu) {
|
|
//console.log("Contextmenu ist vorhanden");
|
|
} else {
|
|
console.warn("Contextmenu ist nicht verfügbar.");
|
|
}
|
|
}, 500);
|
|
});
|
|
}
|
|
};
|
|
|
|
initializeContextMenu();
|
|
}, [map]);
|
|
//--------------------------------------------
|
|
//Tooltip Werte aktualisieren
|
|
useEffect(() => {
|
|
if (!map) return; // Stelle sicher, dass die Karte initialisiert ist
|
|
|
|
const updateGmaData = async () => {
|
|
try {
|
|
const fetchOptions = {
|
|
method: "GET",
|
|
headers: {
|
|
Connection: "close",
|
|
},
|
|
};
|
|
|
|
// Aktualisiere die Messdaten
|
|
await fetchGisStationsMeasurements(mapGisStationsMeasurementsUrl, setGisStationsMeasurements, fetchOptions);
|
|
|
|
// Aktualisiere die Marker-Layer
|
|
// useGmaMarkersLayer(map, gmaMarkers, GisStationsMeasurements, layers.MAP_LAYERS.GMA, oms);
|
|
} catch (error) {
|
|
console.error("Fehler beim Aktualisieren der GMA-Daten:", error);
|
|
}
|
|
};
|
|
|
|
// Initialer Datenabruf
|
|
updateGmaData();
|
|
|
|
// Setze ein Intervall, um die Daten alle 5 Sekunden zu aktualisieren
|
|
/* const intervalId = setInterval(() => {
|
|
updateGmaData();
|
|
}, 5000);
|
|
|
|
// Cleanup-Funktion, um das Intervall zu entfernen, wenn die Komponente entladen wird
|
|
return () => clearInterval(intervalId); */
|
|
}, [map, gmaMarkers, layers.MAP_LAYERS.GMA, oms, mapGisStationsMeasurementsUrl]);
|
|
|
|
//---------------------------------
|
|
|
|
const gmaLayerRef = useRef(null);
|
|
const talasLayerRef = useRef(null);
|
|
const eciMarkersLayerRef = useRef(null);
|
|
const gsmModemMarkersLayerRef = useRef(null);
|
|
const ciscoRouterMarkersLayerRef = useRef(null);
|
|
const wagoMarkersLayerRef = useRef(null);
|
|
const siemensMarkersLayerRef = useRef(null);
|
|
const otdrMarkersLayerRef = useRef(null);
|
|
const wdmMarkersLayerRef = useRef(null);
|
|
const messstellenMarkersLayerRef = useRef(null);
|
|
const talasiclMarkersLayerRef = useRef(null);
|
|
const dauzMarkersLayerRef = useRef(null);
|
|
const smsfunkmodemMarkersLayerRef = useRef(null);
|
|
const ulafMarkersLayerRef = useRef(null);
|
|
const sonstigeMarkersLayerRef = useRef(null);
|
|
const tkComponentsMarkersRef = useRef(null);
|
|
useEffect(() => {
|
|
if (!gisSystemStaticLoaded || !map) return; // Sicherstellen, dass die Karte und Daten geladen sind
|
|
|
|
const layerGroups = [
|
|
{ ref: gmaLayerRef, id: 11, setState: setGmaMarkers },
|
|
{ ref: talasLayerRef, id: 1, setState: setTalasMarkers },
|
|
{ ref: eciMarkersLayerRef, id: 2, setState: setEciMarkers },
|
|
{ ref: gsmModemMarkersLayerRef, id: 5, setState: setGsmModemMarkers },
|
|
{ ref: ciscoRouterMarkersLayerRef, id: 6, setState: setCiscoRouterMarkers },
|
|
{ ref: wagoMarkersLayerRef, id: 7, setState: setWagoMarkers },
|
|
{ ref: siemensMarkersLayerRef, id: 8, setState: setSiemensMarkers },
|
|
{ ref: otdrMarkersLayerRef, id: 9, setState: setOtdrMarkers },
|
|
{ ref: wdmMarkersLayerRef, id: 10, setState: setWdmMarkers },
|
|
{ ref: messstellenMarkersLayerRef, id: 13, setState: setMessstellenMarkers },
|
|
{ ref: talasiclMarkersLayerRef, id: 100, setState: setTalasiclMarkers },
|
|
{ ref: dauzMarkersLayerRef, id: 110, setState: setDauzMarkers },
|
|
{ ref: smsfunkmodemMarkersLayerRef, id: 111, setState: setSmsfunkmodemMarkers },
|
|
{ ref: ulafMarkersLayerRef, id: 0, setState: setUlafMarkers },
|
|
{ ref: sonstigeMarkersLayerRef, id: 200, setState: setSonstigeMarkers },
|
|
{ ref: tkComponentsMarkersRef, id: 30, setState: setTkComponentsMarkers },
|
|
];
|
|
|
|
// Initialisiere LayerGroups nur einmal
|
|
layerGroups.forEach(({ ref }) => {
|
|
if (!ref.current) {
|
|
ref.current = new L.LayerGroup().addTo(map);
|
|
}
|
|
});
|
|
|
|
const updateMarkers = ({ ref, id, setState }) => {
|
|
if (ref.current) {
|
|
ref.current.clearLayers(); // Entferne alte Marker
|
|
}
|
|
|
|
// Erstelle und füge neue Marker hinzu
|
|
createAndSetDevices(
|
|
id,
|
|
(newMarkers) => {
|
|
setState(newMarkers); // Zustand aktualisieren
|
|
newMarkers.forEach((marker) => ref.current.addLayer(marker)); // Marker zur LayerGroup hinzufügen
|
|
|
|
// Überprüfe auf überlappende Marker und füge das Plus-Icon hinzu
|
|
checkOverlappingMarkers(map, newMarkers, plusRoundIcon);
|
|
},
|
|
GisSystemStatic,
|
|
priorityConfig
|
|
);
|
|
};
|
|
|
|
// Aktualisiere alle Marker-Gruppen
|
|
const updateAllMarkers = () => {
|
|
layerGroups.forEach(updateMarkers);
|
|
};
|
|
|
|
// Initiales Update
|
|
updateAllMarkers();
|
|
|
|
// Setze ein Intervall für regelmäßige Updates
|
|
/* const intervalId = setInterval(() => {
|
|
updateAllMarkers();
|
|
}, 60000); // 20 Sekunden
|
|
|
|
// Aufräumen bei Komponentenentladung
|
|
return () => {
|
|
clearInterval(intervalId); // Entferne Intervall
|
|
|
|
// LayerGroups leeren
|
|
layerGroups.forEach(({ ref }) => {
|
|
if (ref.current) {
|
|
ref.current.clearLayers();
|
|
}
|
|
});
|
|
}; */
|
|
}, [gisSystemStaticLoaded, map, GisSystemStatic, priorityConfig]);
|
|
|
|
//---------------------------------------
|
|
// Initialisiere Leaflet-Karte
|
|
// Rufe useBereicheMarkersLayer direkt auf
|
|
const bereicheMarkers = useBereicheMarkersLayer(map, oms, "/api/talas_v5_DB/bereich/readBereich?m=12");
|
|
|
|
useEffect(() => {
|
|
if (map && oms) {
|
|
// Wenn zusätzliche Initialisierung nötig ist, führe sie hier aus.
|
|
console.log("Bereiche-Markierungen geladen:", bereicheMarkers);
|
|
}
|
|
}, [map, oms, bereicheMarkers]);
|
|
|
|
//----------------------------------
|
|
|
|
//---------------------------------------
|
|
|
|
return (
|
|
<>
|
|
<ToastContainer />
|
|
<div>{showPoiUpdateModal && <PoiUpdateModal onClose={() => setShowPoiUpdateModal(false)} poiData={currentPoiData} onSubmit={() => {}} latlng={popupCoordinates} />}</div>
|
|
|
|
<div>
|
|
{showPopup && (
|
|
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-[1000]" onClick={closePopup}>
|
|
<div className="relative bg-white p-6 rounded-lg shadow-lg" onClick={(e) => e.stopPropagation()}>
|
|
<button onClick={closePopup} className="absolute top-0 right-0 mt-2 mr-2 p-1 text-gray-700 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-600" aria-label="Close">
|
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
<AddPoiModalWindow onClose={closePopup} onSubmit={handleAddStation} latlng={popupCoordinates} />
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<DataSheet className="z-50" />
|
|
|
|
<div id="map" ref={mapRef} className="z-0" style={{ height: "100vh", width: "100vw" }}></div>
|
|
|
|
<div className="absolute bottom-3 left-3 w-72 p-4 bg-white rounded-lg shadow-md z-50">
|
|
<div className="flex justify-between items-center">
|
|
<div>
|
|
<span className="text-black text-lg font-semibold"> TALAS.Map </span>
|
|
<br />
|
|
<span className="text-black text-lg">Version {APP_VERSION}</span>
|
|
</div>
|
|
<div>
|
|
<button onClick={openVersionInfoModal}>
|
|
<InformationCircleIcon className="text-blue-900 h-8 w-8 pr-1" title="Weitere Infos" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<VersionInfoModal showVersionInfoModal={showVersionInfoModal} closeVersionInfoModal={closeVersionInfoModal} APP_VERSION={APP_VERSION} />
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default MapComponent;
|