Utvider synops-calendar CLI med --url for å hente ICS fra eksterne URLer (Google Calendar, Outlook, etc). Ny calendar_poller i maskinrommet poller samlingers calendar_subscriptions[] med konfigurerbart intervall, etter samme mønster som feed_poller for RSS-feeds. Endringer: - synops-calendar: ny --url parameter + reqwest for HTTP-henting - calendar_poller.rs: bakgrunnsloop som finner forfalne abonnementer - calendar_poll jobbtype i dispatcher med CLI-dispatch til synops-calendar - API: configure_calendar_subscription + remove_calendar_subscription - Migrasjon 031: indeks + prioritetsregel for calendar_poll-jobber
5 KiB
5 KiB
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. CalDAV/ICS-abonnement implementert. ICS-eksport 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(respekterernode_access-matrise) - Sanntidsoppdatering via WebSocket (PG LISTEN/NOTIFY)
- Rute:
- ICS-import (oppgave 29.11):
synops-calendarCLI som parser ICS-filer- Input:
--file <ics>eller--url <url>+--collection-id <uuid> - Duplikatdeteksjon via
metadata.ics_uid - Oppdatering ved re-import
- Input:
- CalDAV-abonnement (oppgave 29.12): Periodisk polling av eksterne kalendere
- Abonnement lagres i
metadata.calendar_subscriptions[]på samlingsnoder calendar_polleri maskinrommet sjekker hvert 60. sekund- Enqueuer
calendar_poll-jobber som spawnersynops-calendar --url - API:
POST /intentions/configure_calendar_subscriptionogremove_calendar_subscription - Støtter Google Calendar, Outlook, og andre ICS/CalDAV-URLer
- Abonnement lagres i
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-eksport (offentlige kalendere →
/cal/{id}.ics) - Varsler/påminnelser via jobbkøen
3. Datamodell (implementert)
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, aldriT00:00:00(tidssone-felle) - Tilgang styres via
node_access-matrisen - Sjekk
docs/erfaringer/adapter_moenster.mdfor hybrid-strategi