Merge branch 'develop'

This commit is contained in:
ISA
2024-12-27 08:30:26 +01:00
8 changed files with 229 additions and 29 deletions

View File

@@ -11,4 +11,6 @@ DB_PORT=3306
######################### Offline Karte
#NEXT_PUBLIC_ONLINE_TILE_LAYER="http://127.0.0.1:3000/mapTiles/{z}/{x}/{y}.png"
#NEXT_PUBLIC_ONLINE_TILE_LAYER="http://10.10.0.13:3000/mapTiles/{z}/{x}/{y}.png"
####################
NEXT_PUBLIC_ENABLE_GEOCODER=true

View File

@@ -3,6 +3,7 @@ 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";
@@ -43,13 +44,7 @@ import useLineData from "../hooks/useLineData.js";
import { useMapComponentState } from "../hooks/useMapComponentState";
import { disablePolylineEvents, enablePolylineEvents } from "../utils/setupPolylines";
import { updateLocation } from "../utils/updateBereichUtil";
import { usePolylineTooltipLayer } from "../hooks/usePolylineTooltipLayer";
import { useFetchLineStatusData } from "../hooks/useFetchLineStatusData";
import { useFetchPriorityConfig } from "../hooks/useFetchPriorityConfig";
import { useUpdateGmaData } from "../hooks/useUpdateGmaData";
import { useDynamicMarkerLayers } from "../hooks/useDynamicMarkerLayers";
import { useFetchUserRights } from "../hooks/useFetchUserRights";
import { useFetchWebServiceMap } from "../hooks/useFetchWebServiceMap";
import { initGeocoderFeature } from "../components/features/GeocoderFeature";
//--------------------------------------------
import { currentPoiState } from "../redux/slices/currentPoiSlice.js";
import { selectGisStationsStaticDistrict, setGisStationsStaticDistrict } from "../redux/slices/gisStationsStaticDistrictSlice";
@@ -522,24 +517,100 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
useUpdateGmaData(map, setGisStationsMeasurements, mapGisStationsMeasurementsUrl, gmaMarkers, layers, oms);
//---------------------------------
useDynamicMarkerLayers(map, gisSystemStaticLoaded, GisSystemStatic, priorityConfig, {
setGmaMarkers,
setTalasMarkers,
setEciMarkers,
setGsmModemMarkers,
setCiscoRouterMarkers,
setWagoMarkers,
setSiemensMarkers,
setOtdrMarkers,
setWdmMarkers,
setMessstellenMarkers,
setTalasiclMarkers,
setDauzMarkers,
setSmsfunkmodemMarkers,
setUlafMarkers,
setSonstigeMarkers,
setTkComponentsMarkers,
});
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
@@ -601,6 +672,12 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}, [map, allMarkers]);
//---------------------------------------
useEffect(() => {
if (map) {
initGeocoderFeature(map); // Geocoder-Feature initialisieren
}
}, [map]);
//--------------------------------------------
return (
<>

View File

@@ -0,0 +1,49 @@
// components/features/GeocoderFeature.js
export function initGeocoderFeature(map) {
// Feature Toggle
const isGeocoderEnabled = process.env.NEXT_PUBLIC_ENABLE_GEOCODER === "true";
if (!isGeocoderEnabled) return; // Falls deaktiviert, nichts ausführen
// Benutzerdefiniertes Icon erstellen
const customIcon = L.icon({
iconUrl: "/img/marker-icon.png",
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -32],
});
// Geocoder hinzufügen
const geocoder = L.Control.geocoder({
position: "topleft",
defaultMarkGeocode: false,
errorMessage: "", // Keine Fehlermeldung anzeigen
geocoder: new L.Control.Geocoder.Nominatim({
serviceUrl: "https://nominatim.openstreetmap.org/",
geocodingQueryParams: {
"accept-language": "de",
countrycodes: "DE",
},
}),
})
.on("markgeocode", function (e) {
const latlng = e.geocode.center;
map.setView(latlng, 15);
L.marker(latlng, { icon: customIcon }).addTo(map).bindPopup(e.geocode.name).openPopup();
})
.addTo(map);
// Styling mit Tailwind CSS
setTimeout(() => {
const geocoderContainer = document.querySelector(".leaflet-control-geocoder");
if (geocoderContainer) {
geocoderContainer.classList.add("shadow-md", "border", "border-gray-300", "rounded-full", "bg-white", "p-2", "w-96");
const geocoderInput = geocoderContainer.querySelector("input");
if (geocoderInput) {
geocoderInput.classList.add("border-none", "outline-none", "w-full", "text-sm", "text-gray-700", "pl-3");
geocoderInput.placeholder = "Ort oder Adresse suchen...";
}
}
}, 100);
}

20
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{
"name": "13.12.2024 NodeMap V1.0.16.0",
"name": "23.12.2024 NodeMap V1.0.17.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
@@ -15,6 +15,7 @@
"http-proxy-middleware": "^3.0.0",
"leaflet": "^1.9.4",
"leaflet-contextmenu": "^1.4.0",
"leaflet-control-geocoder": "^3.1.0",
"leaflet.smooth_marker_bouncing": "^3.1.0",
"mysql": "^2.18.1",
"mysql2": "^3.11.0",
@@ -7435,6 +7436,17 @@
"resolved": "https://registry.npmjs.org/leaflet-contextmenu/-/leaflet-contextmenu-1.4.0.tgz",
"integrity": "sha512-BXASCmJ5bLkuJGDCpWmvGqhZi5AzeOY0IbQalfkgBcMAMfAOFSvD4y0gIQxF/XzEyLkjXaRiUpibVj4+Cf3tUA=="
},
"node_modules/leaflet-control-geocoder": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leaflet-control-geocoder/-/leaflet-control-geocoder-3.1.0.tgz",
"integrity": "sha512-0YlcjBmVq6/9vozpjMCNhxReHaZoCfoRwxKNXQXwjdfYr3TMRQi0YFmpN/dWbqOVc0fWbY1EsoV8r11G2SZ9eA==",
"optionalDependencies": {
"open-location-code": "^1.0.3"
},
"peerDependencies": {
"leaflet": "^1.6.0"
}
},
"node_modules/leaflet.smooth_marker_bouncing": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leaflet.smooth_marker_bouncing/-/leaflet.smooth_marker_bouncing-3.1.0.tgz",
@@ -8126,6 +8138,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/open-location-code": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/open-location-code/-/open-location-code-1.0.3.tgz",
"integrity": "sha512-DBm14BSn40Ee241n80zIFXIT6+y8Tb0I+jTdosLJ8Sidvr2qONvymwqymVbHV2nS+1gkDZ5eTNpnOIVV0Kn2fw==",
"optional": true
},
"node_modules/ospath": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",

View File

@@ -10,6 +10,7 @@
"http-proxy-middleware": "^3.0.0",
"leaflet": "^1.9.4",
"leaflet-contextmenu": "^1.4.0",
"leaflet-control-geocoder": "^3.1.0",
"leaflet.smooth_marker_bouncing": "^3.1.0",
"mysql": "^2.18.1",
"mysql2": "^3.11.0",

View File

@@ -4,6 +4,7 @@ import { RecoilRoot } from "recoil";
import { Provider } from "react-redux";
import store from "../redux/store";
import "../styles/global.css";
//import "../public/css/geocoder.css";
function MyApp({ Component, pageProps }) {
return (

42
public/css/geocoder.css Normal file
View File

@@ -0,0 +1,42 @@
.leaflet-control-geocoder {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Weicher Schatten */
border: 1px solid #d9d9d9; /* Heller Rand */
border-radius: 20px; /* Abgerundete Ecken für Google Maps Look */
padding: 5px 10px; /* Innenabstand */
font-size: 14px; /* Schriftgröße */
font-family: Arial, sans-serif; /* Schriftart */
width: 300px; /* Breite des Suchfeldes */
background-color: #fff; /* Hintergrundfarbe */
display: flex; /* Flexbox für Icon-Ausrichtung */
align-items: center; /* Zentrierte Inhalte */
}
.leaflet-control-geocoder input {
border: none; /* Kein Rand für das Eingabefeld */
outline: none; /* Kein Fokus-Rahmen */
width: 100%; /* Volle Breite */
font-size: 14px; /* Schriftgröße */
color: #333; /* Textfarbe */
padding-left: 10px; /* Abstand vom Rand */
}
.leaflet-control-geocoder input::placeholder {
color: #757575; /* Platzhalter-Farbe */
}
.leaflet-control-geocoder-icon {
background-color: transparent; /* Kein Hintergrund */
border: none; /* Kein Rand */
cursor: pointer; /* Zeiger beim Überfahren */
margin-right: 5px; /* Abstand zum Textfeld */
}
.leaflet-control-geocoder-icon img {
width: 20px; /* Icon-Größe */
height: 20px;
}
/* Alternative Ergebnisse verbergen */
.leaflet-control-geocoder-alternatives {
display: none;
}

View File

@@ -1,11 +1,10 @@
// utils/initializeMap.js
// TODO: Add a comment
//FIXME: Add a comment
//BUG: Add a comment
import L from "leaflet";
import "leaflet-contextmenu";
import "leaflet/dist/leaflet.css";
import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
import "leaflet-control-geocoder";
import * as urls from "../config/urls.js";
import * as layers from "../config/layers.js";
import { openInNewTab } from "./openInNewTab.js";
@@ -71,6 +70,17 @@ export const initializeMap = (mapRef, setMap, setOms, setMenuItemAdded, addItems
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(initMap);
// Suchfeld hinzufügen
const geocoder = L.Control.geocoder({
defaultMarkGeocode: false,
})
.on("markgeocode", function (e) {
const latlng = e.geocode.center;
initMap.setView(latlng, 15);
L.marker(latlng).addTo(initMap).bindPopup(e.geocode.name).openPopup();
})
.addTo(initMap);
// Initialisiere OverlappingMarkerSpiderfier
const overlappingMarkerSpiderfier = new OverlappingMarkerSpiderfier(initMap, {
nearbyDistance: 20,