diff --git a/frontend/src/lib/components/traits/CalendarTrait.svelte b/frontend/src/lib/components/traits/CalendarTrait.svelte new file mode 100644 index 0000000..c5cfb05 --- /dev/null +++ b/frontend/src/lib/components/traits/CalendarTrait.svelte @@ -0,0 +1,55 @@ + + + + {#snippet children()} + + Åpne kalender → + + {#if events.length > 0} + + {/if} + {/snippet} + diff --git a/frontend/src/lib/components/traits/ChatTrait.svelte b/frontend/src/lib/components/traits/ChatTrait.svelte new file mode 100644 index 0000000..00283a6 --- /dev/null +++ b/frontend/src/lib/components/traits/ChatTrait.svelte @@ -0,0 +1,55 @@ + + + + {#snippet children()} + {#if chatNodes.length === 0} +

Ingen samtaler knyttet til denne samlingen.

+ {:else} + + {/if} + {/snippet} +
diff --git a/frontend/src/lib/components/traits/EditorTrait.svelte b/frontend/src/lib/components/traits/EditorTrait.svelte new file mode 100644 index 0000000..e7519df --- /dev/null +++ b/frontend/src/lib/components/traits/EditorTrait.svelte @@ -0,0 +1,58 @@ + + + + {#snippet children()} +

+ Preset: {preset} + {#if config.allow_collaborators} + · Samarbeid aktivert + {/if} +

+ {#if contentNodes.length === 0} +

Ingen innholdsnoder ennå.

+ {:else} + + {/if} + {/snippet} +
diff --git a/frontend/src/lib/components/traits/GenericTrait.svelte b/frontend/src/lib/components/traits/GenericTrait.svelte new file mode 100644 index 0000000..f627356 --- /dev/null +++ b/frontend/src/lib/components/traits/GenericTrait.svelte @@ -0,0 +1,29 @@ + + + + {#snippet children()} + {#if configKeys.length > 0} +
+ {#each configKeys as key (key)} +
+
{key}:
+
{JSON.stringify(config[key])}
+
+ {/each} +
+ {:else} +

Aktivert, ingen konfigurasjon.

+ {/if} + {/snippet} +
diff --git a/frontend/src/lib/components/traits/KanbanTrait.svelte b/frontend/src/lib/components/traits/KanbanTrait.svelte new file mode 100644 index 0000000..c27c8b8 --- /dev/null +++ b/frontend/src/lib/components/traits/KanbanTrait.svelte @@ -0,0 +1,23 @@ + + + + {#snippet children()} + + Åpne brett → + + {/snippet} + diff --git a/frontend/src/lib/components/traits/PodcastTrait.svelte b/frontend/src/lib/components/traits/PodcastTrait.svelte new file mode 100644 index 0000000..35d58eb --- /dev/null +++ b/frontend/src/lib/components/traits/PodcastTrait.svelte @@ -0,0 +1,80 @@ + + + + {#snippet children()} + {#if episodes.length === 0} +

Ingen episoder ennå.

+ {:else} + + {/if} + {/snippet} +
diff --git a/frontend/src/lib/components/traits/PublishingTrait.svelte b/frontend/src/lib/components/traits/PublishingTrait.svelte new file mode 100644 index 0000000..b27be1d --- /dev/null +++ b/frontend/src/lib/components/traits/PublishingTrait.svelte @@ -0,0 +1,38 @@ + + + + {#snippet children()} +
+ {#if slug} +
+
Slug
+
{slug}
+
+ {/if} +
+
Tema
+
{theme}
+
+ {#if customDomain} +
+
Domene
+
{customDomain}
+
+ {/if} +
+ {/snippet} +
diff --git a/frontend/src/lib/components/traits/RecordingTrait.svelte b/frontend/src/lib/components/traits/RecordingTrait.svelte new file mode 100644 index 0000000..ab9bb91 --- /dev/null +++ b/frontend/src/lib/components/traits/RecordingTrait.svelte @@ -0,0 +1,17 @@ + + + + {#snippet children()} +

LiveKit-studio for opptak og sanntidslyd.

+ {/snippet} +
diff --git a/frontend/src/lib/components/traits/RssTrait.svelte b/frontend/src/lib/components/traits/RssTrait.svelte new file mode 100644 index 0000000..6db46c3 --- /dev/null +++ b/frontend/src/lib/components/traits/RssTrait.svelte @@ -0,0 +1,49 @@ + + + + {#snippet children()} +
+
+ Format: + {format.toUpperCase()} +
+
+ Maks elementer: + {maxItems} +
+ +
+ {/snippet} +
diff --git a/frontend/src/lib/components/traits/TraitPanel.svelte b/frontend/src/lib/components/traits/TraitPanel.svelte new file mode 100644 index 0000000..8c62a01 --- /dev/null +++ b/frontend/src/lib/components/traits/TraitPanel.svelte @@ -0,0 +1,30 @@ + + +
+
+ {#if icon} + + {/if} +

{label}

+
+
+ {#if children} + {@render children()} + {:else} +

Ingen innhold ennå.

+ {/if} +
+
diff --git a/frontend/src/lib/components/traits/TranscriptionTrait.svelte b/frontend/src/lib/components/traits/TranscriptionTrait.svelte new file mode 100644 index 0000000..a67540f --- /dev/null +++ b/frontend/src/lib/components/traits/TranscriptionTrait.svelte @@ -0,0 +1,17 @@ + + + + {#snippet children()} +

Automatisk tale-til-tekst via Whisper.

+ {/snippet} +
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index f9c5766..090588c 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -120,15 +120,33 @@ return null; } - /** Check if a node is a kanban board (collection with board metadata) */ + /** Check if a node is a kanban board (collection with board metadata, no traits) */ function isBoard(node: Node): boolean { if (node.nodeKind !== 'collection') return false; try { const meta = JSON.parse(node.metadata ?? '{}'); - return meta.board === true; + return meta.board === true && !meta.traits; } catch { return false; } } + /** Check if a collection has traits */ + function hasTraits(node: Node): boolean { + if (node.nodeKind !== 'collection') return false; + try { + const meta = JSON.parse(node.metadata ?? '{}'); + return meta.traits && typeof meta.traits === 'object' && Object.keys(meta.traits).length > 0; + } catch { return false; } + } + + /** Get trait names from a collection node */ + function traitNames(node: Node): string[] { + try { + const meta = JSON.parse(node.metadata ?? '{}'); + if (meta.traits && typeof meta.traits === 'object') return Object.keys(meta.traits); + } catch { /* ignore */ } + return []; + } + /** Count scheduled events for badge display */ const scheduledCount = $derived.by(() => { if (!connected) return 0; @@ -366,7 +384,37 @@