Files
windmill/frontend/src/lib/components/JobArgs.svelte
T
Guilhem 3b5c1657c7 fix(frontend): improve runs detail page (#7694)
* separate flow and status with splitpane

* fix autoscroll behavior

* Flow log viewer nit

* not graph viewer

* Improve flow job result

* Create job detail header to replace metadata

* Remove FlowPreviewResult

* Create compact job header

* Use job header in runs page

* Improve runs page run preview

* Use flow header in detail section

* Show logs for script steps

* Clean old schedule status

* Limit result height

* Script run detail improvement

* Script run preview improvement

* Fix csv table overflow

* surface tertiary as background for Inputs

* nit

* Improve runs detail skeleton

* fix check

* nit

* Improve node definition

* fix flow module component overflow

* Use component DataTable for flow schema viewer

* Add language icon to step detail

* improve run header

* Improve Job detail header

* nit

* restore isOwner logic

* Handle resume flows

* restore execution status in run preview

* restore flow execution status in the preview

* flow preview, add status bar

* nit module status

* nit

* Remove flor preview result

* nit

* nit

* fix flow result card

* nit

* nit

* nit

* improve field selection on runs detail based on job type

* Improve column layout

* create JobStatusIcon component

* remove job status badge icons

* improve compact version

* use shared job field display

* improve job detail field display

* fix badge alignment

* increase padding

* nit

* nit

* improve compact display

* make background darker for metadata

* use auto layout

* fix auto layout

* improve display

* fix truncate logic

* fix compact

* improve flex adaptibility

* improve responsive layout

* improve extra compact header

* nit

* remove unused icons

* nit

* Improve flow result display

* nit

* merge progressbar and execution status

* handle canceled flow better
2026-02-03 17:20:35 +00:00

183 lines
5.1 KiB
Svelte

<script lang="ts">
import { ChevronRightSquare, ClipboardCopy, Download, Expand } from 'lucide-svelte'
import ArgInfo from './ArgInfo.svelte'
import { Button, Drawer, DrawerContent, Skeleton } from './common'
import { Highlight } from 'svelte-highlight'
import { copyToClipboard } from '$lib/utils'
import { json } from 'svelte-highlight/languages'
import DataTable from './table/DataTable.svelte'
import Cell from './table/Cell.svelte'
import Head from './table/Head.svelte'
import Row from './table/Row.svelte'
import HighlightTheme from './HighlightTheme.svelte'
import { deepEqual } from 'fast-equals'
import { isWindmillTooBigObject } from './job_args'
interface Props {
id?: string | undefined
args: any
argLabel?: string | undefined
workspace?: string | undefined
}
let { id = undefined, args, argLabel = undefined, workspace = undefined }: Props = $props()
let jsonViewer: Drawer | undefined = $state()
let runLocally: Drawer | undefined = $state()
let jsonStr = $state('')
function pythonCode() {
return `
if __name__ == "__main__":
${Object.entries(args)
.map(([arg, value]) => {
return ` ${arg} = ${JSON.stringify(value)}`
})
.join('\n')}
main(${Object.keys(args)
.map((x) => `${x} = ${x}`)
.join(', ')})
`
}
function typescriptCode() {
return `
if (import.meta.main) {
${Object.entries(args)
.map(([arg, value]) => {
return ` let ${arg} = ${JSON.stringify(value)}`
})
.join('\n')}
await main(...)
}
`
}
</script>
{#if args && typeof args === 'object' && deepEqual( Object.keys(args ?? {}), ['reason'] ) && args['reason'] == 'PREPROCESSOR_ARGS_ARE_DISCARDED'}
Preprocessor args are discarded
{:else if id && workspace && args && typeof args === 'object' && deepEqual( Object.keys(args ?? {}), ['reason'] ) && args['reason'] == 'WINDMILL_TOO_BIG'}
The args are too big in size to be able to fetch alongside job. Please <a
href="/api/w/{workspace}/jobs_u/get_args/{id}"
target="_blank">download the JSON file to view them</a
>.
{:else}
<div class="relative">
<DataTable size="sm" containerClass="bg-surface-tertiary">
<Head>
<tr class="w-full">
<Cell head first>{argLabel ?? 'Input'}</Cell>
<Cell head last>Value</Cell>
</tr>
{#snippet headerAction()}
<div class="center-center -m-1">
<Button
unifiedSize="md"
variant="subtle"
onClick={() => {
jsonStr = JSON.stringify(args, null, 4)
jsonViewer?.openDrawer()
}}
iconOnly
startIcon={{ icon: Expand }}
></Button>
</div>
{/snippet}
</Head>
<tbody class="divide-y w-full">
{#if args && typeof args === 'object' && Object.keys(args ?? {}).length > 0}
{#each Object.entries(args ?? {}).sort( (a, b) => a?.[0]?.localeCompare(b?.[0]) ) as [arg, value]}
<Row>
<Cell first>{arg}</Cell>
<Cell><ArgInfo {value} /></Cell>
</Row>
{/each}
{:else if args && typeof args !== 'object'}
<Row><Cell>Argument is not an object (type: {typeof args})</Cell></Row>
{:else if args}
<Row><Cell>No arguments</Cell></Row>
{:else}
<Row>
<Cell first>
<Skeleton layout={[[1], 0.5, [1]]} />
</Cell>
<Cell last>
<Skeleton layout={[[1], 0.5, [1]]} />
</Cell>
</Row>
{/if}
</tbody>
</DataTable>
</div>
{/if}
<HighlightTheme />
<Drawer bind:this={jsonViewer} size="900px">
<DrawerContent title="Expanded Args" on:close={jsonViewer.closeDrawer}>
{#snippet actions()}
<Button
download="windmill-args.json"
href={id && workspace
? `/api/w/${workspace}/jobs_u/get_args/${id}`
: `data:text/json;charset=utf-8,${encodeURIComponent(jsonStr)}`}
startIcon={{ icon: Download }}
size="xs"
color="light"
>
Download
</Button>
<Button
on:click={() => runLocally?.openDrawer()}
color="light"
size="xs"
startIcon={{ icon: ChevronRightSquare }}
>
Use in a local script
</Button>
<Button
on:click={() => copyToClipboard(jsonStr)}
color="light"
size="xs"
startIcon={{ icon: ClipboardCopy }}
>
Copy to clipboard
</Button>
{/snippet}
{#if jsonStr.length > 100000 || (id && workspace && args && isWindmillTooBigObject(args))}
<div class="text-sm mb-2 text-primary">
<a
download="windmill-args.json"
href={id && workspace
? `/api/w/${workspace}/jobs_u/get_args/${id}`
: `data:text/json;charset=utf-8,${encodeURIComponent(jsonStr)}`}
>
JSON is too large to be displayed in full.
</a></div
>
{:else}
<Highlight language={json} code={jsonStr.replace(/\\n/g, '\n')} />
{/if}
</DrawerContent>
</Drawer>
<Drawer bind:this={runLocally} size="900px">
<DrawerContent title="Run locally" on:close={runLocally.closeDrawer}>
<h3 class="mb-2">Envs</h3>
If using the wmill client in your code, set the following env variables:
<pre
><code
>BASE_URL="{window.location.origin}"
WM_TOKEN="{'<TOKEN>'}"</code
></pre
>
<h3 class="mt-8">TypeScript</h3>
<pre><code>{typescriptCode()}</code></pre>
<h3 class="mt-8">Python</h3>
<pre><code>{pythonCode()}</code></pre>
</DrawerContent>
</Drawer>