mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 08:07:15 +00:00
3119e16ed8df0daec0e019ae2efb2176d7e9e953
633
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3119e16ed8 |
feat: prompt browser confirmation on page exit with unsaved changes (#9503)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7fc5340da3 |
fix(frontend): allow copy/paste shortcuts inside ConfirmationModal (#9505)
The modal's window keydown-capture handler called preventDefault() and stopPropagation() on every keystroke while open, which swallowed Cmd/Ctrl+C and Cmd/Ctrl+V (and blocked typing in any child input). Only intercept Enter/Escape without modifiers and let all other keys through. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b0b330c786 |
feat: deployed↔draft compare + AI-session draft bar (#9435)
* feat: deployed↔draft compare for current workspace + session draft bar Add a "Deployed ↔ draft" comparison alongside the existing fork-vs-parent compare flow, and surface drafts in the AI session UI. - Merge the fork-direction toggle (Deploy to parent / Update current) and the new deployed↔draft mode into one 3-way CompareModeToggle, rendered inside the comparison card. Hidden in non-fork workspaces (draft only). - CompareDrafts: list/deploy/discard server drafts (scripts, flows, apps incl. raw apps) via shared WorkspaceDeployLayout. - Session draft bar (SessionDraftBar) mirrors the fork bar, only visible when drafts exist; its diff button opens the shared read-only diff drawer extracted as WorkspaceDiffDrawer (ForkDiffDrawer + DraftDiffDrawer are thin wrappers over it). - WorkspaceDraftsBanner: home banner linking to draft review. - Backend: GET /drafts/count endpoint for the draft-count badge. - Raw app draft deploy (rawAppDeploy.ts) + vite /ui_builder proxy headers so the bundler iframe loads cross-origin. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: refine draft/fork compare toggle UX Follow-up polish on the merged deploy/draft compare control: - Relabel the draft toggle to "Deploy draft (N)" and show per-direction counts on all three toggle buttons (deployable / updateable / drafts), suppressed when zero. Counts are computed page-side so they persist in draft mode too. - Warn before deploying to the parent when the fork has undeployed drafts ("Only deployed versions in this fork can be sent to {parent} …") with a one-click link to the draft view; milder note in the update direction. - Show an empty-state message per direction ("Nothing to update — this fork is up to date with {parent}") instead of a table of greyed, non-actionable rows; hide the deploy/update button in that case. - Drop the standalone "Pending drafts" info alert from the draft list. - Align the fork "Show diff" button to the non-deprecated Button API (unifiedSize, onClick, startIcon) so it matches the draft one; mark "Discard draft" destructive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: link compare row titles to the item editor - Render each compare row title (fork and draft) as a link that opens the item in a new tab, scoped to the current workspace (raw apps route to /apps_raw/edit), matching the AI-session diff drawer: target=_blank, hover underline + ExternalLink icon, click stops row-selection propagation. Kinds without an editor stay plain; the fork rename markup is preserved. - Drop the "Kind → name" prefix from draft rows — that arrow reads as the rename visual and the kind is already shown by the row icon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: clickable rows + multi-select in deploy layout - Make deploy-layout row cards selectable on click via an opt-in `selectOnRowClick` prop on the shared Row (default off, other tables unaffected); clicks on the checkbox, title link and action buttons are ignored. Adds role/tabindex + Enter/Space keyboard support. - Support multi-select with modifier keys like classic list pickers: Shift+click selects the contiguous range from the anchor row; Cmd/Ctrl (and plain) click toggles a single row. select-none avoids text highlighting on shift-click. - Turn the "Select all" text into a <label> associated with its checkbox so clicking the text toggles it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: select all drafts by default in draft compare Drafts now load pre-selected (deploy-all is the common intent); guarded so a reload after a deploy doesn't re-select the items left behind. Mirrors CompareWorkspaces' default auto-selection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: show diff for draft-only items stored without a draft row A draft_only flow/script/app whose content lives in the entity row itself (created via create*(draft_only: true), no separate draft-table row — like u/admin/new) returns draft == null from get*ByPathWithDraft. getDraftDiffValues passed that null through, so the diff "after" side was empty and nothing rendered. Fall back to the row's own value as the draft content when draft is null (deployDraft already did this), fixing both the compare-page DiffDrawer and the session bars' WorkspaceDiffDrawer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: shared diff button across session bars + bar spacing - Extract SessionDiffButton (variant=default, ± DiffIcon, count, "Open diff" title) and use it for the diff-drawer trigger in both the fork bar and the draft bar, so they're identical. Drop the icons from both "Review" buttons. - Add gap-1 (4px) between the fork bar and draft bar when both are visible (flex wrapper; single in-flow root per bar, drawer is portalled — no stray gap when only one shows). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: deploying a new (draft-only) flow or app A draft_only flow/app already has an entity row (created via create*(draft_only: true)), so deployDraft's createFlow/createApp rejected it with 400 "already exists". Use updateFlow/updateApp instead — a listed draft always has a row, and update promotes a draft_only entity to a real deployed version (clearing the flag), like the editor does. Scripts were unaffected (createScript + parent_hash makes a new version). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: refresh fork comparison after deploying/discarding a draft Deploying a draft promotes it to the workspace's deployed version, changing the fork comparison (ahead/behind vs parent) — but the compare page only re-fetched it on workspace change, so the deploy/update toggle counts and the CompareWorkspaces tab went stale. CompareDrafts now fires onChanged after a successful deploy/discard; the page rewires it to refresh the comparison and draft count. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix: stop draft-count effect from freezing the AI session page ensureDraftCount cleared its dedupe key on error; since the caller is a reactive $effect (SessionDraftBar), a persistently-failing countDrafts spun the effect into an infinite retry loop that flooded the console and froze the tab. Claim the key before awaiting and keep it set on failure; refresh*() still forces a re-fetch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: correct draft count and refresh compare counts after actions count_drafts now counts deployable drafts (draft_only OR has-a-draft-row across script/flow/app), matching the CompareDrafts list, instead of raw draft-table rows which miss new draft-only items. CompareWorkspaces and CompareDrafts fire onChanged so the compare page re-fetches the comparison and draft count after deploy/update/discard, keeping the toggle badges in sync. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: session draft bar shows a fresh count on every (re)open The runtime persists across client-side navigation, so the deduped ensureDraftCount() kept a stale count (e.g. a 0 cached before a draft was created) when a session was re-opened — the bar stayed hidden even though the server count was >0. Force one fresh fetch per mount from a non-reactive onMount via refreshDraftCount(workspace) (which now takes the workspace so it works before the dedupe key is set). The reactive $effect keeps using ensureDraftCount: refreshDraftCount reads loadingDraftCount ($state), so calling it from an effect would track-and-mutate that state into an infinite fetch loop — ensureDraftCount's plain-key early-return avoids it. ensureDraftCount also now releases its key after a 5s backoff on failure so a transient countDrafts error retries instead of leaving the bar stuck. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor: make the draft count a single deep Workspace Drafts module The Draft Count was computed four ways (backend count_drafts SQL, the CompareDrafts list filter, a bespoke sessionRuntime cache, and the compare page state) that drifted — the root cause of the unreliable count, the stale-on-reopen bug, and the effect-loop freeze. Introduce one module (workspaceDrafts.svelte.ts): - getDraftItems(ws) lists the deployable Draft Items once; count ≡ list length, never a separate query. - useWorkspaceDrafts(() => ws) is a component-scoped runed resource (fetches on mount + ws change, no persistent cache → fresh on every (re)open). - invalidateWorkspaceDrafts(ws) refreshes mounted consumers; deployDraft/ discardDraft self-invalidate, so callers never reason about staleness. Rewire every reader to it (SessionDraftBar, CompareDrafts, DraftDiffDrawer, WorkspaceDraftsBanner, compare page) and delete the sessionRuntime draftCount apparatus (key + loading flag + 4 methods + effects + backoff). With no caller left, remove the count_drafts endpoint (handler, route, openapi, sqlx cache, generated client) — drafts.rs/openapi return to their main state. Record the draft vocabulary in CONTEXT.md. A single GET /w/{ws}/drafts/items endpoint can later replace getDraftItems' three list calls behind the unchanged seam. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat: warn before deploying a draft based on an outdated version When a newer version is deployed while a draft exists (git-sync/CLI deploys preserve drafts via skip_draft_deletion), the compare/deploy-drafts page now flags the draft as Outdated and gates deploy behind an override confirmation with a diff — instead of silently clobbering the newer version. Staleness is read from the draft's base version: scripts already store parent_hash; flows/apps now record a draft_base_version sidecar on save. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: drop redundant /ui_builder proxyRes hack (superseded by #9433) main's global configure-response-headers plugin now runs with enforce:'pre' and sets COOP/COEP/CORP on dev responses (#9433), so the per-proxy proxyRes override is no longer needed. Revert the /ui_builder block to main's headers form — vite.config.js now matches main with no branch-specific change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(sessions): keep draft count reactive to preview/chat deploys Invalidate the Workspace Drafts resource at every frontend deploy seam (ScriptEditorView / FlowEditorView / RawAppEditorView onDeploy + onSaveDraft) so user-driven deploys from the Preview panel update the count immediately, and refresh SessionDraftBar on the same coarse signals SessionForkBar uses (AI turn-end + tab refocus) to cover chat-driven deploys that happen server-side and never surface as frontend calls. Also: always show the draft toggle count including (0) on the compare page, drop the header/content separator line in both compare cards, and derive the "Deploy N drafts" footer count so it stays reactive after discard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor: address branch review findings - WorkspaceDraftsBanner: use the modern Button API (variant/unifiedSize/onclick) instead of the deprecated size/color/on:click triad; drop "pending" from the banner copy to match CONTEXT.md vocabulary. - WorkspaceDeployLayout: make Cmd/Ctrl-click distinct from a plain click. Plain row click now selects only that row (classic file-picker), Cmd/Ctrl toggles, Shift extends the range, and the checkbox still plain-toggles. Adds an onSelectOnly callback wired in CompareDrafts/CompareWorkspaces. - WorkspaceDiffDrawer: document why the file filter is a raw input (bespoke keyboard-nav integration the design-system inputs can't express). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * revert: drop draft version-gating (stale-draft warning) Remove the "deploying an outdated draft would override a newer version" guard. It's a rare edge case and will be handled properly by conflict resolution in a follow-up PR. - CompareDrafts: drop staleMap/computeStaleness, the TOCTOU pre-deploy re-check, the "Outdated" badge, the override-in-diff button, and the "Newer version deployed" confirmation modal; deploySelected is now the plain deploy. - utils_draft_deploy: remove getDraftStaleness/DraftStaleness and the draft_base_version strip. - FlowBuilder / AppEditorHeader / RawAppEditorHeader / AppJsonEditor: stop injecting draft_base_version into draft saves — these editor paths are back to matching main, shrinking the PR's blast radius. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * style: unify home banner CTAs on the modern Button API Both the Workspace Drafts banner and the sibling Fork banner now use variant="default" unifiedSize="sm" onclick, so the two CTAs on the home page render identically and neither uses the deprecated size/color/on:click props. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): show draft deploy direction badge inside forks Mirror the fork compare header's "from → into" badges on the Deploy-draft tab: "deploy: draft → into: <fork>". Makes it explicit that deploying a draft promotes it within the fork (deployed↔draft), not up to the parent. Only rendered inside forks, where the parent could otherwise be confused with the deploy target. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(compare): address PR review — dedup drafts resource + shared link - De-dupe the compare page Workspace Drafts fetch: the page owns the single resource and passes draftItems/draftsLoading into CompareDrafts (was mounting a second resource → 6 list calls; now 3). - Prune transient deploymentStatus for items dropped from the list (no unbounded growth, no stale 'deployed' suppressing a re-drafted row). - Type getDraftItems' list fields via a narrow DraftListEntry (drop Array<any>). - Clear comparison catch-up timers on unmount (onDestroy). - Extract shared ExternalEditLink.svelte; use it in CompareDrafts, CompareWorkspaces, WorkspaceDiffDrawer (was a near-verbatim <a> block x3). - Note conflicts intentionally count in both toggle directions; drop a stray blank line in sessionRuntime. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): show draft summary renames via shared item-summary component Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(compare): address round-2 PR review - Point the fork-compare edit link at the workspace the item actually lives in: a parent-only row (absent in the fork) would 404 if linked into the fork, so link it into the parent instead. - Replace the bespoke raw <button class="underline">Deploy drafts</button> in the undeployed-drafts alert with a design-system Button (variant=subtle). - Drop the stray Prettier reflow in sessionRuntime (restore to match main). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): warn on fork items with a pending draft In the fork compare list, items that are deployed *and* have a pending draft (has_draft) now: - show a yellow "+Draft" badge (AlertTriangle), rendered before the New/status badges, with a per-direction tooltip explaining that deploying/updating moves the deployed version, not the draft; - are excluded from the default selection (still manually selectable); - trigger a confirmation modal if explicitly selected and deployed/updated, listing the affected paths. The signal comes from the page's existing fork drafts resource (a kind:path Set passed down) — no new fetch, no backend change. Also rename the undeployed-drafts alert CTA from "Deploy drafts" to "See drafts". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(compare): rename page to "Compare & Deploy" Update both the page heading (PageHeader) and the browser-tab title. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(compare): multi-select rows by default (no modifier) In the shared WorkspaceDeployLayout (fork + draft lists), a plain row click now toggles the item in/out of the selection instead of replacing the whole selection with it. Removed the modifier-based selection entirely: the now-dead onSelectOnly path and its two call sites, plus shift+click range selection (and its anchor/isPickable helpers). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(table): don't toggle row selection on keyboard child activation Row's onkeydown selection handler lacked the interactive-child guard that handleRowClick already had, so pressing Enter/Space on a checkbox, action button, or title link both activated the child and toggled the row's selection. Extract a shared fromInteractiveChild() guard and apply it in handleRowKeydown, mirroring the click path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(fork-banner): show draft CTA when fork is up to date When a fork has no changes vs its parent ("Everything is up to date") but has pending drafts, the banner now mirrors the non-fork drafts banner: the status text becomes "This workspace has N draft(s)" and the button becomes "Review & deploy drafts", linking to the compare page in draft mode. When the fork has real ahead/behind diffs, the existing status and buttons are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): honor renamed draft paths + raw-app draft fixes Address the Codex review: - Draft deploy now uses the draft payload's path for scripts, flows and raw apps (keeping the URL path as the existing item key), so a rename in a draft deploys to the new path instead of silently staying at the old one. - DraftDiffDrawer maps raw apps to the `raw_app` kind so their row edit links open the raw-app editor, not the legacy app editor. - ScriptEditorView.restoreDeployed invalidates the workspace drafts after deleting the draft, so the session draft-bar count drops immediately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): guard showDiff race, tree label, mode fallback Address the cubic review: - CompareDrafts.showDiff uses a monotonic request token so two quick "Show diff" clicks can't let a slow earlier fetch overwrite a faster later one. - WorkspaceDiffDrawer.buildTree labels a 2-segment path with its leaf name (parts[1]) instead of the full scope key. - The compare page only resolves ?mode=draft immediately; ?mode=fork (and an absent mode) defer to the isFork-aware effect, which falls back to draft for non-fork workspaces instead of stranding them on the fork UI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore: remove CONTEXT.md from the PR Drop the root CONTEXT.md domain glossary and the lone comment pointer to it in workspaceDrafts.svelte.ts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): send custom_path on raw-app draft deploy A raw-app draft that changes or clears its custom route was silently dropped on deploy from the compare page: updateAppRaw omitted custom_path, so the backend preserved the old route. Send the draft's custom_path on update — matching the fork deploy path (which spreads the full app, custom_path included) and the createAppRaw branch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(sessions): refresh draft count on raw-app session save-draft The script/flow session editors invalidate the workspace drafts on save-draft, but the raw-app editor only did so on deploy. Thread an onSaveDraft callback through RawAppEditor → RawAppEditorHeader and call invalidateWorkspaceDrafts from RawAppEditorView, so saving a raw-app draft in an AI session updates the SessionDraftBar count immediately (and the bar appears when the count was zero). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): honor renamed paths, draft triggers & paginate inventory Address the Codex review: - Draft deploy honors the draft's renamed path for scripts/flows/raw apps (keeping the URL path as the existing item key). - Script/flow draft deploy now deploys draft_triggers via the shared deployTriggers, instead of silently dropping them with the draft. - rawAppDeploy sends custom_path admin-gated on update (admin: value/'' to clear; non-admin: undefined) so non-admins don't hit RequireAdmin. - getDraftItems pages through listScripts/listFlows/listApps so drafts past the first page are included in the count, banners, drawer and deploy list. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): admin-gate custom_path on visual-app draft deploy The visual-app branch of deployDraft sent custom_path unconditionally on updateApp, so a non-admin deploying an app draft for an app with a custom route hit RequireAdmin. Mirror AppEditorHeader and the raw-app path: admins send the draft's custom_path ('' clears), non-admins send undefined so the backend preserves the existing route. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(raw-app): save initial draft directly when path is known In the AI-session preview, a never-deployed raw app has newApp=true but a known path, so saveDraft opened the "Initial draft save" path-picker drawer — which is gated on `appPath == ''` and therefore never rendered, making Save draft silently do nothing. Branch the new-app case on appPath: pick a path via the drawer only when none is chosen yet; otherwise call saveInitialDraft() directly. saveInitialDraft now also toasts and fires onSaveDraft so the session draft-bar count refreshes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(compare): preserve deployed custom_path on visual-app draft deploy The visual-app draft value usually omits custom_path, so the admin branch's `d.custom_path ?? ''` sent an empty string, which the backend treats as "clear the route" — an admin deploying a content-only draft would wipe the app's existing custom route. Fall back to the deployed route (`r.custom_path`) when the draft omits it; an explicit '' still clears. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
075faabf3b |
feat(frontend): surface local drafts in drawer editors with an unsaved-changes banner (#9335)
* feat(frontend): surface local drafts in drawer editors with an unsaved-changes banner Drawer-based editors (the 11 trigger types, plus resource and variable) restore unsaved edits from browser localStorage on open using the same mechanism as flows/scripts, but only showed a transient "Reset to deployed" toast with no way to review the diff. Add a persistent "You have unsaved changes" banner below the drawer header with Show diff / Discard actions, shown whenever the form diverges from the deployed baseline. Replaces the toast for these editors; flows/scripts/apps (full-page) keep their existing toast. - new shared LocalDraftBanner.svelte (Alert-styled bar + DiffDrawer) - DrawerContent: optional `banner` snippet rendered below the header - useTriggerDraftSync: reactive `hasDraft`, `deployed`/`current` getters and `resetToDeployed`; drop the restore toast (banner supersedes it) - wire the banner into all 11 trigger editors + variable; resource lifts its dirty state up to ResourceEditorDrawer via a callback + accessors - fix ScheduleEditorInner.openNew not resetting initialConfig (reused editor instance kept a stale baseline, wrongly flagging a new schedule dirty) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): address PR review on local-draft drawer banners - LocalDraftBanner: snapshot diff sides at click time so the diff drawer doesn't keep updating as the user types behind it. - VariableEditor / ResourceEditor: scope the banner and its Discard action to the selected workspace; the cross-workspace dirty state stays surfaced by the existing otherDirty Alert. Forward can_write via a new onCanWriteChange callback so the resource banner hides Discard in read-only mode (matching the trigger editors). - useTriggerDraftSync: drop the now-unused path arg from maybeRestore and update all 11 trigger editor call sites. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): deep-clone fallback in UserDraft.discard to avoid baseline aliasing When a caller passed a live $state proxy as `fallback` (Variable/Resource editors handed `initialStates[selected]` to the banner's Discard), the handle's draft cell ended up sharing the same proxy as the caller's baseline. Subsequent form edits mutated both sides in lock-step and the dirty check kept reporting equal, so the banner never reappeared and the Update button stayed disabled until the drawer was reopened. Cloning the fallback inside `discard` (via `snapshotDraftValue`) gives the handle a fresh tree and decouples the two reactive graphs. Trigger editors already cloned at their call site (resetToDeployed); this just makes the API self-contained for all callers. Also switch the variable form's "Audit log for each access" alert from warning to info — it's informational, not a warning. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(frontend): honor disabled prop in LocalDraftBanner's diff drawer The banner's `disabled` prop hid the inline Discard button but the diff drawer's "Discard changes" action was still wired unconditionally, so a read-only user could bypass the hidden inline action via Show diff. Gate the diff-drawer button on the same flag so both surfaces agree. Flagged by cubic and Codex on PR #9335. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
eadeac248b |
feat: sessions page with isolated AI chat + flow editor (#9034)
* feat(sessions): chat + editor side-by-side with multi-session state
Introduces the Sessions feature: a workspace where the AI chat and an
editor (flow / script / app / raw-app) sit side-by-side, with each session
having its own AIChatManager instance, history, and target item. Sessions
are persisted across reloads and can be staged into forks for review.
Key pieces:
- sessions/ — SessionWrapper (the split-pane shell), SessionPicker
(sidebar list), SessionForkBar, SessionWorkspaceBar, FlowEditorView /
ScriptEditorView / AppEditorView / RawAppEditorView, ForkDiffDrawer,
sessionRuntime (per-session AIChatManager + draft state),
sessionState (in-memory + persisted index), sessionUnread, sessionScope,
appDraftCodec / flowDraftCodec, forkEditUrl, /sessions route.
- WorkspaceItemDrillPicker refactor — extracts WorkspaceItemRow + adds
surfaceAI drafts, stale-while-revalidate. workspacePicker.ts drops
explicit invalidate() in favor of always re-fetching in the background.
- ForkDiffDrawer + WorkspaceItemDiffViewer — per-kind diff bodies
reusable from the compare page. FlowGraphDiffViewer / FlowGraphV2 gain
inlineDiff forwarding + onHeight callback for equal-height layout.
- Global AI chat sessions plumbing — AIChatManager exports the class +
adds disabledModes, beforeSend hook, scoped instance context. AIChat /
AIChatDisplay accept session-only props (wideLayout, emptyHint,
inputPreface, hideHeader, hideModeSelector, forceDisabled). Chat
preserved across /flows/add → /flows/edit, /scripts/add → /scripts/edit.
- Draft-first loaders — sessions open drafts when present, otherwise
seed a draft from the last deployed value via globalDraftStore.
RawAppEditor / AppEditor / AppEditorHeaderDeploy get newApp prop +
fixes so draft-only apps can deploy.
- Compare page (/forks/compare) — bigger overhaul to plug into the new
drawer.
- Sidebar — Sessions entry + unread badge + status dot in
SidebarContent / MenuButton / SideBarNotification.
- Misc fixes — chat group color palette constraint, deploy_workspace_item
confirmation dropped, open_preview tool, picker drafts surfacing,
fork archive/delete buttons on compare page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): bypass UserDraft inside session panes + sessionUnread crash
After merging main's UserDraft PR (#9121) into the sessions branch, two
integration issues surfaced:
1. AppEditor.svelte calls `UserDraft.use<App>('app', path)` at the
component level — keyed by ($workspaceStore, 'app', path). Sessions
that haven't materialized a fork yet stay at the user's main
workspace, so a session targeting an app at the same path as a
regular /apps/edit tab shared the same LS key. The session would
read the regular tab's autosave and write its fork-edits back over
it.
Gate UserDraft.use on `!getContext('aiChatManager')` — sessions
inject the manager via setContext, so inside a session pane the
handle is `undefined`, stateApp falls through to the `app` prop
the session loaded, and the auto-save $effect bails. Same gate on
the four UserDraft.remove call sites in AppEditorHeader and
RawAppEditorHeader so save/deploy from a session pane doesn't wipe
the LS draft of a non-session tab at the same path.
2. sessionUnread.svelte.ts called useLocalStorageValue at module
scope. Main's PR added a deep-mutation $effect inside that helper,
which now requires component-initialization context — every page
crashed at import time with `Svelte error: effect_orphan`.
Replaced with a plain module-level $state + manual localStorage
persist; same reactivity contract for callers.
3. ScriptEditorView.svelte was passing a `replaceStateFn` prop that
ScriptBuilder dropped on main. Removed.
Verified end-to-end with Playwright:
- /flows/edit/{path} regression: UserDraft handle still created, no
console errors
- /sessions loads, sessionUnread doesn't crash
- Session targeting non-raw app `u/admin/userdraft_collision_test`
displays the fork content (FORK_ONLY_MARKER) even with an LS
poison at `userdraft/w/local/app/{path}` containing a
POISONED_BY_REGULAR_TAB_AUTOSAVE marker; poison remains untouched
after the session loads and renders
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): stop fork-create retry loop on first user message
Removed the SessionWrapper $effect that retroactively committed the
session's workspace from the in-memory chat history. When opening a
session whose previous commit attempt had failed (or whose response was
lost) the effect ran in a tight retry loop, flooding the user with
`workspace_pkey` violations from `create_workspace_fork`.
The send path already commits through `AIChatManager.beforeSend` →
`commitSessionWorkspace`, which is the deterministic moment-of-action.
The $effect was a redundant reactive bridge that turned every backend
failure into an infinite retry.
Also hardens `materializeFork`/`commitSessionWorkspace` so the most
common cause of the duplicate-key error self-heals:
- `materializeFork` short-circuits when `fork.id` is already in
`$userWorkspaces` (the previous create actually succeeded, we just
lost the response). On a `workspace_pkey` catch, refresh the workspace
list and adopt the existing row instead of toasting an error.
- On a real `materializeFork` failure, `commitSessionWorkspace` now
drops `pending_fork` so the session falls through to the
workspace-pick fallback instead of looping on the same broken intent.
* feat(sessions): show EditorHeader breadcrumb in the not-found state
When a session's target item has been deleted or moved, the editor pane
used to render a bare "Script not found at path X" line — leaving the
user with no way to navigate to a different target without backing out
of the session.
Each editor view now renders a `SessionItemNotFound` shell instead: a
real `EditorHeader` (read-only summary, no pen popover) with a
breadcrumb keyed to the missing kind+path, plus the "not found" copy
below. Clicking any breadcrumb segment opens the workspace picker
scoped to that level — pick a replacement and the session swaps target
via the existing `onNavigate` callback.
`SessionItemNotFound` maps `raw_app` to `EditorHeader`'s `kind: 'app'
+ raw_app: true` so the picker routes through `/apps_raw/...`; the
local label still says "Raw app not found" (not "App not found") so
the user knows which surface is missing.
* fix(picker): stop self-feeding fetch effect that OOM'd the tab
The drill picker's $effect watched `scope` and called `ensureLoaded`
on every change. `ensureLoaded` reads `loaded[kind]` synchronously
(to decide whether to show a spinner), so the effect ended up
subscribed to the very signal it fills. Each fetch result wrote
`loaded[kind] = items`; Svelte 5's $state proxy notifies on every
property set even when the reference is unchanged from cache, which
refired the effect, which called `ensureLoaded` again, which awaited
the cached fetch, which wrote `loaded[kind]` again... runaway loop.
In `/scripts/edit/...` the picker's lifecycle stabilised quickly
enough to mask the loop, but in a session pane (multiple warm
sessions, picker kept alive by the surrounding state) the cycle
spun freely — 29.8 million iterations in <100 ms during testing,
enough to OOM Firefox / kill the Chromium tab.
Two changes:
- Replace the scope-watching $effect with an explicit `setScope()`
helper called from `drill()`, `goUp()`, and `onMount`. Fetch is
now a callback reaction to user navigation, never a reactive
consequence of one. No closed feedback cycle is possible.
- Untrack the `loaded[kind]` read inside `ensureLoaded`. The search
$effect (which loads every kind on first keystroke) is still a
reactive caller; the untrack stops it from subscribing to the
signal `ensureLoaded` fills, so the same loop can't form there.
* feat(script-editor): wire initialTestPanelCollapsed through ScriptBuilder
The `initialTestPanelCollapsed` prop was already declared on
`ScriptBuilderProps` (used by the session preview to start the editor
with the run/test pane closed) but never destructured in
`ScriptBuilder.svelte`, so the value silently dropped on the floor
and the test pane always opened.
- `ScriptBuilder.svelte` — destructure the prop and forward it to
`<ScriptEditor>`.
- `ScriptEditor.svelte` — accept the prop and seed `rawTestPanelSize`
to 0 when true, while keeping `storedTestPanelSize` at the default
30 so the user's first toggle expands the pane to a sensible width
rather than 0.
Regular `/scripts/edit/...` doesn't pass the prop → default `false`
→ panel still opens by default.
* fix(sessions): resolve aiChatManager via context in AskUserQuestionDisplay
Inside a session the chat uses a per-pane AIChatManager injected via context. AskUserQuestionDisplay imported the global singleton, so answers clicked in a session dispatched to the singleton's callback map and the AI loop stalled. Resolve via getContext with singleton fallback, matching ChatMode / ToolExecutionDisplay.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(raw_apps): let preview start in single-view on the preview tab
Add a defaultSplitWithPreview prop (default true). When false (session preview), the editor boots in single view with the preview tab selected: gate the onMount default-file activation, the setActiveDocument auto-activation, and iframeShouldMount so the UI Builder bundler iframe still mounts when preview is the active tab. RawAppEditorView passes defaultSplitWithPreview={false}.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(copilot): add get_preview_status tool and make open_preview idempotent
So the assistant can tell whether the session preview already shows the item it just edited, instead of re-opening or re-offering it. Mirrors the open_preview handler plumbing (setGetPreviewStatusHandler) and the session runtime registers it alongside open_preview. open_preview now returns 'already open' when the requested target matches the active session's current target. The system prompt steers the AI to check status before offering. Unit tests cover the no-arg schema, the session-only error, and handler dispatch.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make script preview reactive to AI draft writes
ScriptEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists. None did for the preview path, so the chat's writes (UserDraft.save) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft, materializing the shared $state cell that bridges the chat's writes to the editor.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make raw-app preview reactive to AI draft writes
Mirror of the script-preview fix. RawAppEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists. None did for the preview path, so the chat's raw-app writes (UserDraft.save / setDraftAndMeta, from write_app_file / patch_app_file / write_app_runnable) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft. Verified in-browser: an external UserDraft.save live-updates the bound summary in the open preview.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(sessions): make flow preview reactive to AI draft writes
Mirror of the script/raw-app preview fixes, completing two-way binding for all three session editor kinds. FlowEditorView read the draft via static UserDraft.get inside an effect, which only subscribes to UserDraft's reactive cell when a live entry exists — none did, so the chat's writes (write_flow / patch_flow_json / set_flow_module_code) only touched localStorage and the open preview never updated. Hold a live handle via UserDraft.useMany (reactive getter so it re-acquires when open_preview swaps the path without remounting) and read inbound through handle.draft. Verified in-browser both directions: an external UserDraft.save live-updates the flow header summary and rebuilds the module graph; a preview edit propagates through the debounced save to both UserDraft.get and the chat's getGlobalDraft adapter.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(sessions): surface local-storage drafts in fork diff & compare page
Augments the backend fork-vs-parent comparison with browser-local (UserDraft) drafts so a session's uncommitted AI/user changes are visible in the Fork Diff Viewer and the /forks/compare page. Adds forkDraftDiff.ts (augmentForkComparisonWithLocalDrafts + getForkItemValue), a 'local changes detected' / new-draft warning surface (checkbox-slot warning icon, no-op-baseline filtering, dedup), a 'Local draft <> fork' tab in DiffDrawer, and selectTooltip/nonSelectableTooltip plumbing in Row/WorkspaceDeployLayout.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* Revert "feat(sessions): surface local-storage drafts in fork diff & compare page"
This reverts commit
|
||
|
|
368e677419 |
feat(raw_apps): tab-based editor surface with split-with-preview (#9273)
* feat(raw_apps): custom tab system for source / runnable / preview
Replaces the fixed split-pane layout with a tab bar inside the editor
area. Each frontend file is a tab, each selected runnable is a tab,
and the Preview is pinned to the right (non-closable). Tabs are an
alternative discoverability surface to the sidebar — both stay
functional, but tabs make navigation viable on small screens with
the sidebar collapsed.
A "Split with Preview" toggle in the tab bar's trailing slot pairs
the active tab with the preview side-by-side for wide-screen
multitasking. The toggle hides when Preview is already the active
tab.
The UI Builder, runnable editor, and preview iframe all stay mounted
across tab switches (toggled via `display`) — no bundler restarts, no
preview state loss, no editor remounts.
- New common/tabs/DraggableTabs.svelte: reusable tab strip with
drag-reorder (@windmill-labs/svelte-dnd-action), pinned-left/right
slots excluded from the drag zone, hover-revealed X close, middle-
click close, keyboard navigation (arrows / Enter / Backspace),
and a `trailing` snippet for inline toolbar add-ons.
- raw_apps/RawAppEditor.svelte:
- Tab state (`tabs`, `activeTabId`, `splitWithPreview`) lives in
Windmill. Persisted in localStorage keyed by workspace + app path.
- Sidebar file clicks (`handleSelectFile`) and runnable selection
(`selectedRunnable` via `bind:`) are mirrored into tabs via an
effect — the sidebar interaction is otherwise untouched.
- Listener augmented: `setActiveDocument` backfills tabs for files
VS Code opens by itself; `setFiles` / `runnables` updates drop
stale tabs.
- Bundler / inspector / rebuild toolbar moves into the tab bar's
trailing slot — always visible regardless of active tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(raw_apps): modern tab styling + resizable split-with-preview
Two polish passes on the new tab system:
DraggableTabs styling:
- Remove the bottom border on the tab strip + the accent-coloured
border-b-2 on the active tab. The active tab now shares the
surface background with the content area below it, so the
boundary visually "disappears" — modern IDE-style tabs.
- Inactive tabs sit on the darker surface-secondary tab strip and
get a subtle right separator so they don't blur into each other.
Split-with-Preview is now a real resizable Splitpanes:
- The content area is rendered as a Splitpanes (always), with the
source/runnable slot on the left and the preview iframe on the
right. The user can drag the divider to adjust the ratio when
the "Split with Preview" toggle is on.
- Iframes never remount across single↔split toggles — pane sizes
are driven reactively from (activeTabKind, splitWithPreview),
not by adding/removing the Splitpanes itself.
- The user's preferred split ratio is remembered while they're
dragging and reapplied next time split is enabled.
- The inner splitter is CSS-hidden in single mode so the toggle
button stays the single canonical way to flip layouts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(raw_apps): split mode moves preview tab into the right pane
Cleaner mental model for split-with-preview. Instead of "split the
active tab + always keep the Preview tab around", the Split toggle
now physically moves the Preview tab out of the bar and into a
permanent right pane. When the user toggles split off, the Preview
tab reappears in the bar like any other tab.
- New `displayedTabs` derived: filters out the Preview tab when
splitWithPreview is on, so the user sees only file/runnable tabs
in the bar and a dedicated preview pane on the right.
- `toggleSplit` redirects the active tab to the most recent
file/runnable when the user toggles split on with Preview active,
so they don't end up staring at an empty left pane.
- Split toggle is now always visible — the user can flip both ways.
The button label flips between "Pin preview to the right" and
"Move preview back into a tab" to reflect what's about to happen.
- reorderTabs preserves the Preview tab in the underlying `tabs`
array even though it's filtered out of the drag set in split mode.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(raw_apps): VS Code-style "Preview" header on the right pane
In split mode, the right pane now shows a small "Preview" tab-styled
header anchored at its top-left — making the layout read like a real
VS Code editor split, where each group has its own tab bar.
- Header appears only when `splitWithPreview && activeTabKind !== 'preview'`
(i.e. when the right pane is meaningfully separate from the left's
content). In single mode with preview active, the right pane is the
only thing visible and the main tab bar already labels it.
- The header uses the same styling as an active tab: `bg-surface`
on a `bg-surface-secondary` strip, h-8, text-xs, no border.
- An X button next to the label toggles split off — equivalent to
closing the editor in VS Code's split view (preview goes back to
living as a tab in the main bar).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(raw_apps): VS Code-style symmetric tab bars per pane
Restructure the editor area so each pane is a self-contained "editor
group" with its own tab bar at the top. The Splitpanes is now the
topmost element — the divider runs floor-to-ceiling, splitting both
the tab bars and the content.
Layout (left pane = source / runnable, right pane = preview):
- Left pane top: DraggableTabs (file/runnable tabs, Preview tab when
split is off) + Split-toggle in the trailing slot.
- Right pane top: a custom preview header — "Preview" label styled
like an active tab on the left + the preview-affecting toolbar
(bundler, inspector, rebuild) on the right.
- Each pane independently sized via Splitpanes; iframes + the
runnable panel stay mounted and toggled via `display` so state
survives every transition.
Trade-off: in single-mode with Preview active (paneA=0), the left
tab bar is hidden along with the left pane. To switch back to a
file tab the user uses the sidebar — which is exactly the
discoverability surface tabs were meant to complement, not replace.
Button placement by semantic ownership:
- Layout control (Split toggle) — left side, with the editor.
- Preview-affecting controls (bundler, inspector, rebuild) — right
side, with the preview. No close-X on the right; the Split toggle
on the left is the canonical way to flip layouts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(raw_apps): keep tab bar visible when Preview is active in single mode
The "VS Code-style" restructure put the tab bar inside the left
Pane. When activeTabKind became 'preview' in single mode, the left
pane collapsed to width 0 and the entire tab bar disappeared with
it — leaving the user with no way to switch back to a file tab
except via the sidebar.
Move the main tab bar back above the inner Splitpanes (full width,
always visible). The preview pseudo-header stays inside the right
pane, carrying the bundler / inspector / rebuild toolbar. The
splitter only goes through the content area below the tab bar,
which is acceptable given how much friction the disappearing-tabs
edge case caused.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(raw_apps): per-pane tab bars with mirrored single-mode lists
Replace the single tab bar above the inner Splitpanes with one
DraggableTabs per pane. Splitter now goes floor-to-ceiling through
tabs AND content in split mode.
In single mode both bars mirror the full tab list, so the visible
pane always carries every tab — fixes the bug where activating
Preview hid the tab strip. Clicking Preview while in split mode is
a no-op (Preview is permanently visible in the right pane).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(raw_apps): polish tab strip and sync editor font to text-xs
* feat(raw_apps): move logs overlay onto the preview pane
* refactor(splitpanes): extract pixel-aware minSize helper
* fix(raw_apps): tab hydration loads correct file; closeTab in split mode
* fix(raw_apps): lazy-mount UI Builder iframe + add dev:ui-builder script
* feat(raw_apps): default split view, blue preview tab, fix dnd ghosting
* fix(raw_apps): remove 1px splitter sliver beside preview in single view
* fix(raw_apps): tab scrollbar on hover, fix thumb height + resize staleness
* refactor(raw_apps): don't persist tab/split layout in localStorage
* refactor(raw_apps): derive pane sizes + binding setter instead of effects
* style(raw_apps): trim verbose comments
* feat(raw_apps): accept appendLogs delta from the UI Builder iframe
* fix(raw_apps): exit inspect mode on Escape
* fix(raw_apps): Escape clears lingering inspector selection after pick
* style(raw_apps): accent-selected styling for active tab, bg-surface strip
* fix(raw_apps): address PR review nits (drop debug log, timer/reorder/pane-setter, dev script restore)
* fix(raw_apps): clear inspector overlay on the preview iframe, not the source
* style(raw_apps): neutral tab look (surface-tertiary/text-emphasis selected, text-hint idle)
* chore(raw_apps): bump bundled ui_builder to 61b6fdd
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
2f50e8bab0 |
feat(ai-chat): align footer bar + DropdownV2 mode/autonomy selectors (#9308)
* feat(ai-chat): align footer bar, use DropdownV2 for mode/autonomy selectors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(dropdown): add `selected` item prop rendering a trailing check Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): add small spacing between chat input and footer bar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): always offer the 3 autonomy options in the auto-accept picker Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ai-chat): default autonomy mode to auto-accept on Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor(ai-chat): use Button component for footer dropdown triggers Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): use a hand icon for the auto-accept-off autonomy state Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): use subtle Button variant for mode and model selectors Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): tighten spacing between input and footer bar Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): reword autonomy levels as ask/auto-accept/bypass permissions Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(button): add 2xs unified size with tighter padding Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ai-chat): compact footer bar — 2xs buttons, AtSign context icon, short Yolo label, discreet model Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(ai-chat): widen the permission selector dropdown Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dropdown): group shortcut + selected check to avoid ml-auto collision Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(ai-chat): cover getPersistedAutonomyMode default; clarify default comment Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0f7dd86e5c |
feat: persistent in-editor drafts via UserDraft (#9121)
* refactor(frontend): remove localStorage-backed autosave drafts
Strip the per-editor localStorage autosave for flows, apps and raw apps,
along with the associated restore toasts and diff actions, so we can
replace them with a unified UserDraft service in a follow-up. The
backend DraftService (DB-backed drafts) is untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): add UserDraft service for per-workspace local drafts
Introduces UserDraft, a key-value store keyed by
`{workspace}/{itemKind}/{path}` and backed by localStorage. Supports
save/get/remove plus a reactive use() handle so multiple component
instances observing the same draft stay in sync via a shared $state
loaded through useLocalStorageValue. Designed to host drafts for
scripts, flows, apps, raw apps, resources, variables, and all trigger
kinds.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* tests
* nit schedule_ prefix
* feat(frontend): persist deep mutations in useLocalStorageValue
Track the serialized value alongside the $state and add an $effect that
deep-reads it (via readFieldsRecursively). When a deep mutation produces
a serialization that differs from the last persisted blob, write it to
localStorage. The setter keeps writing synchronously so callers reading
localStorage right after assignment still see the new value; the effect
no-ops on those because lastSerialized was already updated by the setter.
Undefined values are persisted as a removal.
UserDraft no longer needs its own removeItem workarounds for undefined
values — useLocalStorageValue handles that uniformly now.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): add defaultValue + empty-path handling to UserDraft
UserDraft.use() accepts an opts.defaultValue used when no localStorage
entry exists yet. It is not persisted on first read — only an actual
mutation writes through.
Empty paths (new items) bypass localStorage entirely. The entry still
lives in the in-memory Map so multiple components on the same /add page
share state, but save/get/remove/use never read or write localStorage
with an empty path. Once the item is saved and the route navigates to
its new URL, a fresh use() on the non-empty path takes over.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire script editor to UserDraft
The script editor's top-level state now lives in UserDraft.use(), keyed
on the route's path (page.params.path on /scripts/edit, '' on /scripts/add).
Deep edits inside ScriptBuilder persist automatically; deploy and draft
restore now call UserDraft.remove to clear the local autosave alongside
the backend draft.
Replaces the URL-hash autosave that ScriptBuilder used to write via
replaceStateFn — that prop is now gone, the encodeScriptState debounce
is gone, and Triggers no longer takes a saveSessionDraft callback.
Viewing a specific historical hash (?hash=...) is kept draft-free by
passing '' as the path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire flow editor to UserDraft
flows/add and flows/edit drive the flow value through a StateStore
adapter backed by UserDraft.use, so every edit auto-persists at
userdraft/w/{ws}/flow/{path} without touching FlowBuilder's internal
.val convention. On returning visits the local autosave wins and a
toast offers a diff against the latest backend draft/deployed version;
on a fresh visit the backend value is written into the handle. Deploy,
save-as-draft rename, restore-draft and restore-deployed each call
UserDraft.remove on the route path so the local autosave doesn't
outlive the action.
Adds UserDraft.has() for "is there already a local draft?" detection
in the load path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire app editor to UserDraft
AppEditor registers a UserDraft.use<App> handle for its current path
(empty path for /apps/add stays in-memory) and a single $effect
deep-tracks the internal stateApp and forwards every mutation to the
handle. useLocalStorageValue's lastSerialized check then dedupes the
actual localStorage writes per tick, so even fast drag/resize loops
only persist when the JSON output really changes.
/apps/edit overlays a local autosave from UserDraft.get on top of the
backend value when one exists, with the existing "Discard / Show diff"
toast wired to UserDraft.remove. Deploy, save-as-draft, restore-draft
and restore-deployed all call UserDraft.remove on the relevant path,
including the JSON editor save paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire raw app editor to UserDraft
/apps_raw/edit owns the canonical raw-app state (files, runnables,
data, summary) in four $state vars; a single $effect deep-tracks them
and forwards the bundle to a UserDraft.use<RawAppDraft> handle so each
mutation tick persists at userdraft/w/{ws}/raw_app/{path} (deduped by
useLocalStorageValue's serialized check). On load the route overlays
the local autosave on top of backend.draft/deployed and offers a
"Discard / Show diff" toast when they diverge; matching local entries
are silently dropped. Deploy, save-as-draft rename, restore-draft and
restore-deployed each call UserDraft.remove on the route path.
/apps_raw/add keeps the same shape (UserDraft.use with empty path)
so the draft is in-memory only and we drop it explicitly when the
initial save creates the real path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire resource editor to UserDraft
ResourceEditor registers a UserDraft.use<ResourceState> handle keyed
on the initialPath (empty for new resources, in-memory only). A
$effect deep-tracks the current workspace's edit state and forwards
mutations to the handle; on bootstrap and lazy backend-fetch the
local autosave wins over the backend value when they diverge. After
a successful save() we call UserDraft.remove so the local autosave
doesn't outlive the deploy. Cross-workspace deploys always start from
the live backend value rather than the local draft.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(frontend): wire variable editor to UserDraft
VariableEditor persists the current workspace's edit state via
UserDraft.save on every mutation, keyed on editPath ('' for new
variables → in-memory only). Backend fetches now overlay a matching
local autosave when one exists, and initNew() rehydrates from the
in-memory empty-path entry so opening a fresh "Add variable" drawer
keeps any unsaved work from the previous open. After a successful
save we drop the corresponding entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* editor external changes sync
* fix(frontend): don't UserDraft.remove flows while route is still mounted
The /flows/add and /flows/edit routes drive FlowBuilder from a flowStore
whose getter reads flowHandle.draft directly. Calling UserDraft.remove
synchronously before goto() therefore wiped the in-memory entry, made
flowStore.val collapse to emptyFlow(), and tripped
UnsavedConfirmationModal against the just-saved value — even though the
deploy/save-draft itself succeeded.
Drop those explicit removes in onSaveInitial, /add onDeploy, and
/edit onDeploy. The empty-path entry self-cleans on unmount via
onDestroy ref counting; for the non-empty edit path the next visit's
load-time diff will silently overwrite localStorage when the local
autosave matches the deployed value. Restore-draft/restore-deployed
keep their explicit remove because they navigate to the same route
(no modal) and loadFlow immediately rehydrates the handle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Revert "fix(frontend): don't UserDraft.remove flows while route is still mounted"
This reverts commit
|
||
|
|
d0f23cc523 |
feat(frontend): unified EditorHeader with file picker for flow/script/app editors (#9047)
* feat: add EditableInput component
* feat: add EditorHeader for flow editor with file picker entry point
* feat: WorkspaceItemPicker for editor header navigation
* feat: clickable breadcrumb in EditorHeader, scoped picker keyboard nav
* fix: reload flow on URL change and reset highlight in search mode
* feat: editor header layout polish and trigger removal
* feat: apply EditorHeader to script, app, and raw app editors
* fix: show generated initial path for new apps in EditorHeader
* fix: align EditorHeader new-app path with draft drawer's Path component
* fix: read page.params.path in loadApp to reload on URL change
* fix: remount AppEditor when navigating between apps
* fix: clear app/files on URL change so editor remounts with fresh data
* fix: route picker selections to /apps/edit or /apps_raw/edit based on raw_app
* fix: drop Save button from path popover; defer rename to deploy
* refactor: drop pathPopoverContent snippet, bind newEditedPath directly
* refactor: dedupe editor header plumbing (editPathFor, userPathPrefix, breadcrumb snippet)
* fix: freeze breadcrumb during path edit so popover doesn't drift
* fix: drop spinner from path dependency-check; render nothing when no usages
* fix: swallow 404 in checkFlowOnBehalfOf so renaming a flow doesn't toast
* Revert "fix: swallow 404 in checkFlowOnBehalfOf so renaming a flow doesn't toast"
This reverts commit
|
||
|
|
07a4cb6872 |
branch download UI on shouldDownloadViaClient instead of onclick interception (#9118)
* fix(frontend): branch download UI on shouldDownloadViaClient instead of intercepting in onclick When OpenAPI.TOKEN is set, several download links rendered an `<a href>` to the API and relied on an `onclick` handler to call `e.preventDefault()` and route the request through `downloadViaClient`. This is fragile in embedded contexts (e.g. the whitelabel React SDK) where Svelte's hydrated event listener may not intercept the click in time, so the browser follows the unauthenticated `href` straight to the API. Mirror the drawer pattern already used in `LogViewer` and `FlowStatusViewerInner`: render a `<button>` calling `downloadViaClient` when `shouldDownloadViaClient()` is true, and fall back to the plain `<a href download>` otherwise. Affects the LogViewer top bar, the large- result download in DisplayResult, the inline S3 link in ObjectViewer, the CSV link in ParqetCsvTableRenderer, and FileDownload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(frontend): treat custom HEADERS / basic auth as token equivalents in shouldDownloadViaClient Customers wiring the SDK with cookie-bypass auth via custom request headers (e.g. `OpenAPI.HEADERS = getAuthHeaders()` returning a Bearer header) had `shouldDownloadViaClient()` return false because it only checked `OpenAPI.TOKEN`. The plain `<a href download>` branch then followed the link without those headers, so authenticated downloads silently degraded to the cookie path (or failed when there is no cookie). Widen the check to any non-cookie auth: TOKEN, HEADERS, or USERNAME (basic auth). Route `downloadViaClient` through the generated client's `getHeaders` so all configured auth schemes are applied consistently instead of hand-building an Authorization header for TOKEN only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e3a914fd48 | download files via openapi client when token is set (#9102) | ||
|
|
9de38f9a09 |
feat(forks): handle triggers and schedules in wmill workspace merge (#9023)
* feat(forks): handle triggers and schedules in wmill workspace merge Closes #9001. Brings CLI parity with the merge UI by routing trigger and schedule diffs through the existing workspace_diff tally infrastructure and lifting the deploy logic into the shared windmill-utils-internal module. - Backend: extend tally + compare to all 10 trigger kinds + schedule; new compare_two_trigger_or_schedule helper using to_jsonb minus runtime ignore set; CompareSummary gains schedules_changed/triggers_changed. - Operational-state invariant: fork operations never flip target's mode/enabled. Triggers strip mode/enabled in both UI and CLI deploy payloads (preserved by is_mode_unspecified on backend). Schedules drop the setScheduleEnabled mirror entirely on merge — EditSchedule lacks enabled by design. - Shared module: DeployKind extended with schedule + per-kind triggers; DeployProvider gains per-kind dispatch methods. - Frontend: ~600 lines of client-side trigger-diff machinery deleted; rows flow through comparison.diffs like every other kind. Diff drawer returns full GET response stripped of runtime fields, matching backend semantics. Default selection excludes triggers/schedules (opt-in). - CLI (merge.ts): per-kind provider, GCP-specific transforms (audience reset, base_endpoint with /api stripped to match frontend), summary table rows for Schedules/Triggers, default-deselect mirroring the UI. - Bumps windmill-utils-internal to 1.5.0 (new exports for trigger per-kind dispatch); frontend depends on ^1.5.0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(enterprise): clarify [ee] prefix applies whenever an EE companion PR exists Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to 6ee680c25e3413d928fc22002be6deb118092668 This commit updates the EE repository reference after PR #557 was merged in windmill-ee-private. Previous ee-repo-ref: ad35a056627656fd426fb19856ea945955d4727f New ee-repo-ref: 6ee680c25e3413d928fc22002be6deb118092668 Automated by sync-ee-ref workflow. * fix(forks): preserve target state on merge update, mirror source on create Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(forks): strip server-managed trigger fields and honor --include with --skip-conflicts Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
c1e52eab09 |
fix: navigate home arrows (#9024)
* Navigate with arrows * Jumps to other side item + load 30 more * No workspace selector * Recommendations Claude check * Navigation horizontal * Same --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev> |
||
|
|
05baa4ab02 |
feat: allow hiding catalog picker and raw input on s3 form fields (#8902)
* feat: allow hiding catalog picker and raw input on s3 form fields Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * refactor: type itemsType.resourceType instead of casting to any Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
91064ce857 |
feat(frontend): improve permissions drawer UX and auto-share resource variables (#8824)
* feat: improve permissions drawer UX and auto-share resource variables
- When sharing a resource, automatically detect linked variables ($var: refs)
and offer to apply the same permission changes via a toggle (on by default)
- Rename "Share" to "Permissions" across all dropdown menus (resources, variables,
scripts, flows, apps, schedules, triggers)
- Replace Share icon with Shield icon for consistency
- Show default permissions (folder/user/group) as a separate section in the drawer
- Move item path into drawer title ("Permissions for {path}")
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: guard async results against stale drawer state and null-safe extra_perms
- Add path staleness check in loadLinkedVarPaths and loadDefaultPerms
to prevent late async responses from overwriting state when the drawer
was reopened for a different item
- Use ?? {} fallback for folder.extra_perms which can be undefined
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
b783bf2d83 |
fix: show full path on hover in deploy drawer and widen drawer (#8799)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
c57c769dea |
feat: add CI test scripts with auto-trigger on deploy (#8736)
* feat: add CI test scripts with auto-trigger on deploy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix annotation parser early return and handle renames correctly Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: move CI test results to top of script/flow detail pages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: improve CI test results spacing, icon, and remove pass label Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: support one-line annotation and use script/path format Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: move CI test trigger logic to EE Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: move CI badge next to New badge and add deduplicated CI summary Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add CI test e2e tests and fix nullable column annotations Add integration tests for CI test annotation parsing (creates/removes ci_test_reference rows) and the CI test results API (single + batch endpoints). Add backend test for auto-trigger on deploy (private+python). Fix sqlx LEFT JOIN LATERAL nullable column annotations in get_ci_test_results and get_ci_test_results_batch queries — sqlx cannot infer nullability from LATERAL subqueries, causing runtime decode errors when no matching job exists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix build/sqlx * fix * feat: CI test improvements and templates - Fix windmill-dep-map/private feature propagation in worker, api-scripts, and api-flows Cargo.toml so CI test triggers actually fire in EE mode - Clone ci_test_reference rows during workspace fork - Add polling to CiTestResults component (refetch every 3s while running) - Add running state and auto-refresh to ForkWorkspaceBanner CI summary - Add yellow "CI test" badge on script list rows and detail page - Fix Library badge border color (remove indigo border override) - Add CI Test TypeScript and CI Test Python templates in ScriptBuilder - Update sqlx offline cache - Add debug tracing for CI test trigger in worker_lockfiles Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add missing children prop to WorkspaceDeployLayout Fixes svelte-fast-check type error when passing named snippets as children content inside the component tag. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review feedback - Remove empty wrapper divs around CiTestResults, move mb-4 into component - Add batch endpoint size cap (max 200 items) - Add ON DELETE CASCADE to ci_test_reference workspace FK (new migration) - Downgrade CI test trigger logs from info to debug - Fix false-positive polling: only treat status='running' as running, not null status (CiTestResults, CompareWorkspaces, ForkWorkspaceBanner) - Fix test numbering in integration tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to latest EE commit Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update ee-repo-ref to d9d68c2406df0b59f413ea0b2cb24780a9817d04 This commit updates the EE repository reference after PR #516 was merged in windmill-ee-private. Previous ee-repo-ref: d7ccd9b86da99ec056a0e8708e3637d64290387a New ee-repo-ref: d9d68c2406df0b59f413ea0b2cb24780a9817d04 Automated by sync-ee-ref workflow. * fix: treat queued jobs (job_id set, null status) as running Jobs that have been pushed but not yet picked up by a worker have a job_id but null status. Treat these as 'running' to avoid showing misleading 'pass' badges or '0 passing'. Tests that were never triggered (no job_id, null status) remain neutral/hidden. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: hugocasa <hugo@casademont.ch> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
3d4f4c6c38 |
feat: Fork datatables (#8339)
* export_datatable_schema * Propose to fork the datatable on ws fork * dump datatable * Dockerfile * Fix import_datatable_dump * datatable schema fork works! * Option to copy both schema and data * Datatable fork behavior * nit ui * use psql instead * remove fork_datatable route * feat: add fork_pg_database and export_pg_schema routes with DB Manager UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: pluralize "schema" to "schemas" in DB Manager export/import UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add import mode select (schema only vs schema + data) to DB Manager import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Select schema or schema+data when important database * fix: prepend $res: prefix to resource paths in DB Manager import/export Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: dynamic import button label based on selected mode Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nits * feat: add warning alert when schema+data import mode is selected Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit hide on cloud hosted * refactor: remove fork_behavior from datatable settings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: split CreateWorkspace into layout wrapper and CreateWorkspaceInner Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: instantiate CreateWorkspaceInner in globalForkModal Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit icons * Data table fork UI * feat: pass per-datatable fork behaviors from UI to backend during workspace fork Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix fork overwriting all datatables * UI nits * custom instance db refactor * custom instance db wizard btn for all in dropdown * nit * Delete custom instance database button * Disable forking for resource datatables * Big import buttons when db empty * Revert "Disable forking for resource datatables" This reverts commit |
||
|
|
c4c9ef5fd7 |
feat: add optional labels to scripts, flows, apps, schedules, triggers (#8609)
* feat: add optional labels to scripts, flows, apps, raw apps, schedules, and triggers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: update sqlx cache, make labels optional in openapi, regenerate system prompts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add minimal labels input UI to script, flow, and schedule editors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: reduce gap between summary and labels input
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add labels to script/flow detail pages and summary/path popover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move labels inside SummaryPathDisplay trigger for clickable area, reduce gap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: display labels inline to the right of summary, not below
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase gap between summary and labels
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add labels to resources/variables, make labels nullable, add home page label filter badges
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add labels to workspace export/import, resources, variables + test coverage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: make migration idempotent, regenerate sqlx cache after merge
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass labels in script create and flow create/update API calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add labels input UI to resource and variable editors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove negative margin from LabelsInput to prevent overlap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add top and left margin to LabelsInput for better spacing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: reduce left margin on LabelsInput
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: widen label input to w-32
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use inline-flex so LabelsInput doesn't stretch full width
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove flex-wrap so label input stays on same line as badges
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add label filter presets to resources, variables, and schedules search
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use max-w-32 on label input to prevent stretching
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pull labels closer to summary with negative top margin
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: increase negative margin to pull labels even closer to summary
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass labels in schedule create/update API calls
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use COALESCE to preserve existing labels when not provided in schedule/flow update
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add labels to CreateResource, EditResource, CreateVariable, EditVariable in OpenAPI spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: display label badges on resource and variable list pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: display label badges on schedule and all trigger list pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add folder and label presets to schedules search filter
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: apply user_folders_only filter on all workspaces including admins
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add label presets to resources and variables search filters
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: derive folder presets from loaded items, not all workspace folders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add label query parameter to resource and variable list endpoints in OpenAPI
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: display label filter badges inline with folder filters on home page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Revert "feat: display label filter badges inline with folder filters on home page"
This reverts commit
|
||
|
|
a46aa641f9 |
feat: add R language support (#8263)
* feat: add R language support Add R as a new supported scripting language in Windmill, following the same pattern used for Ruby. Includes: - Backend: ScriptLang::Rlang enum variant, DB migration, tree-sitter-r parser crate with tests, WASM parser binding, R executor with NSJail sandboxing, job dispatch and signature parsing - Frontend: language picker, R icon, syntax highlighting, editor bar insertions (Sys.getenv, get_variable, get_resource), schema inference, init code template, BETA badge - CLI: .r extension mapping, sync support, bootstrap template R scripts use `main <- function(...)` syntax, jsonlite for JSON serialization, and system curl for the Windmill client helper. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add R package resolution and installation Parse library()/require() calls from R scripts to extract dependencies. Resolve versions from CRAN, cache lockfiles in pip_resolution_cache, and install packages to a shared R library cache. The run step sets R_LIBS_USER so installed packages are available to the script. - Parser: parse_r_requirements() extracts package names from AST - Executor: resolve() generates lockfile, install() installs from CRAN - Worker lockfiles: wire up R resolve for dependency jobs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add nsjail sandboxing for R resolve and install phases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fix R get_variable/get_resource and add sandbox annotation + e2e tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: fix R arg inference with JS fallback parser and get_variable/get_resource Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix flake * nsjail * nits * fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits - Suppress renv verbose output during resolve and install (controlled by #verbose annotation) - Filter renv from install list (already loaded, causes noisy restart message) - Log compact "resolved N packages" instead of full renv.lock JSON - Add R (r-base, r-cran-renv) to DockerfileFull and DockerfileFullEe - Use disable_rl for nsjail install config (R compiles from source) - Reduce default concurrency from 20 to 5 - Add rlang to openflow.openapi.yaml - Fix MainArgSignature (no_main_func -> auto_kind) after main merge Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * final * fix: remove accidental R install from multiplayer Dockerfile Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove R from Windows build and DockerfileExtra Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: rename R migration to avoid timestamp collision with trigger_filter_logic Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * all * fix: R install improvements - suppress verbose output, flat lockfile logging, Dockerfile R support, rlimits Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add clear error when Rscript binary is missing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: fix type errors in R fallback parser, use format! in wrap(), add R system prompts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pyranota <pyra@duck.com> |
||
|
|
1fa4d919b3 | fix: upload_s3_file not working in VS Code extension (#8547) | ||
|
|
1a73012e07 |
fix: filter null entries in FileUpload initialValue to prevent s3 access error (#8544)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
69ce946241 | feat: add trashbin system for soft-deleting items (#8519) | ||
|
|
f481ea4059 |
fix(frontend): fix output of resultnode + svelte5 nits (#8424)
* fix(frontend): remove banned $bindable('') pattern from ClearableInput
Switching format types in the flow input editor caused a
props_invalid_value error because ClearableInput used
value = $bindable(''), which conflicts with undefined bindings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(frontend): restore flow result display in result node
The fix in #8390 changed updateLastJob() to only use testJob when
actively running/streaming, preferring flowStateStore for completed
results. But the result node has moduleId='' and no flowStateStore
entry, so the early return made it always show the empty state.
Add !moduleId to the testJob condition so the result node (which has
no flowStateStore entry) still uses testJob as its only data source.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|
|
31d6660d56 |
feat: script module mode with CLI sync, preview, and WAC UI improvements (#8380)
* feat: add script module mode with folder model for Bun and Python Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add missing modules field to RawCode in bun_executor Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * sqlx * feat: enrich WAC templates with checkpoint and replay semantics Add prominent comments explaining that all computation must happen inside task/step/taskScript or it will be replayed on resume/retry. Clarify that waitForApproval does not hold a worker and that approve/reject URLs are available in the timeline step details. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(cli): script module sync idempotency, per-module hash tracking, and preview support - Fix pull→push idempotency: use `??` instead of `||` for module lock field so empty strings are preserved (matches API's `lock: ""`) - Add per-module hash tracking in wmill-lock.yaml following the flow inline script pattern (SCRIPT_TOP_HASH + per-module subpath hashes) - Selective module lock regeneration: only regenerate locks for modules whose content actually changed, not all modules - Use unfiltered rawWorkspaceDependencies for module hashes to match what updateModuleLocks passes to fetchScriptLock - Show changed module names in stale script output for clarity - Add module support to `script preview` command: read modules from __mod/ folder and pass them in the preview API request - Add preview tests for taskScript pattern (flat and folder layout) - Update test assertion for module stale detection output Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(frontend): WAC UI improvements — reorder templates, module tab rename, import consolidation - Reorder WAC template buttons: TypeScript before Python in ScriptBuilder, CreateActionsScript, and CreateActionsFlow - Remove dropdown items from +Script button (simplify to direct link) - Move "Import Workflow-as-Code" to +Flow dropdown with dedicated drawer - Add module tab rename: pencil icon on hover opens popover with validation, fixed-width icon container prevents layout shift Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: remaining module-mode changes from working branch - Backend parser updates for WAC detection - CLI sync/types updates for raw app path and module support - Frontend UI polish (Dev.svelte, ScriptRow, script hash page) - Test fixture updates Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test(cli): add test for module modification detection in generate-metadata Verifies that modifying a single module file re-triggers stale detection and only the changed module is listed, not all modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): critical fixes from PR review - Fix hardcoded dev path in bun_executor.rs WAC v2 wrapper — use "windmill-client" import instead of absolute filesystem path - Fix missed no_main_func → auto_kind rename in parser TS test - Add modules column to clone_script SQL (windmill-common and windmill-api-workspaces) so cloned scripts retain their modules - Add modules: None to RawCode structs in worker tests - Restore complete sqlx cache (merge main's cache + our new queries) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): fix clone warning treated as error in CI Change `.clone()` on double reference to `*k` dereference in scripts.rs hash implementation. Update sqlx cache with new query hashes from modified clone_script SQL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(frontend): use published parser wasm versions for CI build The local file:// paths for windmill-parser-wasm-py and windmill-parser-wasm-ts don't exist in the Cloudflare Pages build environment. Revert to published npm versions (1.655.0). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(frontend): update parser wasm packages to 1.657.2 Use newly published windmill-parser-wasm-ts and windmill-parser-wasm-py v1.657.2 which include auto_kind/WAC detection changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(frontend): regenerate package-lock.json for npm ci compatibility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(frontend): use main's lockfile as base, update only parser wasm packages Regenerating package-lock.json from scratch pulled different dependency versions causing svelte-check type errors. Instead, start from main's lockfile and only update the two changed packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): add modules column to fetch_script_for_update query The Script<SR> struct has a modules field (FromRow), but fetch_script_for_update didn't SELECT modules, causing a runtime error "no column found for name: modules" when the worker processed dependency jobs. This was the root cause of the relock_skip test timeout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): fix script module execution for Python and Bun - Fix modules not passed through job queue: inject _MODULES into PushArgs.extra when pushing Code jobs so worker can extract them - Fix Python module imports: use relative imports (from .helper) and add sys.path.insert for module directory in wrapper - Fix Python tests: use relative imports and empty lock to prevent pip from resolving module names as packages - Add local file check in Bun loader for module resolution - Ignore Bun module test (bundle mode loader integration tracked separately) - Add missing modules column to fetch_script_for_update query Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): remove unnecessary empty lock in Python module tests Relative imports (from .helper) are not parsed as pip packages, so the empty lock workaround is not needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(backend): fix module execution for Python and Bun — all tests pass Python modules: - Use relative imports (from .helper import greet) since scripts run as packages - Add sys.path.insert for module directory in wrapper to ensure local modules take precedence over pip packages with same name Bun modules: - Use bundled output (./out/main.js) as wrapper import when modules are present — the bundled output has module content inlined by Bun.build, avoiding runtime loader resolution issues - Add local file check in loader.bun.js onResolve to short-circuit API URL resolution for module files on disk Job queue: - Inject _MODULES into PushArgs.extra when pushing Code jobs so the worker can extract them at execution time Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: address PR review — simplify, fix correctness, remove dead code Critical fixes: - Replace all CLI `no_main_func` references with `auto_kind` (string) to match the backend migration and API changes - Remove duplicated `compute_python_module_dir` in worker.rs, use the canonical version from python_executor.rs High priority: - Auto-create `__init__.py` in intermediate directories for nested Python modules so imports like `from .utils.math import add` work without users manually creating __init__.py files - Remove redundant `sys_path_insert` — relative imports use Python's package system, not sys.path Medium: - Fix lock file base name extraction: use regex to strip only the final extension (`.replace(/\.[^.]+$/, '')`) instead of `indexOf(".")` which breaks for files like `helper.test.ts` Simplification: - Remove dead `{#if false}` Popover block in ScriptEditor.svelte - Guard loader.bun.js local file check to only run for relative paths (matching the Windows loader pattern) - Add clarifying comment on Bun dual mechanism (build + run phases) - Add maintenance comment on manual Hash impl for NewScript Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: final review fixes — stale cleanup, baseName, auto_kind export - Fix sync.ts baseName extraction using indexOf(".") → regex (same fix as script.ts/metadata.ts, missed this instance) - Add stale module file cleanup in writeModulesToDisk: removes files from __mod/ that are no longer in the modules map before writing, fixing the pull→push cycle that couldn't delete modules - Log warning when _MODULES serialization fails in job push instead of silently dropping modules - Use strict equality (===) for auto_kind comparison - Exclude auto_kind from workspace export — it is auto-detected by the parser at deploy time from script content Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove auto_kind from push, comparison, and metadata auto_kind is auto-detected by the parser at deploy time, so the CLI should not send it, compare it, or write it to script.yaml. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove erroneously added backend/backend/.sqlx directory Duplicate .sqlx cache was committed at the wrong nested path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address PR review feedback + fix CI dead_code warning Frontend (ScriptEditor.svelte): - Fix switchToMain() missing lastSyncedCode update — prevents stale code sync on external changes while editing a module tab - Fix formatAction saving module code to main script's localStorage draft — now saves main code when on a module tab - Fix non-null assertion on inferModuleLang in renameModule — fall back to original language instead of force unwrap - Remove redundant activeModuleTab truthy check in runTest CLI (script.ts): - Clean up empty directories after removing stale module files in writeModulesToDisk Backend: - Add path traversal guard in write_module_files — reject module paths containing ".." - Fix dead_code warning on auto_kind field in workspace export struct Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(frontend): improve auto_kind UX + address review findings - Rename "Include without main function" toggle to "Include library scripts" in script list (ItemsList.svelte) - Update NoMainFuncBadge: "No main" → "Library" with clearer tooltip - Filter module file extensions by main script language — Python scripts only allow .py modules, TypeScript only .ts, etc. - Split flushModuleState into flushModuleContent (no UI side-effect) and flushModuleState (flush + reset tab), reducing duplication - Dynamic placeholder and hint text in add module popover based on main script language Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
9d2c439e2a |
fix: resource drawer opening behind dialog in chat mode (#8328)
* fix: resource drawer opening behind dialog in chat mode Integrate Modal into the Disposable z-index stacking system so drawers opened from within a modal (e.g. "Add a new resource") correctly appear above the dialog instead of behind it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resource drawer opening behind dialog in chat mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: simplify minZIndex tracking by removing unnecessary refcount Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use map-based minZIndex tracking and conditional chat elevation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: use plain object instead of Map for reactive minZIndex tracking $state(new Map()) is not deeply reactive in Svelte 5 — only plain objects and arrays are proxied. Replaced with Record<string, number> so that property assignments properly trigger $derived updates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
ae019237d1 | runs page nits (#8325) | ||
|
|
5d79f33590 |
Final Svelte 5 migration (#8211)
* Remove $$props.field usage * Rename slots to ensure no hyphen * _props * _trigger * OnSelectedIteration type correct capitalization * rename _content * Remove afterUpdate * Migrate everything to svelte 5 * array bind * Fix popover * type never * nit fixes * Fixed many trivial errors * onClick * Fix errors * use let: * nit typing * fix: wrap state_referenced_locally vars with untrack() Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add untrack import * Fix all syntax errors due to untrack migration * Fix undefined errors * Fix more undefined errors * untrack(() => initialOpen) * svelte-ignore * Fix state_descriptors_fixed error in Chart.svelte Use $state.snapshot() to pass plain copies of data/options to Chart.js instead of $state proxies. Chart.js's listenArrayEvents tries to define property descriptors on data arrays, which Svelte 5 proxies reject. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * nit typing * Merge issue * Fix "path is not set" error in resource picker / editor * Fix InputTransformForm error when rerunning some flows * fix npm run check --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
5f0ef936d1 | feat: add sandbox annotations, volume mounts, for AI sandbox starting with claude (#8058) | ||
|
|
c9c3baecb3 |
add context menu with delete option to preprocessor nodes (#8223)
* fix: add context menu with delete option to preprocessor nodes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add delete styling and shortcuts to right-click context menu Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
f6ceb2e366 |
Remove edit in fork button for app.windmill.dev (#8213)
* Remove edit in fork button for app.windmill.dev * remove duplicate import |
||
|
|
18552046c2 |
feat: add right-click context menu to ObjectViewer (#8181)
* feat: add right-click context menu to ObjectViewer Add a contextual menu to ObjectViewer.svelte that appears on right-click with three actions: - Copy value: copies the field's value to clipboard - Copy object key: copies the property key name - Copy entire object: copies the parent object as JSON Uses setContext/getContext to share the context menu handler across recursive ObjectViewer instances, rendering a single menu at the root level via Portal. Reuses existing contextMenuStyles for visual consistency. Closes #8177 Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> * Fix popover closing * Use existing ContextMenuItem patterns * hover style * close contextmenu on pointerdown outside * try catch for circular objects * Fix copying undefined not working --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> Co-authored-by: Diego Imbert <diego@windmill.dev> Co-authored-by: Diego Imbert <70353967+diegoimbert@users.noreply.github.com> |
||
|
|
eeb823b0b5 |
Runs page nits (#8084)
* nit warning toast * timeframe as URL param * all workspaces filter only in admins workspace * nit bold todays date |
||
|
|
cf7f704a91 |
add button to edit in workspace fork (#8119)
* Add button to edit in workspace fork * Remove old fork from script row * Remove fork button from approw * fix frontend check |
||
|
|
16a6d5e7af |
feat: Broad filters for search (#8112)
* Default filters * nit style * Nit fixes * broadFilter for runs * unused param * Remove debounce from assets page * Escape ILIKE patterns * fix pg enum cast to text for ILIKE * nit error |
||
|
|
935b0058e2 |
feat: show triggers in fork deploy to parent UI. (#8094)
* Add rudimentary trigger display in WorkspaceCOmparison * Trigger display * Add email specification * Add link to trigger page * fix typo * fix frontend check |
||
|
|
7ac93f6ee3 | feat: option to preserve on_behalf_of and edited_by for admins and users in the new wm_deployers group (#8079) | ||
|
|
9b28c85469 |
feat: Unified filters and new runs page (#8027)
* RunsPage redesign v0 * nit * Remove manualdatepicker * remove shadow * ui nits * nit scrollbar bg * prettier cards * nit * Remove code * command/meta multi select * Shift select * RightClickPopover * nit * Ctrl A * nit card * DropdownMenu * nit * count hint * fix stuck keys * opacity UX * error toasts pickhubscript * Improve UX * fix undefined error * keyboard nav * nit batch rerun fixes * nit fix scroll / height * Batch reruns actions + nits * nit * Cancel selected jobs * Cancel / re-run all filtered jobs * Go to job / flow / script action * nit * add batch actions back * nit * nit * bar on splitpane hover * nit * New Timeframe system * reset btn * nit fixes * dead code * nits * typecheck * naming clarity * Update frontend/src/lib/components/RightClickPopover.svelte Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> * unnecessary json stringify * dedup 'the' * Code deletion to prepare for changes * filter types * ui * fix bug with maxTs * stuck with melt * GenericDropdown * filters onclick * iterate * iter * add all filters * Descriptions * focus position * stash * TaggedTextInput works much much better * placeholder * currentTag suggestion * improve * nit * Keyboard nav * buildRunsFilterSearchbarSchema * nit naming * assignObjInPlace * Escaping + pretty dates * nit empty * fix cursor * nit space * Filter filtering * escape pasted value * nit * escape spaces * nit undefined * add space at end if right arrow * escape all spaces * arrow skips escape chars * escape \ too * delete whole escaped characters * double space to escape tag * code refactor * Ensure cursor visible * fix keyboard nav * safety * filterSchemaRecToZodSchema * URL Sync * fix readonly * fix typing * start replacing old filter logic * use new filter impl * nit * nit reactivity * nit fix * no more localStorage * Add back status and kind toggles * Nit fix * style nit * focus at end on click * clearn btn + fixes * fix broken date uri * nit * useSyncedTimeframe * negative filter button * negative filters helpers rust * Negated filters backed * nit * highlight * New useSearchParams * Accept comma separated list * nit allowNegative * openapi update * Fix trigger kind list/negation not working * nit oipenpai * Presets * DebouncedTempValue * remove presets from list when already applied * UI nit improvements * allowMultiple * hint * validateFilterInstance fn * nit fix * error highlights * nit ux selecting negative list * nit * on clear btn * SimpleEditor for JSON * nit * flop * Pass presets as param * nit delete * preventCursorMoveOnNextSync * responsive layout * Escape \n * Inline calendar input * mm/dd or dd/mm depending on US or not * onClickBehavior * infiniteRange * other nits * Wiring with runs filter * formatDateRange better * inits on right page * style * min hour support * Time input * use our components * Improve SKILL.md * dd mm yyyy numeric input * TimeframeSelect with new date picker * fixes * ensure date is in view when value changes externally * fixes * nit select all on focus * select year + nits * nit layout shift * nit negative when starting with ! * nit * SelectDropdown uses GenericDropdown now * Fix blank select dropdown rendering bug * icons * Reset btn + shorter date range formatting * overflow fix * unnecessary absolute * fix clear btn overlap * Update routes for new filters (assets, schedule, resource, variables) * update openapi * Impl for other pages * ui nits * nit fixes * Fix columns filter * super nits --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> |
||
|
|
dd419ade94 |
fix(frontend): redesign instance settings (#7916)
* handle dirty config * Move instance update in drawer actions * Put windmill version in drawer header * Use sidebar instead of tabs * Rework user section * improve user table * Handle EE * Add settings section header * test-1 * option 2 * create new settings group * harmonize all settings inputs * improve members/users table styling * refactor instance setup * show user count * nit * Create setting card component * harmonize instance settings and workspace settings * fix python version loader * nit * clean code * nit * add email validation * fix reactivity issue on default value * fix dirty config check * fix object storage dirty config check * Fix object storage settings reactivity * fix indexer dirty reactivity * Add validation for indexer * fix sso dirty issues * clean * nit |
||
|
|
b11d6ed794 |
fix(frontend): revert CloseButton refactor that broke tag removal in MultiSelect (#7909)
The recent refactor of CloseButton (from on:close component events to onClick prop) broke tag removal in MultiSelect/TagsToListenTo. The refactor changed on:pointerdown (component event) to onPointerdown (native DOM event), which stopped native pointerdown propagation and broke the drag tracking in DraggableTags, causing the dropdown to open on every close button click. Reverts CloseButton and all callers back to using createEventDispatcher and on:close. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
5e9b4cfa99 | nit UI + more tests | ||
|
|
31bfccc745 |
fix(frontend): improve time picker (#7893)
* clean layout * remove useless toggle * improve layout * nit * Fix input type seconds * convert secondInputs to svelte 5 * redesign seconds input * Adapt layout where time input is used * nit |
||
|
|
2851b6b7ca | feat: restriction rulesets for workspaces (#7879) | ||
|
|
dd421845ba |
fix(frontend): reorganize workspace settings (#7788)
* Add vertical nav bar to workspace settings * harmonize settings content titles * remove sidebar icons * add background to sidebar * nit user section * EEonly display * Workspace settings general design * Add schema validation and dirty detection * Put critical alerts in a separated tab * separate error success handler * only enable save when there is some changes * Fix dirty detection for deployment UI * Only enable save button when changes for datatables ws storage * Add setting footer component * Use new footer setting for saving configs * nit * apply setting footer * improve save button * nit * nit * nit * make ws app use same pattern as other tabs * Separate scrolling between sidebar and content * Gather error handlers * use universal save button for object storage * Title sentence case * nit * nit * improve dirty config logic * nit * nit * clean dead code * Use settings footer for deployment settings * Git sync settings * move tabs * fix dirty stats of error handlers * nit * nit |
||
|
|
1dc6b7493a | remove legacy RawAppService endpoints | ||
|
|
309de58134 |
Revert "feat: restriction rulesets for workspaces (#7791)" (#7820)
This reverts commit
|
||
|
|
a1cd02d7f8 |
feat: restriction rulesets for workspaces (#7791)
* Add frontend for the workspace proctection rules * api to add and update workspace protection rules * Fix bypasser selection * Fix Select bug on refocus * Change rulesets to use bitflags * Messages for protection rules errors * claude remove ui for rules * Hide edit buttons when rule * No edit refactor pt1 * Update edit buttons to be disabled when rule is active * Merge deploy ui and rulsets in one tab * Remove not cleaned line in migration * multiple fixes * Remove old protection rule logic * Add prrotection rule for deploying through Merge UI * Add Alert on legacy Deploy UI * Add backend enforcing of workspace rules * Finish backend blocking on rulsets * Last changes to api ruleset blocks * Prepare sqlx * Remove unused import and argument * Update SQLx metadata * fix npm run check * Re trigger CI --------- Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com> |
||
|
|
e1545943e1 | fix check (#7811) | ||
|
|
a3d75ba10a |
feat: favorite datatable and ducklake tables + asset page nits (#7795)
* update cf worker hostname
* set remote_url cookie from param
* ephemeral backends v1
* nit
* Run queue server
* ntis
* timeout
* better db process management
* commit hash and worktree
* nit use map
* nit
* err handling
* Revert "err handling"
This reverts commit
|
||
|
|
df51f96905 |
fix: Prettier and less invasive toasts (#7758)
* Toast update * ToastType * nit adjustements * nit smaller toast |