Arbeidsflaten: workspace+tools-modell erstatter vokse-modellen
Ny retning: arbeidsflaten.md — spatial canvas med verktøy-paneler. Drag-and-drop mellom verktøy oppretter nye noder med source_material-edges. Noder muterer ikke — de føder nye noder. Oppdatert docs: - universell_input.md: "retyping" → "nye noder fra eksisterende" - rom_ikke_forum.md: "bli" → "føde", siloer → verktøy-paneler - universell_overfoering.md: blokker → verktøy-paneler, dual-modell - meldingsboks.md: multi-rolle → visning i flere kontekster Nye docs: - arbeidsflaten.md: retning med kompatibilitetsmatrise og inkompatibilitet - artikkelverktoy.md: langform TipTap-editor med drag-and-drop mottak Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
822bcb41d1
commit
9fefa0a8c2
8 changed files with 384 additions and 55 deletions
|
|
@ -34,6 +34,7 @@ CLAUDE.md er eneste startdokument. Alt annet ligger under `docs/`:
|
|||
- `maskinrommet.md` — Rust-orkestrator: fang, prosesser, lever
|
||||
- `bruker_ikke_workspace.md` — Noder er sentrum: brukere, team, innhold er noder. Tilgangsmatrise fra edges.
|
||||
- `datalaget.md` — PG(+AGE) som graf og arkiv, SpacetimeDB som sanntidslag
|
||||
- `arbeidsflaten.md` — Spatial canvas med verktøy-paneler, drag-and-drop, kompatibilitetsmatrise
|
||||
- `docs/primitiver/` — Spesifikasjoner for kjerneprimitivene:
|
||||
- `nodes.md` — Node-skjema, node_kind, visibility, CAS-noder, eierskap
|
||||
- `edges.md` — Edge-skjema, typer, metadata, systemedges
|
||||
|
|
@ -46,6 +47,9 @@ CLAUDE.md er eneste startdokument. Alt annet ligger under `docs/`:
|
|||
- `docs/features/` — Tekniske byggeklosser:
|
||||
- Se individuelle filer for chat, kanban, kalender, meldingsboks,
|
||||
kunnskapsgraf, whiteboard, live transkripsjon, ressursforbruk, m.fl.
|
||||
- `lydstudio.md` — Lydredigering via FFmpeg, EDL, ikke-destruktiv prosessering
|
||||
- `artikkelverktoy.md` — Langform TipTap-editor, drag-and-drop mottak, source_material-edges
|
||||
- `universell_overfoering.md` — Drag-and-drop mellom verktøy-paneler, kompatibilitetsmatrise
|
||||
- `docs/proposals/` — Idébank med 32+ uimplementerte forslag (se README.md)
|
||||
- `docs/setup/` — Oppsett og drift:
|
||||
- `produksjon.md` — Steg-for-steg oppsett av Hetzner VPS fra scratch
|
||||
|
|
|
|||
100
docs/features/artikkelverktoy.md
Normal file
100
docs/features/artikkelverktoy.md
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
# Feature: Artikkelverktøyet — langform-editor på arbeidsflaten
|
||||
|
||||
## 1. Konsept
|
||||
|
||||
Artikkelverktøyet er et verktøy-panel på arbeidsflaten med en TipTap-editor
|
||||
optimalisert for langform-skriving. Det aksepterer drag-and-drop fra andre
|
||||
paneler og oppretter innholdsnoder med `source_material`-edges tilbake
|
||||
til kildene.
|
||||
|
||||
Ref: [arbeidsflaten](../retninger/arbeidsflaten.md),
|
||||
[publisering](../concepts/publisering.md)
|
||||
|
||||
## 2. Opprettelse
|
||||
|
||||
Når artikkelverktøyet åpnes, opprettes en ny innholdsnode:
|
||||
|
||||
```
|
||||
node_kind: "content"
|
||||
metadata.document: { "type": "doc", "content": [] } // Tom TipTap-doc
|
||||
visibility: "hidden" // Privat til forfatteren deler
|
||||
```
|
||||
|
||||
Noden er en artikkel fra fødsel — ingen "konvertering" fra annet innhold.
|
||||
|
||||
## 3. Drag-and-drop mottak
|
||||
|
||||
Artikkelverktøyet implementerer `BlockReceiver`-interfacet og aksepterer:
|
||||
|
||||
| Kilde | Handling | Edge |
|
||||
|-------|----------|------|
|
||||
| **Chatboble** | Sett inn sitert tekst i editoren | `source_material` (context: "quoted") |
|
||||
| **Transkripsjon** | Sett inn tekstblokk fra segment | `source_material` (context: "quoted") |
|
||||
| **Bilde** | Sett inn inline-bilde | `has_media` |
|
||||
| **Lydfil** | Sett inn lydavspiller (embed) | `has_media` |
|
||||
| **Tekst/notat** | Sett inn innhold | `source_material` (context: "referenced") |
|
||||
| **Annen artikkel** | Sett inn utdrag | `source_material` (context: "quoted") |
|
||||
|
||||
Ved drop:
|
||||
1. Ny `source_material`-edge fra artikkel → kilde
|
||||
2. Innhold settes inn i editoren på markørposisjon
|
||||
3. Visuell indikator i editoren viser at teksten har en kilde
|
||||
(subtil venstrekant-markering, klikkbar for å se originalen)
|
||||
|
||||
## 4. Editor-konfigurasjon
|
||||
|
||||
TipTap med fulle extensions for langform:
|
||||
|
||||
- Overskrifter (h2, h3, h4)
|
||||
- Blockquotes, kodeblokker
|
||||
- Bilder (inline, refererer CAS-noder via `has_media`)
|
||||
- Lister (ordnet, uordnet, sjekklister)
|
||||
- Tabeller
|
||||
- Lenker
|
||||
- Embeds (lyd, video)
|
||||
|
||||
Forenklede presets tilgjengelig:
|
||||
- **Artikkel** (default): alle extensions
|
||||
- **Show notes**: lister, tidskoder, lenker
|
||||
- **Notat**: tekst, sjekklister
|
||||
|
||||
## 5. Publiseringsintegrasjon
|
||||
|
||||
Artikkelen følger publiseringsreisen via edge-progresjon:
|
||||
|
||||
```
|
||||
intended_for → submitted_to → belongs_to
|
||||
(arbeidsfase) (vurdering) (publisert)
|
||||
```
|
||||
|
||||
Publiseringspanelet vises ved siden av editoren når `intended_for`-edge
|
||||
finnes. Forfatteren fyller ut presentasjonselementer (tittel, ingress,
|
||||
forsidebilde) som egne noder med edges til artikkelen.
|
||||
|
||||
## 6. Kildesporbarhet
|
||||
|
||||
Artikkelens `source_material`-edges gir komplett lineage:
|
||||
|
||||
```
|
||||
Artikkel "Trikken kan bli gratis"
|
||||
←source_material── Chatboble i #redaksjon (sitert)
|
||||
←source_material── Transkripsjonssegment fra episode 42 (sitert)
|
||||
←source_material── Notat fra dagboken (referert)
|
||||
←has_media──────── Bilde av trikken (CAS-media)
|
||||
```
|
||||
|
||||
UI viser en "Kilder"-panel i editoren med alle koblede noder.
|
||||
Klikk → naviger til originalen.
|
||||
|
||||
## 7. Bygger på
|
||||
|
||||
- [Universell input](../retninger/universell_input.md) — TipTap-editor, dokumentlagring
|
||||
- [Publisering](../concepts/publisering.md) — publiseringsreise via edges
|
||||
- [Arbeidsflaten](../retninger/arbeidsflaten.md) — drag-and-drop, verktøy-panel
|
||||
- [Universell overføring](universell_overfoering.md) — mottaker-interface
|
||||
|
||||
## 8. Responsivt
|
||||
|
||||
- **Desktop:** Side ved side med andre paneler, full editor
|
||||
- **Tablet:** Fullskjerm-editor med "Send til..."-meny for kilder
|
||||
- **Mobil:** Forenklet editor, ingen drag-and-drop (bruk meny)
|
||||
|
|
@ -166,9 +166,15 @@ Aktive verdier etter migrering:
|
|||
Utfasede verdier (kan ikke fjernes fra PG ENUM, men skal aldri brukes i ny kode):
|
||||
`'aktør'`, `'tema'`, `'faktoide'`, `'note'`, `'kanban_card'`, `'calendar_event'`
|
||||
|
||||
## 4. Multi-rolle via view-config
|
||||
## 4. Visning i flere kontekster
|
||||
|
||||
Konvertering = legg til view-config. Ingen data flyttes:
|
||||
En node kan vises i flere verktøy samtidig via edges og view-configs.
|
||||
For lettvekts-triage (node → kanban, node → kalender) legges en edge/
|
||||
view-config til. For innholdstransformasjon (chatboble → artikkel)
|
||||
opprettes en ny node med `source_material`-edge. Se
|
||||
[arbeidsflaten](../retninger/arbeidsflaten.md).
|
||||
|
||||
Multi-visning via view-config (samme node, flere kontekster):
|
||||
|
||||
```
|
||||
Meldingsboks (messages + nodes)
|
||||
|
|
@ -312,7 +318,7 @@ Migrasjonen konverterer eksisterende data:
|
|||
- **Kalenderhendelse:** INSERT i `nodes` + `messages` (med tittel) + `calendar_event_view`. Én transaksjon.
|
||||
- **Faktoide:** INSERT i `nodes` + `messages` (`message_type = 'factoid'`) + `graph_edges` med `ABOUT`-relasjon til aktør/tema. Én transaksjon.
|
||||
- **Notat:** INSERT i `nodes` + `messages` (med tittel + body). `channel_id` peker på en personlig eller delt channel, eller er NULL.
|
||||
- **Konvertering mellom roller:** Legg til view-config-rad (kanban/kalender). Aldri kopier data.
|
||||
- **Visning i ny kontekst:** Legg til view-config-rad (kanban/kalender) for lettvekts-triage. For innholdstransfer: ny node med `source_material`-edge.
|
||||
- **Kontekst-navigering:** Bruk `reply_to`-kjeden for å bygge brødsmulesti tilbake til opprinnelig diskusjonskontekst.
|
||||
- **TTL:** Implementér som nattlig jobbkø-jobb (`message_ttl_cleanup`). Sjekk fritak-regler før sletting. Ved sletting: slett fra `messages` → cascade til `nodes` via FK.
|
||||
- **Tilgang:** Styres via `node_access`-matrisen. Visibility håndteres i applikasjonskode (SvelteKit): `WHERE visibility = 'shared' OR author_id = $current_user`.
|
||||
|
|
|
|||
|
|
@ -1,22 +1,38 @@
|
|||
# Feature: Universell overføring — flytt objekter mellom blokker
|
||||
# Feature: Universell overføring — flytt innhold mellom verktøy
|
||||
**Filsti:** `docs/features/universell_overfoering.md`
|
||||
|
||||
## 1. Konsept
|
||||
|
||||
Universell overføring er mekanikken som lar brukere flytte meldingsboks-objekter mellom vilkårlige blokker: fra storyboard til chat, fra kanban til kalender, fra chat til storyboard. Enhver blokk kan *sende* og *motta* objekter. Meldingsboksen er alltid det underliggende objektet — overføringen endrer kun *view-config*, ikke selve meldingen.
|
||||
Universell overføring er kjerneinteraksjonen på arbeidsflaten: drag-and-drop
|
||||
mellom verktøy-paneler. Se [arbeidsflaten](../retninger/arbeidsflaten.md) for
|
||||
den overordnede retningen.
|
||||
|
||||
### 1.1 Grunnprinsipp
|
||||
### 1.1 To moduser
|
||||
|
||||
En meldingsboks (node i kunnskapsgrafen) kan ha flere samtidige roller via view-configs (se `meldingsboks.md` §4). Universell overføring gjør dette til en førsteklasses brukerinteraksjon:
|
||||
| Modus | Hva skjer | Eksempel |
|
||||
|-------|-----------|---------|
|
||||
| **Innholdstransfer** | Ny node opprettes med `source_material`-edge til kilden | Chatboble → artikkelverktøy: ny artikkelnode |
|
||||
| **Lettvekts-triage** | Eksisterende node får ny edge/plassering | Chatboble → kanban: noden vises i kanban OG chat |
|
||||
|
||||
Default avhenger av verktøy-paret. Se kompatibilitetsmatrisen i
|
||||
[arbeidsflaten](../retninger/arbeidsflaten.md). Bruker kan overstyre
|
||||
med modifier-tast (Shift = alltid ny node).
|
||||
|
||||
### 1.2 Grunnprinsipp
|
||||
|
||||
```
|
||||
Bruker drar kort fra Storyboard → slipper på Chat-blokken
|
||||
→ Meldingen får en ny plassering i chatten (placement-record)
|
||||
→ Meldingen beholder sin posisjon på storyboardet
|
||||
→ Diskusjonstråden er synlig begge steder (samme objekt)
|
||||
Bruker drar kort fra Chat → slipper på Artikkelverktøyet
|
||||
→ Ny artikkelnode opprettes med sitert tekst
|
||||
→ source_material-edge kobler artikkel → chatboble
|
||||
→ Chatboblen forblir uendret i chatten
|
||||
|
||||
Bruker drar kort fra Chat → slipper på Kanban-brettet
|
||||
→ Noden får board-edge + status-edge (lettvekts)
|
||||
→ Noden vises i kanban OG chat (samme node, to kontekster)
|
||||
```
|
||||
|
||||
Alternativt kan brukeren *flytte* (fjerne fra kilde, legge til i mål) i stedet for å *kopiere* (beholde begge). Kontekstmeny gir valget.
|
||||
Bruker kan alltid flytte (fjerne fra kilde) i stedet for å kopiere
|
||||
(beholde begge). Kontekstmeny gir valget.
|
||||
|
||||
## 2. Plasseringsrelasjon (Placement)
|
||||
|
||||
|
|
@ -70,10 +86,10 @@ En melding opprettet mandag i chatten som dras til storyboardet onsdag har `crea
|
|||
|
||||
### 3.1 Drag-and-drop
|
||||
|
||||
Brukeren drar et objekt ut av en blokk. Når objektet forlater blokk-grensen:
|
||||
Brukeren drar et objekt ut av en verktøy-panel. Når objektet forlater verktøy-panel-grensen:
|
||||
|
||||
1. Objektet blir en "ghost" (semi-transparent drag-representasjon)
|
||||
2. Andre blokker som kan motta objektet highlighter sin mottakssone
|
||||
2. Andre verktøy-paneler som kan motta objektet highlighter sin mottakssone
|
||||
3. Slipp på en mottakssone → overføring
|
||||
|
||||
### 3.2 Kontekstmeny: "Send til..."
|
||||
|
|
@ -88,7 +104,7 @@ Høyreklikk kort → "Send til..." →
|
|||
└── 🎬 Storyboard: Episode 47
|
||||
```
|
||||
|
||||
Listen viser alle blokker brukeren har tilgang til som kan motta meldinger.
|
||||
Listen viser alle verktøy-paneler brukeren har tilgang til som kan motta meldinger.
|
||||
|
||||
### 3.3 Flytt vs. kopier
|
||||
|
||||
|
|
@ -97,31 +113,35 @@ Listen viser alle blokker brukeren har tilgang til som kan motta meldinger.
|
|||
|
||||
## 4. Mottak-mekanikk (target)
|
||||
|
||||
Hver blokk-type definerer en **mottaker** som bestemmer hva som skjer når et objekt ankommer:
|
||||
Hver verktøy-panel-type definerer en **mottaker** som bestemmer hva som skjer når et objekt ankommer:
|
||||
|
||||
### 4.1 Mottaker per blokk-type
|
||||
### 4.1 Mottaker per verktøy-panel-type
|
||||
|
||||
| Blokk | Default-plassering | Visuell feedback |
|
||||
| Verktøy-panel | Default-plassering | Visuell feedback |
|
||||
|-------|-------------------|-----------------|
|
||||
| **Chat** | Ny melding i bunnen, `entered_at = now()` | Kort blinker inn i chatflyten |
|
||||
| **Kanban** | Første kolonne (eller "Innboks"), posisjon øverst | Kort glir inn i kolonnen |
|
||||
| **Storyboard** | Senter av viewport (eller slipp-posisjon) | Kort fader inn |
|
||||
| **Kalender** | Dagens dato, heldagshendelse | Dato highlighter |
|
||||
| **Notes** | Ny blokk i bunnen av notatet | Tekst fades inn |
|
||||
| **Notes** | Ny verktøy-panel i bunnen av notatet | Tekst fades inn |
|
||||
|
||||
### 4.2 Mottakssone-rendering
|
||||
### 4.2 Mottakssone-rendering og inkompatibilitet
|
||||
|
||||
Hver blokk rendrer en visuell drop-target når en drag er aktiv:
|
||||
Hver verktøy-panel rendrer en visuell drop-target når en drag er aktiv:
|
||||
|
||||
- **Hele blokken** lyser opp med en subtil border/glow
|
||||
- **Spesifikke soner** (f.eks. en kolonne i kanban, en dato i kalender) highlighter ved hover
|
||||
- **Avviste drops** (feil type objekt) viser en dempet tilstand
|
||||
- **Kompatibel:** Panelet lyser opp med subtil border/glow
|
||||
- **Spesifikke soner** (f.eks. en kolonne i kanban) highlighter ved hover
|
||||
- **Inkompatibel:** Drop-sonen er rød/grå. Tooltip forklarer *hvorfor*
|
||||
og foreslår alternativ der det gir mening.
|
||||
|
||||
Se kompatibilitetsmatrisen i [arbeidsflaten](../retninger/arbeidsflaten.md)
|
||||
for komplett oversikt over hva som kan dras til hva.
|
||||
|
||||
### 4.3 Mottaker-interface
|
||||
|
||||
```typescript
|
||||
interface BlockReceiver {
|
||||
/** Kan denne blokken motta dette objektet? */
|
||||
/** Kan denne verktøy-panelen motta dette objektet? */
|
||||
canReceive(message: Message): boolean;
|
||||
|
||||
/** Opprett plassering for mottatt objekt */
|
||||
|
|
@ -132,7 +152,7 @@ interface BlockReceiver {
|
|||
}
|
||||
```
|
||||
|
||||
Alle blokk-typer implementerer dette interfacet.
|
||||
Alle verktøy-panel-typer implementerer dette interfacet.
|
||||
|
||||
## 5. SpacetimeDB-integrasjon
|
||||
|
||||
|
|
@ -164,15 +184,15 @@ Sync-workeren persisterer til PG `message_placements`-tabellen.
|
|||
|
||||
## 6. Responsivt design
|
||||
|
||||
- **Desktop:** Drag-and-drop mellom blokker fungerer naturlig
|
||||
- **Desktop:** Drag-and-drop mellom verktøy-paneler fungerer naturlig
|
||||
- **Tablet:** Drag-and-drop fungerer med touch, men "Send til..."-meny er primær
|
||||
- **Mobil:** Kun "Send til..."-meny (blokker er stacked i én kolonne, drag mellom dem er upraktisk)
|
||||
- **Mobil:** Kun "Send til..."-meny (verktøy-paneler er stacked i én kolonne, drag mellom dem er upraktisk)
|
||||
|
||||
## 7. Bygger på
|
||||
|
||||
- **Meldingsboks** (`meldingsboks.md`): Alle overførte objekter er meldingsbokser
|
||||
- **Kunnskapsgraf** (`kunnskapsgraf_og_relasjoner.md`): Plasseringer er relasjoner i grafen
|
||||
- **BlockShell** / PageGrid: Blokk-rammen som rendrer mottakssoner
|
||||
- **BlockShell** / PageGrid: Verktøy-panel-rammen som rendrer mottakssoner
|
||||
- **SpacetimeDB** (`synkronisering.md`): Sanntidssynk av plasseringer
|
||||
|
||||
## 8. Konsekvenser for eksisterende kode
|
||||
|
|
@ -181,7 +201,7 @@ Sync-workeren persisterer til PG `message_placements`-tabellen.
|
|||
|
||||
`BlockShell` trenger:
|
||||
- `onDragEnter`/`onDragLeave`/`onDrop` handlers for visuell feedback
|
||||
- Prop for `receiver: BlockReceiver` fra innholdsblokken
|
||||
- Prop for `receiver: BlockReceiver` fra innholdsverktøy-panelen
|
||||
- Fullskjerm-toggle (knapp i header + Esc for å lukke)
|
||||
|
||||
### 8.2 Ny plasserings-tabell
|
||||
|
|
@ -193,9 +213,12 @@ Sync-workeren persisterer til PG `message_placements`-tabellen.
|
|||
Ny tabell `message_placement` med reducers for place/remove/move.
|
||||
|
||||
## 9. Instruks for Claude Code
|
||||
- Overføring oppretter aldri en kopi av meldingen — kun en ny plassering (view-config)
|
||||
- `entered_at` er alltid `now()` ved overføring, aldri kopiert fra kilden
|
||||
- En melding uten noen plasseringer er "løs" — den eksisterer i grafen men vises ikke noe sted. UI skal advare om dette ved siste fjerning
|
||||
- Drag-and-drop bruker HTML5 Drag and Drop API for blokk-til-blokk, og pointer events for intra-canvas (storyboard/whiteboard)
|
||||
- Hold overføringslogikken i en sentral `transferService` — ikke spread ut i hver blokk-type
|
||||
- Mottaker-interfacet er obligatorisk for alle blokk-typer
|
||||
- **Innholdstransfer** (ny node) brukes når innholdet transformeres (chat → artikkel)
|
||||
- **Lettvekts-triage** (ny edge/plassering) brukes når kontekst legges til (chat → kanban)
|
||||
- `source_material`-edge kobler ny node tilbake til kilden ved innholdstransfer
|
||||
- `entered_at` er alltid `now()` ved plassering, aldri kopiert fra kilden
|
||||
- En melding uten noen plasseringer er "løs" — UI advarer ved siste fjerning
|
||||
- Inkompatible drops gir visuell feedback (rød/grå) + tooltip med forklaring
|
||||
- Drag-and-drop bruker HTML5 API mellom paneler, pointer events intra-canvas
|
||||
- Hold overføringslogikken i en sentral `transferService`
|
||||
- Mottaker-interfacet er obligatorisk for alle verktøy-panel-typer
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ andre dokumenter. En retning kan også forkastes eller parkeres.
|
|||
| [Maskinrommet](maskinrommet.md) | **Besluttet** | Én Rust-tjeneste: fang, prosesser, lever. Eier all skriving. Edge-drevet ressursorkestrering. |
|
||||
| [Noder er sentrum](bruker_ikke_workspace.md) | **Besluttet** | Alt er noder (brukere, team, innhold). Edges definerer relasjoner og tilgang. Materialisert tilgangsmatrise for RLS. |
|
||||
| [Datalaget](datalaget.md) | **Besluttet** | SpacetimeDB holder hele grafen, PG er persistent arkiv, CAS for binærdata, AGE ved behov |
|
||||
| [Arbeidsflaten](arbeidsflaten.md) | **Besluttet** | Spatial canvas med verktøy-paneler. Drag-and-drop skaper nye noder med edges. |
|
||||
|
||||
### Relaterte spesifikasjoner
|
||||
|
||||
|
|
|
|||
184
docs/retninger/arbeidsflaten.md
Normal file
184
docs/retninger/arbeidsflaten.md
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
# Arbeidsflaten — verktøy og rom
|
||||
|
||||
**Status: Besluttet.**
|
||||
|
||||
> Arbeidsflaten er en spatial canvas der verktøy-paneler lever side ved side.
|
||||
> Brukeren arrangerer sitt eget rom. Drag-and-drop mellom verktøy er
|
||||
> kjerneinteraksjonen. Innhold flyter mellom verktøy via nye noder og edges.
|
||||
|
||||
## Observasjoner
|
||||
|
||||
Synops har bygget chat, kanban, kalender, studio, kunnskapsgraf — hver som
|
||||
sin visning. De er alle spørringer mot samme graf, men de lever på separate
|
||||
ruter (`/chat/[id]`, `/board/[id]`, `/calendar`). Brukeren navigerer mellom
|
||||
dem.
|
||||
|
||||
Tidligere beskrev vi at innhold "vokser" mellom kategorier: en chatmelding
|
||||
kan "bli" en artikkel ved å få edges. Arkitektonisk elegant, men klønete i
|
||||
praksis — du vil ikke redigere en chatboble til en langform-artikkel.
|
||||
|
||||
Observasjoner som ledet hit:
|
||||
|
||||
- **Verktøy-spesifikke oppgaver trenger verktøy-spesifikke grensesnitt.**
|
||||
En artikkel-editor er ikke en chat-input. Et lydstudio er ikke en
|
||||
medieavspiller. Å late som alt er én overflate gir dårlig UX.
|
||||
- **Kontekstbytte koster.** Å navigere mellom /chat og /board og /calendar
|
||||
bryter flyten. Verktøyene bør leve side ved side.
|
||||
- **Innhold bør flyttes mellom verktøy, ikke muteres.**
|
||||
Når en chatmelding inspirerer en artikkel, bør resultatet være en *ny*
|
||||
artikkelnode med en edge tilbake til meldingen — ikke en mutert melding.
|
||||
|
||||
## Tesen
|
||||
|
||||
**Arbeidsflaten er et personlig rom med verktøy-paneler.** Brukeren
|
||||
arrangerer sin egen flate med de verktøyene de trenger. Drag-and-drop
|
||||
mellom paneler er den primære interaksjonen for å flytte innhold.
|
||||
|
||||
Nøkkelprinsipp: **Noder føder nye noder.** Når innhold flyttes mellom
|
||||
verktøy, opprettes nye noder med `source_material`-edges tilbake til
|
||||
kilden. Originalen forblir uendret. Artikkelen sporer sine kilder
|
||||
gjennom grafen.
|
||||
|
||||
## Verktøy-paneler
|
||||
|
||||
Hvert verktøy er en selvinneholdt Svelte-komponent som:
|
||||
- Tar `nodeId` / `collectionId` + config som props
|
||||
- Håndterer egen datahenting og tilstand
|
||||
- Respekterer container-størrelse (responsive innenfor panelet)
|
||||
- Kan maksimeres til fullskjerm
|
||||
- Implementerer drag-and-drop mottak der det gir mening
|
||||
|
||||
| Verktøy | Hva det gjør | Aksepterer drag |
|
||||
|---------|--------------|-----------------|
|
||||
| **Chat** | Sanntidsmeldinger i kommunikasjonsnode | Vilkårlig node → del som melding |
|
||||
| **Artikkelverktøy** | TipTap langform-editor | Chatbobler, tekst, transkripsjoner, bilder, lyd |
|
||||
| **Kanban** | Oppgavestyring med kolonner | Chatbobler, tekst → ny oppgave |
|
||||
| **Kalender** | Tidslinje med `scheduled`-edges | Kanban-kort, chatbobler → ny hendelse |
|
||||
| **Lydstudio** | Waveform-redigering, ffmpeg-prosessering | Lydfiler → åpne i studio |
|
||||
| **Kunnskapsgraf** | D3-visualisering av noder og edges | — (visuell utforsker) |
|
||||
| **Transkripsjon** | Segmenter synkronisert med lyd | — (les-visning) |
|
||||
| **Dagbok** | Private notater, kronologisk | — (personlig) |
|
||||
| **AI-verktøy** | Konfigurerbar AI-tekstbehandling med prompt-velger | Tekstnoder, chatbobler, transkripsjoner → AI-prosessert output |
|
||||
|
||||
## Drag-and-drop mellom verktøy
|
||||
|
||||
### Mekanisme
|
||||
|
||||
1. Bruker drar en node fra verktøy A
|
||||
2. Under drag vises drop-soner i kompatible verktøy
|
||||
3. Ved drop: mål-verktøyet bestemmer hva som skjer
|
||||
4. Typisk: ny node opprettes + `source_material`-edge til kilden
|
||||
5. Alternativt: eksisterende node får ny edge (lettvekts-triage)
|
||||
|
||||
### To moduser
|
||||
|
||||
| Modus | Hva skjer | Når |
|
||||
|-------|-----------|-----|
|
||||
| **Innholdstransfer** | Ny node opprettes med `source_material`-edge | Innholdet transformeres (chat → artikkel, chat → oppgave) |
|
||||
| **Lettvekts-triage** | Eksisterende node får ny edge | Kontekst legges til (node → kanban-board, node → kalender) |
|
||||
|
||||
Default avhenger av verktøy-paret. Bruker kan overstyre med modifier-tast
|
||||
(Shift = alltid ny node).
|
||||
|
||||
## Kompatibilitetsmatrise
|
||||
|
||||
| Kilde → Mål | Artikkelverktøy | Chat | Kanban | Kalender | Studio |
|
||||
|---|---|---|---|---|---|
|
||||
| **Chatboble** | Ny artikkelnode, sitert tekst, `source_material` | (samme kontekst) | Ny oppgave + `source_material` | Ny hendelse + `source_material` | — |
|
||||
| **Tekst/notat** | Kopier inn, `source_material` | Del som melding med `mentions` | Ny oppgave | Ny hendelse | — |
|
||||
| **Lydfil** | Sett inn avspiller, `has_media` | Del med mention | — | — | Åpne i studio |
|
||||
| **Lydfil → Lydfil** | — | — | — | — | **Inkompatibel** |
|
||||
| **Transkripsjon** | Sett inn tekst + `source_material` | Del utdrag | — | — | — |
|
||||
| **Kanban-kort** | Kopier innhold + `source_material` | Del som melding | (flytt mellom kolonner) | Legg til `scheduled` edge | — |
|
||||
| **Bilde** | Sett inn + `has_media` | Del som melding | — | — | — |
|
||||
| **Vilkårlig node** | — | Del-melding med `mentions` | — | — | — |
|
||||
| **AI-verktøy → node** | — | — | — | — | — |
|
||||
|
||||
**AI-verktøy som mål:**
|
||||
|
||||
| Kilde → AI-verktøy | Resultat |
|
||||
|---|---|
|
||||
| **Chatboble** | Ny node med AI-output + `derived_from`-edge |
|
||||
| **Tekst/notat** | Ny node med AI-output + `derived_from`-edge |
|
||||
| **Transkripsjon** | Ny node med AI-output + `derived_from`-edge |
|
||||
| **Lydfil/bilde** | Inkompatibel: "AI-verktøyet behandler kun tekst" |
|
||||
|
||||
**AI-verktøy som kilde (dra verktøyet → tekstnode):**
|
||||
Modifiserer noden in-place. Originalen versjoneres. Se `docs/features/ai_verktoy.md`.
|
||||
|
||||
"—" betyr at kombinasjonen ikke gir mening og drop-sonen er inaktiv.
|
||||
|
||||
## Inkompatibilitet
|
||||
|
||||
Ikke alt kan gå overalt. Når en drag er inkompatibel:
|
||||
|
||||
1. **Visuell feedback:** Drop-sonen blir rød/grå under drag-over
|
||||
2. **Forklaring:** Tooltip viser *hvorfor* — ikke bare "kan ikke slippes her"
|
||||
3. **Alternativ:** Foreslå en bedre handling der det er mulig
|
||||
|
||||
### Eksempler
|
||||
|
||||
| Forsøk | Feedback |
|
||||
|--------|----------|
|
||||
| Lydfil → Lydfil | "Lydfiler kan ikke slås sammen direkte. Åpne i Studioet for å redigere." |
|
||||
| Bilde → Studio | "Studioet behandler kun lydfiler." |
|
||||
| Lydfil → Kanban | "Lydfiler kan ikke bli oppgaver direkte. Dra til Chat for å dele, eller til Artikkelverktøyet for å sette inn." |
|
||||
|
||||
## Tre lag for arbeidsflaten
|
||||
|
||||
Hver bruker har sin egen arbeidsflate. Arrangement lagres som preferanser
|
||||
på brukernoden.
|
||||
|
||||
| Lag | Kilde | Forrang |
|
||||
|-----|-------|---------|
|
||||
| **Personlig** | Brukerens eget arrangement | Høyest — overstyrer alt |
|
||||
| **Node-default** | Samlingens traits foreslår layout | Mellom — utgangspunkt |
|
||||
| **Plattform-default** | Synops sine standarder | Lavest — fallback |
|
||||
|
||||
Eksempel: en samling med `podcast` + `studio` + `chat` traits foreslår
|
||||
en layout med disse tre panelene. Brukeren kan flytte, legge til, fjerne
|
||||
paneler fritt. Arrangementet huskes per bruker per kontekst.
|
||||
|
||||
## `source_material`-edge
|
||||
|
||||
Ny edge-type som kobler en avledet node til kilden den ble laget fra.
|
||||
|
||||
```
|
||||
Artikkel-node ──source_material──→ Chatboble
|
||||
Artikkel-node ──source_material──→ Transkripsjonssegment
|
||||
Artikkel-node ──source_material──→ Notat
|
||||
```
|
||||
|
||||
Edge-metadata:
|
||||
```jsonc
|
||||
{
|
||||
"context": "quoted", // "quoted", "summarized", "referenced"
|
||||
"excerpt": "Den opprinnelige teksten som ble dratt inn"
|
||||
}
|
||||
```
|
||||
|
||||
Gir artikler sporbar lineage: du kan alltid se *hvor* materialet kom fra.
|
||||
|
||||
## Forhold til andre retninger
|
||||
|
||||
- **[Rom, ikke forum](rom_ikke_forum.md):** Arbeidsflaten *er* rommet.
|
||||
Verktøy-paneler er lagene som kan slås av og på. "Trylle frem, legge
|
||||
fra seg" realiseres som paneler som dukker opp og forsvinner.
|
||||
- **[Universell input](universell_input.md):** Input-primitiven lever
|
||||
i hvert verktøy med kontekst-tilpasset konfigurasjon. Arbeidsflaten
|
||||
bestemmer *hvor* input havner.
|
||||
- **[Noder er sentrum](bruker_ikke_workspace.md):** Verktøy er visninger
|
||||
av grafen. Arbeidsflaten er brukerens personlige arrangement av disse
|
||||
visningene.
|
||||
- **[Datalaget](datalaget.md):** SpacetimeDB driver sanntidsoppdatering
|
||||
mellom paneler. Drag-and-drop oppretter noder/edges som synkes instant.
|
||||
|
||||
## Hva ville vært annerledes
|
||||
|
||||
- Chat, kanban, kalender lever **side ved side**, ikke som separate sider
|
||||
- Du **drar en chatboble til artikkelverktøyet** i stedet for å "retype"
|
||||
den med edges
|
||||
- Artikkelen **sporer sine kilder** via `source_material`-edges
|
||||
- Inkompatible handlinger gir **tydelig feedback** med forklaringer
|
||||
- Brukerens arrangement er **personlig og persistent** — du setter opp
|
||||
arbeidsflaten din én gang og den huskes
|
||||
|
|
@ -84,11 +84,12 @@ Tesen ovenfor kan føles abstrakt. Mer konkret: Sidelinja bør være en
|
|||
der produktive ting er lette å oppnå og strukturen følger deg, ikke omvendt.
|
||||
|
||||
### Formløs input, struktur etterpå
|
||||
I dag velger du visning først: "nå er jeg i chat", "nå er jeg i kanban." Men
|
||||
meldingsboksen er allerede designet for at input ikke trenger å vite hva den
|
||||
*er* på forhånd. En tanke bør kunne starte som en løs setning og bli et
|
||||
kanban-kort, en faktoid, en kalenderoppføring — uten at brukeren måtte
|
||||
bestemme det på forhånd. Visninger er flyktige linser. Innhold er permanent.
|
||||
Input trenger ikke vite hva den *er* på forhånd. En tanke starter som en
|
||||
løs setning i input-feltet. Etterpå kan den *føde* et kanban-kort, en
|
||||
faktoid, en artikkel — brukeren drar den til riktig verktøy-panel på
|
||||
arbeidsflaten, og en ny node opprettes med riktige edges. Originaltanken
|
||||
forblir uendret. Verktøy-panelene bestemmer strukturen, ikke input-metoden.
|
||||
Se [arbeidsflaten](arbeidsflaten.md).
|
||||
|
||||
### Trylle frem, legge fra seg
|
||||
Trenger du et whiteboard? Det dukker opp. En videosamtale? Den starter.
|
||||
|
|
@ -98,10 +99,12 @@ trenger ikke "lukke" noe eller "lagre" noe. Ting eksisterer i verden
|
|||
og kan gjenfinnes.
|
||||
|
||||
### Siloer forsvinner
|
||||
"Universell overføring" som eksplisitt feature blir overflødig fordi det
|
||||
ikke finnes separate steder å overføre *mellom*. Du endrer ikke *hvor*
|
||||
noe er — du endrer *hvordan* du ser på det som allerede er der. Chat,
|
||||
kanban, kalender er ikke apper — de er visninger av samme tilstandsrom.
|
||||
Universell overføring er ikke en separat feature — det er selve
|
||||
interaksjonsmønsteret. Verktøy-paneler lever side ved side på
|
||||
arbeidsflaten, og drag-and-drop mellom dem er den primære flyten.
|
||||
Du flytter ikke innhold mellom apper — du drar det fra et verktøy
|
||||
til et annet i rommet du allerede er i. Chat, kanban, kalender er
|
||||
visninger av samme graf, arrangert på samme flate.
|
||||
|
||||
### Privat og delt som lag, ikke separate systemer
|
||||
Privat/delt er bare en
|
||||
|
|
|
|||
|
|
@ -58,9 +58,11 @@ setter en *default* editor-konfigurasjon. Men brukeren kan alltid
|
|||
overstyre — utvide til full editor eller forenkle. Ingen kunstig
|
||||
grense mellom "chatmelding" og "artikkel."
|
||||
|
||||
Du *kan* skrive en gjennomformatert tekst med overskrifter, bilder
|
||||
og blockquotes i chatten. Om du vil publisere den etterpå er det
|
||||
bare å legge til en publiserings-edge. Innholdet er det samme.
|
||||
Du *kan* skrive en gjennomformatert tekst i chatten. Men hvis en
|
||||
chatmelding inspirerer en artikkel, drar du den til artikkelverktøyet
|
||||
på arbeidsflaten. En ny innholdsnode opprettes med `source_material`-edge
|
||||
til meldingen. Artikkelen skrives i et verktøy designet for langform —
|
||||
chatinput er designet for samtale. Se [arbeidsflaten](arbeidsflaten.md).
|
||||
|
||||
Editoren husker brukerens valg per kontekst via preferanser på
|
||||
brukernoden.
|
||||
|
|
@ -131,12 +133,16 @@ Hva en node "er" bestemmes utelukkende av edges:
|
|||
- Node + `mentions` → topic = faktoid i kunnskapsgrafen
|
||||
- Node uten edges = løs tanke, ennå uorganisert
|
||||
|
||||
**Retyping er trivielt.** Chatmelding → kanban-kort = legg til
|
||||
board-edge og status-edge. Ingen datamigrering, bare edges.
|
||||
**Nye noder fra eksisterende.** Chatmelding → oppgave = ny
|
||||
oppgavenode med `source_material`-edge til meldingen. Meldingen
|
||||
forblir uendret. For lettvekts-triage (noden vises i kanban OG
|
||||
chat): legg til `status`-edge direkte — ingen ny node nødvendig.
|
||||
|
||||
**Multitype er naturlig.** En node kan være *både* kanban-kort
|
||||
*og* kalenderoppføring *og* faktoid. Det er ikke en edge case —
|
||||
det er arkitekturen.
|
||||
**Multitype er naturlig.** En node kan ha flere roller samtidig
|
||||
— både kanban-kort og kalenderoppføring og faktoid. Det er for
|
||||
noder som genuint tjener flere formål, ikke for å "gro" en
|
||||
chatboble til en artikkel. Artikkelen er en *ny* node med
|
||||
`source_material`-edge. Se [arbeidsflaten](arbeidsflaten.md).
|
||||
|
||||
### Edge-tildeling
|
||||
|
||||
|
|
@ -144,8 +150,10 @@ Når du "bare sier noe" — hvem bestemmer edges?
|
|||
|
||||
1. **Kontekst gir det meste.** Du er i en samtale → `belongs_to`-
|
||||
edge til samtalen. Du er alene → privat. Dekker 80%.
|
||||
2. **Eksplisitt handling.** Du drar en node til kanban-brettet.
|
||||
Du tagger noe. Du setter en dato.
|
||||
2. **Eksplisitt handling.** Du drar en node til kanban-brettet
|
||||
(legg til board-edge) eller til artikkelverktøyet (ny node med
|
||||
`source_material`-edge). Du tagger noe. Du setter en dato.
|
||||
Se [arbeidsflaten](arbeidsflaten.md) for kompatibilitetsmatrise.
|
||||
3. **AI-foreslått.** Systemet foreslår `mentions`-edge når du
|
||||
nevner en person. Foreslår kanban når noe ligner en oppgave.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue