mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-13 08:02:47 +00:00
fix(schedules): take the deployed enabled state from the deployed config alone
`loadScheduleCfg` applies the draft overlay as well as the deployed config, so recording the accepted `enabled` there let a draft's own value pass for one the server had taken: saving then settled the form back to it, and a schedule the user had switched on came out off, clean, with nothing said. It is read where the deployed config is the one on the form, and reset for a schedule that has none yet. 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
45c53a37da
commit
2583569150
@@ -32,8 +32,7 @@
|
||||
disableChatOffset?: boolean
|
||||
/** A version was restored, at this path and in the workspace the history was
|
||||
* pointed at — which `WsSpecificVersions` can make a linked one rather than the
|
||||
* acting workspace. Both reported rather than left for the caller to read off
|
||||
* its own live state, which the restore's await has already outlived. */
|
||||
* acting workspace. */
|
||||
onRestored?: (workspace: string, path: string) => void
|
||||
/** Fires after Save has written, with the path it wrote to — which is not the
|
||||
* one it was opened on when the user renamed it — and the workspace and path
|
||||
|
||||
@@ -198,8 +198,11 @@
|
||||
draftOnly = noDeployed
|
||||
if (!defaultCfg) {
|
||||
// Form holds DEPLOYED here; capture it as `initialConfig` so the
|
||||
// dirty check / banner fires whenever a saved draft exists.
|
||||
// dirty check / banner fires whenever a saved draft exists. This is also
|
||||
// the only point where the deployed `enabled` is on the form — the draft
|
||||
// overlay below can carry one of its own, which the server has not taken.
|
||||
initialConfig = structuredClone($state.snapshot(getScheduleCfg()))
|
||||
deployedEnabled = enabled
|
||||
}
|
||||
if (draftOverlay) await loadScheduleCfg(draftOverlay)
|
||||
await draftSync.maybeRestore()
|
||||
@@ -353,6 +356,8 @@
|
||||
runnable = undefined
|
||||
edit = false
|
||||
draftOnly = false
|
||||
// Nothing deployed yet, so nothing accepted.
|
||||
deployedEnabled = false
|
||||
// No deployed baseline for a brand-new schedule. The editor instance
|
||||
// is reused across open() calls, so clear any baseline left by a prior
|
||||
// openEdit — otherwise the "unsaved changes" banner / dirty check would
|
||||
@@ -549,7 +554,6 @@
|
||||
initialCronVersion = cronVersion
|
||||
isLatestCron = cronVersion == 'v2'
|
||||
enabled = cfg.enabled
|
||||
deployedEnabled = cfg.enabled
|
||||
schedule = cfg.schedule
|
||||
initialSchedule = schedule
|
||||
timezone = cfg.timezone
|
||||
|
||||
@@ -572,8 +572,12 @@
|
||||
const tabHosts: Record<string, PreviewTabHost | undefined> = {}
|
||||
|
||||
let reloadHandle: ReturnType<typeof setTimeout> | undefined
|
||||
// Base-stripped list-page paths (e.g. `/schedules`) a chat round touched since
|
||||
// the last flush — see toolReloadEffect for how tools map to pages.
|
||||
/** A list page in the workspace it was touched in — see `queuePageReload`. */
|
||||
function pageReloadKey(workspace: string, page: string): string {
|
||||
return `${workspace}\u0000${page}`
|
||||
}
|
||||
// Pages touched since the last flush, by whatever touched them: a chat round
|
||||
// (see toolReloadEffect), a hosted editor's write, a draft landing after one.
|
||||
let pendingPages = new Set<string>()
|
||||
// The same round's mutations, kept whole rather than folded into one verdict:
|
||||
// a hosted entity editor is only affected by a mutation to its own item, in
|
||||
@@ -590,7 +594,7 @@
|
||||
const workspace = getEffectiveWorkspaceId(s)
|
||||
// The queue names the workspace each page was touched in; this session only
|
||||
// cares about the ones touched in its own.
|
||||
const prefix = `${workspace}\u0000`
|
||||
const prefix = pageReloadKey(workspace ?? '', '')
|
||||
const mine = new Set(
|
||||
[...pages].filter((p) => p.startsWith(prefix)).map((p) => p.slice(prefix.length))
|
||||
)
|
||||
@@ -668,7 +672,7 @@
|
||||
// frame its scroll and everything else it holds.
|
||||
function queuePageReload(workspace: string | undefined, page: string) {
|
||||
if (!workspace) return
|
||||
pendingPages.add(`${workspace}\u0000${page}`)
|
||||
pendingPages.add(pageReloadKey(workspace, page))
|
||||
clearTimeout(reloadHandle)
|
||||
reloadHandle = setTimeout(flushReload, 500)
|
||||
}
|
||||
@@ -695,7 +699,7 @@
|
||||
setToolCompletionListener((name, args, workspace) => {
|
||||
const { pages, entity, path } = toolReloadEffect(name, args)
|
||||
if (pages.length === 0) return
|
||||
for (const p of pages) pendingPages.add(`${workspace}\u0000${p}`)
|
||||
for (const p of pages) pendingPages.add(pageReloadKey(workspace, p))
|
||||
// A write reaches a hosted editor through the draft cell it holds, but an
|
||||
// editor still loading holds none yet and the seed no-opped past it. The
|
||||
// miss is recorded when it happens — asking now would be too late, since
|
||||
|
||||
Reference in New Issue
Block a user