[agent-pipeline] pipe-20260315110231-zn60 round-2
This commit is contained in:
parent
558acd1f9b
commit
3ef8cebf1a
|
|
@ -506,21 +506,21 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`group relative flex w-[260px] flex-col overflow-visible rounded-xl border border-border/50 bg-card/80 backdrop-blur-sm shadow-lg ${
|
className={`group relative flex w-[260px] flex-col overflow-visible rounded-[10px] border bg-card/80 backdrop-blur-sm shadow-[0_4px_24px_-8px_rgba(0,0,0,0.5)] ${
|
||||||
// 1. 필터 테이블 (마스터-디테일의 디테일 테이블): 항상 primary 테두리
|
// 1. 필터 테이블 (마스터-디테일의 디테일 테이블)
|
||||||
isFilterTable
|
isFilterTable
|
||||||
? "border-2 border-primary ring-2 ring-primary/20 shadow-lg bg-primary/5"
|
? "border-primary/30 shadow-[0_0_0_1px_hsl(var(--primary)/0.3)]"
|
||||||
// 2. 필터 관련 테이블 (마스터 또는 디테일) 포커스 시: primary 강조
|
// 2. 필터 관련 테이블 포커스 시
|
||||||
: (hasFilterRelation || isFilterSource)
|
: (hasFilterRelation || isFilterSource)
|
||||||
? "border-2 border-primary ring-4 ring-primary/30 shadow-xl bg-primary/5"
|
? "border-primary/30 shadow-[0_0_0_1px_hsl(var(--primary)/0.3),0_0_24px_-8px_hsl(var(--primary)/0.1)]"
|
||||||
// 3. 순수 포커스 (필터 관계 없음): primary
|
// 3. 순수 포커스
|
||||||
: isFocused
|
: isFocused
|
||||||
? "border-2 border-primary ring-4 ring-primary/30 shadow-xl bg-card"
|
? "border-primary/30 shadow-[0_0_0_1px_hsl(var(--primary)/0.3),0_0_24px_-8px_hsl(var(--primary)/0.1)] bg-card"
|
||||||
// 4. 흐리게 처리
|
// 4. 흐리게 처리
|
||||||
: isFaded
|
: isFaded
|
||||||
? "opacity-60 bg-card"
|
? "opacity-60 bg-card border-border/10"
|
||||||
// 5. 기본
|
// 5. 기본
|
||||||
: "hover:shadow-xl hover:ring-2 hover:ring-primary/20"
|
: "border-border/10 hover:border-border/20"
|
||||||
}`}
|
}`}
|
||||||
style={{
|
style={{
|
||||||
filter: isFaded ? "grayscale(80%)" : "none",
|
filter: isFaded ? "grayscale(80%)" : "none",
|
||||||
|
|
@ -548,7 +548,7 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Top}
|
position={Position.Top}
|
||||||
id="top"
|
id="top"
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-primary opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
{/* top source: 메인테이블 → 메인테이블 연결용 (위쪽으로 나가는 선) */}
|
{/* top source: 메인테이블 → 메인테이블 연결용 (위쪽으로 나가는 선) */}
|
||||||
<Handle
|
<Handle
|
||||||
|
|
@ -556,25 +556,25 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
position={Position.Top}
|
position={Position.Top}
|
||||||
id="top_source"
|
id="top_source"
|
||||||
style={{ top: -4 }}
|
style={{ top: -4 }}
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-warning opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
<Handle
|
<Handle
|
||||||
type="target"
|
type="target"
|
||||||
position={Position.Left}
|
position={Position.Left}
|
||||||
id="left"
|
id="left"
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-primary opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
<Handle
|
<Handle
|
||||||
type="source"
|
type="source"
|
||||||
position={Position.Right}
|
position={Position.Right}
|
||||||
id="right"
|
id="right"
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-primary opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
<Handle
|
<Handle
|
||||||
type="source"
|
type="source"
|
||||||
position={Position.Bottom}
|
position={Position.Bottom}
|
||||||
id="bottom"
|
id="bottom"
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-warning opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
{/* bottom target: 메인테이블 ← 메인테이블 연결용 (아래에서 들어오는 선) */}
|
{/* bottom target: 메인테이블 ← 메인테이블 연결용 (아래에서 들어오는 선) */}
|
||||||
<Handle
|
<Handle
|
||||||
|
|
@ -582,24 +582,18 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
position={Position.Bottom}
|
position={Position.Bottom}
|
||||||
id="bottom_target"
|
id="bottom_target"
|
||||||
style={{ bottom: -4 }}
|
style={{ bottom: -4 }}
|
||||||
className="!h-2 !w-2 !border-2 !border-background !bg-warning opacity-0 transition-opacity group-hover:opacity-100"
|
className="!h-2 !w-2 !border-[1.5px] !border-card !bg-muted-foreground/40 opacity-0 transition-opacity group-hover:opacity-100"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* 헤더 (필터 관계: primary, 필터 소스: primary, 메인: primary, 기본: muted-foreground) - 그라데이션 */}
|
{/* 헤더: 그라디언트 제거, bg-muted/30 + 아이콘 박스 */}
|
||||||
<div className={`flex items-center gap-2 px-3 py-1.5 text-primary-foreground rounded-t-xl transition-colors duration-700 ease-in-out ${
|
<div className="flex items-center gap-2.5 px-3.5 py-2.5 border-b border-border/10 bg-muted/30 rounded-t-[10px] transition-colors duration-700 ease-in-out">
|
||||||
isFaded
|
<div className="flex h-7 w-7 items-center justify-center rounded-[7px] bg-cyan-500/10 shrink-0">
|
||||||
? "bg-gradient-to-r from-muted-foreground to-muted-foreground/70"
|
<Database className="h-3.5 w-3.5 text-cyan-400" />
|
||||||
: (hasFilterRelation || isFilterSource)
|
</div>
|
||||||
? "bg-gradient-to-r from-primary to-primary/70"
|
|
||||||
: isMain
|
|
||||||
? "bg-gradient-to-r from-primary to-primary/70"
|
|
||||||
: "bg-gradient-to-r from-muted-foreground to-muted-foreground/70"
|
|
||||||
}`}>
|
|
||||||
<Database className="h-3.5 w-3.5 shrink-0" />
|
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
<div className="truncate text-[11px] font-semibold">{label}</div>
|
<div className="truncate text-[11px] font-semibold text-foreground font-mono">{label}</div>
|
||||||
{/* 필터 관계에 따른 문구 변경 */}
|
{/* 필터 관계에 따른 문구 변경 */}
|
||||||
<div className="truncate text-[9px] opacity-80">
|
<div className="truncate text-[9px] font-mono text-muted-foreground/40 tracking-[-0.3px]">
|
||||||
{isFilterSource
|
{isFilterSource
|
||||||
? "마스터 테이블 (필터 소스)"
|
? "마스터 테이블 (필터 소스)"
|
||||||
: hasFilterRelation
|
: hasFilterRelation
|
||||||
|
|
@ -608,8 +602,8 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{hasActiveColumns && (
|
{hasActiveColumns && (
|
||||||
<span className="rounded-full bg-primary-foreground/25 backdrop-blur-sm border border-primary-foreground/10 px-1.5 py-0.5 text-[8px] shrink-0">
|
<span className="text-[9px] font-mono text-muted-foreground/40 px-1.5 py-0.5 rounded bg-foreground/5 border border-border/10 tracking-[-0.3px] shrink-0">
|
||||||
{displayColumns.length}개 활성
|
{displayColumns.length} ref
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -697,18 +691,22 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
opacity: hasActiveColumns ? 0 : 1,
|
opacity: hasActiveColumns ? 0 : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* PK/FK/조인/필터 아이콘 */}
|
{/* 3px 세로 마커 (PK/FK/조인/필터) */}
|
||||||
{isJoinColumn && <Link2 className="h-2.5 w-2.5 text-warning" />}
|
<div
|
||||||
{(isFilterColumn || isFilterSourceColumn) && !isJoinColumn && <Link2 className="h-2.5 w-2.5 text-primary" />}
|
className={`w-[3px] h-[14px] rounded-sm flex-shrink-0 ${
|
||||||
{!isJoinColumn && !isFilterColumn && !isFilterSourceColumn && col.isPrimaryKey && <Key className="h-2.5 w-2.5 text-warning" />}
|
isJoinColumn ? "bg-amber-400"
|
||||||
{!isJoinColumn && !isFilterColumn && !isFilterSourceColumn && col.isForeignKey && !col.isPrimaryKey && <Link2 className="h-2.5 w-2.5 text-primary" />}
|
: (isFilterColumn || isFilterSourceColumn) ? "bg-primary opacity-80"
|
||||||
{!isJoinColumn && !isFilterColumn && !isFilterSourceColumn && !col.isPrimaryKey && !col.isForeignKey && <div className="w-2.5" />}
|
: col.isPrimaryKey ? "bg-amber-400"
|
||||||
|
: col.isForeignKey ? "bg-primary opacity-80"
|
||||||
|
: "bg-muted-foreground/20"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* 컬럼명 */}
|
{/* 컬럼명 */}
|
||||||
<span className={`flex-1 truncate font-mono text-[9px] font-medium ${
|
<span className={`flex-1 truncate font-mono text-[9px] font-medium ${
|
||||||
isJoinColumn ? "text-warning"
|
isJoinColumn ? "text-amber-400"
|
||||||
: (isFilterColumn || isFilterSourceColumn) ? "text-primary"
|
: (isFilterColumn || isFilterSourceColumn) ? "text-primary"
|
||||||
: isHighlighted ? "text-primary"
|
: isHighlighted ? "text-primary"
|
||||||
: "text-foreground"
|
: "text-foreground"
|
||||||
}`}>
|
}`}>
|
||||||
{col.name}
|
{col.name}
|
||||||
|
|
@ -749,7 +747,7 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 타입 */}
|
{/* 타입 */}
|
||||||
<span className="text-[8px] text-muted-foreground">{col.type}</span>
|
<span className="text-[8px] text-muted-foreground/30 font-mono tracking-[-0.3px]">{col.type}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
@ -768,13 +766,25 @@ export const TableNode: React.FC<{ data: TableNodeData }> = ({ data }) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 푸터 (컴팩트) */}
|
{/* 푸터: cols + PK/FK 카운트 */}
|
||||||
<div className="flex items-center justify-end border-t border-border bg-muted/30 px-2 py-1">
|
<div className="flex items-center justify-between border-t border-border/10 px-3.5 py-1.5 bg-background/50">
|
||||||
{columns && (
|
<span className="text-[9px] text-muted-foreground/40 font-mono tracking-[-0.3px]">
|
||||||
<span className="text-[9px] text-muted-foreground">
|
{hasActiveColumns ? `${displayColumns.length}/${totalCount}` : totalCount} cols
|
||||||
{hasActiveColumns ? `${displayColumns.length}/${totalCount}` : totalCount}개 컬럼
|
</span>
|
||||||
</span>
|
<div className="flex gap-2.5 text-[9px] font-mono tracking-[-0.3px]">
|
||||||
)}
|
{columns?.some(c => c.isPrimaryKey) && (
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<span className="w-1 h-1 rounded-full bg-amber-400" />
|
||||||
|
<span className="text-muted-foreground/40">PK {columns.filter(c => c.isPrimaryKey).length}</span>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{columns?.some(c => c.isForeignKey) && (
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<span className="w-1 h-1 rounded-full bg-primary" />
|
||||||
|
<span className="text-muted-foreground/40">FK {columns.filter(c => c.isForeignKey).length}</span>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CSS 애니메이션 정의 */}
|
{/* CSS 애니메이션 정의 */}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue