200 lines
6.7 KiB
Markdown
200 lines
6.7 KiB
Markdown
# Ka-Note — Entitäten & Datenmodell
|
||
|
||
## Hierarchie
|
||
|
||
```
|
||
Kontext (AgendaContext) z.B. "JF Team Sysadmins", "Project TISAX"
|
||
└─ Thema (Topic) z.B. "TISAX: Sperren Produktionsrechner"
|
||
└─ Eintrag (HistoryEntry) z.B. "Hr. Müller angerufen. Server down."
|
||
└─ Bewertung (Rating) z.B. STEFE gibt 3/4
|
||
```
|
||
|
||
---
|
||
|
||
## Entitäten im Detail
|
||
|
||
### 1. Kontext (AgendaContext)
|
||
|
||
Oberster Container. Gruppiert Themen nach Anlass.
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `id` | UUID (Sonderfall: `"daily-log"` ist hartkodiert) |
|
||
| `name` | Anzeigename |
|
||
| `type` | `meeting` · `project` · `person` |
|
||
| `sortOrder` | Reihenfolge in der Sidebar |
|
||
| `meta` | Typ-abhängig: ProjectMeta oder PersonMeta |
|
||
| `archivedAt` | Archiviert (soft) |
|
||
|
||
**Drei Typen:**
|
||
|
||
| Typ | Zweck | Meta-Felder |
|
||
|-----|-------|-------------|
|
||
| `meeting` | Regelmeetings, Daily Log | — |
|
||
| `project` | Projektbezogene Themen | status, owner, links |
|
||
| `person` | Personenbezogene Themen | fullName, email, phone, duSince |
|
||
|
||
**Sonder-Kontext:** `daily-log` — immer vorhanden, Standard-Inbox, immer Meeting-Modus.
|
||
|
||
---
|
||
|
||
### 2. Thema (Topic)
|
||
|
||
Ein Diskussionspunkt / Agenda-Item / Aufgabenblock innerhalb eines Kontexts.
|
||
**Bündelt mehrere Einträge (Notizen).**
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `id` | UUID |
|
||
| `contextId` | Verweis auf übergeordneten Kontext |
|
||
| `title` | Titel des Themas |
|
||
| `status` | `active` · `snoozed` · `done` |
|
||
| `snoozeUntil` | Datum, ab dem snoozed-Thema wieder erscheint |
|
||
| `sortOrder` | Reihenfolge innerhalb des Kontexts |
|
||
| `isNew` | Zeigt grünes "NEU"-Badge bis erster Eintrag erstellt |
|
||
|
||
**Status-Bedeutung:**
|
||
|
||
| Status | Bedeutung |
|
||
|--------|-----------|
|
||
| `active` | Offen, wird angezeigt |
|
||
| `snoozed` | Versteckt bis `snoozeUntil`-Datum |
|
||
| `done` | Erledigt / archiviert |
|
||
|
||
**Sonder-Themen (automatisch, versteckt):**
|
||
- `daily-log-journal` — Journal-Einträge im Daily Log
|
||
- `{contextId}-notes` — Freie Notizen je Projekt/Person
|
||
|
||
---
|
||
|
||
### 3. Eintrag (HistoryEntry)
|
||
|
||
Eine einzelne, datierte Notiz innerhalb eines Themas. Markdown-formatiert.
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `id` | UUID |
|
||
| `topicId` | Verweis auf übergeordnetes Thema |
|
||
| `date` | Datum (YYYY-MM-DD) |
|
||
| `text` | Markdown-Inhalt mit Inline-Tags |
|
||
| `sortOrder` | Reihenfolge (neueste oben) |
|
||
| `linkedContextId` | Optionaler Verweis auf anderen Kontext |
|
||
| `doneAt` | Erledigt-Zeitstempel (toggle) |
|
||
|
||
**Inline-Tags im Text:**
|
||
|
||
| Syntax | Zweck | Beispiel |
|
||
|--------|-------|---------|
|
||
| `-> NAME` | Zuweisung an Person | `-> STEFE` |
|
||
| `@P:PROJEKT` | Projekt-Referenz | `@P:TISAX` |
|
||
| `@NAME` | Person erwähnen | `@CHFI` |
|
||
|
||
---
|
||
|
||
### 4. Bewertung (Rating)
|
||
|
||
Bewertung eines Eintrags durch eine Person (1–4 Skala).
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `id` | UUID |
|
||
| `topicId` | Verweis auf Thema |
|
||
| `historyEntryId` | Verweis auf bewerteten Eintrag |
|
||
| `personName` | Name des Bewertenden |
|
||
| `value` | `1` · `2` · `3` · `4` |
|
||
|
||
---
|
||
|
||
## Zusammenfassung: "Thema anlegen" vs. "Eintrag hinzufügen"
|
||
|
||
| Aktion | Erzeugt | Was passiert |
|
||
|--------|---------|-------------|
|
||
| **Thema anlegen** | Topic | Neuer Diskussionspunkt/Block. Kann danach beliebig viele Einträge enthalten. Erscheint mit "NEU"-Badge. |
|
||
| **Eintrag hinzufügen** | HistoryEntry | Einzelne datierte Notiz innerhalb eines bestehenden Themas. Markdown mit Inline-Tags. |
|
||
|
||
**Kurz:** Ein Thema ist der Ordner, ein Eintrag ist das Blatt darin.
|
||
|
||
---
|
||
|
||
## Querschnittliche Konzepte
|
||
|
||
### Soft-Delete
|
||
Nichts wird hart gelöscht. Stattdessen wird `deletedAt` gesetzt. Ermöglicht Wiederherstellung und Sync.
|
||
|
||
### Basis-Felder (SyncEntity)
|
||
Jede Entität hat: `id`, `updatedAt`, `deletedAt`, `version`.
|
||
|
||
### Session-State (nicht persistiert)
|
||
- `processedInCurrentSession` — Thema wurde in laufender Sitzung besprochen (sessionStorage, verschwindet bei Tab-Schließung)
|
||
- `isCollapsed` — UI-only, ob Thema-Karte eingeklappt ist (nur im Svelte-Store)
|
||
|
||
### Modi
|
||
- **Prep-Modus** — Vorbereitung: Themen anlegen, Einträge schreiben
|
||
- **Meeting-Modus** — Durchführung: Themen als besprochen markieren, aufteilen in "Aktuell" / "Bereits besprochen"
|
||
|
||
---
|
||
|
||
## Datenspeicherung
|
||
|
||
### Client: IndexedDB via Dexie.js
|
||
|
||
Alle Daten liegen **lokal im Browser** in einer IndexedDB-Datenbank.
|
||
|
||
| Eigenschaft | Wert |
|
||
|-------------|------|
|
||
| DB-Name | `ka-note` |
|
||
| Library | Dexie.js v4 |
|
||
| Schema-Version | 5 |
|
||
| Schema-Datei | `client/src/lib/db/schema.ts` |
|
||
|
||
**Tabellen & Indizes:**
|
||
|
||
| Tabelle | Indizes | Zweck |
|
||
|---------|---------|-------|
|
||
| `contexts` | `id, type, sortOrder, deletedAt, archivedAt` | Kontexte |
|
||
| `topics` | `id, contextId, status, sortOrder, deletedAt` | Themen |
|
||
| `historyEntries` | `id, topicId, date, sortOrder, deletedAt, linkedContextId, doneAt` | Einträge |
|
||
| `ratings` | `id, topicId, historyEntryId, personName, deletedAt` | Bewertungen |
|
||
| `syncMeta` | `id, entityType, entityId, synced` | Sync-Status (0=unsynced, 1=synced) |
|
||
| `imageBlobs` | `id, createdAt` | Bilder als Binärdaten in IndexedDB |
|
||
|
||
**Reaktive Abfragen:** Svelte-Stores nutzen Dexie `liveQuery` (`client/src/lib/stores/agenda.ts`) — UI aktualisiert sich automatisch bei DB-Änderungen.
|
||
|
||
**CRUD-Schicht:** `client/src/lib/db/repositories.ts` — alle Lese-/Schreiboperationen.
|
||
|
||
**Seed-Daten:** `client/src/lib/db/seed.ts` — Beispieldaten beim ersten Start.
|
||
|
||
### Server: SQLite via Hono
|
||
|
||
| Eigenschaft | Wert |
|
||
|-------------|------|
|
||
| Framework | Hono v4 + @hono/node-server |
|
||
| Datenbank | SQLite |
|
||
| DB-Dateipfad (Docker) | `/data/ka-note.db` |
|
||
| Env-Variable | `DATABASE_PATH` |
|
||
| Port | 3001 |
|
||
|
||
**Aktueller Stand:** Der Server stellt bisher nur einen Health-Endpoint bereit (`GET /api/health`). Drizzle ORM und Sync-Endpunkte sind noch nicht implementiert.
|
||
|
||
**Docker-Volume:** Die SQLite-Datei wird über ein Docker-Volume (`server-data`) persistiert, sodass Daten Container-Neustarts überleben.
|
||
|
||
### Sync-Mechanismus (in Entwicklung)
|
||
|
||
Infrastruktur vorbereitet, aber noch nicht aktiv:
|
||
|
||
- **SyncMeta-Tabelle** im Client trackt pro Entität, ob sie synchronisiert ist (`synced: 0|1`)
|
||
- **`version`-Feld** auf jeder Entität für Konflikterkennung
|
||
- **`updatedAt`-Timestamp** (ISO 8601) für Reihenfolge
|
||
- **Soft-Delete** ermöglicht sichere Sync-Abgleichung (gelöschte Einträge bleiben als Marker erhalten)
|
||
|
||
### Session-Speicher (flüchtig)
|
||
|
||
| Speicher | Key | Inhalt | Lebensdauer |
|
||
|----------|-----|--------|-------------|
|
||
| sessionStorage | `ka-note-processed` | IDs besprochener Themen | Bis Tab geschlossen |
|
||
| Svelte-Store (Memory) | — | Collapsed-Status der Themen-Karten | Bis Seite neu geladen |
|
||
|
||
### Bilder
|
||
|
||
Bilder werden als Blobs direkt in IndexedDB gespeichert (Tabelle `imageBlobs`). Im Markdown-Text werden sie über `ka-img:{imageId}` referenziert. Verwaltung in `client/src/lib/db/imageStore.ts`.
|