테이블 관계 저장 구현
This commit is contained in:
@@ -17,7 +17,14 @@ import "@xyflow/react/dist/style.css";
|
||||
import { TableNode } from "./TableNode";
|
||||
import { TableSelector } from "./TableSelector";
|
||||
import { ConnectionSetupModal } from "./ConnectionSetupModal";
|
||||
import { TableDefinition } from "@/lib/api/dataflow";
|
||||
import { TableDefinition, TableRelationship, DataFlowAPI } from "@/lib/api/dataflow";
|
||||
|
||||
// 고유 ID 생성 함수
|
||||
const generateUniqueId = (prefix: string, relationshipId?: number): string => {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substr(2, 9);
|
||||
return `${prefix}-${relationshipId || timestamp}-${random}`;
|
||||
};
|
||||
|
||||
// 테이블 노드 데이터 타입 정의
|
||||
interface TableNodeData extends Record<string, unknown> {
|
||||
@@ -47,19 +54,7 @@ interface DataFlowDesignerProps {
|
||||
onSave?: (relationships: TableRelationship[]) => void;
|
||||
}
|
||||
|
||||
interface TableRelationship {
|
||||
relationshipId?: number;
|
||||
relationshipName: string;
|
||||
fromTableName: string;
|
||||
fromColumnName: string;
|
||||
toTableName: string;
|
||||
toColumnName: string;
|
||||
relationshipType: "one-to-one" | "one-to-many" | "many-to-one" | "many-to-many";
|
||||
connectionType: "simple-key" | "data-save" | "external-call";
|
||||
settings?: Record<string, unknown>;
|
||||
companyCode: string;
|
||||
isActive?: string;
|
||||
}
|
||||
// TableRelationship 타입은 dataflow.ts에서 import
|
||||
|
||||
export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode, onSave }) => {
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node<TableNodeData>>([]);
|
||||
@@ -81,6 +76,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
};
|
||||
};
|
||||
} | null>(null);
|
||||
const [relationships, setRelationships] = useState<TableRelationship[]>([]);
|
||||
const toastShownRef = useRef(false);
|
||||
|
||||
// 키보드 이벤트 핸들러 (Del 키로 선택된 노드 삭제)
|
||||
@@ -117,6 +113,44 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
||||
}, [selectedNodes, setNodes]);
|
||||
|
||||
// 기존 관계 로드
|
||||
const loadExistingRelationships = useCallback(async () => {
|
||||
try {
|
||||
const existingRelationships = await DataFlowAPI.getRelationshipsByCompany(companyCode);
|
||||
setRelationships(existingRelationships);
|
||||
|
||||
// 기존 관계를 엣지로 변환하여 표시
|
||||
const existingEdges = existingRelationships.map((rel) => ({
|
||||
id: generateUniqueId("edge", rel.relationshipId),
|
||||
source: `table-${rel.fromTableName}`,
|
||||
target: `table-${rel.toTableName}`,
|
||||
sourceHandle: "right",
|
||||
targetHandle: "left",
|
||||
type: "default",
|
||||
data: {
|
||||
relationshipId: rel.relationshipId,
|
||||
relationshipType: rel.relationshipType,
|
||||
connectionType: rel.connectionType,
|
||||
label: rel.relationshipName,
|
||||
fromColumn: rel.fromColumnName,
|
||||
toColumn: rel.toColumnName,
|
||||
},
|
||||
}));
|
||||
|
||||
setEdges(existingEdges);
|
||||
} catch (error) {
|
||||
console.error("기존 관계 로드 실패:", error);
|
||||
toast.error("기존 관계를 불러오는데 실패했습니다.");
|
||||
}
|
||||
}, [companyCode, setEdges]);
|
||||
|
||||
// 컴포넌트 마운트 시 기존 관계 로드
|
||||
useEffect(() => {
|
||||
if (companyCode) {
|
||||
loadExistingRelationships();
|
||||
}
|
||||
}, [companyCode, loadExistingRelationships]);
|
||||
|
||||
// 노드 선택 변경 핸들러
|
||||
const onSelectionChange = useCallback(({ nodes }: { nodes: Node<TableNodeData>[] }) => {
|
||||
const selectedNodeIds = nodes.map((node) => node.id);
|
||||
@@ -229,6 +263,10 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
|
||||
if (!firstNode || !secondNode) return;
|
||||
|
||||
// 첫 번째로 선택된 컬럼들 가져오기
|
||||
const firstTableColumns = selectedColumns[firstTableName] || [];
|
||||
const secondTableColumns = selectedColumns[secondTableName] || [];
|
||||
|
||||
setPendingConnection({
|
||||
fromNode: {
|
||||
id: firstNode.id,
|
||||
@@ -240,6 +278,9 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
tableName: secondNode.data.table.tableName,
|
||||
displayName: secondNode.data.table.displayName,
|
||||
},
|
||||
// 선택된 첫 번째 컬럼을 연결 컬럼으로 설정
|
||||
fromColumn: firstTableColumns[0] || "",
|
||||
toColumn: secondTableColumns[0] || "",
|
||||
// 선택된 모든 컬럼 정보를 선택 순서대로 전달
|
||||
selectedColumnsData: (() => {
|
||||
const orderedData: { [key: string]: { displayName: string; columns: string[] } } = {};
|
||||
@@ -335,28 +376,41 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
|
||||
// 연결 설정 확인
|
||||
const handleConfirmConnection = useCallback(
|
||||
(config: { relationshipType: string; connectionType: string; relationshipName: string }) => {
|
||||
(relationship: TableRelationship) => {
|
||||
if (!pendingConnection) return;
|
||||
|
||||
const newEdge = {
|
||||
id: `edge-${Date.now()}`,
|
||||
id: generateUniqueId("edge", relationship.relationshipId),
|
||||
source: pendingConnection.fromNode.id,
|
||||
target: pendingConnection.toNode.id,
|
||||
sourceHandle: "right",
|
||||
targetHandle: "left",
|
||||
type: "default",
|
||||
data: {
|
||||
relationshipType: config.relationshipType,
|
||||
connectionType: config.connectionType,
|
||||
label: config.relationshipName,
|
||||
relationshipId: relationship.relationshipId,
|
||||
relationshipType: relationship.relationshipType,
|
||||
connectionType: relationship.connectionType,
|
||||
label: relationship.relationshipName,
|
||||
fromColumn: relationship.fromColumnName,
|
||||
toColumn: relationship.toColumnName,
|
||||
},
|
||||
};
|
||||
|
||||
setEdges((eds) => [...eds, newEdge]);
|
||||
setRelationships((prev) => [...prev, relationship]);
|
||||
setPendingConnection(null);
|
||||
|
||||
// TODO: 백엔드 API 호출하여 관계 저장
|
||||
console.log("연결 설정:", config);
|
||||
console.log("관계 생성 완료:", relationship);
|
||||
// 저장 콜백 호출 (필요한 경우)
|
||||
if (onSave) {
|
||||
// 현재 모든 관계를 수집하여 전달
|
||||
setRelationships((currentRelationships) => {
|
||||
onSave([...currentRelationships, relationship]);
|
||||
return currentRelationships;
|
||||
});
|
||||
}
|
||||
},
|
||||
[pendingConnection, setEdges],
|
||||
[pendingConnection, setEdges, onSave],
|
||||
);
|
||||
|
||||
// 연결 설정 취소
|
||||
@@ -536,6 +590,7 @@ export const DataFlowDesigner: React.FC<DataFlowDesignerProps> = ({ companyCode,
|
||||
<ConnectionSetupModal
|
||||
isOpen={!!pendingConnection}
|
||||
connection={pendingConnection}
|
||||
companyCode={companyCode}
|
||||
onConfirm={handleConfirmConnection}
|
||||
onCancel={handleCancelConnection}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user