From 5e414147199a34e051d9b592af6dd8d088253b40 Mon Sep 17 00:00:00 2001 From: "Ricardo M." Date: Thu, 17 Oct 2024 16:10:54 +0200 Subject: [PATCH] feat(Edge): Use Decorator for adding a + icon --- .../e2e/codeEditor/multiFlowEditor.cy.ts | 3 +- .../multiflow/multiFlowDesigner.cy.ts | 3 +- .../Canvas/__snapshots__/Canvas.test.tsx.snap | 724 +++++++++++++++--- .../Visualization/Canvas/flow.service.test.ts | 16 +- .../Visualization/Custom/Edge/CustomEdge.scss | 20 - .../Visualization/Custom/Edge/EdgeEnd.tsx | 62 +- .../Visualization/Custom/NoBendingEdge.tsx | 15 +- .../__snapshots__/nodes-edges.test.ts.snap | 21 + 8 files changed, 701 insertions(+), 163 deletions(-) delete mode 100644 packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.scss diff --git a/packages/ui-tests/cypress/e2e/codeEditor/multiFlowEditor.cy.ts b/packages/ui-tests/cypress/e2e/codeEditor/multiFlowEditor.cy.ts index 9157561e5..3286e13fa 100644 --- a/packages/ui-tests/cypress/e2e/codeEditor/multiFlowEditor.cy.ts +++ b/packages/ui-tests/cypress/e2e/codeEditor/multiFlowEditor.cy.ts @@ -56,7 +56,8 @@ describe('Test for Multi route actions from the code editor', () => { cy.editorDeleteLine(7, 4); cy.openDesignPage(); cy.showAllRoutes(); - cy.get('[data-id^="log"]').should('have.length', 1); + /** We check how many nodes are remaining */ + cy.get('[data-id^="log"][data-kind="node"]').should('have.length', 1); cy.get('[data-testid="flows-list-route-count"]').should('have.text', '2/2'); }); diff --git a/packages/ui-tests/cypress/e2e/designer/multiflow/multiFlowDesigner.cy.ts b/packages/ui-tests/cypress/e2e/designer/multiflow/multiFlowDesigner.cy.ts index 6f9f8205b..a4ab36036 100644 --- a/packages/ui-tests/cypress/e2e/designer/multiflow/multiFlowDesigner.cy.ts +++ b/packages/ui-tests/cypress/e2e/designer/multiflow/multiFlowDesigner.cy.ts @@ -101,7 +101,8 @@ describe('Test for Multi route actions from the canvas', () => { cy.addNewRoute(); cy.showAllRoutes(); - cy.get('[data-id^="log"]').should('have.length', 3); + /** We check how many nodes are remaining */ + cy.get('[data-id^="log"][data-kind="node"]').should('have.length', 3); cy.get('[data-testid="flows-list-route-count"]').should('have.text', '3/3'); }); }); diff --git a/packages/ui/src/components/Visualization/Canvas/__snapshots__/Canvas.test.tsx.snap b/packages/ui/src/components/Visualization/Canvas/__snapshots__/Canvas.test.tsx.snap index 7c4630a16..099ea61a6 100644 --- a/packages/ui/src/components/Visualization/Canvas/__snapshots__/Canvas.test.tsx.snap +++ b/packages/ui/src/components/Visualization/Canvas/__snapshots__/Canvas.test.tsx.snap @@ -30,6 +30,23 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` + + + + + @@ -70,7 +87,7 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` class="foreign-object" data-nodelabel="route-8888" height="902.5" - width="870" + width="900" x="-85" y="12.5" > @@ -154,7 +171,7 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` @@ -162,7 +179,7 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` class="foreign-object" data-nodelabel="choice" height="637.5" - width="750" + width="780" x="-25" y="72.5" > @@ -246,7 +263,7 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` @@ -254,7 +271,7 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` class="foreign-object" data-nodelabel="otherwise" height="205" - width="360" + width="390" x="305" y="445" > @@ -344,16 +361,16 @@ exports[`Canvas Catalog button should NOT be present if \`CatalogModalContext\` > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -789,6 +924,23 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p + + + + + @@ -829,7 +981,7 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p class="foreign-object" data-nodelabel="route-8888" height="902.5" - width="870" + width="900" x="-85" y="12.5" > @@ -913,7 +1065,7 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p @@ -921,7 +1073,7 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p class="foreign-object" data-nodelabel="choice" height="637.5" - width="750" + width="780" x="-25" y="72.5" > @@ -1005,7 +1157,7 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p @@ -1013,7 +1165,7 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p class="foreign-object" data-nodelabel="otherwise" height="205" - width="360" + width="390" x="305" y="445" > @@ -1103,16 +1255,16 @@ exports[`Canvas Catalog button should be present if \`CatalogModalContext\` is p > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2360,6 +2630,23 @@ exports[`Canvas should render correctly 1`] = ` + + + + + @@ -2400,7 +2687,7 @@ exports[`Canvas should render correctly 1`] = ` class="foreign-object" data-nodelabel="route-8888" height="902.5" - width="870" + width="900" x="-85" y="12.5" > @@ -2484,7 +2771,7 @@ exports[`Canvas should render correctly 1`] = ` @@ -2492,7 +2779,7 @@ exports[`Canvas should render correctly 1`] = ` class="foreign-object" data-nodelabel="choice" height="637.5" - width="750" + width="780" x="-25" y="72.5" > @@ -2576,7 +2863,7 @@ exports[`Canvas should render correctly 1`] = ` @@ -2584,7 +2871,7 @@ exports[`Canvas should render correctly 1`] = ` class="foreign-object" data-nodelabel="otherwise" height="205" - width="360" + width="390" x="305" y="445" > @@ -2674,16 +2961,16 @@ exports[`Canvas should render correctly 1`] = ` > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3119,6 +3524,23 @@ exports[`Canvas should render correctly with more routes 1`] = ` + + + + + @@ -3159,7 +3581,7 @@ exports[`Canvas should render correctly with more routes 1`] = ` class="foreign-object" data-nodelabel="route-8888" height="902.5" - width="870" + width="900" x="-85" y="12.5" > @@ -3243,7 +3665,7 @@ exports[`Canvas should render correctly with more routes 1`] = ` @@ -3251,7 +3673,7 @@ exports[`Canvas should render correctly with more routes 1`] = ` class="foreign-object" data-nodelabel="choice" height="637.5" - width="750" + width="780" x="-25" y="72.5" > @@ -3335,7 +3757,7 @@ exports[`Canvas should render correctly with more routes 1`] = ` @@ -3343,7 +3765,7 @@ exports[`Canvas should render correctly with more routes 1`] = ` class="foreign-object" data-nodelabel="otherwise" height="205" - width="360" + width="390" x="305" y="445" > @@ -3433,16 +3855,16 @@ exports[`Canvas should render correctly with more routes 1`] = ` > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ui/src/components/Visualization/Canvas/flow.service.test.ts b/packages/ui/src/components/Visualization/Canvas/flow.service.test.ts index 25a71e49c..6918ada83 100644 --- a/packages/ui/src/components/Visualization/Canvas/flow.service.test.ts +++ b/packages/ui/src/components/Visualization/Canvas/flow.service.test.ts @@ -1,5 +1,4 @@ -import { createVisualizationNode } from '../../../models/visualization'; -import { BaseVisualCamelEntity } from '../../../models/visualization/base-visual-entity'; +import { CamelRouteVisualEntity, createVisualizationNode } from '../../../models/visualization'; import { FlowService } from './flow.service'; describe('FlowService', () => { @@ -86,18 +85,7 @@ describe('FlowService', () => { }); it('should return a group node for a multiple nodes VisualizationNode with a group', () => { - const routeNode = createVisualizationNode('route', { - entity: { getId: () => 'myId' } as BaseVisualCamelEntity, - isGroup: true, - }); - - const fromNode = createVisualizationNode('timer', { - path: 'from', - icon: undefined, - processorName: 'from', - componentName: 'timer', - }); - routeNode.addChild(fromNode); + const routeNode = new CamelRouteVisualEntity({ from: { uri: 'timer:clock', steps: [] } }).toVizNode(); const { nodes, edges } = FlowService.getFlowDiagram(routeNode); diff --git a/packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.scss b/packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.scss deleted file mode 100644 index 053328e3a..000000000 --- a/packages/ui/src/components/Visualization/Custom/Edge/CustomEdge.scss +++ /dev/null @@ -1,20 +0,0 @@ -/* stylelint-disable */ - -.custom-edge { - --pf-topology__edge--m-hover--background--Stroke: none; - background: var(--pf-v5-global--palette--white); - &__end { - border-radius: 3px; - border: 1px solid var(--pf-v5-global--palette--black-400); - --pf-topology__node--Color: var(--pf-v5-global--palette--black-500); - width: 24px; - height: 24px; - padding: 3px; - display: flex; - position: relative; - - &:hover { - border-color: var(--pf-v5-global--palette--blue-500); - } - } -} diff --git a/packages/ui/src/components/Visualization/Custom/Edge/EdgeEnd.tsx b/packages/ui/src/components/Visualization/Custom/Edge/EdgeEnd.tsx index e1101a7a6..3feb83e1e 100644 --- a/packages/ui/src/components/Visualization/Custom/Edge/EdgeEnd.tsx +++ b/packages/ui/src/components/Visualization/Custom/Edge/EdgeEnd.tsx @@ -1,53 +1,57 @@ -import { DefaultEdge, Edge, EdgeModel, EdgeTerminalType, observer } from '@patternfly/react-topology'; -import { Button, Tooltip } from '@patternfly/react-core'; import { PlusIcon } from '@patternfly/react-icons'; -import './CustomEdge.scss'; -import { addNode } from '../ContextMenu/ItemAddStep'; -import { CatalogModalContext, EntitiesContext } from '../../../../providers'; -import { useContext } from 'react'; +import { + Decorator, + DefaultEdge, + EdgeModel, + EdgeTerminalType, + GraphElement, + isEdge, + observer, +} from '@patternfly/react-topology'; +import { FunctionComponent, useCallback, useContext } from 'react'; import { IVisualizationNode } from '../../../../models'; +import { CatalogModalContext, EntitiesContext } from '../../../../providers'; +import { addNode } from '../ContextMenu/ItemAddStep'; +import { LayoutType } from '../../Canvas'; -interface EdgeEndProps { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - element: Edge; +type DefaultEdgeProps = Parameters[0]; +interface EdgeEndProps extends DefaultEdgeProps { + /** We're not providing Data to edges */ + element: GraphElement; } -const EdgeEnd: React.FC = observer(({ element, ...rest }) => { +export const EdgeEndWithButton: FunctionComponent = observer(({ element, ...rest }) => { + if (!isEdge(element)) { + throw new Error('EdgeEndWithButton must be used only on Edge elements'); + } const entitiesContext = useContext(EntitiesContext); const catalogModalContext = useContext(CatalogModalContext); const vizNode: IVisualizationNode = element.getSource().getData()?.vizNode; - const isHorizontal = element.getGraph().getLayout() === 'DagreHorizontal'; + const isHorizontal = element.getGraph().getLayout() === LayoutType.DagreHorizontal; const endPoint = element.getEndPoint(); - let x, y; + + const onAdd = useCallback(() => { + addNode(catalogModalContext, entitiesContext, vizNode); + }, [catalogModalContext, entitiesContext, vizNode]); + + let x = endPoint.x; + let y = endPoint.y; if (isHorizontal) { - x = endPoint.x; - y = endPoint.y - 12; + x += 12; } else { - x = endPoint.x - 12; - y = endPoint.y; + y += 4; } - const onAdd = () => { - addNode(catalogModalContext, entitiesContext, vizNode); - }; + return ( - - - - - + } onClick={onAdd} /> ); }); - -export const EdgeEndWithButton: typeof DefaultEdge = EdgeEnd as typeof DefaultEdge; diff --git a/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx b/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx index 286de213d..6cf06b7f2 100644 --- a/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx +++ b/packages/ui/src/components/Visualization/Custom/NoBendingEdge.tsx @@ -1,13 +1,15 @@ import { BaseEdge, getTopCollapsedParent, Point } from '@patternfly/react-topology'; +import { LayoutType } from '../Canvas'; export class NoBendpointsEdge extends BaseEdge { getBendpoints(): Point[] { return []; } + getStartPoint(): Point { if (this.getTarget() === this.getSource()) { const parent = getTopCollapsedParent(this.getSource()); - const isHorizontal = this.getGraph().getLayout() === 'DagreHorizontal'; + const isHorizontal = this.getGraph().getLayout() === LayoutType.DagreHorizontal; const parentPos = parent.getPosition(); const parentSize = parent.getDimensions(); let x, y; @@ -29,14 +31,15 @@ export class NoBendpointsEdge extends BaseEdge { } } return new Point(x, y); - } else { - return super.getStartPoint(); } + + return super.getStartPoint(); } + getEndPoint(): Point { if (this.getTarget() === this.getSource()) { const parent = getTopCollapsedParent(this.getSource()); - const isHorizontal = this.getGraph().getLayout() === 'DagreHorizontal'; + const isHorizontal = this.getGraph().getLayout() === LayoutType.DagreHorizontal; const parentPos = parent.getPosition(); const parentSize = parent.getDimensions(); let x, y; @@ -58,8 +61,8 @@ export class NoBendpointsEdge extends BaseEdge { } } return new Point(x, y); - } else { - return super.getEndPoint(); } + + return super.getEndPoint(); } } diff --git a/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap b/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap index 2fb521901..de387427c 100644 --- a/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap +++ b/packages/ui/src/tests/__snapshots__/nodes-edges.test.ts.snap @@ -4922,6 +4922,20 @@ exports[`Nodes and Edges should generate edges for steps with branches 2`] = ` "target": "choice-1234", "type": "edge", }, + { + "edgeStyle": "dashed", + "id": "setHeader-1234-end", + "source": "setHeader-1234", + "target": "setHeader-1234", + "type": "edge-end", + }, + { + "edgeStyle": "dashed", + "id": "log-1234-end", + "source": "log-1234", + "target": "log-1234", + "type": "edge-end", + }, { "edgeStyle": "solid", "id": "choice-1234-to-sql-1234", @@ -4929,5 +4943,12 @@ exports[`Nodes and Edges should generate edges for steps with branches 2`] = ` "target": "sql-1234", "type": "edge", }, + { + "edgeStyle": "dashed", + "id": "sql-1234-end", + "source": "sql-1234", + "target": "sql-1234", + "type": "edge-end", + }, ] `;