feat: add ability to copy job args
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { ResourceService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { copyToClipboard, truncate } from '$lib/utils'
|
||||
import { ClipboardCopy } from 'lucide-svelte'
|
||||
import { ClipboardCopy, Expand } from 'lucide-svelte'
|
||||
import { Button, DrawerContent } from './common'
|
||||
import Drawer from './common/drawer/Drawer.svelte'
|
||||
import ObjectViewer from './propertyPicker/ObjectViewer.svelte'
|
||||
@@ -68,16 +68,18 @@
|
||||
>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="max-h-40 overflow-auto">
|
||||
<ObjectViewer collapsed={false} topBrackets={true} pureViewer={true} json={value} />
|
||||
<div class="relative">
|
||||
{#if JSON.stringify(value).length > 120}
|
||||
<button
|
||||
class="text-xs absolute top-0 right-4 text-gray-500"
|
||||
on:click={() => {
|
||||
jsonViewerContent = value
|
||||
jsonViewer.toggleDrawer()
|
||||
}}><Expand size={18} /></button
|
||||
>
|
||||
{/if}
|
||||
<div class="max-h-40 overflow-auto">
|
||||
<ObjectViewer collapsed={false} topBrackets={true} pureViewer={true} json={value} />
|
||||
</div>
|
||||
</div>
|
||||
{#if JSON.stringify(value).length > 120}
|
||||
<button
|
||||
class="text-xs text-blue-500"
|
||||
on:click={() => {
|
||||
jsonViewerContent = value
|
||||
jsonViewer.toggleDrawer()
|
||||
}}>See JSON</button
|
||||
>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import TableCustom from './TableCustom.svelte'
|
||||
import { copyToClipboard, truncate } from '$lib/utils'
|
||||
import { Button, Drawer, DrawerContent } from './common'
|
||||
import { ClipboardCopy } from 'lucide-svelte'
|
||||
import { ClipboardCopy, Download, Expand } from 'lucide-svelte'
|
||||
import Portal from 'svelte-portal'
|
||||
import ObjectViewer from './propertyPicker/ObjectViewer.svelte'
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
}
|
||||
|
||||
let jsonViewer: Drawer
|
||||
$: jsonStr = JSON.stringify(result, null, 4)
|
||||
</script>
|
||||
|
||||
<div class="inline-highlight">
|
||||
@@ -117,8 +118,8 @@
|
||||
class="mb-2 w-full text-sm relative"
|
||||
>The result keys are: <b>{truncate(Object.keys(result).join(', '), 50)}</b>
|
||||
{#if !disableExpand}
|
||||
<div class="text-gray-500 text-xs absolute top-5 right-0">
|
||||
<button on:click={jsonViewer.openDrawer}>Expand</button>
|
||||
<div class="text-gray-500 text-xs absolute top-5.5 right-0">
|
||||
<button on:click={jsonViewer.openDrawer}><Expand size={16} /></button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>{/if}{#if !forceJson && resultKind == 'table-col'}<div
|
||||
@@ -237,7 +238,6 @@
|
||||
>
|
||||
</div>
|
||||
{:else}
|
||||
{@const jsonStr = JSON.stringify(result, null, 4).replace(/\\n/g, '\n')}
|
||||
{#if jsonStr.length > 10000}
|
||||
<div class="text-sm mb-2 text-gray-600">
|
||||
<a
|
||||
@@ -252,7 +252,7 @@
|
||||
{/if}
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="text-gray-500 text-sm">No result: {JSON.stringify(result)}</div>
|
||||
<div class="text-gray-500 text-sm">No result: {jsonStr}</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -261,25 +261,26 @@
|
||||
<Drawer bind:this={jsonViewer} size="900px">
|
||||
<DrawerContent title="Expanded Result" on:close={jsonViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
on:click={() => copyToClipboard(JSON.stringify(result, null, 4))}
|
||||
color="light"
|
||||
size="xs"
|
||||
<a
|
||||
class="text-sm text-gray-600 mr-2 inline-flex gap-2 items-center py-2 px-2 hover:bg-gray-100 rounded-lg"
|
||||
download="{filename ?? 'result'}.json"
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(jsonStr)}"
|
||||
>Download <Download size={14} /></a
|
||||
>
|
||||
<Button on:click={() => copyToClipboard(jsonStr)} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Copy to clipboard <ClipboardCopy /> </div>
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{@const str = JSON.stringify(result, null, 4).replace(/\\n/g, '\n')}
|
||||
{#if str.length > 100000}
|
||||
{#if jsonStr.length > 100000}
|
||||
<div class="text-sm mb-2 text-gray-600">
|
||||
<a
|
||||
download="{filename ?? 'result'}.json"
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(str)}">Download</a
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(jsonStr)}">Download</a
|
||||
>
|
||||
JSON is too large to be displayed in full.
|
||||
</div>
|
||||
{:else}
|
||||
<Highlight language={json} code={JSON.stringify(result, null, 4).replace(/\\n/g, '\n')} />
|
||||
<Highlight language={json} code={jsonStr.replace(/\\n/g, '\n')} />
|
||||
{/if}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
@@ -1,36 +1,132 @@
|
||||
<script lang="ts">
|
||||
import { ChevronRightSquare, ClipboardCopy, Download, Expand } from 'lucide-svelte'
|
||||
import ArgInfo from './ArgInfo.svelte'
|
||||
import { Skeleton } from './common'
|
||||
import { Button, Drawer, DrawerContent, Skeleton } from './common'
|
||||
import TableCustom from './TableCustom.svelte'
|
||||
import Portal from 'svelte-portal'
|
||||
import { Highlight } from 'svelte-highlight'
|
||||
import { copyToClipboard } from '$lib/utils'
|
||||
import { json, r } from 'svelte-highlight/languages'
|
||||
|
||||
export let args: any
|
||||
export let tableClass = ''
|
||||
|
||||
let jsonViewer: Drawer
|
||||
let runLocally: Drawer
|
||||
let jsonStr = ''
|
||||
|
||||
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>
|
||||
|
||||
<TableCustom class="py-2 {tableClass}">
|
||||
<tr slot="header-row">
|
||||
<th>Argument</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tbody slot="body">
|
||||
{#if args && Object.keys(args).length > 0}
|
||||
{#each Object.entries(args) as [arg, value]}
|
||||
<div class="relative">
|
||||
<div class="text-gray-500 text-xs absolute top-8 right-0">
|
||||
<button
|
||||
on:click={() => {
|
||||
jsonStr = JSON.stringify(args, null, 4)
|
||||
jsonViewer.openDrawer()
|
||||
}}><Expand size={18} /></button
|
||||
>
|
||||
</div>
|
||||
<TableCustom class="py-2 {tableClass}">
|
||||
<tr slot="header-row">
|
||||
<th>Argument</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
<tbody slot="body">
|
||||
{#if args && Object.keys(args).length > 0}
|
||||
{#each Object.entries(args) as [arg, value]}
|
||||
<tr>
|
||||
<td class="font-semibold">{arg}</td>
|
||||
<td><ArgInfo {value} /></td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:else if args}
|
||||
<tr><div class="text-gray-600 pt-2 pl-1 text-sm">No arguments</div></tr>
|
||||
{:else}
|
||||
<tr>
|
||||
<td class="font-semibold">{arg}</td>
|
||||
<td><ArgInfo {value} /></td>
|
||||
<td>
|
||||
<Skeleton layout={[[3], 0.5, [3]]} />
|
||||
</td>
|
||||
<td>
|
||||
<Skeleton layout={[[3], 0.5, [3]]} />
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:else if args}
|
||||
<tr><div class="text-gray-600 pt-2 pl-1 text-sm">No arguments</div></tr>
|
||||
{:else}
|
||||
<tr>
|
||||
<td>
|
||||
<Skeleton layout={[[3], 0.5, [3]]} />
|
||||
</td>
|
||||
<td>
|
||||
<Skeleton layout={[[3], 0.5, [3]]} />
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</tbody>
|
||||
</TableCustom>
|
||||
{/if}
|
||||
</tbody>
|
||||
</TableCustom>
|
||||
</div>
|
||||
|
||||
<Portal>
|
||||
<Drawer bind:this={jsonViewer} size="900px">
|
||||
<DrawerContent title="Expanded Args" on:close={jsonViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
<a
|
||||
class="text-sm text-gray-600 mr-2 inline-flex gap-2 items-center py-2 px-2 hover:bg-gray-100 rounded-lg"
|
||||
download="windmill-args.json"
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(jsonStr)}"
|
||||
>Download <Download size={14} /></a
|
||||
>
|
||||
<Button on:click={runLocally.openDrawer} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Use in a local script<ChevronRightSquare /> </div>
|
||||
</Button>
|
||||
<Button on:click={() => copyToClipboard(jsonStr)} color="light" size="xs">
|
||||
<div class="flex gap-2 items-center">Copy to clipboard <ClipboardCopy /> </div>
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
{#if jsonStr.length > 100000}
|
||||
<div class="text-sm mb-2 text-gray-600">
|
||||
<a
|
||||
download="windmill-args.json"
|
||||
href="data:text/json;charset=utf-8,{encodeURIComponent(jsonStr)}">Download</a
|
||||
>
|
||||
JSON is too large to be displayed in full.
|
||||
</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>
|
||||
</Portal>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
async function loadVersion() {
|
||||
try {
|
||||
const res = await SettingsService.backendUptodate()
|
||||
console.log(res)
|
||||
if (res != 'yes') {
|
||||
uptodate = res
|
||||
}
|
||||
|
||||
@@ -233,8 +233,8 @@
|
||||
</svelte:fragment>
|
||||
</ActionRow>
|
||||
<CenteredPage>
|
||||
<h1 class="flex flex-row flex-wrap justify-between items-center gap-4 py-6">
|
||||
<div>
|
||||
<h1 class="flex flex-row flex-wrap justify-between items-center gap-x-4 py-6">
|
||||
<div class="flex flex-row flex-wrap gap-6 items-center">
|
||||
{#if job}
|
||||
{#if 'success' in job && job.success}
|
||||
{#if job.is_skipped}
|
||||
@@ -282,22 +282,29 @@
|
||||
/>
|
||||
{/if}
|
||||
{job.script_path ?? (job.job_kind == 'dependencies' ? 'lock dependencies' : 'No path')}
|
||||
{#if job.script_hash}
|
||||
<a href="/scripts/get/{job.script_hash}?$workspaceStore={$workspaceStore}}"
|
||||
><Badge color="gray">{truncateHash(job.script_hash)}</Badge></a
|
||||
>
|
||||
{/if}
|
||||
{#if job && 'job_kind' in job}<Badge baseClass="ml-2" color="blue">{job.job_kind}</Badge>
|
||||
{/if}
|
||||
{#if job.tag && !['deno', 'python3', 'flow', 'other', 'go', 'bash', 'other', 'dependency'].includes(job.tag)}
|
||||
<Badge color="indigo">Worker group: {job.tag}</Badge>
|
||||
{/if}
|
||||
{#if !job.visible_to_owner}<Badge color="red"
|
||||
>only visible to you <Tooltip
|
||||
>The option to hide this run from the owner of this script or flow was activated</Tooltip
|
||||
></Badge
|
||||
>
|
||||
{/if}
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
{#if job.script_hash}
|
||||
<a href="/scripts/get/{job.script_hash}?workspace={$workspaceStore}"
|
||||
><Badge color="gray">{truncateHash(job.script_hash)}</Badge></a
|
||||
>
|
||||
{/if}
|
||||
{#if job && 'job_kind' in job}
|
||||
<div>
|
||||
<Badge color="blue">{job.job_kind}</Badge>
|
||||
</div>
|
||||
{/if}
|
||||
{#if job.tag && !['deno', 'python3', 'flow', 'other', 'go', 'bash', 'other', 'dependency'].includes(job.tag)}
|
||||
<div>
|
||||
<Badge color="indigo">Worker group: {job.tag}</Badge>
|
||||
</div>
|
||||
{/if}
|
||||
{#if !job.visible_to_owner}<Badge color="red"
|
||||
>only visible to you <Tooltip
|
||||
>The option to hide this run from the owner of this script or flow was activated</Tooltip
|
||||
></Badge
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</h1>
|
||||
@@ -308,11 +315,11 @@
|
||||
{/if}
|
||||
|
||||
<!-- Arguments and actions -->
|
||||
<div class="flex flex-col mr-2 sm:mr-0 sm:grid sm:grid-cols-3 sm:gap-5">
|
||||
<div class="flex flex-col mr-2 sm:mr-0 sm:grid sm:grid-cols-3 sm:gap-10">
|
||||
<div class="col-span-2">
|
||||
<JobArgs args={job?.args} />
|
||||
</div>
|
||||
<div>
|
||||
<div class="mt-6">
|
||||
<Skeleton loading={!job} layout={[[9.5]]} />
|
||||
{#if job}<FlowMetadata {job} />{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user