-- Meldingsboks: Universell diskusjonsprimitiv -- Erstatter separate tabeller for kanban-kort, kalenderhendelser, faktoider og notater. -- Alle disse blir meldingsbokser (messages) med view-config-tabeller. -- Se docs/features/meldingsboks.md for full spec. -- -- Avhenger av: 0001, 0002, 0003, 0004 BEGIN; -- ============================================================ -- 1. ALTER messages-tabellen -- ============================================================ -- channel_id nullable (notater, standalone-bokser trenger ikke channel) ALTER TABLE messages ALTER COLUMN channel_id DROP NOT NULL; -- Nye kolonner ALTER TABLE messages ADD COLUMN title TEXT; ALTER TABLE messages ADD COLUMN pinned BOOLEAN NOT NULL DEFAULT false; ALTER TABLE messages ADD COLUMN visibility TEXT NOT NULL DEFAULT 'workspace'; ALTER TABLE messages ADD COLUMN updated_at TIMESTAMPTZ NOT NULL DEFAULT now(); -- Indeks for reply_to (tråd-oppslag) CREATE INDEX IF NOT EXISTS idx_messages_reply ON messages(reply_to) WHERE reply_to IS NOT NULL; -- updated_at trigger CREATE TRIGGER trg_messages_updated_at BEFORE UPDATE ON messages FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- ============================================================ -- 2. View-config-tabeller -- ============================================================ -- Kanban: view-metadata for meldingsbokser som vises som kort CREATE TABLE kanban_card_view ( message_id UUID PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE, column_id UUID NOT NULL REFERENCES kanban_columns(id) ON DELETE CASCADE, position REAL NOT NULL DEFAULT 0, color TEXT, assignee_id TEXT REFERENCES users(authentik_id) ON DELETE SET NULL ); CREATE INDEX idx_kanban_card_view_column ON kanban_card_view(column_id, position); -- Kalender: view-metadata for meldingsbokser som vises som hendelser CREATE TABLE calendar_event_view ( message_id UUID PRIMARY KEY REFERENCES messages(id) ON DELETE CASCADE, calendar_id UUID NOT NULL REFERENCES calendars(id) ON DELETE CASCADE, starts_at TIMESTAMPTZ NOT NULL, ends_at TIMESTAMPTZ, all_day BOOLEAN NOT NULL DEFAULT false, color TEXT ); CREATE INDEX idx_calendar_event_view_calendar ON calendar_event_view(calendar_id, starts_at); -- ============================================================ -- 3. Migrer kanban_cards → messages + kanban_card_view -- ============================================================ -- Oppdater node_type til 'melding' UPDATE nodes SET node_type = 'melding' WHERE id IN (SELECT id FROM kanban_cards); -- Opprett meldingsbokser fra kanban-kort INSERT INTO messages (id, channel_id, author_id, message_type, title, body, created_at, updated_at) SELECT kc.id, NULL, kc.created_by, 'text', kc.title, COALESCE(kc.description, ''), kc.created_at, kc.updated_at FROM kanban_cards kc; -- Opprett kanban view-config INSERT INTO kanban_card_view (message_id, column_id, position, assignee_id) SELECT kc.id, kc.column_id, kc.position, kc.assignee_id FROM kanban_cards kc; -- ============================================================ -- 4. Migrer calendar_events → messages + calendar_event_view -- ============================================================ UPDATE nodes SET node_type = 'melding' WHERE id IN (SELECT id FROM calendar_events); INSERT INTO messages (id, channel_id, author_id, message_type, title, body, created_at, updated_at) SELECT ce.id, NULL, ce.created_by, 'text', ce.title, COALESCE(ce.description, ''), ce.created_at, ce.created_at FROM calendar_events ce; INSERT INTO calendar_event_view (message_id, calendar_id, starts_at, ends_at, all_day, color) SELECT ce.id, ce.calendar_id, ce.starts_at, ce.ends_at, ce.all_day, ce.color FROM calendar_events ce; -- ============================================================ -- 5. Reaksjoner (erstatter message_votes og factoid_votes) -- ============================================================ CREATE TABLE message_reactions ( message_id UUID NOT NULL REFERENCES messages(id) ON DELETE CASCADE, user_id TEXT NOT NULL REFERENCES users(authentik_id) ON DELETE CASCADE, reaction TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (message_id, user_id, reaction) ); -- Migrer eksisterende message_votes til reactions INSERT INTO message_reactions (message_id, user_id, reaction, created_at) SELECT mv.message_id, mv.user_id, CASE WHEN mv.vote = 1 THEN 'upvote' ELSE 'downvote' END, mv.created_at FROM message_votes mv; -- ============================================================ -- 6. Migrer factoids → messages -- ============================================================ UPDATE nodes SET node_type = 'melding' WHERE id IN (SELECT id FROM factoids); INSERT INTO messages (id, channel_id, author_id, message_type, body, created_at, updated_at) SELECT f.id, NULL, f.created_by, 'factoid', f.body, f.created_at, f.created_at FROM factoids f; -- Flytt factoid_votes til reactions INSERT INTO message_reactions (message_id, user_id, reaction, created_at) SELECT fv.factoid_id, fv.user_id, CASE WHEN fv.vote = 1 THEN 'upvote' ELSE 'downvote' END, fv.created_at FROM factoid_votes fv ON CONFLICT (message_id, user_id, reaction) DO NOTHING; -- ============================================================ -- 7. Migrer notes → messages -- ============================================================ UPDATE nodes SET node_type = 'melding' WHERE id IN (SELECT id FROM notes); INSERT INTO messages (id, channel_id, author_id, message_type, title, body, created_at, updated_at) SELECT n.id, NULL, n.created_by, 'text', n.title, COALESCE(n.content, ''), n.created_at, n.updated_at FROM notes n; -- ============================================================ -- 8. Drop gamle tabeller -- ============================================================ -- Triggers først DROP TRIGGER IF EXISTS trg_kanban_cards_updated_at ON kanban_cards; DROP TRIGGER IF EXISTS trg_calendar_events_updated_at ON calendar_events; DROP TRIGGER IF EXISTS trg_notes_updated_at ON notes; -- Tabeller (rekkefølge: FK-avhengigheter) DROP TABLE factoid_votes; DROP TABLE factoids; DROP TABLE message_votes; DROP TABLE kanban_cards; DROP TABLE calendar_events; DROP TABLE notes; -- ============================================================ -- RLS: Ikke nødvendig på messages/view-config-tabeller. -- Workspace-isolasjon arves via FK til nodes (samme mønster -- som episodes, segments, entities). -- ============================================================ COMMIT; -- ============================================================ -- 9. Entities (erstatter actors + topics) -- ============================================================ -- Alt som kan nevnes med # er en entitet: personer, organisasjoner, -- steder, temaer, konsepter. Én tabell, én autocomplete. -- -- ALTER TYPE ADD VALUE kan ikke kjøres i en transaksjon (PG < 16), -- derfor utenfor BEGIN/COMMIT-blokken. ALTER TYPE node_type ADD VALUE IF NOT EXISTS 'entitet'; BEGIN; CREATE TABLE entities ( id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE, name TEXT NOT NULL, type TEXT NOT NULL, -- 'person', 'organisasjon', 'sted', 'tema', 'konsept' aliases TEXT[] DEFAULT '{}', -- Forkortelser, kallenavn: {'JGS', 'Støre'} avatar_url TEXT ); CREATE INDEX idx_entities_name ON entities(name); CREATE INDEX idx_entities_aliases ON entities USING GIN(aliases); -- Migrer actors → entities INSERT INTO entities (id, name, type) SELECT id, name, COALESCE(type, 'person') FROM actors; UPDATE nodes SET node_type = 'entitet' WHERE id IN (SELECT id FROM actors); -- Migrer topics → entities INSERT INTO entities (id, name, type) SELECT id, name, 'tema' FROM topics; UPDATE nodes SET node_type = 'entitet' WHERE id IN (SELECT id FROM topics); DROP TABLE actors; DROP TABLE topics; -- ============================================================ -- RLS: Ikke nødvendig på messages/view-config/entities. -- Workspace-isolasjon arves via FK til nodes (samme mønster -- som episodes, segments). -- ============================================================ COMMIT;