feat(gma): GMA-Werte aus Measurements-Redux im Marker-Tooltip angezeigt

- createAndSetDevices.js erweitert mit dynamischer GMA-Zuordnung
- Tooltip für System 11 zeigt LT, FBT, GT, RLF
- GMA-Zuordnung über gmaMap basierend auf Na und IdLD
- Version auf 1.1.232 erhöht
This commit is contained in:
ISA
2025-06-04 12:14:14 +02:00
parent d80b36cb2d
commit f4342e17ef
6 changed files with 126 additions and 48 deletions

2
.gitignore vendored
View File

@@ -33,3 +33,5 @@ docs.zip
# Entwicklungsdaten # Entwicklungsdaten
/mockData/ /mockData/
/__mocks__/
/__tests__/

View File

@@ -4,6 +4,30 @@ Alle bedeutenden Änderungen an diesem Projekt werden in dieser Datei dokumentie
--- ---
## [1.1.232] 2025-06-04
### ✨ Added
- GMA-Werte (z.B. FBT, GT, LT, RLF) werden nun im Tooltip angezeigt direkt aus
`gisStationsMeasurements`.
### 🛠 Changed
- `createAndSetDevices.js` überarbeitet: GMA-Messwerte werden dynamisch anhand `Na`-Feld gruppiert
und in Map-Tooltips eingebunden.
- Hilfsstruktur `gmaMap` integriert zur sicheren Zuordnung von Messwerten über `IdLD`.
### 🧪 Debug & Visualisierung
- Tooltip zeigt standardmäßig `"-"` bei fehlenden Werten.
- Darstellung ist aktuell nur für `System === 11` aktiv (z.B. GMA-Messstellen).
### 🔧 Version
- 📦 `appVersion.js` auf Version **1.1.232** erhöht
---
## [1.1.231] 2025-06-04 ## [1.1.231] 2025-06-04
### ✨ Added ### ✨ Added

10
TODO.md
View File

@@ -14,8 +14,10 @@
- [ ] TODO: In editMode ohne Rechte kann noch den Bereich positioniert werden, es soll das nicht! - [ ] TODO: In editMode ohne Rechte kann noch den Bereich positioniert werden, es soll das nicht!
- [ ] TODO: die Messwerte GMA werden nicht angezeigt - [ ] TODO: die Messwerte GMA werden nicht angezeigt
- [ ] TODO: der Kunde könnte statt GMA andere Name haben - [ ] TODO: der Kunde könnte statt GMA andere Name haben
- [ ] TODO: überall durch ein Interval Services aufrufen um die Daten zu aktualisieren , am besten - [x] TODO: überall durch ein Interval Services aufrufen um die Daten zu aktualisieren , am besten
in eine Zentraler Stelle in eine Zentraler Stelle ---> von ein Hook die alle gebrauchte Slice und thunks holt mit
setInterval, diesen hokk in main component integrieren
- [ ] TODO: Möglichkeit bevor in Gitea hochgeladen, .env.local anpassen, vielleicht mit husky Wenn - [x] TODO: Möglichkeit bevor in Gitea hochgeladen, .env.local anpassen, vielleicht mit husky Wenn
git push genutzt wird soll für Produktionsumgebung angepasst werden, Vorschlag git push genutzt wird soll für Produktionsumgebung angepasst werden, Vorschlag ---> .env.local
und .env.production für Entwicklungsumgebung und Produktionsumgebung automatische Switch

View File

@@ -14,7 +14,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
const mapLayersVisibility = useSelector(selectMapLayersState); const mapLayersVisibility = useSelector(selectMapLayersState);
const poiTypData = useSelector(selectPoiTypData); const poiTypData = useSelector(selectPoiTypData);
const poiTypStatus = useSelector(selectPoiTypStatus); const poiTypStatus = useSelector(selectPoiTypStatus);
const devices = useSelector((state) => state.locationDevicesFromDB.devices); const devices = useSelector(state => state.locationDevicesFromDB.devices);
const [poiId, setPoiId] = useState(poiData?.idPoi || ""); const [poiId, setPoiId] = useState(poiData?.idPoi || "");
const [name, setName] = useState(poiData?.name || ""); const [name, setName] = useState(poiData?.name || "");
@@ -22,24 +22,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
const [deviceName, setDeviceName] = useState(null); const [deviceName, setDeviceName] = useState(null);
const [poiTypeId, setPoiTypeId] = useState(null); const [poiTypeId, setPoiTypeId] = useState(null);
const systemNameToIdMap = { const systemNameToIdMap = {};
TALAS: 1,
ECI: 2,
ULAF: 3,
GSMModem: 5,
CiscoRouter: 6,
WAGO: 7,
Siemens: 8,
OTDR: 9,
WDM: 10,
GMA: 11,
Messdatensammler: 12,
Messstellen: 13,
TALASICL: 100,
DAUZ: 110,
SMSFunkmodem: 111,
Basisgerät: 200,
};
useEffect(() => { useEffect(() => {
dispatch(fetchLocationDevicesThunk()); dispatch(fetchLocationDevicesThunk());
@@ -50,7 +33,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
useEffect(() => { useEffect(() => {
if (poiData && devices.length > 0) { if (poiData && devices.length > 0) {
const selectedDevice = devices.find((device) => device.idLD === poiData.idLD); const selectedDevice = devices.find(device => device.idLD === poiData.idLD);
if (selectedDevice) { if (selectedDevice) {
setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.name }); setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.name });
} }
@@ -59,7 +42,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
useEffect(() => { useEffect(() => {
if (poiData && poiTypData.length > 0) { if (poiData && poiTypData.length > 0) {
const selectedTyp = poiTypData.find((typ) => typ.idPoiTyp === poiData.idPoiTyp); const selectedTyp = poiTypData.find(typ => typ.idPoiTyp === poiData.idPoiTyp);
if (selectedTyp) { if (selectedTyp) {
setPoiTypeId({ value: selectedTyp.idPoiTyp, label: selectedTyp.name }); setPoiTypeId({ value: selectedTyp.idPoiTyp, label: selectedTyp.name });
} }
@@ -67,12 +50,16 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
}, [poiData, poiTypData]); }, [poiData, poiTypData]);
const filterDevices = () => { const filterDevices = () => {
const activeSystems = Object.keys(mapLayersVisibility).filter((system) => mapLayersVisibility[system]); const activeSystems = Object.keys(mapLayersVisibility).filter(
const activeSystemIds = activeSystems.map((system) => systemNameToIdMap[system]).filter((id) => id !== undefined); system => mapLayersVisibility[system]
return devices.filter((device) => activeSystemIds.includes(device.idsystem_typ)); );
const activeSystemIds = activeSystems
.map(system => systemNameToIdMap[system])
.filter(id => id !== undefined);
return devices.filter(device => activeSystemIds.includes(device.idsystem_typ));
}; };
const handleSubmit = async (event) => { const handleSubmit = async event => {
event.preventDefault(); event.preventDefault();
try { try {
await dispatch( await dispatch(
@@ -106,25 +93,25 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
}; };
const poiTypeOptions = Array.isArray(poiTypData) const poiTypeOptions = Array.isArray(poiTypData)
? poiTypData.map((poiTyp) => ({ ? poiTypData.map(poiTyp => ({
value: poiTyp.idPoiTyp, value: poiTyp.idPoiTyp,
label: poiTyp.name, label: poiTyp.name,
})) }))
: []; : [];
const deviceOptions = filterDevices().map((device) => ({ const deviceOptions = filterDevices().map(device => ({
value: device.idLD, value: device.idLD,
label: device.name, label: device.name,
})); }));
const customStyles = { const customStyles = {
control: (provided) => ({ control: provided => ({
...provided, ...provided,
width: "100%", width: "100%",
minWidth: "300px", minWidth: "300px",
maxWidth: "100%", maxWidth: "100%",
}), }),
menu: (provided) => ({ menu: provided => ({
...provided, ...provided,
width: "100%", width: "100%",
minWidth: "300px", minWidth: "300px",
@@ -132,11 +119,32 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
}; };
return ( return (
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-[1000]" onClick={onClose}> <div
<div className="relative bg-white p-6 rounded-lg shadow-lg" onClick={(e) => e.stopPropagation()}> className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-[1000]"
<button onClick={onClose} 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"> onClick={onClose}
<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" /> <div
className="relative bg-white p-6 rounded-lg shadow-lg"
onClick={e => e.stopPropagation()}
>
<button
onClick={onClose}
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> </svg>
</button> </button>
<form onSubmit={handleSubmit} className="m-0 p-2 w-full"> <form onSubmit={handleSubmit} className="m-0 p-2 w-full">
@@ -144,27 +152,58 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
<label htmlFor="description" className="block mb-2 font-bold text-sm text-gray-700"> <label htmlFor="description" className="block mb-2 font-bold text-sm text-gray-700">
Beschreibung: Beschreibung:
</label> </label>
<input type="text" id="description" name="description" value={description} onChange={(e) => setDescription(e.target.value)} placeholder="Beschreibung der Station" className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" /> <input
type="text"
id="description"
name="description"
value={description}
onChange={e => setDescription(e.target.value)}
placeholder="Beschreibung der Station"
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm"
/>
</div> </div>
<div className="flex flex-col mb-4"> <div className="flex flex-col mb-4">
<label htmlFor="deviceName" className="block mb-2 font-bold text-sm text-gray-700"> <label htmlFor="deviceName" className="block mb-2 font-bold text-sm text-gray-700">
Gerät: Gerät:
</label> </label>
<Select id="deviceName" value={deviceName} onChange={setDeviceName} options={deviceOptions} placeholder="Gerät auswählen..." isClearable={true} styles={customStyles} /> <Select
id="deviceName"
value={deviceName}
onChange={setDeviceName}
options={deviceOptions}
placeholder="Gerät auswählen..."
isClearable={true}
styles={customStyles}
/>
</div> </div>
<div className="flex flex-col mb-4"> <div className="flex flex-col mb-4">
<label htmlFor="idPoiTyp" className="block mb-2 font-bold text-sm text-gray-700"> <label htmlFor="idPoiTyp" className="block mb-2 font-bold text-sm text-gray-700">
Typ: Typ:
</label> </label>
<Select id="idPoiTyp" value={poiTypeId} onChange={setPoiTypeId} options={poiTypeOptions} placeholder="Typ auswählen..." isClearable={true} styles={customStyles} /> <Select
id="idPoiTyp"
value={poiTypeId}
onChange={setPoiTypeId}
options={poiTypeOptions}
placeholder="Typ auswählen..."
isClearable={true}
styles={customStyles}
/>
</div> </div>
<button type="button" onClick={handleDeletePoi} className="bg-red-400 hover:bg-red-600 text-white font-bold py-2 px-4 rounded w-full mb-4"> <button
type="button"
onClick={handleDeletePoi}
className="bg-red-400 hover:bg-red-600 text-white font-bold py-2 px-4 rounded w-full mb-4"
>
POI löschen POI löschen
</button> </button>
<button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"> <button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"
>
POI aktualisieren POI aktualisieren
</button> </button>
</form> </form>

View File

@@ -1,2 +1,2 @@
// /config/appVersion // /config/appVersion
export const APP_VERSION = "1.1.232"; export const APP_VERSION = "1.1.233";

View File

@@ -101,10 +101,21 @@ export const createAndSetDevices = async (
// ✅ Tooltip (nur für System 11) // ✅ Tooltip (nur für System 11)
if (station.System === 11 && messung) { if (station.System === 11 && messung) {
const lt = messung["LT"] ?? "-"; const gmaMap = new Map();
const fbt = messung["FBT"] ?? "-";
const gt = messung["GT"] ?? "-"; measurementData?.forEach(m => {
const rlf = messung["RLF"] ?? "-"; if (!gmaMap.has(m.IdLD)) {
gmaMap.set(m.IdLD, {});
}
const mapEntry = gmaMap.get(m.IdLD);
mapEntry[m.Na] = m.Val; // z.B. mapEntry["FBT"] = 6
});
const gmaValues = gmaMap.get(station.IdLD) ?? {};
const lt = gmaValues["LT"] ?? "-";
const fbt = gmaValues["FBT"] ?? "-";
const gt = gmaValues["GT"] ?? "-";
const rlf = gmaValues["RLF"] ?? "-";
const gmaTooltipHtml = ` const gmaTooltipHtml = `
<div class="p-0 rounded-lg bg-white bg-opacity-90 tooltip-content"> <div class="p-0 rounded-lg bg-white bg-opacity-90 tooltip-content">