163 lines
4.1 KiB
TypeScript
163 lines
4.1 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import React from "react";
|
||
|
|
import { EdgeProps, getBezierPath, EdgeLabelRenderer, BaseEdge } from "@xyflow/react";
|
||
|
|
|
||
|
|
interface CustomEdgeData {
|
||
|
|
relationshipType: string;
|
||
|
|
connectionType: string;
|
||
|
|
label?: string;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const CustomEdge: React.FC<EdgeProps<CustomEdgeData>> = ({
|
||
|
|
id,
|
||
|
|
sourceX,
|
||
|
|
sourceY,
|
||
|
|
targetX,
|
||
|
|
targetY,
|
||
|
|
sourcePosition,
|
||
|
|
targetPosition,
|
||
|
|
data,
|
||
|
|
markerEnd,
|
||
|
|
selected,
|
||
|
|
}) => {
|
||
|
|
const [edgePath, labelX, labelY] = getBezierPath({
|
||
|
|
sourceX,
|
||
|
|
sourceY,
|
||
|
|
sourcePosition,
|
||
|
|
targetX,
|
||
|
|
targetY,
|
||
|
|
targetPosition,
|
||
|
|
});
|
||
|
|
|
||
|
|
// 연결 타입에 따른 색상 반환
|
||
|
|
const getEdgeColor = (connectionType: string) => {
|
||
|
|
switch (connectionType) {
|
||
|
|
case "simple-key":
|
||
|
|
return "#3B82F6"; // 파란색 - 단순 키값 연결
|
||
|
|
case "data-save":
|
||
|
|
return "#10B981"; // 초록색 - 데이터 저장
|
||
|
|
case "external-call":
|
||
|
|
return "#F59E0B"; // 주황색 - 외부 호출
|
||
|
|
default:
|
||
|
|
return "#6B7280"; // 회색 - 기본
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 연결 타입에 따른 스타일 반환
|
||
|
|
const getEdgeStyle = (connectionType: string) => {
|
||
|
|
switch (connectionType) {
|
||
|
|
case "simple-key":
|
||
|
|
return {
|
||
|
|
strokeWidth: 2,
|
||
|
|
strokeDasharray: "5,5",
|
||
|
|
opacity: selected ? 1 : 0.8,
|
||
|
|
};
|
||
|
|
case "data-save":
|
||
|
|
return {
|
||
|
|
strokeWidth: 3,
|
||
|
|
opacity: selected ? 1 : 0.8,
|
||
|
|
};
|
||
|
|
case "external-call":
|
||
|
|
return {
|
||
|
|
strokeWidth: 2,
|
||
|
|
strokeDasharray: "10,5",
|
||
|
|
opacity: selected ? 1 : 0.8,
|
||
|
|
};
|
||
|
|
default:
|
||
|
|
return {
|
||
|
|
strokeWidth: 2,
|
||
|
|
opacity: selected ? 1 : 0.6,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 관계 타입에 따른 아이콘 반환
|
||
|
|
const getRelationshipIcon = (relationshipType: string) => {
|
||
|
|
switch (relationshipType) {
|
||
|
|
case "one-to-one":
|
||
|
|
return "1:1";
|
||
|
|
case "one-to-many":
|
||
|
|
return "1:N";
|
||
|
|
case "many-to-one":
|
||
|
|
return "N:1";
|
||
|
|
case "many-to-many":
|
||
|
|
return "N:N";
|
||
|
|
default:
|
||
|
|
return "1:1";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 연결 타입에 따른 설명 반환
|
||
|
|
const getConnectionTypeDescription = (connectionType: string) => {
|
||
|
|
switch (connectionType) {
|
||
|
|
case "simple-key":
|
||
|
|
return "단순 키값";
|
||
|
|
case "data-save":
|
||
|
|
return "데이터 저장";
|
||
|
|
case "external-call":
|
||
|
|
return "외부 호출";
|
||
|
|
default:
|
||
|
|
return "연결";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const edgeColor = getEdgeColor(data?.connectionType || "");
|
||
|
|
const edgeStyle = getEdgeStyle(data?.connectionType || "");
|
||
|
|
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<BaseEdge
|
||
|
|
id={id}
|
||
|
|
path={edgePath}
|
||
|
|
markerEnd={markerEnd}
|
||
|
|
style={{
|
||
|
|
stroke: edgeColor,
|
||
|
|
...edgeStyle,
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<EdgeLabelRenderer>
|
||
|
|
<div
|
||
|
|
style={{
|
||
|
|
position: "absolute",
|
||
|
|
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
|
||
|
|
background: "white",
|
||
|
|
padding: "8px 12px",
|
||
|
|
borderRadius: "8px",
|
||
|
|
fontSize: "12px",
|
||
|
|
fontWeight: 600,
|
||
|
|
border: `2px solid ${edgeColor}`,
|
||
|
|
boxShadow: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
|
||
|
|
color: edgeColor,
|
||
|
|
minWidth: "80px",
|
||
|
|
textAlign: "center",
|
||
|
|
}}
|
||
|
|
className={`nodrag nopan transition-all duration-200 ${selected ? "scale-110" : "hover:scale-105"}`}
|
||
|
|
>
|
||
|
|
<div className="flex flex-col items-center">
|
||
|
|
<div className="text-sm font-bold">
|
||
|
|
{data?.label || getRelationshipIcon(data?.relationshipType || "one-to-one")}
|
||
|
|
</div>
|
||
|
|
<div className="mt-1 text-xs opacity-75">
|
||
|
|
{getConnectionTypeDescription(data?.connectionType || "simple-key")}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</EdgeLabelRenderer>
|
||
|
|
|
||
|
|
{/* 선택된 상태일 때 추가 시각적 효과 */}
|
||
|
|
{selected && (
|
||
|
|
<BaseEdge
|
||
|
|
id={`${id}-glow`}
|
||
|
|
path={edgePath}
|
||
|
|
style={{
|
||
|
|
stroke: edgeColor,
|
||
|
|
strokeWidth: 6,
|
||
|
|
opacity: 0.3,
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
};
|