Skip to content

Commit 1710744

Browse files
fix: possibility of moving blocks in visualiser (#516)
1 parent 462c86e commit 1710744

File tree

3 files changed

+27
-50
lines changed

3 files changed

+27
-50
lines changed

src/components/Visualiser/Controls.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const Controls: FunctionComponent<ControlsProps> = () => {
2525
}, [animateNodes]);
2626

2727
const reloadInterface = () => {
28-
setNodes([...calculateNodesForDynamicLayout(nodes)]);
28+
setNodes(calculateNodesForDynamicLayout(nodes));
2929
fitView();
3030
};
3131

src/components/Visualiser/FlowDiagram.tsx

Lines changed: 21 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,44 @@
1-
import { useState, useEffect, useCallback } from 'react';
2-
import ReactFlow, { Controls as FlowControls, Background, BackgroundVariant, useReactFlow, useStore, useNodesState, useEdgesState, useNodes, useEdges } from 'reactflow';
1+
import { useEffect } from 'react';
2+
import ReactFlow, { Controls as FlowControls, Background, BackgroundVariant, useReactFlow, useStore, useNodesState, useEdgesState, useNodes } from 'reactflow';
33

4-
import { Controls } from './Controls';
54
import NodeTypes from './Nodes';
5+
import { Controls } from './Controls';
66
import { getElementsFromAsyncAPISpec } from './utils/node-factory';
77
import { calculateNodesForDynamicLayout } from './utils/node-calculator';
88

99
import type { OldAsyncAPIDocument as AsyncAPIDocument } from '@asyncapi/parser/cjs';
10-
import type { FunctionComponent, PropsWithChildren } from 'react';
11-
import type { ReactFlowInstance } from 'reactflow';
10+
import type { FunctionComponent } from 'react';
1211

1312
interface FlowDiagramProps {
1413
parsedSpec: AsyncAPIDocument;
1514
}
1615

17-
interface AutoLayoutProps extends PropsWithChildren {
18-
elementsToRenderNumber: number;
19-
}
16+
interface AutoLayoutProps {}
2017

21-
const AutoLayout: FunctionComponent<AutoLayoutProps> = ({ elementsToRenderNumber }) => {
18+
const AutoLayout: FunctionComponent<AutoLayoutProps> = () => {
2219
const { fitView } = useReactFlow();
2320
const nodes = useNodes();
24-
const edges = useEdges();
2521
const setNodes = useStore(state => state.setNodes);
2622

27-
const rerender = () => {
28-
const calculatedNodes = calculateNodesForDynamicLayout(nodes);
29-
setNodes(calculatedNodes);
30-
fitView();
31-
};
32-
3323
useEffect(() => {
34-
if (elementsToRenderNumber === (nodes.length + edges.length)) {
35-
// stop overlap no nodes when re-render, recalculate where they should go
36-
const nodesWithOrginalPosition = nodes.filter(node => node.position.x === 0 && node.position.y === 0);
37-
if (nodesWithOrginalPosition.length > 1) {
38-
setTimeout(() => {
39-
rerender();
40-
}, 1);
41-
}
24+
if (nodes.length === 0 || !nodes[0].width) {
25+
return;
26+
}
27+
28+
const nodesWithOrginalPosition = nodes.filter(node => node.position.x === 0 && node.position.y === 0);
29+
if (nodesWithOrginalPosition.length > 1) {
30+
const calculatedNodes = calculateNodesForDynamicLayout(nodes);
31+
setNodes(calculatedNodes);
32+
fitView();
4233
}
4334
}, [nodes]);
4435

4536
return null;
4637
};
4738

4839
export const FlowDiagram: FunctionComponent<FlowDiagramProps> = ({ parsedSpec }) => {
49-
const [loaded, setLoaded] = useState(false);
50-
51-
const elements = getElementsFromAsyncAPISpec(parsedSpec);
52-
const _nodes = elements.map(el => el.node).filter(Boolean);
53-
const _edges = elements.map(el => el.edge).filter(Boolean);
54-
55-
const [nodes, setNodes, onNodesChange] = useNodesState(_nodes);
56-
const [edges, setEdges, onEdgesChange] = useEdgesState(_edges);
57-
58-
const onInit = useCallback((instance: ReactFlowInstance) => {
59-
setLoaded(true);
60-
instance.fitView();
61-
}, []);
40+
const [nodes, setNodes, onNodesChange] = useNodesState([]);
41+
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
6242

6343
useEffect(() => {
6444
const elements = getElementsFromAsyncAPISpec(parsedSpec);
@@ -76,15 +56,15 @@ export const FlowDiagram: FunctionComponent<FlowDiagramProps> = ({ parsedSpec })
7656
nodes={nodes}
7757
edges={edges}
7858
minZoom={0.1}
79-
onInit={onInit}
8059
onNodesChange={onNodesChange}
8160
onEdgesChange={onEdgesChange}
61+
fitView={true}
8262
>
83-
<Background color="#d1d1d3" variant={BackgroundVariant.Dots} gap={20} size={1} className="bg-gray-200" />
84-
{loaded && <AutoLayout elementsToRenderNumber={nodes.length + edges.length} />}
63+
<Background variant={BackgroundVariant.Dots} gap={20} size={1} className="bg-gray-200" />
64+
<AutoLayout />
8565
<Controls />
8666
<div className="-mt-20">
87-
<FlowControls style={{ bottom: '105px' }} />
67+
<FlowControls style={{ bottom: '95px' }} className='bg-white' />
8868
</div>
8969
</ReactFlow>
9070
<div className="m-4 px-2 text-lg absolute text-gray-800 top-0 left-0 bg-white space-x-2 py-2 border border-gray-100 inline-block">

src/components/Visualiser/utils/node-calculator.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const calculateNodesForDynamicLayout = (elements: Node[]) => {
2222
const elementsGroupedByColumn = groupNodesByColumn(elements);
2323

2424
const newElements: { nodes: Node[], currentXPosition: number } = Object.keys(elementsGroupedByColumn).reduce(
25-
(data: any, group: string) => {
25+
(data: { nodes: Node[], currentXPosition: number }, group: string) => {
2626
const groupNodes = elementsGroupedByColumn[String(group)];
2727

2828
// eslint-disable-next-line
@@ -35,24 +35,21 @@ export const calculateNodesForDynamicLayout = (elements: Node[]) => {
3535

3636
// For each group (column), render the nodes based on height they require (with some padding)
3737
const { positionedNodes } = groupNodes.reduce(
38-
(groupedNodes: any, currentNode: Node) => {
38+
(groupedNodes: { positionedNodes: Node[], currentYPosition: number }, currentNode: Node) => {
3939
const verticalPadding = 40;
4040

41-
currentNode.position = {
42-
x: data.currentXPosition,
43-
y: groupedNodes.currentYPosition,
44-
};
41+
currentNode.position.x = data.currentXPosition;
42+
currentNode.position.y = groupedNodes.currentYPosition;
4543

4644
return {
4745
positionedNodes: groupedNodes.positionedNodes.concat([currentNode]),
48-
currentYPosition: groupedNodes.currentYPosition + currentNode.height + verticalPadding,
46+
currentYPosition: groupedNodes.currentYPosition + (currentNode.height || 0) + verticalPadding,
4947
};
5048
},
5149
{ positionedNodes: [], currentYPosition: 0 }
5250
);
5351

5452
return {
55-
...data,
5653
nodes: [...data.nodes, ...positionedNodes],
5754
currentXPosition: data.currentXPosition + maxWidthOfColumn + 100,
5855
};

0 commit comments

Comments
 (0)