Files
windmill/frontend/src/lib/components/graph/renderers/nodes/ModuleNode.svelte
T
Guilhem cec2fac7e4 feat(frontend): run test flow from graph (#6122)
* migrate FlowPreviewContent to svelte 5

* run background preview from input panel

* share local run test

* Show approval in graph is testing in graph

* use component and props instead of portal for approval in graph

* Add a toggle to show module status in graph

* open module result after each run

* Fix module reactivity issue

* Add test flow button

* Extract preview run logic from flowPreviewContent

* Revert "Extract preview run logic from flowPreviewContent"

This reverts commit a39c70a920.

* nit

* lazy load preview content

* create component for flow preview button

* open preview v0

* open preview v1

* connect open preview button

* improve graph run display

* enable cancel preview

* Run test flow from input panel

* nit

* wip

* Use global context instead of module context for moduleTestState

* nit

* fix flow preview rendering

* Add testJob to modulesTest context

* update module status based on individual test data

* fix: clear job status on run preview

* detatch run buttons from input node

* move preview job in FlowEditorContext

* move outputPickerOpenFns to FlowEditorContext

* add result panel

* Add result output picker

* add status to loops and branch

* add open detail button to result panel

* fix test up to

* clean unnecessary binding

* clean

* Make iteration annotation smaller in editmode

* detatch test button to and aproval from node

* prevent flow edition during execution

* Prevent step test run during flow run

* Show approval in graph edges

* prevent opening output popover if node is outside the graph

* fix pointerdownOutside action

* fix test up to dropdown not closing

* fix test up to

* nit

* change job status badge display

* fix running status

* Enable test flow in Dev

* fix darkmode

* fix node panel display in Dev

* fix test flow button positionning

* fix suspend in subflows

* improve lazy load of preview

* prevent preview data unmount on close drawer

* clean code

* move flowjob into flow context

* Revert "move flowjob into flow context"

This reverts commit 939e9dbaaf.

* clean context

* nit

* fix dark mode status view

* fix test button alignment

* clean job status on deleted step

* fix retry bad status display

* Detect flow change

* Update frontend/src/lib/components/flows/header/FlowPreviewButtons.svelte

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>

---------

Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
2025-07-09 16:24:03 +00:00

129 lines
3.5 KiB
Svelte

<script lang="ts">
import { preventDefault, stopPropagation } from 'svelte/legacy'
import MapItem from '$lib/components/flows/map/MapItem.svelte'
import { GitBranchPlus, Maximize2 } from 'lucide-svelte'
import NodeWrapper from './NodeWrapper.svelte'
import { getStateColor, getStateHoverColor } from '../../util'
import type { ModuleN } from '../../graphBuilder.svelte'
interface Props {
data: ModuleN['data']
}
let { data }: Props = $props()
let moduleState = $derived(data.flowModuleStates?.[data.id])
let flowJobs = $derived(
moduleState?.flow_jobs
? {
flowJobs: moduleState?.flow_jobs,
selected: moduleState?.selectedForloopIndex ?? 0,
selectedManually: moduleState?.selectedForLoopSetManually,
flowJobsSuccess: moduleState?.flow_jobs_success
}
: (undefined as any)
)
let type = $derived.by(() => {
let typ = data.flowModuleStates?.[data.id]?.type
if (!typ && flowJobs) {
return 'InProgress'
}
return typ
})
</script>
<NodeWrapper offset={data.offset}>
{#snippet children({ darkMode })}
{#if data.module.value.type == 'flow'}
<button
title="Expand subflow"
class="z-50 absolute -top-[10px] right-[25px] rounded-full h-[20px] w-[20px] center-center text-primary bg-surface duration-0 hover:bg-surface-hover"
onclick={stopPropagation(
preventDefault(() => {
if (data.module.value.type == 'flow') {
data.eventHandlers.expandSubflow(data.id, data.module.value.path)
}
})
)}
>
<Maximize2 size={12} />
</button>
{/if}
<MapItem
moduleId={data.id}
mod={data.module}
insertable={data.insertable}
editMode={data.editMode}
annotation={flowJobs &&
(data.module.value.type === 'forloopflow' || data.module.value.type === 'whileloopflow')
? 'Iteration: ' +
((moduleState?.selectedForloopIndex ?? 0) >= 0
? (moduleState?.selectedForloopIndex ?? 0) + 1
: moduleState?.flow_jobs?.length) +
'/' +
(moduleState?.iteration_total ?? '?')
: ''}
bgColor={getStateColor(
data.editMode ? undefined : type,
darkMode,
true,
moduleState?.skipped
)}
bgHoverColor={getStateHoverColor(
data.editMode ? undefined : type,
darkMode,
true,
moduleState?.skipped
)}
moving={data.moving}
duration_ms={moduleState?.duration_ms}
retries={moduleState?.retries}
{flowJobs}
on:delete={(e) => {
data.eventHandlers.delete(e.detail, '')
}}
on:changeId={(e) => {
data.eventHandlers.changeId(e.detail)
}}
on:move={(e) => {
data.eventHandlers.move({ id: data.id })
}}
on:newBranch={(e) => {
data.eventHandlers.newBranch(data.id)
}}
onSelect={(e) => {
setTimeout(() => e && data.eventHandlers.select(e))
}}
onSelectedIteration={(e) => {
data.eventHandlers.selectedIteration(e)
}}
onTestUpTo={data.eventHandlers.testUpTo}
onUpdateMock={(detail) => {
data.eventHandlers.updateMock(detail)
}}
onEditInput={data.eventHandlers.editInput}
flowJob={data.flowJob}
isOwner={data.isOwner}
{type}
{darkMode}
skipped={moduleState?.skipped}
/>
<div class="absolute -bottom-10 left-1/2 transform -translate-x-1/2 z-10">
{#if (data.module.value.type === 'branchall' || data.module.value.type === 'branchone') && data.insertable}
<button
title="Add branch"
class="rounded text-secondary border hover:bg-surface-hover bg-surface p-1"
onclick={() => {
data?.eventHandlers?.newBranch(data.id)
}}
>
<GitBranchPlus size={16} />
</button>
{/if}
</div>
{/snippet}
</NodeWrapper>