mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 08:02:47 +00:00
fix(editors): read the live form after a save only while it is still the item's
The variable and schedule editors are reused for whatever is opened next, so a drawer switched while a write is in flight leaves every post-await read describing the item now on screen. The settle then took that for an edit made over the write and left the saved item's draft standing, and the schedule also installed the saved item's baseline into the new one, which the mirror published as a draft it never had. What was sent is still adopted; the live form is read only while the editor is where it saved from. Re-pointed, the cell it released during the write is what answers for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
This commit is contained in:
co-authored by
Claude Opus 5
parent
44833bfc6b
commit
dd9cc68362
@@ -373,9 +373,19 @@
|
||||
// to it via `discard` (not `remove` — blanking the cell to `undefined` reads
|
||||
// as dirty) and keeps an edit made mid-request. Each workspace settles
|
||||
// against the path its own write used, not the reported one.
|
||||
await settleDraftAfterWrite('variable', s, states[ws]?.draft, from ?? '', s.path, {
|
||||
workspace: ws
|
||||
})
|
||||
// The live cell only while this editor is still on the item it saved: the
|
||||
// drawer is reused, so after a re-point `states` is the next item's, and
|
||||
// reading it here would take that for an edit made over this write —
|
||||
// leaving this item's draft behind. Re-pointed, the cell it released
|
||||
// during the write is what answers.
|
||||
await settleDraftAfterWrite(
|
||||
'variable',
|
||||
s,
|
||||
editPath === from ? states[ws]?.draft : undefined,
|
||||
from ?? '',
|
||||
s.path,
|
||||
{ workspace: ws }
|
||||
)
|
||||
// Collected, not reported yet: a report retargets the host, whose `{#key
|
||||
// path}` would unmount this editor at the next workspace's await and leave
|
||||
// that one's handle released — its draft then settles against nothing.
|
||||
|
||||
@@ -699,6 +699,11 @@
|
||||
try {
|
||||
const isSaved = await saveScheduleFromCfg(scheduleCfg, edit, wsId!)
|
||||
if (isSaved) {
|
||||
// This editor is reused for whatever is opened next, so a drawer switched
|
||||
// during the write leaves every read below describing THAT schedule. Only
|
||||
// what was sent may still be adopted then; the live form belongs to the
|
||||
// item on screen, and its cell is not this write's to settle.
|
||||
const stillHere = initialPath === previousPath && wsId === previousWs
|
||||
// A create deploys the schedule enabled whatever the form said (see
|
||||
// saveScheduleFromCfg), so what counts as written records that — the baseline
|
||||
// would otherwise claim a state the server does not have. The form follows
|
||||
@@ -706,31 +711,35 @@
|
||||
if (wasCreate) {
|
||||
const sentEnabled = scheduleCfg.enabled
|
||||
scheduleCfg.enabled = true
|
||||
deployedEnabled = true
|
||||
if (enabled === sentEnabled) enabled = true
|
||||
} else {
|
||||
if (stillHere) {
|
||||
deployedEnabled = true
|
||||
if (enabled === sentEnabled) enabled = true
|
||||
}
|
||||
} else if (stillHere) {
|
||||
// An update's payload carries no `enabled` (see saveScheduleFromCfg), so
|
||||
// this write did not move it: what counts as written keeps the value the
|
||||
// server has accepted, and the baseline below with it.
|
||||
scheduleCfg.enabled = deployedEnabled
|
||||
}
|
||||
// What was sent is the deployed value now. Adopted here rather than by
|
||||
// remounting: the form stays editable during the write, and a remount would
|
||||
// re-read over an edit made then — which `settleDraftAfterWrite` keeps.
|
||||
initialConfig = structuredClone(scheduleCfg)
|
||||
baselineNonce++
|
||||
if (stillHere) {
|
||||
// What was sent is the deployed value now. Adopted here rather than by
|
||||
// remounting: the form stays editable during the write, and a remount would
|
||||
// re-read over an edit made then — which `settleDraftAfterWrite` keeps.
|
||||
initialConfig = structuredClone(scheduleCfg)
|
||||
baselineNonce++
|
||||
|
||||
// The schedule is deployed now, whether it was before or not. Set here rather
|
||||
// than left to the remount, which a kept edit skips: they decide whether the
|
||||
// next save updates or creates, and whether a discard removes the item.
|
||||
edit = true
|
||||
draftOnly = false
|
||||
// The schedule is deployed now, whether it was before or not. Set here rather
|
||||
// than left to the remount, which a kept edit skips: they decide whether the
|
||||
// next save updates or creates, and whether a discard removes the item.
|
||||
edit = true
|
||||
draftOnly = false
|
||||
}
|
||||
// Awaited before the host hears: it remounts on the report, and a remount
|
||||
// that overtook this would load the draft this is removing.
|
||||
await settleDraftAfterWrite(
|
||||
'trigger_schedule',
|
||||
scheduleCfg,
|
||||
getScheduleCfg(),
|
||||
stillHere ? getScheduleCfg() : undefined,
|
||||
previousPath,
|
||||
scheduleCfg.path,
|
||||
{ workspace: previousWs ?? undefined }
|
||||
@@ -742,9 +751,9 @@
|
||||
scheduleCfg.path,
|
||||
previousPath,
|
||||
previousWs,
|
||||
!draftValuesEqual(getScheduleCfg(), scheduleCfg)
|
||||
stillHere && !draftValuesEqual(getScheduleCfg(), scheduleCfg)
|
||||
)
|
||||
drawer?.closeDrawer()
|
||||
if (stillHere) drawer?.closeDrawer()
|
||||
}
|
||||
} finally {
|
||||
deploymentLoading = false
|
||||
|
||||
Reference in New Issue
Block a user