Files
windmill/frontend/src/lib/components/flows/FlowEditor.svelte
T
Guilhem 74795bec71 Merge remote-tracking branch 'origin/main' into feat/frontend/save-flow-builder-layout
# Conflicts:
#	frontend/src/lib/components/FlowBuilder.svelte
2025-06-23 15:03:56 +01:00

135 lines
3.9 KiB
Svelte

<script lang="ts">
import FlowEditorPanel from './content/FlowEditorPanel.svelte'
import FlowModuleSchemaMap from './map/FlowModuleSchemaMap.svelte'
import WindmillIcon from '../icons/WindmillIcon.svelte'
import { Skeleton } from '../common'
import { getContext, onDestroy, onMount, setContext } from 'svelte'
import type { FlowEditorContext } from './types'
import { writable } from 'svelte/store'
import type { PropPickerContext, FlowPropPickerConfig } from '$lib/components/prop_picker'
import type { PickableProperties } from '$lib/components/flows/previousResults'
import type { Flow } from '$lib/gen'
import type { Trigger } from '$lib/components/triggers/utils'
import { Splitpanes, Pane } from '$lib/components/splitPanes/index'
import FlowAIChat from '../copilot/chat/flow/FlowAIChat.svelte'
import { aiChatManager, AIMode } from '../copilot/chat/AIChatManager.svelte'
import TriggerableByAI from '../TriggerableByAI.svelte'
const { flowStore } = getContext<FlowEditorContext>('FlowEditorContext')
interface Props {
loading: boolean
disableStaticInputs?: boolean
disableTutorials?: boolean
disableAi?: boolean
disableSettings?: boolean
disabledFlowInputs?: boolean
smallErrorHandler?: boolean
newFlow?: boolean
savedFlow?:
| (Flow & {
draft?: Flow | undefined
})
| undefined
onDeployTrigger?: (trigger: Trigger) => void
onTestUpTo?: ((id: string) => void) | undefined
onEditInput?: ((moduleId: string, key: string) => void) | undefined
forceTestTab?: Record<string, boolean>
highlightArg?: Record<string, string | undefined>
}
let {
loading,
disableStaticInputs = false,
disableTutorials = false,
disableAi = false,
disableSettings = false,
disabledFlowInputs = false,
smallErrorHandler = false,
newFlow = false,
savedFlow = undefined,
onDeployTrigger = () => {},
onTestUpTo = undefined,
onEditInput = undefined,
forceTestTab,
highlightArg
}: Props = $props()
let flowModuleSchemaMap: FlowModuleSchemaMap | undefined = $state()
setContext<PropPickerContext>('PropPickerContext', {
flowPropPickerConfig: writable<FlowPropPickerConfig | undefined>(undefined),
pickablePropertiesFiltered: writable<PickableProperties | undefined>(undefined)
})
onMount(() => {
aiChatManager.changeMode(AIMode.FLOW)
})
onDestroy(() => {
aiChatManager.changeMode(AIMode.NAVIGATOR)
})
</script>
<div
id="flow-editor"
class={'h-full overflow-hidden transition-colors duration-[400ms] ease-linear border-t'}
>
<TriggerableByAI id="flow-editor" description="Component to edit a flow" />
<Splitpanes id="flow-editor" defaultSizes={[60, 40]}>
<Pane minSize={15} class="h-full relative z-0" index={0}>
<div class="grow overflow-hidden bg-gray h-full bg-surface-secondary relative">
{#if loading}
<div class="p-2 pt-10">
{#each new Array(6) as _}
<Skeleton layout={[[2], 1.5]} />
{/each}
</div>
{:else if flowStore.val.value.modules}
<FlowModuleSchemaMap
bind:this={flowModuleSchemaMap}
{disableStaticInputs}
{disableTutorials}
{disableAi}
{disableSettings}
{smallErrorHandler}
{newFlow}
on:reload
on:generateStep={({ detail }) => {
if (!aiChatManager.open) {
aiChatManager.openChat()
}
aiChatManager.generateStep(detail.moduleId, detail.lang, detail.instructions)
}}
{onTestUpTo}
{onEditInput}
/>
{/if}
</div>
</Pane>
<Pane class="relative z-10" index={1} minSize={20}>
{#if loading}
<div class="w-full h-full">
<div class="block m-auto pt-40 w-10">
<WindmillIcon height="40px" width="40px" spin="fast" />
</div>
</div>
{:else}
<FlowEditorPanel
{disabledFlowInputs}
{newFlow}
{savedFlow}
enableAi={!disableAi}
on:applyArgs
on:testWithArgs
{onDeployTrigger}
{forceTestTab}
{highlightArg}
/>
{/if}
</Pane>
{#if !disableAi}
<FlowAIChat {flowModuleSchemaMap} />
{/if}
</Splitpanes>
</div>