synops/frontend/src/lib/components/traits/RssTrait.svelte
vegard e8a1a80652 Valider fase 22: STDB-migrering fullført, ingen rester i aktiv kode
Validering av fase 22 (SpacetimeDB-migrering) bekrefter:

1. WebSocket-sanntid fungerer:
   - maskinrommet lytter på PG NOTIFY-kanaler (node_changed, edge_changed,
     access_changed, mixer_channel_changed)
   - Enrichment av events med fulle rader fra PG
   - Broadcast via tokio::broadcast til WebSocket-klienter
   - Tilgangskontroll filtrerer events per bruker
   - Frontend kobler til /ws med JWT, mottar initial_sync + inkrementelle events

2. PG LISTEN/NOTIFY-triggere verifisert i database:
   - 4 notify-funksjoner: notify_node_change, notify_edge_change,
     notify_access_change, notify_mixer_channel_change
   - 4 triggere: nodes_notify, edges_notify, node_access_notify,
     mixer_channels_notify

3. Ingen STDB-rester i aktiv kode/konfig:
   - maskinrommet/src/: rent
   - Cargo.toml: ingen spacetimedb-avhengigheter
   - docker-compose.yml: ingen spacetimedb-tjeneste
   - Caddyfile: ingen spacetimedb-proxy
   - Eneste funn: frontend/src/lib/spacetime/ katalognavn —
     omdøpt til frontend/src/lib/realtime/ (32 filer oppdatert)
   - Historiske referanser i docs/arkiv og scripts/synops.md er OK
2026-03-18 16:31:16 +00:00

50 lines
1.5 KiB
Svelte

<script lang="ts">
import type { Node } from '$lib/realtime';
import TraitPanel from './TraitPanel.svelte';
interface Props {
collection?: Node;
config: Record<string, unknown>;
}
let { collection, config }: Props = $props();
const format = $derived((config.format as string) ?? 'rss');
const maxItems = $derived((config.max_items as number) ?? 50);
/** Build the feed URL from publishing slug if available */
const feedUrl = $derived.by(() => {
if (!collection) return '';
try {
const meta = JSON.parse(collection.metadata ?? '{}');
const slug = meta.traits?.publishing?.slug;
if (slug) return `/pub/${slug}/feed.xml`;
} catch { /* ignore */ }
return `/api/rss/${collection.id}`;
});
</script>
<TraitPanel name="rss" label="RSS-feed" icon="📡">
{#snippet children()}
<div class="space-y-2 text-sm">
<div class="flex items-center gap-2">
<span class="text-xs text-gray-500">Format:</span>
<span class="rounded bg-orange-50 px-2 py-0.5 text-xs font-medium text-orange-700">{format.toUpperCase()}</span>
</div>
<div>
<span class="text-xs text-gray-500">Maks elementer:</span>
<span class="ml-1 text-gray-900">{maxItems}</span>
</div>
<div class="mt-2">
<a
href={feedUrl}
target="_blank"
rel="noopener"
class="inline-flex items-center gap-1.5 rounded bg-orange-100 px-3 py-1.5 text-xs font-medium text-orange-800 hover:bg-orange-200"
>
Feed-URL &rarr;
</a>
</div>
</div>
{/snippet}
</TraitPanel>