mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 08:07:15 +00:00
fix: gate operators earlier, skip the write tx without lineage, unblock a chained move
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
c33789e266
commit
0b0822cd2f
@@ -48,7 +48,17 @@
|
||||
return { ...(value as Record<string, unknown>), ...patch }
|
||||
}
|
||||
|
||||
let carryError = $state<{ title: string; detail: string } | undefined>(undefined)
|
||||
// Tagged with the destination it was raised for, because this component is
|
||||
// mounted for the editor's lifetime rather than per prompt: an untagged error
|
||||
// would still be rendered when the next move verdict opens the modal. Tagging
|
||||
// also survives the A→B→C case, where we deliberately re-point the verdict and
|
||||
// then raise an error about the new destination.
|
||||
let carryError = $state<{ title: string; detail: string; forMovedTo: string } | undefined>(
|
||||
undefined
|
||||
)
|
||||
const shownError = $derived(
|
||||
carryError && carryError.forMovedTo === moveHandle.move?.movedTo ? carryError : undefined
|
||||
)
|
||||
|
||||
async function continueThere() {
|
||||
const move = moveHandle.move
|
||||
@@ -67,16 +77,25 @@
|
||||
// so; the draft is still in this editor, so the user can retry.
|
||||
const failed = UserDraftDbSyncer.getState(target).failureMessage
|
||||
const movedAgain = UserDraftDbSyncer.getMove(target).move
|
||||
if (failed || movedAgain) {
|
||||
carryError = movedAgain
|
||||
? {
|
||||
title: 'It moved again',
|
||||
detail: `It is now at ${movedAgain.movedTo}. Your edits are still in this editor — retry to follow it.`
|
||||
}
|
||||
: {
|
||||
title: 'Could not save at the new path',
|
||||
detail: `${failed} Your edits are still in this editor.`
|
||||
}
|
||||
if (movedAgain) {
|
||||
// It moved again while we were carrying (A→B→C). Re-point this
|
||||
// editor's own move record at C so the modal now offers C and a
|
||||
// retry makes progress — without this the retry would keep
|
||||
// overwriting at B, be refused again, and loop with no way out.
|
||||
UserDraftDbSyncer.recordMove(query, movedAgain)
|
||||
carryError = {
|
||||
title: 'It moved again while saving',
|
||||
detail: `It is now at ${movedAgain.movedTo}. Your edits are still in this editor — continue to follow it there.`,
|
||||
forMovedTo: movedAgain.movedTo
|
||||
}
|
||||
return
|
||||
}
|
||||
if (failed) {
|
||||
carryError = {
|
||||
title: 'Could not save at the new path',
|
||||
detail: `${failed.replace(/\.?$/, '.')} Your edits are still in this editor.`,
|
||||
forMovedTo: move.movedTo
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -107,8 +126,8 @@
|
||||
Continuing takes your current edits to the new path, replacing any draft already there.
|
||||
Staying here leaves them unsaved.
|
||||
</p>
|
||||
{#if carryError}
|
||||
<Alert type="error" size="xs" title={carryError.title}>{carryError.detail}</Alert>
|
||||
{#if shownError}
|
||||
<Alert type="error" size="xs" title={shownError.title}>{shownError.detail}</Alert>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -663,6 +663,13 @@ export const UserDraftDbSyncer = {
|
||||
moves.delete(draftKey(query.workspace, query.itemKind, query.path))
|
||||
},
|
||||
|
||||
/** Re-point a key's move verdict, for an item that moved again while its
|
||||
* carry was in flight (A→B→C). Without this the prompt keeps naming B, and
|
||||
* every retry is refused for the same reason. */
|
||||
recordMove(query: UserDraftLastSyncQuery, move: DraftMovedInfo): void {
|
||||
moves.set(draftKey(query.workspace, query.itemKind, query.path), move)
|
||||
},
|
||||
|
||||
/**
|
||||
* Force-save: bypass the `last_sync` check and overwrite the server row
|
||||
* (conflict modal's "Overwrite the remote"). Resolves once the key's save
|
||||
|
||||
Reference in New Issue
Block a user