{
inputsDrawerOpen = true
}
- }
+ },
+
+ ...(savedApp
+ ? [
+ {
+ displayName: 'Diff',
+ icon: DiffIcon,
+ action: () => {
+ if (!savedApp) {
+ return
+ }
+ diffDrawer?.openDrawer()
+ diffDrawer?.setDiff({
+ mode: 'normal',
+ deployed: savedApp,
+ draft: savedApp.draft,
+ current: {
+ summary: $summary,
+ value: $app,
+ path: newPath || savedApp.draft?.path || savedApp.path,
+ policy
+ }
+ })
+ }
+ }
+ ]
+ : [])
]
let appEditorTutorial: AppEditorTutorial | undefined = undefined
@@ -455,7 +595,16 @@
-
+
{#if appPath == ''}
@@ -465,6 +614,7 @@
Summary
+
closeSaveDrawer()}>
Summary
+
-
+
+
{
+ if (!savedApp) {
+ return
+ }
+ saveDrawerOpen = false
+ diffDrawer?.openDrawer()
+ diffDrawer?.setDiff({
+ mode: 'normal',
+ deployed: savedApp,
+ draft: savedApp.draft,
+ current: {
+ summary: $summary,
+ value: $app,
+ path: newPath || savedApp.draft?.path || savedApp.path,
+ policy
+ },
+ button: {
+ text: 'Looks good, deploy',
+ onClick: () => {
+ if (appPath == '') {
+ createApp(newPath)
+ } else {
+ updateApp(newPath)
+ }
+ }
+ }
+ })
+ }}
+ >
+
+
+ Diff
+
+
import type { AppEditorContext, AppViewerContext } from '../../types'
import { getContext, onMount, tick } from 'svelte'
- import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import {
components as componentsRecord,
presets as presetsRecord,
@@ -35,8 +34,6 @@
function addComponent(appComponentType: TypedComponent['type']): string {
push(history, $app)
- $dirtyStore = true
-
const id = insertNewGridItem(
$app,
appComponentFromType(appComponentType) as (id: string) => AppComponent,
@@ -56,8 +53,6 @@
push(history, $app)
- $dirtyStore = true
-
const id = copyComponent($app, res.value.item, $focusedGrid, res.value.subgrids, [])
if (id) {
@@ -71,8 +66,6 @@
push(history, $app)
- $dirtyStore = true
-
const id = insertNewGridItem(
$app,
appComponentFromType(preset.targetComponent, preset.configuration) as (
diff --git a/frontend/src/lib/components/common/badge/Badge.svelte b/frontend/src/lib/components/common/badge/Badge.svelte
index 9ed8434a93..f2f50ef54a 100644
--- a/frontend/src/lib/components/common/badge/Badge.svelte
+++ b/frontend/src/lib/components/common/badge/Badge.svelte
@@ -57,6 +57,7 @@
const handleHide = () => (hidden = !hidden)
+
import ConfirmationModal from './ConfirmationModal.svelte'
import { beforeNavigate, goto } from '$app/navigation'
- import { onDestroy } from 'svelte'
- import { dirtyStore } from './dirtyStore'
+ import Button from '../button/Button.svelte'
+ import type DiffDrawer from '$lib/components/DiffDrawer.svelte'
+ import { cleanValueProperties, orderedJsonStringify, type Value } from '$lib/utils'
+ import { tick } from 'svelte'
- let navigationState: { from: URL | undefined; to: URL | null; cancel: () => void } | undefined =
- undefined
- $: open = Boolean(navigationState)
+ export let savedValue: Value | undefined = undefined
+ export let modifiedValue: Value | undefined = undefined
+ export let diffDrawer: DiffDrawer | undefined = undefined
- beforeNavigate((newNavigationState) => {
+ let bypassBeforeNavigate = false
+ let open = false
+ let goingTo: URL | undefined = undefined
+
+ beforeNavigate(async (newNavigationState) => {
if (
- !navigationState &&
- $dirtyStore &&
+ !bypassBeforeNavigate &&
newNavigationState.to &&
newNavigationState.to.url.pathname !== newNavigationState.from?.url.pathname
) {
- navigationState = {
- to: newNavigationState.to.url,
- from: newNavigationState.from?.url,
- cancel: newNavigationState.cancel
- }
+ goingTo = newNavigationState.to.url
newNavigationState.cancel()
+ await tick() // make sure saved value is updated when clicking on save draft or deploy
+ if (savedValue && modifiedValue) {
+ const draftOrDeployed = cleanValueProperties(savedValue.draft || savedValue)
+ const current = cleanValueProperties(modifiedValue)
+ if (orderedJsonStringify(draftOrDeployed) === orderedJsonStringify(current)) {
+ bypassBeforeNavigate = true
+ goto(goingTo)
+ } else {
+ open = true
+ }
+ } else {
+ open = true
+ }
+ } else if (bypassBeforeNavigate) {
+ bypassBeforeNavigate = false
}
})
-
- onDestroy(() => {
- $dirtyStore = false
- })
{
- if (navigationState) {
- navigationState.cancel()
- }
- navigationState = undefined
+ open = false
}}
on:confirmed={() => {
- if (navigationState?.to) {
- goto(navigationState.to)
+ if (goingTo) {
+ bypassBeforeNavigate = true
+ goto(goingTo)
}
- $dirtyStore = false
- navigationState = undefined
}}
>
Are you sure you want to discard the changes you have made?
+ {#if savedValue && modifiedValue}
+ {
+ if (!savedValue || !modifiedValue) {
+ return
+ }
+ open = false
+ diffDrawer?.openDrawer()
+ diffDrawer?.setDiff({
+ mode: 'normal',
+ deployed: savedValue,
+ draft: savedValue.draft,
+ current: modifiedValue,
+ defaultDiffType: 'draft',
+ button: {
+ text: 'Leave anyway',
+ onClick: () => {
+ if (goingTo) {
+ bypassBeforeNavigate = true
+ goto(goingTo)
+ }
+ }
+ }
+ })
+ }}
+ >Show diff
+
+ {/if}
diff --git a/frontend/src/lib/components/common/confirmationModal/dirtyStore.ts b/frontend/src/lib/components/common/confirmationModal/dirtyStore.ts
deleted file mode 100644
index 0429a9df43..0000000000
--- a/frontend/src/lib/components/common/confirmationModal/dirtyStore.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { writable } from 'svelte/store'
-
-export const dirtyStore = writable(false)
diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte
index dc5bbda9c5..5dfd6e6153 100644
--- a/frontend/src/lib/components/common/table/ScriptRow.svelte
+++ b/frontend/src/lib/components/common/table/ScriptRow.svelte
@@ -11,6 +11,7 @@
import {
faArchive,
faCalendarAlt,
+ faCode,
faCodeFork,
faCopy,
faEdit,
@@ -37,6 +38,7 @@
export let deploymentDrawer: DeployWorkspaceDrawer
export let deleteConfirmedCallback: (() => void) | undefined
export let errorHandlerMuted: boolean
+ export let showCode: (path: string, summary: string) => void
export let depth: number = 0
let {
@@ -151,6 +153,13 @@
let owner = isOwner(path, $userStore, $workspaceStore)
if (draft_only) {
return [
+ {
+ displayName: 'View code',
+ icon: faCode,
+ action: () => {
+ showCode(script.path, script.summary)
+ }
+ },
{
displayName: 'Delete',
icon: faTrashAlt,
@@ -169,6 +178,13 @@
]
}
return [
+ {
+ displayName: 'View code',
+ icon: faCode,
+ action: () => {
+ showCode(script.path, script.summary)
+ }
+ },
{
displayName: 'Duplicate/Fork',
icon: faCodeFork,
diff --git a/frontend/src/lib/components/copilot/FlowCopilotStatus.svelte b/frontend/src/lib/components/copilot/FlowCopilotStatus.svelte
index e5a1427dda..d807b1712e 100644
--- a/frontend/src/lib/components/copilot/FlowCopilotStatus.svelte
+++ b/frontend/src/lib/components/copilot/FlowCopilotStatus.svelte
@@ -11,7 +11,6 @@
import type { FlowModule } from '$lib/gen'
import type { FlowEditorContext } from '../flows/types'
import { ExternalLink } from 'lucide-svelte'
- import { twMerge } from 'tailwind-merge'
export let copilotLoading: boolean
export let copilotStatus: string
@@ -35,7 +34,7 @@
{
if (copilotLoading || ($currentStepStore !== undefined && $currentStepStore !== 'Input')) {
abortController?.abort()
@@ -116,7 +115,6 @@
Test up to
-
+
{$selectedId}
diff --git a/frontend/src/lib/components/flows/map/FlowModuleSchemaMap.svelte b/frontend/src/lib/components/flows/map/FlowModuleSchemaMap.svelte
index c749346c0f..c19abf7b16 100644
--- a/frontend/src/lib/components/flows/map/FlowModuleSchemaMap.svelte
+++ b/frontend/src/lib/components/flows/map/FlowModuleSchemaMap.svelte
@@ -277,7 +277,6 @@
on:move={async ({ detail }) => {
if (!$moving || $moving.module.id !== detail.module.id) {
if (detail.module && detail.modules) {
- console.log('MOVE+')
$moving = { module: detail.module, modules: detail.modules }
}
} else {
diff --git a/frontend/src/lib/components/home/Item.svelte b/frontend/src/lib/components/home/Item.svelte
index c2d75a66e2..110cdf5f0b 100644
--- a/frontend/src/lib/components/home/Item.svelte
+++ b/frontend/src/lib/components/home/Item.svelte
@@ -19,6 +19,7 @@
let shareModal: ShareModal
let moveDrawer: MoveDrawer
let deploymentDrawer: DeployWorkspaceDrawer
+ export let showCode: (path: string, summary: string) => void
{#key item.summary}
@@ -39,6 +40,7 @@
{moveDrawer}
{deploymentDrawer}
{depth}
+ {showCode}
/>
{:else if item.type == 'flow'}
+ {
+ setTimeout(() => {
+ viewCodeTitle = undefined
+ script = undefined
+ }, 300)
+ }}
+>
+
+ {#if script}
+
+ {:else}
+
+ {/if}
+
+
+
@@ -370,6 +403,7 @@
loadApps()
loadRawApps()
}}
+ {showCode}
/>
{/each}
{:else}
@@ -386,6 +420,7 @@
loadApps()
loadRawApps()
}}
+ {showCode}
/>
{/each}
{/if}
diff --git a/frontend/src/lib/components/home/TreeView.svelte b/frontend/src/lib/components/home/TreeView.svelte
index 2b386de10a..ecf834511c 100644
--- a/frontend/src/lib/components/home/TreeView.svelte
+++ b/frontend/src/lib/components/home/TreeView.svelte
@@ -14,6 +14,7 @@
const isUser = (i: any): i is UserItem => i && 'username' in i
let opened: boolean = true
+ export let showCode: (path: string, summary: string) => void
{#if item}
@@ -110,6 +111,15 @@
{/if}
{:else}
-
+
{/if}
{/if}
diff --git a/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte b/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte
index 246b398bd4..c977a89cd5 100644
--- a/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte
+++ b/frontend/src/lib/components/sidebar/WorkspaceMenu.svelte
@@ -6,7 +6,6 @@
import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'
import { Icon } from 'svelte-awesome'
import { goto } from '$app/navigation'
- import { dirtyStore } from '../common/confirmationModal/dirtyStore'
import { page } from '$app/stores'
import { switchWorkspace } from '$lib/storeUtils'
import MultiplayerMenu from './MultiplayerMenu.svelte'
@@ -16,42 +15,26 @@
export let isCollapsed: boolean = false
- function waitForNextUpdate(store) {
- return new Promise((resolve) => {
- let firstEmission = true
- store.subscribe((value) => {
- if (firstEmission) {
- firstEmission = false
- return
- }
- resolve(value)
- })
- })
- }
-
async function toggleSwitchWorkspace(id: string) {
if ($workspaceStore === id) {
return
}
- const editPages = ['/scripts/edit/', '/flows/edit/', '/apps/edit/']
+ const editPages = [
+ '/scripts/edit/',
+ '/flows/edit/',
+ '/apps/edit/',
+ '/scripts/get/',
+ '/flows/get/',
+ '/apps/get/'
+ ]
const isOnEditPage = editPages.some((editPage) => $page.route.id?.includes(editPage) ?? false)
- // Check if we have unsaved changes
- const wasDirty = $dirtyStore
- // Try to go to the home page
-
- // If we weren't dirty, we can directly switch workspaces
- if (!wasDirty && !isOnEditPage) {
+ if (!isOnEditPage) {
switchWorkspace(id)
} else {
await goto('/')
-
- const isStillDirty = await waitForNextUpdate(dirtyStore)
-
- if (!isStillDirty) {
- switchWorkspace(id)
- }
+ switchWorkspace(id)
}
}
diff --git a/frontend/src/lib/components/tutorials/app/AppTutorial.svelte b/frontend/src/lib/components/tutorials/app/AppTutorial.svelte
index b3dc895902..4f7e5160b8 100644
--- a/frontend/src/lib/components/tutorials/app/AppTutorial.svelte
+++ b/frontend/src/lib/components/tutorials/app/AppTutorial.svelte
@@ -2,7 +2,6 @@
import { insertNewGridItem, appComponentFromType } from '$lib/components/apps/editor/appUtils'
import type { AppComponent, TypedComponent } from '$lib/components/apps/editor/component'
import type { AppViewerContext, AppEditorContext } from '$lib/components/apps/types'
- import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import { push } from '$lib/history'
import { getContext } from 'svelte'
import Tutorial from '../Tutorial.svelte'
@@ -31,8 +30,6 @@
function addComponent(appComponentType: TypedComponent['type']): void {
push(history, $app)
- $dirtyStore = true
-
const id = insertNewGridItem(
$app,
appComponentFromType(appComponentType) as (id: string) => AppComponent,
diff --git a/frontend/src/lib/components/tutorials/app/ConnectionTutorial.svelte b/frontend/src/lib/components/tutorials/app/ConnectionTutorial.svelte
index 15ec4acb8c..019e2b5335 100644
--- a/frontend/src/lib/components/tutorials/app/ConnectionTutorial.svelte
+++ b/frontend/src/lib/components/tutorials/app/ConnectionTutorial.svelte
@@ -2,7 +2,6 @@
import { insertNewGridItem, appComponentFromType } from '$lib/components/apps/editor/appUtils'
import type { AppComponent } from '$lib/components/apps/editor/component'
import type { AppViewerContext, AppEditorContext } from '$lib/components/apps/types'
- import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import { push } from '$lib/history'
import { getContext } from 'svelte'
import Tutorial from '../Tutorial.svelte'
@@ -24,8 +23,6 @@
function addComponent(): void {
push(history, $app)
- $dirtyStore = true
-
const id = insertNewGridItem(
$app,
appComponentFromType('textcomponent') as (id: string) => AppComponent,
diff --git a/frontend/src/lib/toast.ts b/frontend/src/lib/toast.ts
index d2ce0d33d3..6f37988d87 100644
--- a/frontend/src/lib/toast.ts
+++ b/frontend/src/lib/toast.ts
@@ -10,7 +10,8 @@ export function sendUserToast(
message: string,
error: boolean = false,
actions: ToastAction[] = [],
- errorMessage: string | undefined = undefined
+ errorMessage: string | undefined = undefined,
+ duration: number = 5000
): void {
toast.push({
component: {
@@ -19,7 +20,8 @@ export function sendUserToast(
message,
error,
actions,
- errorMessage
+ errorMessage,
+ duration
},
sendIdTo: 'toastId'
},
diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts
index 78e8c52a18..a7c50bb56f 100644
--- a/frontend/src/lib/utils.ts
+++ b/frontend/src/lib/utils.ts
@@ -10,6 +10,7 @@
import { deepEqual } from 'fast-equals'
import type { UserExt } from './stores'
import { sendUserToast } from './toast'
+import type { Script } from './gen'
export { sendUserToast }
export function validateUsername(username: string): string {
@@ -660,3 +661,33 @@ export function roughSizeOfObject(object: object | string) {
}
return bytes
}
+
+export type Value = {
+ language?: Script.language
+ content?: string
+ path?: string
+ draft_only?: boolean
+ value?: any
+ draft?: Value
+ [key: string]: any
+}
+
+export function cleanValueProperties(obj: Value) {
+ if (typeof obj !== 'object') {
+ return obj
+ } else {
+ let newObj: any = {}
+ for (const key of Object.keys(obj)) {
+ if (key !== 'draft' && key !== 'draft_only' && key !== 'parent_hash' && obj[key]) {
+ newObj[key] = obj[key]
+ }
+ }
+ return newObj
+ }
+}
+
+export function orderedJsonStringify(obj: any, space?: string | number) {
+ const allKeys = new Set()
+ JSON.stringify(obj, (key, value) => (allKeys.add(key), value))
+ return JSON.stringify(obj, (Array.from(allKeys) as string[]).sort(), space)
+}
diff --git a/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte
index 27fc1b0a73..851c1a19e9 100644
--- a/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/apps/add/+page.svelte
@@ -5,7 +5,6 @@
import { AppService, Policy } from '$lib/gen'
import { page } from '$app/stores'
import { decodeState } from '$lib/utils'
- import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
import { userStore, workspaceStore } from '$lib/stores'
import type { App } from '$lib/components/apps/types'
import { goto } from '$app/navigation'
@@ -105,8 +104,6 @@
value = decodeState(state)
}
}
-
- $dirtyStore = false
{#if value}
diff --git a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte
index ff95bf7ff4..74fbe899b1 100644
--- a/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/apps/edit/[...path]/+page.svelte
@@ -1,15 +1,26 @@
+
+
{#key redraw}
{#if app}
@@ -88,6 +185,8 @@
app={app.value}
path={app.path}
policy={app.policy}
+ bind:savedApp
+ {diffDrawer}
/>
{/if}
diff --git a/frontend/src/routes/(root)/(logged)/flows/add/+page.svelte b/frontend/src/routes/(root)/(logged)/flows/add/+page.svelte
index c39d523201..037a4dab3a 100644
--- a/frontend/src/routes/(root)/(logged)/flows/add/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/flows/add/+page.svelte
@@ -1,8 +1,6 @@
-
{
diff --git a/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte b/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte
index e6db75faaf..4b86ac03fd 100644
--- a/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/flows/edit/[...path]/+page.svelte
@@ -1,23 +1,35 @@
-
-
+
{
goto(`/flows/get/${e.detail}?workspace=${$workspaceStore}`)
@@ -109,4 +198,6 @@
{selectedId}
{initialArgs}
{loading}
+ bind:savedFlow
+ {diffDrawer}
/>
diff --git a/frontend/src/routes/(root)/(logged)/scripts/add/+page.svelte b/frontend/src/routes/(root)/(logged)/scripts/add/+page.svelte
index b8d846f8b8..a7dd46d9aa 100644
--- a/frontend/src/routes/(root)/(logged)/scripts/add/+page.svelte
+++ b/frontend/src/routes/(root)/(logged)/scripts/add/+page.svelte
@@ -6,7 +6,6 @@
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
import type { Schema } from '$lib/common'
import { decodeState, emptySchema } from '$lib/utils'
- import { dirtyStore } from '$lib/components/common/confirmationModal/dirtyStore'
// Default
let schema: Schema = emptySchema()
@@ -71,7 +70,6 @@
loadTemplate()
}
}
- $dirtyStore = true
- import { ScriptService, NewScript } from '$lib/gen'
+ import { ScriptService, NewScript, type NewScriptWithDraft, DraftService } from '$lib/gen'
import { page } from '$app/stores'
import { runFormStore, workspaceStore } from '$lib/stores'
import ScriptBuilder from '$lib/components/ScriptBuilder.svelte'
- import { decodeState } from '$lib/utils'
+ import { decodeState, cleanValueProperties, orderedJsonStringify } from '$lib/utils'
import { goto } from '$app/navigation'
import { sendUserToast } from '$lib/toast'
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
+ import { cloneDeep } from 'lodash'
const initialState = $page.url.hash != '' ? $page.url.hash.slice(1) : undefined
let initialArgs = {}
@@ -27,71 +28,97 @@
let scriptBuilder: ScriptBuilder | undefined = undefined
- let reloadAction: () => void = () => {}
+ let reloadAction: () => Promise = async () => {}
+
+ let savedScript: NewScriptWithDraft | undefined = undefined
async function loadScript(): Promise {
if (scriptLoadedFromUrl != undefined && scriptLoadedFromUrl.path == $page.params.path) {
script = scriptLoadedFromUrl
- reloadAction = () => {
+ reloadAction = async () => {
scriptLoadedFromUrl = undefined
goto(`/scripts/edit/${script!.path}`)
loadScript()
}
- sendUserToast('Script loaded from latest autosave stored in the URL', false, [
- {
- label: 'Discard browser stored autosave and reload',
- callback: reloadAction
- },
- {
- label: 'Show diff',
- callback: async () => {
- diffDrawer.openDrawer()
- let remoteContent = await ScriptService.getScriptByPathWithDraft({
- workspace: $workspaceStore!,
- path: script!.path
- })
- diffDrawer.setDiff(
- remoteContent?.draft?.content ?? remoteContent.content,
- scriptLoadedFromUrl.content
- )
- }
+
+ async function compareAutosave() {
+ savedScript = await ScriptService.getScriptByPathWithDraft({
+ workspace: $workspaceStore!,
+ path: script!.path
+ })
+
+ const draftOrDeployed = cleanValueProperties(savedScript?.draft || savedScript)
+ const urlScript = cleanValueProperties(scriptLoadedFromUrl)
+ if (orderedJsonStringify(draftOrDeployed) === orderedJsonStringify(urlScript)) {
+ reloadAction()
+ } else {
+ sendUserToast('Script loaded from latest autosave stored in the URL', false, [
+ {
+ label: 'Discard browser stored autosave and reload',
+ callback: reloadAction
+ },
+ {
+ label: 'Show diff',
+ callback: async () => {
+ diffDrawer.openDrawer()
+ diffDrawer.setDiff({
+ mode: 'simple',
+ original: draftOrDeployed,
+ current: urlScript,
+ title: `${savedScript?.draft ? 'Latest saved draft' : 'Deployed'} <> Autosave`,
+ button: { text: 'Discard autosave', onClick: reloadAction }
+ })
+ }
+ }
+ ])
}
- ])
+ }
+ compareAutosave()
} else {
if (hash) {
const scriptByHash = await ScriptService.getScriptByHash({
workspace: $workspaceStore!,
hash
})
+ savedScript = cloneDeep(scriptByHash) as NewScriptWithDraft
script = { ...scriptByHash, parent_hash: hash, lock: undefined }
} else {
const scriptWithDraft = await ScriptService.getScriptByPathWithDraft({
workspace: $workspaceStore!,
path: $page.params.path
})
+ savedScript = cloneDeep(scriptWithDraft)
if (scriptWithDraft.draft != undefined) {
script = scriptWithDraft.draft
if (!scriptWithDraft.draft_only) {
- reloadAction = () => {
+ reloadAction = async () => {
scriptLoadedFromUrl = undefined
- hash = scriptWithDraft.hash
+ 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: 'Ignore draft and load from latest deployed version',
+ label: 'Discard draft and load from latest deployed version',
callback: reloadAction
},
{
label: 'Show diff',
callback: async () => {
diffDrawer.openDrawer()
- let remoteContent = await ScriptService.getScriptByPath({
- workspace: $workspaceStore!,
- path: script!.path
+ diffDrawer.setDiff({
+ mode: 'simple',
+ original: deployed,
+ current: draft,
+ title: 'Deployed <> Draft',
+ button: { text: 'Discard draft', onClick: reloadAction }
})
- diffDrawer.setDiff(remoteContent.content, script?.content ?? '')
}
}
])
@@ -128,9 +155,43 @@
}
let diffDrawer: DiffDrawer
+
+ async function restoreDraft() {
+ if (!savedScript) {
+ sendUserToast('Could not restore to draft', true)
+ return
+ }
+ diffDrawer.closeDrawer()
+ goto(`/scripts/edit/${savedScript.path}`)
+ loadScript()
+ }
+
+ async function restoreDeployed() {
+ if (!savedScript) {
+ sendUserToast('Could not restore to deployed', true)
+ return
+ }
+ diffDrawer.closeDrawer()
+ if (savedScript['draft']) {
+ await DraftService.deleteDraft({
+ workspace: $workspaceStore!,
+ kind: 'script',
+ path: savedScript.path
+ })
+ }
+ goto(`/scripts/edit/${savedScript.path}`)
+ loadScript()
+ }
-
+
{#if script}
-
+
{/if}