feat: 테이블 테두리 및 라운드 제거, 검색 필터 제목 제거

- 모든 테이블 컴포넌트의 외곽 테두리(border) 제거
- 테이블 컨테이너의 라운드(rounded-lg) 제거
- 테이블 행 구분선(border-b)은 유지하여 데이터 구분
- FlowWidget과 TableListComponent에 동일한 스타일 적용
- 검색 필터 영역의 회색 배경(bg-muted/30) 제거
- 검색 필터 제목 제거
- AdvancedSearchFilters 컴포넌트의 '검색 필터' 제목 제거
This commit is contained in:
kjs
2025-10-30 15:39:39 +09:00
parent 0e9e5f29cf
commit 4010273d67
67 changed files with 2546 additions and 741 deletions

View File

@@ -63,17 +63,17 @@ export const DataflowVisualization: React.FC<DataflowVisualizationProps> = ({ st
);
return (
<div className="space-y-6 p-6">
<div className="space-y-4 p-4 sm:space-y-6 sm:p-6">
{/* 헤더 */}
<div className="flex items-center justify-between">
<p className="text-sm text-gray-600"> </p>
<Badge variant={isComplete ? "default" : "secondary"} className="text-sm">
<div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
<p className="text-xs sm:text-sm text-muted-foreground"> </p>
<Badge variant={isComplete ? "default" : "secondary"} className="text-xs sm:text-sm w-fit">
{isComplete ? "✅ 설정 완료" : "⚠️ 설정 필요"}
</Badge>
</div>
{/* Sankey 다이어그램 */}
<div className="relative flex items-center justify-center py-12">
<div className="relative flex flex-col items-center justify-center gap-6 py-8 sm:flex-row sm:gap-0 sm:py-12">
{/* 연결선 레이어 */}
<svg className="absolute inset-0 h-full w-full" style={{ zIndex: 0 }}>
{/* 소스 → 조건 선 */}
@@ -106,105 +106,109 @@ export const DataflowVisualization: React.FC<DataflowVisualizationProps> = ({ st
})}
</svg>
<div className="relative flex w-full items-center justify-around" style={{ zIndex: 1 }}>
<div className="relative flex w-full flex-col items-center justify-around gap-4 sm:flex-row sm:gap-0" style={{ zIndex: 1 }}>
{/* 1. 소스 노드 */}
<div className="flex flex-col items-center" style={{ width: "28%" }}>
<div className="flex flex-col items-center w-full sm:w-[28%]">
<Card
className={`w-full cursor-pointer border-2 transition-all hover:shadow-lg ${
hasSource ? "border-blue-400 bg-blue-50" : "border-gray-300 bg-gray-50"
hasSource ? "border-primary bg-primary/10" : "border-border bg-muted"
}`}
onClick={() => onEdit("source")}
>
<CardContent className="p-4">
<CardContent>
<div className="p-4">
<div className="flex items-center justify-between">
<div className="flex-1">
<div className="mb-2 flex items-center gap-2">
<Database className="h-5 w-5 text-blue-600" />
<span className="text-sm font-semibold text-gray-900"> </span>
<Database className="h-5 w-5 text-primary" />
<span className="text-sm font-semibold text-foreground"> </span>
</div>
{hasSource ? (
<div className="space-y-1">
<p className="text-sm font-medium text-gray-900">
<p className="text-sm font-medium text-foreground">
{fromTable.tableLabel || fromTable.displayName || fromTable.tableName}
</p>
{(fromTable.tableLabel || fromTable.displayName) && (
<p className="text-xs text-gray-500">({fromTable.tableName})</p>
<p className="text-xs text-muted-foreground">({fromTable.tableName})</p>
)}
</div>
) : (
<p className="text-xs text-gray-500"></p>
<p className="text-xs text-muted-foreground"></p>
)}
</div>
<Button variant="ghost" size="sm" className="h-7 w-7 p-0">
<Edit className="h-3 w-3" />
</Button>
</div>
</div>
</CardContent>
</Card>
</div>
{/* 2. 조건 노드 (중앙) */}
<div className="flex flex-col items-center" style={{ width: "28%" }}>
<div className="flex flex-col items-center w-full sm:w-[28%]">
<Card
className={`w-full cursor-pointer border-2 transition-all hover:shadow-lg ${
hasConditions ? "border-yellow-400 bg-yellow-50" : "border-gray-300 bg-gray-50"
hasConditions ? "border-warning bg-warning/10" : "border-border bg-muted"
}`}
onClick={() => onEdit("conditions")}
>
<CardContent className="p-4">
<CardContent>
<div className="p-4">
<div className="flex items-center justify-between">
<div className="flex-1">
<div className="mb-2 flex items-center gap-2">
<Filter className="h-5 w-5 text-yellow-600" />
<span className="text-sm font-semibold text-gray-900"> </span>
<Filter className="h-5 w-5 text-warning" />
<span className="text-sm font-semibold text-foreground"> </span>
</div>
{hasConditions ? (
<div className="space-y-2">
{/* 실제 조건들 표시 */}
<div className="max-h-32 space-y-1 overflow-y-auto">
{controlConditions.slice(0, 3).map((condition, index) => (
<div key={index} className="rounded bg-white/50 px-2 py-1">
<p className="text-xs font-medium text-gray-800">
<div key={index} className="rounded bg-background/50 px-2 py-1">
<p className="text-xs font-medium text-foreground">
{index > 0 && (
<span className="mr-1 font-bold text-blue-600">
<span className="mr-1 font-bold text-primary">
{condition.logicalOperator || "AND"}
</span>
)}
<span className="text-blue-800">{getFieldLabel(condition.field)}</span>{" "}
<span className="text-gray-600">{condition.operator}</span>{" "}
<span className="text-green-700">{condition.value}</span>
<span className="text-primary">{getFieldLabel(condition.field)}</span>{" "}
<span className="text-muted-foreground">{condition.operator}</span>{" "}
<span className="text-success">{condition.value}</span>
</p>
</div>
))}
{controlConditions.length > 3 && (
<p className="px-2 text-xs text-gray-500"> {controlConditions.length - 3}...</p>
<p className="px-2 text-xs text-muted-foreground"> {controlConditions.length - 3}...</p>
)}
</div>
<div className="mt-2 flex items-center justify-between border-t pt-2">
<div className="flex items-center gap-1">
<CheckCircle className="h-3 w-3 text-green-600" />
<span className="text-xs text-gray-600"> </span>
<CheckCircle className="h-3 w-3 text-success" />
<span className="text-xs text-muted-foreground"> </span>
</div>
<div className="flex items-center gap-1">
<XCircle className="h-3 w-3 text-red-600" />
<span className="text-xs text-gray-600"> </span>
<XCircle className="h-3 w-3 text-destructive" />
<span className="text-xs text-muted-foreground"> </span>
</div>
</div>
</div>
) : (
<p className="text-xs text-gray-500"> ( )</p>
<p className="text-xs text-muted-foreground"> ( )</p>
)}
</div>
<Button variant="ghost" size="sm" className="h-7 w-7 p-0">
<Edit className="h-3 w-3" />
</Button>
</div>
</div>
</CardContent>
</Card>
</div>
{/* 3. 액션 노드들 (우측) */}
<div className="flex flex-col items-center gap-3" style={{ width: "28%" }}>
<div className="flex flex-col items-center gap-3 w-full sm:w-[28%]">
<Button
variant="ghost"
size="sm"
@@ -227,10 +231,12 @@ export const DataflowVisualization: React.FC<DataflowVisualizationProps> = ({ st
))}
</div>
) : (
<Card className="w-full border-2 border-dashed border-gray-300 bg-gray-50">
<CardContent className="p-4 text-center">
<Zap className="mx-auto mb-2 h-6 w-6 text-gray-400" />
<p className="text-xs text-gray-500"> </p>
<Card className="w-full border-2 border-dashed border-border bg-muted">
<CardContent>
<div className="p-4 text-center">
<Zap className="mx-auto mb-2 h-6 w-6 text-muted-foreground" />
<p className="text-xs text-muted-foreground"> </p>
</div>
</CardContent>
</Card>
)}
@@ -240,34 +246,36 @@ export const DataflowVisualization: React.FC<DataflowVisualizationProps> = ({ st
{/* 조건 불만족 시 중단 표시 (하단) */}
{hasConditions && (
<div
className="absolute bottom-0 flex items-center gap-2 rounded-lg border-2 border-red-300 bg-red-50 px-3 py-2"
className="absolute bottom-0 flex items-center gap-2 rounded-lg border-2 border-destructive/30 bg-destructive/10 px-3 py-2"
style={{ left: "50%", transform: "translateX(-50%)" }}
>
<XCircle className="h-4 w-4 text-red-600" />
<span className="text-xs font-medium text-red-900"> </span>
<XCircle className="h-4 w-4 text-destructive" />
<span className="text-xs font-medium text-destructive"> </span>
</div>
)}
</div>
{/* 통계 요약 */}
<Card className="border-gray-200 bg-gradient-to-r from-gray-50 to-slate-50">
<CardContent className="p-4">
<div className="flex items-center justify-around text-center">
<Card className="border-border bg-gradient-to-r from-muted to-muted/50">
<CardContent>
<div className="p-4">
<div className="flex flex-col items-center justify-around gap-4 text-center sm:flex-row sm:gap-0">
<div>
<p className="text-xs text-gray-600"></p>
<p className="text-lg font-bold text-blue-600">{hasSource ? 1 : 0}</p>
<p className="text-xs text-muted-foreground"></p>
<p className="text-base font-bold text-primary sm:text-lg">{hasSource ? 1 : 0}</p>
</div>
<div className="h-8 w-px bg-gray-300"></div>
<div className="h-8 w-px bg-border hidden sm:block"></div>
<div>
<p className="text-xs text-gray-600"></p>
<p className="text-lg font-bold text-yellow-600">{controlConditions.length}</p>
<p className="text-xs text-muted-foreground"></p>
<p className="text-base font-bold text-warning sm:text-lg">{controlConditions.length}</p>
</div>
<div className="h-8 w-px bg-gray-300"></div>
<div className="h-8 w-px bg-border hidden sm:block"></div>
<div>
<p className="text-xs text-gray-600"></p>
<p className="text-lg font-bold text-green-600">{dataflowActions.length}</p>
<p className="text-xs text-muted-foreground"></p>
<p className="text-base font-bold text-success sm:text-lg">{dataflowActions.length}</p>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
@@ -288,10 +296,10 @@ interface ActionFlowCardProps {
const ActionFlowCard: React.FC<ActionFlowCardProps> = ({ type, actions, getTableLabel }) => {
const actionColors = {
insert: { bg: "bg-blue-50", border: "border-blue-300", text: "text-blue-900", icon: "text-blue-600" },
update: { bg: "bg-green-50", border: "border-green-300", text: "text-green-900", icon: "text-green-600" },
delete: { bg: "bg-red-50", border: "border-red-300", text: "text-red-900", icon: "text-red-600" },
upsert: { bg: "bg-purple-50", border: "border-purple-300", text: "text-purple-900", icon: "text-purple-600" },
insert: { bg: "bg-primary/10", border: "border-primary/30", text: "text-primary", icon: "text-primary" },
update: { bg: "bg-success/10", border: "border-success/30", text: "text-success", icon: "text-success" },
delete: { bg: "bg-destructive/10", border: "border-destructive/30", text: "text-destructive", icon: "text-destructive" },
upsert: { bg: "bg-primary/10", border: "border-primary/30", text: "text-primary", icon: "text-primary" },
};
const colors = actionColors[type as keyof typeof actionColors] || actionColors.insert;
@@ -301,20 +309,22 @@ const ActionFlowCard: React.FC<ActionFlowCardProps> = ({ type, actions, getTable
return (
<Card className={`border-2 ${colors.border} ${colors.bg}`}>
<CardContent className="p-3">
<CardContent>
<div className="p-3">
<div className="mb-2 flex items-center gap-2">
<Zap className={`h-4 w-4 ${colors.icon}`} />
<span className={`text-sm font-semibold ${colors.text}`}>{type.toUpperCase()}</span>
</div>
<div className="flex flex-col gap-0.5">
<div className="flex items-center gap-2 text-xs">
<Database className="h-3 w-3 text-gray-500" />
<span className="truncate font-medium text-gray-900">{displayName}</span>
<Database className="h-3 w-3 text-muted-foreground" />
<span className="truncate font-medium text-foreground">{displayName}</span>
</div>
{isTableLabel && action.targetTable && (
<span className="ml-5 truncate text-xs text-gray-500">({action.targetTable})</span>
<span className="ml-5 truncate text-xs text-muted-foreground">({action.targetTable})</span>
)}
</div>
</div>
</CardContent>
</Card>
);