feat: added ReactFlow-based node graph #11
@@ -38,7 +38,7 @@
|
|||||||
filter: drop-shadow(0 0 0.75rem black);
|
filter: drop-shadow(0 0 0.75rem black);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-node__norm {
|
.default-node-norm {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem forestgreen);
|
filter: drop-shadow(0 0 0.25rem forestgreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-node__phase {
|
.default-node-phase {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem dodgerblue);
|
filter: drop-shadow(0 0 0.25rem dodgerblue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-node__start {
|
.default-node-start {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem orange);
|
filter: drop-shadow(0 0 0.25rem orange);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-node__end {
|
.default-node-end {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
filter: drop-shadow(0 0 0.75rem black);
|
filter: drop-shadow(0 0 0.75rem black);
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-node__norm {
|
.draggable-node-norm {
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem forestgreen);
|
filter: drop-shadow(0 0 0.25rem forestgreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-node__phase {
|
.draggable-node-phase {
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem dodgerblue);
|
filter: drop-shadow(0 0 0.25rem dodgerblue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-node__start {
|
.draggable-node-start {
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
filter: drop-shadow(0 0 0.25rem orange);
|
filter: drop-shadow(0 0 0.25rem orange);
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-node__end {
|
.draggable-node-end {
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
background-color: canvas;
|
background-color: canvas;
|
||||||
border-radius: 5pt;
|
border-radius: 5pt;
|
||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
import {DndToolbar} from './components/DragDropSidebar.tsx';
|
import {DndToolbar} from './components/DragDropSidebar.tsx';
|
||||||
import useFlowStore from './VisProgStores.tsx';
|
import useFlowStore from './VisProgStores.tsx';
|
||||||
import type {FlowState} from './VisProgTypes.tsx';
|
import type {FlowState} from './VisProgTypes.tsx';
|
||||||
import './VisProgUI.css'
|
import styles from './VisProgUI.module.css'
|
||||||
|
|
||||||
// --| config starting params for flow |--
|
// --| config starting params for flow |--
|
||||||
|
|
||||||
@@ -79,8 +79,8 @@ const VisProgUI = () => {
|
|||||||
} = useFlowStore(useShallow(selector)); // instructs the editor to use the corresponding functions from the FlowStore
|
} = useFlowStore(useShallow(selector)); // instructs the editor to use the corresponding functions from the FlowStore
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"outer-editor-container"}>
|
<div className={styles.outerEditorContainer}>
|
||||||
<div className={"inner-editor-container"}>
|
<div className={styles.innerEditorContainer}>
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
@@ -96,7 +96,7 @@ const VisProgUI = () => {
|
|||||||
fitView
|
fitView
|
||||||
proOptions={{hideAttribution: true}}
|
proOptions={{hideAttribution: true}}
|
||||||
>
|
>
|
||||||
<Panel position="top-center" className={"dnd-panel"}>
|
<Panel position="top-center" className={styles.dndPanel}>
|
||||||
<DndToolbar/> {/* contains the drag and drop panel for nodes */}
|
<DndToolbar/> {/* contains the drag and drop panel for nodes */}
|
||||||
</Panel>
|
</Panel>
|
||||||
<Controls/>
|
<Controls/>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
import styles from "../VisProgUI.module.css"
|
||||||
|
|
||||||
// Is used to make sure each subsequent node gets a unique id, so the ReactFlow implementation
|
// Is used to make sure each subsequent node gets a unique id, so the ReactFlow implementation
|
||||||
// can distinguish between different nodes.
|
// can distinguish between different nodes.
|
||||||
@@ -40,7 +41,7 @@ function DraggableNode({className, children, nodeType, onDrop}: DraggableNodePro
|
|||||||
const draggableRef = useRef<HTMLDivElement>(null);
|
const draggableRef = useRef<HTMLDivElement>(null);
|
||||||
const [position, setPosition] = useState<XYPosition>({x: 0, y: 0});
|
const [position, setPosition] = useState<XYPosition>({x: 0, y: 0});
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-expect-error comes from a package and doesn't appear to play nicely with strict typescript typing
|
||||||
useDraggable(draggableRef, {
|
useDraggable(draggableRef, {
|
||||||
position: position,
|
position: position,
|
||||||
onDrag: ({offsetX, offsetY}) => {
|
onDrag: ({offsetX, offsetY}) => {
|
||||||
@@ -60,8 +61,7 @@ function DraggableNode({className, children, nodeType, onDrop}: DraggableNodePro
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className === "default" ? "draggable-node" : "draggable-node" + "__" + className}
|
<div className={className} ref={draggableRef}>
|
||||||
ref={draggableRef}>
|
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -162,10 +162,10 @@ export function DndToolbar() {
|
|||||||
gap: '1rem',
|
gap: '1rem',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
}}>
|
}}>
|
||||||
<DraggableNode className="phase" nodeType="phase" onDrop={handleNodeDrop}>
|
<DraggableNode className={styles.draggableNodePhase} nodeType="phase" onDrop={handleNodeDrop}>
|
||||||
phase Node
|
phase Node
|
||||||
</DraggableNode>
|
</DraggableNode>
|
||||||
<DraggableNode className="norm" nodeType="norm" onDrop={handleNodeDrop}>
|
<DraggableNode className={styles.draggableNodeNorm} nodeType="norm" onDrop={handleNodeDrop}>
|
||||||
norm Node
|
norm Node
|
||||||
</DraggableNode>
|
</DraggableNode>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Handle, NodeToolbar, Position, useReactFlow} from '@xyflow/react';
|
import {Handle, NodeToolbar, Position, useReactFlow} from '@xyflow/react';
|
||||||
import '@xyflow/react/dist/style.css';
|
import '@xyflow/react/dist/style.css';
|
||||||
import '../VisProgUI.css';
|
import styles from '../VisProgUI.module.css';
|
||||||
|
|
||||||
// Contains the datatypes for the data inside our NodeTypes
|
// Contains the datatypes for the data inside our NodeTypes
|
||||||
// this has to be improved or adapted to suit our implementation for computing the graph
|
// this has to be improved or adapted to suit our implementation for computing the graph
|
||||||
@@ -53,7 +53,7 @@ export const StartNode = ({id, data}: StartNodeProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar nodeId={id} allowDelete={false}/>
|
<Toolbar nodeId={id} allowDelete={false}/>
|
||||||
<div className="default-node__start">
|
<div className={styles.defaultNodeStart}>
|
||||||
<div> data test {data.label} </div>
|
<div> data test {data.label} </div>
|
||||||
<Handle type="source" position={Position.Right} id="start"/>
|
<Handle type="source" position={Position.Right} id="start"/>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +73,7 @@ export const EndNode = ({id, data}: EndNodeProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar nodeId={id} allowDelete={false}/>
|
<Toolbar nodeId={id} allowDelete={false}/>
|
||||||
<div className="default-node__end">
|
<div className={styles.defaultNodeEnd}>
|
||||||
<div> {data.label} </div>
|
<div> {data.label} </div>
|
||||||
<Handle type="target" position={Position.Left} id="end"/>
|
<Handle type="target" position={Position.Left} id="end"/>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,7 +93,7 @@ export const PhaseNode = ({id, data}: PhaseNodeProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar nodeId={id} allowDelete={true}/>
|
<Toolbar nodeId={id} allowDelete={true}/>
|
||||||
<div className="default-node__phase">
|
<div className={styles.defaultNodePhase}>
|
||||||
<div> phase {data.number} {data.label} </div>
|
<div> phase {data.number} {data.label} </div>
|
||||||
<Handle type="target" position={Position.Left} id="target"/>
|
<Handle type="target" position={Position.Left} id="target"/>
|
||||||
<Handle type="target" position={Position.Bottom} id="norms"/>
|
<Handle type="target" position={Position.Bottom} id="norms"/>
|
||||||
@@ -115,7 +115,7 @@ export const NormNode = ({id, data}: NormNodeProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar nodeId={id} allowDelete={true}/>
|
<Toolbar nodeId={id} allowDelete={true}/>
|
||||||
<div className="default-node__norm">
|
<div className={styles.defaultNodeNorm}>
|
||||||
<div> Norm {data.label} </div>
|
<div> Norm {data.label} </div>
|
||||||
<Handle type="source" position={Position.Right} id="NormSource"/>
|
<Handle type="source" position={Position.Right} id="NormSource"/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user