[agent-pipeline] pipe-20260315121506-3c5c round-2
This commit is contained in:
parent
009607f3f1
commit
8ed7faf517
|
|
@ -1488,6 +1488,32 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lookup 필터 OFF일 때: lookup 연결만 있는 테이블 노드를 dim 처리
|
||||||
|
const lookupOnlyNodes = new Set<string>();
|
||||||
|
if (!edgeFilterState.lookup) {
|
||||||
|
const nodeEdgeCategories = new Map<string, Set<EdgeCategory>>();
|
||||||
|
edges.forEach((edge) => {
|
||||||
|
const category = (edge.data as any)?.edgeCategory as EdgeCategory | undefined;
|
||||||
|
if (!category) return;
|
||||||
|
[edge.source, edge.target].forEach((nodeId) => {
|
||||||
|
if (!nodeEdgeCategories.has(nodeId)) {
|
||||||
|
nodeEdgeCategories.set(nodeId, new Set());
|
||||||
|
}
|
||||||
|
nodeEdgeCategories.get(nodeId)!.add(category);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
nodeEdgeCategories.forEach((categories, nodeId) => {
|
||||||
|
if (nodeId.startsWith("table-") || nodeId.startsWith("subtable-")) {
|
||||||
|
const hasVisibleCategory = Array.from(categories).some(
|
||||||
|
(cat) => cat !== "lookup" && edgeFilterState[cat]
|
||||||
|
);
|
||||||
|
if (!hasVisibleCategory) {
|
||||||
|
lookupOnlyNodes.add(nodeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return nodes.map((node) => {
|
return nodes.map((node) => {
|
||||||
// 화면 노드 스타일링 (포커스가 있을 때만)
|
// 화면 노드 스타일링 (포커스가 있을 때만)
|
||||||
if (node.id.startsWith("screen-")) {
|
if (node.id.startsWith("screen-")) {
|
||||||
|
|
@ -1783,7 +1809,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
...node.data,
|
...node.data,
|
||||||
isFocused: isFocusedTable,
|
isFocused: isFocusedTable,
|
||||||
isRelated: isRelatedTable,
|
isRelated: isRelatedTable,
|
||||||
isFaded: focusedScreenId !== null && !isActiveTable,
|
isFaded: (focusedScreenId !== null && !isActiveTable) || lookupOnlyNodes.has(node.id),
|
||||||
highlightedColumns: isActiveTable ? highlightedColumns : [],
|
highlightedColumns: isActiveTable ? highlightedColumns : [],
|
||||||
joinColumns: isActiveTable ? joinColumns : [],
|
joinColumns: isActiveTable ? joinColumns : [],
|
||||||
joinColumnRefs: focusedJoinColumnRefs.length > 0 ? focusedJoinColumnRefs : undefined, // 조인 컬럼 참조 정보
|
joinColumnRefs: focusedJoinColumnRefs.length > 0 ? focusedJoinColumnRefs : undefined, // 조인 컬럼 참조 정보
|
||||||
|
|
@ -1894,7 +1920,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
data: {
|
data: {
|
||||||
...node.data,
|
...node.data,
|
||||||
isFocused: isActiveSubTable,
|
isFocused: isActiveSubTable,
|
||||||
isFaded: !isActiveSubTable,
|
isFaded: !isActiveSubTable || lookupOnlyNodes.has(node.id),
|
||||||
highlightedColumns: isActiveSubTable ? subTableHighlightedColumns : [],
|
highlightedColumns: isActiveSubTable ? subTableHighlightedColumns : [],
|
||||||
joinColumns: isActiveSubTable ? subTableJoinColumns : [],
|
joinColumns: isActiveSubTable ? subTableJoinColumns : [],
|
||||||
fieldMappings: isActiveSubTable ? displayFieldMappings : [],
|
fieldMappings: isActiveSubTable ? displayFieldMappings : [],
|
||||||
|
|
@ -1905,7 +1931,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
});
|
});
|
||||||
}, [nodes, selectedGroup, focusedScreenId, screenSubTableMap, subTablesDataMap, screenUsedColumnsMap, screenTableMap, tableColumns]);
|
}, [nodes, selectedGroup, focusedScreenId, screenSubTableMap, subTablesDataMap, screenUsedColumnsMap, screenTableMap, tableColumns, edgeFilterState, edges]);
|
||||||
|
|
||||||
// 포커스에 따른 엣지 스타일링 (그룹 모드 & 개별 화면 모드)
|
// 포커스에 따른 엣지 스타일링 (그룹 모드 & 개별 화면 모드)
|
||||||
const styledEdges = React.useMemo(() => {
|
const styledEdges = React.useMemo(() => {
|
||||||
|
|
@ -2304,8 +2330,19 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
});
|
});
|
||||||
|
|
||||||
// 기존 엣지 + 조인 관계 엣지 합치기
|
// 기존 엣지 + 조인 관계 엣지 합치기
|
||||||
return [...styledOriginalEdges, ...joinEdges];
|
const allEdges = [...styledOriginalEdges, ...joinEdges];
|
||||||
}, [edges, nodes, selectedGroup, focusedScreenId, screen, screenSubTableMap, subTablesDataMap, screenTableMap]);
|
// 엣지 필터 적용 (edgeFilterState에 따라 숨김)
|
||||||
|
return allEdges.map((edge) => {
|
||||||
|
const category = (edge.data as any)?.edgeCategory as EdgeCategory | undefined;
|
||||||
|
if (category && !edgeFilterState[category]) {
|
||||||
|
return {
|
||||||
|
...edge,
|
||||||
|
hidden: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return edge;
|
||||||
|
});
|
||||||
|
}, [edges, nodes, selectedGroup, focusedScreenId, screen, screenSubTableMap, subTablesDataMap, screenTableMap, edgeFilterState]);
|
||||||
|
|
||||||
// 그룹의 화면 목록 (데이터 흐름 설정용) - 모든 조건부 return 전에 선언해야 함
|
// 그룹의 화면 목록 (데이터 흐름 설정용) - 모든 조건부 return 전에 선언해야 함
|
||||||
const groupScreensList = React.useMemo(() => {
|
const groupScreensList = React.useMemo(() => {
|
||||||
|
|
@ -2385,6 +2422,37 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
<span className="text-xs text-muted-foreground font-mono">{screen.screenCode}</span>
|
<span className="text-xs text-muted-foreground font-mono">{screen.screenCode}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className="h-4 w-px bg-border/30 mx-1" />
|
||||||
|
<span className="text-[10px] font-medium text-muted-foreground/50">연결</span>
|
||||||
|
|
||||||
|
{(
|
||||||
|
[
|
||||||
|
{ key: "main" as EdgeCategory, label: "메인", color: "bg-primary", defaultOn: true },
|
||||||
|
{ key: "filter" as EdgeCategory, label: "마스터-디테일", color: "bg-[hsl(var(--info))]", defaultOn: true },
|
||||||
|
{ key: "join" as EdgeCategory, label: "엔티티 조인", color: "bg-amber-400", defaultOn: true },
|
||||||
|
{ key: "lookup" as EdgeCategory, label: "코드 참조", color: "bg-warning", defaultOn: false },
|
||||||
|
] as const
|
||||||
|
).map(({ key, label, color, defaultOn }) => {
|
||||||
|
const isOn = edgeFilterState[key];
|
||||||
|
const count = edges.filter((e) => (e.data as any)?.edgeCategory === key).length;
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={key}
|
||||||
|
type="button"
|
||||||
|
onClick={() => setEdgeFilterState((prev) => ({ ...prev, [key]: !prev[key] }))}
|
||||||
|
className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-[10px] font-medium transition-all duration-200 ${
|
||||||
|
isOn
|
||||||
|
? "bg-foreground/5 border border-border/20 text-foreground/80"
|
||||||
|
: `border text-muted-foreground/40 ${!defaultOn ? "border-dashed border-border/20" : "border-border/10"}`
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<span className={`w-1.5 h-1.5 rounded-full ${color} transition-opacity ${isOn ? "opacity-100 shadow-sm" : "opacity-30"}`} />
|
||||||
|
{label}
|
||||||
|
<span className="text-[9px] text-muted-foreground/40 font-mono">{count}</span>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* isViewReady가 false면 숨김 처리하여 깜빡임 방지 */}
|
{/* isViewReady가 false면 숨김 처리하여 깜빡임 방지 */}
|
||||||
|
|
@ -2434,28 +2502,6 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
marginBottom: "8px",
|
marginBottom: "8px",
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/* 관계 범례 */}
|
|
||||||
<div className="absolute bottom-4 left-4 z-10 rounded-lg border bg-card/90 backdrop-blur-sm p-3 shadow-md">
|
|
||||||
<p className="text-[10px] font-medium text-muted-foreground mb-2">관계 유형</p>
|
|
||||||
<div className="flex flex-col gap-1.5">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<div className="h-0.5 w-6 rounded-full bg-primary" />
|
|
||||||
<span className="text-[10px] text-muted-foreground">메인 테이블</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<div className="h-0.5 w-6 rounded-full bg-primary/50" />
|
|
||||||
<span className="text-[10px] text-muted-foreground">마스터-디테일</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<div className="h-0.5 w-6 rounded-full bg-warning" />
|
|
||||||
<span className="text-[10px] text-muted-foreground">코드 참조</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<div className="h-0.5 w-6 rounded-full bg-success" />
|
|
||||||
<span className="text-[10px] text-muted-foreground">엔티티 조인</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue