From 9babdf582dae0c74b9b2b6817ade94d086074411 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 6 Jul 2026 01:12:36 +0900 Subject: [PATCH] feat(inference-ui): inferred-relationships suggestions panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Read-only modal surfacing GET /inferred-relationships: child.col -> parent.col with high/medium confidence badge and reason tooltip. Toolbar 'πŸ”—' button (enabled with a snapshot); api fetchInferredRelationships + demo. tsc clean, frontend 24 files / 140 tests (+4 RTL). Add-to-canvas (dashed edge) is a deliberate follow-up. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd --- frontend/src/App.tsx | 46 +++++++++- frontend/src/api.ts | 20 ++++- .../InferredRelationshipsModal.test.tsx | 54 ++++++++++++ .../modals/InferredRelationshipsModal.tsx | 84 +++++++++++++++++++ frontend/src/components/modals/index.ts | 1 + frontend/src/types.ts | 11 +++ 6 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/modals/InferredRelationshipsModal.test.tsx create mode 100644 frontend/src/components/modals/InferredRelationshipsModal.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6d8675ce..e86951d3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -18,6 +18,7 @@ import { AddTableModal, CardinalityModal, AnnotationsModal, + InferredRelationshipsModal, DiffModal, EditEdgeModal, EditTableModal, @@ -36,6 +37,7 @@ import { deleteAnnotation, deleteView, diffSnapshots, + fetchInferredRelationships, getSnapshot, getView, listAnnotations, @@ -71,7 +73,7 @@ import { } from "./erd/export"; import { exportMermaid } from "./erd/mermaid"; import { GRID_COLUMNS, GRID_X_GAP, GRID_Y_GAP } from "./erd/layoutConstants"; -import type { Connection, ConnectionTestResult, DiagramView, Project, SchemaDiff, Snapshot, SnapshotDetail, TableAnnotation } from "./types"; +import type { Connection, ConnectionTestResult, DiagramView, InferredRelationship, Project, SchemaDiff, Snapshot, SnapshotDetail, TableAnnotation } from "./types"; const TERMINAL_SNAPSHOT_STATUSES = new Set([ "succeeded", @@ -184,6 +186,11 @@ export default function App() { const [connTestResult, setConnTestResult] = useState(null); const [isTestingConn, setIsTestingConn] = useState(false); + const [isInferredModalOpen, setIsInferredModalOpen] = useState(false); + const [inferredRelationships, setInferredRelationships] = useState([]); + const [isInferredLoading, setIsInferredLoading] = useState(false); + const [inferredError, setInferredError] = useState(null); + const [editingEdge, setEditingEdge] = useState(null); const [editingNode, setEditingNode] = useState | null>(null); const [isEditTableModalOpen, setIsEditTableModalOpen] = useState(false); @@ -699,6 +706,22 @@ export default function App() { .finally(() => setIsTestingConn(false)); } + function onOpenInferredRelationships() { + setInferredError(null); + setInferredRelationships([]); + setIsInferredModalOpen(true); + if (!snapshotId) return; + setIsInferredLoading(true); + fetchInferredRelationships(snapshotId) + .then(setInferredRelationships) + .catch(() => setInferredError("μΆ”λ‘ λœ 관계λ₯Ό λΆˆλŸ¬μ˜€μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.")) + .finally(() => setIsInferredLoading(false)); + } + + function onCloseInferredRelationships() { + setIsInferredModalOpen(false); + } + function onSelectDiffBase(baseSnapshotId: string) { setDiffBaseId(baseSnapshotId); if (!snapshotId) return; @@ -1664,6 +1687,19 @@ export default function App() { > πŸ—’ + + + + {isLoading ? ( + 뢄석 쀑… + ) : null} + {error ? ( +
{error}
+ ) : null} + + {!isLoading && !error ? ( +
+ {relationships.length === 0 ? ( + μΆ”λ‘ λœ 관계가 μ—†μŠ΅λ‹ˆλ‹€. + ) : ( +
    + {relationships.map((r, i) => ( +
  • + + {r.child_table}.{r.child_column} β†’ {r.parent_table}. + {r.parent_column} + + + {r.confidence === 'high' ? 'λ†’μŒ' : '보톡'} + +
  • + ))} +
+ )} +
+ ) : null} + + + ); +} diff --git a/frontend/src/components/modals/index.ts b/frontend/src/components/modals/index.ts index 001c3923..018f626e 100644 --- a/frontend/src/components/modals/index.ts +++ b/frontend/src/components/modals/index.ts @@ -1,5 +1,6 @@ export { AddTableModal } from './AddTableModal'; export { AnnotationsModal } from './AnnotationsModal'; +export { InferredRelationshipsModal } from './InferredRelationshipsModal'; export { CardinalityModal } from './CardinalityModal'; export { DiffModal } from './DiffModal'; export { EditEdgeModal } from './EditEdgeModal'; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index ad78df91..afb60034 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -165,6 +165,17 @@ export type TableAnnotation = { updated_at: string } +export type InferredRelationship = { + child_schema: string + child_table: string + child_column: string + parent_schema: string + parent_table: string + parent_column: string + confidence: string + reason: string +} + export type SnapshotDetailResponse = Omit & { error_message: unknown }