feat: add diff viewer to script autosave discard menu

This commit is contained in:
Ruben Fiszel
2023-06-19 00:37:31 +02:00
parent 4a5e7810c6
commit a794a6a690
7 changed files with 118 additions and 63 deletions
@@ -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}
+1 -1
View File
@@ -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}