mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-21 00:02:23 +00:00
feat(frontend): cancellable inline script editor run
This commit is contained in:
@@ -146,7 +146,7 @@
|
||||
if (previewJobUpdates.new_logs) {
|
||||
job.logs = (job?.logs ?? '').concat(previewJobUpdates.new_logs)
|
||||
}
|
||||
if (previewJobUpdates.mem_peak) {
|
||||
if (previewJobUpdates.mem_peak && job) {
|
||||
job.mem_peak = previewJobUpdates.mem_peak
|
||||
}
|
||||
if ((previewJobUpdates.running ?? false) || (previewJobUpdates.completed ?? false)) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
import { createEventDispatcher, getContext, onDestroy } from 'svelte'
|
||||
import type { AppInputs, Runnable } from '../../inputType'
|
||||
import type { Output } from '../../rx'
|
||||
import type { AppViewerContext, InlineScript } from '../../types'
|
||||
import type { AppViewerContext, CancelablePromise, InlineScript } from '../../types'
|
||||
import { computeGlobalContext, eval_like } from './eval'
|
||||
import InputValue from './InputValue.svelte'
|
||||
import RefreshButton from './RefreshButton.svelte'
|
||||
@@ -58,12 +58,29 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let donePromise: (() => void) | undefined = undefined
|
||||
|
||||
const cancellableRun: (inlineScript?: InlineScript) => CancelablePromise<void> = (
|
||||
inlineScript?: InlineScript
|
||||
) => {
|
||||
let rejectCb: (err: Error) => void
|
||||
let p: Partial<CancelablePromise<void>> = new Promise<void>((resolve, reject) => {
|
||||
rejectCb = reject
|
||||
donePromise = resolve
|
||||
executeComponent(true, inlineScript).catch(reject)
|
||||
})
|
||||
p.cancel = () => {
|
||||
testJobLoader?.cancelJob()
|
||||
loading = false
|
||||
rejectCb(new Error('Canceled'))
|
||||
}
|
||||
return p as CancelablePromise<void>
|
||||
}
|
||||
|
||||
$runnableComponents[id] = {
|
||||
autoRefresh: autoRefresh && recomputableByRefreshButton,
|
||||
refreshOnStart,
|
||||
cb: async (inlineScript?: InlineScript) => {
|
||||
await executeComponent(true, inlineScript)
|
||||
}
|
||||
cb: cancellableRun
|
||||
}
|
||||
|
||||
if (!$initialized.initializedComponents.includes(id)) {
|
||||
@@ -372,6 +389,7 @@
|
||||
if (startedAt > lastStartedAt) {
|
||||
lastStartedAt = startedAt
|
||||
setResult(e.detail.result)
|
||||
donePromise?.()
|
||||
}
|
||||
}
|
||||
loading = false
|
||||
|
||||
@@ -396,7 +396,7 @@
|
||||
<Skeleton layout={[[40]]} />
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="flex flex-col h-full w-full gap-4 mb-4">
|
||||
<div class="flex flex-col h-full w-full gap-4 p-2 mb-4">
|
||||
{#if job?.['running']}
|
||||
<div class="flex flex-row-reverse w-full">
|
||||
<Button
|
||||
@@ -404,6 +404,8 @@
|
||||
variant="border"
|
||||
on:click={() => testJobLoader?.cancelJob()}
|
||||
>
|
||||
<Loader2 size={14} class="animate-spin mr-2" />
|
||||
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
@@ -633,7 +635,12 @@
|
||||
</span>
|
||||
<span class="hidden md:inline">
|
||||
<Button
|
||||
on:click={() => (jobsDrawerOpen = true)}
|
||||
on:click={() => {
|
||||
if (selectedJobId == undefined && $jobs.length > 0) {
|
||||
selectedJobId = $jobs[0].job
|
||||
}
|
||||
jobsDrawerOpen = true
|
||||
}}
|
||||
color={hasErrors ? 'red' : 'light'}
|
||||
size="xs"
|
||||
variant="border"
|
||||
|
||||
+48
-25
@@ -2,8 +2,8 @@
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import type { Preview } from '$lib/gen'
|
||||
import { createEventDispatcher, getContext, onMount } from 'svelte'
|
||||
import type { AppViewerContext, InlineScript } from '../../types'
|
||||
import { CornerDownLeft, Maximize2, Trash2 } from 'lucide-svelte'
|
||||
import type { AppViewerContext, CancelablePromise, InlineScript } from '../../types'
|
||||
import { CornerDownLeft, Loader2, Maximize2, Trash2 } from 'lucide-svelte'
|
||||
import InlineScriptEditorDrawer from './InlineScriptEditorDrawer.svelte'
|
||||
import { inferArgs } from '$lib/infer'
|
||||
import type { Schema } from '$lib/common'
|
||||
@@ -87,6 +87,8 @@
|
||||
inlineScript?.language == 'frontend' && worldStore
|
||||
? buildExtraLib($worldStore?.outputsById ?? {}, id, false, $state, true)
|
||||
: undefined
|
||||
|
||||
let cancelable: CancelablePromise<void> | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if inlineScript}
|
||||
@@ -166,31 +168,52 @@
|
||||
</div>
|
||||
</Button>
|
||||
{#if $runnableComponents[id] != undefined}
|
||||
<Button
|
||||
loading={runLoading}
|
||||
size="xs"
|
||||
color="dark"
|
||||
variant="border"
|
||||
btnClasses="!px-2 !py-1 !bg-gray-700 !text-white hover:!bg-gray-900"
|
||||
on:click={async () => {
|
||||
runLoading = true
|
||||
await $runnableComponents[id]?.cb?.(!transformer ? inlineScript : undefined)
|
||||
runLoading = false
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
Run
|
||||
{#if !runLoading}
|
||||
<Button
|
||||
loading={runLoading}
|
||||
size="xs"
|
||||
color="dark"
|
||||
variant="border"
|
||||
btnClasses="!px-2 !py-1 !bg-gray-700 !text-white hover:!bg-gray-900"
|
||||
on:click={async () => {
|
||||
runLoading = true
|
||||
try {
|
||||
cancelable = $runnableComponents[id]?.cb?.(
|
||||
!transformer ? inlineScript : undefined
|
||||
)
|
||||
await cancelable
|
||||
} catch {}
|
||||
runLoading = false
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-row gap-1 items-center">
|
||||
Run
|
||||
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<Kbd>{getModifierKey()}</Kbd>
|
||||
<Kbd>
|
||||
<div class="h-4 flex items-center justify-center">
|
||||
<CornerDownLeft size={10} />
|
||||
</div>
|
||||
</Kbd>
|
||||
<div class="flex flex-row items-center gap-1">
|
||||
<Kbd>{getModifierKey()}</Kbd>
|
||||
<Kbd>
|
||||
<div class="h-4 flex items-center justify-center">
|
||||
<CornerDownLeft size={10} />
|
||||
</div>
|
||||
</Kbd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
size="xs"
|
||||
color="red"
|
||||
variant="border"
|
||||
btnClasses="!px-2 !py-1.5"
|
||||
on:click={async () => {
|
||||
cancelable?.cancel()
|
||||
runLoading = false
|
||||
}}
|
||||
>
|
||||
<Loader2 size={14} class="animate-spin mr-2" />
|
||||
Cancel
|
||||
</Button>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -130,6 +130,10 @@ export type ConnectingInput = {
|
||||
hoveredComponent: string | undefined
|
||||
}
|
||||
|
||||
export interface CancelablePromise<T> extends Promise<T> {
|
||||
cancel: () => void
|
||||
}
|
||||
|
||||
export type AppViewerContext = {
|
||||
worldStore: Writable<World>
|
||||
app: Writable<App>
|
||||
@@ -148,7 +152,7 @@ export type AppViewerContext = {
|
||||
{
|
||||
autoRefresh: boolean
|
||||
refreshOnStart?: boolean
|
||||
cb: (inlineScript?: InlineScript) => Promise<void>
|
||||
cb: (inlineScript?: InlineScript) => CancelablePromise<void>
|
||||
}
|
||||
>
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user