277 lines
8.3 KiB
Markdown
277 lines
8.3 KiB
Markdown
|
|
# AP0.6 – Abschlussbericht Kairo Workspace UX mit minimaler Widget Registry
|
|||
|
|
|
|||
|
|
**Status:** abgeschlossen
|
|||
|
|
**Stand:** 2026-07-05
|
|||
|
|
**Branch:** `develop` · Frontend `0.6.0-ap0.6` · Backend Schema `006` (unverändert)
|
|||
|
|
**Backend-Änderungen:** keine
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Scope und Einordnung
|
|||
|
|
|
|||
|
|
AP0.6 macht Kairo erstmals als **Arbeitswerkzeug nutzbar** — ohne neue Foundation-Schicht, ohne Backend-Widget-Registry, ohne KI/MCP/Projects.
|
|||
|
|
|
|||
|
|
| Anforderung (AP0.6) | Status |
|
|||
|
|
|---------------------|--------|
|
|||
|
|
| Workspace mit Widget-Karten | ✓ |
|
|||
|
|
| Vorhabenliste + Detail | ✓ |
|
|||
|
|
| Maßnahmen CRUD in UI | ✓ |
|
|||
|
|
| Status / Priorität ändern | ✓ |
|
|||
|
|
| Actor-Zuweisung (minimal) | ✓ |
|
|||
|
|
| Meine offenen Maßnahmen | ✓ |
|
|||
|
|
| Blockierte Maßnahmen erkennbar | ✓ |
|
|||
|
|
| Erledigte filterbar/ausblenden | ✓ |
|
|||
|
|
| Frontend Widget Registry | ✓ |
|
|||
|
|
| View Registry + Navigation | ✓ |
|
|||
|
|
| Capability-bewusste UI | ✓ |
|
|||
|
|
| Loading / Error / Empty States | ✓ |
|
|||
|
|
| Vitest (Registry + Badges) | ✓ 7 Tests |
|
|||
|
|
| README UI-Doku | ✓ |
|
|||
|
|
|
|||
|
|
**Produktfrage beantwortet:** Ja — mit AP0.5-APIs kann ein Nutzer Vorhaben und Maßnahmen praktisch verwalten.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Umgesetzte Dateien
|
|||
|
|
|
|||
|
|
| Bereich | Dateien |
|
|||
|
|
|---------|---------|
|
|||
|
|
| API-Client | `frontend/src/api/client.js`, `me.js`, `initiatives.js`, `actions.js`, `actors.js` |
|
|||
|
|
| Session | `frontend/src/context/SessionContext.jsx`, `hooks/useCapabilities.js` |
|
|||
|
|
| Registry | `frontend/src/registry/widgetRegistry.js`, `viewRegistry.js` |
|
|||
|
|
| Widgets | `TenantContextWidget`, `MyOpenActionsWidget`, `BlockedActionsWidget`, `InitiativesWidget` |
|
|||
|
|
| Pages | `WorkspacePage`, `InitiativesPage`, `InitiativeDetailPage`, `AuthPanel` |
|
|||
|
|
| Components | Badges, Forms, Lists, Empty/Loading/Error |
|
|||
|
|
| Layout | `frontend/src/layout/AppLayout.jsx` |
|
|||
|
|
| Styles | `frontend/src/styles/workspace.css` |
|
|||
|
|
| App | `App.jsx`, `main.jsx` (React Router) |
|
|||
|
|
| Tests | `registry.test.js`, `badges.test.jsx` |
|
|||
|
|
| Doku | `README.md`, dieser Bericht |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Frontend-Struktur
|
|||
|
|
|
|||
|
|
```text
|
|||
|
|
frontend/src/
|
|||
|
|
api/ # HTTP-Schicht
|
|||
|
|
context/ # SessionProvider
|
|||
|
|
hooks/ # useCapabilities
|
|||
|
|
registry/ # Widget + View Registry
|
|||
|
|
widgets/ # Workspace-Karten
|
|||
|
|
pages/ # Routen
|
|||
|
|
components/ # Wiederverwendbare UI-Bausteine
|
|||
|
|
layout/ # App-Shell + Navigation
|
|||
|
|
constants/ # Status/Priority Labels
|
|||
|
|
styles/ # workspace.css
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Keine monolithische God Page — `App.jsx` nur Routing + Session.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Widget Registry
|
|||
|
|
|
|||
|
|
**Datei:** `registry/widgetRegistry.js`
|
|||
|
|
|
|||
|
|
| key | title | capability | order |
|
|||
|
|
|-----|-------|------------|-------|
|
|||
|
|
| `kairo.tenant_context` | Kontext | — | 0 |
|
|||
|
|
| `kairo.my_open_actions` | Meine offenen Maßnahmen | `kairo.action.read` | 10 |
|
|||
|
|
| `kairo.blocked_actions` | Blockierte Maßnahmen | `kairo.action.read` | 20 |
|
|||
|
|
| `kairo.active_initiatives` | Aktive Vorhaben | `kairo.initiative.read` | 30 |
|
|||
|
|
|
|||
|
|
`getWidgetsForArea('workspace', capabilities)` filtert und sortiert.
|
|||
|
|
|
|||
|
|
**Frontend-only** — keine DB, kein Drag & Drop, keine User-Layouts.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. View Registry / Navigation
|
|||
|
|
|
|||
|
|
**Datei:** `registry/viewRegistry.js`
|
|||
|
|
|
|||
|
|
| key | path | Nav | capability |
|
|||
|
|
|-----|------|-----|------------|
|
|||
|
|
| `kairo.workspace` | `/workspace` | ✓ | `kairo.action.read` |
|
|||
|
|
| `kairo.initiatives` | `/initiatives` | ✓ | `kairo.initiative.read` |
|
|||
|
|
| `kairo.initiative_detail` | `/initiatives/:id` | — | `kairo.initiative.read` |
|
|||
|
|
|
|||
|
|
`AppLayout` rendert NavLinks aus `getNavViews(capabilities)`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Workspace UX
|
|||
|
|
|
|||
|
|
Route `/workspace`:
|
|||
|
|
|
|||
|
|
- Tenant-/Actor-Kontext-Karte
|
|||
|
|
- Offene Maßnahmen (ohne `blocked` — die haben eigene Karte)
|
|||
|
|
- Blockierte Maßnahmen (gefiltert aus `/api/actions/me/open`)
|
|||
|
|
- Aktive/pausierte Vorhaben (Top 5)
|
|||
|
|
- Quick-Action „Vorhaben anlegen“ (mit `kairo.initiative.manage`)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Vorhaben-UX
|
|||
|
|
|
|||
|
|
**Liste** `/initiatives`: aktive + pausierte Vorhaben, Status/Priority-Badges, offene Maßnahmen-Zähler (parallele API-Calls pro Vorhaben).
|
|||
|
|
|
|||
|
|
**Detail** `/initiatives/:id`: Titel, Goal, Badges, Maßnahmenliste, Filter „Erledigte ausblenden“.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Maßnahmen-UX
|
|||
|
|
|
|||
|
|
- Anlegen via `ActionForm` im Detail
|
|||
|
|
- Inline Status-Dropdown (Quick-Change)
|
|||
|
|
- Vollständiges Bearbeiten (Titel, Beschreibung, Status, Priority, Assignment)
|
|||
|
|
- Erledigte (`done`/`discarded`) standardmäßig ausgeblendet
|
|||
|
|
- Offene Liste über Backend `/api/actions/me/open` — erledigte erscheinen dort nicht
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. Actor-Zuweisung
|
|||
|
|
|
|||
|
|
**Lücke:** Kein `GET /api/actors` im Backend.
|
|||
|
|
|
|||
|
|
**AP0.6-Lösung:** `api/actors.js` → `actorsFromContext()` liefert nur den aktuellen Human Actor aus `/api/me/context`.
|
|||
|
|
|
|||
|
|
`ActorSelect` zeigt Checkboxen für verfügbare Actors; Hinweistext auf AP0.7.
|
|||
|
|
|
|||
|
|
Assignments via `PUT /api/actions/{id}/assignments` — Actor-IDs, nicht User.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. Capability-bewusste UI
|
|||
|
|
|
|||
|
|
Quelle: `/api/me/entitlements` + `/api/me/context` → `useCapabilities()`.
|
|||
|
|
|
|||
|
|
| Capability | UI-Effekt |
|
|||
|
|
|------------|-----------|
|
|||
|
|
| `kairo.initiative.manage` | Button „Vorhaben anlegen“ |
|
|||
|
|
| `kairo.initiative.read` | Vorhaben-Widgets/Views |
|
|||
|
|
| `kairo.action.manage` | Maßnahme anlegen/bearbeiten, Status, Assignment |
|
|||
|
|
| `kairo.action.read` | Workspace, offene Maßnahmen |
|
|||
|
|
|
|||
|
|
Backend bleibt autoritativ — Frontend nur UX-Gates.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 11. Loading / Error / Empty States
|
|||
|
|
|
|||
|
|
Jedes Widget und jede Page nutzt `LoadingState`, `ErrorState` (mit Retry), `EmptyState` mit kontextbezogenen Texten.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 12. Responsive Verhalten
|
|||
|
|
|
|||
|
|
`workspace.css` — `@media (max-width: 640px)`:
|
|||
|
|
|
|||
|
|
- Header stapelt vertikal
|
|||
|
|
- Widget-Grid einspaltig
|
|||
|
|
- Buttons full-width (Form-Ausnahmen)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 13. Tests und Smoke-Tests
|
|||
|
|
|
|||
|
|
### Automatisiert (Vitest)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd frontend && npm run test
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
7 Tests: Registry-Inhalt, Capability-Filter, StatusBadge, PriorityBadge.
|
|||
|
|
|
|||
|
|
### Manueller Smoke-Test
|
|||
|
|
|
|||
|
|
1. Login (Dev: `lars@stommer.com`)
|
|||
|
|
2. `/workspace` — Karten laden
|
|||
|
|
3. Vorhaben anlegen
|
|||
|
|
4. Detail → Maßnahme anlegen (Self-Assignment)
|
|||
|
|
5. Status → In Arbeit → Erledigt
|
|||
|
|
6. Workspace: Maßnahme nicht mehr unter „Offen“
|
|||
|
|
7. Blockiert setzen → erscheint in „Blockierte Maßnahmen“
|
|||
|
|
|
|||
|
|
Kein Playwright im Repo — dokumentierter manueller Smoke-Test.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 14. Übernommene Muster aus Mitai
|
|||
|
|
|
|||
|
|
| Muster | Umsetzung |
|
|||
|
|
|--------|-----------|
|
|||
|
|
| Kartenbasierte Oberfläche | `widget-card`, `widget-grid` |
|
|||
|
|
| Widget-Registry-Idee | `widgetRegistry.js` (frontend-only, minimal) |
|
|||
|
|
| Status-Badges | `StatusBadge`, `PriorityBadge` |
|
|||
|
|
| Leere Zustände | `EmptyState` |
|
|||
|
|
| Loading/Error | eigene Komponenten |
|
|||
|
|
|
|||
|
|
**Nicht übernommen:** volles Widget Dashboard, Layout-Persistenz, Drag & Drop, Backend-Registry.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 15. Übernommene Muster aus Shinkan
|
|||
|
|
|
|||
|
|
| Muster | Umsetzung |
|
|||
|
|
|--------|-----------|
|
|||
|
|
| Schlankes KPI/Listen-Layout | kompakte Widget-Karten |
|
|||
|
|
| Tenant-Kontext sichtbar | `TenantContextWidget`, App-Header |
|
|||
|
|
| Capability-bewusste Nav | `getNavViews()` |
|
|||
|
|
| Robuste Frontend-Struktur | api/ + pages/ + components/ |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 16. Bewusst nicht übernommene Muster
|
|||
|
|
|
|||
|
|
- Mitai/Shinkan-Domänenlogik
|
|||
|
|
- Backend-Widget-Registry
|
|||
|
|
- Admin-Konsole, Prompt/Feature/Config UI
|
|||
|
|
- Actor-Admin-API
|
|||
|
|
- Playwright E2E (noch nicht im Stack)
|
|||
|
|
- Designsystem / UI-Library
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 17. Backend-Änderungen
|
|||
|
|
|
|||
|
|
**Keine.** AP0.5-APIs reichen aus.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 18. Abweichungen von der Spezifikation
|
|||
|
|
|
|||
|
|
| Thema | Abweichung | Begründung |
|
|||
|
|
|-------|------------|------------|
|
|||
|
|
| Actor-Liste | nur Context-Actor | kein GET /api/actors |
|
|||
|
|
| Owner Actor wählen | nicht in UI | keine Actor-List-API |
|
|||
|
|
| Open-Count Vorhaben | N+1 API-Calls | akzeptabel für MVP |
|
|||
|
|
| Playwright Smoke | manuell dokumentiert | nicht im CI-Stack |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 19. Offene UX-/Produktentscheidungen
|
|||
|
|
|
|||
|
|
1. **`GET /api/actors`** — read-only für Assignment-UI (AP0.7)?
|
|||
|
|
2. **Initiative bearbeiten in UI** — PATCH existiert, Form fehlt noch
|
|||
|
|
3. **Workspace-Refresh** — Widgets laden eigenständig; kein globales Event-Bus
|
|||
|
|
4. **Foundation AP0.5 (Audit/Admin)** — weiterhin AP0.6/0.7 backlog
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 20. Empfehlung für AP0.7
|
|||
|
|
|
|||
|
|
**Kleinster Nutzwert:** `GET /api/actors` (tenant-scoped, read, `kairo.action.read`) + ActorSelect mit echten Tenant-Actors.
|
|||
|
|
|
|||
|
|
Alternativ: **Kommentare pro Maßnahme** (aus AP0.5-Empfehlung) — erhöht Kollaboration ohne Backend-Explosion.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Referenzen
|
|||
|
|
|
|||
|
|
- AP0.5 Backend: `docs/sprints/Sprint0_AP0_5_Completion_Report_v0.2.md`
|
|||
|
|
- ADP Scope: `docs/architecture/ADP_AP0_5_Sprint0_Scope_Shift_v0.1.md`
|
|||
|
|
- Mitai: `docs/reference/design-principles/mitai/DASHBOARD_WIDGETS_DESIGN_PRINCIPLES.md`
|
|||
|
|
- Shinkan: `docs/reference/design-principles/shinkan/NAVIGATION_IA_DESIGN_PRINCIPLES.md`
|