mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 16:02:19 +00:00
feat(frontend): fill schema and test args from payload
This commit is contained in:
Generated
+11
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
||||
"@redocly/json-to-json-schema": "^0.0.1",
|
||||
"async-mutex": "^0.4.0",
|
||||
"fuse.js": "^6.4.6",
|
||||
"highlight.js": "^11.5.1",
|
||||
@@ -403,6 +404,11 @@
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@redocly/json-to-json-schema": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@redocly/json-to-json-schema/-/json-to-json-schema-0.0.1.tgz",
|
||||
"integrity": "sha512-dSMyuNPN2k+tFeNZ0+QJ7S1zDJ0UeNL+lpnPFR9K5avj2V4uG4m6FdjrApQ9Zi35AIocaDp/KGfBD9gR5MLUbQ=="
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||
@@ -6847,6 +6853,11 @@
|
||||
"dev": true,
|
||||
"peer": true
|
||||
},
|
||||
"@redocly/json-to-json-schema": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@redocly/json-to-json-schema/-/json-to-json-schema-0.0.1.tgz",
|
||||
"integrity": "sha512-dSMyuNPN2k+tFeNZ0+QJ7S1zDJ0UeNL+lpnPFR9K5avj2V4uG4m6FdjrApQ9Zi35AIocaDp/KGfBD9gR5MLUbQ=="
|
||||
},
|
||||
"@rollup/pluginutils": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
"dependencies": {
|
||||
"@fortawesome/free-brands-svg-icons": "^6.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.2.0",
|
||||
"@redocly/json-to-json-schema": "^0.0.1",
|
||||
"async-mutex": "^0.4.0",
|
||||
"fuse.js": "^6.4.6",
|
||||
"highlight.js": "^11.5.1",
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
import FlowStatusViewer from '../components/FlowStatusViewer.svelte'
|
||||
import FlowProgressBar from './flows/FlowProgressBar.svelte'
|
||||
import { flowStateStore } from './flows/flowState'
|
||||
import CapturePayload from './flows/content/CapturePayload.svelte'
|
||||
|
||||
let capturePayload: CapturePayload
|
||||
export let previewMode: 'upTo' | 'whole'
|
||||
export let open: boolean
|
||||
|
||||
@@ -89,19 +91,33 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<CapturePayload bind:this={capturePayload} />
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
|
||||
<div class="flex divide-y flex-col space-y-2 h-screen bg-white p-6 w-full">
|
||||
<div class="flex justify-between">
|
||||
<div class="flex flex-row justify-center items-center ">
|
||||
<div class="flex justify-between w-full ">
|
||||
<div class="flex flex-row justify-center items-center w-full mr-4">
|
||||
<div class="flex justify-center p-2 w-8 h-8 bg-blue-200 rounded-lg mr-2 ">
|
||||
<Icon data={faPlay} scale={1} class="text-blue-500" />
|
||||
</div>
|
||||
|
||||
<h3 class="text-lg leading-6 font-bold text-gray-900">
|
||||
Test preview - {previewMode === 'upTo'
|
||||
? `up to step ${$selectedId.split('-').join(',')}`
|
||||
: ' whole flow'}
|
||||
<h3
|
||||
class="text-lg leading-6 font-bold text-gray-900 inline-flex flex-row justify-between w-full"
|
||||
>
|
||||
<div>
|
||||
Test preview - {previewMode === 'upTo'
|
||||
? `up to step ${$selectedId.split('-').join(',')}`
|
||||
: ' whole flow'}
|
||||
</div>
|
||||
<Button
|
||||
btnClasses="ml-2"
|
||||
size="sm"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
capturePayload.openDrawer()
|
||||
}}>Fill test args from payload</Button
|
||||
>
|
||||
</h3>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
<td>
|
||||
<SchemaEditorProperty {property} />
|
||||
</td>
|
||||
<td>{property.description}</td>
|
||||
<td>{property.description ?? ''}</td>
|
||||
<td>{property.default ? JSON.stringify(property.default) : ''}</td>
|
||||
<td
|
||||
>{#if schema.required.includes(name)}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import Tab from './common/tabs/Tab.svelte'
|
||||
import TabContent from './common/tabs/TabContent.svelte'
|
||||
import Tabs from './common/tabs/Tabs.svelte'
|
||||
import { Badge } from './common'
|
||||
|
||||
export let schema: Schema | undefined = emptySchema()
|
||||
</script>
|
||||
@@ -32,11 +33,13 @@
|
||||
<tbody slot="body">
|
||||
{#each Object.entries(schema.properties) as [name, property] (name)}
|
||||
<tr>
|
||||
<td>{name}</td>
|
||||
<td class="font-semibold pl-1">{name}</td>
|
||||
<td
|
||||
>{#if !property.type} any {:else} {property.type} {/if}</td
|
||||
><Badge color="blue"
|
||||
>{#if !property.type} any {:else} {property.type} {/if}</Badge
|
||||
></td
|
||||
>
|
||||
<td>{property.description}</td>
|
||||
<td>{property.description ?? ''}</td>
|
||||
<td
|
||||
>{property.default == '<function call>'
|
||||
? '<function call>'
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { Button, Kbd } from './common'
|
||||
import SplitPanesWrapper from './splitPanes/SplitPanesWrapper.svelte'
|
||||
import Tooltip from './Tooltip.svelte'
|
||||
import WindmillIcon from './icons/WindmillIcon.svelte'
|
||||
|
||||
// Exported
|
||||
export let schema: Schema = emptySchema()
|
||||
@@ -177,16 +178,13 @@
|
||||
<Pane size={67}>
|
||||
<div class="px-2 py-1 w-full">
|
||||
{#if testIsLoading}
|
||||
<Button
|
||||
on:click={testJobLoader?.cancelJob}
|
||||
btnClasses="w-full"
|
||||
color="red"
|
||||
size="xs"
|
||||
startIcon={{
|
||||
icon: faRotateRight,
|
||||
classes: 'animate-spin'
|
||||
}}
|
||||
>
|
||||
<Button on:click={testJobLoader?.cancelJob} btnClasses="w-full" color="red" size="xs">
|
||||
<WindmillIcon
|
||||
white={true}
|
||||
class="animate-[spin_5s_linear_infinite] mr-2 text-white"
|
||||
height="20px"
|
||||
width="20px"
|
||||
/>
|
||||
Cancel
|
||||
</Button>
|
||||
{:else}
|
||||
|
||||
@@ -61,7 +61,8 @@
|
||||
'focus:ring-4 font-semibold',
|
||||
'rounded-md',
|
||||
'justify-center items-center text-center whitespace-nowrap inline-flex',
|
||||
btnClasses
|
||||
btnClasses,
|
||||
disabled ? 'bg-gray-200' : ''
|
||||
),
|
||||
disabled,
|
||||
href,
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
<svelte:window on:keydown={onKeyDown} />
|
||||
|
||||
<aside class="drawer" class:open class:close={!open} {style}>
|
||||
<aside class="drawer" class:open class:close={!open && timeout} {style}>
|
||||
<div class="overlay" on:click={handleClickAway} />
|
||||
<div class="panel {placement}" class:size>
|
||||
{#if open || !timeout}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { Button } from '$lib/components/common'
|
||||
import Drawer from '$lib/components/common/drawer/Drawer.svelte'
|
||||
import DrawerContent from '$lib/components/common/drawer/DrawerContent.svelte'
|
||||
import WindmillIcon from '$lib/components/icons/WindmillIcon.svelte'
|
||||
import ObjectViewer from '$lib/components/propertyPicker/ObjectViewer.svelte'
|
||||
|
||||
import { CaptureService } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { flowStore } from '../flowStore'
|
||||
|
||||
import { convert } from '@redocly/json-to-json-schema'
|
||||
import SchemaViewer from '$lib/components/SchemaViewer.svelte'
|
||||
import { getContext } from 'svelte'
|
||||
import type { FlowEditorContext } from '../types'
|
||||
|
||||
const { previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
|
||||
|
||||
let drawer: Drawer
|
||||
let interval: NodeJS.Timeout | undefined = undefined
|
||||
let captureInput: any | undefined = undefined
|
||||
let jsonSchema: any = undefined
|
||||
|
||||
export function openDrawer() {
|
||||
drawer.openDrawer()
|
||||
}
|
||||
|
||||
async function startCapturePoint() {
|
||||
await CaptureService.createCapture({
|
||||
workspace: $workspaceStore!,
|
||||
path: $flowStore.path
|
||||
})
|
||||
}
|
||||
|
||||
async function getCaptureInput() {
|
||||
const capture = await CaptureService.getCapture({
|
||||
workspace: $workspaceStore!,
|
||||
path: $flowStore.path
|
||||
})
|
||||
captureInput = capture
|
||||
jsonSchema = { required: [], ...convert(capture) }
|
||||
}
|
||||
</script>
|
||||
|
||||
<Drawer
|
||||
bind:this={drawer}
|
||||
on:open={() => {
|
||||
startCapturePoint()
|
||||
interval = setInterval(() => {
|
||||
getCaptureInput()
|
||||
}, 1000)
|
||||
}}
|
||||
on:close={() => interval && clearInterval(interval)}
|
||||
>
|
||||
<DrawerContent title="Capture from a request to seed inputs" on:close={drawer.closeDrawer}>
|
||||
Send a payload at: <div
|
||||
><a
|
||||
class="text-2xl"
|
||||
href="{$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/capture/{$flowStore.path}"
|
||||
>{$page.url.protocol}//{$page.url
|
||||
.hostname}/api/w/{$workspaceStore}/capture/{$flowStore.path}</a
|
||||
></div
|
||||
>
|
||||
<div class="items-center flex flex-row gap-x-2 text-xs text-gray-600">
|
||||
Listening for new payload
|
||||
<WindmillIcon
|
||||
class="animate-[pulse_5s_linear_infinite] animate-[spin_5s_linear_infinite]"
|
||||
/></div
|
||||
>
|
||||
<div class="box p-2 my-2">
|
||||
<ObjectViewer topBrackets={true} json={captureInput} />
|
||||
</div>
|
||||
<div class="flex flex-row gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
on:click={() => {
|
||||
$previewArgs = captureInput
|
||||
$flowStore.schema = jsonSchema
|
||||
}}>Copy as flow inputs and test args</Button
|
||||
>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="border"
|
||||
on:click={() => {
|
||||
$previewArgs = captureInput
|
||||
}}>Copy only as test args</Button
|
||||
>
|
||||
</div>
|
||||
<h3 class="mt-2">JSONSchema</h3>
|
||||
<div class="box p-2">
|
||||
<SchemaViewer schema={jsonSchema} />
|
||||
</div>
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
@@ -1,15 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { copyFirstStepSchema, flowStore } from '../flowStore'
|
||||
import { isEmptyFlowModule } from '../utils'
|
||||
</script>
|
||||
|
||||
<Button
|
||||
color="light"
|
||||
size="xs"
|
||||
disabled={$flowStore.value.modules.length === 0 || isEmptyFlowModule($flowStore.value.modules[0])}
|
||||
on:click={copyFirstStepSchema}
|
||||
variant="border"
|
||||
>
|
||||
Copy from first step schema
|
||||
</Button>
|
||||
@@ -1,15 +1,42 @@
|
||||
<script lang="ts">
|
||||
import { flowStore } from '$lib/components/flows/flowStore'
|
||||
import { Button } from '$lib/components/common'
|
||||
|
||||
import SchemaEditor from '$lib/components/SchemaEditor.svelte'
|
||||
import SchemaForm from '$lib/components/SchemaForm.svelte'
|
||||
import FlowCard from '../common/FlowCard.svelte'
|
||||
import { copyFirstStepSchema, flowStore } from '../flowStore'
|
||||
import { isEmptyFlowModule } from '../utils'
|
||||
import CapturePayload from './CapturePayload.svelte'
|
||||
|
||||
import CopyFirstStepSchema from './CopyFirstStepSchema.svelte'
|
||||
let capturePayload: CapturePayload
|
||||
</script>
|
||||
|
||||
<CapturePayload bind:this={capturePayload} />
|
||||
<FlowCard title="Flow Inputs">
|
||||
<div slot="header">
|
||||
<CopyFirstStepSchema />
|
||||
<div class="flex flex-row space-x-4">
|
||||
<Button
|
||||
color="light"
|
||||
size="sm"
|
||||
on:click={() => {
|
||||
capturePayload.openDrawer()
|
||||
}}
|
||||
variant="border"
|
||||
>
|
||||
Capture from a request to seed inputs
|
||||
</Button>
|
||||
<Button
|
||||
color="light"
|
||||
size="sm"
|
||||
disabled={$flowStore.value.modules.length === 0 ||
|
||||
isEmptyFlowModule($flowStore.value.modules[0])}
|
||||
on:click={copyFirstStepSchema}
|
||||
variant="border"
|
||||
>
|
||||
Copy from first step schema {#if $flowStore.value.modules.length === 0 || isEmptyFlowModule($flowStore.value.modules[0])}
|
||||
(no steps to copy from!){/if}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="p-6">
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<script lang="ts">
|
||||
export let height = '24px'
|
||||
export let width = '24px'
|
||||
export let white = false
|
||||
</script>
|
||||
|
||||
<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg
|
||||
class={$$props.class}
|
||||
version="1.1"
|
||||
id="Calque_1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -74,16 +76,19 @@
|
||||
points="134.78,14.22 114.31,48.21 101.33,69.75 158.22,69.75 177.97,36.95 191.67,14.22 "
|
||||
/>
|
||||
<polygon
|
||||
class="st3"
|
||||
class:st3={!white}
|
||||
class:st0={white}
|
||||
points="227.55,69.75 186.61,69.75 101.33,69.75 129.78,119.02 158.16,119.02 228.61,119.02 256,119.02 "
|
||||
/>
|
||||
<polygon
|
||||
class="st3"
|
||||
class:st3={!white}
|
||||
class:st0={white}
|
||||
points="136.93,132.47 116.46,167.93 73.82,241.78 130.71,241.78 144.9,217.2 180.13,156.18 193.82,132.46
|
||||
"
|
||||
/>
|
||||
<polygon
|
||||
class="st3"
|
||||
class:st3={!white}
|
||||
class:st0={white}
|
||||
points="121.7,131.95 101.23,96.49 58.59,22.63 30.15,71.91 44.34,96.49 79.57,157.5 93.26,181.22 "
|
||||
/>
|
||||
<polygon
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
import { beforeNavigate } from '$app/navigation'
|
||||
import UserSettings from '$lib/components/UserSettings.svelte'
|
||||
import SuperadminSettings from '$lib/components/SuperadminSettings.svelte'
|
||||
import WindmillIcon from '$lib/components/icons/WindmillIcon.svelte'
|
||||
|
||||
OpenAPI.WITH_CREDENTIALS = true
|
||||
|
||||
@@ -180,7 +181,7 @@
|
||||
{:else}
|
||||
<CenteredModal title="Loading user">
|
||||
<div class="mx-auto w-0">
|
||||
<Icon class="animate-spin" data={faSpinner} scale={2.0} />
|
||||
<WindmillIcon class="animate-[spin_5s_linear_infinite]" height="80px" width="80px" />
|
||||
</div>
|
||||
</CenteredModal>
|
||||
{/if}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import { faSpinner } from '@fortawesome/free-solid-svg-icons'
|
||||
import CenteredPage from '$lib/components/CenteredPage.svelte'
|
||||
import PageHeader from '$lib/components/PageHeader.svelte'
|
||||
import WindmillIcon from '$lib/components/icons/WindmillIcon.svelte'
|
||||
|
||||
let error = $page.url.searchParams.get('error')
|
||||
let code = $page.url.searchParams.get('code') ?? undefined
|
||||
@@ -33,6 +34,6 @@
|
||||
<CenteredPage>
|
||||
<PageHeader title="Connection to slack in progress" />
|
||||
<div class="mx-auto w-0">
|
||||
<Icon class="animate-spin" data={faSpinner} scale={2.0} />
|
||||
<WindmillIcon class="animate-[spin_5s_linear_infinite]" height="80px" width="80px" />
|
||||
</div>
|
||||
</CenteredPage>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import { userStore, workspaceStore } from '$lib/stores'
|
||||
import { getUserExt } from '$lib/user'
|
||||
import { logoutWithRedirect } from '$lib/logout'
|
||||
import WindmillIcon from '$lib/components/icons/WindmillIcon.svelte'
|
||||
|
||||
let error = $page.url.searchParams.get('error')
|
||||
let clientName = $page.params.client_name
|
||||
@@ -51,6 +52,6 @@
|
||||
|
||||
<CenteredModal title="Login from {clientName} in progress">
|
||||
<div class="mx-auto w-0">
|
||||
<Icon class="animate-spin" data={faSpinner} scale={2.0} />
|
||||
<WindmillIcon class="animate-[spin_5s_linear_infinite]" height="80px" width="80px" />
|
||||
</div>
|
||||
</CenteredModal>
|
||||
|
||||
Reference in New Issue
Block a user