mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 16:03:21 +00:00
* feat: add flow group nodes core infrastructure Add group data model (start_id/end_id boundary pairs), GroupEditor for CRUD operations, groupDetectionUtils for membership computation and validation, GroupedModulesProxy for reactive sync, and compound layout support. Update openflow.openapi.yaml with group schema. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add group UI components and rendering Add GroupOverlay with bounding box and z-ordering, GroupHeader with StepCountTab and ellipsis menu, GroupNodeCard, GroupNoteArea for inline markdown notes, CollapsedGroupNode/CollapsedSubflowNode for collapsed rendering, GroupEndNode/GroupHeadNode boundary markers, and group actions in NodeContextMenu and SelectionBoundingBox. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: integrate groups into flow graph, builder, and existing components Wire group support into FlowGraphV2 (overlays, collapsed rendering, group-aware layout), graphBuilder (GroupedModule tree, container collapse/expand, group boundary nodes), BaseEdge (drop targets for group operations), ModuleNode (collapsed container rendering), and flow map components (schema item grouping). Remove SubflowBound in favor of CollapsedSubflowNode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove banned $bindable(default) pattern and dead ternary Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: decouple collapse state from grouped module tree Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: pass groups prop to FlowGraphV2 and use GroupDisplayState via graphContext Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove group membership system, compute nesting depth from visual bounds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: simplify GroupOverlay bounds, remove unused headerY and showNotes prop Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: populate innerNodeIds for expanded subflow overlay Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove expanded subflow overlay feature for separate PR Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: flatten groups in getContainerModules to prevent crash on collapsed containers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add drag-to-move support for group nodes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: derive group boundaries from expanded membership to prevent splitting existing groups Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: catch group validation errors and display as flow graph alert Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add unit tests for group validation in buildGroupedModules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: reject virtual nodes (Input, Result, Trigger) from groups Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add virtual node rejection tests for buildGroupedModules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: exclude preprocessor and failure module from groups Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: disable Create group button when preprocessor is selected Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: reject selection entirely when it contains excluded nodes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove unnecessary excludeIds from buildGroupedModules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: remove debug console.log from FlowGraphV2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use cross-browser CSS grid trick for group summary input auto-sizing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: hide group boundary edges and reformat GroupNoteArea Hide edges between group header and first node, and between last node and group-end, keeping them in the DOM but visually hidden. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: stop FlowGraphV2 from reading groups via groupEditorContext Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: show module previews with status, selection, and suspend popover in collapsed groups Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: extract collapsible implicit containers to separate branch Remove collapse/expand functionality for implicit containers (forloops, while loops, branches) from this branch. Backed up as collapsible-implicit-containers-backup for later rebase. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: use original reactive modules for graph node data instead of proxy snapshots Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: prevent node loss when moving into forloop inside a group Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: replace GroupedModule proxy with structure-only FlowStructureNode tree Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use "group-" prefix for group IDs instead of "note-" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update group boundaries when renaming a module ID When a module at a group boundary (start_id or end_id) is renamed, the group definitions now get updated before the reactive rebuild, preventing stale references that would break the flow structure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: update graph layout when removing a group note Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add opaque background behind test run button to prevent see-through Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: detect and reject duplicate group IDs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: simplify group creation validation with early marker normalization Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: use $state.raw in MiniFlowGraph to avoid xyflow performance warning Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: address code review feedback - Revert backend traverse_modules change (not part of this feature) - Use Map for node lookup in GroupOverlay (O(1) vs O(n) per group) - Extract computeNodeExtraSpace to nodeExtraSpace.ts for testability Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: address PR review feedback - Compute group depths from structure tree O(n) instead of O(n²) bounds comparison - Remove unnecessary $derived(groups) in GroupOverlay - Remove unused collapsed field from container types in OpenAPI spec - Use NODE.width constant in GroupNodeCard instead of hardcoded 275px - Add comment explaining intentional stale preservation in rebuild() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: preserve flow groups during dependency job re-serialization Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: resolve Svelte state_referenced_locally warnings in GroupHeader and FlowGraphV2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: show subflow groups when expanding a subflow in the graph - Store both modules and groups when expanding a subflow - Pass groups to buildStructureTree so group nodes render - Include subflow groups in overlay rendering and collapse tracking - Clone modules for prefix rewriting to avoid state_unsafe_mutation - Register expanded subflow modules in moduleMap before prefix rewriting - Disable group editing in expanded subflows and read-only views Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: restore accidentally removed code from main - Restore subflowBound selection handling in selectionUtils - Restore comments in SelectionBoundingBox - Restore deletable={false} in FirstStepInputs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove redundant adjacency check from MoveManager The disableMoveIds check already prevents all invalid drop targets, making the adjacencySourceId/adjacencyTargetId fields unnecessary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate auto-generated files after OpenAPI schema change Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate cli skills after main merge Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: include groups in view_graph localStorage state Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: centralize canCreateGroup and replace group note with group creation - Add canCreateGroup StateStore to GroupEditorContext, computed in FlowGraphV2 - Replace "Create group note" with "Create group" in FlowSelectionPanel - Remove "Add note" from selection bounding box dropdown - Remove unused NodeContextMenu component - Wire createGroup through FlowModuleSchemaMap → FlowGraphV2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: reject groups spanning parallel branches and surface ill-formed group errors Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate auto-generated files after main merge Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: ensure modules appears before groups in YAML export Svelte 5's $state proxy registers groups as a tracked property before it's explicitly set, causing it to appear before modules in Object.keys iteration. Reorder the value object at export time for readable YAML. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: address second round of PR review feedback - Add comment explaining duplicateMultiple bypasses structure tree - Add warning log for inverted ranges in computeGroupModuleIds - Use NODE.width constant in CollapsedGroupNode instead of hardcoded 275px - Simplify redundant condition in getGroupsEmptiedBy Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: remove stored group ID, derive ephemeral key from start_id:end_id Groups no longer store an `id` field. Instead, a `groupKey(g)` helper derives an ephemeral key from `${start_id}:${end_id}` at read time. This simplifies the schema while preserving all runtime functionality. When boundaries shift (module deletion), runtime state (collapse, note heights) is remapped to the new key via GroupDisplayState.remapGroupKey. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add note button, save/cancel hints, and rename collapsed_by_default to autocollapse Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: propagate selection from collapsed group badges to external listeners Pass eventHandlers to GroupModuleIcons so clicking a module badge calls both selectionManager.selectId (visual highlight) and eventHandlers.select (side panel propagation via onSelect). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: regenerate auto-generated files after main merge Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: hide In/Out popovers and actions during click-to-move Replace isDragging with isMoving derived that covers both drag-move and click-move states, disabling popovers, delete button, and test run button during any move operation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
124 lines
3.7 KiB
Svelte
124 lines
3.7 KiB
Svelte
<script lang="ts">
|
|
import { writable } from 'svelte/store'
|
|
import {
|
|
SvelteFlow,
|
|
SvelteFlowProvider,
|
|
type Node,
|
|
type Edge,
|
|
type Viewport
|
|
} from '@xyflow/svelte'
|
|
import { setGraphContext } from './graphContext'
|
|
import { SelectionManager } from './selectionUtils.svelte'
|
|
import { createFlowDiffManager } from '../flows/flowDiffManager.svelte'
|
|
|
|
import ModuleNode from './renderers/nodes/ModuleNode.svelte'
|
|
import InputNode from './renderers/nodes/InputNode.svelte'
|
|
import BranchAllStart from './renderers/nodes/BranchAllStart.svelte'
|
|
import BranchAllEndNode from './renderers/nodes/BranchAllEndNode.svelte'
|
|
import ForLoopEndNode from './renderers/nodes/ForLoopEndNode.svelte'
|
|
import ForLoopStartNode from './renderers/nodes/ForLoopStartNode.svelte'
|
|
import ResultNode from './renderers/nodes/ResultNode.svelte'
|
|
import BranchOneStart from './renderers/nodes/BranchOneStart.svelte'
|
|
import BranchOneEndNode from './renderers/nodes/branchOneEndNode.svelte'
|
|
import SubflowBound from './renderers/nodes/SubflowBound.svelte'
|
|
import NoBranchNode from './renderers/nodes/NoBranchNode.svelte'
|
|
import AssetNode from './renderers/nodes/AssetNode.svelte'
|
|
import AssetsOverflowedNode from './renderers/nodes/AssetsOverflowedNode.svelte'
|
|
import AiToolNode from './renderers/nodes/AIToolNode.svelte'
|
|
import NewAiToolNode from './renderers/nodes/NewAIToolNode.svelte'
|
|
import CollapsedGroupNode from './renderers/nodes/CollapsedGroupNode.svelte'
|
|
import GroupHeadNode from './renderers/nodes/GroupHeadNode.svelte'
|
|
import GroupEndNode from './renderers/nodes/GroupEndNode.svelte'
|
|
import BaseEdge from './renderers/edges/BaseEdge.svelte'
|
|
import EmptyEdge from './renderers/edges/EmptyEdge.svelte'
|
|
import DataflowEdge from './renderers/edges/DataflowEdge.svelte'
|
|
import HiddenBaseEdge from './renderers/edges/HiddenBaseEdge.svelte'
|
|
|
|
let {
|
|
nodes: nodesProp,
|
|
edges: edgesProp,
|
|
width,
|
|
height,
|
|
initialViewport
|
|
}: {
|
|
nodes: Node[]
|
|
edges: Edge[]
|
|
width: number
|
|
height: number
|
|
initialViewport?: Viewport
|
|
} = $props()
|
|
|
|
// Use $state.raw to avoid deep reactive proxies that trigger xyflow's performance warning
|
|
let nodes = $state.raw<Node[]>([])
|
|
let edges = $state.raw<Edge[]>([])
|
|
$effect(() => {
|
|
nodes = [...nodesProp]
|
|
})
|
|
$effect(() => {
|
|
edges = [...edgesProp]
|
|
})
|
|
|
|
setGraphContext({
|
|
selectionManager: new SelectionManager(),
|
|
useDataflow: writable(false),
|
|
showAssets: writable(false),
|
|
diffManager: createFlowDiffManager()
|
|
})
|
|
|
|
const nodeTypes = {
|
|
input2: InputNode,
|
|
module: ModuleNode,
|
|
branchAllStart: BranchAllStart,
|
|
branchAllEnd: BranchAllEndNode,
|
|
forLoopEnd: ForLoopEndNode,
|
|
forLoopStart: ForLoopStartNode,
|
|
result: ResultNode,
|
|
whileLoopStart: ForLoopStartNode,
|
|
whileLoopEnd: ForLoopEndNode,
|
|
branchOneStart: BranchOneStart,
|
|
branchOneEnd: BranchOneEndNode,
|
|
subflowBound: SubflowBound,
|
|
noBranch: NoBranchNode,
|
|
asset: AssetNode,
|
|
assetsOverflowed: AssetsOverflowedNode,
|
|
aiTool: AiToolNode,
|
|
newAiTool: NewAiToolNode,
|
|
collapsedGroup: CollapsedGroupNode,
|
|
groupHead: GroupHeadNode,
|
|
groupEnd: GroupEndNode
|
|
} as any
|
|
|
|
const edgeTypes = {
|
|
edge: BaseEdge,
|
|
empty: EmptyEdge,
|
|
dataflowedge: DataflowEdge,
|
|
hiddenedge: HiddenBaseEdge
|
|
} as any
|
|
|
|
const proOptions = { hideAttribution: true }
|
|
const fitViewOptions = { padding: 0 }
|
|
</script>
|
|
|
|
<div style="width: {width}px; height: {height}px;">
|
|
<SvelteFlowProvider>
|
|
<SvelteFlow
|
|
{nodes}
|
|
{edges}
|
|
{nodeTypes}
|
|
{edgeTypes}
|
|
fitView={!initialViewport}
|
|
{fitViewOptions}
|
|
{initialViewport}
|
|
nodesDraggable={false}
|
|
elementsSelectable={false}
|
|
panOnDrag={false}
|
|
zoomOnScroll={false}
|
|
zoomOnPinch={false}
|
|
zoomOnDoubleClick={false}
|
|
preventScrolling={false}
|
|
{proOptions}
|
|
style="width: {width}px; height: {height}px; background: transparent;"
|
|
/>
|
|
</SvelteFlowProvider>
|
|
</div>
|