Files
windmill/frontend/src/lib/components/flows/content/FlowWhileLoop.svelte
T
GuilhemandClaude Opus 4.8 09c8f3b1f3 feat: redesign flow step, loop and branch settings panels (#10026)
* feat: responsive modal step panel for the flow editor in sessions

On narrow layouts the flow editor's step-details pane opens as a modal
(double-click a graph node) instead of a split pane, with a dock/float
toggle. Scoped to sessions via allowModalPanel; the full-page editor is
unchanged.

- FlowEditor: modal/docked modes gated by mount width + allowModalPanel,
  small header (step-id Badge + subtle dock/close), standing
  double-click hint, and a per-step hint in the name tooltip
- selectionManager: onSelectIntent hook so flow-level panels (settings,
  input, triggers…) open the modal on single click
- PropPickerWrapper: collapse the prop picker until connect and animate
  it in via AnimatedPane (runs-page pattern), no blue connect ring in
  modal mode
- StepInputGen: drop the TAB/Wand autocompletion button + spinner
  (feature still works via focus + Tab)
- InputTransformForm: decouple the Help dropdown from the AI suggestion
- FlowModuleHeader: move 'Save to workspace' into an ellipsis dropdown

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: loop editor rendering and nested splitpanes splitters in the sessions modal

- Loop iterator/parallelism: keep the picker split pane (forceExpanded) so
  the editor fills its box and the picker shows; the collapse-until-connect
  mode stays for the step inputs
- Remove the intrusive AI TAB/Wand autocompletion button from IteratorGen
  (generation still runs headless via focus + Tab)
- Size the iterator connect plug and restyle the loop header/labels/toggles
- Scope the global `.splitter-hidden` splitter-hiding rule to direct children
  so it no longer leaks into nested Splitpanes under the sessions preview

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: redesign flow step advanced settings as a single toggle-first column

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: taller step test pane by default and restyle advanced section titles

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: show flow run-settings params disabled when a setting is toggled off

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: single-column for-loop panel reusing the run-settings accordion

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: single-column while-loop panel reusing the run-settings accordion

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: single-column branch panels reusing the run-settings accordion

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: auto-open modal panel when creating an AI agent tool

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: redesign branch panels with card layout and shared predicate editor

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor: remove per-setting status badges from flow map nodes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: sync package-lock after windmill-utils-internal bump

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style: polish prop-picker plug button and branch panel layouts

* fix: persist skip-if-stopped toggles in early stop settings

* fix: open the step panel modal on demand and cap its width

* fix: restore graph step setting badges, strip panel header chips instead

* feat: docked panel header with detach action and open-details step menu

* feat: width-based panel mode on every surface with inline detach action

* refactor: single source for flow step settings and their defaults

* docs: pin flow editor vocabulary in CONTEXT.md

* fix: open the trigger panel on double click or a specific trigger

* fix: keep module pickers inside their pane and dismissable

* fix: drop the misleading chevron on the MCP tool entry

* fix: resolve flow approvals against the job's workspace, not the nav one

* refactor: derive the approval workspace from the job, not from callers

* fix: restore S3 snippets and gate params while their setting is off

* fix: restore branch mock controls and address review findings

* chore: drop stray debug log from the flow map item

* feat: pinned output section for loop and branch panels

* fix: open the panel for deliberate navigation from the flow header

* perf: mount branch predicate editors on demand

* fix: skip predicate picker previews the previous step's result

* fix: flow-level graph nodes open their panel on a single click

* fix: open the step panel for AI chat selections, not for undo

* chore: drop dead console.log and duplicated modalPanel doc

* fix: re-sync expression editors and scope error-handler settings

* fix: match the failure module exactly and ignore unselectable nodes

* fix: keep concurrency editable, honour module cache_ttl, tighten panel ids

* fix: open panel from indirect selections, use presence for value-driven toggles

* fix: don't open settings on error-handler delete, flush editors on unmount

* fix: guard editor destroy flush, keep retry kind reachable

* refactor: name the run settings panel after the domain vocabulary

* fix: only write editor flushes to the step they belong to

* fix: bind step panels by id so a delete can't retarget editor writes

* fix: don't let the trigger picker's escape close the drawer beneath it

* docs: condense two comments to the constraint they record

* fix: arbitrate escape through the overlay stack instead of deferring to it

* fix: key nested step blocks by identity so anchored bindings can't go stale

* fix: untrack the overlay-stack push and drop the frozen branch binding

* chore: state the escape rationale once, key branch lists, format

* fix: let the topmost overlay own escape instead of the graph

* fix: keep the dynamic-input help box out of static template fields

* fix: restore the graph connect on the for-loop iterator

* fix: end connect mode with the modal and keep it to docked panels

* fix: never enter graph connect mode from the modal panel

* fix: reveal inserted steps, restore editor pane size, unleak the drawer stack

* fix: keep the enable-AI popover reachable in session panes

* feat: add the connect policy and its single armed slot

* refactor: one picker for every expression input

* refactor: route every connect through one armed slot

* fix: give every connect button the same footprint

* fix: keep the connect ring from showing through the button

* fix: keep flow card actions right-aligned beside the detach button

* fix: give the connect ring an opaque ground to mask against

* feat: dock the panel back without reopening it

* feat: dock the panel from the graph control bar

* style: round the graph control bar and size its glyphs

* style: customize the graph controls through their supported api

* style: build the graph control bar from lucide icons

* fix: use the graph's tooltip component in the zoom controls

* style: pad the graph controls and enlarge their glyphs

* style: pad the graph controls and put dock at the bar's end

* refactor: give settings rows the same popover picker as other expressions

* fix: pass the wrapper's pickable properties to nested inputs

* refactor: stack step settings and render every expression through the step input form

* feat: split loop panels into tabs and rework the approval form

* feat: anchor drawers to their host pane and give them a size floor

* fix: mark the loop iterator expression as required

* refactor: badge ee-only toggles instead of a warning line

* fix: flag an empty loop iterator expression as an error

* refactor: pick the early-stop flow status from one toggle group

* fix: keep parallel loops uncapped unless a limit is opted into

* fix: scope the overlay stack to its host and disarm connect on dismissal

* fix: anchor the trigger picker to its host pane

* feat: move diff into the menu when the top bar is narrow

* fix: gate the result logs toggle to the graph popover

* feat: raise the modal-panel breakpoint to 1280

* fix: anchor flow editor popovers and fullscreen to their host pane

* fix: anchor overlays to their host pane and mute them when hidden

* fix: portal hosted modals and menus into the pane they anchor to

* fix: keep non-listening dialogs off the overlay stack

* fix: drop the topmost gate from confirmation dialogs

* fix: silence overlays in a collapsed preview panel

* feat: rework the branch panels with tabs, reordering and add/delete

* refactor: fold the detached-panel chrome into the card header

* fix: give every flow panel a titled card header

* fix: stop the step panel oscillating on an auto-height editor

* feat: consolidate script panel actions and restore branch predicate AI

* fix: restore the logs toggle on the flow result popover

* fix: collapse the idle property picker in modal step panels

* fix: stop the docked pane scrolling alongside its panel

* fix: space the last settings row off the panel bottom

* revert: always show the property picker pane in step panels

* chore: keep the inline script AI button identical to main

* fix: ask for AI input suggestions on click, not on hover

* fix: keep graph connects armed and remount the parallelism input

* style: reveal the predicate AI button on row hover

* style: give branch cards a handle and delete column

* refactor: arbitrate flow overlay escape through Disposable

* fix: give the popover picker its results and re-narrow the EE badge

* docs: correct loopSubset and guard the modal width measurement

* fix: insert picked properties at the cursor in expression inputs

* fix: give the expanded-subflow panel the shared header chrome

* style: rename the suspend setting to Suspend until approval/resume

* feat: open a step's modal when clicking the step already selected

* feat: add an auto/attached/detached toggle for the step panel

* refactor: pick the step panel's placement from one named menu

* refactor: keep the panel-mode module's exports to what is consumed

* feat: show each configured setting's value on its badge

* fix: carry the suspend rename into the step settings registry

* docs: name both gestures in the step explore hint

* test: pin where the step panel goes for a given width and preference

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 12:25:25 +02:00

156 lines
5.0 KiB
Svelte

<script lang="ts">
import { getContext, tick } from 'svelte'
import FlowCard from '../common/FlowCard.svelte'
import type { FlowEditorContext } from '../types'
import Toggle from '$lib/components/Toggle.svelte'
import { Button, Drawer, Alert, Tab, Tabs } from '$lib/components/common'
import { Play } from 'lucide-svelte'
import type { FlowModule, Job, WhileloopFlow } from '$lib/gen'
import FlowLoopIterationPreview from '$lib/components/FlowLoopIterationPreview.svelte'
import FlowRunSettings from './FlowRunSettings.svelte'
import StepSettingsBadges from './StepSettingsBadges.svelte'
import FlowModuleEarlyStop from './FlowModuleEarlyStop.svelte'
import { useUiIntent } from '$lib/components/copilot/chat/flow/useUiIntent'
const { flowStateStore } = getContext<FlowEditorContext>('FlowEditorContext')
interface Props {
mod: FlowModule
previousModule: FlowModule | undefined
parentModule: FlowModule | undefined
noEditor: boolean
}
let { mod = $bindable(), previousModule, parentModule, noEditor }: Props = $props()
let runSettings: FlowRunSettings | undefined = $state(undefined)
let previewOpen = $state(false)
let jobId: string | undefined = $state(undefined)
let job: Job | undefined = $state(undefined)
let previewIterationArgs = $derived(flowStateStore.val[mod.id]?.previewArgs ?? {})
let selectedTab = $state('loop')
useUiIntent(`whileloopflow-${mod.id}`, {
openTab: async (tab) => {
// Every setting the intent can name lives in the other tab, which only mounts
// `runSettings` once selected.
selectedTab = 'settings'
await tick()
runSettings?.openSetting(tab)
}
})
</script>
<Drawer bind:open={previewOpen} alwaysOpen size="75%">
<FlowLoopIterationPreview
modules={mod.value.type == 'whileloopflow' ? mod.value.modules : []}
open={previewOpen}
previewArgs={previewIterationArgs}
whileLoop
bind:job
bind:jobId
on:close={() => {
previewOpen = false
}}
/>
</Drawer>
<FlowCard {noEditor} title="While loop">
{#snippet header()}
<div class="grow">
<div class="flex flex-row gap-2 items-center">
<div class="grow">
<input bind:value={mod.summary} placeholder={'Summary'} />
</div>
<div class="justify-end">
<Button
on:click={() => (previewOpen = true)}
startIcon={{ icon: Play }}
variant="default"
size="sm">Test an iteration</Button
>
</div>
</div>
</div>
{/snippet}
<div class="flex h-full min-h-0 flex-col">
{#if mod.value.type === 'whileloopflow'}
<Tabs bind:selected={selectedTab} wrapperClass="shrink-0">
<Tab value="loop" label="Loop" />
<Tab value="settings" label="Run settings">
{#snippet extra()}
<StepSettingsBadges flowModule={mod} />
{/snippet}
</Tab>
</Tabs>
<div
class="flex min-h-0 flex-1 flex-col gap-8 overflow-auto p-4"
style="scrollbar-gutter: stable"
>
{#if selectedTab === 'loop'}
{#if !noEditor}
<Alert
type="info"
title="While loops"
size="xs"
documentationLink="https://www.windmill.dev/docs/flows/while_loops"
>
Add steps inside the while loop but have one of them use early stop/break in their Run
settings (or do it at the loop level that will watch the last step) to break out of
the while loop (otherwise it will loop forever and you will have to cancel the flow
manually).
</Alert>
{/if}
<section class="flex flex-col gap-6">
<FlowModuleEarlyStop blocks="stop-after" bind:flowModule={mod} />
<Toggle
size="xs"
textClass="text-xs font-normal text-primary"
bind:checked={mod.value.skip_failures}
options={{
right: 'Skip failures',
rightTooltip:
'If disabled, the flow will fail as soon as one of the iteration fail. Otherwise, the error will be collected as the result of the iteration. Regardless of this setting, if a flow level error handler is defined, it will process the error. (Workspace error handlers will NOT be used to process errors if enabled.)',
rightDocumentationLink: 'https://www.windmill.dev/docs/flows/while_loops'
}}
/>
<Toggle
size="xs"
textClass="text-xs font-normal text-primary"
bind:checked={mod.value.squash}
on:change={({ detail }) => {
;(mod.value as WhileloopFlow).squash = detail
}}
options={{
right: 'Squash',
rightTooltip:
'Squashing a while loop runs all iterations on the same worker, using a single runner per step for the entire loop. This eliminates cold starts between iterations for supported languages (Bun, Deno, and Python).',
rightDocumentationLink: 'https://www.windmill.dev/docs/flows/while_loops'
}}
/>
</section>
{:else}
<FlowRunSettings
embedded
loopSubset
earlyStopBlocks="all-iters"
bind:this={runSettings}
bind:flowModule={mod}
{parentModule}
{previousModule}
selectedId={mod.id}
/>
{/if}
</div>
{/if}
</div>
</FlowCard>