Files
pepperplus-ui/src/visualProgrammingUI/VisProgUI.tsx
JGerla 79f0827b39 feat: created new nodes and a default nodeType
added a type for defaultNodeData, this can house common data that all nodes should have. the other types can build on this defaultData. Also added an endNode and phaseNode to NodeDefinitions.tsx, together with a nodeData type for each new node type.

ref: N25B-114
2025-10-01 10:58:43 +02:00

115 lines
2.9 KiB
TypeScript

import './VisProgUI.css'
import {
useCallback,
useRef
} from 'react';
import {
Background,
Controls,
ReactFlow,
useNodesState,
useEdgesState,
reconnectEdge,
addEdge,
MarkerType,
type Edge,
type Connection,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import {
StartNode,
EndNode,
PhaseNode
} from "./components/NodeDefinitions.tsx";
const nodeTypes = {
start: StartNode,
end: EndNode,
phase: PhaseNode,
};
const initialNodes = [
{
id: 'start',
type: 'start',
position: {x: 0, y: 0},
data: {label: 'start'}
},
{
id: 'genericPhase',
type: 'phase',
position: {x: 0, y: 150},
data: {label: 'Generic Phase', number: 1},
},
{
id: 'end',
type: 'end',
position: {x: 0, y: 300},
data: {label: 'End'}
}
];
const initialEdges = [{id: 'start-end', source: 'start', target: 'end'}];
const defaultEdgeOptions = {
type: 'floating',
markerEnd: {
type: MarkerType.ArrowClosed,
color: '#505050',
},
};
const VisualProgrammingUI = ()=> {
const edgeReconnectSuccessful = useRef(true);
const [nodes, , onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = useCallback(
(params: Edge | Connection) => setEdges((els) => addEdge(params, els)),
[setEdges],
);
const onReconnectStart = useCallback(() => {
edgeReconnectSuccessful.current = false;
}, []);
const onReconnect = useCallback((oldEdge: Edge, newConnection: Connection) => {
edgeReconnectSuccessful.current = true;
setEdges((els) => reconnectEdge(oldEdge, newConnection, els));
}, [setEdges]);
const onReconnectEnd = useCallback((_: unknown, edge: { id: string; }) => {
if (!edgeReconnectSuccessful.current) {
setEdges((eds) => eds.filter((e) => e.id !== edge.id));
}
edgeReconnectSuccessful.current = true;
}, [setEdges]);
return (
<div style={{outlineStyle: 'solid', borderRadius: '10pt' ,marginInline: 'auto',width: '60vw', height: '60vh' }}>
<ReactFlow
nodes={nodes}
edges={edges}
defaultEdgeOptions={defaultEdgeOptions}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
nodeTypes={nodeTypes}
snapToGrid
onReconnect={onReconnect}
onReconnectStart={onReconnectStart}
onReconnectEnd={onReconnectEnd}
onConnect={onConnect}
fitView
proOptions={{hideAttribution: true }}
>
<Controls />
<Background />
</ReactFlow>
</div>
);
};
export default VisualProgrammingUI