fix: close only draft editors during a move, and say why

Variable, resource and trigger editors save on click and write no draft,
so closing them during a move protected nothing and lost a half-filled
form when the move stopped. Only the editors that save drafts close, and
the pipeline tab names the move instead of Use mode.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem Lemouel
2026-10-26 11:21:24 -07:00
co-authored by Claude Opus 5.5
parent 6912a9546c
commit e8a17f42c8
2 changed files with 15 additions and 7 deletions
@@ -424,9 +424,11 @@
{:else}
<!-- A pipeline has no deployed page, only its editor. -->
<div class="flex-1 flex items-center justify-center p-8 text-center text-sm text-secondary">
{permissions.readOnly
? 'The pipeline editor saves drafts, which a session in Use mode cannot do.'
: 'The pipeline editor saves drafts, which your role cannot do in this workspace.'}
{permissions.moving
? 'The pipeline editor reopens once the session has moved to its fork.'
: permissions.readOnly
? 'The pipeline editor saves drafts, which a session in Use mode cannot do.'
: 'The pipeline editor saves drafts, which your role cannot do in this workspace.'}
</div>
{/if}
</div>
@@ -51,7 +51,8 @@ type WorkModeHost = { readonly workMode: AIWorkMode; readonly moving?: boolean }
* resolves: hiding every editor from a developer while `whoami` is in flight is the worse
* mistake, and the server refuses an operator anyway. A session held in Use opens no editor: one
* in a protected workspace, one whose role builds nothing there, or one whose chat is in Use
* mode — the chat `chat` returns, else the `aiChatManager` context's — and one moving into a fork.
* mode — the chat `chat` returns, else the `aiChatManager` context's. One moving into a fork opens
* no draft editor until the move ends, so nothing saves a draft in the workspace being left.
* Reads context and registers an effect: call during component initialisation.
*/
export function useSessionPermissions(
@@ -66,9 +67,9 @@ export function useSessionPermissions(
const readOnly = $derived(
protectedWorkspace.current ||
!buildsAnything(rights.capabilities) ||
host?.workMode === AIWorkMode.USE ||
!!host?.moving
host?.workMode === AIWorkMode.USE
)
const moving = $derived(!!host?.moving)
const workspaces = fromStore(userWorkspaces)
const entry = $derived(workspaces.current.find((w) => w.id === workspace()))
@@ -77,11 +78,16 @@ export function useSessionPermissions(
get readOnly() {
return readOnly
},
/** The session is moving into a fork: its draft editors stay closed until it ends. */
get moving() {
return moving
},
/** Whether this user can save the drafts the `kind` editor writes. */
canOpenEditor: (kind: string) => !readOnly && rights.roleCanDraft(kind),
canOpenEditor: (kind: string) => !readOnly && !moving && rights.roleCanDraft(kind),
/** The same, and this item's own permissions let them write it. */
canEditItem: (item: Pick<WorkspaceItem, 'kind' | 'raw_app' | 'path' | 'extraPerms'>) =>
!readOnly &&
!moving &&
rights.canDraftItem(item.raw_app ? 'raw_app' : item.kind, item.path, item.extraPerms),
/** Whether the page loads for this user rather than refusing them. */
pageAllowed: (page: PreviewPage) =>