fix(frontend) : handle flow card height

This commit is contained in:
Guilhem
2025-01-15 14:16:40 +01:00
parent 74385ef70b
commit e37feb8aa6
4 changed files with 297 additions and 301 deletions
@@ -86,217 +86,215 @@
/>
</Drawer>
<div class="h-full flex flex-col">
<FlowCard {noEditor} title="For loop">
<div slot="header" class="grow">
<div class="my-2 flex flex-row gap-2 items-center">
<div>
<Tooltip documentationLink="https://www.windmill.dev/docs/flows/flow_loops">
Add steps inside the loop and specify an iterator expression that defines the sequence
over which your subsequent steps will iterate.
</Tooltip>
</div>
<div class="grow">
<input bind:value={mod.summary} placeholder={'Summary'} />
</div>
<div class="justify-end">
<Button
on:click={() => (previewOpen = true)}
startIcon={{ icon: Play }}
color="dark"
size="sm">Test an iteration</Button
>
</div>
<FlowCard {noEditor} title="For loop">
<div slot="header" class="grow">
<div class="my-2 flex flex-row gap-2 items-center">
<div>
<Tooltip documentationLink="https://www.windmill.dev/docs/flows/flow_loops">
Add steps inside the loop and specify an iterator expression that defines the sequence
over which your subsequent steps will iterate.
</Tooltip>
</div>
<div class="grow">
<input bind:value={mod.summary} placeholder={'Summary'} />
</div>
<div class="justify-end">
<Button
on:click={() => (previewOpen = true)}
startIcon={{ icon: Play }}
color="dark"
size="sm">Test an iteration</Button
>
</div>
</div>
</div>
<Splitpanes horizontal class="!max-h-[calc(100%-30px)]">
<Pane size={60} minSize={20} class="p-4">
{#if mod.value.type === 'forloopflow'}
<div class="flex flex-row gap-8 mt-2 mb-6">
<div>
<div class="mb-2 text-sm font-bold"
>Skip failures <Tooltip
documentationLink="https://www.windmill.dev/docs/flows/flow_loops"
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
the error will be collected as the result of the iteration. Regardless of this
setting, if an error handler is defined, it will process the error.</Tooltip
></div
>
<Toggle
bind:checked={mod.value.skip_failures}
options={{
right: 'Skip failures'
}}
/>
</div>
<div>
<div class="mb-2 text-sm font-bold">Run in parallel</div>
<Toggle
bind:checked={mod.value.parallel}
options={{
right: 'All iterations run in parallel'
}}
/>
</div>
<div>
<div class="mb-2 text-sm font-bold"
>Parallelism <Tooltip
>Assign a maximum number of branches run in parallel to control huge for-loops.</Tooltip
>
</div>
<input
type="number"
disabled={!mod.value.parallel}
bind:value={mod.value.parallelism}
/>
</div>
</div>
<div class="my-2 flex flex-row gap-2 items-center">
<div class="text-sm font-bold whitespace-nowrap">
Iterator expression
<Tooltip documentationLink="https://www.windmill.dev/docs/flows/flow_loops">
The JavaScript expression that will be evaluated to get the list of items to iterate
over. Example : ["banana", "apple", flow_input.my_fruit].
</Tooltip>
</div>
<FlowPlugConnect
connecting={$flowPropPickerConfig?.insertionMode == CONNECT}
on:click={() => {
const config = {
insertionMode: CONNECT,
onSelect: (code) => {
setExpr(code)
return true
},
clearFocus: () => {
flowPropPickerConfig.set(undefined)
}
}
flowPropPickerConfig.set({
...config,
clearFocus: () => {
flowPropPickerConfig.set(undefined)
}
})
<Splitpanes horizontal class="h-full">
<Pane size={50} minSize={20} class="p-4">
{#if mod.value.type === 'forloopflow'}
<div class="flex flex-row gap-8 mt-2 mb-6">
<div>
<div class="mb-2 text-sm font-bold"
>Skip failures <Tooltip
documentationLink="https://www.windmill.dev/docs/flows/flow_loops"
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
the error will be collected as the result of the iteration. Regardless of this
setting, if an error handler is defined, it will process the error.</Tooltip
></div
>
<Toggle
bind:checked={mod.value.skip_failures}
options={{
right: 'Skip failures'
}}
/>
{#if enableAi}
<IteratorGen
bind:this={iteratorGen}
focused={iteratorFieldFocused}
arg={mod.value.iterator}
on:showExpr={(e) => {
editor?.setSuggestion(e.detail)
}}
on:setExpr={(e) => {
setExpr(e.detail)
}}
pickableProperties={stepPropPicker.pickableProperties}
/>
{/if}
</div>
{#if mod.value.iterator.type == 'javascript'}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="border w-full"
id="flow-editor-iterator-expression"
on:keyup={iteratorGen?.onKeyUp}
>
<PropPickerWrapper
alwaysOn
notSelectable
pickableProperties={stepPropPicker.pickableProperties}
on:select={({ detail }) => {
if ($flowPropPickerConfig?.insertionMode == CONNECT) {
setExpr(detail)
flowPropPickerConfig.set(undefined)
return
}
editor?.insertAtCursor(detail)
editor?.focus()
}}
noPadding
>
<SimpleEditor
bind:this={editor}
on:focus={() => {
iteratorFieldFocused = true
}}
on:blur={() => {
iteratorFieldFocused = false
}}
autofocus
lang="javascript"
bind:code={mod.value.iterator.expr}
class="small-editor"
shouldBindKey={false}
extraLib={stepPropPicker.extraLib}
/>
</PropPickerWrapper>
</div>
{:else}
<Button
on:click={() => {
if (mod.value.type === 'forloopflow') mod.value.iterator.type = 'javascript'
<div>
<div class="mb-2 text-sm font-bold">Run in parallel</div>
<Toggle
bind:checked={mod.value.parallel}
options={{
right: 'All iterations run in parallel'
}}
/>
</div>
<div>
<div class="mb-2 text-sm font-bold"
>Parallelism <Tooltip
>Assign a maximum number of branches run in parallel to control huge for-loops.</Tooltip
>
</div>
<input
type="number"
disabled={!mod.value.parallel}
bind:value={mod.value.parallelism}
/>
</div>
</div>
<div class="my-2 flex flex-row gap-2 items-center">
<div class="text-sm font-bold whitespace-nowrap">
Iterator expression
<Tooltip documentationLink="https://www.windmill.dev/docs/flows/flow_loops">
The JavaScript expression that will be evaluated to get the list of items to iterate
over. Example : ["banana", "apple", flow_input.my_fruit].
</Tooltip>
</div>
<FlowPlugConnect
connecting={$flowPropPickerConfig?.insertionMode == CONNECT}
on:click={() => {
const config = {
insertionMode: CONNECT,
onSelect: (code) => {
setExpr(code)
return true
},
clearFocus: () => {
flowPropPickerConfig.set(undefined)
}
}
flowPropPickerConfig.set({
...config,
clearFocus: () => {
flowPropPickerConfig.set(undefined)
}
})
}}
/>
{#if enableAi}
<IteratorGen
bind:this={iteratorGen}
focused={iteratorFieldFocused}
arg={mod.value.iterator}
on:showExpr={(e) => {
editor?.setSuggestion(e.detail)
}}
on:setExpr={(e) => {
setExpr(e.detail)
}}
pickableProperties={stepPropPicker.pickableProperties}
/>
{/if}
{/if}
</Pane>
<Pane size={40} minSize={20} class="flex flex-col flex-1">
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop/Break</Tab>
<Tab value="skip">Skip</Tab>
<Tab value="suspend">Suspend/Approval/Prompt</Tab>
<Tab value="sleep">Sleep</Tab>
<Tab value="mock">Mock</Tab>
<Tab value="lifetime">Lifetime</Tab>
</div>
<svelte:fragment slot="content">
<div class="overflow-hidden bg-surface" style="height:calc(100% - 32px);">
<!-- <TabContent value="retries" class="flex flex-col flex-1 h-full">
{#if mod.value.iterator.type == 'javascript'}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="border w-full"
id="flow-editor-iterator-expression"
on:keyup={iteratorGen?.onKeyUp}
>
<PropPickerWrapper
alwaysOn
notSelectable
pickableProperties={stepPropPicker.pickableProperties}
on:select={({ detail }) => {
if ($flowPropPickerConfig?.insertionMode == CONNECT) {
setExpr(detail)
flowPropPickerConfig.set(undefined)
return
}
editor?.insertAtCursor(detail)
editor?.focus()
}}
noPadding
>
<SimpleEditor
bind:this={editor}
on:focus={() => {
iteratorFieldFocused = true
}}
on:blur={() => {
iteratorFieldFocused = false
}}
autofocus
lang="javascript"
bind:code={mod.value.iterator.expr}
class="small-editor"
shouldBindKey={false}
extraLib={stepPropPicker.extraLib}
/>
</PropPickerWrapper>
</div>
{:else}
<Button
on:click={() => {
if (mod.value.type === 'forloopflow') mod.value.iterator.type = 'javascript'
}}
/>
{/if}
{/if}
</Pane>
<Pane size={40} minSize={20} class="flex flex-col flex-1">
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop/Break</Tab>
<Tab value="skip">Skip</Tab>
<Tab value="suspend">Suspend/Approval/Prompt</Tab>
<Tab value="sleep">Sleep</Tab>
<Tab value="mock">Mock</Tab>
<Tab value="lifetime">Lifetime</Tab>
<svelte:fragment slot="content">
<div class="overflow-hidden bg-surface" style="height:calc(100% - 32px);">
<!-- <TabContent value="retries" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowRetries bind:flowModule={mod} />
</div>
</TabContent> -->
<TabContent value="early-stop" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleEarlyStop bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="skip" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSkip bind:flowModule={mod} {parentModule} {previousModule} />
</div>
</TabContent>
<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} />
</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>
<TabContent value="mock" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleMock bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="lifetime" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleDeleteAfterUse bind:flowModule={mod} disabled={!$enterpriseLicense} />
</div>
</TabContent>
</div>
</svelte:fragment>
</Tabs>
</Pane>
</Splitpanes>
</FlowCard>
</div>
<TabContent value="early-stop" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleEarlyStop bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="skip" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSkip bind:flowModule={mod} {parentModule} {previousModule} />
</div>
</TabContent>
<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} />
</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>
<TabContent value="mock" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleMock bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="lifetime" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleDeleteAfterUse bind:flowModule={mod} disabled={!$enterpriseLicense} />
</div>
</TabContent>
</div>
</svelte:fragment>
</Tabs>
</Pane>
</Splitpanes>
</FlowCard>
@@ -380,7 +380,7 @@
/>
{#if !$enterpriseLicense}
<span
class="inline-flex text-xs text-primary items-center gap-1 !text-yellow-500 whitespace-nowrap ml-8"
class="inline-flex text-xs items-center gap-1 !text-yellow-500 whitespace-nowrap ml-8"
>
<AlertTriangle size={16} />
EE only <Tooltip>Enterprise Edition only feature</Tooltip>
@@ -501,7 +501,7 @@
/>
{#if !$enterpriseLicense || isCloudHosted()}
<span
class="inline-flex absolute top-0 left-72 text-xs text-primary items-center gap-1 !text-yellow-500 whitespace-nowrap ml-8"
class="inline-flex absolute top-0 left-72 text-xs items-center gap-1 !text-yellow-500 whitespace-nowrap ml-8"
>
<AlertTriangle size={16} />
EE only <Tooltip>Enterprise Edition only feature</Tooltip>
@@ -48,115 +48,113 @@
/>
</Drawer>
<div class="h-full flex flex-col">
<FlowCard {noEditor} title="While loop">
<div slot="header" class="grow">
<input bind:value={mod.summary} placeholder={'Summary'} />
</div>
<FlowCard {noEditor} title="While loop">
<div slot="header" class="grow">
<input bind:value={mod.summary} placeholder={'Summary'} />
</div>
<Splitpanes horizontal class="!max-h-[calc(100%-48px)]">
<Pane size={60} minSize={20} class="p-4">
{#if !noEditor}
<Alert
type="info"
title="While loops"
class="mb-4"
size="xs"
documentationLink="https://www.windmill.dev/docs/flows/while_loops"
>
Add steps inside the while loop but have one of them use early stop/break in their
Advanced settings (or do it at the loop level that will watch the last step) to break
out of the while loop (otherwise it will loop forever and you will have to cancel the
flow manually).
</Alert>
{/if}
<Splitpanes horizontal class="h-full">
<Pane size={50} minSize={20} class="p-4">
{#if !noEditor}
<Alert
type="info"
title="While loops"
class="mb-4"
size="xs"
documentationLink="https://www.windmill.dev/docs/flows/while_loops"
>
Add steps inside the while loop but have one of them use early stop/break in their
Advanced settings (or do it at the loop level that will watch the last step) to break out
of the while loop (otherwise it will loop forever and you will have to cancel the flow
manually).
</Alert>
{/if}
{#if mod.value.type === 'whileloopflow'}
<div class="flex flex-row gap-8 mt-2 mb-6">
<div>
<div class="mb-2 text-sm font-bold"
>Skip failures <Tooltip
documentationLink="https://www.windmill.dev/docs/flows/while_loops"
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
the error will be collected as the result of the iteration. Regardless of this
setting, if an error handler is defined, it will process the error.</Tooltip
></div
>
<Toggle
bind:checked={mod.value.skip_failures}
options={{
right: 'Skip failures'
}}
/>
</div>
{#if mod.value.type === 'whileloopflow'}
<div class="flex flex-row gap-8 mt-2 mb-6">
<div>
<div class="mb-2 text-sm font-bold"
>Skip failures <Tooltip
documentationLink="https://www.windmill.dev/docs/flows/while_loops"
>If disabled, the flow will fail as soon as one of the iteration fail. Otherwise,
the error will be collected as the result of the iteration. Regardless of this
setting, if an error handler is defined, it will process the error.</Tooltip
></div
>
<Toggle
bind:checked={mod.value.skip_failures}
options={{
right: 'Skip failures'
}}
/>
</div>
</div>
<div class="my-2 flex flex-row gap-2 items-center">
<div class="flex w-full justify-end">
<Button
on:click={() => (previewOpen = true)}
startIcon={{ icon: Play }}
color="dark"
size="sm">Test an iteration</Button
>
</div>
<div class="my-2 flex flex-row gap-2 items-center">
<div class="flex w-full justify-end">
<Button
on:click={() => (previewOpen = true)}
startIcon={{ icon: Play }}
color="dark"
size="sm">Test an iteration</Button
>
</div>
{/if}
</Pane>
<Pane size={40} minSize={20} class="flex flex-col flex-1">
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop/Break</Tab>
<Tab value="skip">Skip</Tab>
<Tab value="suspend">Suspend/Approval/Prompt</Tab>
<Tab value="sleep">Sleep</Tab>
<Tab value="mock">Mock</Tab>
<Tab value="lifetime">Lifetime</Tab>
</div>
{/if}
</Pane>
<Pane size={40} minSize={20} class="flex flex-col flex-1">
<Tabs bind:selected>
<!-- <Tab value="retries">Retries</Tab> -->
<Tab value="early-stop">Early Stop/Break</Tab>
<Tab value="skip">Skip</Tab>
<Tab value="suspend">Suspend/Approval/Prompt</Tab>
<Tab value="sleep">Sleep</Tab>
<Tab value="mock">Mock</Tab>
<Tab value="lifetime">Lifetime</Tab>
<svelte:fragment slot="content">
<div class="overflow-hidden bg-surface" style="height:calc(100% - 32px);">
<!-- <TabContent value="retries" class="flex flex-col flex-1 h-full">
<svelte:fragment slot="content">
<div class="overflow-hidden bg-surface" style="height:calc(100% - 32px);">
<!-- <TabContent value="retries" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowRetries bind:flowModule={mod} />
</div>
</TabContent> -->
<TabContent value="early-stop" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleEarlyStop bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="early-stop" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleEarlyStop bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="skip" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSkip bind:flowModule={mod} {parentModule} {previousModule} />
</div>
</TabContent>
<TabContent value="skip" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleSkip bind:flowModule={mod} {parentModule} {previousModule} />
</div>
</TabContent>
<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} />
</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>
<TabContent value="mock" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleMock bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="lifetime" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleDeleteAfterUse bind:flowModule={mod} disabled={!$enterpriseLicense} />
</div>
</TabContent>
</div>
</svelte:fragment>
</Tabs>
</Pane>
</Splitpanes>
</FlowCard>
</div>
<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} />
</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>
<TabContent value="mock" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleMock bind:flowModule={mod} />
</div>
</TabContent>
<TabContent value="lifetime" class="flex flex-col flex-1 h-full">
<div class="p-4 overflow-y-auto">
<FlowModuleDeleteAfterUse bind:flowModule={mod} disabled={!$enterpriseLicense} />
</div>
</TabContent>
</div>
</svelte:fragment>
</Tabs>
</Pane>
</Splitpanes>
</FlowCard>
@@ -399,7 +399,7 @@
{/if}
<Toggle
options={{
right: 'Disableds',
right: 'Disabled',
rightTooltip: 'Do not let user modify this field'
}}
lightMode