wiki/b-reference/frontend-nyla/architecture.md

14 KiB

Frontend Nyla -- Architektur

Überblick

Frontend Nyla ist eine React-Single-Page-Application (SPA) mit TypeScript und Vite. Routing über React Router; Schichten: Presentation (Pages, Components), Business Logic (Hooks, *Logic-Module), Data Access (api.ts, Feature-API-Module), Infrastructure (Contexts, Provider, Konfiguration). PageManager lädt Seiten dynamisch (Lazy Loading, State Preservation, Lifecycle-Hooks). Authentifizierung über Azure MSAL; HTTP über Axios mit Interceptors.

Technologie-Stack (Stand UI-Doku): React 19.x, Vite 5.x, TypeScript 5.8.x, React Router DOM 7.x, Axios, @azure/msal-browser / @azure/msal-react, Framer Motion, XState, CSS Modules, React Icons.

Ordnerstruktur (src/)

Ordner Inhalt
pages/ Seiten: admin/, basedata/, billing/, settings/, views/ (workspace, commcoach, chatbot, trustee, graphicalEditor, realestate, neutralization, teamsbot)
components/ Wiederverwendbar: FormGenerator (Table, Form, Tree, List, Report), Navigation, UnifiedDataBar, FlowEditor (Graphical Editor), OnboardingAssistant
hooks/ useApiRequest (useApi.ts), useFiles, useNavigation, useConfirm, usePrompt, useResizablePanels, etc.
contexts/ FileContext, PekContext, ToastContext, WorkflowSelectionContext
api/ API-Client (api.ts) und Feature-spezifische API-Module
core/ PageManager
layouts/ Layout-Komponenten
locales/ i18n: API-basiertes Language-Loading (index.ts, types.ts), keine statischen Locale-Files
types/ TypeScript-Typen
utils/ Utility-Funktionen

Ergänzend typische Root-Dateien und Bereiche im Repo: main.tsx, App.tsx, api.ts (Root), auth/ (MSAL, ProtectedRoute), assets/ — Feature-Module unter components/ oft nach Muster: Haupt-.tsx, *.module.css, *Logic.tsx, *Types.ts, optional index.ts.

Wichtige UI-Komponenten

Komponente Zweck
UnifiedDataBar (UDB) Multi-Tab-Panel: Chats, Files, Sources — wird in Workspace, CommCoach und Graphical Editor genutzt
FormGenerator Dynamische Formulare/Tabellen aus Backend-Attribut-Definitionen (siehe formgenerator.md)
FormGeneratorTree Generische Baumkomponente mit Provider-Pattern (TreeNodeProvider), Multiselect, DnD, Inline-Editing, Scope/Neutralize, Batch-Actions; ersetzt fruehere FolderTree-Komponente (siehe formgenerator.md)
MandateNavigation Feature-Baum-Navigation mit Mandanten-Kontext
Automation2FlowEditor Konsolidierter n8n-style Flow-Builder (Graphical Editor) mit 3-Column-Layout: [UDB + Chat/Tracing] [Canvas + Header] [Nodes]
FlowCanvas Custom React Canvas fuer Workflow-Graph-Rendering mit Node-Highlighting (SSE Live-Tracing)
RunTracingPanel Live-Tracing von Workflow-Runs via SSE mit Fallback-Polling
EditorChatPanel AI Chat im Editor mit Drag&Drop-Dateianhang und Source-Picker
CanvasHeader Workflow-Metadaten, Versioning (Draft/Publish/Archive), Save-as-Template, New-from-Template
TemplatePicker Modal zur Auswahl von Workflow-Vorlagen beim Erstellen neuer Workflows
WorkspacePage AI-Workspace mit Chat, UDB, Agent-Streaming
TrusteeDataTablesView Konsolidierte Daten-Tabellen-Seite (Treuhand): 13 Tabs (Stammdaten, Lokale Daten, Konfiguration, Buchhaltungs-Daten) ueber generischen TrusteeDataTab-Wrapper, Lazy-Mount pro Tab, URL-State ?tab=<key>, read-only fuer Sync-Tabellen

Routing

  • Einstieg: main.tsx rendert App.tsx mit Providern (z. B. Sprache, Auth) und React Router (Routes / Route).
  • Geschützte Bereiche: Route-Guards (z. B. ProtectedRoute) prüfen Authentifizierung; Redirect bei fehlender Session.
  • Haupt-App: Nach Login MainLayout.tsx mit MandateNavigation (Sidebar) und <Outlet /> (React Router).
  • Seiten-Mapping: pageRegistry.tsx definiert PAGE_REGISTRY und FEATURE_REGISTRY; Seiten werden lazy geladen. core/PageManager/ enthält ergänzende Infrastruktur (State Preservation, Lifecycle-Hooks).
  • i18n: DB-backed via LanguageContext (t()-Hook). Sprachsets werden dynamisch via public API geladen (GET /api/i18n/sets/{code}). Key-Konvention: Deutscher Klartext = Key. Jeder neue/geaenderte UI-Text MUSS mit t('Deutscher Klartext') getaggt werden. t() darf NUR String-Literale enthaltent(variable) ist verboten. Werte vom Backend (Labels, Descriptions) sind bereits uebersetzt und werden direkt gerendert. Variable Interpolation: t('Text {var}', {var: 'Wert'}). Fallback: Ziel-Set → de-Set → [key] (eckige Klammern machen fehlende Uebersetzungen sichtbar). Keine statischen Locale-Files. Fuer statische Frontend-Maps (z.B. Wochentage, Monatsnamen, Status-Labels) wird t() per switch/Funktion mit Literalen aufgerufen, nicht ueber Map-Lookup.
  • TextMultilingual: Felder vom Typ TextMultilingual rendern dynamisch Eingabefelder fuer alle verfuegbaren Sprachen (aus availableLanguages). xx ist das Pflichtfeld (Quelltext). Keine hardcodierten Sprach-Codes. Sprachcodes folgen ISO 639-1 (en, de, fr, it, …).
  • Theme: global über Context; API-Requests mit Auth-Header (Interceptor in zentralem API-Client).

UI-Regeln

  • Keine Browser-Dialoge (alert / confirm / prompt) — stattdessen useConfirm() und usePrompt() Hooks
  • i18n-Pflicht: Jeder UI-Text (Label, Button, Placeholder, Tooltip, Fehlermeldung) MUSS mit t('Deutscher Klartext') getaggt werden. Hardcodierte deutsche Strings im JSX sind nicht erlaubt. Import: const { t } = useLanguage();. t() darf NUR String-Literale enthalten — nie Variablen. Backend-Werte (feature.label, role.description etc.) sind bereits uebersetzt und werden direkt gerendert.
  • Alle internen Funktionen mit _ Prefix
  • camelCase für Variablen und Funktionen

Schlüssel-Dateien

Datei / Bereich Rolle
main.tsx Application Entry Point
App.tsx Root-Komponente, Router-Setup, Provider
api.ts (Root) Axios-Instanz, Base URL, Token-Interceptor, 401-Handling
layouts/MainLayout.tsx Haupt-Shell mit MandateNavigation + Outlet
config/pageRegistry.tsx PAGE_REGISTRY, FEATURE_REGISTRY, Lazy Imports
core/PageManager/ State Preservation, Lifecycle, Caching
auth/authConfig, authProvider, ProtectedRoute MSAL, geschützte Routen
contexts/* FileContext, PekContext, Toast, Workflow-Auswahl, etc.
components/FlowEditor/editor/Automation2FlowEditor.tsx Haupt-Editor-Komponente (3-Column-Layout, State-Management)
components/FlowEditor/editor/FlowCanvas.tsx Custom Canvas mit Node-Rendering, Connections, Highlighting; CanvasNode traegt inputPorts/outputPorts
components/FlowEditor/nodes/frontendTypeRenderers/index.tsx FRONTEND_TYPE_RENDERERS Registry — generischer Renderer pro FrontendType statt pro Node-Typ
components/FlowEditor/editor/NodeConfigPanel.tsx Generischer Config-Renderer via FRONTEND_TYPE_RENDERERS (kein NODE_CONFIG_REGISTRY mehr)
components/FlowEditor/nodes/shared/graphUtils.ts fromApiGraph/toApiGraph serialisieren inputPorts/outputPorts auf CanvasNode
components/FlowEditor/nodes/shared/DataPicker.tsx Schema-basierte Pfad-Aufloesung, Transit-Chain, System-Variablen-Sektion
components/FlowEditor/context/Automation2DataFlowContext.tsx Stellt portTypeCatalog und systemVariables im Context bereit
components/FlowEditor/editor/RunTracingPanel.tsx SSE Live-Push + Canvas-Highlighting fuer Workflow-Runs
components/FlowEditor/editor/EditorChatPanel.tsx AI Chat mit Dateianhang (Drag&Drop) und Source-Picker
components/FlowEditor/editor/CanvasHeader.tsx Versioning, Template-Management, Workflow-Aktionen
components/FlowEditor/editor/TemplatePicker.tsx Template-Auswahl-Modal
pages/views/graphicalEditor/GraphicalEditorPage.tsx Feature-Seite mit KeepAlive, URL-basiertem Workflow-Loading
locales/index.ts, types.ts i18n: API-basiertes Language-Loading (DB-backed, keine statischen Files)
providers/language/LanguageContext.tsx t()-Hook mit {variable}-Interpolation, Fallback-Kette, availableLanguages
components/FormGenerator/FormGeneratorForm/FormGeneratorForm.tsx Rendert frontend_type: multilingual (TextMultilingual) dynamisch nach availableLanguages; Button „In alle Sprachen uebersetzen“ (KI via POST /api/i18n/translate-field)
pages/admin/AdminLanguagesPage.tsx Admin-Seite: Sprachset-Verwaltung (CRUD, AI-Übersetzung, UI/API-Key-Counts)
pages/admin/AdminLanguagesKeepAlive.tsx KeepAlive-Wrapper: Sprach-Seite bleibt persistent bei Seitenwechsel

Tab-Pattern fuer mehrere Modelle pro Seite

Wenn eine Feature-Seite N verwandte Modelle in eigenen Tabs zeigen soll (Beispiel: TrusteeDataTablesView mit 13 Trustee-Tabellen), gilt folgendes Muster:

  1. Pro Tab ein Wrapper-Component, das exakt einen Hook aufruft. So bleiben React Hook Rules eingehalten und inaktive Tabs fetchen keine Daten (Lazy-Mount).
  2. FormGeneratorTable direkt im Wrapper (siehe formgenerator.md -- "Bei Tabs / Wrapper-Komponenten"). Jeder Wrapper reicht die Flex-Chain (flex:1; min-height:0) durch, sonst kollabiert die Tabelle auf 0 px.
  3. URL-State via ?tab=<key> (useSearchParams). Erlaubt Deep-Links aus Notifications, Quick Actions oder Doku.
  4. Read-only-Tabs: separater Wrapper ohne Operations-Hook, readOnly={true}. Sync-Tabellen (z.B. TrusteeData*) verzichten auf Edit-/Delete-Buttons, damit der naechste Sync nicht versehentlich ueberschriebene Daten zerstoert.
  5. Tab-Bar im Stil bestehender Trustee-Tab-Seiten (TrusteeAbschlussView, TrusteeAccountingSettingsView); Gruppierung per TabGroupDef (z.B. "Stammdaten", "Lokale Daten", "Konfiguration", "Buchhaltungs-Daten") erhoeht Lesbarkeit bei vielen Tabs.
  6. Spalten-Definitionen kommen aus getModelAttributeDefinitions(...) (Backend) -- nie hardcodiert. So bleibt das UI automatisch synchron mit Pydantic-Modellaenderungen.

FlowEditor -- Typed Action Architecture (Phasen 1-5)

Seit April 2026 stuetzt sich der FlowEditor (Graphical Editor) auf eine typisierte Action-Architektur. Quellen: wiki/c-work/3-validate/2026-04-typed-action-architecture.md, Tests in frontend_nyla/src/components/FlowEditor/**/*.test.tsx.

Picker-Komponenten

Komponente Datei Zweck
RequiredAttributePicker nodes/shared/RequiredAttributePicker.tsx Auflistung + Auswahl von 0/1/N Pflicht-Attributen (featureInstanceId, connection, ...). Bei genau einer Quelle: Auto-Bind mit Override-Knopf; bei N: explizite Auswahl; bei 0: Hint "Iterieren-Vorschlag" oder Ressource fehlt.
DataPicker nodes/shared/DataPicker.tsx Strict-Type-Filter (expectedParamType) + Object-Drill-Down + *-Wildcard fuer List-Iteration. Default ist Strict-Mode (Nur kompatible-Toggle). Hard-Mismatches werden ausgeblendet, Coerce-Faelle (z.B. int -> str) bleiben sichtbar.
paramValidation.ts nodes/shared/paramValidation.ts Single source of truth fuer Pflicht-Feld-Pruefung. Liefert nodeErrors: List[NodeError] (genutzt von Save-Toast, Run-Block, Node-Highlighting).

Save / Run Gating (AC-9)

  • Save ist immer erlaubt (auch mit Pflicht-Fehlern). CanvasHeader.tsx zeigt nach Save bei Fehlern einen amber-Banner ("Gespeichert mit X Pflicht-Fehlern in Y Nodes").
  • Run wird per executeBlockedReason blockiert; der Button wechselt auf "Pflicht-Felder fehlen", behaelt aria-disabled und triggert onExecuteBlockedClick (markiert die First-Error-Node).
  • Hintergrund: executeGraph validiert serverseitig zusaetzlich (Port-Mismatch, fehlende Pflicht-Bindings) und liefert klare Fehlermeldungen falls jemand den Editor-Block umgeht.

FeatureInstanceRef im Frontend

  • featureInstanceId-Bindings werden als typisierter Envelope {$type: "FeatureInstanceRef", id, featureCode} ans Backend geschickt; das Backend persistiert sie 1:1 (Phase 5).
  • Der Picker zeigt [<featureCode>] <Label> (z.B. [trustee] Buchhaltung PWG), damit die Variante auf einen Blick erkennbar ist.
  • Legacy-Workflows (rohe UUIDs) bleiben funktionsfaehig -- die Backend-Engine migriert sie bei jedem Run automatisch (materializeFeatureInstanceRefs).

Tests (Vitest + RTL)

frontend_nyla nutzt seit Track A1 Vitest 2.x + jsdom + @testing-library/react. Die Test-Dateien liegen neben den Komponenten als *.test.tsx:

Test Datei Akzeptanzkriterium
RequiredAttributePicker (0/1/N + Override + Iterate) RequiredAttributePicker.test.tsx T5, T6
DataPicker -- strict-mode + coerce DataPicker.strict.test.tsx (in DataPicker.test.tsx) T7
DataPicker -- generic object drill-down + *-Wildcard DataPicker.drillDown.test.tsx (in DataPicker.test.tsx) T8
CanvasHeader Run/Save-Gating + Warning-Toast CanvasHeader.test.tsx T10, AC-9

Befehle: npm test (CI-Mode), npm run test:ui (Vitest UI). Konfiguration: vitest.config.ts, vitest.setup.ts.


Regeln / Invarianten

  • Feature-Organisation: UI, Logic (*Logic), Types und CSS Modules pro Feature-Modul trennen; Exporte über index.ts wo üblich.
  • Datenfluss: Pages → Feature-Komponenten → Hooks → useApi / API-Module → Gateway; Fehler nicht verschlucken, konsistente Backend-Fehlerdarstellung.
  • Performance: Seiten lazy laden; bei konfigurierten Seiten State Preservation nutzen.
  • Styling: CSS Modules, Theme über CSS-Variablen (Light/Dark) wo vorgesehen.
  • Typisierung: TypeScript durchgängig; API-Response-Typen an den Grenzen definieren.
  • Naming: Komponenten PascalCase, Hooks use*, interne Hilfsfunktionen _ + camelCase — kein snake_case in neuem Frontend-Code.