improve webhooks for UX

This commit is contained in:
Ruben Fiszel
2022-11-04 21:19:29 +01:00
parent 15ca49ca18
commit 587b16e34e
8 changed files with 113 additions and 56 deletions
+25 -11
View File
@@ -7,6 +7,7 @@
import { workspaceStore } from '$lib/stores'
import Drawer from './common/drawer/Drawer.svelte'
import { DrawerContent } from './common'
import ObjectViewer from './propertyPicker/ObjectViewer.svelte'
export let value: any
let jsonViewer: Drawer
@@ -20,11 +21,9 @@
jsonViewerContent = (await ResourceService.getResource({ workspace: $workspaceStore!, path }))
.value
}
$: asJson = JSON.stringify(value, null, 4)
</script>
<Drawer bind:this={jsonViewer} size="400px">
<Drawer bind:this={jsonViewer} size="800px">
<DrawerContent title="See JSON" on:close={jsonViewer.toggleDrawer}>
<Highlight language={json} code={JSON.stringify(jsonViewerContent, null, 4)} />
</DrawerContent>
@@ -42,14 +41,29 @@
await getResource(value.substring('$res:'.length))
jsonViewer.toggleDrawer()
}}>{value}</button
>{:else if asJson.length > 40}
{truncate(asJson, 40)}<a
href="#json"
on:click|preventDefault={() => {
jsonViewerContent = value
jsonViewer.toggleDrawer()
}}>(+)</a
>
{:else if typeof value !== 'object'}
{truncate(value, 40)}
{#if JSON.stringify(value).length > 40}
<button
class="text-xs text-blue-500"
on:click={() => {
jsonViewerContent = value
jsonViewer.toggleDrawer()
}}>See expanded</button
>
{/if}
{:else}
{asJson}
<div class="max-h-40 overflow-auto">
<ObjectViewer pureViewer={true} json={value} />
</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}
+2 -2
View File
@@ -16,8 +16,8 @@
{#if job && job.args && Object.keys(job.args).length > 0}
{#each Object.entries(job.args) as [arg, value]}
<tr>
<td>{arg}</td>
<td> <ArgInfo {value} /></td>
<td class="font-semibold">{arg}</td>
<td><ArgInfo {value} /></td>
</tr>
{/each}
{:else if job}
@@ -21,6 +21,7 @@
} from '@fortawesome/free-solid-svg-icons'
import Icon from 'svelte-awesome'
import { check } from 'svelte-awesome/icons'
import { Badge } from '../common'
const SMALL_ICON_SCALE = 0.7
@@ -95,19 +96,12 @@
{/if}
</div>
<div class="whitespace-nowrap">
{#if job.script_hash}
<a href="/scripts/get/{job.script_hash}" class="commit-hash"
>{truncateHash(job.script_hash ?? '')}</a
{#if 'job_kind' in job}<a href="/run/{job.id}"
><Badge color="blue">{job.job_kind}</Badge></a
>
{/if}
{#if 'job_kind' in job && job.job_kind != 'script'}<span
class="bg-blue-200 text-gray-700 text-xs rounded px-1 whitespace-nowrap"
><a href="/run/{job.id}">{job.job_kind}</a></span
>
{:else if job.is_flow_step}
<span class="bg-blue-200 text-gray-700 text-xs rounded px-1 "
><a href="/run/{job.parent_job}">step of flow</a></span
>
{#if (job.is_flow_step && job.job_kind == 'script') || job.job_kind == 'preview'}
<a href="/run/{job.parent_job}"><Badge color="gray">flow step</Badge></a>
{/if}
</div>
</div>
@@ -14,6 +14,7 @@
export let pureViewer = false
export let collapsed = level == 3 || Array.isArray(json)
export let rawKey = false
export let topBrackets = false
const collapsedSymbol = '...'
let keys: string | any[]
@@ -44,12 +45,13 @@
{#if level != 0}
<span class="cursor-pointer hover:bg-gray-200 px-1 rounded" on:click={collapse}> (-) </span>
{/if}
{#if level == 0 && topBrackets}<span class="h-0">{openBracket}</span>{/if}
<ul class="w-full">
{#each keys as key, index}
<li class="pt-1">
<button
on:click={() => selectProp(key)}
class="key font-normal rounded px-1 hover:bg-blue-100"
class="key {pureViewer ? 'cursor-auto' : ''} font-normal rounded px-1 hover:bg-blue-100"
>
{!isArray ? key : index}:
</button>
@@ -65,7 +67,9 @@
/>
{:else}
<button
class="val rounded px-1 hover:bg-blue-100 {getTypeAsString(json[key])}"
class="val {pureViewer
? 'cursor-auto'
: ''} rounded px-1 hover:bg-blue-100 {getTypeAsString(json[key])}"
on:click={() => selectProp(key)}
>
{#if json[key] === NEVER_TESTED_THIS_FAR}
@@ -80,6 +84,7 @@
</li>
{/each}
</ul>
{#if level == 0 && topBrackets}<span class="h-0">{closeBracket}</span>{/if}
</span>
<span
class="cursor-pointer hover:bg-gray-200 {level == 0 ? 'ml-2' : ''}"
+48 -19
View File
@@ -14,7 +14,8 @@
canWrite,
sendUserToast,
defaultIfEmptyString,
flowToHubUrl
flowToHubUrl,
copyToClipboard
} from '$lib/utils'
import {
faPlay,
@@ -24,7 +25,8 @@
faCalendar,
faShare,
faGlobe,
faCodeFork
faCodeFork,
faClipboard
} from '@fortawesome/free-solid-svg-icons'
import Tooltip from '$lib/components/Tooltip.svelte'
@@ -37,7 +39,10 @@
import CenteredPage from '$lib/components/CenteredPage.svelte'
import FlowViewer from '$lib/components/FlowViewer.svelte'
import ObjectViewer from '$lib/components/propertyPicker/ObjectViewer.svelte'
import { Button, ActionRow, Skeleton } from '$lib/components/common'
import { Button, ActionRow, Skeleton, Badge } from '$lib/components/common'
import UserSettings from '$lib/components/UserSettings.svelte'
let userSettings: UserSettings
let flow: Flow | undefined
let schedule: Schedule | undefined
@@ -87,8 +92,12 @@
flow = await FlowService.getFlowByPath({ workspace: $workspaceStore!, path })
can_write = canWrite(flow.path, flow.extra_perms!, $userStore)
}
$: url = `${$page.url.hostname}/api/w/${$workspaceStore}/jobs/run/f/${flow?.path}`
</script>
<UserSettings bind:this={userSettings} />
<Skeleton
class="!max-w-6xl !px-4 sm:!px-6 md:!px-8"
loading={!flow}
@@ -200,10 +209,11 @@
<p class="text-sm text-gray-600"
>Edited {displayDaysAgo(flow.edited_at ?? '')} by {flow.edited_by}</p
>
<h2>{flow.summary}</h2>
<div class="prose">
<SvelteMarkdown source={defaultIfEmptyString(flow.description, 'No description')} />
<div>
<h2 class="font-bold mb-2">{flow.summary}</h2>
<div class="prose">
<SvelteMarkdown source={defaultIfEmptyString(flow.description, 'No description')} />
</div>
</div>
{#if schedule}
<div>
@@ -242,19 +252,38 @@
</div>
{/if}
<div>
<span>Webhook to run this flow:</span>
<Tooltip
>Send a POST http request with a token as bearer token and the args respecting the
corresponding jsonschema as payload. To create a permanent token, go to your user setting
by clicking your username on the top-left.</Tooltip
>
<pre
><code
><a href="/api/w/{$workspaceStore}/jobs/run/f/{flow?.path}"
>/api/w/{$workspaceStore}/jobs/run/f/{flow?.path}</a
></code
></pre
<h3 class="text-lg mb-1 font-bold text-gray-600"
>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
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
>
<div class="max-w-lg border border-blue-200 p-4">
<div class="flex flex-row gap-x-2">
<a
href={$page.url.protocol + '//' + url}
class="whitespace-nowrap text-ellipsis overflow-hidden mr-1"
>
{url}
</a>
<Button
on:click={() => copyToClipboard($page.url.protocol + '//' + url)}
color="blue"
size="xs"
startIcon={{ icon: faClipboard }}
btnClasses="ml-2"
>
Copy
</Button>
</div>
<div class="flex flex-row-reverse mt-2">
<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>
+9 -9
View File
@@ -37,6 +37,7 @@
import JobArgs from '$lib/components/JobArgs.svelte'
import FlowProgressBar from '$lib/components/flows/FlowProgressBar.svelte'
import Tabs from '$lib/components/common/tabs/Tabs.svelte'
import Badge from '$lib/components/common/badge/Badge.svelte'
let workspace_id_query: string | undefined = $page.url.searchParams.get('workspace') ?? undefined
let workspace_id: string | undefined
@@ -206,14 +207,11 @@
{/if}
{job.script_path ?? (job.job_kind == 'dependencies' ? 'lock dependencies' : 'No path')}
{#if job.script_hash}
<a
href="/scripts/get/{job.script_hash}"
class="text-2xs text-gray-500 bg-gray-100 font-mono">{truncateHash(job.script_hash)}</a
<a href="/scripts/get/{job.script_hash}"
><Badge color="gray">{truncateHash(job.script_hash)}</Badge></a
>
{/if}
{#if job && 'job_kind' in job}<span
class="bg-blue-200 text-gray-700 text-xs rounded px-1 mx-3">{job.job_kind}</span
>
{#if job && 'job_kind' in job}<Badge color="blue">{job.job_kind}</Badge>
{/if}
{/if}
</div>
@@ -255,9 +253,11 @@
<Tabs bind:selected={viewTab}>
<Tab value="result">Result</Tab>
<Tab value="logs">Logs</Tab>
<Tab value="code"
>{job?.job_kind == 'dependencies' ? 'Input Dependencies' : 'Code previewed'}</Tab
>
{#if job?.job_kind == 'dependencies'}
<Tab value="code">Dependencies</Tab>
{:else if job?.job_kind == 'preview'}
<Tab value="code">Code</Tab>
{/if}
</Tabs>
<Skeleton loading={!job} layout={[[5]]} />
@@ -19,7 +19,6 @@
import Tab from '$lib/components/common/tabs/Tab.svelte'
import JobDetail from '$lib/components/jobs/JobDetail.svelte'
import { Skeleton } from '$lib/components/common'
import Tooltip from '../../lib/components/Tooltip.svelte'
import { goto } from '$app/navigation'
import PageHeader from '$lib/components/PageHeader.svelte'
@@ -43,7 +43,9 @@
import HighlightCode from '$lib/components/HighlightCode.svelte'
import { Badge, Tabs, Tab, TabContent, Button, ActionRow } from '$lib/components/common'
import Skeleton from '../../../lib/components/common/skeleton/Skeleton.svelte'
import UserSettings from '$lib/components/UserSettings.svelte'
let userSettings: UserSettings
let script: Script | undefined
let topHash: string | undefined
let can_write = false
@@ -128,6 +130,8 @@
})
</script>
<UserSettings bind:this={userSettings} />
<Skeleton {loading} class="!px-4 sm:!px-6 md:!px-8 !max-w-6xl" layout={[0.75, [2, 0, 2], 1]} />
{#if script}
<ActionRow applyPageWidth stickToTop>
@@ -326,7 +330,16 @@
<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</h3>
<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">
@@ -363,6 +376,9 @@
</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>