mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 16:00:38 +00:00
stop the app editor crashing on a grid-less draft (#10203)
* fix(apps): default a missing grid so the app preview does not crash * fix(apps): migrate the adopted draft so the editor matches the viewer * docs: tighten grid-normalization comments to durable constraints * test: drop the migrateApp grid-default test
This commit is contained in:
@@ -127,7 +127,15 @@
|
||||
if (appDraftHandle) UserDraft.stopSync('app', appDraftPath)
|
||||
// Prefer a prior-session autosave over the prop (the route seeds an empty
|
||||
// template on `new_draft=true`; it calls `UserDraft.remove` to force a reset).
|
||||
const stateApp = $state(untrack(() => appDraftHandle?.draft ?? app))
|
||||
// A draft is a stored value that can predate any schema migration, so whichever
|
||||
// value is adopted needs the same normalization as the prop above.
|
||||
const stateApp = $state(
|
||||
untrack(() => {
|
||||
const adopted = appDraftHandle?.draft ?? app
|
||||
migrateApp(adopted)
|
||||
return adopted
|
||||
})
|
||||
)
|
||||
const appStore = writable<App>(stateApp)
|
||||
// Mirror `stateApp` mutations into the autosave cell. The first mirror is the
|
||||
// seed — `acquireEntry`'s `skipNextWrite` swallows it; later writes POST.
|
||||
|
||||
@@ -4,10 +4,11 @@ import { allItems } from './editor/appUtilsCore'
|
||||
|
||||
/**
|
||||
* Normalize an `App` in place to the current schema: default `hiddenInlineScripts`
|
||||
* type, migrate the legacy `doNotRecomputeOnInputChanged` flag, and default
|
||||
* `fullHeight` on every grid item. Lives in its own light module (no app-editor
|
||||
* component imports) so non-editor callers — e.g. the localStorage→DB draft
|
||||
* migration — can reuse it without pulling the whole `apps/utils` graph.
|
||||
* type, migrate the legacy `doNotRecomputeOnInputChanged` flag, default a missing
|
||||
* `grid`, and default `fullHeight` on every grid item. Lives in its own light
|
||||
* module (no app-editor component imports) so non-editor callers, e.g. the
|
||||
* localStorage→DB draft migration, can reuse it without pulling the whole
|
||||
* `apps/utils` graph.
|
||||
*/
|
||||
export function migrateApp(app: App) {
|
||||
;(app?.hiddenInlineScripts ?? []).forEach((x) => {
|
||||
@@ -22,6 +23,14 @@ export function migrateApp(app: App) {
|
||||
}
|
||||
})
|
||||
|
||||
// A stored app value can have no `grid` at all: a persisted draft row is the
|
||||
// confirmed case, and the editor renders a draft in place of the deployed
|
||||
// value. The grid components dereference it unguarded, so normalize it here,
|
||||
// the one hook every load path runs through.
|
||||
if (!Array.isArray(app.grid)) {
|
||||
app.grid = []
|
||||
}
|
||||
|
||||
allItems(app.grid, app.subgrids).forEach((x) => {
|
||||
gridColumns.forEach((column: number) => {
|
||||
if (x?.[column]?.fullHeight === undefined) {
|
||||
|
||||
Reference in New Issue
Block a user