From 486d6406f605f16419f24adafbee801a2a097362 Mon Sep 17 00:00:00 2001 From: tristantr Date: Tue, 26 May 2026 10:50:09 +0200 Subject: [PATCH] Allow per-item selection inside the bundle scope - Items in predeploy now have checkboxes (all selected by default) - Select all / Deselect all act on the current folder filter - manualDeselected resets when the folder filter changes - Bundle button uses the selected count, disabled when zero - Draft snapshot keeps only the selected items - Checkboxes hidden in draft / under_review / live phases Co-Authored-By: Claude Opus 4.7 (1M context) --- .../workspaceSettings/DeployToHub.svelte | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte b/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte index 6a1269b77a..799c714623 100644 --- a/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte +++ b/frontend/src/lib/components/workspaceSettings/DeployToHub.svelte @@ -76,6 +76,36 @@ : workspaceItems.filter((i) => selectedFolders.some((f) => i.path.startsWith(f + '/'))) ) let items = $derived(phase === 'predeploy' ? filteredWorkspaceItems : draftItems) + // Per-item selection inside the predeploy filter. Defaults to "all visible items". + let manualDeselected = $state>(new Set()) + $effect(() => { + // Reset deselection when the folder filter changes. + selectedFolders + manualDeselected = new Set() + }) + let selectedItemKeys = $derived( + phase === 'predeploy' + ? filteredWorkspaceItems.filter((i) => !manualDeselected.has(i.key)).map((i) => i.key) + : [] + ) + let allSelected = $derived( + phase === 'predeploy' && selectedItemKeys.length === filteredWorkspaceItems.length + ) + function toggleItem(item: { key: string }) { + const next = new Set(manualDeselected) + if (next.has(item.key)) next.delete(item.key) + else next.add(item.key) + manualDeselected = next + } + function selectAll() { + manualDeselected = new Set() + } + function deselectAll() { + manualDeselected = new Set(filteredWorkspaceItems.map((i) => i.key)) + } + let selectedItems = $derived( + filteredWorkspaceItems.filter((i) => selectedItemKeys.includes(i.key)) + ) let loading = $state(false) let workspaceRateLimit = $state(undefined) let recordableItems = $derived(items.filter((i) => canRecord(i.kind))) @@ -232,7 +262,7 @@ // MOCK: bundle/version push to the Hub is not implemented backend-side. deploying = true try { - for (const it of filteredWorkspaceItems) { + for (const it of selectedItems) { deploymentStatus = { ...deploymentStatus, [it.key]: { status: 'loading' } } await delay(120) deploymentStatus = { ...deploymentStatus, [it.key]: { status: 'deployed' } } @@ -241,7 +271,7 @@ deploymentStatus = {} // Freeze the set of items for this draft cycle. Workspace changes after this point // will not affect the draft until a new draft cycle is started. - draftItems = filteredWorkspaceItems.map((i) => ({ ...i, rec: 'none' })) + draftItems = selectedItems.map((i) => ({ ...i, rec: 'none' })) recordings = {} phase = 'draft' sendUserToast( @@ -445,9 +475,13 @@
{#snippet header()} @@ -472,8 +506,7 @@
  • 3 ? 'opacity-60' : 'opacity-40'}> {stepNum > 3 ? '✓' : '3.'} - Submit for review — send the bundle to the - Windmill team for approval. + Submit for review — send the bundle for approval.
  • @@ -513,9 +546,9 @@ placeholder="All folders" /> - {selectedFolders.length === 0 - ? `Bundling the whole workspace — ${filteredWorkspaceItems.length} items.` - : `Bundling ${filteredWorkspaceItems.length} items from ${selectedFolders.length} folder${selectedFolders.length > 1 ? 's' : ''}.`} + {selectedItems.length} of {filteredWorkspaceItems.length} items selected{selectedFolders.length + ? ` across ${selectedFolders.length} folder${selectedFolders.length > 1 ? 's' : ''}` + : ' from the whole workspace'}.
    {/if} @@ -662,16 +695,16 @@
    {#if phase === 'predeploy'} - Create a bundle with every script, flow, app and resource of your workspace. + Select the items to include — all selected by default. {:else if phase === 'draft'}