mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-25 00:01:55 +00:00
feat(frontend): wire script editor to UserDraft
The script editor's top-level state now lives in UserDraft.use(), keyed on the route's path (page.params.path on /scripts/edit, '' on /scripts/add). Deep edits inside ScriptBuilder persist automatically; deploy and draft restore now call UserDraft.remove to clear the local autosave alongside the backend draft. Replaces the URL-hash autosave that ScriptBuilder used to write via replaceStateFn — that prop is now gone, the encodeScriptState debounce is gone, and Triggers no longer takes a saveSessionDraft callback. Viewing a specific historical hash (?hash=...) is kept draft-free by passing '' as the path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
const bubble = createBubbler()
|
||||
import {
|
||||
DraftService,
|
||||
type NewScript,
|
||||
ScriptService,
|
||||
type NewScriptWithDraft,
|
||||
type Script,
|
||||
@@ -35,7 +34,6 @@
|
||||
cleanValueProperties,
|
||||
emptySchema,
|
||||
emptyString,
|
||||
encodeState,
|
||||
generateRandomString,
|
||||
orderedJsonStringify,
|
||||
readFieldsRecursively,
|
||||
@@ -141,7 +139,6 @@
|
||||
savedScript = $bindable(undefined),
|
||||
searchParams = new URLSearchParams(),
|
||||
disableHistoryChange = false,
|
||||
replaceStateFn = (url) => window.history.replaceState(null, '', url),
|
||||
customUi = {},
|
||||
savedPrimarySchedule = undefined,
|
||||
functionExports = undefined,
|
||||
@@ -288,15 +285,11 @@
|
||||
|
||||
// Add triggers context store
|
||||
const triggersState = $state(
|
||||
new Triggers(
|
||||
[
|
||||
{ type: 'webhook', path: '', isDraft: false },
|
||||
{ type: 'default_email', path: '', isDraft: false },
|
||||
...(script.draft_triggers ?? [])
|
||||
],
|
||||
undefined,
|
||||
saveSessionDraft
|
||||
)
|
||||
new Triggers([
|
||||
{ type: 'webhook', path: '', isDraft: false },
|
||||
{ type: 'default_email', path: '', isDraft: false },
|
||||
...(script.draft_triggers ?? [])
|
||||
])
|
||||
)
|
||||
|
||||
const captureOn = writable<boolean | undefined>(undefined)
|
||||
@@ -360,28 +353,6 @@
|
||||
let loadingSave = $state(false)
|
||||
let loadingDraft = $state(false)
|
||||
|
||||
let timeout2: number | undefined = undefined
|
||||
function encodeScriptState(script: NewScript) {
|
||||
untrack(() => timeout2 && clearTimeout(timeout2))
|
||||
timeout2 = setTimeout(() => {
|
||||
replaceStateFn(
|
||||
'#' +
|
||||
encodeState({
|
||||
...script,
|
||||
draft_triggers: structuredClone(triggersState.getDraftTriggersSnapshot())
|
||||
})
|
||||
)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
let timeout: number | undefined = undefined
|
||||
function saveSessionDraft() {
|
||||
timeout && clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
encodeScriptState(script)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
if (script.content == '') {
|
||||
if (template === 'wac_python') {
|
||||
script.modules = {
|
||||
@@ -1059,7 +1030,6 @@
|
||||
})
|
||||
$effect(() => {
|
||||
readFieldsRecursively(script)
|
||||
!disableHistoryChange && encodeScriptState(script)
|
||||
})
|
||||
|
||||
loadWorkerTags()
|
||||
|
||||
@@ -31,7 +31,6 @@ export interface ScriptBuilderProps {
|
||||
savedScript?: NewScriptWithDraftAndDraftTriggers | undefined
|
||||
searchParams?: URLSearchParams
|
||||
disableHistoryChange?: boolean
|
||||
replaceStateFn?: (url: string) => void
|
||||
customUi?: ScriptBuilderWhitelabelCustomUi
|
||||
savedPrimarySchedule?: ScheduleTrigger | undefined
|
||||
functionExports?: ((exports: ScriptBuilderFunctionExports) => void) | undefined
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import type { Schema } from '$lib/common'
|
||||
import { decodeState, emptySchema, emptyString, sendUserToast } from '$lib/utils'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { replaceState } from '$app/navigation'
|
||||
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
import { replaceScriptPlaceholderWithItsValues } from '$lib/hub'
|
||||
import type { Trigger } from '$lib/components/triggers/utils'
|
||||
@@ -16,6 +15,7 @@
|
||||
import ScriptEditorSkeleton from '$lib/components/ScriptEditorSkeleton.svelte'
|
||||
import { importScriptStore } from '$lib/components/scripts/scriptStore.svelte'
|
||||
import { isWorkflowAsCode } from '$lib/components/graph/wacToFlow'
|
||||
import { UserDraft } from '$lib/userDraft.svelte'
|
||||
|
||||
type Script = NewScript & {
|
||||
draft_triggers?: Trigger[]
|
||||
@@ -39,20 +39,8 @@
|
||||
|
||||
const path = page.url.searchParams.get('path')
|
||||
|
||||
const initialState = page.url.hash != '' ? page.url.hash.slice(1) : undefined
|
||||
|
||||
let scriptBuilder: ScriptBuilder | undefined = $state(undefined)
|
||||
|
||||
function decodeStateAndHandleError(state) {
|
||||
try {
|
||||
const decoded = decodeState(state)
|
||||
return decoded
|
||||
} catch (e) {
|
||||
console.error('Error decoding state', e)
|
||||
return defaultScript()
|
||||
}
|
||||
}
|
||||
|
||||
function defaultScript(): Script {
|
||||
return {
|
||||
hash: '',
|
||||
@@ -63,20 +51,22 @@
|
||||
schema: schema,
|
||||
is_template: false,
|
||||
extra_perms: {},
|
||||
language: (wacParam === 'python' ? 'python3' : wacParam === 'typescript' ? 'bun' : null) ?? collabLang ?? ($defaultScripts?.order?.filter(
|
||||
(x) => $defaultScripts?.hidden == undefined || !$defaultScripts.hidden.includes(x)
|
||||
)?.[0] ?? 'bun') as ScriptLang,
|
||||
language:
|
||||
(wacParam === 'python' ? 'python3' : wacParam === 'typescript' ? 'bun' : null) ??
|
||||
collabLang ??
|
||||
(($defaultScripts?.order?.filter(
|
||||
(x) => $defaultScripts?.hidden == undefined || !$defaultScripts.hidden.includes(x)
|
||||
)?.[0] ?? 'bun') as ScriptLang),
|
||||
kind: 'script'
|
||||
}
|
||||
}
|
||||
|
||||
let script: Script | undefined = $state(
|
||||
templatePath || hubPath
|
||||
? undefined
|
||||
: !path && initialState != undefined
|
||||
? decodeStateAndHandleError(initialState)
|
||||
: defaultScript()
|
||||
)
|
||||
// New script: keyed on '' (in-memory only — empty paths bypass localStorage).
|
||||
// templatePath/hubPath/import flows replace the value before render, so
|
||||
// defaultValue is left undefined for those to avoid flashing a blank editor.
|
||||
const scriptHandle = UserDraft.use<Script>('script', '', {
|
||||
defaultValue: templatePath || hubPath ? undefined : defaultScript()
|
||||
})
|
||||
|
||||
async function loadTemplate(): Promise<void> {
|
||||
if (templatePath) {
|
||||
@@ -85,7 +75,7 @@
|
||||
workspace: $workspaceStore!,
|
||||
path: templatePath
|
||||
})
|
||||
script = {
|
||||
scriptHandle.draft = {
|
||||
...defaultScript(),
|
||||
summary: !emptyString(template.summary) ? `Copy of ${template.summary}` : '',
|
||||
description: template.description,
|
||||
@@ -95,7 +85,7 @@
|
||||
path: template.path + '_fork'
|
||||
}
|
||||
} catch (err) {
|
||||
script = defaultScript()
|
||||
scriptHandle.draft = defaultScript()
|
||||
console.error('Error loading template', err)
|
||||
sendUserToast('Error loading template: ' + err.message, true)
|
||||
}
|
||||
@@ -108,7 +98,7 @@
|
||||
const { content, language, summary } = await ScriptService.getHubScriptByPath({
|
||||
path: hubPath
|
||||
})
|
||||
script = {
|
||||
scriptHandle.draft = {
|
||||
...defaultScript(),
|
||||
description: `Fork of ${hubPath}`,
|
||||
content: replaceScriptPlaceholderWithItsValues(hubPath, content),
|
||||
@@ -117,7 +107,7 @@
|
||||
path: hubPath + '_fork'
|
||||
}
|
||||
} catch (err) {
|
||||
script = defaultScript()
|
||||
scriptHandle.draft = defaultScript()
|
||||
console.error('Error loading script from hub', err)
|
||||
sendUserToast('Error loading script from hub: ' + err.message, true)
|
||||
}
|
||||
@@ -131,7 +121,7 @@
|
||||
const imported = $importScriptStore
|
||||
$importScriptStore = undefined
|
||||
const isWac = isWorkflowAsCode(imported.content ?? '', imported.language ?? '')
|
||||
script = {
|
||||
scriptHandle.draft = {
|
||||
...defaultScript(),
|
||||
...imported,
|
||||
path: path ?? '',
|
||||
@@ -139,8 +129,7 @@
|
||||
extra_perms: {}
|
||||
}
|
||||
if (isWac) {
|
||||
importedWacTemplate =
|
||||
imported.language === 'python3' ? 'wac_python' : 'wac_typescript'
|
||||
importedWacTemplate = imported.language === 'python3' ? 'wac_python' : 'wac_typescript'
|
||||
sendUserToast('WAC script loaded from YAML/JSON')
|
||||
} else {
|
||||
sendUserToast('Script loaded from YAML/JSON')
|
||||
@@ -154,12 +143,17 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if script}
|
||||
{#if scriptHandle.draft}
|
||||
<ScriptBuilder
|
||||
{initialArgs}
|
||||
bind:this={scriptBuilder}
|
||||
lockedLanguage={templatePath != null || hubPath != null}
|
||||
template={importedWacTemplate ?? (wacParam === 'python' ? 'wac_python' : wacParam === 'typescript' ? 'wac_typescript' : 'script')}
|
||||
template={importedWacTemplate ??
|
||||
(wacParam === 'python'
|
||||
? 'wac_python'
|
||||
: wacParam === 'typescript'
|
||||
? 'wac_typescript'
|
||||
: 'script')}
|
||||
onDeploy={(e) => {
|
||||
goto(`/scripts/get/${e.hash}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
@@ -167,9 +161,8 @@
|
||||
goto(`/scripts/edit/${e.path}`)
|
||||
}}
|
||||
searchParams={page.url.searchParams}
|
||||
bind:script
|
||||
bind:script={scriptHandle.draft}
|
||||
{showMeta}
|
||||
replaceStateFn={(path) => replaceState(path, page.state)}
|
||||
>
|
||||
<UnsavedConfirmationModal
|
||||
getInitialAndModifiedValues={scriptBuilder?.getInitialAndModifiedValues}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
|
||||
import { initialArgsStore, workspaceStore } from '$lib/stores'
|
||||
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
|
||||
import { decodeState, cleanValueProperties, orderedJsonStringify } from '$lib/utils'
|
||||
import { cleanValueProperties, orderedJsonStringify } from '$lib/utils'
|
||||
import { goto } from '$lib/navigation'
|
||||
import { replaceState } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
import UnsavedConfirmationModal from '$lib/components/common/confirmationModal/UnsavedConfirmationModal.svelte'
|
||||
@@ -14,8 +13,10 @@
|
||||
import { get } from 'svelte/store'
|
||||
import { untrack } from 'svelte'
|
||||
import { page } from '$app/state'
|
||||
import { UserDraft } from '$lib/userDraft.svelte'
|
||||
|
||||
type EditableScript = NewScript & { draft_triggers?: Trigger[] }
|
||||
|
||||
let initialState = window.location.hash != '' ? window.location.hash.slice(1) : undefined
|
||||
let initialArgs = get(initialArgsStore) ?? {}
|
||||
if (get(initialArgsStore)) $initialArgsStore = undefined
|
||||
|
||||
@@ -23,16 +24,15 @@
|
||||
|
||||
let hash = page.url.searchParams.get('hash') ?? undefined
|
||||
|
||||
let scriptLoadedFromUrl = initialState != undefined ? decodeState(initialState) : undefined
|
||||
|
||||
let script: (NewScript & { draft_triggers?: Trigger[] }) | undefined = $state(undefined)
|
||||
// When viewing a specific historical hash we don't want to load or write a
|
||||
// local draft — that view is read-only relative to drafts.
|
||||
const draftPath = hash ? '' : (page.params.path ?? '')
|
||||
const scriptHandle = UserDraft.use<EditableScript>('script', draftPath)
|
||||
|
||||
let initialPath: string = $state('')
|
||||
|
||||
let scriptBuilder: ScriptBuilder | undefined = $state(undefined)
|
||||
|
||||
let reloadAction: () => Promise<void> = async () => {}
|
||||
|
||||
let savedScript: NewScriptWithDraft | undefined = $state(undefined)
|
||||
let fullyLoaded = $state(false)
|
||||
|
||||
@@ -40,28 +40,87 @@
|
||||
|
||||
async function loadScript(): Promise<void> {
|
||||
fullyLoaded = false
|
||||
if (scriptLoadedFromUrl != undefined && scriptLoadedFromUrl.path == page.params.path) {
|
||||
script = scriptLoadedFromUrl
|
||||
reloadAction = async () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
}
|
||||
if (hash) {
|
||||
const scriptByHash = await ScriptService.getScriptByHash({
|
||||
workspace: $workspaceStore!,
|
||||
hash
|
||||
})
|
||||
savedScript = structuredClone($state.snapshot(scriptByHash)) as NewScriptWithDraft
|
||||
scriptHandle.draft = { ...scriptByHash, parent_hash: hash, lock: undefined }
|
||||
} else {
|
||||
const scriptWithDraft = await ScriptService.getScriptByPathWithDraft({
|
||||
workspace: $workspaceStore!,
|
||||
path: page.params.path ?? ''
|
||||
})
|
||||
savedScript = structuredClone($state.snapshot(scriptWithDraft))
|
||||
|
||||
async function compareAutosave() {
|
||||
savedScript = await ScriptService.getScriptByPathWithDraft({
|
||||
workspace: $workspaceStore!,
|
||||
path: script!.path
|
||||
})
|
||||
const localDraft = scriptHandle.draft
|
||||
const backendDraft = scriptWithDraft.draft
|
||||
? ({ ...scriptWithDraft.draft } as EditableScript)
|
||||
: undefined
|
||||
|
||||
const draftOrDeployed = cleanValueProperties(savedScript?.draft || savedScript)
|
||||
const urlScript = cleanValueProperties(scriptLoadedFromUrl)
|
||||
if (orderedJsonStringify(draftOrDeployed) === orderedJsonStringify(urlScript)) {
|
||||
reloadAction()
|
||||
if (localDraft != undefined) {
|
||||
// Local autosave wins; offer a diff against the latest saved
|
||||
// version (backend draft if any, otherwise deployed) so the
|
||||
// user can discard it.
|
||||
const reference = backendDraft ?? scriptWithDraft
|
||||
const referenceClean = cleanValueProperties(reference)
|
||||
const localClean = cleanValueProperties(localDraft)
|
||||
if (orderedJsonStringify(referenceClean) === orderedJsonStringify(localClean)) {
|
||||
// Local matches the saved version — silently drop it and use the saved one.
|
||||
scriptHandle.draft = backendDraft ?? (scriptWithDraft as EditableScript)
|
||||
} else {
|
||||
sendUserToast('Script loaded from latest autosave stored in the URL', false, [
|
||||
sendUserToast('Script loaded from local autosave', false, [
|
||||
{
|
||||
label: 'Discard browser stored autosave and reload',
|
||||
label: 'Discard local autosave',
|
||||
callback: () => {
|
||||
scriptHandle.draft = backendDraft ?? (scriptWithDraft as EditableScript)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Show diff',
|
||||
callback: async () => {
|
||||
diffDrawer?.openDrawer()
|
||||
diffDrawer?.setDiff({
|
||||
mode: 'simple',
|
||||
original: referenceClean,
|
||||
current: localClean,
|
||||
title: `${backendDraft ? 'Latest saved draft' : 'Deployed'} <> Autosave`,
|
||||
button: {
|
||||
text: 'Discard autosave',
|
||||
onClick: () => {
|
||||
scriptHandle.draft = backendDraft ?? (scriptWithDraft as EditableScript)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
} else if (backendDraft) {
|
||||
scriptHandle.draft = backendDraft
|
||||
if (scriptHandle.draft?.['primary_schedule']) {
|
||||
savedPrimarySchedule = scriptHandle.draft['primary_schedule']
|
||||
scriptBuilder?.setPrimarySchedule(savedPrimarySchedule)
|
||||
}
|
||||
scriptBuilder?.setDraftTriggers(scriptHandle.draft.draft_triggers)
|
||||
|
||||
if (!scriptWithDraft.draft_only) {
|
||||
const reloadAction = async () => {
|
||||
await DraftService.deleteDraft({
|
||||
workspace: $workspaceStore!,
|
||||
kind: 'script',
|
||||
path: scriptHandle.draft!.path
|
||||
})
|
||||
UserDraft.remove('script', draftPath)
|
||||
goto(`/scripts/edit/${scriptHandle.draft!.path}`)
|
||||
loadScript()
|
||||
}
|
||||
const deployed = cleanValueProperties(scriptWithDraft)
|
||||
const draft = cleanValueProperties(scriptHandle.draft)
|
||||
sendUserToast('Script loaded from latest saved draft', false, [
|
||||
{
|
||||
label: 'Discard draft reset to deployed version',
|
||||
callback: reloadAction
|
||||
},
|
||||
{
|
||||
@@ -70,94 +129,29 @@
|
||||
diffDrawer?.openDrawer()
|
||||
diffDrawer?.setDiff({
|
||||
mode: 'simple',
|
||||
original: draftOrDeployed,
|
||||
current: urlScript,
|
||||
title: `${savedScript?.draft ? 'Latest saved draft' : 'Deployed'} <> Autosave`,
|
||||
button: { text: 'Discard autosave', onClick: reloadAction }
|
||||
original: deployed,
|
||||
current: draft,
|
||||
title: 'Deployed <> Draft',
|
||||
button: { text: 'Discard draft', onClick: reloadAction }
|
||||
})
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
compareAutosave()
|
||||
} else {
|
||||
if (hash) {
|
||||
const scriptByHash = await ScriptService.getScriptByHash({
|
||||
workspace: $workspaceStore!,
|
||||
hash
|
||||
})
|
||||
savedScript = structuredClone($state.snapshot(scriptByHash)) as NewScriptWithDraft
|
||||
script = { ...scriptByHash, parent_hash: hash, lock: undefined }
|
||||
} else {
|
||||
const scriptWithDraft = await ScriptService.getScriptByPathWithDraft({
|
||||
workspace: $workspaceStore!,
|
||||
path: page.params.path ?? ''
|
||||
})
|
||||
savedScript = structuredClone($state.snapshot(scriptWithDraft))
|
||||
if (scriptWithDraft.draft != undefined) {
|
||||
script = scriptWithDraft.draft
|
||||
scriptBuilder?.setDraftTriggers(script.draft_triggers)
|
||||
if (script['primary_schedule']) {
|
||||
savedPrimarySchedule = script['primary_schedule']
|
||||
scriptBuilder?.setPrimarySchedule(savedPrimarySchedule)
|
||||
}
|
||||
|
||||
if (!scriptWithDraft.draft_only) {
|
||||
reloadAction = async () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
await DraftService.deleteDraft({
|
||||
workspace: $workspaceStore!,
|
||||
kind: 'script',
|
||||
path: script!.path
|
||||
})
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
}
|
||||
const deployed = cleanValueProperties(scriptWithDraft)
|
||||
const draft = cleanValueProperties(script)
|
||||
sendUserToast('Script loaded from latest saved draft', false, [
|
||||
{
|
||||
label: 'Discard draft reset to deployed version',
|
||||
callback: reloadAction
|
||||
},
|
||||
{
|
||||
label: 'Show diff',
|
||||
callback: async () => {
|
||||
diffDrawer?.openDrawer()
|
||||
diffDrawer?.setDiff({
|
||||
mode: 'simple',
|
||||
original: deployed,
|
||||
current: draft,
|
||||
title: 'Deployed <> Draft',
|
||||
button: { text: 'Discard draft', onClick: reloadAction }
|
||||
})
|
||||
}
|
||||
}
|
||||
])
|
||||
}
|
||||
} else {
|
||||
script = scriptWithDraft
|
||||
}
|
||||
script.parent_hash = scriptWithDraft.hash
|
||||
scriptHandle.draft = scriptWithDraft as EditableScript
|
||||
}
|
||||
if (scriptHandle.draft) {
|
||||
scriptHandle.draft.parent_hash = scriptWithDraft.hash
|
||||
}
|
||||
}
|
||||
// hash
|
||||
// ? await ScriptService.getScriptByHash({
|
||||
// workspace: $workspaceStore!,
|
||||
// hash: page.params.hash
|
||||
// })
|
||||
// : await ScriptService.getScriptByPathWithDraft({
|
||||
// workspace: $workspaceStore!,
|
||||
// path: $page.params.path
|
||||
// })
|
||||
|
||||
if (script) {
|
||||
initialPath = script.path
|
||||
scriptBuilder?.setDraftTriggers(script.draft_triggers)
|
||||
scriptBuilder?.setCode(script.content)
|
||||
if (scriptHandle.draft) {
|
||||
initialPath = scriptHandle.draft.path
|
||||
scriptBuilder?.setDraftTriggers(scriptHandle.draft.draft_triggers)
|
||||
scriptBuilder?.setCode(scriptHandle.draft.content)
|
||||
if (topHash) {
|
||||
script.parent_hash = topHash
|
||||
scriptHandle.draft.parent_hash = topHash
|
||||
}
|
||||
}
|
||||
fullyLoaded = true
|
||||
@@ -177,8 +171,8 @@
|
||||
return
|
||||
}
|
||||
diffDrawer?.closeDrawer()
|
||||
UserDraft.remove('script', draftPath)
|
||||
goto(`/scripts/edit/${savedScript.draft.path}`)
|
||||
scriptLoadedFromUrl = undefined
|
||||
loadScript()
|
||||
}
|
||||
|
||||
@@ -195,18 +189,18 @@
|
||||
path: savedScript.path
|
||||
})
|
||||
}
|
||||
UserDraft.remove('script', draftPath)
|
||||
goto(`/scripts/edit/${savedScript.path}`)
|
||||
scriptLoadedFromUrl = undefined
|
||||
loadScript()
|
||||
}
|
||||
</script>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} {restoreDraft} {restoreDeployed} />
|
||||
{#if script}
|
||||
{#if scriptHandle.draft}
|
||||
<ScriptBuilder
|
||||
bind:this={scriptBuilder}
|
||||
{initialPath}
|
||||
bind:script
|
||||
bind:script={scriptHandle.draft}
|
||||
{fullyLoaded}
|
||||
bind:savedScript
|
||||
{initialArgs}
|
||||
@@ -214,6 +208,7 @@
|
||||
{savedPrimarySchedule}
|
||||
searchParams={page.url.searchParams}
|
||||
onDeploy={(e) => {
|
||||
UserDraft.remove('script', draftPath)
|
||||
goto(`/scripts/get/${e.hash}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
onSaveInitial={(e) => {
|
||||
@@ -222,9 +217,6 @@
|
||||
onSeeDetails={(e) => {
|
||||
goto(`/scripts/get/${e.path}?workspace=${$workspaceStore}`)
|
||||
}}
|
||||
replaceStateFn={(path) => {
|
||||
replaceState(path, page.state)
|
||||
}}
|
||||
>
|
||||
<UnsavedConfirmationModal
|
||||
{diffDrawer}
|
||||
|
||||
Reference in New Issue
Block a user