2024-06-05 10:46:06 +08:00
|
|
|
|
import {
|
|
|
|
|
|
BaseEdge,
|
|
|
|
|
|
EdgeLabelRenderer,
|
|
|
|
|
|
EdgeProps,
|
|
|
|
|
|
getBezierPath,
|
|
|
|
|
|
} from 'reactflow';
|
2024-06-06 19:29:36 +08:00
|
|
|
|
import useGraphStore from '../../store';
|
2024-06-05 10:46:06 +08:00
|
|
|
|
|
2024-07-08 17:45:17 +08:00
|
|
|
|
import { useFetchFlow } from '@/hooks/flow-hooks';
|
2024-06-05 10:46:06 +08:00
|
|
|
|
import { useMemo } from 'react';
|
|
|
|
|
|
import styles from './index.less';
|
|
|
|
|
|
|
|
|
|
|
|
export function ButtonEdge({
|
|
|
|
|
|
id,
|
|
|
|
|
|
sourceX,
|
|
|
|
|
|
sourceY,
|
|
|
|
|
|
targetX,
|
|
|
|
|
|
targetY,
|
|
|
|
|
|
sourcePosition,
|
|
|
|
|
|
targetPosition,
|
2024-07-08 17:45:17 +08:00
|
|
|
|
source,
|
|
|
|
|
|
target,
|
2024-06-05 10:46:06 +08:00
|
|
|
|
style = {},
|
|
|
|
|
|
markerEnd,
|
|
|
|
|
|
selected,
|
|
|
|
|
|
}: EdgeProps) {
|
2024-06-06 19:29:36 +08:00
|
|
|
|
const deleteEdgeById = useGraphStore((state) => state.deleteEdgeById);
|
2024-06-05 10:46:06 +08:00
|
|
|
|
const [edgePath, labelX, labelY] = getBezierPath({
|
|
|
|
|
|
sourceX,
|
|
|
|
|
|
sourceY,
|
|
|
|
|
|
sourcePosition,
|
|
|
|
|
|
targetX,
|
|
|
|
|
|
targetY,
|
|
|
|
|
|
targetPosition,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const selectedStyle = useMemo(() => {
|
2024-07-08 17:45:17 +08:00
|
|
|
|
return selected ? { strokeWidth: 2, stroke: '#1677ff' } : {};
|
2024-06-05 10:46:06 +08:00
|
|
|
|
}, [selected]);
|
|
|
|
|
|
|
|
|
|
|
|
const onEdgeClick = () => {
|
|
|
|
|
|
deleteEdgeById(id);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-07-08 17:45:17 +08:00
|
|
|
|
// highlight the nodes that the workflow passes through
|
|
|
|
|
|
const { data: flowDetail } = useFetchFlow();
|
|
|
|
|
|
const graphPath = useMemo(() => {
|
|
|
|
|
|
// TODO: this will be called multiple times
|
|
|
|
|
|
const path = flowDetail.dsl.path ?? [];
|
|
|
|
|
|
// The second to last
|
|
|
|
|
|
const previousGraphPath: string[] = path.at(-2) ?? [];
|
|
|
|
|
|
let graphPath: string[] = path.at(-1) ?? [];
|
|
|
|
|
|
// The last of the second to last article
|
|
|
|
|
|
const previousLatestElement = previousGraphPath.at(-1);
|
|
|
|
|
|
if (previousGraphPath.length > 0 && previousLatestElement) {
|
|
|
|
|
|
graphPath = [previousLatestElement, ...graphPath];
|
|
|
|
|
|
}
|
|
|
|
|
|
return graphPath;
|
|
|
|
|
|
}, [flowDetail.dsl.path]);
|
|
|
|
|
|
|
|
|
|
|
|
const highlightStyle = useMemo(() => {
|
|
|
|
|
|
const idx = graphPath.findIndex((x) => x === source);
|
|
|
|
|
|
if (idx !== -1 && graphPath[idx + 1] === target) {
|
|
|
|
|
|
return { strokeWidth: 2, stroke: 'red' };
|
|
|
|
|
|
}
|
|
|
|
|
|
return {};
|
|
|
|
|
|
}, [source, target, graphPath]);
|
|
|
|
|
|
|
2024-06-05 10:46:06 +08:00
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<BaseEdge
|
|
|
|
|
|
path={edgePath}
|
|
|
|
|
|
markerEnd={markerEnd}
|
2024-07-08 17:45:17 +08:00
|
|
|
|
style={{ ...style, ...selectedStyle, ...highlightStyle }}
|
2024-06-05 10:46:06 +08:00
|
|
|
|
/>
|
|
|
|
|
|
<EdgeLabelRenderer>
|
|
|
|
|
|
<div
|
|
|
|
|
|
style={{
|
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
|
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
// everything inside EdgeLabelRenderer has no pointer events by default
|
|
|
|
|
|
// if you have an interactive element, set pointer-events: all
|
|
|
|
|
|
pointerEvents: 'all',
|
|
|
|
|
|
}}
|
|
|
|
|
|
className="nodrag nopan"
|
|
|
|
|
|
>
|
|
|
|
|
|
<button
|
|
|
|
|
|
className={styles.edgeButton}
|
|
|
|
|
|
type="button"
|
|
|
|
|
|
onClick={onEdgeClick}
|
|
|
|
|
|
>
|
|
|
|
|
|
×
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</EdgeLabelRenderer>
|
|
|
|
|
|
</>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|