# 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