From e6cef5a7e39b7dc766ec0db3c79ce0fb4e255be3 Mon Sep 17 00:00:00 2001 From: Diego Imbert Date: Tue, 9 Jun 2026 15:07:11 +0200 Subject: [PATCH] feat(drafts): drop the authed user's circle, mark own drafts with a '*' suffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three tweaks to the home-page Draft badge: 1. Filter the authed user out of `draft_users` before rendering circles. The row already signals 'this user has a draft' via the asterisk (below), so a circle for them would be redundant noise. New `currentUsername` prop on DraftBadge — pass `$userStore?.username` from each row. The tooltip still lists every user (with `(you)` next to the authed one) so the full picture is one hover away. 2. The badge already showed whenever `is_draft || draft_users.length > 0` (per-user OR any-user). Spelled the rationale out in a comment — no logic change. 3. Append '*' to the displayed summary when `is_draft` is true. Falls back to `draft_path`/`path` when summary is empty so the marker never decorates an empty string. Threaded the same expression into ScriptRow / FlowRow / AppRow. Slice/overflow math now keys on the post-filter `otherUsers` list, so dropping the authed user doesn't silently shrink the visible count (e.g. 3 users incl. self → 2 circles, not 1 circle + a '+1' bubble). --- frontend/src/lib/components/DraftBadge.svelte | 40 +++++++++++++++---- .../lib/components/common/table/AppRow.svelte | 9 ++++- .../components/common/table/FlowRow.svelte | 3 +- .../components/common/table/ScriptRow.svelte | 5 ++- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/frontend/src/lib/components/DraftBadge.svelte b/frontend/src/lib/components/DraftBadge.svelte index 4bf200b1fc..9a172cacf4 100644 --- a/frontend/src/lib/components/DraftBadge.svelte +++ b/frontend/src/lib/components/DraftBadge.svelte @@ -23,9 +23,26 @@ is_draft?: boolean draft_only?: boolean draft_users?: DraftUser[] + /** Authed user's workspace username — circles for THIS user are + * omitted because the row already signals their own draft via + * the asterisk appended to the displayed summary. Pass + * `$userStore?.username` from the row. */ + currentUsername?: string | null } - let { is_draft = false, draft_only = false, draft_users = [] }: Props = $props() + let { + is_draft = false, + draft_only = false, + draft_users = [], + currentUsername = undefined + }: Props = $props() + + // Drop the authed user from the circle row — their own draft is + // signalled by the asterisk on the row's summary, so showing both + // would be visual noise. Keep the legacy NULL-username row. + const otherUsers = $derived( + currentUsername ? draft_users.filter((u) => u.username !== currentUsername) : draft_users + ) /** Two-letter uppercase initials from a username — `john.doe`/`john_doe` → * `JD`, `alice` → `AL`, the legacy NULL-email row (no username) → `?`. */ @@ -60,15 +77,22 @@ return PALETTE[hash % PALETTE.length] } - // First 3 circles when ≤3 users; first 2 + a "+N" overflow when 4+. + // First 3 circles when ≤3 OTHER users; first 2 + a "+N" overflow + // when 4+. The slice/overflow math applies to `otherUsers` (post + // current-user filter), not the raw `draft_users` — otherwise + // dropping the authed user would silently change the visible count. const MAX_CIRCLES = 3 const visibleUsers = $derived( - draft_users.length <= MAX_CIRCLES ? draft_users : draft_users.slice(0, MAX_CIRCLES - 1) + otherUsers.length <= MAX_CIRCLES ? otherUsers : otherUsers.slice(0, MAX_CIRCLES - 1) ) const overflowCount = $derived( - draft_users.length > MAX_CIRCLES ? draft_users.length - (MAX_CIRCLES - 1) : 0 + otherUsers.length > MAX_CIRCLES ? otherUsers.length - (MAX_CIRCLES - 1) : 0 ) + // Show the badge whenever ANY draft exists (`draft_users` non-empty) + // OR when the authed user has a draft (`is_draft` true — the list + // endpoint sets this even for paths the user has a draft on but no + // one else does). const showBadge = $derived(is_draft || draft_users.length > 0) @@ -79,7 +103,7 @@ {draft_only ? 'Never deployed — only a draft exists.' : 'Deployed with drafts pending.'}
{#each draft_users as u} - • {fullLabel(u)} + • {fullLabel(u)}{u.username === currentUsername ? ' (you)' : ''} {/each}
{:else if draft_only} @@ -89,11 +113,13 @@ {/if} {/snippet} - {#if draft_users.length > 0} + {#if otherUsers.length > 0} + intentional rather than a stack-of-floating-dots. Only OTHER + users get a circle — the authed user's own draft is + signalled by the row's asterisk. --> {#each visibleUsers as u} Raw {/if} - + {#if app.labels?.length}
{#each app.labels.slice(0, 3) as label} diff --git a/frontend/src/lib/components/common/table/FlowRow.svelte b/frontend/src/lib/components/common/table/FlowRow.svelte index 15ae5c6517..5b03fb421b 100644 --- a/frontend/src/lib/components/common/table/FlowRow.svelte +++ b/frontend/src/lib/components/common/table/FlowRow.svelte @@ -130,7 +130,7 @@ workspaceId={flow.workspace_id ?? $workspaceStore ?? ''} {marked} path={flow.draft_path ?? flow.path} - summary={flow.summary} + summary={flow.is_draft ? `${flow.summary || flow.draft_path || flow.path}*` : flow.summary} {errorHandlerMuted} canFavorite={!flow.draft_only} {depth} @@ -145,6 +145,7 @@ is_draft={flow.is_draft} draft_only={flow.draft_only} draft_users={flow.draft_users} + currentUsername={$userStore?.username} /> {#if flow.labels?.length}
diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte index 298aebe678..f4ff55016b 100644 --- a/frontend/src/lib/components/common/table/ScriptRow.svelte +++ b/frontend/src/lib/components/common/table/ScriptRow.svelte @@ -147,7 +147,9 @@ kind="script" {marked} path={script.draft_path ?? script.path} - summary={script.summary} + summary={script.is_draft + ? `${script.summary || script.draft_path || script.path}*` + : script.summary} {errorHandlerMuted} workspaceId={$workspaceStore ?? ''} canFavorite={!script.draft_only} @@ -192,6 +194,7 @@ is_draft={script.is_draft} draft_only={script.draft_only} draft_users={script.draft_users} + currentUsername={$userStore?.username} /> {#if script.labels?.length}