10 KiB
🧠 Architekturübersicht – NodeMap
Dieses Dokument beschreibt die technische Gesamtarchitektur des Projekts NodeMap, einer kartenbasierten Webanwendung zur Anzeige, Bearbeitung und Verwaltung von GIS-Daten, POIs und Gerätestatus.
⚙️ Technologie-Stack
| Komponente | Beschreibung |
|---|---|
| Frontend | React 18 + Next.js (App Router) |
| State-Management | Redux Toolkit mit zentralem Store, Thunks & Slices |
| UI | Tailwind CSS + Leaflet + React-Icons |
| Backend-Anbindung | Webservices via WebServiceMap.asmx (IIS) + lokale Next.js API für DB |
| Datenbank | MySQL (Produktiv & Entwicklung, z. T. via Docker) |
| Deployment | Windows Server (IIS), optional per nssm als Dienst |
🔄 Systemübersicht (Ablauf)
sequenceDiagram
participant Browser
participant TALASweb
participant NodeMap
participant MySQL
Browser->>TALASweb: mapTypC.aspx?m=12&u=484
TALASweb-->>Browser: iFrame lädt NodeMap
Browser->>NodeMap: Liest m & u aus URL
NodeMap->>TALASweb: WebService-Requests (5 APIs)
NodeMap->>MySQL: API-Anfragen zu POIs, Geräten, Linien
NodeMap-->>Browser: Interaktive Karte anzeigen
🗺️ Architekturüberblick
+------------------+ +------------------+ +------------------+
| Leaflet Map | <---> | Redux Store | <---> | Webservices |
| (Interaktivität) | | (Status & Data) | | (IIS, .asmx) |
+------------------+ +------------------+ +------------------+
^
|
v
+------------------+ +------------------+ +-------------------+
| POI-Komponenten | <---> | Redux Slices | <---> | Next.js API-Routen|
| (Add/Edit) | | (z. B. poiSlice) | | (Datenbank) |
+------------------+ +------------------+ +-------------------+
🔁 Datenfluss (Beispiel: POI anzeigen)
- Leaflet-Karte lädt bei
MapComponentMounting - Redux-Thunk
fetchPoiMarkersThunkwird ausgelöst - Thunk ruft
fetchPoiDataService.js(DB) oder Webservice (IIS) auf - Ergebnisse werden im Slice
readPoiMarkersStoreSlicegespeichert - Komponenten lesen POI-Daten über
useSelector(...)aus dem Store - POIs werden als Marker in Leaflet gesetzt
📁 Schlüsselfunktionen & Module
| Bereich | Datei/Modul | Aufgabe |
|---|---|---|
| Kartenlogik | MapComponent.js |
Zentrale Initialisierung und Layer-Logik |
| Webservices | services/webservice/ |
Kommunikation mit TALAS V5 Webservice |
| Datenbank | services/database/ |
Zugriff auf lokale Next.js-API & DB |
| POIs | AddPOIModal.js, PoiUpdateModal.js |
UI für POI-Erstellung & -Bearbeitung |
| Redux | redux/slices/, redux/thunks/, redux/store |
Globaler State, API-Steuerung |
| Konfiguration | .env.development,.env.production, config.js, dynamic URLs |
IP, basePath, Ports |
🧩 Besonderheiten
-
Konfigurierbarer basePath:
-
Konfigurierbarer basePath:
Pfad wie/talas5ist optional und wird jetzt inpublic/config.jsonalsbasePathgepflegt werden.
Die Konfiguration erfolgt je nach Umgebung über:.env.developmentfür lokale Entwicklung.env.productionfür produktiven Einsatz
-
Rechteabhängige UI:
Funktionen (z. B. POI bearbeiten) basieren auf Benutzerrechten (IdRight) vom Server. -
Zentrale Komponentensteuerung:
Komponenten wieMapLayersControlPaneloderCoordinatePopupkontrollieren Layer & Interaktion. -
Kontextmenü-Logik:
Marker & Polylinien besitzen eigene Kontextmenüs – dynamisch zusammengesetzt und verwaltet.
📦 Versionierung & Builds
- Version wird mit Husky Bibliothek automatisch erhöhert in
scripts/bumpVersion.js
📚 Weiterführende Dokumentation
Dynamische Layer-Verwaltung mit Redux
flowchart TD
%% Webservice
subgraph Webservice
A1[GisSystemStatic API]
A2[GisStationsStaticDistrict API]
end
%% Redux
subgraph Redux
B1[fetchGisSystemStaticThunk]
B2[fetchGisStationsStaticDistrictThunk]
C1["gisSystemStaticSlice → selectGisSystemStatic"]
C2["gisStationsStaticDistrictSlice → selectGisStationsStaticDistrict"]
C3["mapLayersSlice → mapLayersVisibility"]
end
%% React
subgraph React-Komponente
D1[MapComponent.js]
D2["useEffect: dynamische Layer"]
D3["createAndSetDevices"]
D4["layerRefs (useRef)"]
D5["markerStates (useState)"]
D6["useEffect: Sichtbarkeit prüfen"]
D7["Map aktualisieren / add/remove"]
D8["checkOverlappingMarkers"]
end
%% Datenfluss
A1 --> B1 --> C1 --> D2
A2 --> B2 --> C2 --> D3
C3 --> D6
D2 --> D3
D3 --> D4
D3 --> D5
D5 --> D6
D6 --> D7
D6 --> D8
D7 --> D1
Jetzt (dynamisch & Redux-basiert): MapComponent.js ruft folgenden Hook auf:
js Copy Edit const { markerStates, layerRefs } = useDynamicDeviceLayers(map, GisSystemStatic, mapLayersVisibility, priorityConfig, oms); useDynamicDeviceLayers.js verarbeitet die GisSystemStatic-Liste:
Jedes System (z. B. "TALAS", "ECI", "Cisco") bekommt einen eigenen Marker-Layer.
Die Marker werden erstellt durch:
js Copy Edit createAndSetDevices(...) // Systemweise Marker erzeugen createAndSetDevices.js:
Filtert alle Stations aus staticDistrictData, deren System === IdSystem.
Erstellt Marker für jedes Gerät.
Bindet Popup, Kontextmenü, Styling, Bounce usw.
Ruft setMarkersFunction(markers) auf → Übergibt die Marker zurück an den Hook.
Der Hook speichert:
js Copy Edit setMarkerStates((prev) => ({ ...prev, [Name]: newMarkers })); MapComponent.js hat dann:
Zugriff auf alle Marker dynamisch über markerStates (ein Objekt mit Schlüssel = Systemname)
Sichtbarkeit und OverlappingMarkerSpiderfier werden damit verarbeitet.
🔁 Die Geräte-Marker sind nicht mehr fest codiert, sondern werden dynamisch erzeugt anhand der Webservice-Daten GisSystemStatic.
🔄 Sichtbarkeit (Checkbox im Control Panel) löst ein Event visibilityChanged aus → MapComponent reagiert und rendert Marker neu.
🕷️ Überlappende Marker werden mit checkOverlappingMarkers + PlusRoundIcon verarbeitet.
flowchart TD
A1[MapComponent] --> B1[useDynamicDeviceLayers]
B1 --> C1[loop über GisSystemStatic]
C1 --> D1[createAndSetDevices]
D1 --> E1[Filter stations aus Redux]
E1 --> F1[erstelle Marker /Leaflet]
F1 --> G1[Marker in LayerGroup einfügen]
G1 --> H1[setMarkerStates im Hook]
H1 --> A2[markerStates zurück nach MapComponent]
A2 --> I1[Map aktualisiert Marker]
A2 --> I2[checkOverlappingMarkers mit OMS]
10.06.2025
Datenfluss-Konzept: WebSocket ↔ Redux ↔ UI
Dieses Dokument beschreibt den technischen Ablauf des Live-Datenflusses im NodeMap-Projekt, um neue Entwickler:innen beim Onboarding zu unterstützen.
ᵀᵃᵗᵉᵖᵏᴼᵏᴼᵉ: Architekturübersicht
sequenceDiagram
autonumber
participant WS_Server as WebSocket Server
participant WebService as TALAS WebService
participant Browser
participant ReduxStore as Redux Store
participant UI as React Leaflet UI
loop Alle 5 Sekunden
WS_Server->>WebService: fetch endpointX
alt Daten haben sich geändert
WS_Server-->>Browser: emit 'endpointXUpdated'
Browser->>ReduxStore: dispatch(fetchEndpointXThunk())
ReduxStore->>WebService: fetch endpointX
WebService-->>ReduxStore: JSON response
ReduxStore-->>UI: update Slice
UI-->>User: re-render Markers
else Keine Änderung
WS_Server-->>WS_Server: keine Aktion
end
end
Beteiligte Komponenten
WebSocket Server (server.js)
- Ruft regelmäßig (
setInterval) die Webservice-Endpunkte auf. - Erkennt Änderungen durch JSON-Vergleich (
JSON.stringify). - Sendet WebSocket-Events nur bei echten Änderungen.
Client: MapComponent
- Hört auf
socket.on("endpointXUpdated"). - Ruft dann gezielt den passenden Redux-Thunk auf (z. B.
fetchGisLinesStatusThunk).
Redux Store & Thunks
-
Jeder Endpunkt besitzt:
- einen
Service(API-Fetch) - einen
Thunk(Redux-Logik) - einen
Slice(State-Verwaltung)
- einen
React UI (Leaflet Map)
- Beobachtet relevante Redux-Slices via
useSelector(). - Aktualisiert Marker, Tooltip und Popup über
createAndSetDevices()unduseDynamicDeviceLayers().
Beispiel-Endpunkte
| Endpunktname | WebSocket Event | Redux Thunk |
|---|---|---|
GisLinesStatus |
GisLinesStatusUpdated |
fetchGisLinesStatusThunk() |
GisStationsMeasurements |
GisStationsMeasurementsUpdated |
fetchGisStationsMeasurementsThunk() |
GisStationsStaticDistrict |
GisStationsStaticDistrictUpdated |
fetchGisStationsStaticDistrictThunk() |
GisStationsStatusDistrict |
GisStationsStatusDistrictUpdated |
fetchGisStationsStatusDistrictThunk() |
Vorteile
- UI aktualisiert sich nur bei echten Datenänderungen → weniger Re-Renders.
- Live-Synchronisation zwischen Datenquelle und Anzeige.
- Skalierbar für beliebige Endpunkte.
ToDo/Erweiterungen
- Automatische Reconnect-Logik für WebSocket.
- Anzeige des letzten Update-Zeitpunkts in UI.
- Logging-UI für WebSocket-Messages zur Diagnose.
Letzte Änderung:
{{heutiges Datum}}von Ismail Ali