From 4b8ce53777d4cbaaaa01012e0f67b3314e1fe38c Mon Sep 17 00:00:00 2001 From: vegard Date: Thu, 19 Mar 2026 22:09:20 +0000 Subject: [PATCH] Flow Meter: varighetsindikator for storyboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ny FlowMeter-komponent som viser episodeprogresjon som en fargekodet linje (rød→gul→grønn) med pulsering nær mål. StoryboardTrait viser Flow Meter øverst og kort gruppert etter status (Klar, Tatt opp, Droppet). Ref: docs/proposals/flow_meter.md --- .../lib/components/traits/FlowMeter.svelte | 162 ++++++++++ .../components/traits/StoryboardTrait.svelte | 292 ++++++++++++++++++ frontend/src/lib/workspace/types.ts | 1 + .../src/routes/collection/[id]/+page.svelte | 7 +- 4 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 frontend/src/lib/components/traits/FlowMeter.svelte create mode 100644 frontend/src/lib/components/traits/StoryboardTrait.svelte diff --git a/frontend/src/lib/components/traits/FlowMeter.svelte b/frontend/src/lib/components/traits/FlowMeter.svelte new file mode 100644 index 0000000..11ddf7e --- /dev/null +++ b/frontend/src/lib/components/traits/FlowMeter.svelte @@ -0,0 +1,162 @@ + + +
+
+
+
+
+ {formatMinutes(recordedMinutes)} + / + {formatMinutes(targetMinutes)} + {#if overGoal} + Over mål + {:else if percent >= 70} + Solid + {:else if percent >= 30} + Trenger mer + {:else} + For kort + {/if} +
+
+ + diff --git a/frontend/src/lib/components/traits/StoryboardTrait.svelte b/frontend/src/lib/components/traits/StoryboardTrait.svelte new file mode 100644 index 0000000..08f1e5b --- /dev/null +++ b/frontend/src/lib/components/traits/StoryboardTrait.svelte @@ -0,0 +1,292 @@ + + +
+ + + + +
+ {#each ['tatt_opp', 'klar', 'droppet'] as status (status)} + {@const group = cardsByStatus[status] ?? []} + {#if group.length > 0} +
+
+ {statusIcons[status]} + {statusLabels[status]} + {group.length} +
+ {#each group as card (card.node.id)} +
+ {card.node.title || 'Uten tittel'} + {#if card.durationSeconds > 0} + + {Math.floor(card.durationSeconds / 60)}:{(card.durationSeconds % 60).toString().padStart(2, '0')} + + {/if} +
+ {/each} +
+ {/if} + {/each} + + {#if cards.length === 0} +
+

Ingen kort ennå.

+

+ Legg til kort med status for å se episodeprogresjonen i Flow Meter. +

+
+ {/if} +
+
+ + diff --git a/frontend/src/lib/workspace/types.ts b/frontend/src/lib/workspace/types.ts index 60f0855..17e982d 100644 --- a/frontend/src/lib/workspace/types.ts +++ b/frontend/src/lib/workspace/types.ts @@ -58,6 +58,7 @@ export const TRAIT_PANEL_INFO: Record = { mindmap: { title: 'Tankekart', icon: '🧠', defaultWidth: 600, defaultHeight: 500 }, ai: { title: 'AI-verktøy', icon: '🤖', defaultWidth: 420, defaultHeight: 500 }, usage: { title: 'Ressursforbruk', icon: '📊', defaultWidth: 380, defaultHeight: 350 }, + storyboard: { title: 'Storyboard', icon: '🎬', defaultWidth: 500, defaultHeight: 450 }, }; /** Default info for unknown traits */ diff --git a/frontend/src/routes/collection/[id]/+page.svelte b/frontend/src/routes/collection/[id]/+page.svelte index 692c8ad..7f3d8da 100644 --- a/frontend/src/routes/collection/[id]/+page.svelte +++ b/frontend/src/routes/collection/[id]/+page.svelte @@ -36,6 +36,7 @@ import MixerTrait from '$lib/components/traits/MixerTrait.svelte'; import OrchestrationTrait from '$lib/components/traits/OrchestrationTrait.svelte'; import MindMapTrait from '$lib/components/traits/MindMapTrait.svelte'; + import StoryboardTrait from '$lib/components/traits/StoryboardTrait.svelte'; import GenericTrait from '$lib/components/traits/GenericTrait.svelte'; import TraitAdmin from '$lib/components/traits/TraitAdmin.svelte'; @@ -70,7 +71,7 @@ /** Traits with dedicated components */ const knownTraits = new Set([ 'editor', 'chat', 'kanban', 'podcast', 'publishing', - 'rss', 'calendar', 'recording', 'transcription', 'studio', 'mixer', 'orchestration', 'mindmap' + 'rss', 'calendar', 'recording', 'transcription', 'studio', 'mixer', 'orchestration', 'mindmap', 'storyboard' ]); /** Count of child nodes */ @@ -365,6 +366,8 @@ {:else if trait === 'mindmap'} + {:else if trait === 'storyboard'} + {/if} {:else} @@ -424,6 +427,8 @@ {:else if trait === 'mindmap'} + {:else if trait === 'storyboard'} + {/if} {:else}