Files
nodeMap/components/MapComponent.js

579 lines
23 KiB
JavaScript

// components/MapComponent.js
import {
React,
useEffect,
useRef,
useState,
L,
config,
urls,
OverlappingMarkerSpiderfier,
DataSheet,
useRecoilValue,
useSetRecoilState,
gisStationsStaticDistrictState,
gisSystemStaticState,
mapLayersState,
selectedAreaState,
zoomTriggerState,
AddPoiModalWindow,
poiReadFromDbTriggerAtom,
InformationCircleIcon,
PoiUpdateModal,
selectedPoiState,
currentPoiState,
ToastContainer,
toast,
mapIdState,
userIdState,
poiLayerVisibleState,
plusRoundIcon,
createAndSetDevices,
restoreMapSettings,
checkOverlappingMarkers,
fetchGisStatusStations,
fetchPoiData,
fetchUserRights,
MAP_VERSION,
layers,
initializeMap,
addItemsToMapContextMenu,
useGmaMarkersLayer,
useTalasMarkersLayer,
useEciMarkersLayer,
useGsmModemMarkersLayer,
useCiscoRouterMarkersLayer,
useWagoMarkersLayer,
useSiemensMarkersLayer,
useOtdrMarkersLayer,
useWdmMarkersLayer,
useMessstellenMarkersLayer,
useTalasiclMarkersLayer,
useDauzMarkersLayer,
useSmsfunkmodemMarkersLayer,
useUlafMarkersLayer,
useSonstigeMarkersLayer,
fetchGisStationsStaticDistrict,
fetchGisStationsStatusDistrict,
fetchGisStationsMeasurements,
fetchGisSystemStatic,
setupPolylines,
setupPOIs,
VersionInfoModal,
useFetchPoiData,
usePoiTypData,
useLayerVisibility,
useLineData,
} from "./imports.js";
import useCreateAndSetDevices from "../hooks/useCreateAndSetDevices";
//import { useCreateAndSetDevices } from "../hooks/useCreateAndSetDevices";
import { useMapComponentState } from "../hooks/useMapComponentState";
import { useRecoilState } from "recoil";
import { polylineEventsDisabledState } from "../store/atoms/polylineEventsDisabledState";
import { disablePolylineEvents, enablePolylineEvents } from "../utils/setupPolylines";
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
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 talasMarkers = useTalasMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const eciMarkers = useEciMarkersLayer(map, eciMarkers, oms, layers.MAP_LAYERS.ECI);
const gsmModemMarkers = useGsmModemMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const ciscoRouterMarkers = useCiscoRouterMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const wagoMarkers = useWagoMarkersLayer(map, oms, GisSystemStatic, priorityConfig);
const siemensMarkers = useSiemensMarkersLayer(map, oms, GisSystemStatic, priorityConfig);
const otdrMarkers = useOtdrMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const wdmMarkers = useWdmMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const messstellenMarkers = useMessstellenMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const talasiclMarkers = useTalasiclMarkersLayer(map, oms, GisSystemStatic, priorityConfig);
const dauzMarkers = useDauzMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const smsfunkmodemMarkers = useSmsfunkmodemMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const ulafMarkers = useUlafMarkersLayer(map, oms, GisSystemStatic, priorityConfig);
const sonstigeMarkers = useSonstigeMarkersLayer(map, oms, GisSystemStatic, priorityConfig); // Use the new custom hook
const [gmaMarkers, setGmaMarkers] = useState([]); //--------------------station.System === 11 alle sind untetschiedlich Nummern
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];
}
});
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);
setHasRights(rights && rights.includes(56)); // Prüfen, ob Benutzer die Rechte hat
};
fetchAndSetUserRights();
}, []);
useGmaMarkersLayer(map, gmaMarkers, GisStationsMeasurements, layers.MAP_LAYERS.GMA, oms); // Verwende den ausgelagerten Hook
useEffect(() => {
const fetchAllData = async () => {
try {
// Fetch GIS Stations Static District
await fetchGisStationsStaticDistrict(mapGisStationsStaticDistrictUrl, setGisStationsStaticDistrict);
// Fetch GIS Stations Status District
await fetchGisStationsStatusDistrict(mapGisStationsStatusDistrictUrl, setGisStationsStatusDistrict);
// Fetch GIS Stations Measurements
await fetchGisStationsMeasurements(mapGisStationsMeasurementsUrl, setGisStationsMeasurements);
// Fetch GIS System Static
await fetchGisSystemStatic(mapGisSystemStaticUrl, setGisSystemStatic, setGisSystemStaticLoaded);
} catch (error) {
console.error("Error fetching data:", error);
}
};
fetchAllData();
}, []);
//--------------------------------------------------------
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);
}, [map, locations, onLocationUpdate, poiReadTrigger, isPoiTypLoaded, userRights, poiLayerVisible, poiData, poiTypMap]);
//---------------------------------------------
//console.log("priorityConfig in MapComponent2: ", priorityConfig);
useEffect(() => {
if (gisSystemStaticLoaded && map) {
createAndSetDevices(1, GisSystemStatic, priorityConfig); // TALAS-System
createAndSetDevices(2, GisSystemStatic, priorityConfig); // ECI-System
createAndSetDevices(5, GisSystemStatic, priorityConfig); // GSM-Modem-System
createAndSetDevices(6, GisSystemStatic, priorityConfig); // Cisco-Router-System
createAndSetDevices(7, GisSystemStatic, priorityConfig); // WAGO-System
createAndSetDevices(8, GisSystemStatic, priorityConfig); // Siemens-System
createAndSetDevices(9, GisSystemStatic, priorityConfig); // OTDR-System
createAndSetDevices(10, GisSystemStatic, priorityConfig); // WDM-System
createAndSetDevices(11, setGmaMarkers, GisSystemStatic, priorityConfig); // GMA-System
createAndSetDevices(13, GisSystemStatic, priorityConfig); // Messstellen-System
createAndSetDevices(100, GisSystemStatic, priorityConfig); // TALASICL-System
createAndSetDevices(110, GisSystemStatic, priorityConfig); // DAUZ-System
createAndSetDevices(111, GisSystemStatic, priorityConfig); // SMS-Funkmodem-System
createAndSetDevices(200, GisSystemStatic, priorityConfig); // Sonstige-System
createAndSetDevices(0, GisSystemStatic, priorityConfig); // ULAF-System
}
}, [gisSystemStaticLoaded, map, GisSystemStatic, priorityConfig]);
//useCreateAndSetDevices(1, talasMarkers, GisSystemStatic, priorityConfig);
useLayerVisibility(map, talasMarkers, mapLayersVisibility, "TALAS");
useLayerVisibility(map, eciMarkers, mapLayersVisibility, "ECI");
useLayerVisibility(map, gsmModemMarkers, mapLayersVisibility, "GSMModem");
useLayerVisibility(map, ciscoRouterMarkers, mapLayersVisibility, "CiscoRouter");
useLayerVisibility(map, wagoMarkers, mapLayersVisibility, "WAGO");
useLayerVisibility(map, siemensMarkers, mapLayersVisibility, "Siemens");
useLayerVisibility(map, otdrMarkers, mapLayersVisibility, "OTDR");
useLayerVisibility(map, wdmMarkers, mapLayersVisibility, "WDM");
useLayerVisibility(map, gmaMarkers, mapLayersVisibility, "GMA");
useLayerVisibility(map, sonstigeMarkers, mapLayersVisibility, "Sonstige");
useLayerVisibility(map, talasiclMarkers, mapLayersVisibility, "TALASICL");
useLayerVisibility(map, dauzMarkers, mapLayersVisibility, "DAUZ");
useLayerVisibility(map, smsfunkmodemMarkers, mapLayersVisibility, "SMSFunkmodem");
useLayerVisibility(map, messstellenMarkers, mapLayersVisibility, "Messstellen");
useLayerVisibility(map, ulafMarkers, mapLayersVisibility, "ULAF");
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) {
const allMarkers = [
...talasMarkers,
...eciMarkers,
...gsmModemMarkers,
...ciscoRouterMarkers,
...wagoMarkers,
...siemensMarkers,
...otdrMarkers,
...wdmMarkers,
...gmaMarkers,
...messstellenMarkers,
...talasiclMarkers,
...dauzMarkers,
...smsfunkmodemMarkers,
...sonstigeMarkers,
...ulafMarkers,
];
checkOverlappingMarkers(map, allMarkers, plusRoundIcon);
}
}, [map, talasMarkers, eciMarkers, gsmModemMarkers, ciscoRouterMarkers, wagoMarkers, siemensMarkers, otdrMarkers, wdmMarkers, gmaMarkers, messstellenMarkers, talasiclMarkers, dauzMarkers, smsfunkmodemMarkers, sonstigeMarkers, 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();
}, []);
useEffect(() => {
if (!map) return;
markers.forEach((marker) => marker.remove());
polylines.forEach((polyline) => polyline.remove());
const { markers: newMarkers, polylines: newPolylines } = setupPolylines(map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker);
setMarkers(newMarkers);
setPolylines(newPolylines);
}, [map, linePositions, lineColors, tooltipContents, newPoint, newCoords, tempMarker]);
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 (mapRef.current && !map) {
initializeMap(mapRef, setMap, setOms, setMenuItemAdded, addItemsToMapContextMenu, hasRights);
}
}, [mapRef, map, hasRights, addItemsToMapContextMenu]);
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 (!map) return;
markers.forEach((marker) => marker.remove());
polylines.forEach((polyline) => polyline.remove());
const { markers: newMarkers, polylines: newPolylines } = setupPolylines(map, linePositions, lineColors, tooltipContents, setNewCoords, tempMarker, currentZoom, currentCenter);
setMarkers(newMarkers);
setPolylines(newPolylines);
}, [map, linePositions, lineColors, tooltipContents, newPoint, newCoords, tempMarker, currentZoom, currentCenter]); // Ensure currentZoom and currentCenter are included in the dependency array */
//--------------------------------------------
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 {MAP_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} MAP_VERSION={MAP_VERSION} />
</>
);
};
export default MapComponent;