Files
windmill/frontend/src/lib/components/ScriptSettingsBadges.svelte
T
Ruben Fiszel bf16e7d49a feat: surface workspace-script advanced settings in flow editor (#10289)
* feat(flow-editor): surface workspace-script advanced settings in flows

Workspace-script steps in a flow could not view or edit script-level
runtime settings (concurrency, cache, timeout, debounce, dedicated
worker, priority, delete-after-use). The concurrency and cache tabs
only showed a "set it on the script" warning with no value and no way
to act on it.

- Add ScriptAdvancedSettings, a reusable subset of the script editor's
  runtime settings, and two entry points that reuse it:
  - WorkspaceScriptSettingsDrawer: a mini settings drawer reachable from
    the flow step (header "Settings" button and the delegating tabs),
    saving a new script version with the code left unchanged.
  - an inner "Settings" drawer inside ScriptEditorDrawer, saved together
    with the code.
- Replace the concurrency/cache delegation warnings with a box that
  fetches the referenced script's current value and offers an
  "Edit script settings" shortcut (useWorkspaceScriptSettings loader).
- Add ScriptSettingsBadges showing active advanced settings, in the
  standalone script editor top bar, the edit-code drawer, and above the
  workspace-script step preview.

Fixes WIN-2233

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

* fix(flow-editor): keep subflow concurrency note distinct from workspace-script

The concurrency delegation box is workspace-script specific; subflow
steps now keep a plain limitation note instead of the script settings
shortcut.

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

* fix(flow-editor): preserve all script fields when saving settings-only version

Building the createScript body by hand dropped codebase/labels/envs and
other fields on the new version. Spread the loaded script instead and
override only lineage, matching ScriptEditorDrawer's save.

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

* fix(flow-editor): address review — settings-save safety and stale display

- WorkspaceScriptSettingsDrawer: keep settings-only saves from hijacking
  execution identity or discarding the author's draft (preserve_on_behalf_of
  + skip_draft_deletion), and normalize cleared concurrency/debounce keys to
  undefined so blanks don't become shared global keys.
- ScriptEditorDrawer: normalize cleared keys in its save too (the inner
  settings drawer edits them).
- FlowModuleComponent: reload the surfaced concurrency/cache values + badges
  after a header settings/code save; gate settings editing on customUi.scriptEdit.
- useWorkspaceScriptSettings: sequence-guard load() against stale overwrites.
- Add unit tests for getActiveScriptSettingsBadges.

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

* fix(flow-editor): round-3 review — concurrency-safe save, load guards, UI gates

- WorkspaceScriptSettingsDrawer: drop auto_parent so a settings-only save uses
  the loaded parent as an optimistic-concurrency guard (fails loudly instead of
  silently reverting a concurrent deploy); sequence-guard openDrawer so a slow
  load for a previous script can't clobber a reopened one.
- useWorkspaceScriptSettings: clear loading in the superseded/early-return path
  so a hub/empty step can't spin forever.
- ScriptBuilder: gate the clickable settings badges on customUi.topBar.settings
  and settingsPanel.disableRuntime.

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

* fix(flow-editor): round-4 review — template, load-error, legacy-zero handling

- WorkspaceScriptSettingsDrawer: stop forcing is_template=false so saving a
  setting on a template keeps its template status; show a recoverable error
  (with Retry) when the settings load fails instead of spinning forever.
- scriptSettings/FlowModuleComponent: treat non-positive concurrent_limit and
  timeout as unset (legacy zero rows), so no "Max 0 executions"/"Timeout 0s".
- Add badge tests for the non-positive cases.

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

* fix(flow-editor): round-5 nits — neutral card wording, load-error surfacing, cache zero

- WorkspaceScriptSettingInfo: neutral "managed on the referenced workspace
  script" header (no longer claims "configured" when unset) and a distinct
  error line so a failed load isn't misread as "not set".
- useWorkspaceScriptSettings: expose an error state; thread it into the
  concurrency and cache cards.
- Treat cache_ttl <= 0 as unset, matching concurrency/timeout; add test.

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

* feat(flow-editor): icon-only script action buttons + gate settings in local-dev

- Gate the workspace-script settings actions (header button, clickable badges,
  Concurrency/Cache shortcuts) on the settings drawer actually being mounted, so
  the local-dev flow editors (Dev.svelte / flows/dev) that provide the context
  store but never render the drawer keep the values read-only instead of showing
  no-op controls.
- Make the script action buttons icon-only with clear hover popovers to save
  space in the crowded step/script-editor top bars: Edit, Settings and Fork in
  the step header, Settings in the edit-code drawer, and the settings badges
  (icon chip + label/value popover).

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

* fix(flow-editor): round-6 nits — a11y names + accurate read-only reason

- Add aria-label to the icon-only Edit/Settings/Fork buttons and the setting
  badges so keyboard/screen-reader users get an accessible name (the hover
  popover alone didn't expose it).
- WorkspaceScriptSettingInfo takes a noEditReason so the read-only explanation
  matches the actual gate (hub / hash-pinned / unavailable-in-this-editor)
  instead of always blaming hub/pinned — fixes the wrong reason shown in the
  local-dev flow editors.

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

* chore(flow-editor): drop narrating comment on the no-edit-reason derived

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

* fix(flow-editor): bind settings save completion to the drawer target

The drawer is a singleton, so a save that outlived a reopen ran the new
target's callback and closed its drawer, discarding edits in progress.
Capture the target sequence and callback at save time: the captured
callback still fires (it refreshes the script it belongs to) while the
close, error toast and saving flag only apply if the target is unchanged.
Reopening also resets the saving flag, which the seq-guarded save no
longer clears for a superseded target.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 23:21:24 +02:00

43 lines
1.3 KiB
Svelte

<script lang="ts">
import Badge from '$lib/components/common/badge/Badge.svelte'
import Popover from '$lib/components/Popover.svelte'
import {
getActiveScriptSettingsBadges,
type ScriptAdvancedSettingsFields
} from './scriptSettings'
interface Props {
settings: ScriptAdvancedSettingsFields | undefined
// When provided, badges become clickable and call this with the badge key
// (e.g. to open the settings drawer focused on that section).
onclick?: (key: string) => void
small?: boolean
}
let { settings, onclick, small = true }: Props = $props()
let badges = $derived(getActiveScriptSettingsBadges(settings))
</script>
{#if badges.length > 0}
<div class="flex flex-row flex-wrap gap-1 items-center">
{#each badges as badge (badge.key)}
<!-- Icon-only chips to save space in crowded top bars; the label and current
value are shown in the hover popover. -->
<Popover notClickable placement="bottom">
<Badge
color="blue"
{small}
icon={{ icon: badge.icon, position: 'left' }}
clickable={Boolean(onclick)}
onclick={onclick ? () => onclick?.(badge.key) : undefined}
aria-label={`${badge.label}: ${badge.detail}`}
/>
{#snippet text()}
<span class="font-semibold">{badge.label}</span>{badge.detail}
{/snippet}
</Popover>
{/each}
</div>
{/if}