UX improvements

This commit is contained in:
Ruben Fiszel
2022-12-04 01:02:33 +01:00
parent e4839e21ff
commit e7e79bbaf7
10 changed files with 174 additions and 126 deletions
+6 -2
View File
@@ -818,7 +818,11 @@ async fn push_next_flow_job(
InputTransform::Static { value } => value,
InputTransform::Javascript { expr } => eval_timeout(
expr.to_string(),
[("result".to_string(), last_result.clone())].into(),
[
("flow_input".to_string(), flow_input),
("result".to_string(), last_result.clone()),
]
.into(),
None,
None,
"".to_string(),
@@ -835,7 +839,7 @@ async fn push_next_flow_job(
n.as_u64().map(|x| from_now(Duration::from_secs(x)))
}
_ => Err(Error::ExecutionErr(format!(
"Expected an array value, found: {json_value}"
"Expected a number value, found: {json_value}"
)))?,
}
} else {
+46 -44
View File
@@ -165,50 +165,52 @@
</div>
</Pane>
<Pane size={40} minSize={10}>
<Splitpanes horizontal>
<Pane size={33}>
<div class="w-full border-b p-2 text-xs font-bold">Preview</div>
<div class="px-2">
<div class="break-words relative font-sans">
<SchemaForm compact {schema} bind:args bind:isValid />
<div class="flex flex-col h-full">
<div class="px-2 w-full border-b py-1">
{#if testIsLoading}
<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}
<Button
on:click={runTest}
btnClasses="w-full"
size="xs"
startIcon={{
icon: faPlay,
classes: 'animate-none'
}}
>
{#if testIsLoading}Running{:else}Test <Kbd class="ml-4 text-5xs -my-0.5">Ctrl+Enter</Kbd
>{/if}
</Button>
{/if}
</div>
<Splitpanes horizontal>
<Pane size={33}>
<div class="px-2">
<div class="break-words relative font-sans">
<SchemaForm compact {schema} bind:args bind:isValid />
</div>
</div>
</div>
</Pane>
<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">
<WindmillIcon
white={true}
class="animate-[spin_5s_linear_infinite] mr-2 text-white"
height="20px"
width="20px"
/>
Cancel
</Button>
{:else}
<Button
on:click={runTest}
btnClasses="w-full"
size="xs"
startIcon={{
icon: faPlay,
classes: 'animate-none'
}}
>
{#if testIsLoading}Running{:else}Test <Kbd class="ml-4 text-5xs">Ctrl+Enter</Kbd>{/if}
</Button>
{/if}
</div>
<LogPanel
{path}
{lang}
previewJob={testJob}
{pastPreviews}
previewIsLoading={testIsLoading}
bind:lastSave
/>
</Pane>
</Splitpanes>
</Pane>
<Pane size={67}>
<LogPanel
{path}
{lang}
previewJob={testJob}
{pastPreviews}
previewIsLoading={testIsLoading}
bind:lastSave
/>
</Pane>
</Splitpanes>
</div>
</Pane>
</SplitPanesWrapper>
@@ -11,6 +11,7 @@
import FlowCard from '../common/FlowCard.svelte'
import type { FlowEditorContext } from '../types'
import FlowModuleEarlyStop from './FlowModuleEarlyStop.svelte'
import FlowModuleSleep from './FlowModuleSleep.svelte'
import FlowModuleSuspend from './FlowModuleSuspend.svelte'
// import FlowRetries from './FlowRetries.svelte'
@@ -117,7 +118,8 @@
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop</Tab>
<Tab value="suspend">Sleep/Suspend</Tab>
<Tab value="suspend">Suspend</Tab>
<Tab value="sleep">Sleep</Tab>
<svelte:fragment slot="content">
<div class="overflow-hidden bg-white">
@@ -135,7 +137,12 @@
<TabContent value="suspend" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSuspend previousModuleId={previousModule?.id} bind:flowModule />
<FlowModuleSuspend bind:flowModule />
</div>
</TabContent>
<TabContent value="sleep" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSleep previousModuleId={previousModule?.id} bind:flowModule />
</div>
</TabContent>
</div>
@@ -15,6 +15,7 @@
import { getStepPropPicker } from '../previousResults'
import { flowStateStore } from '../flowState'
import { flowStore } from '../flowStore'
import FlowModuleSleep from './FlowModuleSleep.svelte'
const { previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
@@ -98,7 +99,8 @@
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop</Tab>
<Tab value="suspend">Sleep/Suspend</Tab>
<Tab value="suspend">Suspend</Tab>
<Tab value="sleep">Sleep</Tab>
<svelte:fragment slot="content">
<div class="overflow-hidden bg-white" style="height:calc(100% - 32px);">
@@ -116,7 +118,12 @@
<TabContent value="suspend" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSuspend previousModuleId={previousModule?.id} bind:flowModule={mod} />
<FlowModuleSuspend bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="sleep" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSleep previousModuleId={previousModule?.id} bind:flowModule={mod} />
</div>
</TabContent>
</div>
@@ -25,6 +25,7 @@
import Button from '$lib/components/common/button/Button.svelte'
import Alert from '$lib/components/common/alert/Alert.svelte'
import FlowModuleSleep from './FlowModuleSleep.svelte'
const { selectedId, previewArgs } = getContext<FlowEditorContext>('FlowEditorContext')
@@ -56,7 +57,7 @@
$: stepPropPicker = failureModule
? {
pickableProperties: {
flow_input: $flowStateStore.previewArgs,
flow_input: $previewArgs,
priorIds: {},
previousId: undefined
},
@@ -221,7 +222,8 @@
<Tab value="advanced-retries">Retries</Tab>
{#if !$selectedId.includes('failure')}
<Tab value="advanced-early-stop">Early Stop</Tab>
<Tab value="advanced-suspend">Sleep/Suspend</Tab>
<Tab value="advanced-suspend">Suspend</Tab>
<Tab value="advanced-sleep">Sleep</Tab>
<Tab value="advanced-same_worker">Same Worker/Shared dir</Tab>
{/if}
</Tabs>
@@ -231,7 +233,11 @@
<FlowModuleEarlyStop bind:flowModule class="px-4 pb-4 h-full overflow-auto" />
{:else if selected === 'advanced-suspend'}
<div class="px-4 pb-4 h-full overflow-auto">
<FlowModuleSuspend previousModuleId={previousModule?.id} bind:flowModule />
<FlowModuleSuspend bind:flowModule />
</div>
{:else if selected === 'advanced-sleep'}
<div class="px-4 pb-4 h-full overflow-auto">
<FlowModuleSleep previousModuleId={previousModule?.id} bind:flowModule />
</div>
{:else if selected === 'advanced-same_worker'}
<div class="p-4 h-full overflow-auto">
@@ -0,0 +1,80 @@
<script lang="ts">
import InputTransformForm from '$lib/components/InputTransformForm.svelte'
import type SimpleEditor from '$lib/components/SimpleEditor.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import type { FlowModule } from '$lib/gen'
import { emptySchema } from '$lib/utils'
import { getContext } from 'svelte'
import { flowStateStore } from '../flowState'
import PropPickerWrapper from '../propPicker/PropPickerWrapper.svelte'
import type { FlowEditorContext } from '../types'
export let flowModule: FlowModule
export let previousModuleId: string | undefined
const { selectedId } = getContext<FlowEditorContext>('FlowEditorContext')
let schema = emptySchema()
schema.properties['sleep'] = {
type: 'number',
description: 'Sleep time in seconds'
}
let editor: SimpleEditor | undefined = undefined
const result = $flowStateStore[$selectedId]?.previewResult ?? {}
$: isSleepEnabled = Boolean(flowModule.sleep)
</script>
<h2 class="mt-2"
>Sleep<Tooltip>
If defined, at the end of the step, the flow will sleep for a number of seconds before
scheduling the next job (if any, no effect if the step is the last one). Sleeping is passive and
does not consume any resources.</Tooltip
></h2
>
<Toggle
checked={isSleepEnabled}
on:change={() => {
if (isSleepEnabled && flowModule.sleep != undefined) {
flowModule.sleep = undefined
} else {
flowModule.sleep = {
type: 'static',
value: 0
}
}
}}
options={{
right: 'Sleep after module successful execution'
}}
/>
<div>
<span class="text-xs font-bold">Sleep for duration (seconds)</span>
{#if flowModule.sleep && schema.properties['sleep']}
<div class="border">
<PropPickerWrapper
notSelectable
{result}
displayContext={false}
pickableProperties={undefined}
on:select={({ detail }) => {
editor?.insertAtCursor(detail)
}}
>
<InputTransformForm
bind:arg={flowModule.sleep}
argName="sleep"
{schema}
{previousModuleId}
/>
</PropPickerWrapper>
</div>
{:else}
<input type="number" disabled />
{/if}
</div>
@@ -1,20 +1,11 @@
<script lang="ts">
import InputTransformForm from '$lib/components/InputTransformForm.svelte'
import type SimpleEditor from '$lib/components/SimpleEditor.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import type { FlowModule } from '$lib/gen'
import { emptySchema } from '$lib/utils'
import { getContext } from 'svelte'
import { flowStateStore } from '../flowState'
import PropPickerWrapper from '../propPicker/PropPickerWrapper.svelte'
import type { FlowEditorContext } from '../types'
export let flowModule: FlowModule
export let previousModuleId: string | undefined
const { selectedId } = getContext<FlowEditorContext>('FlowEditorContext')
let schema = emptySchema()
schema.properties['sleep'] = {
@@ -22,19 +13,15 @@
description: 'Sleep time in seconds'
}
let editor: SimpleEditor | undefined = undefined
const result = $flowStateStore[$selectedId]?.previewResult ?? {}
$: isSuspendEnabled = Boolean(flowModule.suspend)
$: isSleepEnabled = Boolean(flowModule.sleep)
</script>
<h2 class="mt-2"
>Suspend<Tooltip>
If defined, at the end of the step, the flow will be suspended until it receives external
requests to be resumed or canceled. This is most useful to implement approval steps but can be
used flexibly for other purpose. To get the resume urls, use `wmill.getResumeEndpoints`.</Tooltip
used flexibly for other purpose. To get the resume urls, use `wmill.getResumeUrls()` in
Typescript, or `wmill.get_resume_urls()` in Python.</Tooltip
></h2
>
<Toggle
@@ -50,11 +37,11 @@
}
}}
options={{
right: 'Suspend flow execution until approvals received'
right: 'Suspend flow execution until events/approvals received'
}}
/>
<div class="mb-4">
<span class="text-xs font-bold">Number of approvals required for resuming flow</span>
<span class="text-xs font-bold">Number of approvals/events required for resuming flow</span>
{#if flowModule.suspend}
<input bind:value={flowModule.suspend.required_events} type="number" min="1" placeholder="1" />
@@ -70,53 +57,3 @@
<input type="number" disabled />
{/if}
</div>
<h2 class="mt-4"
>Sleep<Tooltip>
If defined, at the end of the step, the flow will sleep for a number of seconds before
scheduling the next job (if any, no effect if the step is the last one). Sleeping is passive and
does not consume any resources.</Tooltip
></h2
>
<Toggle
checked={isSleepEnabled}
on:change={() => {
if (isSleepEnabled && flowModule.sleep != undefined) {
flowModule.sleep = undefined
} else {
flowModule.sleep = {
type: 'static',
value: 0
}
}
}}
options={{
right: 'Sleep after module successful execution'
}}
/>
<div>
<span class="text-xs font-bold">Sleep for duration (seconds)</span>
{#if flowModule.sleep && schema.properties['sleep']}
<div class="border">
<PropPickerWrapper
notSelectable
{result}
displayContext={false}
pickableProperties={undefined}
on:select={({ detail }) => {
editor?.insertAtCursor(detail)
}}
>
<InputTransformForm
bind:arg={flowModule.sleep}
argName="sleep"
{schema}
{previousModuleId}
/>
</PropPickerWrapper>
</div>
{:else}
<input type="number" disabled />
{/if}
</div>
@@ -9,7 +9,6 @@
onSelect: SelectCallback
}
writable
export type PropPickerWrapperContext = {
propPickerConfig: Writable<PropPickerConfig | undefined>
focusProp: (propName: string, insertionMode: InsertionMode, onSelect: SelectCallback) => void
@@ -55,7 +54,15 @@
</Pane>
<Pane minSize={20} size={40} class="py-2 relative !transition-none">
{#if result}
<PropPickerResult {result} />
<PropPickerResult
{result}
on:select={({ detail }) => {
dispatch('select', detail)
if ($propPickerConfig?.onSelect(detail)) {
propPickerConfig.set(undefined)
}
}}
/>
{:else if pickableProperties}
<PropPicker
{displayContext}
@@ -1,12 +1,10 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import ObjectViewer from './ObjectViewer.svelte'
export let result: any
</script>
<div class="w-full">
<div class="w-full px-2">
<span class="font-bold text-sm">Result</span>
<div class="overflow-y-auto mb-2 w-full">
<ObjectViewer json={{ result }} on:select />
+1 -1
View File
@@ -96,7 +96,7 @@
<CenteredPage>
{#if $workspaceStore == 'demo'}
<div class="my-4" />
<Alert title="Demo workspace">All uers get an invitation to this workspace.</Alert>
<Alert title="Demo workspace">All users get an invitation to this workspace.</Alert>
{:else if $workspaceStore == 'starter'}
<div class="my-4" />