From c04b0d7fb1f7f46b7903c3e7fe61e577c4d450e9 Mon Sep 17 00:00:00 2001 From: Srdjan Arsic Date: Wed, 11 Dec 2024 12:41:56 +0100 Subject: [PATCH] add size example --- .../examples/src/example4-size.tsx | 67 +++++++++++++++++++ .../pipeline-graph/examples/src/examples.tsx | 7 ++ .../simple-parallel-group-node.tsx | 31 +++++++++ .../nodes-simple/simple-serial-group-node.tsx | 31 +++++++++ .../src/nodes-simple/simple-stage-node.tsx | 31 +++++++++ .../src/nodes-simple/simple-step-node.tsx | 60 +++++++++++++++++ .../examples/src/parser/yaml2AnyNodes.tsx | 23 ++++--- .../src/context/graph-provider.tsx | 12 +++- 8 files changed, 250 insertions(+), 12 deletions(-) create mode 100644 packages/pipeline-graph/examples/src/example4-size.tsx create mode 100644 packages/pipeline-graph/examples/src/nodes-simple/simple-parallel-group-node.tsx create mode 100644 packages/pipeline-graph/examples/src/nodes-simple/simple-serial-group-node.tsx create mode 100644 packages/pipeline-graph/examples/src/nodes-simple/simple-stage-node.tsx create mode 100644 packages/pipeline-graph/examples/src/nodes-simple/simple-step-node.tsx diff --git a/packages/pipeline-graph/examples/src/example4-size.tsx b/packages/pipeline-graph/examples/src/example4-size.tsx new file mode 100644 index 000000000..d9e6135d0 --- /dev/null +++ b/packages/pipeline-graph/examples/src/example4-size.tsx @@ -0,0 +1,67 @@ +import { parse } from 'yaml' + +import { PipelineGraph } from '../../src/pipeline-graph' +import { NodeContent } from '../../src/types/node-content' +import { ContainerNode } from '../../src/types/nodes' +import { yaml2Nodes } from './parser/yaml2AnyNodes' +import { pipeline } from './sample-data/pipeline' + +import './sample-data/pipeline-data' + +import React from 'react' + +import { CanvasProvider } from '../../src/context/canvas-provider' +import { CanvasControls } from './canvas/CanvasControls' +import { SimpleParallelGroupNodeContent } from './nodes-simple/simple-parallel-group-node' +import { SimpleSerialGroupContentNode } from './nodes-simple/simple-stage-node' +import { SimpleStepNode } from './nodes-simple/simple-step-node' +import { ContentNodeTypes } from './types/content-node-types' + +const nodes: NodeContent[] = [ + { + type: ContentNodeTypes.step, + containerType: ContainerNode.leaf, + component: SimpleStepNode + }, + { + type: ContentNodeTypes.parallel, + containerType: ContainerNode.parallel, + component: SimpleParallelGroupNodeContent + }, + { + type: ContentNodeTypes.serial, + containerType: ContainerNode.serial, + component: SimpleSerialGroupContentNode + }, + { + type: ContentNodeTypes.stage, + containerType: ContainerNode.serial, + component: SimpleSerialGroupContentNode + } +] + +const yamlObject = parse(pipeline) +const plData = yaml2Nodes(yamlObject, {}) + +function Example4() { + return ( +
+ + {}} onAdd={() => {}} onDelete={() => {}} /> + + +
+ ) +} + +export default Example4 diff --git a/packages/pipeline-graph/examples/src/examples.tsx b/packages/pipeline-graph/examples/src/examples.tsx index b0f4adaec..412bec981 100644 --- a/packages/pipeline-graph/examples/src/examples.tsx +++ b/packages/pipeline-graph/examples/src/examples.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from 'react' import Example1 from './example1' import AnimationExample from './example2-animations' import PerformanceExample from './example3-performance' +import SizeExample from './example4-size' import { ContentNodeTypes } from './types/content-node-types' import './examples.css' @@ -23,6 +24,10 @@ const examplesArr = [ { name: 'Performance', component: PerformanceExample + }, + { + name: 'Size', + component: SizeExample } ] @@ -47,6 +52,8 @@ function App() { return case 'Performance': return + case 'Size': + return } } diff --git a/packages/pipeline-graph/examples/src/nodes-simple/simple-parallel-group-node.tsx b/packages/pipeline-graph/examples/src/nodes-simple/simple-parallel-group-node.tsx new file mode 100644 index 000000000..64c02009b --- /dev/null +++ b/packages/pipeline-graph/examples/src/nodes-simple/simple-parallel-group-node.tsx @@ -0,0 +1,31 @@ +import React from 'react' + +import { ParallelNodeInternalType } from '../../../src/types/nodes-internal' + +export interface ParallelGroupContentNodeDataType { + yamlPath: string + name: string +} + +export function SimpleParallelGroupNodeContent(props: { + node: ParallelNodeInternalType + children: React.ReactElement +}) { + const { children } = props + + return ( +
+
+ {children} +
+ ) +} diff --git a/packages/pipeline-graph/examples/src/nodes-simple/simple-serial-group-node.tsx b/packages/pipeline-graph/examples/src/nodes-simple/simple-serial-group-node.tsx new file mode 100644 index 000000000..864909dac --- /dev/null +++ b/packages/pipeline-graph/examples/src/nodes-simple/simple-serial-group-node.tsx @@ -0,0 +1,31 @@ +import React from 'react' + +import { SerialNodeInternalType } from '../../../src/types/nodes-internal' + +export interface SerialGroupContentNodeDataType { + yamlPath: string + name: string +} + +export function SimpleSerialGroupNodeContent(props: { + node: SerialNodeInternalType + children: React.ReactElement +}) { + const { children } = props + + return ( +
+
+ {children} +
+ ) +} diff --git a/packages/pipeline-graph/examples/src/nodes-simple/simple-stage-node.tsx b/packages/pipeline-graph/examples/src/nodes-simple/simple-stage-node.tsx new file mode 100644 index 000000000..3b5b41d33 --- /dev/null +++ b/packages/pipeline-graph/examples/src/nodes-simple/simple-stage-node.tsx @@ -0,0 +1,31 @@ +import React from 'react' + +import { SerialNodeInternalType } from '../../../src/types/nodes-internal' + +export interface StageNodeContentType { + yamlPath: string + name: string +} + +export function SimpleSerialGroupContentNode(props: { + node: SerialNodeInternalType + children: React.ReactElement +}) { + const { children } = props + + return ( +
+
+ {children} +
+ ) +} diff --git a/packages/pipeline-graph/examples/src/nodes-simple/simple-step-node.tsx b/packages/pipeline-graph/examples/src/nodes-simple/simple-step-node.tsx new file mode 100644 index 000000000..b1d907699 --- /dev/null +++ b/packages/pipeline-graph/examples/src/nodes-simple/simple-step-node.tsx @@ -0,0 +1,60 @@ +import React, { useEffect, useRef, useState } from 'react' + +import { useGraphContext } from '../../../src/context/graph-provider' +import { LeafNodeInternalType } from '../../../src/types/nodes-internal' + +export interface StepNodeDataType { + yamlPath: string + name: string + icon?: React.ReactElement +} + +export function SimpleStepNode(props: { node: LeafNodeInternalType }) { + const { rerender } = useGraphContext() + const { node } = props + const data = node.data as StepNodeDataType + + const increment = useRef(Math.random() * 2) + const size = useRef({ x: 150, y: 150 }) + + const [_, setRerender] = useState(1) + + useEffect(() => { + const interval = setInterval(() => { + if (size.current.x > 200) increment.current = -Math.abs(increment.current) + if (size.current.x < 100) increment.current = Math.abs(increment.current) + + size.current = { x: size.current.x + increment.current, y: size.current.y + increment.current } + rerender() + }, 33) + + setRerender(prev => prev + 1) + return () => clearInterval(interval) + }, []) + + const style: React.CSSProperties = { + height: size.current.x + 'px', + width: size.current.y + 'px', + boxSizing: 'border-box', + border: '1px solid #454545', + borderRadius: '6px', + wordBreak: 'break-all', + fontSize: '11px', + fontFamily: 'Verdana', + background: 'linear-gradient(-47deg, rgba(152, 150, 172, 0.05) 0%, rgba(177, 177, 177, 0.15) 100%)', + overflow: 'hidden' + } + + const name = data?.name ?? 'Step' + + return ( +
+
{data?.icon}
+
+ {name} +
+ {props.node.path} +
+
+ ) +} diff --git a/packages/pipeline-graph/examples/src/parser/yaml2AnyNodes.tsx b/packages/pipeline-graph/examples/src/parser/yaml2AnyNodes.tsx index d3c5e696a..4f37f39c2 100644 --- a/packages/pipeline-graph/examples/src/parser/yaml2AnyNodes.tsx +++ b/packages/pipeline-graph/examples/src/parser/yaml2AnyNodes.tsx @@ -5,12 +5,15 @@ import { StepNodeDataType } from '../nodes/step-node' import { ContentNodeTypes } from '../types/content-node-types' import { getIcon } from './utils' -export const yaml2Nodes = (yamlObject: Record): AnyNodeType[] => { +export const yaml2Nodes = ( + yamlObject: Record, + options: { maxWidth?: number } = { maxWidth: 140 } +): AnyNodeType[] => { const nodes: AnyNodeType[] = [] const stages = yamlObject?.pipeline?.stages if (stages) { - const stagesNodes = processStages(stages, '') + const stagesNodes = processStages(stages, '', options) nodes.push(...stagesNodes) } @@ -23,7 +26,7 @@ const getGroupKey = (stage: Record): 'group' | 'parallel' | undefin return undefined } -const processStages = (stages: any[], currentPath: string): AnyNodeType[] => { +const processStages = (stages: any[], currentPath: string, options: { maxWidth?: number }): AnyNodeType[] => { return stages.map((stage, idx) => { // parallel stage const groupKey = getGroupKey(stage) @@ -43,7 +46,7 @@ const processStages = (stages: any[], currentPath: string): AnyNodeType[] => { name } satisfies StageNodeContentType, - children: processStages(stage[groupKey].stages, path) + children: processStages(stage[groupKey].stages, path, options) } satisfies SerialNodeType } else if (groupKey === 'parallel') { const name = stage.name ?? `Parallel group ${idx}` @@ -60,7 +63,7 @@ const processStages = (stages: any[], currentPath: string): AnyNodeType[] => { yamlPath: path, name } satisfies ParallelGroupContentNodeDataType, - children: processStages(stage[groupKey].stages, path) + children: processStages(stage[groupKey].stages, path, options) } satisfies ParallelNodeType } // regular stage @@ -79,13 +82,13 @@ const processStages = (stages: any[], currentPath: string): AnyNodeType[] => { yamlPath: path, name } satisfies StageNodeContentType, - children: processSteps(stage.steps, path) + children: processSteps(stage.steps, path, options) } satisfies SerialNodeType } }) } -const processSteps = (steps: any[], currentPath: string): AnyNodeType[] => { +const processSteps = (steps: any[], currentPath: string, options: { maxWidth?: number }): AnyNodeType[] => { return steps.map((step, idx) => { // parallel stage const groupKey = getGroupKey(step) @@ -105,7 +108,7 @@ const processSteps = (steps: any[], currentPath: string): AnyNodeType[] => { name } satisfies StageNodeContentType, - children: processSteps(step[groupKey].steps, path) + children: processSteps(step[groupKey].steps, path, options) } satisfies SerialNodeType } else if (groupKey === 'parallel') { const name = step.name ?? `Parallel group ${idx}` @@ -122,7 +125,7 @@ const processSteps = (steps: any[], currentPath: string): AnyNodeType[] => { yamlPath: path, name } satisfies ParallelGroupContentNodeDataType, - children: processSteps(step[groupKey].steps, path) + children: processSteps(step[groupKey].steps, path, options) } satisfies ParallelNodeType } // regular step @@ -133,7 +136,7 @@ const processSteps = (steps: any[], currentPath: string): AnyNodeType[] => { return { type: ContentNodeTypes.step, config: { - maxWidth: 140, + ...options, hideDeleteButton: false, selectable: true }, diff --git a/packages/pipeline-graph/src/context/graph-provider.tsx b/packages/pipeline-graph/src/context/graph-provider.tsx index 2344ee6c5..eaf832724 100644 --- a/packages/pipeline-graph/src/context/graph-provider.tsx +++ b/packages/pipeline-graph/src/context/graph-provider.tsx @@ -12,6 +12,7 @@ interface GraphContextProps { isCollapsed: (path: string) => boolean setNodeToRemove: (path: string | null) => void nodeToRemove: string | null + rerender: () => void // rerenderConnections: number // @@ -27,7 +28,8 @@ const GraphContext = createContext({ rerenderConnections: 0, setNodeToRemove: (_path: string | null) => undefined, nodeToRemove: null, - shiftCollapsed: (_path: string, _index: number) => undefined + shiftCollapsed: (_path: string, _index: number) => undefined, + rerender: () => undefined }) const GraphProvider = ({ nodes: nodesArr, children }: React.PropsWithChildren<{ nodes: NodeContent[] }>) => { @@ -79,6 +81,10 @@ const GraphProvider = ({ nodes: nodesArr, children }: React.PropsWithChildren<{ [collapsed, setCollapsed, rerenderConnections, setRerenderConnections] ) + const rerender = useCallback(() => { + setRerenderConnections(prev => prev + 1) + }, [setRerenderConnections]) + const isCollapsed = useCallback( (path: string) => { return !!collapsed[path] @@ -109,7 +115,9 @@ const GraphProvider = ({ nodes: nodesArr, children }: React.PropsWithChildren<{ // force rerender rerenderConnections, // shift collapsed on node deletion - shiftCollapsed + shiftCollapsed, + // rerender connections + rerender }} > {children}