feat: AreaDropdown separate from MapLayerControlPanel
This commit is contained in:
@@ -23,4 +23,4 @@ NEXT_PUBLIC_USE_MOCKS=true
|
|||||||
# z.B. http://10.10.0.13/xyz/index.aspx -> basePath in config.json auf /xyz setzen
|
# z.B. http://10.10.0.13/xyz/index.aspx -> basePath in config.json auf /xyz setzen
|
||||||
# basePath wird jetzt in public/config.json gepflegt
|
# basePath wird jetzt in public/config.json gepflegt
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.1.365
|
NEXT_PUBLIC_APP_VERSION=1.1.366
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ NEXT_PUBLIC_USE_MOCKS=false
|
|||||||
# basePath wird jetzt in public/config.json gepflegt
|
# basePath wird jetzt in public/config.json gepflegt
|
||||||
|
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.1.365
|
NEXT_PUBLIC_APP_VERSION=1.1.366
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import CoordinatePopup from "@/components/contextmenu/CoordinatePopup.js";
|
|||||||
import MapLayersControlPanel from "@/components/uiWidgets/mapLayersControlPanel/MapLayersControlPanel.js";
|
import MapLayersControlPanel from "@/components/uiWidgets/mapLayersControlPanel/MapLayersControlPanel.js";
|
||||||
import CoordinateInput from "@/components/uiWidgets/CoordinateInput.js";
|
import CoordinateInput from "@/components/uiWidgets/CoordinateInput.js";
|
||||||
import VersionInfoModal from "@/components/uiWidgets/VersionInfoModal.js";
|
import VersionInfoModal from "@/components/uiWidgets/VersionInfoModal.js";
|
||||||
|
import AreaDropdown from "@/components/uiWidgets/AreaDropdown";
|
||||||
//----------Daten aus API--------------------
|
//----------Daten aus API--------------------
|
||||||
import { fetchPoiDataService } from "@/services/database/pois/fetchPoiDataByIdService.js";
|
import { fetchPoiDataService } from "@/services/database/pois/fetchPoiDataByIdService.js";
|
||||||
import AddPOIModal from "@/components/pois/AddPOIModal.js";
|
import AddPOIModal from "@/components/pois/AddPOIModal.js";
|
||||||
@@ -164,6 +165,7 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
|||||||
const [showVersionInfoModal, setShowVersionInfoModal] = useState(false);
|
const [showVersionInfoModal, setShowVersionInfoModal] = useState(false);
|
||||||
const [poiTypMap, setPoiTypMap] = useState(new Map());
|
const [poiTypMap, setPoiTypMap] = useState(new Map());
|
||||||
const [showPopup, setShowPopup] = useState(false);
|
const [showPopup, setShowPopup] = useState(false);
|
||||||
|
const [showAreaDropdown, setShowAreaDropdown] = useState(false);
|
||||||
const poiLayerRef = useRef(null); // Referenz auf die Layer-Gruppe für Datenbank-Marker
|
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 mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
|
||||||
const [map, setMap] = useState(null); // Zustand der Karteninstanz
|
const [map, setMap] = useState(null); // Zustand der Karteninstanz
|
||||||
@@ -1133,7 +1135,8 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
|||||||
|
|
||||||
{GisStationsStaticDistrict &&
|
{GisStationsStaticDistrict &&
|
||||||
GisStationsStaticDistrict.Points?.length > 0 &&
|
GisStationsStaticDistrict.Points?.length > 0 &&
|
||||||
showLayersPanel && (
|
showLayersPanel &&
|
||||||
|
!showAreaDropdown && (
|
||||||
<MapLayersControlPanel
|
<MapLayersControlPanel
|
||||||
className="z-50"
|
className="z-50"
|
||||||
handlePolylineCheckboxChange={handlePolylineCheckboxChange}
|
handlePolylineCheckboxChange={handlePolylineCheckboxChange}
|
||||||
@@ -1157,13 +1160,14 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
|
|||||||
)}
|
)}
|
||||||
{/* Marker-Icon (line-md) */}
|
{/* Marker-Icon (line-md) */}
|
||||||
<button
|
<button
|
||||||
onClick={() => {}}
|
onClick={() => setShowAreaDropdown(v => !v)}
|
||||||
aria-label="Marker"
|
aria-label="Marker"
|
||||||
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
|
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
|
||||||
title="Marker"
|
title="Marker"
|
||||||
>
|
>
|
||||||
<MapMarkerIcon className="h-8 w-8" />
|
<MapMarkerIcon className="h-8 w-8" />
|
||||||
</button>
|
</button>
|
||||||
|
{showAreaDropdown && <AreaDropdown onClose={() => setShowAreaDropdown(false)} />}
|
||||||
{/*Lupe: Koordinatensuche ein-/ausblenden */}
|
{/*Lupe: Koordinatensuche ein-/ausblenden */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowCoordinateInput(v => !v)}
|
onClick={() => setShowCoordinateInput(v => !v)}
|
||||||
|
|||||||
79
components/uiWidgets/AreaDropdown.js
Normal file
79
components/uiWidgets/AreaDropdown.js
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
// /components/uiWidgets/AreaDropdown.js
|
||||||
|
import React, { useEffect, useMemo } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { setSelectedArea } from "@/redux/slices/selectedAreaSlice";
|
||||||
|
import { selectGisStationsStaticDistrict } from "@/redux/slices/webservice/gisStationsStaticDistrictSlice";
|
||||||
|
import { selectGisSystemStatic } from "@/redux/slices/webservice/gisSystemStaticSlice";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kleines Dropdown zur Auswahl der Station (Area_Name),
|
||||||
|
* nutzt dieselbe Datenquelle wie das MapLayersControlPanel.
|
||||||
|
*/
|
||||||
|
const AreaDropdown = ({ onClose }) => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const GisStationsStaticDistrict = useSelector(selectGisStationsStaticDistrict) || {};
|
||||||
|
const GisSystemStatic = useSelector(selectGisSystemStatic) || [];
|
||||||
|
|
||||||
|
// Erlaubte Systeme: Allow === 1 und Map === 1
|
||||||
|
const allowedSystems = useMemo(() => {
|
||||||
|
return new Set(
|
||||||
|
(Array.isArray(GisSystemStatic) ? GisSystemStatic : [])
|
||||||
|
.filter(sys => sys.Allow === 1 && sys.Map === 1)
|
||||||
|
.map(sys => sys.IdSystem)
|
||||||
|
);
|
||||||
|
}, [GisSystemStatic]);
|
||||||
|
|
||||||
|
// Uniqe Areas basierend auf Allowed Systems
|
||||||
|
const areaOptions = useMemo(() => {
|
||||||
|
const points = GisStationsStaticDistrict?.Points || [];
|
||||||
|
const seen = new Set();
|
||||||
|
const filtered = points.filter(p => {
|
||||||
|
if (!p?.Area_Name) return false;
|
||||||
|
if (!allowedSystems.has(p.System)) return false;
|
||||||
|
if (seen.has(p.Area_Name)) return false;
|
||||||
|
seen.add(p.Area_Name);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return filtered.map(p => ({ label: p.Area_Name, value: p.IdLD }));
|
||||||
|
}, [GisStationsStaticDistrict, allowedSystems]);
|
||||||
|
|
||||||
|
const handleChange = e => {
|
||||||
|
const selectedIndex = e.target.options.selectedIndex;
|
||||||
|
const label = e.target.options[selectedIndex].text;
|
||||||
|
dispatch(setSelectedArea(label));
|
||||||
|
onClose?.();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Schließe mit ESC
|
||||||
|
useEffect(() => {
|
||||||
|
const onKey = e => {
|
||||||
|
if (e.key === "Escape") onClose?.();
|
||||||
|
};
|
||||||
|
window.addEventListener("keydown", onKey);
|
||||||
|
return () => window.removeEventListener("keydown", onKey);
|
||||||
|
}, [onClose]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="absolute top-16 right-3 z-[60]">
|
||||||
|
<div className="bg-white rounded-md shadow-lg p-3 border border-gray-200 min-w-[220px]">
|
||||||
|
<div className="text-sm font-semibold mb-2">Station wählen</div>
|
||||||
|
<select
|
||||||
|
onChange={handleChange}
|
||||||
|
className="border p-2 rounded w-full"
|
||||||
|
defaultValue="__default__"
|
||||||
|
>
|
||||||
|
<option value="__default__" disabled>
|
||||||
|
Bitte wählen…
|
||||||
|
</option>
|
||||||
|
{areaOptions.map(opt => (
|
||||||
|
<option key={opt.value} value={opt.value}>
|
||||||
|
{opt.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AreaDropdown;
|
||||||
@@ -241,14 +241,47 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
|
|||||||
}, [GisStationsStaticDistrict]);
|
}, [GisStationsStaticDistrict]);
|
||||||
//---------------------------
|
//---------------------------
|
||||||
|
|
||||||
|
// Polyline (Kabelstrecken) abhängig von TALAS (system-1)
|
||||||
|
const onPolylineToggle = checked => {
|
||||||
|
if (editMode) return;
|
||||||
|
|
||||||
|
// Wenn Nutzer Kabelstrecken einschaltet, aber TALAS aktuell ausgeblendet ist,
|
||||||
|
// dann TALAS automatisch aktivieren (sofern erlaubt)
|
||||||
|
const talasKey = "system-1";
|
||||||
|
const talasVisible = !!mapLayersVisibility[talasKey];
|
||||||
|
if (checked && isTalasAllowed && !talasVisible) {
|
||||||
|
dispatch(setLayerVisibility({ layer: talasKey, visibility: true }));
|
||||||
|
|
||||||
|
// Persistiere Sichtbarkeit map/user-spezifisch
|
||||||
|
const mapId2 = localStorage.getItem("currentMapId");
|
||||||
|
const userId2 = localStorage.getItem("currentUserId");
|
||||||
|
const mapStorageKey =
|
||||||
|
mapId2 && userId2 ? `mapLayersVisibility_m${mapId2}_u${userId2}` : "mapLayersVisibility";
|
||||||
|
localStorage.setItem(
|
||||||
|
mapStorageKey,
|
||||||
|
JSON.stringify({ ...mapLayersVisibility, [talasKey]: true })
|
||||||
|
);
|
||||||
|
|
||||||
|
// Event feuern wie an anderer Stelle
|
||||||
|
setTimeout(() => {
|
||||||
|
const event = new Event("visibilityChanged");
|
||||||
|
window.dispatchEvent(event);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sichtbarkeit der Kabelstrecken setzen
|
||||||
|
handlePolylineCheckboxChange(checked);
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------
|
//---------------------------
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="mainDataSheet"
|
id="mainDataSheet"
|
||||||
className="absolute top-3 right-3 w-1/6 min-w-[300px] max-w-[400px] z-10 bg-white p-2 rounded-lg shadow-lg"
|
className="absolute top-16 right-3 w-1/6 min-w-[300px] max-w-[200px] z-10 bg-white p-2 rounded-lg shadow-lg"
|
||||||
>
|
>
|
||||||
<div className="flex flex-col gap-4 p-4">
|
<div className="flex flex-col gap-4 p-4">
|
||||||
<div className="flex items-center justify-between space-x-2">
|
<div className="flex items-center justify-between space-x-2">
|
||||||
|
{/*
|
||||||
<select
|
<select
|
||||||
onChange={handleAreaChange}
|
onChange={handleAreaChange}
|
||||||
id="stationListing"
|
id="stationListing"
|
||||||
@@ -256,13 +289,7 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
|
|||||||
style={{ minWidth: "150px", maxWidth: "200px" }}
|
style={{ minWidth: "150px", maxWidth: "200px" }}
|
||||||
>
|
>
|
||||||
<option value="Station wählen">Station wählen</option>
|
<option value="Station wählen">Station wählen</option>
|
||||||
{/*
|
|
||||||
...new Map(
|
|
||||||
(GisStationsStaticDistrict.Points || [])
|
|
||||||
.filter(p => !!p.Area_Name)
|
|
||||||
.map(p => [p.Area_Name, p])
|
|
||||||
).values(),
|
|
||||||
*/}
|
|
||||||
{[
|
{[
|
||||||
...new Map(
|
...new Map(
|
||||||
(GisStationsStaticDistrict.Points || [])
|
(GisStationsStaticDistrict.Points || [])
|
||||||
@@ -275,6 +302,8 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
*/}
|
||||||
|
|
||||||
{/*
|
{/*
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<EditModeToggle />
|
<EditModeToggle />
|
||||||
@@ -312,7 +341,7 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={kabelstreckenVisible}
|
checked={kabelstreckenVisible}
|
||||||
onChange={e => handlePolylineCheckboxChange(e.target.checked)}
|
onChange={e => onPolylineToggle(e.target.checked)}
|
||||||
id="polyline-checkbox"
|
id="polyline-checkbox"
|
||||||
disabled={!isTalasAllowed || editMode}
|
disabled={!isTalasAllowed || editMode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "nodemap",
|
"name": "nodemap",
|
||||||
"version": "1.1.365",
|
"version": "1.1.366",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "nodemap",
|
"name": "nodemap",
|
||||||
"version": "1.1.365",
|
"version": "1.1.366",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nodemap",
|
"name": "nodemap",
|
||||||
"version": "1.1.365",
|
"version": "1.1.366",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.3",
|
"@emotion/react": "^11.13.3",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user