mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-21 08:03:33 +00:00
fix(drafts): make the home-page View/Edit JSON action work on draft-only apps
The "View/Edit JSON" entry on the home page called `AppService.getAppByPath`
without `get_draft=true`, so for draft-only items at `u/{user}/draft_{uuid}`
the backend 404'd with "App not found at path …". Pass `get_draft=true`
and render the synthesized stand-in's editable shape:
- App drafts come back as `{summary, value, path, policy, ...}` — `value`
is the App definition the editor was working on; show that.
- Raw-app drafts come back as the flattened
`{files, runnables, data, summary, policy, ...}` with no nested `value`;
show the whole shape.
On save, draft-only items can't go through `updateApp` (no deployed row).
Route the edit through `UserDraftDbSyncer.save` (with `immediate: true`
so `await` resolves after the POST lands) and relabel the button
"Save draft" + Save icon. Deployed items keep the existing "Deploy"
flow unchanged.
This commit is contained in:
@@ -6,16 +6,19 @@
|
||||
import JsonEditor from '../../JsonEditor.svelte'
|
||||
import { AppService } from '$lib/gen'
|
||||
import { UserDraft } from '$lib/userDraft.svelte'
|
||||
import { UserDraftDbSyncer } from '$lib/userDraftDbSyncer.svelte'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { Globe, Loader2 } from 'lucide-svelte'
|
||||
import { Globe, Loader2, Save } from 'lucide-svelte'
|
||||
|
||||
let jsonViewerDrawer: Drawer | undefined = $state()
|
||||
|
||||
let code: string = $state('')
|
||||
let path: string = ''
|
||||
let loading = $state(true)
|
||||
let isDraftOnly = $state(false)
|
||||
let isRawApp = $state(false)
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let app: any | undefined = undefined
|
||||
@@ -24,24 +27,55 @@
|
||||
loading = true
|
||||
jsonViewerDrawer?.toggleDrawer()
|
||||
path = path_l
|
||||
const fapp = await AppService.getAppByPath({
|
||||
// `get_draft=true` so draft-only items at `u/{user}/draft_{uuid}`
|
||||
// resolve to the synthesized draft stand-in instead of 404'ing the
|
||||
// home-page "View/Edit JSON" menu entry. Deployed apps continue to
|
||||
// return the deployed payload unchanged (see WithDraftOverlay).
|
||||
const fapp = (await AppService.getAppByPath({
|
||||
workspace: $workspaceStore!,
|
||||
path
|
||||
})
|
||||
path,
|
||||
getDraft: true
|
||||
})) as any
|
||||
app = { ...fapp }
|
||||
code = JSON.stringify(fapp.value, null, 4)
|
||||
isDraftOnly = !!fapp.no_deployed
|
||||
isRawApp = !!fapp.raw_app
|
||||
// For deployed (or app drafts overlaid on a deployed row) the
|
||||
// editable shape is the App definition under `.value`. For raw-app
|
||||
// drafts there is no nested `.value` — the editable shape is the
|
||||
// whole flattened draft (`{files, runnables, data, ...}`).
|
||||
const display = isDraftOnly && isRawApp ? fapp : fapp.value
|
||||
code = JSON.stringify(display, null, 4)
|
||||
loading = false
|
||||
}
|
||||
|
||||
export async function saveApp() {
|
||||
await AppService.updateApp({
|
||||
workspace: $workspaceStore!,
|
||||
path,
|
||||
requestBody: { ...app, value: JSON.parse(code) }
|
||||
})
|
||||
dispatch('change')
|
||||
UserDraft.remove('app', path)
|
||||
sendUserToast('App deployed')
|
||||
const parsed = JSON.parse(code)
|
||||
if (isDraftOnly) {
|
||||
// Draft-only items have no deployed row — `updateApp` would
|
||||
// 404. Route the edit through the syncer (`immediate: true`
|
||||
// so the caller's `await` resolves only after the POST lands)
|
||||
// so the user keeps editing under the draft path until they
|
||||
// rename + deploy from the regular editor.
|
||||
const value = isRawApp ? { ...app, ...parsed } : { ...app, value: parsed }
|
||||
await UserDraftDbSyncer.save({
|
||||
workspace: $workspaceStore!,
|
||||
itemKind: isRawApp ? 'raw_app' : 'app',
|
||||
path,
|
||||
value,
|
||||
immediate: true
|
||||
})
|
||||
dispatch('change')
|
||||
sendUserToast('Draft saved')
|
||||
} else {
|
||||
await AppService.updateApp({
|
||||
workspace: $workspaceStore!,
|
||||
path,
|
||||
requestBody: { ...app, value: parsed }
|
||||
})
|
||||
dispatch('change')
|
||||
UserDraft.remove('app', path)
|
||||
sendUserToast('App deployed')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -55,8 +89,13 @@
|
||||
|
||||
{#snippet actions()}
|
||||
{#if !$userStore?.operator}
|
||||
<Button on:click={saveApp} startIcon={{ icon: Globe }} variant="accent" size="xs">
|
||||
Deploy
|
||||
<Button
|
||||
on:click={saveApp}
|
||||
startIcon={{ icon: isDraftOnly ? Save : Globe }}
|
||||
variant="accent"
|
||||
size="xs"
|
||||
>
|
||||
{isDraftOnly ? 'Save draft' : 'Deploy'}
|
||||
</Button>
|
||||
{/if}
|
||||
{/snippet}
|
||||
|
||||
Reference in New Issue
Block a user