122 lines
3.4 KiB
TypeScript
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;
|