mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-22 00:01:34 +00:00
24f9115dc0
* Add note component
* save note size and position
* move add note button up
* nit
* Add markdown support
* wip
* fix add sticky note button
* fix text update
* Add sticky note to saved flow data
* add note color picker
* Introduce node multiselect
* Add group notes
* Adapt layout to group node
* create a note manager class
* clean reactivity
* clean
* improve adaptive layout to group note
* modify layout based on cached text height
* fined grained graph rendering for notes
* separate noteManager into editor and render
* separate noteManager into editor and render
* create a note change observer
* render note node from context
* simplify note state managment
* show note in flow viewer
* clean dirty changes
* clean selection manager
* fix layout check
* improve bg surface select
* Handle z-index for stacked group notes
* clean selection manager
* exclude notes from rect select
* Allow switch between selection modes with keyboard keys
* improve selection box styling
* prevent dragging note when editing
* nit
* Simplify selection using svelte flow built in feature
* handle note selection separately
* Add min size for notes
* improve selection toggle
* improve mode switch
* make size and position optional for group notes
* Improve initial viewport position
* Add context menu for the canevas
* nit
* Add node context menu
* improve note select
* use clickoutside for note deselect
* use pointerdown outside to close context menu
* nit
* fix selection issues
* make edges non selectable
* improve color palette
* fix backend
* fix backend check
* cargo lock restore
* Add toggle to display notes
* fix note selection
* nit
* account for css offset in for loop
* fix multiple selection pannel styling
* clear flow selection when creating note
* Improve placeholder and note default text
* Escape note edit mode when pressing Esc
* Allow note edition in local dev
* clean
* Handle subflow selection
* prevent group note resizing
* nit
* allow notes in flow expand
* Improve multi select panel
* Allow context menu in note mode
* Add event listenner to fix pane click deselect
* prevent zoom in text area in notes
* improve bounding box styling
* Use control for box selection for non mac users
* nit
* clean notes groups
* nit
* use portal for note actions
* handle assets node when computing note layout
* Simplify layout compute for notes
* use smart color choice for notes
* Switch display note when adding a new note
* clean code
* improve group note bound size calculation
* simplify AI tool nodes and asset handling
* nit
* nit
* improve flow centering
* create group note button
* Improve selection of nodes
* Revert "Improve selection of nodes"
This reverts commit d2c40d82b1.
* refert backend changes
* nit
* improve graph selection
* clean
* make backend work except job runs
* fix notSelectable
---------
Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
173 lines
5.2 KiB
Svelte
173 lines
5.2 KiB
Svelte
<script lang="ts">
|
|
import { getContext } from 'svelte'
|
|
import type { FlowEditorContext } from '../types'
|
|
import FlowModuleWrapper from './FlowModuleWrapper.svelte'
|
|
import FlowSettings from './FlowSettings.svelte'
|
|
import FlowInput from './FlowInput.svelte'
|
|
import FlowFailureModule from './FlowFailureModule.svelte'
|
|
import FlowEnvironmentVariables from './FlowEnvironmentVariables.svelte'
|
|
import type { FlowModule, Flow, Job } from '$lib/gen'
|
|
import FlowPreprocessorModule from './FlowPreprocessorModule.svelte'
|
|
import type { TriggerContext } from '$lib/components/triggers'
|
|
import { insertNewPreprocessorModule } from '../flowStateUtils.svelte'
|
|
import TriggersEditor from '../../triggers/TriggersEditor.svelte'
|
|
import { handleSelectTriggerFromKind, type Trigger } from '$lib/components/triggers/utils'
|
|
import { computeMissingInputWarnings } from '../missingInputWarnings'
|
|
import FlowResult from './FlowResult.svelte'
|
|
import type { StateStore } from '$lib/utils'
|
|
import FlowSelectionPanel from './FlowSelectionPanel.svelte'
|
|
|
|
interface Props {
|
|
noEditor?: boolean
|
|
enableAi?: boolean
|
|
newFlow?: boolean
|
|
disabledFlowInputs?: boolean
|
|
savedFlow?:
|
|
| (Flow & {
|
|
draft?: Flow | undefined
|
|
})
|
|
| undefined
|
|
onDeployTrigger?: (trigger: Trigger) => void
|
|
forceTestTab?: Record<string, boolean>
|
|
highlightArg?: Record<string, string | undefined>
|
|
onTestFlow?: (conversationId?: string) => Promise<string | undefined>
|
|
job?: Job
|
|
isOwner?: boolean
|
|
suspendStatus?: StateStore<Record<string, { job: Job; nb: number }>>
|
|
onOpenDetails?: () => void
|
|
previewOpen?: boolean
|
|
}
|
|
|
|
let {
|
|
noEditor = false,
|
|
enableAi = false,
|
|
newFlow = false,
|
|
disabledFlowInputs = false,
|
|
savedFlow = undefined,
|
|
onDeployTrigger = () => {},
|
|
forceTestTab,
|
|
highlightArg,
|
|
onTestFlow,
|
|
job,
|
|
isOwner,
|
|
suspendStatus,
|
|
onOpenDetails,
|
|
previewOpen = false
|
|
}: Props = $props()
|
|
|
|
const {
|
|
selectionManager,
|
|
flowStore,
|
|
flowStateStore,
|
|
flowInputsStore,
|
|
pathStore,
|
|
initialPathStore,
|
|
fakeInitialPath,
|
|
previewArgs,
|
|
flowInputEditorState
|
|
} = getContext<FlowEditorContext>('FlowEditorContext')
|
|
|
|
const selectedId = $derived(selectionManager.getSelectedId())
|
|
|
|
const { showCaptureHint, triggersState, triggersCount } =
|
|
getContext<TriggerContext>('TriggerContext')
|
|
function checkDup(modules: FlowModule[]): string | undefined {
|
|
let seenModules: string[] = []
|
|
for (const m of modules) {
|
|
if (seenModules.includes(m.id)) {
|
|
console.error(`Duplicate module id: ${m.id}`)
|
|
return m.id
|
|
}
|
|
seenModules.push(m.id)
|
|
}
|
|
}
|
|
|
|
$effect(() => {
|
|
computeMissingInputWarnings(flowStore, flowStateStore.val, flowInputsStore)
|
|
})
|
|
</script>
|
|
|
|
{#if selectionManager && selectionManager.selectedIds.length > 1}
|
|
<FlowSelectionPanel {selectionManager} {noEditor} />
|
|
{:else if selectedId?.startsWith('settings')}
|
|
<FlowSettings {enableAi} {noEditor} />
|
|
{:else if selectedId === 'Input'}
|
|
<FlowInput
|
|
{noEditor}
|
|
disabled={disabledFlowInputs}
|
|
on:openTriggers={(ev) => {
|
|
selectionManager.selectId('Trigger')
|
|
handleSelectTriggerFromKind(triggersState, triggersCount, savedFlow?.path, ev.detail.kind)
|
|
showCaptureHint.set(true)
|
|
}}
|
|
on:applyArgs
|
|
{onTestFlow}
|
|
{previewOpen}
|
|
/>
|
|
{:else if selectedId === 'Result'}
|
|
<FlowResult {noEditor} {job} {isOwner} {suspendStatus} {onOpenDetails} />
|
|
{:else if selectedId === 'constants'}
|
|
<FlowEnvironmentVariables {noEditor} />
|
|
{:else if selectedId === 'failure'}
|
|
<FlowFailureModule {noEditor} savedModule={savedFlow?.value.failure_module} />
|
|
{:else if selectedId === 'preprocessor'}
|
|
<FlowPreprocessorModule {noEditor} savedModule={savedFlow?.value.preprocessor_module} />
|
|
{:else if selectedId === 'Trigger'}
|
|
<TriggersEditor
|
|
on:applyArgs
|
|
on:addPreprocessor={async () => {
|
|
await insertNewPreprocessorModule(flowStore, flowStateStore, {
|
|
language: 'bun'
|
|
})
|
|
selectionManager.selectId('preprocessor')
|
|
}}
|
|
on:updateSchema={(e) => {
|
|
const { payloadData, redirect } = e.detail
|
|
if (payloadData) {
|
|
previewArgs.val = JSON.parse(JSON.stringify(payloadData))
|
|
}
|
|
if (redirect) {
|
|
selectionManager.selectId('Input')
|
|
$flowInputEditorState.selectedTab = 'captures'
|
|
$flowInputEditorState.payloadData = payloadData
|
|
}
|
|
}}
|
|
on:testWithArgs
|
|
currentPath={$pathStore}
|
|
initialPath={$initialPathStore}
|
|
{fakeInitialPath}
|
|
{noEditor}
|
|
newItem={newFlow}
|
|
isFlow={true}
|
|
hasPreprocessor={!!flowStore.val.value.preprocessor_module}
|
|
canHavePreprocessor={true}
|
|
args={previewArgs.val}
|
|
isDeployed={savedFlow && !savedFlow?.draft_only}
|
|
schema={flowStore.val.schema}
|
|
{onDeployTrigger}
|
|
/>
|
|
{:else if selectedId?.startsWith('subflow:')}
|
|
<div class="p-4"
|
|
>Selected step is witin an expanded subflow and is not directly editable in the flow editor</div
|
|
>
|
|
{:else}
|
|
{@const dup = checkDup(flowStore.val.value.modules)}
|
|
{#if dup}
|
|
<div class="text-red-600 text-xl p-2">There are duplicate modules in the flow at id: {dup}</div>
|
|
{:else}
|
|
{#key selectedId}
|
|
{#each flowStore.val.value.modules as flowModule, index (flowModule.id ?? index)}
|
|
<FlowModuleWrapper
|
|
{noEditor}
|
|
bind:flowModule={flowStore.val.value.modules[index]}
|
|
previousModule={flowStore.val.value.modules[index - 1]}
|
|
{enableAi}
|
|
savedModule={savedFlow?.value.modules[index]}
|
|
{forceTestTab}
|
|
{highlightArg}
|
|
/>
|
|
{/each}
|
|
{/key}
|
|
{/if}
|
|
{/if}
|