mirror of
https://github.com/hexastack/hexabot
synced 2024-11-24 13:05:15 +00:00
feat: self attached node
This commit is contained in:
parent
d47deeb899
commit
f9cd6b24db
@ -8,10 +8,7 @@
|
||||
*/
|
||||
|
||||
import { debounce } from "@mui/material";
|
||||
import createEngine, {
|
||||
DefaultLinkModel,
|
||||
DiagramModel,
|
||||
} from "@projectstorm/react-diagrams";
|
||||
import createEngine, { DiagramModel } from "@projectstorm/react-diagrams";
|
||||
import * as React from "react";
|
||||
import { createContext, useContext } from "react";
|
||||
|
||||
@ -26,6 +23,10 @@ import {
|
||||
} from "@/types/visual-editor.types";
|
||||
|
||||
import { ZOOM_LEVEL } from "../constants";
|
||||
import {
|
||||
AdvancedLinkFactory,
|
||||
AdvancedLinkModel,
|
||||
} from "../v2/AdvancedLink/AdvancedLink";
|
||||
import { CustomCanvasWidget } from "../v2/CustomCanvasWidget";
|
||||
import { CustomDeleteItemsAction } from "../v2/CustomDiagramNodes/CustomDeleteAction";
|
||||
import { NodeFactory } from "../v2/CustomDiagramNodes/NodeFactory";
|
||||
@ -87,6 +88,8 @@ const buildDiagram = ({
|
||||
model = new DiagramModel();
|
||||
|
||||
engine.getNodeFactories().registerFactory(new NodeFactory());
|
||||
engine.getLinkFactories().registerFactory(new AdvancedLinkFactory());
|
||||
|
||||
engine
|
||||
.getActionEventBus()
|
||||
.registerAction(new CustomDeleteItemsAction({ callback: onRemoveNode }));
|
||||
@ -139,12 +142,12 @@ const buildDiagram = ({
|
||||
}
|
||||
}
|
||||
};
|
||||
const links: DefaultLinkModel[] = [];
|
||||
const links: AdvancedLinkModel[] = [];
|
||||
|
||||
data.forEach((datum, index) => {
|
||||
if ("nextBlocks" in datum && Array.isArray(datum.nextBlocks)) {
|
||||
datum.nextBlocks?.forEach((nextBlock) => {
|
||||
const link = new DefaultLinkModel();
|
||||
const link = new AdvancedLinkModel();
|
||||
const sourceNode = nodes[index];
|
||||
const targetNode = nodes.find(
|
||||
// @ts-ignore
|
||||
@ -164,7 +167,7 @@ const buildDiagram = ({
|
||||
|
||||
//recursive link
|
||||
if ("attachedBlock" in datum && datum.attachedBlock) {
|
||||
const link = new DefaultLinkModel({
|
||||
const link = new AdvancedLinkModel({
|
||||
color: "#019185",
|
||||
selectedColor: "#019185",
|
||||
type: "default",
|
||||
|
@ -0,0 +1,103 @@
|
||||
import { css, keyframes } from "@emotion/react";
|
||||
import styled from "@emotion/styled";
|
||||
import {
|
||||
DefaultLinkFactory,
|
||||
DefaultLinkModel,
|
||||
DefaultLinkModelOptions,
|
||||
DefaultLinkWidget,
|
||||
} from "@projectstorm/react-diagrams";
|
||||
import React from "react";
|
||||
|
||||
interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
const createCurvedPath = (start: Point, end: Point) => {
|
||||
const controlPoint1X = start.x + 220;
|
||||
const controlPoint1Y = start.y - 250;
|
||||
const controlPoint2X = end.x - 250;
|
||||
const controlPoint2Y = end.y - 250;
|
||||
|
||||
return `M ${start.x},${start.y} C ${controlPoint1X},${controlPoint1Y} ${controlPoint2X},${controlPoint2Y} ${end.x},${end.y}`;
|
||||
};
|
||||
|
||||
namespace S {
|
||||
export const Keyframes = keyframes`
|
||||
from {
|
||||
stroke-dashoffset: 24;
|
||||
}
|
||||
to {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const selected = css`
|
||||
stroke-dasharray: 10, 2;
|
||||
animation: ${Keyframes} 1s linear infinite;
|
||||
`;
|
||||
|
||||
export const Path = styled.path<{ selected: boolean }>`
|
||||
${(p) => p.selected && selected};
|
||||
fill: none;
|
||||
pointer-events: auto;
|
||||
`;
|
||||
}
|
||||
|
||||
export class AdvancedLinkModel extends DefaultLinkModel {
|
||||
constructor(options?: DefaultLinkModelOptions) {
|
||||
super({
|
||||
...options,
|
||||
type: "advanced",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class AdvancedLinkFactory extends DefaultLinkFactory {
|
||||
constructor() {
|
||||
super("advanced");
|
||||
}
|
||||
|
||||
generateModel(): AdvancedLinkModel {
|
||||
return new AdvancedLinkModel();
|
||||
}
|
||||
|
||||
generateReactWidget(event): JSX.Element {
|
||||
return <DefaultLinkWidget link={event.model} diagramEngine={this.engine} />;
|
||||
}
|
||||
|
||||
generateLinkSegment(
|
||||
model: AdvancedLinkModel,
|
||||
selected: boolean,
|
||||
path: string,
|
||||
) {
|
||||
const isSelfLoop =
|
||||
model.getSourcePort().getNode() === model.getTargetPort().getNode();
|
||||
|
||||
if (isSelfLoop) {
|
||||
// Adjust the path to create a curve
|
||||
const sourcePortPosition = model.getSourcePort().getPosition();
|
||||
const targetPortPosition = model.getTargetPort().getPosition();
|
||||
const startPoint: Point = {
|
||||
x: sourcePortPosition.x + 20,
|
||||
y: sourcePortPosition.y + 20,
|
||||
};
|
||||
const endPoint: Point = {
|
||||
x: targetPortPosition.x + 20,
|
||||
y: targetPortPosition.y + 20,
|
||||
};
|
||||
|
||||
path = createCurvedPath(startPoint, endPoint);
|
||||
}
|
||||
|
||||
return (
|
||||
<S.Path
|
||||
selected={selected}
|
||||
stroke={
|
||||
selected ? model.getOptions().selectedColor : model.getOptions().color
|
||||
}
|
||||
strokeWidth={model.getOptions().width}
|
||||
d={path}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
@ -25,7 +25,6 @@ import {
|
||||
tabsClasses,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
DefaultLinkModel,
|
||||
DefaultPortModel,
|
||||
DiagramEngine,
|
||||
DiagramModel,
|
||||
@ -54,6 +53,7 @@ import { IBlock } from "@/types/block.types";
|
||||
import { ICategory } from "@/types/category.types";
|
||||
import { BlockPorts } from "@/types/visual-editor.types";
|
||||
|
||||
import { AdvancedLinkModel } from "./AdvancedLink/AdvancedLink";
|
||||
import BlockDialog from "../BlockDialog";
|
||||
import { ZOOM_LEVEL } from "../constants";
|
||||
import { useVisualEditor } from "../hooks/useVisualEditor";
|
||||
@ -195,7 +195,7 @@ const Diagrams = () => {
|
||||
entity,
|
||||
port,
|
||||
}: {
|
||||
entity: DefaultLinkModel;
|
||||
entity: AdvancedLinkModel;
|
||||
port: DefaultPortModel;
|
||||
}) => {
|
||||
const link = model.getLink(entity.getOptions().id as string);
|
||||
@ -205,7 +205,10 @@ const Diagrams = () => {
|
||||
[BlockPorts.nextBlocksOutPort, BlockPorts.attachmentOutPort].includes(
|
||||
// @ts-expect-error protected attr
|
||||
entity.targetPort.getOptions().label,
|
||||
)
|
||||
) ||
|
||||
(link.getSourcePort().getType() === "attached" &&
|
||||
link.getSourcePort().getParent().getOptions().id ===
|
||||
link.getTargetPort().getParent().getOptions().id)
|
||||
) {
|
||||
model.removeLink(link);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user