Portal/rsconcept/frontend/src/pages/OssPage/EditorOssGraph/OssFlow.tsx
2024-07-20 18:26:32 +03:00

122 lines
3.4 KiB
TypeScript

'use client';
import { useCallback, useMemo } from 'react';
import {
Edge,
EdgeChange,
Node,
NodeChange,
NodeTypes,
ProOptions,
ReactFlow,
useEdgesState,
useNodesState,
useViewport
} from 'reactflow';
import Overlay from '@/components/ui/Overlay';
import AnimateFade from '@/components/wrap/AnimateFade';
import { useConceptOptions } from '@/context/ConceptOptionsContext';
import { useOSS } from '@/context/OssContext';
import { useOssEdit } from '../OssEditContext';
import InputNode from './InputNode';
import OperationNode from './OperationNode';
import ToolbarOssGraph from './ToolbarOssGraph';
function OssFlow() {
const { calculateHeight } = useConceptOptions();
const model = useOSS();
const controller = useOssEdit();
const viewport = useViewport();
console.log(controller.isMutable);
const initialNodes: Node[] = useMemo(
() =>
!model.schema
? []
: 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()
})),
[model.schema]
);
// const initialNodes = [
// { id: '1', data: { label: '-' }, position: { x: 100, y: 100 } },
// { id: '2', data: { label: 'Node 2' }, position: { x: 100, y: 200 } }
// ];
const initialEdges: Edge[] = useMemo(
() =>
!model.schema
? []
: model.schema.arguments.map((argument, index) => ({
id: String(index),
source: String(argument.argument),
target: String(argument.operation)
})),
[model.schema]
);
// const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];
const [nodes, onNodesChange] = useNodesState<Node>(initialNodes);
const [edges, onEdgesChange] = useEdgesState<Edge>(initialEdges);
const handleNodesChange = useCallback(
(changes: NodeChange[]) => {
// @ts-expect-error TODO: Figure out internal type errors in ReactFlow
onNodesChange(changes);
},
[onNodesChange]
);
const handleEdgesChange = useCallback(
(changes: EdgeChange[]) => {
// @ts-expect-error TODO: Figure out internal type errors in ReactFlow
onEdgesChange(changes);
},
[onEdgesChange]
);
const handleCreateOperation = useCallback(() => {
// TODO: calculate insert location
controller.promptCreateOperation(viewport.x, viewport.y);
}, [controller, viewport]);
const proOptions: ProOptions = { hideAttribution: true };
const canvasWidth = useMemo(() => 'calc(100vw - 1rem)', []);
const canvasHeight = useMemo(() => calculateHeight('1.75rem + 4px'), [calculateHeight]);
const OssNodeTypes: NodeTypes = useMemo(
() => ({
synthesis: OperationNode,
input: InputNode
}),
[]
);
return (
<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 }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={handleEdgesChange}
fitView
proOptions={proOptions}
nodeTypes={OssNodeTypes}
/>
</div>
</AnimateFade>
);
}
export default OssFlow;