2024-06-27 14:43:06 +03:00
|
|
|
'use client';
|
|
|
|
|
2024-07-21 22:50:43 +03:00
|
|
|
import { useCallback, useLayoutEffect, useMemo } from 'react';
|
2024-07-20 18:26:32 +03:00
|
|
|
import {
|
|
|
|
EdgeChange,
|
|
|
|
NodeChange,
|
|
|
|
NodeTypes,
|
|
|
|
ProOptions,
|
|
|
|
ReactFlow,
|
|
|
|
useEdgesState,
|
|
|
|
useNodesState,
|
|
|
|
useViewport
|
|
|
|
} from 'reactflow';
|
2024-06-27 14:43:06 +03:00
|
|
|
|
2024-07-20 18:26:32 +03:00
|
|
|
import Overlay from '@/components/ui/Overlay';
|
|
|
|
import AnimateFade from '@/components/wrap/AnimateFade';
|
2024-06-27 14:43:06 +03:00
|
|
|
import { useConceptOptions } from '@/context/ConceptOptionsContext';
|
|
|
|
import { useOSS } from '@/context/OssContext';
|
|
|
|
|
2024-07-20 18:26:32 +03:00
|
|
|
import { useOssEdit } from '../OssEditContext';
|
2024-06-27 14:43:06 +03:00
|
|
|
import InputNode from './InputNode';
|
|
|
|
import OperationNode from './OperationNode';
|
2024-07-20 18:26:32 +03:00
|
|
|
import ToolbarOssGraph from './ToolbarOssGraph';
|
2024-06-27 14:43:06 +03:00
|
|
|
|
2024-07-20 18:26:32 +03:00
|
|
|
function OssFlow() {
|
2024-06-27 14:43:06 +03:00
|
|
|
const { calculateHeight } = useConceptOptions();
|
|
|
|
const model = useOSS();
|
2024-07-20 18:26:32 +03:00
|
|
|
const controller = useOssEdit();
|
|
|
|
const viewport = useViewport();
|
2024-06-27 14:43:06 +03:00
|
|
|
|
2024-07-21 22:50:43 +03:00
|
|
|
const [nodes, setNodes, onNodesChange] = useNodesState([]);
|
|
|
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
if (!model.schema) {
|
|
|
|
setNodes([]);
|
|
|
|
setEdges([]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setNodes(
|
|
|
|
model.schema.items.map(operation => ({
|
|
|
|
id: String(operation.id),
|
|
|
|
data: { label: operation.alias },
|
|
|
|
position: { x: operation.position_x, y: operation.position_y },
|
|
|
|
type: operation.operation_type.toString()
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
setEdges(
|
|
|
|
model.schema.arguments.map((argument, index) => ({
|
|
|
|
id: String(index),
|
|
|
|
source: String(argument.argument),
|
|
|
|
target: String(argument.operation)
|
|
|
|
}))
|
|
|
|
);
|
|
|
|
}, [model.schema, setNodes, setEdges]);
|
2024-06-27 14:43:06 +03:00
|
|
|
|
2024-07-21 15:17:36 +03:00
|
|
|
const getPositions = useCallback(
|
|
|
|
() =>
|
|
|
|
nodes.map(node => ({
|
|
|
|
id: Number(node.id),
|
|
|
|
position_x: node.position.x,
|
|
|
|
position_y: node.position.y
|
|
|
|
})),
|
|
|
|
[nodes]
|
|
|
|
);
|
|
|
|
|
2024-07-20 18:26:32 +03:00
|
|
|
const handleNodesChange = useCallback(
|
|
|
|
(changes: NodeChange[]) => {
|
|
|
|
onNodesChange(changes);
|
|
|
|
},
|
|
|
|
[onNodesChange]
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleEdgesChange = useCallback(
|
|
|
|
(changes: EdgeChange[]) => {
|
|
|
|
onEdgesChange(changes);
|
|
|
|
},
|
|
|
|
[onEdgesChange]
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleCreateOperation = useCallback(() => {
|
|
|
|
// TODO: calculate insert location
|
2024-07-21 15:17:36 +03:00
|
|
|
controller.promptCreateOperation(viewport.x, viewport.y, getPositions());
|
|
|
|
}, [controller, viewport, getPositions]);
|
2024-06-27 14:43:06 +03:00
|
|
|
|
2024-07-21 15:17:36 +03:00
|
|
|
const proOptions: ProOptions = useMemo(() => ({ hideAttribution: true }), []);
|
2024-07-20 18:26:32 +03:00
|
|
|
const canvasWidth = useMemo(() => 'calc(100vw - 1rem)', []);
|
2024-06-27 14:43:06 +03:00
|
|
|
const canvasHeight = useMemo(() => calculateHeight('1.75rem + 4px'), [calculateHeight]);
|
|
|
|
|
2024-07-20 18:26:32 +03:00
|
|
|
const OssNodeTypes: NodeTypes = useMemo(
|
|
|
|
() => ({
|
|
|
|
synthesis: OperationNode,
|
|
|
|
input: InputNode
|
|
|
|
}),
|
|
|
|
[]
|
|
|
|
);
|
|
|
|
|
2024-07-21 15:17:36 +03:00
|
|
|
const graph = useMemo(
|
|
|
|
() => (
|
|
|
|
<ReactFlow
|
|
|
|
nodes={nodes}
|
|
|
|
edges={edges}
|
|
|
|
onNodesChange={handleNodesChange}
|
|
|
|
onEdgesChange={handleEdgesChange}
|
|
|
|
fitView
|
|
|
|
proOptions={proOptions}
|
|
|
|
nodeTypes={OssNodeTypes}
|
2024-07-21 22:50:43 +03:00
|
|
|
maxZoom={2}
|
|
|
|
minZoom={0.75}
|
2024-07-21 15:17:36 +03:00
|
|
|
/>
|
|
|
|
),
|
|
|
|
[nodes, edges, proOptions, handleNodesChange, handleEdgesChange, OssNodeTypes]
|
|
|
|
);
|
|
|
|
|
2024-06-27 14:43:06 +03:00
|
|
|
return (
|
2024-07-20 18:26:32 +03:00
|
|
|
<AnimateFade>
|
|
|
|
<Overlay position='top-0 pt-1 right-1/2 translate-x-1/2' className='rounded-b-2xl cc-blur'>
|
|
|
|
<ToolbarOssGraph onCreate={handleCreateOperation} />
|
|
|
|
</Overlay>
|
|
|
|
<div className='relative' style={{ height: canvasHeight, width: canvasWidth }}>
|
2024-07-21 15:17:36 +03:00
|
|
|
{graph}
|
2024-07-20 18:26:32 +03:00
|
|
|
</div>
|
|
|
|
</AnimateFade>
|
2024-06-27 14:43:06 +03:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default OssFlow;
|