Proposal: Chat/forum-dualitet + lest/ulest
Samme kommunikasjonsnode vises som chat (kronologisk) eller forum (trådet). Bytt fritt mellom visninger. Lest/ulest er én last_seen timestamp per bruker per samtale — transitiv mellom alle visninger. Forum-egenskaper (tråd, kategori, pinning) er metadata på noder. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b3a55af660
commit
1a63ad4e7e
1 changed files with 256 additions and 0 deletions
256
docs/proposals/chat_forum_dualitet.md
Normal file
256
docs/proposals/chat_forum_dualitet.md
Normal file
|
|
@ -0,0 +1,256 @@
|
||||||
|
# Proposal: Chat/forum-dualitet + lest/ulest
|
||||||
|
|
||||||
|
## Konsept
|
||||||
|
|
||||||
|
En kommunikasjonsnode kan vises som chat (kronologisk) eller
|
||||||
|
forum (trådet). Samme data, to visninger. Brukeren bytter
|
||||||
|
fritt mellom dem. Lest/ulest er én status per bruker per
|
||||||
|
samtale — transitiv mellom alle visninger.
|
||||||
|
|
||||||
|
## Problemstilling
|
||||||
|
|
||||||
|
Chatter er gode for rask diskusjon, dårlige for å finne igjen
|
||||||
|
beslutninger. Forum er bra for struktur, dårlige for spontanitet.
|
||||||
|
I praksis trenger en redaksjon begge — og de snakker om de
|
||||||
|
samme tingene. To separate systemer betyr duplisering og
|
||||||
|
informasjonstap.
|
||||||
|
|
||||||
|
## Datamodell
|
||||||
|
|
||||||
|
Meldinger er noder med `belongs_to`-edge til kommunikasjonsnoden.
|
||||||
|
Forum-egenskaper er metadata på meldingsnoden:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"node_kind": "content",
|
||||||
|
"metadata": {
|
||||||
|
"forum_thread": "Episodetema S02E05",
|
||||||
|
"reply_to": "melding-uuid-her",
|
||||||
|
"forum_category": "Planlegging"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `forum_thread`: tildeles når meldingen opprettes i forum-visning,
|
||||||
|
eller når noen i chat-visningen "tråder" en melding
|
||||||
|
- `reply_to`: svar på en spesifikk melding (trådstruktur)
|
||||||
|
- `forum_category`: valgfri gruppering i forumet
|
||||||
|
|
||||||
|
Meldinger uten `forum_thread` vises i forumet under "Generelt"
|
||||||
|
eller "Utrådede".
|
||||||
|
|
||||||
|
## To visninger, én datakilde
|
||||||
|
|
||||||
|
### Chat-visning
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ Redaksjonen (chat) ──────────────┐
|
||||||
|
│ │
|
||||||
|
│ Vegard 10:03 │
|
||||||
|
│ Vi bør ta klimatilpasning │
|
||||||
|
│ │
|
||||||
|
│ Trond 10:15 │
|
||||||
|
│ Fant en god kilde om flom │
|
||||||
|
│ │
|
||||||
|
│ Arne 10:22 │
|
||||||
|
│ Enig, passer med forrige ep │
|
||||||
|
│ │
|
||||||
|
│ Vegard 10:30 │
|
||||||
|
│ Teknisk: mic-nivåene var lave │
|
||||||
|
│ │
|
||||||
|
│ [skriv melding...] │
|
||||||
|
│ [Bytt til 📋] │
|
||||||
|
└────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- Alle meldinger kronologisk
|
||||||
|
- Ingen gruppering — strøm
|
||||||
|
- Forum-metadata (tråd, kategori) er usynlig som default
|
||||||
|
- Valgfritt: vis tråd-markør som subtil tag på meldinger som
|
||||||
|
tilhører en tråd
|
||||||
|
|
||||||
|
### Forum-visning
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─ Redaksjonen (forum) ─────────────┐
|
||||||
|
│ │
|
||||||
|
│ Planlegging │
|
||||||
|
│ 📌 Episodetema S02E05 (3) ● │
|
||||||
|
│ Vegard: Vi bør ta klima... │
|
||||||
|
│ └ Trond: Fant en god kild... │
|
||||||
|
│ └ Arne: Enig, passer med... │
|
||||||
|
│ │
|
||||||
|
│ Teknisk │
|
||||||
|
│ Mic-nivåer (1) │
|
||||||
|
│ Vegard: mic-nivåene var... │
|
||||||
|
│ │
|
||||||
|
│ [ny tråd...] │
|
||||||
|
│ [Bytt til 💬] │
|
||||||
|
└────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
- Gruppert etter `forum_category`, deretter `forum_thread`
|
||||||
|
- Trådstruktur via `reply_to`
|
||||||
|
- Uleste tråder markert med ● (se lest/ulest under)
|
||||||
|
- Innleggsteller per tråd
|
||||||
|
|
||||||
|
### Bytte mellom visninger
|
||||||
|
|
||||||
|
En knapp i panelet: "Bytt til 📋" / "Bytt til 💬"
|
||||||
|
|
||||||
|
Byttet er øyeblikkelig — ingen data lastes på nytt, bare
|
||||||
|
renderingen endres. Samme WebSocket-abonnement, samme noder.
|
||||||
|
|
||||||
|
Kan også være to separate paneler i arbeidsflaten som viser
|
||||||
|
samme kommunikasjonsnode — ett som chat, ett som forum.
|
||||||
|
|
||||||
|
## Tråding fra chat
|
||||||
|
|
||||||
|
I chat-visningen kan brukeren tråde en melding:
|
||||||
|
|
||||||
|
1. Høyreklikk / lang-trykk på en melding
|
||||||
|
2. "Opprett tråd" → sett `forum_thread` på meldingen
|
||||||
|
3. Fremtidige svar i tråden får samme `forum_thread`
|
||||||
|
4. I chatten vises de fortsatt kronologisk
|
||||||
|
5. I forumet vises de som en tråd
|
||||||
|
|
||||||
|
## Skrive fra forum
|
||||||
|
|
||||||
|
Når du skriver i forumet:
|
||||||
|
|
||||||
|
1. Velg tråd (eksisterende eller ny)
|
||||||
|
2. Skriv innlegg
|
||||||
|
3. Noden opprettes med `forum_thread` og evt `reply_to`
|
||||||
|
4. Dukker opp i chatten kronologisk (med subtil trådmarkør)
|
||||||
|
|
||||||
|
## Lest/ulest
|
||||||
|
|
||||||
|
### Modell
|
||||||
|
|
||||||
|
Én verdi per bruker per kommunikasjonsnode: `last_seen` timestamp.
|
||||||
|
|
||||||
|
```
|
||||||
|
Vegard --[member_of {
|
||||||
|
role: "owner",
|
||||||
|
last_seen: "2026-03-19T08:30:00Z"
|
||||||
|
}]--> Redaksjonen
|
||||||
|
```
|
||||||
|
|
||||||
|
Alle meldinger med `created_at > last_seen` er **uleste**.
|
||||||
|
|
||||||
|
### Oppdatering
|
||||||
|
|
||||||
|
- **Chat:** `last_seen` oppdateres når brukeren scroller til
|
||||||
|
bunnen av chatten (eller ser nyeste melding)
|
||||||
|
- **Forum:** `last_seen` oppdateres når brukeren åpner en tråd
|
||||||
|
med uleste meldinger
|
||||||
|
- **Mine ting:** viser ulest-badge basert på `last_seen`
|
||||||
|
|
||||||
|
Begge visninger skriver til samme `last_seen`. Lest i chat =
|
||||||
|
lest i forum. Ingen doble varsler.
|
||||||
|
|
||||||
|
### Ulest-indikatorer
|
||||||
|
|
||||||
|
**Chat:**
|
||||||
|
- Uleste meldinger under en separator-linje: "3 nye meldinger"
|
||||||
|
- Bold / blå prikk på samtalen i Mine ting
|
||||||
|
- Badge-teller i kontekst-velger
|
||||||
|
|
||||||
|
**Forum:**
|
||||||
|
- Uleste tråder markert med ● (prikk)
|
||||||
|
- Ulest-teller per tråd: "(3)" der noen er uleste
|
||||||
|
- Bold tråd-tittel for uleste tråder
|
||||||
|
- Ulest-teller per kategori
|
||||||
|
|
||||||
|
**Mine ting:**
|
||||||
|
- Badge-teller per samtale
|
||||||
|
- Kan gruppere uleste øverst
|
||||||
|
|
||||||
|
### Transitiv
|
||||||
|
|
||||||
|
Lest/ulest er knyttet til **noden** (meldingen), ikke visningen.
|
||||||
|
Har du sett noden — uansett gjennom chat, forum, søk, eller
|
||||||
|
Mine ting — er den lest.
|
||||||
|
|
||||||
|
### Effektivitet
|
||||||
|
|
||||||
|
Ikke én edge per melding per bruker. Bare ett timestamp i
|
||||||
|
edge-metadata. Sjekken er enkel:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
SELECT count(*) FROM nodes n
|
||||||
|
JOIN edges e ON e.target_id = $communication_id
|
||||||
|
AND e.source_id = n.id
|
||||||
|
AND e.edge_type = 'belongs_to'
|
||||||
|
WHERE n.created_at > $last_seen
|
||||||
|
```
|
||||||
|
|
||||||
|
## Forum-egenskaper
|
||||||
|
|
||||||
|
### Kategorier
|
||||||
|
|
||||||
|
Valgfri gruppering. Lagres i kommunikasjonsnodens metadata:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"forum_categories": ["Planlegging", "Teknisk", "Generelt"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Eier/admin kan opprette og rekkefølge-sortere kategorier.
|
||||||
|
Meldinger uten kategori havner i "Generelt".
|
||||||
|
|
||||||
|
### Pinning
|
||||||
|
|
||||||
|
Meldinger kan pinnes til toppen av en tråd eller kategori:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "pinned": true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Synlig som 📌 i forum-visningen. Usynlig i chat (eller
|
||||||
|
subtil markør).
|
||||||
|
|
||||||
|
### Lukking
|
||||||
|
|
||||||
|
Tråder kan lukkes (ingen nye svar):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "forum_thread_closed": true }
|
||||||
|
```
|
||||||
|
|
||||||
|
Synlig i forum. I chat kan du fortsatt se meldingene men
|
||||||
|
ikke svare i tråden.
|
||||||
|
|
||||||
|
## Implementering
|
||||||
|
|
||||||
|
### Fase 1: Grunnleggende dualitet
|
||||||
|
- Legg til `forum_thread`, `reply_to`, `forum_category` i
|
||||||
|
meldings-metadata (ingen skjemaendring, bare metadata)
|
||||||
|
- Ny ForumTrait-komponent som viser kommunikasjonsnode som forum
|
||||||
|
- "Bytt visning"-knapp i ChatTrait og ForumTrait
|
||||||
|
- Registrer `forum` i TRAIT_PANEL_INFO
|
||||||
|
|
||||||
|
### Fase 2: Tråding fra chat
|
||||||
|
- Høyreklikk-meny på meldinger i chat: "Opprett tråd"
|
||||||
|
- Chat viser subtil trådmarkør på trådede meldinger
|
||||||
|
|
||||||
|
### Fase 3: Lest/ulest
|
||||||
|
- `last_seen` i member_of edge-metadata
|
||||||
|
- Oppdateres ved scroll (chat) og åpning (forum)
|
||||||
|
- Ulest-indikatorer i chat, forum og Mine ting
|
||||||
|
|
||||||
|
### Fase 4: Forum-egenskaper
|
||||||
|
- Kategorier, pinning, lukking
|
||||||
|
- Kategori-admin i innstillinger
|
||||||
|
|
||||||
|
## Hva som eksisterer allerede
|
||||||
|
|
||||||
|
- Kommunikasjonsnoder med meldinger (✓)
|
||||||
|
- ChatTrait med WebSocket-abonnement (✓)
|
||||||
|
- member_of-edges med metadata (✓)
|
||||||
|
- BlockShell-paneler og trait-system (✓)
|
||||||
|
- Drag-and-drop (✓)
|
||||||
|
|
||||||
|
Hovedsakelig ny ForumTrait-komponent + metadata-konvensjoner.
|
||||||
|
Ingen ny infrastruktur.
|
||||||
Loading…
Add table
Reference in a new issue