Proposals: varslingssystem + universell input
Varsling: notification-noder i grafen, trigger ved edge-opprettelse/ nevnelse/oppgave. WebSocket toast + ulest-badge + valgfri epost. Universell input: én TipTap-komponent med kontekst-drevne moduser (chat/forum/editor/code). Markup-bytte (WYSIWYG/markdown/LaTeX). Draft-caching i localStorage + valgfri graf-synk for kryssenhets. Integrert medieinput og inline-handlinger (@mentions, [[lenker]]). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1a63ad4e7e
commit
44ec243be8
2 changed files with 289 additions and 0 deletions
214
docs/proposals/universell_input.md
Normal file
214
docs/proposals/universell_input.md
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
# Proposal: Universell input — én editor, alle kontekster
|
||||||
|
|
||||||
|
## Konsept
|
||||||
|
|
||||||
|
Én TipTap-basert input-komponent som tilpasser seg konteksten.
|
||||||
|
Kompakt i chat, trådet i forum, fullskjerm i editor. Brukeren
|
||||||
|
velger markup-modus (WYSIWYG, markdown, LaTeX). Usendt innhold
|
||||||
|
caches automatisk.
|
||||||
|
|
||||||
|
## Problemstilling
|
||||||
|
|
||||||
|
I dag har vi separate input-komponenter for ulike kontekster:
|
||||||
|
- Chat: enkel textarea med enter-sender
|
||||||
|
- NodeEditor (slettet): TipTap med tittel + innhold
|
||||||
|
- EditorTrait: TipTap med toolbar
|
||||||
|
|
||||||
|
Disse er inkonsistente. Brukeren lærer tre forskjellige
|
||||||
|
input-mønstre. Og ingen av dem cacher usendt innhold.
|
||||||
|
|
||||||
|
## Modell: én komponent, kontekst-drevne moduser
|
||||||
|
|
||||||
|
```svelte
|
||||||
|
<UniversalInput
|
||||||
|
mode="chat" <!-- chat | forum | editor | code -->
|
||||||
|
context={nodeId} <!-- for draft-caching -->
|
||||||
|
onSubmit={send}
|
||||||
|
placeholder="Skriv en melding..."
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Moduser
|
||||||
|
|
||||||
|
| Modus | Utseende | Oppførsel |
|
||||||
|
|-------|----------|-----------|
|
||||||
|
| `chat` | Kompakt, én linje (utvider seg) | Enter = send, Shift+Enter = linjeskift |
|
||||||
|
| `forum` | Tittel-felt + brødtekst | Knapp = post, mer plass |
|
||||||
|
| `editor` | Full toolbar, ingen send-knapp | Auto-lagring, kontinuerlig |
|
||||||
|
| `code` | Monospace, syntax highlighting | Tab = indent, ingen auto-format |
|
||||||
|
|
||||||
|
### Smart default per kontekst
|
||||||
|
|
||||||
|
Konteksten bestemmer default-modus:
|
||||||
|
- ChatTrait → `chat`
|
||||||
|
- ForumTrait → `forum`
|
||||||
|
- EditorTrait → `editor`
|
||||||
|
- Frittstående → `editor`
|
||||||
|
|
||||||
|
Men brukeren kan alltid bytte. Skriv mye i chat? Klikk
|
||||||
|
"utvid" → midlertidig editor-modus. Send tilbake som melding.
|
||||||
|
|
||||||
|
## Markup-moduser
|
||||||
|
|
||||||
|
Samme underliggende TipTap-dokument, tre visninger:
|
||||||
|
|
||||||
|
### WYSIWYG (default)
|
||||||
|
- Det du ser er det du får
|
||||||
|
- Toolbar med formatering (bold, italic, lenker, lister, bilder)
|
||||||
|
- Mest tilgjengelig for de fleste
|
||||||
|
|
||||||
|
### Markdown
|
||||||
|
- Kildekode-visning med markdown-syntaks
|
||||||
|
- Forhåndsvisning ved siden av (split) eller toggle
|
||||||
|
- For de som tenker i markdown
|
||||||
|
|
||||||
|
### LaTeX
|
||||||
|
- Matematisk notasjon, formler
|
||||||
|
- KaTeX-rendering i forhåndsvisning
|
||||||
|
- Kanskje mest relevant i editor-modus
|
||||||
|
|
||||||
|
Brukeren velger sin preferanse — lagres i
|
||||||
|
`metadata.preferences.input_mode`. Kan overrides per kontekst.
|
||||||
|
|
||||||
|
### Bytte mellom moduser
|
||||||
|
|
||||||
|
Knapp i input-feltet: `[W]` / `[M]` / `[L]`
|
||||||
|
Bytter visning, dokumentet konverteres automatisk.
|
||||||
|
TipTap sin interne representasjon er den samme uansett.
|
||||||
|
|
||||||
|
## Draft-caching
|
||||||
|
|
||||||
|
### Lokal cache (localStorage)
|
||||||
|
|
||||||
|
Usendt innhold lagres automatisk, knyttet til kontekst:
|
||||||
|
|
||||||
|
```
|
||||||
|
draft:chat:redaksjonen-uuid → "Jeg tenker vi bør..."
|
||||||
|
draft:forum:redaksjonen-uuid:ny-tråd → { title: "Forslag", body: "..." }
|
||||||
|
draft:editor:artikkel-uuid → { document: "..." }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Lagres ved hvert tastetrykk (debounced, 500ms)
|
||||||
|
- Gjenopprettes når du navigerer tilbake
|
||||||
|
- Slettes når innholdet sendes/publiseres
|
||||||
|
- Viser diskret indikator: "Utkast lagret"
|
||||||
|
|
||||||
|
### Graf-synk (valgfritt, for kryssenhets)
|
||||||
|
|
||||||
|
For lengre tekster (editor-modus) kan draftet lagres som en
|
||||||
|
node i grafen:
|
||||||
|
|
||||||
|
```
|
||||||
|
node_kind: 'draft'
|
||||||
|
metadata: { context_id: "artikkel-uuid", auto_saved: true }
|
||||||
|
belongs_to → kontekst-noden
|
||||||
|
created_by → brukeren
|
||||||
|
```
|
||||||
|
|
||||||
|
Synkroniseres via WebSocket. Åpner du editoren på telefonen
|
||||||
|
ser du det du skrev på PC-en. Eksplisitt handling for å
|
||||||
|
publisere/sende — draftet er privat til det.
|
||||||
|
|
||||||
|
## Medieinput integrert
|
||||||
|
|
||||||
|
Universell input inkluderer alle input-modaliteter:
|
||||||
|
|
||||||
|
| Modalitet | Mekanisme |
|
||||||
|
|-----------|-----------|
|
||||||
|
| Tekst | Tastatur, standard |
|
||||||
|
| Bilde | Paste fra clipboard, drag-and-drop, kamera |
|
||||||
|
| Lyd | Opptak-knapp, voice memo |
|
||||||
|
| Video | Opptak-knapp (webcam/skjerm) |
|
||||||
|
| Fil | Drag-and-drop, filvelger |
|
||||||
|
| Tegning | Skisse-modus (enkel canvas) |
|
||||||
|
| Lokasjon | "Del posisjon"-knapp |
|
||||||
|
| Lenke | Paste URL → auto-preview med synops-clip |
|
||||||
|
|
||||||
|
Alt ender som noder i grafen. Tekst = innholds-node.
|
||||||
|
Bilde/lyd/video = media-node med CAS-lagring.
|
||||||
|
|
||||||
|
## Inline-handlinger
|
||||||
|
|
||||||
|
Mens du skriver kan du trigge handlinger:
|
||||||
|
|
||||||
|
- `@person` → nevne noen (autocomplete fra kontakter)
|
||||||
|
- `@bot` → AI-assistent svarer
|
||||||
|
- `/kommando` → slash-kommandoer (som i chat-apper)
|
||||||
|
- `[[nodetittel]]` → lenke til eksisterende node
|
||||||
|
- Paste URL → auto-embed med forhåndsvisning
|
||||||
|
|
||||||
|
## Tilbakemeldings-indikatorer
|
||||||
|
|
||||||
|
Input-feltet viser tilstand:
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────┐
|
||||||
|
│ Skriv en melding... │
|
||||||
|
│ │
|
||||||
|
│ 📎 🎤 [W] [Send] │
|
||||||
|
│ Utkast lagret · 142 tegn │
|
||||||
|
└─────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- 📎 = legg ved fil/bilde
|
||||||
|
- 🎤 = voice memo
|
||||||
|
- [W] / [M] / [L] = markup-modus
|
||||||
|
- Tegnteller (valgfritt)
|
||||||
|
- "Utkast lagret" / "Lagrer..." / "Ikke lagret"
|
||||||
|
|
||||||
|
## Komponent-arkitektur
|
||||||
|
|
||||||
|
```
|
||||||
|
UniversalInput (wrapper)
|
||||||
|
├── TipTapEditor (kjerne — samme instans uansett modus)
|
||||||
|
├── ModeSelector (chat/forum/editor/code)
|
||||||
|
├── MarkupToggle (WYSIWYG/markdown/LaTeX)
|
||||||
|
├── MediaButtons (fil, opptak, kamera, tegning, lokasjon)
|
||||||
|
├── DraftManager (localStorage + valgfri graf-synk)
|
||||||
|
├── MentionProvider (@person, @bot, [[node]])
|
||||||
|
└── ActionBar (send/post/lagre + indikatorer)
|
||||||
|
```
|
||||||
|
|
||||||
|
TipTap-instansen er den samme — wrapper-en endrer layout,
|
||||||
|
toolbar-synlighet og submit-oppførsel basert på modus.
|
||||||
|
|
||||||
|
## Implementering
|
||||||
|
|
||||||
|
### Fase 1: Konsolidert input
|
||||||
|
- UniversalInput-komponent med chat/editor-modus
|
||||||
|
- Erstatt eksisterende input i ChatTrait og EditorTrait
|
||||||
|
- Draft-caching i localStorage
|
||||||
|
|
||||||
|
### Fase 2: Forum-modus
|
||||||
|
- Tittel + brødtekst layout
|
||||||
|
- Integrert med ForumTrait (fra chat/forum-dualitet)
|
||||||
|
|
||||||
|
### Fase 3: Markup-moduser
|
||||||
|
- Markdown-visning med forhåndsvisning
|
||||||
|
- LaTeX via KaTeX
|
||||||
|
- Brukerpreferanse
|
||||||
|
|
||||||
|
### Fase 4: Medieinput
|
||||||
|
- Paste-deteksjon for bilder
|
||||||
|
- Opptak-knapper (lyd, video)
|
||||||
|
- Fil-opplasting
|
||||||
|
|
||||||
|
### Fase 5: Inline-handlinger
|
||||||
|
- @mentions med autocomplete
|
||||||
|
- [[node-lenker]] med søk
|
||||||
|
- URL auto-embed
|
||||||
|
|
||||||
|
### Fase 6: Kryssenhets drafts
|
||||||
|
- Draft-noder i grafen
|
||||||
|
- WebSocket-synkronisering
|
||||||
|
|
||||||
|
## Hva som eksisterer allerede
|
||||||
|
|
||||||
|
- TipTap-editor i EditorTrait (✓)
|
||||||
|
- Voice memo-opptak (✓)
|
||||||
|
- Bilde-paste i TipTap (✓)
|
||||||
|
- @bot-trigger i chat (✓)
|
||||||
|
- synops-clip for URL-parsing (✓)
|
||||||
|
- CAS for medielagring (✓)
|
||||||
|
|
||||||
|
Hovedsakelig konsolidering og utvidelse, ikke nybygg.
|
||||||
75
docs/proposals/varsling.md
Normal file
75
docs/proposals/varsling.md
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Proposal: Varslingssystem
|
||||||
|
|
||||||
|
## Konsept
|
||||||
|
|
||||||
|
Når noe skjer som angår deg — ny samtale, ny melding, ny oppgave,
|
||||||
|
noen nevner deg — får du et varsel. Varsler er noder i grafen,
|
||||||
|
ikke en separat mekanisme.
|
||||||
|
|
||||||
|
## Varsling som noder
|
||||||
|
|
||||||
|
```
|
||||||
|
node_kind: 'notification'
|
||||||
|
metadata: {
|
||||||
|
type: "added_to_conversation",
|
||||||
|
actor_id: "vegard-uuid",
|
||||||
|
target_id: "redaksjonen-uuid",
|
||||||
|
seen: false
|
||||||
|
}
|
||||||
|
belongs_to → din person-node
|
||||||
|
```
|
||||||
|
|
||||||
|
Fordeler:
|
||||||
|
- Varsler er søkbare, filtrerbare, arkiverbare
|
||||||
|
- Samme PG NOTIFY → WebSocket-pipeline som alt annet
|
||||||
|
- Ingen ny infrastruktur
|
||||||
|
|
||||||
|
## Trigger-hendelser
|
||||||
|
|
||||||
|
| Hendelse | Varsel |
|
||||||
|
|----------|--------|
|
||||||
|
| Lagt til i samtale | "Vegard la deg til i Redaksjonen" |
|
||||||
|
| Nevnt i melding (@Trond) | "Vegard nevnte deg i Redaksjonen" |
|
||||||
|
| Ny melding i samtale (valgfritt) | "3 nye meldinger i Redaksjonen" |
|
||||||
|
| Tildelt oppgave | "Vegard tildelte deg: Fiks lyden" |
|
||||||
|
| Innsendt artikkel behandlet | "Artikkelen din ble godkjent" |
|
||||||
|
| Orkestrering fullført | "Transkribering ferdig" |
|
||||||
|
|
||||||
|
## Leveringskanaler
|
||||||
|
|
||||||
|
Samme varsel kan leveres via flere kanaler:
|
||||||
|
|
||||||
|
- **WebSocket → toast i appen** (alltid, sanntid)
|
||||||
|
- **Ulest-badge i Mine ting** (alltid)
|
||||||
|
- **Epost** (konfigurerbart per bruker i metadata.preferences)
|
||||||
|
- **Lyd-ping** (konfigurerbart)
|
||||||
|
|
||||||
|
Brukerens preferanser styrer hva som trigger epost vs bare
|
||||||
|
in-app varsel. Default: alt in-app, epost kun for direkte
|
||||||
|
nevnelser og invitasjoner.
|
||||||
|
|
||||||
|
## Visning
|
||||||
|
|
||||||
|
Varsler vises som:
|
||||||
|
- Klokke-ikon i header med ulest-teller
|
||||||
|
- Dropdown med siste varsler
|
||||||
|
- Klikk → naviger til relevant kontekst
|
||||||
|
- "Marker alle som lest"
|
||||||
|
|
||||||
|
Kan også være et panel i arbeidsflaten ("Varsler"-trait)
|
||||||
|
for de som vil ha det synlig.
|
||||||
|
|
||||||
|
## Ikke-forstyrrende
|
||||||
|
|
||||||
|
- Ingen popup-vinduer, ingen blokkerende dialoger
|
||||||
|
- Toast forsvinner etter 5 sekunder
|
||||||
|
- Bruker velger selv hva som sender epost
|
||||||
|
- "Ikke forstyrr"-modus per arbeidsflate
|
||||||
|
|
||||||
|
## Implementering
|
||||||
|
|
||||||
|
1. `notification`-node-type i maskinrommet
|
||||||
|
2. Trigger-logikk i vaktmesteren (ved edge-opprettelse, melding, etc.)
|
||||||
|
3. Frontend: toast-komponent + varsler-dropdown i header
|
||||||
|
4. `synops-notify` CLI finnes allerede — utvid med notification-noder
|
||||||
|
5. Epost-varsling via eksisterende `synops-mail --send`
|
||||||
Loading…
Add table
Reference in a new issue