### What problem does this PR solve? feat: remove dagre and elkjs #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.9.0
| @@ -15,10 +15,8 @@ | |||
| "antd": "^5.12.7", | |||
| "axios": "^1.6.3", | |||
| "classnames": "^2.5.1", | |||
| "dagre": "^0.8.5", | |||
| "dayjs": "^1.11.10", | |||
| "dompurify": "^3.1.6", | |||
| "elkjs": "^0.9.3", | |||
| "eventsource-parser": "^1.1.2", | |||
| "human-id": "^4.1.1", | |||
| "i18next": "^23.7.16", | |||
| @@ -52,7 +50,6 @@ | |||
| "@redux-devtools/extension": "^3.3.0", | |||
| "@testing-library/jest-dom": "^6.4.5", | |||
| "@testing-library/react": "^15.0.7", | |||
| "@types/dagre": "^0.7.52", | |||
| "@types/dompurify": "^3.0.5", | |||
| "@types/jest": "^29.5.12", | |||
| "@types/lodash": "^4.14.202", | |||
| @@ -4844,12 +4841,6 @@ | |||
| "@types/d3-selection": "*" | |||
| } | |||
| }, | |||
| "node_modules/@types/dagre": { | |||
| "version": "0.7.52", | |||
| "resolved": "https://registry.npmmirror.com/@types/dagre/-/dagre-0.7.52.tgz", | |||
| "integrity": "sha512-XKJdy+OClLk3hketHi9Qg6gTfe1F3y+UFnHxKA2rn9Dw+oXa4Gb378Ztz9HlMgZKSxpPmn4BNVh9wgkpvrK1uw==", | |||
| "dev": true | |||
| }, | |||
| "node_modules/@types/debug": { | |||
| "version": "4.1.12", | |||
| "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz", | |||
| @@ -10140,15 +10131,6 @@ | |||
| "node": ">=12" | |||
| } | |||
| }, | |||
| "node_modules/dagre": { | |||
| "version": "0.8.5", | |||
| "resolved": "https://registry.npmmirror.com/dagre/-/dagre-0.8.5.tgz", | |||
| "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", | |||
| "dependencies": { | |||
| "graphlib": "^2.1.8", | |||
| "lodash": "^4.17.15" | |||
| } | |||
| }, | |||
| "node_modules/data-uri-to-buffer": { | |||
| "version": "4.0.1", | |||
| "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", | |||
| @@ -11114,11 +11096,6 @@ | |||
| "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.767.tgz", | |||
| "integrity": "sha512-nzzHfmQqBss7CE3apQHkHjXW77+8w3ubGCIoEijKCJebPufREaFETgGXWTkh32t259F3Kcq+R8MZdFdOJROgYw==" | |||
| }, | |||
| "node_modules/elkjs": { | |||
| "version": "0.9.3", | |||
| "resolved": "https://registry.npmmirror.com/elkjs/-/elkjs-0.9.3.tgz", | |||
| "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==" | |||
| }, | |||
| "node_modules/elliptic": { | |||
| "version": "6.5.5", | |||
| "resolved": "https://registry.npmmirror.com/elliptic/-/elliptic-6.5.5.tgz", | |||
| @@ -12982,14 +12959,6 @@ | |||
| "resolved": "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz", | |||
| "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" | |||
| }, | |||
| "node_modules/graphlib": { | |||
| "version": "2.1.8", | |||
| "resolved": "https://registry.npmmirror.com/graphlib/-/graphlib-2.1.8.tgz", | |||
| "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", | |||
| "dependencies": { | |||
| "lodash": "^4.17.15" | |||
| } | |||
| }, | |||
| "node_modules/gzip-size": { | |||
| "version": "6.0.0", | |||
| "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz", | |||
| @@ -26,10 +26,8 @@ | |||
| "antd": "^5.12.7", | |||
| "axios": "^1.6.3", | |||
| "classnames": "^2.5.1", | |||
| "dagre": "^0.8.5", | |||
| "dayjs": "^1.11.10", | |||
| "dompurify": "^3.1.6", | |||
| "elkjs": "^0.9.3", | |||
| "eventsource-parser": "^1.1.2", | |||
| "human-id": "^4.1.1", | |||
| "i18next": "^23.7.16", | |||
| @@ -63,7 +61,6 @@ | |||
| "@redux-devtools/extension": "^3.3.0", | |||
| "@testing-library/jest-dom": "^6.4.5", | |||
| "@testing-library/react": "^15.0.7", | |||
| "@types/dagre": "^0.7.52", | |||
| "@types/dompurify": "^3.0.5", | |||
| "@types/jest": "^29.5.12", | |||
| "@types/lodash": "^4.14.202", | |||
| @@ -1,35 +0,0 @@ | |||
| import { useCallback, useLayoutEffect } from 'react'; | |||
| import { getLayoutedElements } from './elk-utils'; | |||
| export const elkOptions = { | |||
| 'elk.algorithm': 'layered', | |||
| 'elk.layered.spacing.nodeNodeBetweenLayers': '100', | |||
| 'elk.spacing.nodeNode': '80', | |||
| }; | |||
| export const useLayoutGraph = ( | |||
| initialNodes, | |||
| initialEdges, | |||
| setNodes, | |||
| setEdges, | |||
| ) => { | |||
| const onLayout = useCallback(({ direction, useInitialNodes = false }) => { | |||
| const opts = { 'elk.direction': direction, ...elkOptions }; | |||
| const ns = initialNodes; | |||
| const es = initialEdges; | |||
| getLayoutedElements(ns, es, opts).then( | |||
| ({ nodes: layoutedNodes, edges: layoutedEdges }) => { | |||
| setNodes(layoutedNodes); | |||
| setEdges(layoutedEdges); | |||
| // window.requestAnimationFrame(() => fitView()); | |||
| }, | |||
| ); | |||
| }, []); | |||
| // Calculate the initial layout on mount. | |||
| useLayoutEffect(() => { | |||
| onLayout({ direction: 'RIGHT', useInitialNodes: true }); | |||
| }, [onLayout]); | |||
| }; | |||
| @@ -1,42 +0,0 @@ | |||
| import ELK from 'elkjs/lib/elk.bundled.js'; | |||
| import { Edge, Node } from 'reactflow'; | |||
| const elk = new ELK(); | |||
| export const getLayoutedElements = ( | |||
| nodes: Node[], | |||
| edges: Edge[], | |||
| options = {}, | |||
| ) => { | |||
| const isHorizontal = options?.['elk.direction'] === 'RIGHT'; | |||
| const graph = { | |||
| id: 'root', | |||
| layoutOptions: options, | |||
| children: nodes.map((node) => ({ | |||
| ...node, | |||
| // Adjust the target and source handle positions based on the layout | |||
| // direction. | |||
| targetPosition: isHorizontal ? 'left' : 'top', | |||
| sourcePosition: isHorizontal ? 'right' : 'bottom', | |||
| // Hardcode a width and height for elk to use when layouting. | |||
| width: 150, | |||
| height: 50, | |||
| })), | |||
| edges: edges, | |||
| }; | |||
| return elk | |||
| .layout(graph) | |||
| .then((layoutedGraph) => ({ | |||
| nodes: layoutedGraph.children.map((node) => ({ | |||
| ...node, | |||
| // React Flow expects a position property on the node instead of `x` | |||
| // and `y` fields. | |||
| position: { x: node.x, y: node.y }, | |||
| })), | |||
| edges: layoutedGraph.edges, | |||
| })) | |||
| .catch(console.error); | |||
| }; | |||
| @@ -1,6 +1,5 @@ | |||
| import { DSLComponents } from '@/interfaces/database/flow'; | |||
| import { removeUselessFieldsFromValues } from '@/utils/form'; | |||
| import dagre from 'dagre'; | |||
| import { humanId } from 'human-id'; | |||
| import { curry, sample } from 'lodash'; | |||
| import pipe from 'lodash/fp/pipe'; | |||
| @@ -80,48 +79,6 @@ export const buildNodesAndEdgesFromDSLComponents = (data: DSLComponents) => { | |||
| return { nodes, edges }; | |||
| }; | |||
| const dagreGraph = new dagre.graphlib.Graph(); | |||
| dagreGraph.setDefaultEdgeLabel(() => ({})); | |||
| const nodeWidth = 172; | |||
| const nodeHeight = 36; | |||
| export const getLayoutedElements = ( | |||
| nodes: Node[], | |||
| edges: Edge[], | |||
| direction = 'TB', | |||
| ) => { | |||
| const isHorizontal = direction === 'LR'; | |||
| dagreGraph.setGraph({ rankdir: direction }); | |||
| nodes.forEach((node) => { | |||
| dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight }); | |||
| }); | |||
| edges.forEach((edge) => { | |||
| dagreGraph.setEdge(edge.source, edge.target); | |||
| }); | |||
| dagre.layout(dagreGraph); | |||
| nodes.forEach((node) => { | |||
| const nodeWithPosition = dagreGraph.node(node.id); | |||
| node.targetPosition = isHorizontal ? Position.Left : Position.Top; | |||
| node.sourcePosition = isHorizontal ? Position.Right : Position.Bottom; | |||
| // We are shifting the dagre node position (anchor=center center) to the top left | |||
| // so it matches the React Flow node anchor point (top left). | |||
| node.position = { | |||
| x: nodeWithPosition.x - nodeWidth / 2, | |||
| y: nodeWithPosition.y - nodeHeight / 2, | |||
| }; | |||
| return node; | |||
| }); | |||
| return { nodes, edges }; | |||
| }; | |||
| const buildComponentDownstreamOrUpstream = ( | |||
| edges: Edge[], | |||
| nodeId: string, | |||