mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-19 08:03:16 +00:00
script and flow details UX improvements
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
let preview: string[] = []
|
||||
let cronError = ''
|
||||
export let schedule: string = '0 0 12 * *'
|
||||
export let disabled = false
|
||||
let limit = 3
|
||||
|
||||
$: handleScheduleInput(schedule)
|
||||
@@ -44,28 +45,31 @@
|
||||
id="cron-schedule"
|
||||
name="cron-schedule"
|
||||
bind:value={schedule}
|
||||
{disabled}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row text-xs text-blue-500 gap-3 pl-28">
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 */15 * * *'
|
||||
cronError = ''
|
||||
}}>every 15 min</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 0 * * * *'
|
||||
cronError = ''
|
||||
}}>every hour</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 0 8 * * *'
|
||||
cronError = ''
|
||||
}}>once a day at 8AM</button
|
||||
>
|
||||
</div>
|
||||
{#if !disabled}
|
||||
<div class="flex flex-row text-xs text-blue-500 gap-3 pl-28">
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 */15 * * *'
|
||||
cronError = ''
|
||||
}}>every 15 min</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 0 * * * *'
|
||||
cronError = ''
|
||||
}}>every hour</button
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
schedule = '0 0 8 * * *'
|
||||
cronError = ''
|
||||
}}>once a day at 8AM</button
|
||||
>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<CollapseLink text="preview next runs" open={true}>
|
||||
{#if preview && preview.length > 0}
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
<script lang="ts">
|
||||
import type { Job } from '$lib/gen'
|
||||
import ArgInfo from './ArgInfo.svelte'
|
||||
import { Skeleton } from './common'
|
||||
import TableCustom from './TableCustom.svelte'
|
||||
|
||||
export let job: Job | undefined
|
||||
export let args: any
|
||||
</script>
|
||||
|
||||
<TableCustom class="px-10 py-4">
|
||||
<TableCustom class="px-10 py-2">
|
||||
<tr slot="header-row"
|
||||
><th>Argument</th>
|
||||
<th>Value</th></tr
|
||||
>
|
||||
<tbody slot="body">
|
||||
{#if job && job.args && Object.keys(job.args).length > 0}
|
||||
{#each Object.entries(job.args) as [arg, value]}
|
||||
{#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 job}
|
||||
{:else if args}
|
||||
<tr>No arguments</tr>
|
||||
{:else}
|
||||
<tr>
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
</div>
|
||||
<h2 class="mt-4">Flow arguments</h2>
|
||||
|
||||
<JobArgs {job} />
|
||||
<JobArgs args={job?.args} />
|
||||
<div class="mt-8">
|
||||
{#if approver}
|
||||
<p>Dis/approving as: <b>{approver}</b></p>
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
import ObjectViewer from '$lib/components/propertyPicker/ObjectViewer.svelte'
|
||||
import { Button, ActionRow, Skeleton, Badge } from '$lib/components/common'
|
||||
import UserSettings from '$lib/components/UserSettings.svelte'
|
||||
import ArgInput from '$lib/components/ArgInput.svelte'
|
||||
import JobArgs from '$lib/components/JobArgs.svelte'
|
||||
import CronInput from '$lib/components/CronInput.svelte'
|
||||
|
||||
let userSettings: UserSettings
|
||||
|
||||
@@ -215,36 +218,6 @@
|
||||
<SvelteMarkdown source={defaultIfEmptyString(flow.description, 'No description')} />
|
||||
</div>
|
||||
</div>
|
||||
{#if schedule}
|
||||
<div>
|
||||
<h2 class="text-gray-700 pb-1 mb-3 border-b">Primary Schedule</h2>
|
||||
<div>
|
||||
<h3 class="text-gray-700 ">Enabled</h3>
|
||||
<Toggle
|
||||
checked={schedule.enabled}
|
||||
on:change={(e) => {
|
||||
if (can_write) {
|
||||
setScheduleEnabled(path, e.detail)
|
||||
} else {
|
||||
sendUserToast('not enough permission', true)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<h3 class="text-gray-700">Schedule</h3>
|
||||
<span class="font-mono p-1 border" class:bg-gray-300={!schedule.enabled}
|
||||
>{schedule.schedule}</span
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-gray-700 ">Args</h3>
|
||||
<ObjectViewer json={schedule.args ?? {}} pureViewer={true} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if flow.archived}
|
||||
<div class="bg-red-100 border-l-4 border-red-500 text-orange-700 p-4" role="alert">
|
||||
<p class="font-bold">Archived</p>
|
||||
@@ -252,7 +225,10 @@
|
||||
</div>
|
||||
{/if}
|
||||
<div>
|
||||
<h3 class="text-lg mb-1 font-bold text-gray-600"
|
||||
<h2 class="text-gray-700 pb-1 mb-3 border-b">Flow</h2>
|
||||
<FlowViewer {flow} />
|
||||
|
||||
<h2 class="my-4 text-gray-700 pb-1 mb-3 border-b"
|
||||
>Webhook<Tooltip
|
||||
>To trigger this script with a webhook, do a POST request to the endpoint below. Flows
|
||||
are not public and can only be run by users with at least view rights on them. You will
|
||||
@@ -260,7 +236,7 @@
|
||||
token or as query arg `?token=XXX`. <a
|
||||
href="https://docs.windmill.dev/docs/getting_started/webhooks">See docs</a
|
||||
></Tooltip
|
||||
></h3
|
||||
></h2
|
||||
>
|
||||
<div class="box max-w-2xl">
|
||||
<div class="flex flex-row gap-x-2 w-full">
|
||||
@@ -284,10 +260,33 @@
|
||||
<Button size="xs" on:click={userSettings.toggleDrawer}>Create token</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-gray-700 pb-1 mb-3 border-b">Flow</h2>
|
||||
<FlowViewer {flow} />
|
||||
{#if schedule}
|
||||
<div class="mt-8">
|
||||
<h2 class="text-gray-700 pb-1 mb-3 border-b inline-flex flex-row items-center gap-x-4"
|
||||
><div>Primary Schedule </div>
|
||||
<Badge color="gray">{schedule.schedule}</Badge>
|
||||
<Toggle
|
||||
checked={schedule.enabled}
|
||||
on:change={(e) => {
|
||||
if (can_write) {
|
||||
setScheduleEnabled(path, e.detail)
|
||||
} else {
|
||||
sendUserToast('not enough permission', true)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button size="xs" href="/schedule/add?edit={flow.path}&isFlow=true"
|
||||
>Edit schedule</Button
|
||||
>
|
||||
</h2>
|
||||
<div class="max-w-lg">
|
||||
<JobArgs args={schedule.args ?? {}} />
|
||||
</div>
|
||||
<div class="box max-w-lg mt-2">
|
||||
<CronInput disabled={true} schedule={schedule.schedule} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
<!-- Arguments and actions -->
|
||||
<div class="flex flex-col mr-2 sm:mr-0 sm:grid sm:grid-cols-3 sm:gap-5">
|
||||
<div class="col-span-2">
|
||||
<JobArgs {job} />
|
||||
<JobArgs args={job?.args} />
|
||||
|
||||
{#if job?.job_kind == 'flow' || job?.job_kind == 'flowpreview'}
|
||||
<div class="mt-10" />
|
||||
|
||||
@@ -328,89 +328,6 @@
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<div class="flex flex-col lg:flex-row gap-4">
|
||||
<div class="lg:w-1/2">
|
||||
<h3 class="text-lg mb-1 font-bold text-gray-600"
|
||||
>Webhooks<Tooltip
|
||||
>To trigger this script with a webhook, do a POST request to the endpoints below.
|
||||
Scripts are not public and can only be run by users with at least view rights on them.
|
||||
You will need to pass a bearer token to authentify as a user. You can either pass it as
|
||||
a Bearer token or as query arg `?token=XXX`. <a
|
||||
href="https://docs.windmill.dev/docs/getting_started/webhooks">See docs</a
|
||||
></Tooltip
|
||||
></h3
|
||||
>
|
||||
<Skeleton {loading} layout={[[8.5]]} />
|
||||
{#if script}
|
||||
<div class="box">
|
||||
<Tabs selected="uuid">
|
||||
<Tab value="uuid">UUID</Tab>
|
||||
<Tab value="result">Result</Tab>
|
||||
<svelte:fragment slot="content">
|
||||
{#each Object.keys(webhooks) as key}
|
||||
<TabContent value={key}>
|
||||
<ul>
|
||||
{#each Object.keys(webhooks[key]) as type}
|
||||
{@const url = webhooks[key][type]}
|
||||
<li class="flex justify-between items-center mt-2">
|
||||
<a
|
||||
href={$page.url.protocol + '//' + url}
|
||||
class="whitespace-nowrap text-ellipsis overflow-hidden mr-1"
|
||||
>
|
||||
{url}
|
||||
</a>
|
||||
<div class="flex">
|
||||
<Badge color="dark-gray" capitalize>
|
||||
{type}
|
||||
</Badge>
|
||||
<Button
|
||||
on:click={() => copyToClipboard($page.url.protocol + '//' + url)}
|
||||
color="blue"
|
||||
size="xs"
|
||||
startIcon={{ icon: faClipboard }}
|
||||
btnClasses="ml-2"
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<div class="flex flex-row-reverse mt-2">
|
||||
<Button size="xs" on:click={userSettings.toggleDrawer}>Create token</Button>
|
||||
</div>
|
||||
</TabContent>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
</Tabs>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="lg:w-1/2">
|
||||
<h3 class="text-lg mb-1 font-bold text-gray-600">Versions</h3>
|
||||
<Skeleton {loading} layout={[[8.5]]} />
|
||||
{#if script}
|
||||
<div class="box">
|
||||
<h4 class="font-bold text-gray-500">Current</h4>
|
||||
<div class="mt-1">
|
||||
{script?.hash}
|
||||
</div>
|
||||
<h4 class="font-bold text-gray-500 mt-2">Previous</h4>
|
||||
{#if script?.parent_hashes?.length}
|
||||
<ul class="max-h-20 overflow-y-auto">
|
||||
{#each script.parent_hashes as hash}
|
||||
<li class="mt-1">
|
||||
<a href="/scripts/get/{hash}">{hash}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{:else}
|
||||
<p class="text-sm text-gray-500">There are no previous versions</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<h2 class="text-lg mb-1 font-bold text-gray-600">
|
||||
Arguments JSON schema
|
||||
@@ -433,16 +350,99 @@
|
||||
<HighlightCode language={script.language} code={script.content} />
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-lg mb-1 font-bold text-gray-600 border-b">Dependencies lock file</h2>
|
||||
<Skeleton {loading} layout={[[5]]} />
|
||||
</div>
|
||||
<div class="flex flex-col lg:flex-row gap-4 mt-8">
|
||||
<div class="lg:w-1/2">
|
||||
<h3 class="text-lg mb-1 font-bold text-gray-600"
|
||||
>Webhooks<Tooltip
|
||||
>To trigger this script with a webhook, do a POST request to the endpoints below. Scripts
|
||||
are not public and can only be run by users with at least view rights on them. You will
|
||||
need to pass a bearer token to authentify as a user. You can either pass it as a Bearer
|
||||
token or as query arg `?token=XXX`. <a
|
||||
href="https://docs.windmill.dev/docs/getting_started/webhooks">See docs</a
|
||||
></Tooltip
|
||||
></h3
|
||||
>
|
||||
<Skeleton {loading} layout={[[8.5]]} />
|
||||
{#if script}
|
||||
{#if script?.lock}
|
||||
<pre class="text-xs">{script.lock}</pre>
|
||||
{:else}
|
||||
<p class="text-sm text-gray-500">There is no lock file for this script</p>
|
||||
{/if}
|
||||
<div class="box">
|
||||
<Tabs selected="uuid">
|
||||
<Tab value="uuid">UUID</Tab>
|
||||
<Tab value="result">Result</Tab>
|
||||
<svelte:fragment slot="content">
|
||||
{#each Object.keys(webhooks) as key}
|
||||
<TabContent value={key}>
|
||||
<ul>
|
||||
{#each Object.keys(webhooks[key]) as type}
|
||||
{@const url = webhooks[key][type]}
|
||||
<li class="flex justify-between items-center mt-2">
|
||||
<a
|
||||
href={$page.url.protocol + '//' + url}
|
||||
class="whitespace-nowrap text-ellipsis overflow-hidden mr-1"
|
||||
>
|
||||
{url}
|
||||
</a>
|
||||
<div class="flex">
|
||||
<Badge color="dark-gray" capitalize>
|
||||
{type}
|
||||
</Badge>
|
||||
<Button
|
||||
on:click={() => copyToClipboard($page.url.protocol + '//' + url)}
|
||||
color="blue"
|
||||
size="xs"
|
||||
startIcon={{ icon: faClipboard }}
|
||||
btnClasses="ml-2"
|
||||
>
|
||||
Copy
|
||||
</Button>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
<div class="flex flex-row-reverse mt-2">
|
||||
<Button size="xs" on:click={userSettings.toggleDrawer}>Create token</Button>
|
||||
</div>
|
||||
</TabContent>
|
||||
{/each}
|
||||
</svelte:fragment>
|
||||
</Tabs>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="lg:w-1/2">
|
||||
<h3 class="text-lg mb-1 font-bold text-gray-600">Versions</h3>
|
||||
<Skeleton {loading} layout={[[8.5]]} />
|
||||
{#if script}
|
||||
<div class="box">
|
||||
<h4 class="font-bold text-gray-500">Current</h4>
|
||||
<div class="mt-1">
|
||||
{script?.hash}
|
||||
</div>
|
||||
<h4 class="font-bold text-gray-500 mt-2">Previous</h4>
|
||||
{#if script?.parent_hashes?.length}
|
||||
<ul class="max-h-20 overflow-y-auto">
|
||||
{#each script.parent_hashes as hash}
|
||||
<li class="mt-1">
|
||||
<a href="/scripts/get/{hash}">{hash}</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{:else}
|
||||
<p class="text-sm text-gray-500">There are no previous versions</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h2 class="text-lg mb-1 font-bold text-gray-600 border-b mt-8">Dependencies lock file</h2>
|
||||
<Skeleton {loading} layout={[[5]]} />
|
||||
{#if script}
|
||||
{#if script?.lock}
|
||||
<pre class="text-xs">{script.lock}</pre>
|
||||
{:else}
|
||||
<p class="text-sm text-gray-500">There is no lock file for this script</p>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</CenteredPage>
|
||||
|
||||
Reference in New Issue
Block a user