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

10 KiB
Raw Blame History

🧠 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)

  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


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)

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