From d4e62922733dbb3f206526c3be04d75b240da29d Mon Sep 17 00:00:00 2001 From: "Ricardo M." Date: Thu, 18 Jul 2024 12:30:19 -0400 Subject: [PATCH] Temp: Last state --- .../Visualization/Canvas/Canvas.tsx | 70 +- .../Canvas/canvas.service.test.ts | 2 + .../Visualization/Canvas/canvas.service.ts | 145 +- .../Canvas/topology-controller.scheduler.ts | 17 + .../Custom/{ => ContextMenu}/ItemAddStep.tsx | 8 +- .../{ => ContextMenu}/ItemDeleteGroup.tsx | 8 +- .../{ => ContextMenu}/ItemDeleteStep.tsx | 8 +- .../{ => ContextMenu}/ItemDisableStep.tsx | 8 +- .../{ => ContextMenu}/ItemInsertStep.tsx | 8 +- .../{ => ContextMenu}/ItemReplaceStep.tsx | 8 +- .../Custom/ContextMenu/NodeContextMenu.tsx | 119 + .../Visualization/Custom/CustomGroup.tsx | 85 - .../Visualization/Custom/CustomNode.tsx | 191 - .../Custom/Group/CollapseButton.tsx | 26 + .../Custom/Group/ContextMenuButton.tsx | 51 + .../Custom/Group/CustomGroup.scss | 87 + .../Custom/Group/CustomGroup.tsx | 43 + .../Custom/Group/CustomGroupCollapsed.tsx | 95 + .../Custom/Group/CustomGroupCollapsible.tsx | 31 + .../Custom/Group/CustomGroupExpanded.tsx | 125 + .../Custom/Group/Group.models.ts | 9 + .../Visualization/Custom/NoBendingEdge.tsx | 7 + .../Custom/{ => Node}/CustomNode.scss | 0 .../Visualization/Custom/Node/CustomNode.tsx | 82 + .../components/Visualization/Custom/index.ts | 5 +- .../flows/abstract-camel-visual-entity.ts | 19 +- .../support/camel-component-schema.service.ts | 2 + .../flows/support/camel-steps.service.ts | 8 +- packages/ui/src/stubs/camel-route-branch.ts | 34 + .../__snapshots__/nodes-edges.test.ts.snap | 4604 +++++++++++++++++ packages/ui/src/tests/nodes-edges.test.ts | 21 + 31 files changed, 5503 insertions(+), 423 deletions(-) create mode 100644 packages/ui/src/components/Visualization/Canvas/topology-controller.scheduler.ts rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemAddStep.tsx (81%) rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemDeleteGroup.tsx (80%) rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemDeleteStep.tsx (80%) rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemDisableStep.tsx (80%) rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemInsertStep.tsx (83%) rename packages/ui/src/components/Visualization/Custom/{ => ContextMenu}/ItemReplaceStep.tsx (81%) create mode 100644 packages/ui/src/components/Visualization/Custom/ContextMenu/NodeContextMenu.tsx delete mode 100644 packages/ui/src/components/Visualization/Custom/CustomGroup.tsx delete mode 100644 packages/ui/src/components/Visualization/Custom/CustomNode.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CollapseButton.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/ContextMenuButton.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CustomGroup.scss create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CustomGroup.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsed.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsible.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/CustomGroupExpanded.tsx create mode 100644 packages/ui/src/components/Visualization/Custom/Group/Group.models.ts create mode 100644 packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx rename packages/ui/src/components/Visualization/Custom/{ => Node}/CustomNode.scss (100%) create mode 100644 packages/ui/src/components/Visualization/Custom/Node/CustomNode.tsx create mode 100644 packages/ui/src/stubs/camel-route-branch.ts create mode 100644 packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap create mode 100644 packages/ui/src/tests/nodes-edges.test.ts diff --git a/packages/ui/src/components/Visualization/Canvas/Canvas.tsx b/packages/ui/src/components/Visualization/Canvas/Canvas.tsx index a708927a7..311d8676f 100644 --- a/packages/ui/src/components/Visualization/Canvas/Canvas.tsx +++ b/packages/ui/src/components/Visualization/Canvas/Canvas.tsx @@ -35,13 +35,14 @@ import { CanvasSideBar } from './CanvasSideBar'; import { CanvasDefaults } from './canvas.defaults'; import { CanvasEdge, CanvasNode, LayoutType } from './canvas.models'; import { CanvasService } from './canvas.service'; +import { TopologyControllerScheduler } from './topology-controller.scheduler'; interface CanvasProps { contextToolbar?: ReactNode; entities: BaseVisualCamelEntity[]; } -export const Canvas: FunctionComponent> = (props) => { +export const Canvas: FunctionComponent> = ({ entities, contextToolbar }) => { /** State for @patternfly/react-topology */ const [selectedIds, setSelectedIds] = useState([]); const [selectedNode, setSelectedNode] = useState(undefined); @@ -51,13 +52,13 @@ export const Canvas: FunctionComponent> = (props) /** Context to interact with the Canvas catalog */ const catalogModalContext = useContext(CatalogModalContext); - const controller = useMemo(() => CanvasService.createController(), []); + const controllerScheduler = useMemo(() => new TopologyControllerScheduler(CanvasService.createController()), []); const { visibleFlows } = useContext(VisibleFlowsContext)!; const shouldShowEmptyState = useMemo(() => { - const areNoFlows = props.entities.length === 0; + const areNoFlows = entities.length === 0; const areAllFlowsHidden = Object.values(visibleFlows).every((visible) => !visible); return areNoFlows || areAllFlowsHidden; - }, [props.entities.length, visibleFlows]); + }, [entities.length, visibleFlows]); const controlButtons = useMemo(() => { const customButtons: TopologyControlButton[] = catalogModalContext @@ -72,9 +73,9 @@ export const Canvas: FunctionComponent> = (props) tooltip: 'Horizontal Layout', callback: action(() => { setActiveLayout(LayoutType.DagreHorizontal); - controller.getGraph().setLayout(LayoutType.DagreHorizontal); - controller.getGraph().reset(); - controller.getGraph().layout(); + controllerScheduler.getGraph().setLayout(LayoutType.DagreHorizontal); + controllerScheduler.getGraph().reset(); + controllerScheduler.getGraph().layout(); }), }, { @@ -87,9 +88,9 @@ export const Canvas: FunctionComponent> = (props) tooltip: 'Vertical Layout', callback: action(() => { setActiveLayout(LayoutType.DagreVertical); - controller.getGraph().setLayout(LayoutType.DagreVertical); - controller.getGraph().reset(); - controller.getGraph().layout(); + controllerScheduler.getGraph().setLayout(LayoutType.DagreVertical); + controllerScheduler.getGraph().reset(); + controllerScheduler.getGraph().layout(); }), }, { @@ -106,22 +107,22 @@ export const Canvas: FunctionComponent> = (props) return createTopologyControlButtons({ ...defaultControlButtonsOptions, zoomInCallback: action(() => { - controller.getGraph().scaleBy(4 / 3); + controllerScheduler.getGraph().scaleBy(4 / 3); }), zoomOutCallback: action(() => { - controller.getGraph().scaleBy(3 / 4); + controllerScheduler.getGraph().scaleBy(3 / 4); }), fitToScreenCallback: action(() => { - controller.getGraph().fit(80); + controllerScheduler.getGraph().fit(80); }), resetViewCallback: action(() => { - controller.getGraph().reset(); - controller.getGraph().layout(); + controllerScheduler.getGraph().reset(); + controllerScheduler.getGraph().layout(); }), legend: false, customButtons, }); - }, [catalogModalContext, controller]); + }, [catalogModalContext, controllerScheduler, setActiveLayout]); const handleSelection = useCallback( (selectedIds: string[]) => { @@ -136,17 +137,17 @@ export const Canvas: FunctionComponent> = (props) /** Set up the controller one time */ useEffect(() => { - const localController = controller; - const graphLayoutEndFn = () => { - localController.getGraph().fit(80); + const localController = controllerScheduler; + const graphLayoutEndFn = async () => { + await localController.fit(80); }; - localController.addEventListener(SELECTION_EVENT, handleSelection); - localController.addEventListener(GRAPH_LAYOUT_END_EVENT, graphLayoutEndFn); + localController.getController().addEventListener(SELECTION_EVENT, handleSelection); + localController.getController().addEventListener(GRAPH_LAYOUT_END_EVENT, graphLayoutEndFn); return () => { - localController.removeEventListener(SELECTION_EVENT, handleSelection); - localController.removeEventListener(GRAPH_LAYOUT_END_EVENT, graphLayoutEndFn); + localController.getController().removeEventListener(SELECTION_EVENT, handleSelection); + localController.getController().removeEventListener(GRAPH_LAYOUT_END_EVENT, graphLayoutEndFn); }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -154,13 +155,13 @@ export const Canvas: FunctionComponent> = (props) /** Draw graph */ useEffect(() => { - if (!Array.isArray(props.entities)) return; + if (!Array.isArray(entities)) return; setSelectedNode(undefined); const nodes: CanvasNode[] = []; const edges: CanvasEdge[] = []; - props.entities.forEach((entity) => { + entities.forEach((entity) => { if (visibleFlows[entity.id]) { const { nodes: childNodes, edges: childEdges } = CanvasService.getFlowDiagram(entity.toVizNode()); nodes.push(...childNodes); @@ -180,17 +181,18 @@ export const Canvas: FunctionComponent> = (props) }, }; - controller.fromModel(model, false); - }, [controller, props.entities, visibleFlows]); + controllerScheduler.getController().fromModel(model, false); + }, [activeLayout, controllerScheduler, entities, visibleFlows]); useEffect(() => { - const timeoutId = setTimeout(() => { - controller.getGraph().fit(80); + const timeoutId = setTimeout(async () => { + await controllerScheduler.fit(80); }, 500); + return () => { clearTimeout(timeoutId); }; - }, [controller, selectedIds]); + }, [controllerScheduler, selectedIds]); const handleCloseSideBar = useCallback(() => { setSelectedIds([]); @@ -201,15 +203,15 @@ export const Canvas: FunctionComponent> = (props) return ( } - contextToolbar={props.contextToolbar} + contextToolbar={contextToolbar} controlBar={} > - + {shouldShowEmptyState ? ( - + ) : ( )} diff --git a/packages/ui/src/components/Visualization/Canvas/canvas.service.test.ts b/packages/ui/src/components/Visualization/Canvas/canvas.service.test.ts index bed4fec85..6ace3e8de 100644 --- a/packages/ui/src/components/Visualization/Canvas/canvas.service.test.ts +++ b/packages/ui/src/components/Visualization/Canvas/canvas.service.test.ts @@ -47,12 +47,14 @@ describe('CanvasService', () => { it('should allow consumers to create a new controller and register its factories', () => { const layoutFactorySpy = jest.spyOn(Visualization.prototype, 'registerLayoutFactory'); const componentFactorySpy = jest.spyOn(Visualization.prototype, 'registerComponentFactory'); + const baselineElementFactorySpy = jest.spyOn(Visualization.prototype, 'registerElementFactory'); const controller = CanvasService.createController(); expect(controller).toBeInstanceOf(Visualization); expect(layoutFactorySpy).toHaveBeenCalledWith(CanvasService.baselineLayoutFactory); expect(componentFactorySpy).toHaveBeenCalledWith(CanvasService.baselineComponentFactory); + expect(baselineElementFactorySpy).toHaveBeenCalledWith(CanvasService.baselineElementFactory); }); describe('baselineComponentFactory', () => { diff --git a/packages/ui/src/components/Visualization/Canvas/canvas.service.ts b/packages/ui/src/components/Visualization/Canvas/canvas.service.ts index f41e1d11f..a6e172a4c 100644 --- a/packages/ui/src/components/Visualization/Canvas/canvas.service.ts +++ b/packages/ui/src/components/Visualization/Canvas/canvas.service.ts @@ -4,21 +4,23 @@ import { ColaLayout, ComponentFactory, ConcentricLayout, - DagreLayout, + DagreGroupsLayout, DefaultEdge, EdgeStyle, ForceLayout, Graph, GraphComponent, + GraphElement, GridLayout, Layout, - Model, + LEFT_TO_RIGHT, ModelKind, + TOP_TO_BOTTOM, Visualization, withPanZoom, } from '@patternfly/react-topology'; import { IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { CustomGroupWithSelection, CustomNodeWithSelection } from '../Custom'; +import { CustomGroupWithSelection, CustomNodeWithSelection, NoBendpointsEdge } from '../Custom'; import { CanvasDefaults } from './canvas.defaults'; import { CanvasEdge, CanvasNode, CanvasNodesAndEdges, LayoutType } from './canvas.models'; @@ -32,37 +34,11 @@ export class CanvasService { newController.registerLayoutFactory(this.baselineLayoutFactory); newController.registerComponentFactory(this.baselineComponentFactory); - - const defaultModel: Model = { - graph: { - id: 'default', - type: 'graph', - }, - }; - - newController.fromModel(defaultModel, false); + newController.registerElementFactory(this.baselineElementFactory); return newController; } - static baselineComponentFactory(kind: ModelKind, type: string): ReturnType { - switch (type) { - case 'group': - return CustomGroupWithSelection; - default: - switch (kind) { - case ModelKind.graph: - return withPanZoom()(GraphComponent); - case ModelKind.node: - return CustomNodeWithSelection; - case ModelKind.edge: - return DefaultEdge; - default: - return undefined; - } - } - } - // ### dagre algo options, uses default value on undefined ### // nodeSep: undefined, // the separation between adjacent nodes in the same rank // edgeSep: undefined, // the separation between adjacent edges in the same rank @@ -103,16 +79,16 @@ export class CanvasService { case LayoutType.Concentric: return new ConcentricLayout(graph); case LayoutType.DagreVertical: - return new DagreLayout(graph, { - rankdir: 'TB', + return new DagreGroupsLayout(graph, { + rankdir: TOP_TO_BOTTOM, ranker: 'network-simplex', nodesep: 20, edgesep: 20, ranksep: 0, }); case LayoutType.DagreHorizontal: - return new DagreLayout(graph, { - rankdir: 'LR', + return new DagreGroupsLayout(graph, { + rankdir: LEFT_TO_RIGHT, ranker: 'network-simplex', nodesep: 20, edgesep: 20, @@ -129,24 +105,39 @@ export class CanvasService { } } + static baselineComponentFactory(kind: ModelKind, type: string): ReturnType { + switch (type) { + case 'group': + return CustomGroupWithSelection; + default: + switch (kind) { + case ModelKind.graph: + return withPanZoom()(GraphComponent); + case ModelKind.node: + return CustomNodeWithSelection; + case ModelKind.edge: + return DefaultEdge; + default: + return undefined; + } + } + } + + static baselineElementFactory(kind: ModelKind): GraphElement | undefined { + switch (kind) { + case ModelKind.edge: + return new NoBendpointsEdge(); + default: + return undefined; + } + } + static getFlowDiagram(vizNode: IVisualizationNode): CanvasNodesAndEdges { this.nodes = []; this.edges = []; this.visitedNodes = []; - const children = vizNode.getChildren(); - if (vizNode.data.isGroup && children) { - children.forEach((child) => this.appendNodesAndEdges(child)); - const containerId = vizNode.getBaseEntity()?.getId() ?? 'Unknown'; - const group = this.getContainer(containerId, { - label: containerId, - children: this.visitedNodes, - data: { vizNode }, - }); - this.nodes.push(group); - } else { - this.appendNodesAndEdges(vizNode); - } + this.appendNodesAndEdges(vizNode); return { nodes: this.nodes, edges: this.edges }; } @@ -157,28 +148,31 @@ export class CanvasService { return; } - const node = this.getCanvasNode(vizNodeParam); - - /** Add node */ - this.nodes.push(node); - this.visitedNodes.push(node.id); - - /** Add edges */ - this.edges.push(...this.getEdgesFromVizNode(vizNodeParam)); + let node: CanvasNode; - /** Traverse the children nodes */ const children = vizNodeParam.getChildren(); - if (children !== undefined) { + if (vizNodeParam.data.isGroup && children) { children.forEach((child) => { this.appendNodesAndEdges(child); }); - } - /** Traverse the next node */ - const nextNode = vizNodeParam.getNextNode(); - if (nextNode !== undefined) { - this.appendNodesAndEdges(nextNode); + const containerId = vizNodeParam.id; + node = this.getContainer(containerId, { + label: containerId, + children: children.map((child) => child.id), + parentNode: vizNodeParam.getParentNode()?.id, + data: { vizNode: vizNodeParam }, + }); + } else { + node = this.getCanvasNode(vizNodeParam); } + + /** Add node */ + this.nodes.push(node); + this.visitedNodes.push(node.id); + + /** Add edges */ + this.edges.push(...this.getEdgesFromVizNode(vizNodeParam)); } private static getCanvasNode(vizNodeParam: IVisualizationNode): CanvasNode { @@ -195,28 +189,8 @@ export class CanvasService { private static getEdgesFromVizNode(vizNodeParam: IVisualizationNode): CanvasEdge[] { const edges: CanvasEdge[] = []; - /** Connect to previous node if it doesn't have children */ - if (vizNodeParam.getPreviousNode() !== undefined && vizNodeParam.getPreviousNode()?.getChildren() === undefined) { - edges.push(this.getEdge(vizNodeParam.getPreviousNode()!.id, vizNodeParam.id)); - } - - /** Connect to the parent if it's not a group and there is no previous node */ - if ( - vizNodeParam.getParentNode() !== undefined && - !vizNodeParam.getParentNode()?.data.isGroup && - vizNodeParam.getPreviousNode() === undefined - ) { - edges.push(this.getEdge(vizNodeParam.getParentNode()!.id, vizNodeParam.id)); - } - - /** Connect to each leaf of the previous node */ - if (vizNodeParam.getPreviousNode() !== undefined && vizNodeParam.getPreviousNode()?.getChildren() !== undefined) { - const leafNodesIds: string[] = []; - vizNodeParam.getPreviousNode()!.populateLeafNodesIds(leafNodesIds); - - leafNodesIds.forEach((leafNodeId) => { - edges.push(this.getEdge(leafNodeId, vizNodeParam.id)); - }); + if (vizNodeParam.getNextNode() !== undefined) { + edges.push(this.getEdge(vizNodeParam.id, vizNodeParam.getNextNode()!.id)); } return edges; @@ -224,7 +198,7 @@ export class CanvasService { private static getContainer( id: string, - options: { label?: string; children?: string[]; data?: CanvasNode['data'] } = {}, + options: { label?: string; children?: string[]; parentNode?: string; data?: CanvasNode['data'] } = {}, ): CanvasNode { return { id, @@ -232,6 +206,7 @@ export class CanvasService { group: true, label: options.label ?? id, children: options.children ?? [], + parentNode: options.parentNode, data: options.data, style: { padding: CanvasDefaults.DEFAULT_NODE_DIAMETER * 0.8, diff --git a/packages/ui/src/components/Visualization/Canvas/topology-controller.scheduler.ts b/packages/ui/src/components/Visualization/Canvas/topology-controller.scheduler.ts new file mode 100644 index 000000000..7159c1240 --- /dev/null +++ b/packages/ui/src/components/Visualization/Canvas/topology-controller.scheduler.ts @@ -0,0 +1,17 @@ +import { Graph, Node, Visualization } from '@patternfly/react-topology'; + +export class TopologyControllerScheduler { + constructor(private controller: Visualization) {} + + getController(): Visualization { + return this.controller; + } + + getGraph(): Graph { + return this.controller.getGraph(); + } + + async fit(padding?: number, node?: Node): Promise { + this.controller.getGraph().fit(padding, node); + } +} diff --git a/packages/ui/src/components/Visualization/Custom/ItemAddStep.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemAddStep.tsx similarity index 81% rename from packages/ui/src/components/Visualization/Custom/ItemAddStep.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemAddStep.tsx index 689d2d444..514493401 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemAddStep.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemAddStep.tsx @@ -1,9 +1,9 @@ import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { AddStepMode, IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { CatalogModalContext } from '../../../providers/catalog-modal.provider'; -import { EntitiesContext } from '../../../providers/entities.provider'; +import { IDataTestID } from '../../../../models'; +import { AddStepMode, IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { CatalogModalContext } from '../../../../providers/catalog-modal.provider'; +import { EntitiesContext } from '../../../../providers/entities.provider'; interface ItemAddStepProps extends PropsWithChildren { mode: AddStepMode.PrependStep | AddStepMode.AppendStep; diff --git a/packages/ui/src/components/Visualization/Custom/ItemDeleteGroup.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteGroup.tsx similarity index 80% rename from packages/ui/src/components/Visualization/Custom/ItemDeleteGroup.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteGroup.tsx index fb86add92..5092d7549 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemDeleteGroup.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteGroup.tsx @@ -1,10 +1,10 @@ import { TrashIcon } from '@patternfly/react-icons'; import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { DeleteModalContext } from '../../../providers/delete-modal.provider'; -import { EntitiesContext } from '../../../providers/entities.provider'; +import { IDataTestID } from '../../../../models'; +import { IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { DeleteModalContext } from '../../../../providers/delete-modal.provider'; +import { EntitiesContext } from '../../../../providers/entities.provider'; interface ItemDeleteGroupProps extends PropsWithChildren { vizNode: IVisualizationNode; diff --git a/packages/ui/src/components/Visualization/Custom/ItemDeleteStep.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteStep.tsx similarity index 80% rename from packages/ui/src/components/Visualization/Custom/ItemDeleteStep.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteStep.tsx index d307cc3d0..093a6ae9f 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemDeleteStep.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDeleteStep.tsx @@ -1,10 +1,10 @@ import { TrashIcon } from '@patternfly/react-icons'; import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { EntitiesContext } from '../../../providers/entities.provider'; -import { DeleteModalContext } from '../../../providers/delete-modal.provider'; +import { IDataTestID } from '../../../../models'; +import { IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { EntitiesContext } from '../../../../providers/entities.provider'; +import { DeleteModalContext } from '../../../../providers/delete-modal.provider'; interface ItemDeleteStepProps extends PropsWithChildren { vizNode: IVisualizationNode; diff --git a/packages/ui/src/components/Visualization/Custom/ItemDisableStep.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDisableStep.tsx similarity index 80% rename from packages/ui/src/components/Visualization/Custom/ItemDisableStep.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDisableStep.tsx index 412269369..7459ccc9a 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemDisableStep.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemDisableStep.tsx @@ -1,10 +1,10 @@ import { BanIcon, CheckIcon } from '@patternfly/react-icons'; import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { EntitiesContext } from '../../../providers/entities.provider'; -import { setValue } from '../../../utils/set-value'; +import { IDataTestID } from '../../../../models'; +import { IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { EntitiesContext } from '../../../../providers/entities.provider'; +import { setValue } from '../../../../utils/set-value'; interface ItemDisableStepProps extends PropsWithChildren { vizNode: IVisualizationNode; diff --git a/packages/ui/src/components/Visualization/Custom/ItemInsertStep.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemInsertStep.tsx similarity index 83% rename from packages/ui/src/components/Visualization/Custom/ItemInsertStep.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemInsertStep.tsx index 3fd4fbb0a..4e48630ec 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemInsertStep.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemInsertStep.tsx @@ -1,9 +1,9 @@ import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { AddStepMode, IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { CatalogModalContext } from '../../../providers/catalog-modal.provider'; -import { EntitiesContext } from '../../../providers/entities.provider'; +import { IDataTestID } from '../../../../models'; +import { AddStepMode, IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { CatalogModalContext } from '../../../../providers/catalog-modal.provider'; +import { EntitiesContext } from '../../../../providers/entities.provider'; interface ItemInsertStepProps extends PropsWithChildren { mode: AddStepMode.InsertChildStep | AddStepMode.InsertSpecialChildStep; diff --git a/packages/ui/src/components/Visualization/Custom/ItemReplaceStep.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemReplaceStep.tsx similarity index 81% rename from packages/ui/src/components/Visualization/Custom/ItemReplaceStep.tsx rename to packages/ui/src/components/Visualization/Custom/ContextMenu/ItemReplaceStep.tsx index 18cbc5547..c96db72b0 100644 --- a/packages/ui/src/components/Visualization/Custom/ItemReplaceStep.tsx +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/ItemReplaceStep.tsx @@ -1,10 +1,10 @@ import { SyncAltIcon } from '@patternfly/react-icons'; import { ContextMenuItem } from '@patternfly/react-topology'; import { FunctionComponent, PropsWithChildren, useCallback, useContext } from 'react'; -import { IDataTestID } from '../../../models'; -import { AddStepMode, IVisualizationNode } from '../../../models/visualization/base-visual-entity'; -import { CatalogModalContext } from '../../../providers/catalog-modal.provider'; -import { EntitiesContext } from '../../../providers/entities.provider'; +import { IDataTestID } from '../../../../models'; +import { AddStepMode, IVisualizationNode } from '../../../../models/visualization/base-visual-entity'; +import { CatalogModalContext } from '../../../../providers/catalog-modal.provider'; +import { EntitiesContext } from '../../../../providers/entities.provider'; interface ItemReplaceStepProps extends PropsWithChildren { vizNode: IVisualizationNode; diff --git a/packages/ui/src/components/Visualization/Custom/ContextMenu/NodeContextMenu.tsx b/packages/ui/src/components/Visualization/Custom/ContextMenu/NodeContextMenu.tsx new file mode 100644 index 000000000..789a0f6f1 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/ContextMenu/NodeContextMenu.tsx @@ -0,0 +1,119 @@ +import { ArrowDownIcon, ArrowUpIcon, CodeBranchIcon, PlusIcon } from '@patternfly/react-icons'; +import { ContextMenuSeparator, ElementModel, GraphElement } from '@patternfly/react-topology'; +import { FunctionComponent, ReactElement } from 'react'; +import { AddStepMode } from '../../../../models/visualization/base-visual-entity'; +import { CanvasNode } from '../../Canvas/canvas.models'; +import { ItemAddStep } from './ItemAddStep'; +import { ItemDeleteGroup } from './ItemDeleteGroup'; +import { ItemDeleteStep } from './ItemDeleteStep'; +import { ItemDisableStep } from './ItemDisableStep'; +import { ItemInsertStep } from './ItemInsertStep'; +import { ItemReplaceStep } from './ItemReplaceStep'; + +export const NodeContextMenuFn = (element: GraphElement) => { + const items: ReactElement[] = []; + const vizNode = element.getData()?.vizNode; + if (!vizNode) return items; + + const nodeInteractions = vizNode.getNodeInteraction(); + + if (nodeInteractions.canHavePreviousStep) { + items.push( + + Prepend + , + ); + } + if (nodeInteractions.canHaveNextStep) { + items.push( + + Append + , + ); + } + if (nodeInteractions.canHavePreviousStep || nodeInteractions.canHaveNextStep) { + items.push(); + } + + if (nodeInteractions.canHaveChildren) { + items.push( + + Add step + , + ); + } + if (nodeInteractions.canHaveSpecialChildren) { + items.push( + + Add branch + , + ); + } + if (nodeInteractions.canHaveChildren || nodeInteractions.canHaveSpecialChildren) { + items.push(); + } + + if (nodeInteractions.canBeDisabled) { + items.push( + , + ); + } + if (nodeInteractions.canReplaceStep) { + items.push( + , + ); + } + if (nodeInteractions.canBeDisabled || nodeInteractions.canReplaceStep) { + items.push(); + } + + if (nodeInteractions.canRemoveStep) { + const childrenNodes = vizNode.getChildren(); + const shouldConfirmBeforeDeletion = childrenNodes !== undefined && childrenNodes.length > 0; + items.push( + , + ); + } + if (nodeInteractions.canRemoveFlow) { + items.push( + , + ); + } + + return items; +}; + +export const NodeContextMenu: FunctionComponent<{ element: GraphElement }> = ({ + element, +}) => { + return <>{NodeContextMenuFn(element)}; +}; diff --git a/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx b/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx deleted file mode 100644 index 89aea0503..000000000 --- a/packages/ui/src/components/Visualization/Custom/CustomGroup.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { CodeBranchIcon } from '@patternfly/react-icons'; -import { - ContextMenuSeparator, - DefaultGroup, - ElementModel, - GraphElement, - Layer, - isNode, - observer, - withContextMenu, - withSelection, -} from '@patternfly/react-topology'; -import { FunctionComponent, ReactElement } from 'react'; -import { AddStepMode } from '../../../models/visualization/base-visual-entity'; -import { CanvasNode } from '../Canvas/canvas.models'; -import { ItemDeleteGroup } from './ItemDeleteGroup'; -import { ItemInsertStep } from './ItemInsertStep'; -import { doTruncateLabel } from '../../../utils/truncate-label'; - -type IDefaultGroup = Parameters[0]; -interface ICustomGroup extends IDefaultGroup { - element: GraphElement; -} - -const CustomGroup: FunctionComponent = observer(({ element, ...rest }) => { - const vizNode = element.getData()?.vizNode; - const label = vizNode?.getNodeLabel(); - - if (!isNode(element)) { - throw new Error('DefaultGroup must be used only on Node elements'); - } - - return ( - - - - - - ); -}); - -export const CustomGroupWithSelection = withSelection()( - withContextMenu((element: GraphElement) => { - const items: ReactElement[] = []; - const vizNode = element.getData()?.vizNode; - if (!vizNode) return items; - - const nodeInteractions = vizNode.getNodeInteraction(); - - if (nodeInteractions.canHaveSpecialChildren) { - items.push( - - Add branch - , - ); - items.push(); - } - - if (nodeInteractions.canRemoveFlow) { - items.push( - , - ); - } - - return items; - })(CustomGroup), -); diff --git a/packages/ui/src/components/Visualization/Custom/CustomNode.tsx b/packages/ui/src/components/Visualization/Custom/CustomNode.tsx deleted file mode 100644 index 429d25e89..000000000 --- a/packages/ui/src/components/Visualization/Custom/CustomNode.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { Tooltip } from '@patternfly/react-core'; -import { ArrowDownIcon, ArrowUpIcon, BanIcon, CodeBranchIcon, PlusIcon } from '@patternfly/react-icons'; -import { - ContextMenuSeparator, - Decorator, - DefaultNode, - ElementModel, - GraphElement, - Node, - NodeStatus, - WithSelectionProps, - observer, - withContextMenu, - withSelection, -} from '@patternfly/react-topology'; -import clsx from 'clsx'; -import { FunctionComponent, ReactElement, useContext } from 'react'; -import { AddStepMode } from '../../../models/visualization/base-visual-entity'; -import { CanvasDefaults } from '../Canvas/canvas.defaults'; -import { CanvasNode } from '../Canvas/canvas.models'; -import './CustomNode.scss'; -import { ItemAddStep } from './ItemAddStep'; -import { ItemDeleteGroup } from './ItemDeleteGroup'; -import { ItemDeleteStep } from './ItemDeleteStep'; -import { ItemDisableStep } from './ItemDisableStep'; -import { ItemInsertStep } from './ItemInsertStep'; -import { ItemReplaceStep } from './ItemReplaceStep'; -import { doTruncateLabel } from '../../../utils/truncate-label'; -import { SettingsContext } from '../../../providers'; - -interface CustomNodeProps extends WithSelectionProps { - element: Node; -} -const noopFn = () => {}; - -const CustomNode: FunctionComponent = observer(({ element, ...rest }) => { - const vizNode = element.getData()?.vizNode; - const settingsAdapter = useContext(SettingsContext); - const label = vizNode?.getNodeLabel(settingsAdapter.getSettings().nodeLabel); - const isDisabled = !!vizNode?.getComponentSchema()?.definition?.disabled; - const tooltipContent = vizNode?.getTooltipContent(); - const statusDecoratorTooltip = vizNode?.getNodeValidationText(); - const nodeStatus = !statusDecoratorTooltip || isDisabled ? NodeStatus.default : NodeStatus.warning; - - return ( - - - - -
- -
-
-
- - {isDisabled && ( - } - showBackground - /> - )} -
-
- ); -}); - -export const CustomNodeWithSelection: typeof DefaultNode = withSelection()( - withContextMenu((element: GraphElement) => { - const items: ReactElement[] = []; - const vizNode = element.getData()?.vizNode; - if (!vizNode) return items; - - const nodeInteractions = vizNode.getNodeInteraction(); - - if (nodeInteractions.canHavePreviousStep) { - items.push( - - Prepend - , - ); - } - if (nodeInteractions.canHaveNextStep) { - items.push( - - Append - , - ); - } - if (nodeInteractions.canHavePreviousStep || nodeInteractions.canHaveNextStep) { - items.push(); - } - - if (nodeInteractions.canHaveChildren) { - items.push( - - Add step - , - ); - } - if (nodeInteractions.canHaveSpecialChildren) { - items.push( - - Add branch - , - ); - } - if (nodeInteractions.canHaveChildren || nodeInteractions.canHaveSpecialChildren) { - items.push(); - } - - if (nodeInteractions.canBeDisabled) { - items.push( - , - ); - } - if (nodeInteractions.canReplaceStep) { - items.push( - , - ); - } - if (nodeInteractions.canBeDisabled || nodeInteractions.canReplaceStep) { - items.push(); - } - - if (nodeInteractions.canRemoveStep) { - const childrenNodes = vizNode.getChildren(); - const shouldConfirmBeforeDeletion = childrenNodes !== undefined && childrenNodes.length > 0; - items.push( - , - ); - } - if (nodeInteractions.canRemoveFlow) { - items.push( - , - ); - } - - return items; - })(CustomNode as typeof DefaultNode), -) as typeof DefaultNode; diff --git a/packages/ui/src/components/Visualization/Custom/Group/CollapseButton.tsx b/packages/ui/src/components/Visualization/Custom/Group/CollapseButton.tsx new file mode 100644 index 000000000..ec3f5ed10 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CollapseButton.tsx @@ -0,0 +1,26 @@ +import { Button, Tooltip } from '@patternfly/react-core'; +import { CompressArrowsAltIcon, ExpandArrowsAltIcon } from '@patternfly/react-icons'; +import { CollapsibleGroupProps } from '@patternfly/react-topology'; +import { FunctionComponent, MouseEventHandler } from 'react'; +import { CustomGroupProps } from './Group.models'; + +interface CollapseButtonProps { + element: CustomGroupProps['element']; + onCollapseChange?: CollapsibleGroupProps['onCollapseChange']; +} + +export const CollapseButton: FunctionComponent = ({ element, onCollapseChange }) => { + const id = element.getId(); + const onClick: MouseEventHandler = (event) => { + event.stopPropagation(); + onCollapseChange?.(element, !element.isCollapsed()); + }; + + return ( + + + + ); +}; diff --git a/packages/ui/src/components/Visualization/Custom/Group/ContextMenuButton.tsx b/packages/ui/src/components/Visualization/Custom/Group/ContextMenuButton.tsx new file mode 100644 index 000000000..805221716 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/ContextMenuButton.tsx @@ -0,0 +1,51 @@ +import { Button, Tooltip } from '@patternfly/react-core'; +import { EllipsisVIcon } from '@patternfly/react-icons'; +import { ContextMenu, PointIface } from '@patternfly/react-topology'; +import { FunctionComponent, MouseEventHandler, useRef, useState } from 'react'; +import { NodeContextMenu } from '../ContextMenu/NodeContextMenu'; +import { CustomGroupProps } from './Group.models'; + +interface ContextMenuButtonProps { + element: CustomGroupProps['element']; +} + +export const ContextMenuButton: FunctionComponent = ({ element }) => { + const [isOpen, setIsOpen] = useState(false); + const menuRef = useRef(null); + const reference = useRef({ x: 0, y: 0 }); + const id = element.getId(); + + const onClick: MouseEventHandler & MouseEventHandler = (event) => { + event.stopPropagation(); + setTimeout(() => { + if (menuRef.current) { + const firstElement = menuRef.current.querySelector( + 'li > button:not(:disabled), li > a:not(:disabled), input:not(:disabled)', + ); + firstElement?.focus(); + } + }, 0); + + reference.current = { x: event.clientX, y: event.clientY }; + setIsOpen(!isOpen); + }; + + return ( + <> + + + + { + setIsOpen(false); + }} + > + + + + ); +}; diff --git a/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.scss b/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.scss new file mode 100644 index 000000000..7264a38ac --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.scss @@ -0,0 +1,87 @@ +.phantom-rect { + stroke: transparent; + fill: transparent; +} + +.foreign-object { + overflow: auto; +} + +.container-controls { + padding: var(--pf-v5-global--BorderWidth--xl); +} + +.custom-group { + --custom-group--BorderColor: var(--pf-v5-global--palette--black-400); + --custom-group--BorderSize: var(--pf-v5-global--BorderWidth--md); + --custom-group--Background: var(--pf-v5-global--palette--white); + --custom-group-TitleHeight: 32px; + + display: flex; + flex-flow: column; + height: 100%; + width: 100%; + background-color: var(--custom-group--Background); + border-radius: var(--pf-v5-global--BorderWidth--xl); + border: var(--custom-group--BorderSize) solid var(--custom-group--BorderColor); + + &__title { + display: flex; + align-items: center; + font-size: var(--pf-v5-global--FontSize--md); + font-weight: bold; + color: var(--pf-v5-global--palette--black-900); + background-color: var(--pf-v5-global--palette--light-blue-400); + height: var(--custom-group-TitleHeight); + + &__img-circle { + margin: 5px -10px 5px 5px; + display: flex; + align-items: center; + justify-content: center; + width: calc(var(--custom-group-TitleHeight) * 0.9); + height: calc(var(--custom-group-TitleHeight) * 0.9); + border: var(--custom-group--BorderSize) solid var(--custom-group--BorderColor); + background-color: var(--pf-v5-global--palette--white); + border-radius: 50px; + + img { + max-width: calc(var(--custom-group-TitleHeight) * 0.6); + max-height: calc(var(--custom-group-TitleHeight) * 0.6); + } + } + + span { + margin: 0 var(--pf-v5-global--FontSize--md); + flex: 1 1 auto; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + + &:hover { + --custom-group--BorderColor: var(--pf-v5-global--primary-color--light-100); + --custom-group--Background: var(--pf-v5-global--palette--black-200); + } + + &--selected { + --custom-group--BorderColor: var(--pf-v5-global--palette--light-blue-400); + --custom-group--Background: var(--pf-v5-global--palette--blue-50); + --custom-group--BorderSize: var(--pf-v5-global--BorderWidth--lg); + + &:hover { + --custom-group--BorderColor: var(--pf-v5-global--palette--light-blue-400); + --custom-group--Background: var(--pf-v5-global--palette--blue-50); + } + } + + &--disabled { + filter: grayscale(100%); + + span { + font-style: italic; + text-decoration: line-through; + } + } +} diff --git a/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.tsx b/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.tsx new file mode 100644 index 000000000..fd7ed5b2b --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CustomGroup.tsx @@ -0,0 +1,43 @@ +import { + DefaultGroup, + GraphElement, + isNode, + observer, + withContextMenu, + withSelection, +} from '@patternfly/react-topology'; +import { FunctionComponent } from 'react'; +import { CanvasDefaults } from '../../Canvas/canvas.defaults'; +import { CanvasNode } from '../../Canvas/canvas.models'; +import { NodeContextMenuFn } from '../ContextMenu/NodeContextMenu'; +import './CustomGroup.scss'; +import { CustomGroupCollapsible } from './CustomGroupCollapsible'; + +type IDefaultGroup = Parameters[0]; +interface ICustomGroup extends IDefaultGroup { + element: GraphElement; +} + +const CustomGroup: FunctionComponent = observer(({ element, ...rest }) => { + const vizNode = element.getData()?.vizNode; + const label = vizNode?.getNodeLabel(); + + if (!isNode(element)) { + throw new Error('DefaultGroup must be used only on Node elements'); + } + + return ( + + ); +}); + +export const CustomGroupWithSelection = withSelection()(withContextMenu(NodeContextMenuFn)(CustomGroup)); diff --git a/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsed.tsx b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsed.tsx new file mode 100644 index 000000000..657bfe641 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsed.tsx @@ -0,0 +1,95 @@ +import { Tooltip } from '@patternfly/react-core'; +import { ExpandArrowsAltIcon } from '@patternfly/react-icons'; +import { + CollapsibleGroupProps, + GROUPS_LAYER, + LabelBadge, + Layer, + NodeLabel, + WithContextMenuProps, + WithDndDropProps, + WithDragNodeProps, + WithSelectionProps, + getShapeComponent, + observer, + useSvgAnchor, +} from '@patternfly/react-topology'; +import { FunctionComponent, useCallback } from 'react'; +import { CanvasDefaults } from '../../Canvas/canvas.defaults'; +import { CustomGroupProps } from './Group.models'; + +type CustomGroupExpandedProps = CustomGroupProps & + CollapsibleGroupProps & + WithDragNodeProps & + WithSelectionProps & + WithDndDropProps & + WithContextMenuProps; + +export const CustomGroupCollapsed: FunctionComponent = observer( + ({ + className, + children, + collapsedWidth = CanvasDefaults.DEFAULT_NODE_DIAMETER, + collapsedHeight = CanvasDefaults.DEFAULT_NODE_DIAMETER, + collapsedShadowOffset = 8, + element, + onSelect, + label: propsLabel, + onContextMenu, + contextMenuOpen, + onCollapseChange, + }) => { + const ShapeComponent = getShapeComponent(element); + const label = propsLabel || element.getLabel(); + const childCount = element.getAllNodeChildren().length; + const vizNode = element.getData()?.vizNode; + const tooltipContent = vizNode?.getTooltipContent(); + const anchorRef = useSvgAnchor(); + + const onActionIconClick = useCallback(() => { + onCollapseChange?.(element, false); + }, [element, onCollapseChange]); + + return ( + + + + + + + + + + + + + + + +
+ +
+
+
+
+
+ + {childCount && } + + } + onActionIconClick={onActionIconClick} + > + {label || element.getLabel()} + + {children} +
+ ); + }, +); diff --git a/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsible.tsx b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsible.tsx new file mode 100644 index 000000000..a055c6b8e --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupCollapsible.tsx @@ -0,0 +1,31 @@ +import { Dimensions, Node, observer } from '@patternfly/react-topology'; +import clsx from 'clsx'; +import { FunctionComponent } from 'react'; +import { CustomGroupCollapsed } from './CustomGroupCollapsed'; +import { CustomGroupExpanded } from './CustomGroupExpanded'; +import { CustomGroupProps } from './Group.models'; + +export const CustomGroupCollapsible: FunctionComponent = observer( + ({ className, element, selected, onCollapseChange, ...rest }) => { + const handleCollapse = (group: Node, collapsed: boolean): void => { + if (collapsed && rest.collapsedWidth !== undefined && rest.collapsedHeight !== undefined) { + group.setDimensions(new Dimensions(rest.collapsedWidth, rest.collapsedHeight)); + } + + group.setCollapsed(collapsed); + group.getController().getGraph().layout(); + + onCollapseChange?.(group, collapsed); + }; + const vizNode = element.getData()?.vizNode; + const isDisabled = !!vizNode?.getComponentSchema()?.definition?.disabled; + const classNames = clsx(className, { 'custom-group--selected': selected, 'custom-group--disabled': isDisabled }); + + if (element.isCollapsed()) { + return ( + + ); + } + return ; + }, +); diff --git a/packages/ui/src/components/Visualization/Custom/Group/CustomGroupExpanded.tsx b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupExpanded.tsx new file mode 100644 index 000000000..ed65f0dee --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/CustomGroupExpanded.tsx @@ -0,0 +1,125 @@ +import { + AbstractAnchor, + AnchorEnd, + CollapsibleGroupProps, + GROUPS_LAYER, + Layer, + Node, + Point, + Rect, + WithContextMenuProps, + WithDndDropProps, + WithDragNodeProps, + WithSelectionProps, + observer, + useAnchor, +} from '@patternfly/react-topology'; +import { FunctionComponent, useRef } from 'react'; +import { CollapseButton } from './CollapseButton'; +import { ContextMenuButton } from './ContextMenuButton'; +import { CustomGroupProps } from './Group.models'; + +type CustomGroupExpandedProps = CustomGroupProps & + CollapsibleGroupProps & + WithDragNodeProps & + WithSelectionProps & + WithDndDropProps & + WithContextMenuProps; + +class TargetAnchor extends AbstractAnchor { + getLocation(reference: Point): Point { + return this.closestPointOnRectangle(this.owner.getBounds(), reference); + } + + getReferencePoint(): Point { + return super.getReferencePoint(); + } + + private closestPointOnRectangle(rect: Rect, point: Point): Point { + // Deconstruct the rectangle and point parameters + const { x: rx, y: ry, width, height } = rect; + const { x: px, y: py } = point; + + // Calculate the projections on the edges + // For left edge + const leftX = rx; + const leftY = Math.max(ry, Math.min(py, ry + height)); + + // For right edge + const rightX = rx + width; + const rightY = Math.max(ry, Math.min(py, ry + height)); + + // For top edge + const topX = Math.max(rx, Math.min(px, rx + width)); + const topY = ry; + + // For bottom edge + const bottomX = Math.max(rx, Math.min(px, rx + width)); + const bottomY = ry + height; + + // Calculate distances to each edge projection + const distances = [ + { x: leftX, y: leftY, dist: Math.hypot(px - leftX, py - leftY) }, + { x: rightX, y: rightY, dist: Math.hypot(px - rightX, py - rightY) }, + { x: topX, y: topY, dist: Math.hypot(px - topX, py - topY) }, + { x: bottomX, y: bottomY, dist: Math.hypot(px - bottomX, py - bottomY) }, + ]; + + // Find the minimum distance + const closestPoint = distances.reduce((minPoint, currentPoint) => + currentPoint.dist < minPoint.dist ? currentPoint : minPoint, + ); + + // Return the closest point + return new Point(closestPoint.x, closestPoint.y); + } +} + +export const CustomGroupExpanded: FunctionComponent = observer( + ({ className, element, onSelect, label: propsLabel, onContextMenu, onCollapseChange }) => { + const label = propsLabel || element.getLabel(); + const boxRef = useRef(element.getBounds()); + const vizNode = element.getData()?.vizNode; + + useAnchor((element: Node) => { + return new TargetAnchor(element); + }, AnchorEnd.both); + + boxRef.current = element.getBounds(); + + return ( + + + + + +
+
+
+ +
+ {label} + + + +
+
+
+
+
+
+ ); + }, +); diff --git a/packages/ui/src/components/Visualization/Custom/Group/Group.models.ts b/packages/ui/src/components/Visualization/Custom/Group/Group.models.ts new file mode 100644 index 000000000..d88de46f9 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Group/Group.models.ts @@ -0,0 +1,9 @@ +import { Node, DefaultGroup as TopologyDefaultGroup } from '@patternfly/react-topology'; +import { CanvasNode } from '../../Canvas'; + +type DefaultGroupProps = Parameters[0]; +export interface CustomGroupProps extends DefaultGroupProps { + element: Node; +} + +export type PointWithSize = [number, number, number]; diff --git a/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx b/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx new file mode 100644 index 000000000..190fe2d2c --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx @@ -0,0 +1,7 @@ +import { BaseEdge, Point } from '@patternfly/react-topology'; + +export class NoBendpointsEdge extends BaseEdge { + getBendpoints(): Point[] { + return []; + } +} diff --git a/packages/ui/src/components/Visualization/Custom/CustomNode.scss b/packages/ui/src/components/Visualization/Custom/Node/CustomNode.scss similarity index 100% rename from packages/ui/src/components/Visualization/Custom/CustomNode.scss rename to packages/ui/src/components/Visualization/Custom/Node/CustomNode.scss diff --git a/packages/ui/src/components/Visualization/Custom/Node/CustomNode.tsx b/packages/ui/src/components/Visualization/Custom/Node/CustomNode.tsx new file mode 100644 index 000000000..7b4aeb4a4 --- /dev/null +++ b/packages/ui/src/components/Visualization/Custom/Node/CustomNode.tsx @@ -0,0 +1,82 @@ +import { Tooltip } from '@patternfly/react-core'; +import { BanIcon } from '@patternfly/react-icons'; +import { + Decorator, + DefaultNode, + Node, + NodeStatus, + WithSelectionProps, + observer, + withContextMenu, + withSelection, +} from '@patternfly/react-topology'; +import clsx from 'clsx'; +import { FunctionComponent, useContext } from 'react'; +import { SettingsContext } from '../../../../providers'; +import { doTruncateLabel } from '../../../../utils/truncate-label'; +import { CanvasDefaults } from '../../Canvas/canvas.defaults'; +import { CanvasNode } from '../../Canvas/canvas.models'; +import './CustomNode.scss'; +import { NodeContextMenuFn } from '../ContextMenu/NodeContextMenu'; + +interface CustomNodeProps extends WithSelectionProps { + element: Node; +} +const noopFn = () => {}; + +const CustomNode: FunctionComponent = observer(({ element, ...rest }) => { + const vizNode = element.getData()?.vizNode; + const settingsAdapter = useContext(SettingsContext); + const label = vizNode?.getNodeLabel(settingsAdapter.getSettings().nodeLabel); + const isDisabled = !!vizNode?.getComponentSchema()?.definition?.disabled; + const tooltipContent = vizNode?.getTooltipContent(); + const statusDecoratorTooltip = vizNode?.getNodeValidationText(); + const nodeStatus = !statusDecoratorTooltip || isDisabled ? NodeStatus.default : NodeStatus.warning; + + return ( + + + + +
+ +
+
+
+ + {isDisabled && ( + } + showBackground + /> + )} +
+
+ ); +}); + +export const CustomNodeWithSelection: typeof DefaultNode = withSelection()( + withContextMenu(NodeContextMenuFn)(CustomNode as typeof DefaultNode), +) as typeof DefaultNode; diff --git a/packages/ui/src/components/Visualization/Custom/index.ts b/packages/ui/src/components/Visualization/Custom/index.ts index cc33063f8..c64861e62 100644 --- a/packages/ui/src/components/Visualization/Custom/index.ts +++ b/packages/ui/src/components/Visualization/Custom/index.ts @@ -1,2 +1,3 @@ -export * from './CustomGroup'; -export * from './CustomNode'; +export * from './Group/CustomGroup'; +export * from './NoBendingEdge'; +export * from './Node/CustomNode'; diff --git a/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts b/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts index 052715e9e..e010275d8 100644 --- a/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts +++ b/packages/ui/src/models/visualization/flows/abstract-camel-visual-entity.ts @@ -190,7 +190,7 @@ export abstract class AbstractCamelVisualEntity implements Bas const canHaveChildren = stepsProperties.find((property) => property.type === 'branch') !== undefined; const canHaveSpecialChildren = Object.keys(stepsProperties).length > 1; const canReplaceStep = CamelComponentSchemaService.canReplaceStep(processorName); - const canRemoveStep = processorName !== ('from' as keyof ProcessorDefinition); + const canRemoveStep = !CamelComponentSchemaService.DISABLED_REMOVE_STEPS.includes(processorName); const canRemoveFlow = data.path === ROOT_PATH; const canBeDisabled = CamelComponentSchemaService.canBeDisabled(processorName); @@ -219,6 +219,7 @@ export abstract class AbstractCamelVisualEntity implements Bas entity: this, isGroup: true, icon: NodeIconResolver.getIcon(this.type, NodeIconType.VisualEntity), + processorName: 'route', }); const fromNode = CamelStepsService.getVizNodeFromProcessor( @@ -235,6 +236,22 @@ export abstract class AbstractCamelVisualEntity implements Bas } routeGroupNode.addChild(fromNode); + fromNode.getChildren()?.forEach((child, index) => { + routeGroupNode.addChild(child); + if (index === 0) { + fromNode.setNextNode(child); + child.setPreviousNode(fromNode); + } + + const previousChild = fromNode.getChildren()?.[index - 1]; + if (previousChild) { + previousChild.setNextNode(child); + child.setPreviousNode(previousChild); + } + }); + fromNode.getChildren()?.splice(0); + fromNode.data.isGroup = false; + return routeGroupNode; } diff --git a/packages/ui/src/models/visualization/flows/support/camel-component-schema.service.ts b/packages/ui/src/models/visualization/flows/support/camel-component-schema.service.ts index 59dd24605..bf2264424 100644 --- a/packages/ui/src/models/visualization/flows/support/camel-component-schema.service.ts +++ b/packages/ui/src/models/visualization/flows/support/camel-component-schema.service.ts @@ -12,6 +12,7 @@ import { CamelProcessorStepsProperties, ICamelElementLookupResult } from './came export class CamelComponentSchemaService { static DISABLED_SIBLING_STEPS = [ + 'route', 'from', 'onWhen', 'when', @@ -24,6 +25,7 @@ export class CamelComponentSchemaService { 'onException', 'onCompletion', ]; + static DISABLED_REMOVE_STEPS = ['from', 'route'] as unknown as (keyof ProcessorDefinition)[]; // eslint-disable-next-line @typescript-eslint/no-explicit-any static getVisualComponentSchema(path: string, definition: any): VisualComponentSchema | undefined { diff --git a/packages/ui/src/models/visualization/flows/support/camel-steps.service.ts b/packages/ui/src/models/visualization/flows/support/camel-steps.service.ts index 41d3aa130..eb145d74e 100644 --- a/packages/ui/src/models/visualization/flows/support/camel-steps.service.ts +++ b/packages/ui/src/models/visualization/flows/support/camel-steps.service.ts @@ -31,9 +31,15 @@ export class CamelStepsService { componentLookup.processorName as keyof ProcessorDefinition, ); + if (childrenStepsProperties.length > 0) { + vizNode.data.isGroup = true; + } + childrenStepsProperties.forEach((stepsProperty) => { const childrenVizNodes = this.getVizNodesFromChildren(path, stepsProperty, entityDefinition); - childrenVizNodes.forEach((childVizNode) => vizNode.addChild(childVizNode)); + childrenVizNodes.forEach((childVizNode) => { + vizNode.addChild(childVizNode); + }); }); return vizNode; diff --git a/packages/ui/src/stubs/camel-route-branch.ts b/packages/ui/src/stubs/camel-route-branch.ts new file mode 100644 index 000000000..26a2fc1c4 --- /dev/null +++ b/packages/ui/src/stubs/camel-route-branch.ts @@ -0,0 +1,34 @@ +import { parse } from 'yaml'; + +export const camelRouteBranch = parse(` +- route: + id: route-2768 + from: + id: from-4014 + uri: timer:template + parameters: + period: "1000" + steps: + - choice: + id: choice-3431 + otherwise: + id: otherwise-3653 + steps: + - log: + id: log-6808 + message: \${body} + when: + - id: when-4112 + steps: + - setHeader: + id: setHeader-6078 + expression: + simple: {} + expression: + simple: + expression: \${header.foo} == 1 + - to: + id: to-3757 + uri: sql + parameters: {} +`); diff --git a/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap b/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap new file mode 100644 index 000000000..acad8efd2 --- /dev/null +++ b/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap @@ -0,0 +1,4604 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Nodes and Edges should generate edges for steps with branches 1`] = ` +[ + { + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + "parentNode": [Circular], + "previousNode": [Circular], + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": [Circular], + }, + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "height": 75, + "id": "timer-1234", + "parentNode": "route-2768-1234", + "shape": "rect", + "type": "node", + "width": 75, + }, + { + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "height": 75, + "id": "setHeader-1234", + "parentNode": "when-1234", + "shape": "rect", + "type": "node", + "width": 75, + }, + { + "children": [ + "setHeader-1234", + ], + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "previousNode": undefined, + }, + }, + "group": true, + "id": "when-1234", + "label": "when-1234", + "parentNode": "choice-1234", + "style": { + "padding": 60, + }, + "type": "group", + }, + { + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "height": 75, + "id": "log-1234", + "parentNode": "otherwise-1234", + "shape": "rect", + "type": "node", + "width": 75, + }, + { + "children": [ + "log-1234", + ], + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + "previousNode": undefined, + }, + }, + "group": true, + "id": "otherwise-1234", + "label": "otherwise-1234", + "parentNode": "choice-1234", + "style": { + "padding": 60, + }, + "type": "group", + }, + { + "children": [ + "when-1234", + "otherwise-1234", + ], + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": [Circular], + }, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + }, + "group": true, + "id": "choice-1234", + "label": "choice-1234", + "parentNode": "route-2768-1234", + "style": { + "padding": 60, + }, + "type": "group", + }, + { + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": [Circular], + }, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + }, + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + [Circular], + [Circular], + [Circular], + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + "previousNode": undefined, + }, + }, + }, + }, + "height": 75, + "id": "sql-1234", + "parentNode": "route-2768-1234", + "shape": "rect", + "type": "node", + "width": 75, + }, + { + "children": [ + "timer-1234", + "choice-1234", + "sql-1234", + ], + "data": { + "vizNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + "parentNode": [Circular], + "previousNode": [Circular], + }, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": [Circular], + }, + "parentNode": [Circular], + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": "sql", + "icon": "", + "path": "from.steps.1.to", + "processorName": "to", + }, + "id": "sql-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.when.0.steps.0.setHeader", + "processorName": "setHeader", + }, + "id": "setHeader-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.when.0", + "processorName": "when", + }, + "id": "when-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [ + VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "data": { + "componentName": undefined, + "icon": "", + "path": "from.steps.0.choice.otherwise.steps.0.log", + "processorName": "log", + }, + "id": "log-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice.otherwise", + "processorName": "otherwise", + }, + "id": "otherwise-1234", + "nextNode": undefined, + "parentNode": [Circular], + "previousNode": undefined, + }, + ], + "data": { + "componentName": undefined, + "icon": "", + "isGroup": true, + "path": "from.steps.0.choice", + "processorName": "choice", + }, + "id": "choice-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": VisualizationNode { + "DISABLED_NODE_INTERACTION": { + "canBeDisabled": false, + "canHaveChildren": false, + "canHaveNextStep": false, + "canHavePreviousStep": false, + "canHaveSpecialChildren": false, + "canRemoveFlow": false, + "canRemoveStep": false, + "canReplaceStep": false, + }, + "children": [], + "data": { + "componentName": "timer", + "icon": "", + "isGroup": false, + "path": "from", + "processorName": "from", + }, + "id": "timer-1234", + "nextNode": [Circular], + "parentNode": [Circular], + "previousNode": undefined, + }, + }, + }, + ], + "data": { + "entity": { + "route": { + "from": { + "id": "from-4014", + "parameters": { + "period": "1000", + }, + "steps": [ + { + "choice": { + "id": "choice-3431", + "otherwise": { + "id": "otherwise-3653", + "steps": [ + { + "log": { + "id": "log-6808", + "message": "\${body}", + }, + }, + ], + }, + "when": [ + { + "expression": { + "simple": { + "expression": "\${header.foo} == 1", + }, + }, + "id": "when-4112", + "steps": [ + { + "setHeader": { + "expression": { + "simple": {}, + }, + "id": "setHeader-6078", + }, + }, + ], + }, + ], + }, + }, + { + "to": { + "id": "to-3757", + "parameters": {}, + "uri": "sql", + }, + }, + ], + "uri": "timer:template", + }, + "id": "route-2768", + }, + }, + "icon": "", + "isGroup": true, + "path": "#", + }, + "id": "route-2768-1234", + "nextNode": undefined, + "parentNode": undefined, + "previousNode": undefined, + }, + }, + "group": true, + "id": "route-2768-1234", + "label": "route-2768-1234", + "parentNode": undefined, + "style": { + "padding": 60, + }, + "type": "group", + }, +] +`; + +exports[`Nodes and Edges should generate edges for steps with branches 2`] = ` +[ + { + "edgeStyle": "solid", + "id": "timer-1234-to-choice-1234", + "source": "timer-1234", + "target": "choice-1234", + "type": "edge", + }, + { + "edgeStyle": "solid", + "id": "choice-1234-to-sql-1234", + "source": "choice-1234", + "target": "sql-1234", + "type": "edge", + }, +] +`; diff --git a/packages/ui/src/tests/nodes-edges.test.ts b/packages/ui/src/tests/nodes-edges.test.ts new file mode 100644 index 000000000..0d76696e1 --- /dev/null +++ b/packages/ui/src/tests/nodes-edges.test.ts @@ -0,0 +1,21 @@ +import { CamelRouteResource } from '../models/camel'; +import { CanvasService } from '../components/Visualization/Canvas/canvas.service'; +import { camelRouteBranch } from '../stubs/camel-route-branch'; + +describe('Nodes and Edges', () => { + beforeEach(() => { + CanvasService.nodes = []; + CanvasService.edges = []; + }); + + it('should generate edges for steps with branches', () => { + const camelResource = new CamelRouteResource(camelRouteBranch); + const [camelRoute] = camelResource.getVisualEntities(); + + const rootVizNode = camelRoute.toVizNode(); + const { nodes, edges } = CanvasService.getFlowDiagram(rootVizNode); + + expect(nodes).toMatchSnapshot(); + expect(edges).toMatchSnapshot(); + }); +});