mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-24 08:01:38 +00:00
feat: add diff viewer to script autosave discard menu
This commit is contained in:
@@ -19,8 +19,7 @@
|
||||
import Toggle from './Toggle.svelte'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
import Badge from './common/badge/Badge.svelte'
|
||||
import * as Diff from 'diff'
|
||||
import { Drawer, DrawerContent } from './common'
|
||||
import DiffDrawer from './DiffDrawer.svelte'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -37,7 +36,9 @@
|
||||
|
||||
const allAlreadyExists: { [key: string]: boolean } = {}
|
||||
|
||||
let diffDrawer: DiffDrawer
|
||||
let notSet: boolean | undefined = undefined
|
||||
|
||||
$: WorkspaceService.getDeployTo({ workspace: $workspaceStore! }).then((x) => {
|
||||
workspaceToDeployTo = x.deploy_to
|
||||
if (x.deploy_to == undefined) {
|
||||
@@ -348,33 +349,6 @@
|
||||
return `${kind}:${path}`
|
||||
}
|
||||
|
||||
export function showDiff(local: string, remote: string) {
|
||||
let finalString = ''
|
||||
for (const part of Diff.diffLines(local, remote)) {
|
||||
if (part.removed) {
|
||||
// print red if removed without newline
|
||||
finalString += `<span class="text-red-600">${part.value}</span>`
|
||||
} else if (part.added) {
|
||||
// print green if added
|
||||
finalString += `<span class="text-green-600">${part.value}</span>`
|
||||
} else {
|
||||
let lines = part.value.split('\n')
|
||||
|
||||
if (lines.length > 12) {
|
||||
lines = lines.slice(0, 6)
|
||||
lines.push('...')
|
||||
lines = lines.concat(part.value.split('\n').slice(-6))
|
||||
}
|
||||
// print white if unchanged
|
||||
finalString += `${lines.join('\n')}`
|
||||
}
|
||||
}
|
||||
return finalString
|
||||
}
|
||||
|
||||
let diffViewer: Drawer
|
||||
let diffContent: string | undefined = undefined
|
||||
|
||||
async function getValue(kind: Kind, path: string, workspace: string) {
|
||||
try {
|
||||
if (kind == 'flow') {
|
||||
@@ -439,12 +413,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function computeDiff(kind: Kind, path: string) {
|
||||
async function showDiff(kind: Kind, path: string) {
|
||||
diffDrawer.openDrawer()
|
||||
let values = await Promise.all([
|
||||
getValue(kind, path, $workspaceStore!),
|
||||
getValue(kind, path, workspaceToDeployTo!)
|
||||
])
|
||||
diffContent = showDiff(JSON.stringify(values[0], null, 2), JSON.stringify(values[1], null, 2))
|
||||
diffDrawer.setDiff(JSON.stringify(values[0], null, 2), JSON.stringify(values[1], null, 2))
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -477,20 +452,7 @@
|
||||
{:else if seeTarget == true}
|
||||
<h3 class="mb-6 mt-16">All related deployable items</h3>
|
||||
|
||||
<Drawer bind:this={diffViewer} size="800px">
|
||||
<DrawerContent title="Diff" on:close={diffViewer.closeDrawer}>
|
||||
{#if diffContent == undefined}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:else}
|
||||
<pre class="border bg-white p-2"><code>{@html diffContent}</code></pre>
|
||||
<div class="flex flex-row-reverse gap-2">
|
||||
<div class="text-red-600">Removed</div>
|
||||
<div class="text-green-600">Added</div></div
|
||||
>
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} />
|
||||
<div class="grid grid-cols-9 justify-center max-w-3xl gap-2">
|
||||
{#each dependencies ?? [] as { kind, path, include }}
|
||||
{@const statusPath = computeStatusPath(kind, path)}
|
||||
@@ -519,9 +481,7 @@
|
||||
<button
|
||||
class="text-blue-600 font-normal mt-1"
|
||||
on:click={() => {
|
||||
diffContent = undefined
|
||||
computeDiff(kind, path)
|
||||
diffViewer.openDrawer()
|
||||
showDiff(kind, path)
|
||||
}}>diff</button
|
||||
>
|
||||
{/if}</div
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<script lang="ts">
|
||||
import * as Diff from 'diff'
|
||||
import { Button, Drawer, DrawerContent } from './common'
|
||||
import { Loader2 } from 'lucide-svelte'
|
||||
|
||||
let diffViewer: Drawer
|
||||
let diffContent: string | undefined = undefined
|
||||
|
||||
export let button: { text: string; onClick: () => void } | undefined = undefined
|
||||
export function openDrawer() {
|
||||
diffContent = undefined
|
||||
diffViewer.openDrawer()
|
||||
}
|
||||
|
||||
export function setDiff(local: string, remote: string) {
|
||||
let finalString = ''
|
||||
for (const part of Diff.diffLines(local, remote)) {
|
||||
if (part.removed) {
|
||||
// print red if removed without newline
|
||||
finalString += `<span class="text-red-600">${part.value}</span>`
|
||||
} else if (part.added) {
|
||||
// print green if added
|
||||
finalString += `<span class="text-green-600">${part.value}</span>`
|
||||
} else {
|
||||
let lines = part.value.split('\n')
|
||||
|
||||
if (lines.length > 12) {
|
||||
lines = lines.slice(0, 6)
|
||||
lines.push('...')
|
||||
lines = lines.concat(part.value.split('\n').slice(-6))
|
||||
}
|
||||
// print white if unchanged
|
||||
finalString += `${lines.join('\n')}`
|
||||
}
|
||||
}
|
||||
diffContent = finalString
|
||||
}
|
||||
</script>
|
||||
|
||||
<Drawer bind:this={diffViewer} size="800px">
|
||||
<DrawerContent title="Diff" on:close={diffViewer.closeDrawer}>
|
||||
{#if diffContent == undefined}
|
||||
<Loader2 class="animate-spin" />
|
||||
{:else}
|
||||
<pre class="border bg-white p-2"><code>{@html diffContent}</code></pre>
|
||||
<div class="flex flex-row-reverse gap-2">
|
||||
<div class="text-red-600">Removed</div>
|
||||
<div class="text-green-600">Added</div></div
|
||||
>
|
||||
{/if}
|
||||
<svelte:fragment slot="actions">
|
||||
{#if button}
|
||||
<Button
|
||||
color="light"
|
||||
on:click={() => {
|
||||
button?.onClick()
|
||||
diffViewer.closeDrawer()
|
||||
}}>{button.text}</Button
|
||||
>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { faMinus, faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons'
|
||||
|
||||
import { setInputCat as computeInputCat } from '$lib/utils'
|
||||
import { Badge, Button } from './common'
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<div class="w-full {clazz} {flexWrap ? 'flex flex-row flex-wrap gap-x-6 gap-y-2' : ''}">
|
||||
{#if keys.length > 0}
|
||||
{#each keys as argName, i (argName)}
|
||||
{#if Object.keys(schema.properties ?? {}).includes(argName)}
|
||||
{#if Object.keys(schema?.properties ?? {}).includes(argName)}
|
||||
<div>
|
||||
{#if typeof args == 'object' && schema?.properties[argName]}
|
||||
{#if editableSchema}
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
<div class="py-1">
|
||||
<Button
|
||||
target="_blank"
|
||||
href="https://github.com/windmill-labs/windmill/tree/main/cli"
|
||||
href="https://docs.windmill.dev/docs/cli_local_dev/vscode-extension"
|
||||
color="light"
|
||||
size="xs"
|
||||
btnClasses="mr-1 hidden lg:block"
|
||||
@@ -253,7 +253,7 @@
|
||||
icon: faGithub
|
||||
}}
|
||||
>
|
||||
Sync from Github
|
||||
Use VScode
|
||||
</Button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2 flex flex-row gap-2 h-15">
|
||||
<div class="mt-2 flex flex-col gap-2 h-15">
|
||||
{#each actions as action, index (index)}
|
||||
<Button
|
||||
on:click={() => {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { decodeState } from '$lib/utils'
|
||||
import { goto } from '$app/navigation'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DiffDrawer from '$lib/components/DiffDrawer.svelte'
|
||||
|
||||
const initialState = $page.url.searchParams.get('state')
|
||||
let initialArgs = {}
|
||||
@@ -26,16 +27,33 @@
|
||||
|
||||
let scriptBuilder: ScriptBuilder | undefined = undefined
|
||||
|
||||
let reloadAction: () => void = () => {}
|
||||
|
||||
async function loadScript(): Promise<void> {
|
||||
if (scriptLoadedFromUrl != undefined && scriptLoadedFromUrl.path == $page.params.path) {
|
||||
script = scriptLoadedFromUrl
|
||||
reloadAction = () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
}
|
||||
sendUserToast('Script loaded from latest autosave stored in the URL', false, [
|
||||
{
|
||||
label: 'Discard autosave and reload',
|
||||
callback: () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
])
|
||||
@@ -55,15 +73,26 @@
|
||||
if (scriptWithDraft.draft != undefined) {
|
||||
script = scriptWithDraft.draft
|
||||
if (!scriptWithDraft.draft_only) {
|
||||
reloadAction = () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
hash = scriptWithDraft.hash
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
}
|
||||
sendUserToast('Script loaded from latest saved draft', false, [
|
||||
{
|
||||
label: 'Ignore draft and load from latest deployed version',
|
||||
callback: () => {
|
||||
scriptLoadedFromUrl = undefined
|
||||
hash = scriptWithDraft.hash
|
||||
console.log(hash)
|
||||
goto(`/scripts/edit/${script!.path}`)
|
||||
loadScript()
|
||||
callback: reloadAction
|
||||
},
|
||||
{
|
||||
label: 'Show diff',
|
||||
callback: async () => {
|
||||
diffDrawer.openDrawer()
|
||||
let remoteContent = await ScriptService.getScriptByPath({
|
||||
workspace: $workspaceStore!,
|
||||
path: script!.path
|
||||
})
|
||||
diffDrawer.setDiff(remoteContent.content, script?.content ?? '')
|
||||
}
|
||||
}
|
||||
])
|
||||
@@ -96,8 +125,11 @@
|
||||
loadScript()
|
||||
}
|
||||
}
|
||||
|
||||
let diffDrawer: DiffDrawer
|
||||
</script>
|
||||
|
||||
<DiffDrawer bind:this={diffDrawer} button={{ text: 'Revert', onClick: reloadAction }} />
|
||||
{#if script}
|
||||
<ScriptBuilder bind:this={scriptBuilder} {topHash} {initialPath} {script} {initialArgs} />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user