Visual work on Flow
parent
88a2841a0b
commit
d6f9f9cdf7
|
|
@ -5,10 +5,21 @@ import ReactFlow, {
|
|||
Controls,
|
||||
ReactFlowInstance,
|
||||
} from "react-flow-renderer";
|
||||
import useStore from "../../lib/FlowEditor/FlowEditorStore";
|
||||
import { GenericNode } from "./nodes/Node";
|
||||
|
||||
const nodeTypes = { generic: GenericNode };
|
||||
import useStore from "../../lib/FlowEditor/FlowEditorStore";
|
||||
|
||||
import LedNode from "./nodes/IO/LedNode";
|
||||
import SensorNode from "./nodes/IO/SensorNode";
|
||||
|
||||
import DelayNode from "./nodes/Logic/DelayNode";
|
||||
import MathNode from "./nodes/Logic/MathNode";
|
||||
|
||||
const nodeTypes = {
|
||||
led: LedNode,
|
||||
sensor: SensorNode,
|
||||
delay: DelayNode,
|
||||
math: MathNode,
|
||||
};
|
||||
|
||||
const Flow = () => {
|
||||
const [reactFlowInstance, setReactFlowInstance] =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { VscArrowLeft, VscArrowRight } from "react-icons/vsc";
|
||||
import useStore from "../../lib/FlowEditor/FlowEditorStore";
|
||||
import { GenericNodeComponent } from "./nodes/Node";
|
||||
import { LedNodeComponent, SensorNodeComponent } from "./nodes/IO/IO";
|
||||
import { DelayNodeComponent, MathNodeComponent } from "./nodes/Logic/Logic";
|
||||
|
||||
const Panel = () => {
|
||||
const { panelClosed, togglePanelState } = useStore();
|
||||
|
|
@ -22,9 +23,13 @@ const Panel = () => {
|
|||
>
|
||||
<PanelButton />
|
||||
{!panelClosed && (
|
||||
<>
|
||||
<GenericNodeComponent />
|
||||
</>
|
||||
<div className="flex flex-col">
|
||||
<SensorNodeComponent />
|
||||
<LedNodeComponent />
|
||||
|
||||
<MathNodeComponent />
|
||||
<DelayNodeComponent />
|
||||
</div>
|
||||
)}
|
||||
</aside>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
import Draggable from "../../../DragNDrop/Draggable";
|
||||
|
||||
const groupColor = "bg-red-700";
|
||||
|
||||
const SensorNodeComponent = () => {
|
||||
return (
|
||||
<Draggable data={{ type: "sensor" }}>
|
||||
<div className="node-component">
|
||||
<div className={`node-component-handle ${groupColor}`} />
|
||||
Сенсор
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
const LedNodeComponent = () => {
|
||||
return (
|
||||
<Draggable data={{ type: "led" }}>
|
||||
<div className="node-component">
|
||||
<div className={`node-component-handle ${groupColor}`} />
|
||||
Светодиод
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
export { SensorNodeComponent, LedNodeComponent };
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import { Handle, Position } from "react-flow-renderer";
|
||||
import { bottomBigStyle, topBigStyle } from "../styles";
|
||||
|
||||
type LedNodeProps = {};
|
||||
|
||||
const LedNode = (props: LedNodeProps) => {
|
||||
return (
|
||||
<div className="led-node node-layout">
|
||||
<Handle style={topBigStyle} type="target" position={Position.Top} />
|
||||
|
||||
<div className="node-header">
|
||||
<span className="node-title">Светодиод</span>
|
||||
</div>
|
||||
|
||||
<div className="node-content">
|
||||
<select className="nodrag">
|
||||
<option>Включить</option>
|
||||
<option>Выключить</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Handle style={bottomBigStyle} type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LedNode;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { Handle, Position } from "react-flow-renderer";
|
||||
import { bottomBigStyle, topBigStyle } from "../styles";
|
||||
|
||||
type SensorNodeProps = {};
|
||||
|
||||
const SensorNode = (props: SensorNodeProps) => {
|
||||
return (
|
||||
<div className="sensor-node node-layout">
|
||||
<Handle style={topBigStyle} type="target" position={Position.Top} />
|
||||
<div className="node-header">
|
||||
<span className="node-title">Сенсор</span>
|
||||
</div>
|
||||
<div className="node-layout">
|
||||
<select className="nodrag">
|
||||
<option>Температура</option>
|
||||
<option>Освещенность</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Handle style={bottomBigStyle} type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SensorNode;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { Handle, Position } from "react-flow-renderer";
|
||||
import { bottomBigStyle, topBigStyle } from "../styles";
|
||||
|
||||
type DelayNodeProps = {};
|
||||
|
||||
const DelayNode = (props: DelayNodeProps) => {
|
||||
return (
|
||||
<div className="delay-node node-layout">
|
||||
<Handle style={topBigStyle} type="target" position={Position.Top} />
|
||||
<div className="node-header">
|
||||
<span className="node-title">Задержка</span>
|
||||
</div>
|
||||
<div className="node-content">
|
||||
<select className="nodrag">
|
||||
<option>1 c</option>
|
||||
<option>2 c</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Handle style={bottomBigStyle} type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DelayNode;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import Draggable from "../../../DragNDrop/Draggable";
|
||||
|
||||
const groupColor = "bg-blue-800";
|
||||
|
||||
const DelayNodeComponent = () => {
|
||||
return (
|
||||
<Draggable data={{ type: "delay" }}>
|
||||
<div className="node-component">
|
||||
<div className={`node-component-handle ${groupColor}`} />
|
||||
Задержка
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
const MathNodeComponent = () => {
|
||||
return (
|
||||
<Draggable data={{ type: "math" }}>
|
||||
<div className="node-component">
|
||||
<div className={`node-component-handle ${groupColor}`} />
|
||||
Математика
|
||||
</div>
|
||||
</Draggable>
|
||||
);
|
||||
};
|
||||
|
||||
export { DelayNodeComponent, MathNodeComponent };
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { Handle, Position } from "react-flow-renderer";
|
||||
import {
|
||||
bottomBigStyle,
|
||||
topDoubleLeftStyle,
|
||||
topDoubleRightStyle,
|
||||
} from "../styles";
|
||||
|
||||
type MathNodeProps = {};
|
||||
|
||||
const MathNode = (props: MathNodeProps) => {
|
||||
return (
|
||||
<div className="math-node node-layout">
|
||||
<Handle
|
||||
style={topDoubleLeftStyle}
|
||||
id="in-a"
|
||||
type="target"
|
||||
position={Position.Top}
|
||||
/>
|
||||
<Handle
|
||||
style={topDoubleRightStyle}
|
||||
id="in-b"
|
||||
type="target"
|
||||
position={Position.Top}
|
||||
/>
|
||||
|
||||
<div className="node-header">
|
||||
<span className="node-title">Математика</span>
|
||||
</div>
|
||||
|
||||
<div className="node-content">
|
||||
<select className="nodrag">
|
||||
<option>+</option>
|
||||
<option>-</option>
|
||||
<option>*</option>
|
||||
<option>/</option>
|
||||
<option>√</option>
|
||||
<option>**</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Handle style={bottomBigStyle} type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MathNode;
|
||||
|
|
@ -33,8 +33,8 @@ const GenericNode = (props: GenericNodeProps) => {
|
|||
const GenericNodeComponent = () => {
|
||||
return (
|
||||
<Draggable data={{ type: "generic" }}>
|
||||
<div className="node-component bg-red-700">
|
||||
<div className="node-component-handle" />
|
||||
<div className="node-component ">
|
||||
<div className="node-component-handle bg-red-700" />
|
||||
Тест
|
||||
</div>
|
||||
</Draggable>
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
import styles from "./Node.module.css";
|
||||
import { Handle, Position } from "react-flow-renderer";
|
||||
|
||||
type InputNodeProps = {};
|
||||
|
||||
const InputNode = (props: InputNodeProps) => {
|
||||
return (
|
||||
// Базовый класс generic-node - прописана ширина и положение, цвет текста и фона
|
||||
|
||||
// Nandle - ручка для коннекта. Можно задать оформление при помощи className, тип (target / source) и позицию
|
||||
|
||||
// Label - подпись ноды. Можно стилизовать
|
||||
|
||||
// Select - DropDown меню, можно стилизовать. Стоит класс nodrag для предотвращения залипания
|
||||
|
||||
<div className="Input-node">
|
||||
<Handle className="" type="target" position={Position.Top} />
|
||||
|
||||
<div className="generic-node-content">
|
||||
|
||||
<select className="nodrag">
|
||||
<option>датчик газа</option>
|
||||
<option>датчик температуры</option>
|
||||
<option>датчик освещенности</option>
|
||||
<option>логи</option>
|
||||
</select>
|
||||
<select className="nodrag">
|
||||
<option>получить полный отчет</option>
|
||||
<option>получить значение</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
||||
<Handle className="" type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputNode;
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
import styles from "./Node.module.css";
|
||||
import { Handle, Position } from "react-flow-renderer";
|
||||
|
||||
type MathNodeProps = {};
|
||||
|
||||
const MathNode = (props: MathNodeProps) => {
|
||||
return (
|
||||
// Базовый класс generic-node - прописана ширина и положение, цвет текста и фона
|
||||
|
||||
// Nandle - ручка для коннекта. Можно задать оформление при помощи className, тип (target / source) и позицию
|
||||
|
||||
// Label - подпись ноды. Можно стилизовать
|
||||
|
||||
// Select - DropDown меню, можно стилизовать. Стоит класс nodrag для предотвращения залипания
|
||||
|
||||
<div className="math-node">
|
||||
<Handle className="" type="target" position={Position.Top} />
|
||||
|
||||
<div className="generic-node-content">
|
||||
|
||||
<input> первое число</input>
|
||||
<select className="nodrag">
|
||||
<option>+</option>
|
||||
<option>-</option>
|
||||
<option>*</option>
|
||||
<option>/</option>
|
||||
<option>корень из</option>
|
||||
<option>возвести в степень</option>
|
||||
</select>
|
||||
<input> второе число</input>
|
||||
</div>
|
||||
|
||||
<Handle className="" type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MathNode;
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import styles from "./Node.module.css";
|
||||
import { Handle, Position } from "react-flow-renderer";
|
||||
|
||||
type OutputNodeProps = {};
|
||||
|
||||
const OutputNode = (props: OutputNodeProps) => {
|
||||
return (
|
||||
// Базовый класс generic-node - прописана ширина и положение, цвет текста и фона
|
||||
|
||||
// Nandle - ручка для коннекта. Можно задать оформление при помощи className, тип (target / source) и позицию
|
||||
|
||||
// Label - подпись ноды. Можно стилизовать
|
||||
|
||||
// Select - DropDown меню, можно стилизовать. Стоит класс nodrag для предотвращения залипания
|
||||
|
||||
<div className="output-node">
|
||||
<Handle className="" type="target" position={Position.Top} />
|
||||
|
||||
<div className="generic-node-content">
|
||||
|
||||
<label htmlFor="select">Выбери своего покемона: </label>
|
||||
<select className="nodrag">
|
||||
<option>Включить</option>
|
||||
<option>Выключить</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<Handle className="" type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default OutputNode;
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
import styles from "./Node.module.css";
|
||||
import { Handle, Position } from "react-flow-renderer";
|
||||
|
||||
type TimerNodeProps = {};
|
||||
|
||||
const TimerNode = (props: TimerNodeProps) => {
|
||||
return (
|
||||
// Базовый класс generic-node - прописана ширина и положение, цвет текста и фона
|
||||
|
||||
// Nandle - ручка для коннекта. Можно задать оформление при помощи className, тип (target / source) и позицию
|
||||
|
||||
// Label - подпись ноды. Можно стилизовать
|
||||
|
||||
// Select - DropDown меню, можно стилизовать. Стоит класс nodrag для предотвращения залипания
|
||||
|
||||
<div className="timer-node">
|
||||
<Handle className="" type="target" position={Position.Top} />
|
||||
|
||||
<div className="generic-node-content">
|
||||
|
||||
<label htmlFor="input">Время задержки: </label>
|
||||
<input> Время задержки</input>
|
||||
|
||||
</div>
|
||||
|
||||
<Handle className="" type="source" position={Position.Bottom} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TimerNode;
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
const topDoubleLeftStyle = {
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
border: "none",
|
||||
borderTopLeftRadius: "10px",
|
||||
borderTopRightRadius: "10px",
|
||||
borderBottomLeftRadius: "0px",
|
||||
borderBottomRightRadius: "0px",
|
||||
top: "-20px",
|
||||
left: "20px",
|
||||
};
|
||||
|
||||
const topDoubleRightStyle = {
|
||||
width: "20px",
|
||||
height: "20px",
|
||||
border: "none",
|
||||
borderTopLeftRadius: "10px",
|
||||
borderTopRightRadius: "10px",
|
||||
borderBottomLeftRadius: "0px",
|
||||
borderBottomRightRadius: "0px",
|
||||
top: "-20px",
|
||||
};
|
||||
|
||||
const topBigStyle = {
|
||||
width: "100%",
|
||||
height: "10px",
|
||||
border: "none",
|
||||
borderTopLeftRadius: "10px",
|
||||
borderTopRightRadius: "10px",
|
||||
borderBottomLeftRadius: "0px",
|
||||
borderBottomRightRadius: "0px",
|
||||
top: "-10px",
|
||||
};
|
||||
|
||||
const bottomBigStyle = {
|
||||
width: "100%",
|
||||
height: "10px",
|
||||
border: "none",
|
||||
borderTopLeftRadius: "0px",
|
||||
borderTopRightRadius: "0px",
|
||||
borderBottomLeftRadius: "10px",
|
||||
borderBottomRightRadius: "10px",
|
||||
bottom: "-10px",
|
||||
};
|
||||
|
||||
export { topBigStyle, bottomBigStyle, topDoubleLeftStyle, topDoubleRightStyle };
|
||||
|
|
@ -61,23 +61,39 @@
|
|||
rounded-xl cursor-pointer;
|
||||
}
|
||||
|
||||
.flow {
|
||||
.node-layout {
|
||||
@apply flex flex-col items-center
|
||||
w-[150px] h-fit bg-gray-700
|
||||
p-[4px];
|
||||
}
|
||||
|
||||
.generic-node {
|
||||
@apply flex flex-row items-center justify-center
|
||||
w-[150px] h-auto bg-white
|
||||
rounded-sm;
|
||||
.node-handle-big {
|
||||
@apply w-[150px] h-[20px];
|
||||
}
|
||||
|
||||
.node-header {
|
||||
@apply flex flex-row w-full h-[20px] justify-between items-center
|
||||
mb-1 px-[4px]
|
||||
border-b border-b-gray-500;
|
||||
}
|
||||
|
||||
.node-title {
|
||||
@apply text-white text-xs font-bold;
|
||||
}
|
||||
|
||||
.node-content {
|
||||
@apply flex flex-col w-full h-fit
|
||||
mb-[4px];
|
||||
}
|
||||
|
||||
.node-component {
|
||||
@apply relative flex flex-row h-fit rounded-md
|
||||
bg-gray-600
|
||||
pr-2 my-2 py-1 mx-2
|
||||
pr-2 my-1 mx-2
|
||||
text-white align-middle;
|
||||
}
|
||||
|
||||
.node-component-handle {
|
||||
@apply left-0 w-[12px] h-full mr-2 rounded-tl-md rounded-bl-md;
|
||||
@apply left-0 w-[12px] h-[30px] mr-2 rounded-tl-md rounded-bl-md;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue