172 lines
9.9 KiB
Markdown
172 lines
9.9 KiB
Markdown
<!-- status: done -->
|
|
<!-- lastUpdated: 2026-04-25 -->
|
|
<!-- lastReviewed: 2026-04-25 -->
|
|
<!-- owner: ai-agent -->
|
|
<!-- related: z-archive/c-work/2026-04-node-typization-audit.md, c-work/4-done/2026-04-typed-action-architecture.md, c-work/4-done/2026-04-typed-action-followups.md -->
|
|
|
|
# FeatureInstanceRef-Adapter-Migration & Graph-Editor UI-Cleanup (2026-04-25)
|
|
|
|
> Restbestand aus dem Node-Typisierungs-Audit (jetzt z-archiv).
|
|
> Ziel: keine `frontendType: "hidden"` Pflichtfelder mehr, klare UI-Texte,
|
|
> theme-konformer DataPicker, optionale Schema-Ansicht fur Sysadmins.
|
|
|
|
## Auslosender Befund
|
|
|
|
Bei der Audit-Umsetzung wurde die _strukturelle_ Korrektur (PORT_TYPE_CATALOG /
|
|
Typed Action Architecture) durchgezogen — die _Anwendung_ in den
|
|
`nodeDefinitions/*.py` jedoch nur teilweise. Trustee + Redmine fuhren
|
|
weiter `featureInstanceId: string, hidden, required=True`, was im Editor
|
|
zu **Phantom-Pflichtfeldern** ("Pflichtfelder ohne Quelle: Trustee Feature-
|
|
Instanz-ID"), unklarer Fehler-Banner und einem nicht-bedienbaren Knoten
|
|
fuhrt.
|
|
|
|
Zusatzlich zeigte der Screenshot 2026-04-25 zwei UI-Probleme die unabhangig
|
|
mitgenommen werden:
|
|
|
|
- DataPicker-Modal mit nicht lesbaren Farb-Kombinationen
|
|
- "Schema (Typ-Referenz)" und ausschweifende `description`-Texte
|
|
(`erarbeitete Dokumentenliste eines Upstream-Producers …`) in der
|
|
End-User-View
|
|
|
|
## Anpassungs-Liste (zum Abhaken)
|
|
|
|
### A. Audit archiviert ✅
|
|
|
|
- [x] `wiki/c-work/1-plan/2026-04-node-typization-audit.md` ->
|
|
`wiki/z-archive/c-work/2026-04-node-typization-audit.md`
|
|
- [x] Forward-Link auf Typed Action Architecture + dieses Track-Doc
|
|
- [x] Changelog-Eintrag
|
|
|
|
### B. Backend — `featureInstanceId` typisieren
|
|
|
|
#### B1. Neuer Frontend-Type + Endpoint
|
|
|
|
- [x] `routeFeatureGraphicalEditor.py`: neuer Endpoint
|
|
`GET /api/workflows/{instanceId}/options/feature.instance?featureCode=<code>&enabledOnly=true`
|
|
- Antwort: `{ options: [{ value: "<id>", label: "<label> ([code])" }] }`
|
|
- Auflosung uber `getRootInterface().getFeatureInstancesByMandate(mandateId, enabledOnly=True)`
|
|
- Filter `featureCode` Pflicht (sonst 400, sonst Datenflut)
|
|
- [x] `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (`NodeConfigPanel.tsx`) erweitert: `'featureInstance'`
|
|
|
|
#### B2. Trustee-Nodes (5 Stuck) — `gateway/.../nodeDefinitions/trustee.py`
|
|
|
|
| Node | aktuell | neu |
|
|
|-------------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
|
|
| `trustee.refreshAccountingData` | `featureInstanceId: string, hidden, required` | `featureInstanceId: FeatureInstanceRef[trustee], frontendType: featureInstance, frontendOptions: {featureCode: trustee}` |
|
|
| `trustee.extractFromFiles` | dito | dito |
|
|
| `trustee.processDocuments` | dito; `documentList` description aufraumen (Dev-Justifikation) | dito + description = `t("Dokumentenliste — gebunden via DataRef.")` |
|
|
| `trustee.syncToAccounting` | dito; `documentList` ebenfalls | dito |
|
|
| `trustee.queryData` | dito | dito |
|
|
|
|
Alle 5 Nodes umgesetzt via wiederverwendbarem `_TRUSTEE_INSTANCE_PARAM`-Dict
|
|
(siehe `trustee.py`). Bestaetigt durch
|
|
`tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`.
|
|
|
|
#### B3. Redmine-Nodes (6 Stuck) — `gateway/.../nodeDefinitions/redmine.py`
|
|
|
|
- [x] `redmine.readTicket`
|
|
- [x] `redmine.listTickets`
|
|
- [x] `redmine.createTicket`
|
|
- [x] `redmine.updateTicket`
|
|
- [x] `redmine.getStats`
|
|
- [x] `redmine.runSync`
|
|
|
|
Alle 6 via `_REDMINE_INSTANCE_PARAM`-Dict, `featureInstanceId` ->
|
|
`FeatureInstanceRef[redmine]` mit
|
|
`frontendType: "featureInstance", frontendOptions: {"featureCode": "redmine"}`.
|
|
|
|
#### B4. Beobachtete `frontendType: hidden`-Restbestande (out-of-scope, in
|
|
2026-05 oder eigenem Track-Doc adressieren — hier nur dokumentiert)
|
|
|
|
| Datei | Param | Typ aktuell | Anmerkung |
|
|
|------------------|----------------|-------------|-----------------------------------------------------------------|
|
|
| `ai.py` | `documentList` | `string` | Korrekt: ueber `dataRef` gebunden, `string` lugt nur den DataPicker |
|
|
| `email.py` | `documentList`, `emailContent` | `string` | dito |
|
|
| `sharepoint.py` | `content` | `string` | dito |
|
|
| `clickup.py` | `content` | `string` | dito |
|
|
| `context.py` | `documentList` | `string` | dito |
|
|
| `file.py` | `context` | `string` | dito |
|
|
|
|
> Diese Faelle sind _nicht_ Phantom-Pflichtfelder (sie sind
|
|
> entweder optional oder werden korrekt via DataRef gebunden), losen aber
|
|
> die "Schema (Typ-Referenz)"-Verwirrung mit aus. Strukturell sind sie
|
|
> Kandidaten fur `frontendType: "dataRef"` mit prazisem `type:
|
|
> "List[ActionDocument]"` etc. — eigene Iteration.
|
|
|
|
### C. Frontend — Renderer & Safety Net
|
|
|
|
- [x] `FeatureInstancePicker.tsx` (Modell: `ConnectionPicker`):
|
|
- Lade `/api/workflows/{instanceId}/options/feature.instance?featureCode=<code>`
|
|
- 0 Ergebnisse: Hinweis _"Keine {code}-Instanz im aktiven Mandanten — bitte in der Admin-Konsole anlegen."_
|
|
- 1 Ergebnis: Auto-Pick (`autoSingleRef`-Guard)
|
|
- N Ergebnisse: `<select>` mit Default-Option `"{code}-Mandant wählen"`
|
|
- [x] `frontendTypeRenderers/index.tsx`:
|
|
- Import + Eintrag in `FRONTEND_TYPE_RENDERERS`: `featureInstance: FeatureInstancePicker`
|
|
- Eintrag in `_LEGACY_RENDERERS_THAT_HANDLE_BINDINGS` (im `NodeConfigPanel.tsx`-Set)
|
|
- [x] **Safety Net direkt in `paramValidation.ts/findRequiredErrors`**:
|
|
hidden-Pflicht-Parameter werden zentral gefiltert, damit Banner,
|
|
FlowCanvas-Badges und Run-Button-`blockedReason` synchron bleiben.
|
|
Zusatzlich `_shouldUseRequiredPicker` (`NodeConfigPanel.tsx`) liefert
|
|
fruh `false` fur `frontendType === 'hidden'` und die Render-Schleife
|
|
uberspringt die Zeile komplett (`return null`).
|
|
|
|
### D. Editor-Verbose-Toggle (Issue 1)
|
|
|
|
- [x] `CanvasHeader.tsx`:
|
|
- Sysadmin-Check via `getUserDataCache()?.isSysAdmin === true`
|
|
- Checkbox _"Schema-Details"_ rechts neben Workspace-Button,
|
|
nur wenn Sysadmin (gestrichelter Rahmen, Tooltip mit Erklaerung)
|
|
- Wert in `localStorage('flowEditor.verboseSchema')`
|
|
- [x] `Automation2FlowEditor.tsx`: `verboseSchema` state + persist-effekt,
|
|
als Prop runtergereicht an `CanvasHeader` und `NodeConfigPanel`
|
|
- [x] `NodeConfigPanel.tsx`: `<details>`-Block "Schema (Typ-Referenz, Sysadmin-
|
|
Ansicht)" und Parameter-Typ-Badges nur, wenn `verboseSchema === true`.
|
|
PortField-Liste + Header-Spans zusatzlich auf CSS-Variablen umgestellt.
|
|
|
|
### E. DataPicker-Theming (Issue 3)
|
|
|
|
- [x] `DataPicker.tsx`: alle hardcoded Farben (`#555`, `#888`, `#999`, `#666`)
|
|
-> CSS-Variablen (`var(--text-secondary)`, `var(--text-tertiary)`,
|
|
`var(--bg-secondary)`, `var(--border-color)`)
|
|
- [x] Inline-Tags (`expectedParamType`-Badge, "Nur kompatible"-Label,
|
|
Schema-Hint, Type-Hint hinter Leaves) auf CSS-Klassen
|
|
`dataPickerLeafType`, `dataPickerNodeSchemaHint` umgezogen
|
|
- [x] `Automation2FlowEditor.module.css`:
|
|
- Hover-Safety-Net `.dataPickerLeaf:hover * { color: inherit; }` —
|
|
keine grauen Type-Hints mehr auf blauem Hover-Hintergrund
|
|
- Neue `.dataPickerLeafType`, `.dataPickerNodeSchemaHint`,
|
|
`.dataPickerIterateBtn` mit theme-konformen Variablen
|
|
|
|
### F. Banner-Klartext (Issue 4)
|
|
|
|
- [x] `NodeConfigPanel.tsx`: Banner _"Pflichtfelder ohne Quelle"_ zeigt
|
|
jetzt `param.name` (kurze Maschinenkennung), die volle Beschreibung
|
|
hangt als mehrzeiliger `title=`-Tooltip am Banner
|
|
- [x] `RequiredAttributePicker.tsx`: nutzt `getLabel(param.description)`
|
|
bereits korrekt; Justifikationen (`erarbeitete Dokumentenliste …`) sind
|
|
fortan nur noch eine Datenfrage in den `nodeDefinitions` und betreffen
|
|
diesen Banner nicht mehr (description-Saeuberung in B2/B3 erledigt)
|
|
|
|
### G. Tests
|
|
|
|
- [x] `gateway/tests/unit/graphicalEditor/test_featureInstanceRef_node_definitions.py`:
|
|
parametrized fuer alle Trustee+Redmine-Nodes — Typ ist
|
|
`FeatureInstanceRef[<code>]`, frontendType `featureInstance`,
|
|
`frontendOptions.featureCode` korrekt; plus Regression-Guard gegen
|
|
Re-Einfuehrung der `string + hidden`-Form (13 Testfaelle)
|
|
- [x] `gateway/tests/unit/graphicalEditor/test_route_options_feature_instance.py`:
|
|
Smoke-Test, dass der Endpoint `GET /api/workflows/{instanceId}/options/feature.instance`
|
|
registriert ist und `featureCode` Pflicht ist (2 Testfaelle)
|
|
- [x] `frontend_nyla/.../paramValidation.test.ts`: neuer Fall
|
|
_"skips required params with frontendType='hidden' (UI safety net)"_
|
|
- [ ] (Optional, Folge-Iteration) FeatureInstancePicker.test.tsx mit msw
|
|
fur 0/1/N-Antworten; aktuell durch das Renderer-Pattern abgedeckt
|
|
(ConnectionPicker hat dasselbe Modell, dort existieren Smoke-Tests)
|
|
|
|
### H. Wrap-up
|
|
|
|
- [x] Track-Doc nach `c-work/4-done/` verschieben
|
|
- [x] Eintrag in `c-work/_CHANGELOG.md`
|
|
- [ ] (Folge-Aufgabe) `b-reference/gateway/workflow.md` um Abschnitt
|
|
_"FeatureInstanceRef adapter binding"_ erweitern; eigenes Mini-Track
|
|
oder bei naechster Workflow-Doku-Iteration mitnehmen
|