# Komponerbare sider (Dashboard-komposisjon) ## Idé Brukere ser ferdige sider (Redaksjonen, Studioet, etc.), men admin kan komponere egne sider fra tilgjengelige byggeklosser — chat, kanban, statistikk, graf-visning, whiteboard, osv. ## Hvorfor interessant? Ulike redaksjoner jobber ulikt. Noen vil ha chat + kanban side-om-side, andre vil ha statistikk + research. I stedet for å hardkode alle kombinasjoner, gir vi admin verktøy til å sette opp sider tilpasset teamets arbeidsflyt. Brukerne ser resultatet som ferdige sider i navigasjonen. ## Modell ### Fase 1: Forhåndsdefinerte layouts (implementeres først) - Admin velger fra en katalog av **blokker** (chat, kanban, statistikk, etc.) - Plasserer dem i et **grid-layout** med forhåndsdefinerte maler (1-kolonne, 2-kolonne, 2+1, etc.) - Lagres som JSONB i `workspaces.settings` (nøkkel `pages`) - Brukere ser sidene i navigasjonen — ingen komposisjon, bare bruk - Mobil: blokkene stacker vertikalt (grid kollapser) ```jsonc // Eksempel: admin-definert side { "slug": "oversikt", "title": "Redaksjonsoversikt", "layout": "two-column", // Forhåndsdefinert mal "blocks": [ { "type": "chat", "channel": "general", "span": 1 }, { "type": "kanban", "board": "episoder", "span": 1 }, { "type": "stats", "view": "lyttere-7d", "span": 2 } ] } ``` ### Fase 2: Konfigurerbare dashboards (senere, ved behov) - Brukere kan lage egne personlige dashboards - Drag-and-drop for å endre rekkefølge og størrelse - Lagres per bruker i `workspace_members.dashboard_config` JSONB (PG, ikke fil) ### Fase 3: Full fri tiling (trolig unødvendig) - VS Code / Bloomberg-stil fritt plassering med splitters - Ekstremt høy kompleksitet, lav marginalverdi vs. Fase 2 - Unngå med mindre det er et demonstrert behov ## Blokker som resizable containere Hver blokk på en side er et selvstendig, resizable panel. Brukeren kan: ### Resize Dra i kanten mellom blokker for å justere proporsjoner. Midlertidig (session) eller persistent (lagres i brukerens `dashboard_config`). ``` Standard layout: Etter resize: ┌──────┬──────┐ ┌───┬─────────┐ │ Chat │Kanban│ │ │ │ │ │ │ → │ │ Kanban │ │ │ │ │ │ │ └──────┴──────┘ └───┴─────────┘ ``` ### Maximize Dobbelklikk på tittellinjen, eller en maximize-knapp — blokken utvider seg til hele tilgjengelig skjermflate. Alle andre blokker kollapses. Trykk Escape eller minimize for å gå tilbake. ``` Maksimert chat: ┌──────────────────────────┐ │ Chat — #Mediepolitikk ✕ │ │ │ │ [full editor, │ │ full tråd-oversikt, │ │ full funksjonalitet] │ │ │ │ │ └──────────────────────────┘ ``` Dette er spesielt verdifullt for: - **Editoren** — en chatmelding som vokser til en artikkel trenger plutselig hele skjermen. Maximize gir deg et reelt skriveverksted i stedet for en bitteliten boks. - **Whiteboard** — trenger plass for å være nyttig - **Graf-visualisering** — uleselig i en liten boks - **Mobil** — der skjermplassen er begrenset er maximize den naturlige interaksjonen. Blokkene stacker vertikalt, og du tapper en blokk for å utvide den til fullskjerm. ### Mobil-opplevelse På mobil er default-visningen en stacked liste med kollapsede blokker: ``` ┌──────────────────┐ │ ▼ Chat (3 nye) │ │ ▼ Kanban │ │ ▼ Statistikk │ └──────────────────┘ ``` Tapp en blokk → den ekspanderer til fullskjerm. Swipe ned eller tilbake-knapp → tilbake til oversikten. Editoren i fullskjerm på mobil = et reelt skriveverksted, ikke en liten inputboks nederst. ### Teknisk implementering - CSS Grid med `grid-template-columns`/`grid-template-rows` som justeres via drag - Resize via pointer events på grid-gapene (eller et lett bibliotek som `svelte-splitpanes`) - Maximize = CSS `position: fixed` + z-index overlay, med smooth transition - Blokk-størrelse lagres i `dashboard_config` JSONB: `{ "blockId": { "span": 1.5 } }` eller lignende - Midlertidig resize (ikke lagret) = Svelte `$state`, forsvinner ved refresh ## Arkitektur-krav Hver feature-komponent MÅ bygges som en **selvstendig Svelte-komponent** som: - Tar imot `workspaceId` (og evt. config-props som `channelId`, `boardId`) - Håndterer sin egen datahenting og tilstand - Respekterer container-størrelse (responsiv innenfor sin blokk, `container queries` i CSS) - Eksponerer en `blockMeta`-descriptor (tittel, min-bredde, min-høyde, ikon) for katalogen - Har en `maximized`-prop som tilpasser layout (f.eks. editoren viser full toolbar i maximized) Dette koster ingenting å gjøre fra start og gir full fleksibilitet senere. ## Bygger på - Workspace-modell, SvelteKit layout - Alle feature-komponenter (chat, kanban, whiteboard, statistikk, etc.) - Editor (proposal) — maximize gir editoren plass til å være et reelt skriveverksted ## Innsats - Fase 1: **Lav** (grid-layout + JSON-config, ingen drag-and-drop) - Fase 1.5: **Lav** (maximize per blokk — relativt enkelt med CSS overlay) - Fase 2: **Middels** (resize, svelte-splitpanes, bruker-lagring) - Fase 3: **Stor** (custom tiling engine — trolig unødvendig) ## Wow-faktor Middels–Høy. Gir en "dette er MITT verktøy"-følelse. Maximize alene er en stor forbedring — spesielt på mobil der det transformerer opplevelsen fra "begrenset app" til "fullverdig arbeidsflate". ## Åpne spørsmål - Skal sider være workspace-globale (alle ser samme oppsett) eller per-bruker? → Fase 1: workspace-globale via `workspaces.settings` JSONB. Fase 2: personlige overrides i `workspace_members.dashboard_config` JSONB. Alt i PG — ingen filer per bruker. - Midlertidig vs persistent resize: bør default være at resize forsvinner ved refresh (session), eller lagres automatisk? → Trolig: auto-lagre med debounce. Brukeren forventer at ting "huskes". En "tilbakestill layout"-knapp for å gå tilbake til admin-default. - Bør det finnes et "standard-oppsett" per workspace-type (podcast, nyhetsredaksjon)? → Ja, som templates admin kan velge som utgangspunkt. - Keyboard shortcut for maximize? F11 er konvensjon for fullskjerm, men kolliderer med nettleser. Kanskje Ctrl+Shift+F eller dobbelklikk. ## Relasjon til andre proposals - **Editor** — maximize gir editoren rom til å gå fra chatinput til fullverdig skriveverksted - **Personlig workspace** — personlige dashboards (fase 2) henger tett sammen med personlig workspace - **Tekst-primitiv** — en melding som vokser trenger plass; maximize er mekanismen som gir den det