Ny rute /calendar som viser alle noder med scheduled-edge i et
månedsbasert kalenderrutenett. Bruker edge-metadata { at: ISO8601 }
for tidspunkt, med T12:00:00-konvensjon for heldagshendelser.
Funksjoner:
- Månedsnavigering med «I dag»-snarvei
- Drag-and-drop for å flytte hendelser mellom datoer (updateEdge)
- Inline-oppretting med tittel og valgfritt klokkeslett
- Fargekoding etter node_kind
- Hendelsesliste under rutenett for gjeldende måned
- Kalender-lenke med hendelsesteller på mottak-siden
- Sanntid via SpacetimeDB (edgeStore.byType('scheduled'))
Arkitekturvalg: Bruker scheduled-edges direkte fra SpacetimeDB
i stedet for legacy calendar_events-tabellen. En node blir en
kalenderoppføring ved å ha en scheduled-edge — konsistent med
«hva edges gjør med noder»-prinsippet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
105 lines
4.4 KiB
Markdown
105 lines
4.4 KiB
Markdown
# Feature: Kalender
|
|
**Filsti:** `docs/features/kalender.md`
|
|
|
|
## 1. Konsept
|
|
Månedsbasert kalendervisning for redaksjonell planlegging. Hendelser er nodes i kunnskapsgrafen og kan kobles til episoder, temaer, aktører og kanban-kort. Komplementerer Kanban ("hva" vs "når").
|
|
|
|
## 2. Status
|
|
**Kalendervisning implementert (mars 2026).** Bruker `scheduled`-edges i stedet for
|
|
separat `calendar_events`-tabell. Abonnement, ICS-eksport og SpacetimeDB-sync gjenstår.
|
|
|
|
### Implementert
|
|
- **Fase 1 (v1, mars 2025):** PG-adapter med `calendars` + `calendar_events` (legacy)
|
|
- **Fase 2 (v2, mars 2026):** Edge-basert kalender med `scheduled`-edges
|
|
- Rute: `/calendar` — månedsbasert rutenett
|
|
- Hendelser er noder med `scheduled`-edge (`metadata.at` = ISO 8601 tidspunkt)
|
|
- Heldagshendelser bruker `T12:00:00`-konvensjon (tidssone-trygg)
|
|
- Tidsbaserte hendelser viser klokkeslett i rutenett
|
|
- Drag-and-drop for å flytte hendelser mellom datoer
|
|
- Inline-oppretting: klikk + på en dato, angi tittel og valgfritt klokkeslett
|
|
- Fargekoding basert på `node_kind` (innhold, kommunikasjon, media, samling)
|
|
- Månedsnavigering med «I dag»-knapp
|
|
- Hendelsesliste under rutenett for gjeldende måned
|
|
- Lenke fra mottak-siden med hendelsesteller
|
|
- Tilgang via `nodeVisibility` (respekterer `node_access`-matrise)
|
|
- Sanntidsoppdatering via SpacetimeDB-subscriptions
|
|
|
|
### Gjenstår — Fase 2
|
|
- Kobling til kanban-kort (vis deadline på kalender)
|
|
- Uke- og dagsvisning
|
|
- Gjentakende hendelser (RRULE)
|
|
- Dra-og-slipp for å flytte hendelser mellom datoer
|
|
- Flerdag-hendelser (vises over flere celler)
|
|
- Abonnementsmodell (kalender → kalender via graph_edges)
|
|
- Personlige vs. delte kalendere (via samlings-noder)
|
|
- ICS/CalDAV-eksport
|
|
- SpacetimeDB-modul + hybrid-adapter
|
|
- Varsler/påminnelser via jobbkøen
|
|
|
|
## 3. Datamodell (implementert)
|
|
|
|
```sql
|
|
CREATE TABLE calendars (
|
|
id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE,
|
|
parent_id UUID NOT NULL REFERENCES nodes(id),
|
|
name TEXT NOT NULL,
|
|
color TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE calendar_events (
|
|
id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE,
|
|
calendar_id UUID NOT NULL REFERENCES calendars(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
description TEXT,
|
|
starts_at TIMESTAMPTZ NOT NULL,
|
|
ends_at TIMESTAMPTZ,
|
|
all_day BOOLEAN NOT NULL DEFAULT false,
|
|
color TEXT,
|
|
linked_node UUID REFERENCES nodes(id) ON DELETE SET NULL,
|
|
created_by TEXT REFERENCES users(authentik_id),
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
```
|
|
|
|
Indekser: `(calendar_id)` og `(calendar_id, starts_at)` for effektiv tidsvindu-filtrering.
|
|
|
|
## 4. API-endepunkter
|
|
|
|
| Metode | Sti | Beskrivelse |
|
|
|---|---|---|
|
|
| GET | `/api/calendar/[calendarId]?from=...&to=...` | Hent kalender med hendelser i tidsvindu |
|
|
| POST | `/api/calendar/[calendarId]/events` | Opprett hendelse |
|
|
| PATCH | `/api/calendar/[calendarId]/events/[eventId]` | Oppdater hendelse |
|
|
| DELETE | `/api/calendar/[calendarId]/events/[eventId]` | Slett hendelse |
|
|
|
|
## 5. Brukes av
|
|
|
|
| Konsept | Bruk |
|
|
|---|---|
|
|
| Redaksjonen | Innspillingsdatoer, publiseringsplan, deadlines |
|
|
| Foreningen Liberalistene | Styremøter, arrangementer |
|
|
| Møterommet (fremtidig) | Møteplanlegging |
|
|
|
|
## 6. Tidssone-håndtering
|
|
- Heldagshendelser lagres som `T12:00:00` (middag) — unngår datoforskyvning ved UTC-konvertering
|
|
- Tidshendelser konverteres til ISO via `new Date().toISOString()` (lokal → UTC)
|
|
- Visning bruker `new Date()` som konverterer tilbake til lokal tid
|
|
|
|
## 7. Fremtidig: Abonnementsmodell
|
|
Kalendere kan abonnere på andre kalendere via `SUBSCRIBES_TO`-edge i grafen. Abonnenten ser hendelser read-only.
|
|
|
|
| Type | Eier | Synlighet |
|
|
|------|------|-----------|
|
|
| Samlings-node | Admin for samlings-noden | Alle med tilgang via `node_access` |
|
|
| Personlig | Bruker | Kun eier + eksplisitt deling |
|
|
| Offentlig | Samlings-node | Alle som abonnerer |
|
|
|
|
## 8. Fremtidig: ICS-eksport
|
|
Offentlige kalendere får en ICS-URL (`/cal/{calendar_id}.ics`) for Google Calendar, Apple Calendar etc.
|
|
|
|
## 9. Instruks for Claude Code
|
|
* Bruk `eventsForDate()` med lokal dato-konvertering, ikke UTC-substring
|
|
* Heldagshendelser: `T12:00:00`, aldri `T00:00:00` (tidssone-felle)
|
|
* Tilgang styres via `node_access`-matrisen
|
|
* Sjekk `docs/erfaringer/adapter_moenster.md` for hybrid-strategi
|