mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 08:02:47 +00:00
feat: a fork's band counts its drafts beside its drift, and every count opens what it names
A fork that had drifted stopped saying anything about its drafts: the banner printed the draft count only while the fork was in sync, and the drift badges replaced it the moment there was anything to deploy. A fork can be 86 ahead, 39 behind and holding 128 drafts; it now says so. All four counts open the page that holds them — ahead the deploy direction, behind `?dir=update`, conflicts the side they are resolved from before deploying, drafts the drafts half. The button beside them still chooses a direction on the reader's behalf; a badge means the one thing it names. The colours and the icons are the compare page's, so the counts in the bar and the rows behind them say the same thing the same way: ahead green, behind blue, conflicts orange. Drafts share blue with behind and are told apart by a pencil and by naming what they count, rather than by an arrow that would read as a third direction. Both arrows are straight, here and on the compare page. "Review changes" replaces "Review & Deploy Changes", and it renders in every state. What the comparison has to say — still counting, or failed — is a mark beside the button rather than a branch that replaces it: a fork whose count is unfinished is exactly when a reader wants the page that counts properly. The drafts banner outside a fork drops "This workspace has", so the count reads the same wherever it appears. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
04c6a9fbdc
commit
87a975f025
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
AlertTriangle,
|
||||
ArrowDownRight,
|
||||
ArrowDown,
|
||||
ArrowRight,
|
||||
ArrowUpRight,
|
||||
ArrowUp,
|
||||
Building,
|
||||
CircleCheck,
|
||||
CircleX,
|
||||
@@ -1650,13 +1650,13 @@
|
||||
{#if isConflict || existsInBothWorkspaces}
|
||||
{#if diff.ahead > 0}
|
||||
<Badge color="green" size="xs">
|
||||
<ArrowUpRight class="w-3 h-3 inline" />
|
||||
<ArrowUp class="w-3 h-3 inline" />
|
||||
{diff.ahead} ahead
|
||||
</Badge>
|
||||
{/if}
|
||||
{#if diff.behind > 0}
|
||||
<Badge color="blue" size="xs">
|
||||
<ArrowDownRight class="w-3 h-3 inline" />
|
||||
<ArrowDown class="w-3 h-3 inline" />
|
||||
{diff.behind} behind
|
||||
</Badge>
|
||||
{/if}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import PageHeaderContent from '$lib/components/PageHeaderContent.svelte'
|
||||
import { Badge } from './common'
|
||||
import { AlertTriangle, ArrowDown, ArrowUp, Pencil } from 'lucide-svelte'
|
||||
import { workspaceStore, userWorkspaces, userStore, type UserExt } from '$lib/stores'
|
||||
import type { WorkspaceComparison } from '$lib/gen'
|
||||
import { fetchWorkspaceComparison } from '$lib/workspaceComparison'
|
||||
@@ -137,6 +138,18 @@
|
||||
|
||||
// Opens the direction the button offers, so the label and the list agree: a fork
|
||||
// with nothing to deploy lands on the update side, not on an empty deploy list.
|
||||
/** The compare page opened on one direction, for a badge that counts exactly that. The button
|
||||
* beside them still chooses on the reader's behalf; a badge means the one thing it names. */
|
||||
function openCompareDir(dir: 'deploy_to' | 'update') {
|
||||
if (!parentWorkspaceId || !$workspaceStore) return
|
||||
goto(
|
||||
'/forks/compare?workspace_id=' +
|
||||
encodeURIComponent($workspaceStore) +
|
||||
(dir === 'update' ? '&dir=update' : ''),
|
||||
{ replaceState: true }
|
||||
)
|
||||
}
|
||||
|
||||
function openComparisonDrawer() {
|
||||
if (parentWorkspaceId && $workspaceStore) {
|
||||
const dir = hasAnswer && changesAhead === 0 ? '&dir=update' : ''
|
||||
@@ -188,6 +201,9 @@
|
||||
{#snippet forkAction()}
|
||||
{@const total = comparison?.summary.total_diffs ?? 0}
|
||||
{@const conflicts = comparison?.summary.conflicts ?? 0}
|
||||
<!-- What the comparison has to say is a mark beside the button, never instead of it: a fork
|
||||
still being counted, or one whose count failed, is exactly when a reader wants the page
|
||||
that does the counting properly. The button below renders in every state. -->
|
||||
{#if loading}
|
||||
<span class="text-2xs text-tertiary">Checking for changes…</span>
|
||||
{:else if error}
|
||||
@@ -196,6 +212,71 @@
|
||||
<Badge color="blue" small>
|
||||
{draftCount} draft{draftCount !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
{:else if total > 0}
|
||||
<!-- Which way the drift goes is the thing to know at a glance: ahead is what this fork has
|
||||
to give its parent, behind is what it has yet to take. -->
|
||||
<!-- The colours and the icons the compare page gives these three, so the counts in the bar
|
||||
and the rows behind the button say the same thing the same way. -->
|
||||
{#if changesAhead > 0}
|
||||
<Badge
|
||||
color="green"
|
||||
small
|
||||
clickable
|
||||
onclick={() => openCompareDir('deploy_to')}
|
||||
title="{changesAhead} ahead of {parentWorkspaceId} — review what this {currentNoun} has to give"
|
||||
>
|
||||
<ArrowUp class="w-3 h-3 inline" />
|
||||
{changesAhead}
|
||||
</Badge>
|
||||
{/if}
|
||||
{#if changesBehind > 0}
|
||||
<Badge
|
||||
color="blue"
|
||||
small
|
||||
clickable
|
||||
onclick={() => openCompareDir('update')}
|
||||
title="{changesBehind} behind {parentWorkspaceId} — review what this {currentNoun} has yet to take"
|
||||
>
|
||||
<ArrowDown class="w-3 h-3 inline" />
|
||||
{changesBehind}
|
||||
</Badge>
|
||||
{/if}
|
||||
{#if conflicts > 0}
|
||||
<!-- A conflict is ahead and behind at once, so it has no direction of its own; it opens
|
||||
the side the reader resolves it from before deploying. -->
|
||||
<Badge
|
||||
color="orange"
|
||||
small
|
||||
clickable
|
||||
onclick={() => openCompareDir('deploy_to')}
|
||||
title="{conflicts} conflicting item{conflicts !== 1 ? 's' : ''} — review them"
|
||||
>
|
||||
<AlertTriangle class="w-3 h-3 inline" />
|
||||
{conflicts} conflict{conflicts !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
{/if}
|
||||
<!-- Drafts are a different axis from the drift beside them: ahead and behind count deployed
|
||||
items against the parent, this counts work in this fork that is not deployed anywhere
|
||||
yet. It shares blue with "behind" and is told apart by the pencil and by naming what it
|
||||
counts, rather than by an arrow that would read as a third direction. Clicking goes to
|
||||
the drafts half of the compare page rather than the drawer the button opens. It shows at
|
||||
every drift — a fork both behind and holding drafts said nothing about the drafts. -->
|
||||
{#if draftCount > 0}
|
||||
<Badge
|
||||
color="blue"
|
||||
small
|
||||
clickable
|
||||
onclick={openDraftCompare}
|
||||
title="{draftCount} draft{draftCount !== 1
|
||||
? 's'
|
||||
: ''} in this {currentNoun}, not deployed anywhere yet — review and deploy"
|
||||
>
|
||||
<Pencil class="w-3 h-3 inline" />
|
||||
{draftCount} draft{draftCount !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
{/if}
|
||||
{/if}
|
||||
{#if showDraftsOnly}
|
||||
<Button
|
||||
variant="subtle"
|
||||
unifiedSize="sm"
|
||||
@@ -204,32 +285,17 @@
|
||||
>
|
||||
Review & deploy drafts
|
||||
</Button>
|
||||
{:else if total > 0}
|
||||
<!-- Which way the drift goes is the thing to know at a glance: ahead is what this fork has
|
||||
to give its parent, behind is what it has yet to take. -->
|
||||
{#if changesAhead > 0}
|
||||
<Badge color="blue" small title="{changesAhead} ahead of {parentWorkspaceId}">
|
||||
↑ {changesAhead}
|
||||
</Badge>
|
||||
{/if}
|
||||
{#if changesBehind > 0}
|
||||
<Badge color="gray" small title="{changesBehind} behind {parentWorkspaceId}">
|
||||
↓ {changesBehind}
|
||||
</Badge>
|
||||
{/if}
|
||||
{#if conflicts > 0}
|
||||
<Badge color="orange" small title="{conflicts} conflicting item{conflicts !== 1 ? 's' : ''}">
|
||||
{conflicts} conflict{conflicts !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
{/if}
|
||||
{:else}
|
||||
<Button
|
||||
variant="subtle"
|
||||
unifiedSize="sm"
|
||||
onclick={openComparisonDrawer}
|
||||
title={`${forkAheadBehindMessage(changesAhead, changesBehind)} ${parentWorkspaceId} over ${total} items`}
|
||||
title={hasAnswer
|
||||
? `${forkAheadBehindMessage(changesAhead, changesBehind)} ${parentWorkspaceId} over ${total} items`
|
||||
: `Review this ${currentNoun} against ${parentWorkspaceId}`}
|
||||
>
|
||||
{#if !hasAnswer || changesAhead > 0}
|
||||
Review & Deploy Changes
|
||||
Review changes
|
||||
{:else}
|
||||
Review & Update {currentNoun}
|
||||
{/if}
|
||||
|
||||
@@ -37,9 +37,8 @@
|
||||
{/if}
|
||||
|
||||
{#snippet draftsAction()}
|
||||
<!-- A count on its own leaves the reader to work out what it counts; the sentence says it.
|
||||
On a phone the sentence goes and the badge becomes the button: the count is the part that
|
||||
has to be seen, and the bar has room for one thing. -->
|
||||
<!-- On a phone the badge becomes the button: the count is the part that has to be seen, and
|
||||
the bar has room for one thing. -->
|
||||
{#if phone}
|
||||
<Button
|
||||
variant="subtle"
|
||||
@@ -50,7 +49,6 @@
|
||||
<Badge color="blue" small>{draftCount}</Badge>
|
||||
</Button>
|
||||
{:else}
|
||||
<span class="shrink-0 text-2xs text-tertiary">This workspace has</span>
|
||||
<Badge color="blue" small>
|
||||
{draftCount} draft{draftCount !== 1 ? 's' : ''}
|
||||
</Badge>
|
||||
|
||||
Reference in New Issue
Block a user