Files
windmill/frontend/src/lib/components/apps
GuilhemandClaude Opus 4.8 e09cd5862c feat: per-user draft review & deploy page (gating, badges, rename, raw-app deploy fixes) (#9625)
* feat: per-user draft gating, badges and rename display on deploy page

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

* fix(frontend): don't strike the path when a draft adds a summary to a summary-less item

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

* fix(frontend): don't strike draft-only items' auto-generated path against the pretty path

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

* fix(frontend): deploy raw-app drafts from top-level files so the bundle isn't dropped

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

* refactor(frontend): share raw-app source→draft-value projection across chat and deploy page

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

* fix(frontend): deploy renamed/new flow, app and raw-app drafts at draft_path, not the temp storage path

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

* refactor(frontend): add a design-system Checkbox and use it for deploy-page row/select-all checkboxes

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

* feat: "Show all drafts" toggle on the deploy-drafts page

Replace the deploy-drafts page's legacy-hiding "Only my drafts" toggle with
a "Show all drafts" toggle that switches the listing scope between the
current user's own drafts (+ legacy no-owner rows) and every user's drafts
in the workspace.

Backend (`drafts.rs`, `openapi.yaml`):
- `/drafts/list` gains an `all_users` query param that drops the owner
  filter, and a per-row `mine` flag (own draft or legacy no-owner row).
  `DISTINCT ON` now prefers the user's own row, then the legacy row, then
  another user's, so `mine`/`legacy_draft` describe the kept row.

Frontend (`CompareDrafts.svelte`, `workspaceDrafts.svelte.ts`):
- "Show all drafts" toggle (default off). The all-users superset is fetched
  lazily via the shared resource only while the toggle is on, so the page's
  fork draft-count (own drafts) is unaffected.
- Other users' drafts are view-only: disabled checkbox + Discard with a
  "belongs to another user" tooltip; Show diff stays enabled. Selection,
  select-all and the deploy count only ever include the user's own drafts.
  The multi-user warning triangle shows on owned rows only.

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

* fix(backend): gate all_users draft listing by read permission

Addresses the PR review on the per-user deploy-drafts page:

- `/drafts/list?all_users=true` previously had only `WHERE workspace_id = $1`
  with no read-permission check, so any non-operator could enumerate every
  draft's path, summary and authors — including items they can't read. Now
  rows the caller doesn't own (`mine = false`) are gated through
  `require_can_read_path` (the same gate `/drafts/get` uses) and dropped when
  unreadable; both its `NotFound` and `NotAuthorized` denials are treated as
  "not visible".
- Skip the per-row `require_can_write_path` probe on those non-owned rows
  (they're never selectable — `isSelectable` requires `mine`): set
  `can_write = false` directly, removing a redundant N RLS write-probes when
  `all_users` is on.

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

* fix(frontend): only confirm destructive draft discards on the deploy page

Discarding a draft is non-destructive in every case except removing the last
draft of a never-deployed item (`draft_only` with no other user's draft),
which permanently deletes it. Confirm only that case; reverting a draft over a
deployed item, or discarding your copy while another user still holds a draft,
now runs immediately (the ⚠️ already signals the multi-user case). Drops the
redundant "other users still have a draft" / "deployed version unaffected"
confirmation branches.

Harden the destructive check: it keyed off `otherDraftUsers()`, which subtracts
`currentUsername`; while `$userStore.username` is unhydrated, your own draft
looked like another user's, flipping a draft-only item to "non-destructive" and
deleting it with no confirmation. Now: deployed counterpart → never destructive;
`draft_only` with unknown `currentUsername` → treated as destructive (confirm).
The delete modal also shows the friendly `draft_path` instead of the raw
`draft_{uuid}` storage path.

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

* fix(frontend): deploy low-code app drafts (value + summary persistence)

A visual (low-code) app draft is autosaved as the *bare* App value
(grid/theme/... plus a draft-only `draft_path`), not wrapped in
{ value, summary, policy } like script/flow drafts. The Review & Deploy page
read `requestBody.value = d.value` — undefined for that shape — so deploying any
low-code app draft (created or edited) sent no value and failed. Read the value
from the draft object itself, strip the draft-only `draft_path` from it, and use
that as the deploy path.

Also persist the app summary, which was dropped entirely: the autosave stores
the bare App value (the summary normally lives only in the `app` table column,
set on deploy), so a draft never carried it — reopening a draft or deploying it
lost the summary. Mirror the summary onto the autosaved App (like `draft_path`),
read it back when loading a draft, and on deploy send it as the summary column
while stripping it (and `draft_path`) from the deployed value so the value stays
clean.

Verified end-to-end: a new low-code app with a summary deploys at its pretty
path with the summary set, content intact, and no draft_path/summary leaked into
the deployed value; the draft is cleaned up.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 13:49:36 +00:00
..
2025-06-24 08:41:46 +02:00