Files
nodeMap/docs/architecture.md
ISA 9a2b438eaf feat: basePath-Konfiguration von .env in config.json verschoben
basePath wird jetzt in config.json gepflegt statt als NEXT_PUBLIC_BASE_PATH in .env.*
Alle relevanten Code-Stellen lesen basePath dynamisch aus config.json
Dokumentation und Beispiele in Markdown-Dateien entsprechend angepasst
Erhöhte Flexibilität für Deployments ohne Rebuild
2025-08-20 08:42:24 +02:00

314 lines
10 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- /docs/architecture.md -->
# 🧠 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)
```mermaid
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)
1. Leaflet-Karte lädt bei `MapComponent` Mounting
2. Redux-Thunk `fetchPoiMarkersThunk` wird ausgelöst
3. Thunk ruft `fetchPoiDataService.js` (DB) oder Webservice (IIS) auf
4. Ergebnisse werden im Slice `readPoiMarkersStoreSlice` gespeichert
5. Komponenten lesen POI-Daten über `useSelector(...)` aus dem Store
6. 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 `/talas5` ist optional und wird jetzt in `public/config.json` als `basePath` gepflegt
werden.
Die Konfiguration erfolgt je nach Umgebung über:
- `.env.development` für lokale Entwicklung
- `.env.production` für produktiven Einsatz
- **Rechteabhängige UI:**
Funktionen (z.B. POI bearbeiten) basieren auf Benutzerrechten (`IdRight`) vom Server.
- **Zentrale Komponentensteuerung:**
Komponenten wie `MapLayersControlPanel` oder `CoordinatePopup` kontrollieren 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
- [`build-and-deploy.md`](./build-and-deploy.md)
- [`env.local.schema.md`](./env.local.schema.md)
- [`redux/slices/`](./redux/slices/)
- [`services/webservice/`](./services/webservice/)
---
## Dynamische Layer-Verwaltung mit Redux
```mermaid
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.
```mermaid
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
```mermaid
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)
### React UI (Leaflet Map)
- Beobachtet relevante Redux-Slices via `useSelector()`.
- Aktualisiert Marker, Tooltip und Popup über `createAndSetDevices()` und
`useDynamicDeviceLayers()`.
## 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
---
[Zurück zur Übersicht](README.md)