trust-module-frontend/src/Components/TreeChart/FlowChart.jsx

99 lines
2.7 KiB
JavaScript

import React, { useEffect, useMemo, useRef } from 'react';
import ReactFlow, { Controls, Background } from 'reactflow';
import 'reactflow/dist/style.css';
import { debounce } from 'lodash';
import { useFlowChart } from './FlowChartComponents/useFlowChart';
import { useNodeHandlers } from './FlowChartComponents/useNodeHandlers';
import { useDataParser } from './FlowChartComponents/DataParser';
import NodeWrapper from './FlowChartComponents/NodeWrapper';
const nodeTypes = {
customNode: NodeWrapper
};
const FlowChart = ({ data }) => {
const {
nodes,
edges,
nodePositions,
setNodes,
setEdges,
onNodesChange,
onEdgesChange,
setNodePositions,
collapsedNodes,
toggleNodeCollapse
} = useFlowChart(data);
const { parseData } = useDataParser(nodePositions, collapsedNodes);
const initialized = useRef(false);
const debouncedSetNodePositions = useMemo(
() => debounce(setNodePositions, 100),
[setNodePositions]
);
const { onNodeDrag, onNodeDragStop } = useNodeHandlers(debouncedSetNodePositions);
useEffect(() => {
const { nodes: initialNodes, edges: initialEdges } = parseData(data);
setNodes(initialNodes);
setEdges(initialEdges);
// Автоматически сворачиваем узлы, которые являются родителями последнего уровня
if (!initialized.current && data) {
const findAndCollapseLastLevelParents = (items) => {
items.forEach(item => {
if (item.items && item.items.length > 0) {
const hasGrandchildren = item.items.some(child =>
child.items && child.items.length > 0
);
if (!hasGrandchildren) {
toggleNodeCollapse(item.id);
} else {
findAndCollapseLastLevelParents(item.items);
}
}
});
};
findAndCollapseLastLevelParents(data.items || []);
initialized.current = true;
}
}, [data, parseData, setNodes, setEdges, toggleNodeCollapse]);
const onNodeClick = (event, node) => {
if (node.data.hasChildren) {
toggleNodeCollapse(node.id);
}
};
useEffect(() => {
return () => {
debouncedSetNodePositions.cancel();
};
}, [debouncedSetNodePositions]);
return (
<div style={{ height: '85vh', width: '100%' }}>
<ReactFlow
nodes={nodes}
edges={edges}
nodeTypes={nodeTypes}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onNodeDrag={onNodeDrag}
onNodeDragStop={onNodeDragStop}
nodeDragThreshold={1}
onNodeClick={onNodeClick}
fitView
>
<Background />
<Controls />
</ReactFlow>
</div>
);
};
export default React.memo(FlowChart);