mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-05 16:03:47 +00:00
fix(frontend): same view as before
This commit is contained in:
@@ -642,6 +642,7 @@
|
||||
.nodeSize(() => [NODE.width + NODE.gap.horizontal, NODE.height + NODE.gap.vertical])
|
||||
boxSize = layout(dag)
|
||||
}
|
||||
|
||||
return {
|
||||
nodes: dag.descendants().map((des) => ({
|
||||
...des.data,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { type FlowModule } from '../../gen'
|
||||
import { type GraphModuleState } from '.'
|
||||
import { NODE, type GraphModuleState } from '.'
|
||||
import { setContext } from 'svelte'
|
||||
|
||||
import { writable, type Writable } from 'svelte/store'
|
||||
@@ -9,7 +9,6 @@
|
||||
import {
|
||||
SvelteFlow,
|
||||
Background,
|
||||
Position,
|
||||
type Node,
|
||||
type Edge,
|
||||
ConnectionLineType,
|
||||
@@ -28,7 +27,8 @@
|
||||
import ResultNode from './renderers/nodes/ResultNode.svelte'
|
||||
import BaseEdge from './renderers/edges/BaseEdge.svelte'
|
||||
import EmptyEdge from './renderers/edges/EmptyEdge.svelte'
|
||||
|
||||
import { sugiyama, dagStratify, decrossOpt, coordCenter } from 'd3-dag'
|
||||
let width = 0
|
||||
export let success: boolean | undefined = undefined
|
||||
export let modules: FlowModule[] | undefined = []
|
||||
export let failureModule: FlowModule | undefined = undefined
|
||||
@@ -55,47 +55,61 @@
|
||||
flowInputsStore: Writable<FlowInput | undefined>
|
||||
}>('FlowGraphContext', { selectedId, flowInputsStore })
|
||||
|
||||
const nodeWidth = 300
|
||||
const nodeHeight = 36
|
||||
const dagreGraph = new dagre.graphlib.Graph()
|
||||
|
||||
dagreGraph.setDefaultEdgeLabel(() => ({}))
|
||||
|
||||
function getLayoutedElements(nodes: Node[], edges: Edge[], direction = 'TB') {
|
||||
dagreGraph.setGraph({ rankdir: direction })
|
||||
|
||||
nodes.forEach((node) => {
|
||||
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight })
|
||||
})
|
||||
|
||||
edges.forEach((edge) => {
|
||||
dagreGraph.setEdge(edge.source, edge.target, {
|
||||
minlen: 1
|
||||
})
|
||||
})
|
||||
|
||||
dagre.layout(dagreGraph)
|
||||
|
||||
nodes.forEach((node) => {
|
||||
const nodeWithPosition = dagreGraph.node(node.id)
|
||||
node.targetPosition = Position.Top
|
||||
node.sourcePosition = Position.Bottom
|
||||
|
||||
node.position = {
|
||||
x: nodeWithPosition.x - nodeWidth / 2,
|
||||
y: nodeWithPosition.y - nodeHeight / 2
|
||||
let fullWidth = 0
|
||||
function layoutNodes(nodes: Node[], edges: Edge[]): { nodes: Node[]; edges: Edge[] } {
|
||||
let seenId: string[] = []
|
||||
for (const n of nodes) {
|
||||
if (seenId.includes(n.id)) {
|
||||
n.id = n.id + '_dup'
|
||||
}
|
||||
})
|
||||
seenId.push(n.id)
|
||||
}
|
||||
|
||||
return { nodes, edges }
|
||||
const flattenParentIds = nodes.map((n) => ({
|
||||
...n,
|
||||
parentIds: n.data?.parentIds ?? []
|
||||
}))
|
||||
|
||||
const stratify = dagStratify().id(({ id }: Node) => id)
|
||||
const dag = stratify(flattenParentIds)
|
||||
|
||||
let boxSize: any
|
||||
try {
|
||||
const layout = sugiyama()
|
||||
.decross(decrossOpt())
|
||||
.coord(coordCenter())
|
||||
.nodeSize(() => [NODE.width + NODE.gap.horizontal, NODE.height + NODE.gap.vertical])
|
||||
boxSize = layout(dag)
|
||||
} catch {
|
||||
const layout = sugiyama()
|
||||
.coord(coordCenter())
|
||||
.nodeSize(() => [NODE.width + NODE.gap.horizontal, NODE.height + NODE.gap.vertical])
|
||||
boxSize = layout(dag)
|
||||
}
|
||||
|
||||
const newNodes = dag.descendants().map((des) => ({
|
||||
...des.data,
|
||||
id: des.data.id,
|
||||
position: {
|
||||
x: des.x
|
||||
? (des.data.data.offset ?? 0) +
|
||||
des.x +
|
||||
(fullSize ? fullWidth : width) / 2 -
|
||||
boxSize.width / 2 -
|
||||
NODE.width / 2
|
||||
: 0,
|
||||
y: des.y || 0
|
||||
}
|
||||
}))
|
||||
|
||||
return {
|
||||
nodes: newNodes,
|
||||
edges
|
||||
}
|
||||
}
|
||||
|
||||
const { nodes: initialNodes, edges: initialEdges } = graphBuilder(modules)
|
||||
|
||||
const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(
|
||||
initialNodes,
|
||||
initialEdges
|
||||
)
|
||||
const { nodes: layoutedNodes, edges: layoutedEdges } = layoutNodes(initialNodes, initialEdges)
|
||||
|
||||
const nodes = writable<Node[]>(layoutedNodes)
|
||||
const edges = writable<Edge[]>(layoutedEdges)
|
||||
@@ -123,19 +137,26 @@
|
||||
style={`min-height: ${minHeight}px; max-height: ${
|
||||
maxHeight ? maxHeight + 'px' : 'none'
|
||||
}; height:100%;`}
|
||||
bind:clientWidth={width}
|
||||
class="h-full"
|
||||
>
|
||||
<SvelteFlow
|
||||
{nodes}
|
||||
{edges}
|
||||
{edgeTypes}
|
||||
{nodeTypes}
|
||||
nodesDraggable={false}
|
||||
connectionLineType={ConnectionLineType.SmoothStep}
|
||||
defaultEdgeOptions={{ type: 'smoothstep' }}
|
||||
fitView
|
||||
{proOptions}
|
||||
>
|
||||
<Background class="!bg-surface-secondary" />
|
||||
<MiniMap nodeStrokeWidth={3} />
|
||||
<MiniMap nodeStrokeWidth={3} darkMode />
|
||||
</SvelteFlow>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
:global(.svelte-flow__handle) {
|
||||
opacity: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -19,16 +19,21 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
value: module.value,
|
||||
offset: offset,
|
||||
module: module,
|
||||
modules: modules
|
||||
modules: modules,
|
||||
parentIds: []
|
||||
},
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: type
|
||||
})
|
||||
|
||||
return module.id
|
||||
}
|
||||
|
||||
const parents: { [key: string]: string[] } = {}
|
||||
|
||||
function addEdge(sourceId: string, targetId: string, customId?: string, type?: string) {
|
||||
parents[targetId] = [...(parents[targetId] ?? []), sourceId]
|
||||
|
||||
edges.push({
|
||||
id: customId || `edge:${sourceId}->${targetId}`,
|
||||
source: sourceId,
|
||||
@@ -39,15 +44,19 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
|
||||
const inputNode: Node = {
|
||||
id: 'input',
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'input2',
|
||||
data: {}
|
||||
data: {
|
||||
parentIds: []
|
||||
}
|
||||
}
|
||||
|
||||
const resultNode: Node = {
|
||||
id: 'result',
|
||||
data: {},
|
||||
position: { x: 0, y: 0 },
|
||||
data: {
|
||||
parentIds: []
|
||||
},
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'result'
|
||||
}
|
||||
|
||||
@@ -70,6 +79,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
|
||||
if (module.value.type === 'rawscript') {
|
||||
addNode(module, currentOffset, 'module')
|
||||
|
||||
previousId = module.id
|
||||
} else if (module.value.type === 'branchall') {
|
||||
// Start
|
||||
@@ -79,7 +89,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const endNode = {
|
||||
id: `${module.id}-end`,
|
||||
data: { offset: currentOffset, id: module.id },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'branchAllEnd'
|
||||
}
|
||||
nodes.push(endNode)
|
||||
@@ -90,7 +100,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const startNode = {
|
||||
id: `${module.id}-branch-${branchIndex}`,
|
||||
data: { offset: currentOffset, label: `Branch ${branchIndex + 1}`, id: module.id },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'branchAllStart'
|
||||
}
|
||||
|
||||
@@ -108,7 +118,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const startNode = {
|
||||
id: `${module.id}-start`,
|
||||
data: { offset: currentOffset + 50, id: module.id },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'forLoopStart'
|
||||
}
|
||||
|
||||
@@ -117,7 +127,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const endNode = {
|
||||
id: `${module.id}-end`,
|
||||
data: { offset: currentOffset, id: module.id },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'forLoopEnd'
|
||||
}
|
||||
|
||||
@@ -133,7 +143,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const startNode = {
|
||||
id: `${module.id}-start`,
|
||||
data: { offset: currentOffset + 50 },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'whileLoopStart'
|
||||
}
|
||||
addEdge(module.id, startNode.id, undefined, 'empty')
|
||||
@@ -141,7 +151,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const endNode = {
|
||||
id: `${module.id}-end`,
|
||||
data: { offset: currentOffset },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'whileLoopEnd'
|
||||
}
|
||||
|
||||
@@ -158,7 +168,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const endNode = {
|
||||
id: `${module.id}-end`,
|
||||
data: { offset: currentOffset },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'branchOneEnd'
|
||||
}
|
||||
nodes.push(endNode)
|
||||
@@ -169,7 +179,7 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
const startNode = {
|
||||
id: `${module.id}-branch-${branchIndex}`,
|
||||
data: { offset: currentOffset },
|
||||
position: { x: 0, y: 0 },
|
||||
position: { x: -1, y: -1 },
|
||||
type: 'branchOneStart'
|
||||
}
|
||||
|
||||
@@ -193,5 +203,13 @@ export default function graphBuilder(modules: FlowModule[] | undefined): {
|
||||
|
||||
processModules(modules, inputNode, resultNode)
|
||||
|
||||
Object.keys(parents).forEach((key) => {
|
||||
const node = nodes.find((n) => n.id === key)
|
||||
|
||||
if (node) {
|
||||
node.data.parentIds = parents[key]
|
||||
}
|
||||
})
|
||||
|
||||
return { nodes, edges }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
type Node
|
||||
// @ts-ignore
|
||||
} from '@xyflow/svelte'
|
||||
import { sugiyama, dagStratify, decrossOpt, coordCenter } from 'd3-dag'
|
||||
import { NODE } from './util'
|
||||
|
||||
export function layoutNodes(
|
||||
nodes: Node[],
|
||||
fullSize: number,
|
||||
fullWidth: number,
|
||||
width: number
|
||||
): { nodes: Node[] } {
|
||||
let seenId: string[] = []
|
||||
for (const n of nodes) {
|
||||
if (seenId.includes(n.id)) {
|
||||
n.id = n.id + '_dup'
|
||||
}
|
||||
seenId.push(n.id)
|
||||
}
|
||||
|
||||
const flattenParentIds = nodes.map((n) => ({
|
||||
...n,
|
||||
parentIds: n.data?.parentIds ?? []
|
||||
}))
|
||||
|
||||
const stratify = dagStratify().id(({ id }: Node) => id)
|
||||
const dag = stratify(flattenParentIds)
|
||||
|
||||
let boxSize: any
|
||||
try {
|
||||
const layout = sugiyama()
|
||||
.decross(decrossOpt())
|
||||
.coord(coordCenter())
|
||||
.nodeSize(() => [NODE.width + NODE.gap.horizontal, NODE.height + NODE.gap.vertical])
|
||||
boxSize = layout(dag)
|
||||
} catch {
|
||||
const layout = sugiyama()
|
||||
.coord(coordCenter())
|
||||
.nodeSize(() => [NODE.width + NODE.gap.horizontal, NODE.height + NODE.gap.vertical])
|
||||
boxSize = layout(dag)
|
||||
}
|
||||
|
||||
const newNodes = dag.descendants().map((des) => ({
|
||||
...des.data,
|
||||
id: des.data.id,
|
||||
position: {
|
||||
x: des.x
|
||||
? (des.data.data.offset ?? 0) +
|
||||
des.x +
|
||||
(fullSize ? fullWidth : width) / 2 -
|
||||
boxSize.width / 2 -
|
||||
NODE.width / 2
|
||||
: 0,
|
||||
y: des.y || 0
|
||||
}
|
||||
}))
|
||||
|
||||
return {
|
||||
nodes: newNodes
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,25 @@
|
||||
|
||||
$: [edgePath, labelX, labelY] = getBezierPath({
|
||||
sourceX,
|
||||
sourceY,
|
||||
sourceY: targetY - sourceY > 100 ? targetY - 100 : sourceY,
|
||||
sourcePosition,
|
||||
targetX,
|
||||
targetY,
|
||||
targetPosition
|
||||
targetPosition,
|
||||
curvature: 0.1
|
||||
})
|
||||
|
||||
function getStraightLinePath({ sourceX, sourceY, targetX, targetY }) {
|
||||
return `M${sourceX},${sourceY} L${sourceX},${targetY - 100}`
|
||||
}
|
||||
|
||||
$: completeEdge =
|
||||
targetY - sourceY > 100
|
||||
? `${edgePath} ${getStraightLinePath({ sourceX, sourceY, targetX, targetY })}`
|
||||
: edgePath
|
||||
</script>
|
||||
|
||||
<BaseEdge path={edgePath} {markerEnd} {style} />
|
||||
<BaseEdge path={completeEdge} {markerEnd} {style} />
|
||||
<EdgeLabelRenderer>
|
||||
<div
|
||||
class="edgeButtonContainer nodrag nopan"
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
</div>
|
||||
|
||||
{#if enableSourceHandle}
|
||||
<Handle type="source" position={Position.Bottom} />
|
||||
<Handle type="source" position={Position.Bottom} style={`margin-left: ${offset / 2}px;`} />
|
||||
{/if}
|
||||
|
||||
{#if enableTargetHandle}
|
||||
<Handle type="target" position={Position.Top} />
|
||||
<Handle type="target" position={Position.Top} style={`margin-left: ${offset / 2}px;`} />
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user