From b2d3c6c68856ed21cb5a5be86203d8cdc138cc81 Mon Sep 17 00:00:00 2001 From: DDD1542 Date: Wed, 11 Mar 2026 21:29:28 +0900 Subject: [PATCH] [agent-pipeline] pipe-20260311122226-4dkx round-2 --- .../v2/config-panels/V2ListConfigPanel.tsx | 183 +++++++++++++++--- 1 file changed, 152 insertions(+), 31 deletions(-) diff --git a/frontend/components/v2/config-panels/V2ListConfigPanel.tsx b/frontend/components/v2/config-panels/V2ListConfigPanel.tsx index e60d0387..ec110ecc 100644 --- a/frontend/components/v2/config-panels/V2ListConfigPanel.tsx +++ b/frontend/components/v2/config-panels/V2ListConfigPanel.tsx @@ -2,33 +2,51 @@ /** * V2List 설정 패널 - * TableListConfigPanel을 래핑하여 동일한 설정 기능을 제공합니다. - * 카드 표시는 별도의 card-display 컴포넌트를 사용합니다. + * 토스식 단계별 UX: 테이블 정보 표시 -> 기본 옵션(Switch) -> 상세 설정(Collapsible) + * 컬럼/필터 등 복잡한 설정은 TableListConfigPanel에 위임하여 기능 누락 방지 */ -import React, { useMemo } from "react"; +import React, { useState, useMemo } from "react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Switch } from "@/components/ui/switch"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; +import { Table2, Settings, ChevronDown } from "lucide-react"; +import { cn } from "@/lib/utils"; import { TableListConfigPanel } from "@/lib/registry/components/table-list/TableListConfigPanel"; import { TableListConfig } from "@/lib/registry/components/table-list/types"; interface V2ListConfigPanelProps { config: Record; onChange: (config: Record) => void; - /** 현재 화면의 테이블명 */ currentTableName?: string; } -/** - * V2List 설정 패널 - * TableListConfigPanel과 동일한 기능을 제공 - */ export const V2ListConfigPanel: React.FC = ({ config, onChange, currentTableName, }) => { - // V2List config를 TableListConfig 형식으로 변환 + const [detailOpen, setDetailOpen] = useState(false); + + const updateConfig = (field: string, value: any) => { + onChange({ ...config, [field]: value }); + }; + + const tableName = config.tableName || config.dataSource?.table || currentTableName || ""; + const columnCount = (config.columns || []).length; + + // ─── V2List config → TableListConfig 변환 (기존 로직 100% 유지) ─── const tableListConfig: TableListConfig = useMemo(() => { - // 컬럼 형식 변환: V2List columns -> TableList columns const columns = (config.columns || []).map((col: any, index: number) => ({ columnName: col.key || col.columnName || col.field || "", displayName: col.title || col.header || col.displayName || col.key || col.columnName || col.field || "", @@ -50,8 +68,8 @@ export const V2ListConfigPanel: React.FC = ({ columns, useCustomTable: config.useCustomTable, customTableName: config.customTableName, - isReadOnly: config.isReadOnly !== false, // V2List는 기본적으로 읽기 전용 - displayMode: "table", // 테이블 모드 고정 (카드는 card-display 컴포넌트 사용) + isReadOnly: config.isReadOnly !== false, + displayMode: "table", pagination: config.pagination !== false ? { enabled: true, pageSize: config.pageSize || 10, @@ -84,28 +102,23 @@ export const V2ListConfigPanel: React.FC = ({ }; }, [config, currentTableName]); - // TableListConfig 변경을 V2List config 형식으로 변환 + // ─── TableListConfig 변경 → V2List config 변환 (기존 로직 100% 유지) ─── const handleConfigChange = (partialConfig: Partial) => { const newConfig: Record = { ...config }; - // 테이블 설정 변환 if (partialConfig.selectedTable !== undefined) { newConfig.tableName = partialConfig.selectedTable; - if (!newConfig.dataSource) { - newConfig.dataSource = {}; - } + if (!newConfig.dataSource) newConfig.dataSource = {}; newConfig.dataSource.table = partialConfig.selectedTable; } if (partialConfig.tableName !== undefined) { newConfig.tableName = partialConfig.tableName; - if (!newConfig.dataSource) { - newConfig.dataSource = {}; - } + if (!newConfig.dataSource) newConfig.dataSource = {}; newConfig.dataSource.table = partialConfig.tableName; } if (partialConfig.useCustomTable !== undefined) { newConfig.useCustomTable = partialConfig.useCustomTable; - } + } if (partialConfig.customTableName !== undefined) { newConfig.customTableName = partialConfig.customTableName; } @@ -113,7 +126,6 @@ export const V2ListConfigPanel: React.FC = ({ newConfig.isReadOnly = partialConfig.isReadOnly; } - // 컬럼 형식 변환: TableList columns -> V2List columns if (partialConfig.columns !== undefined) { newConfig.columns = partialConfig.columns.map((col: any) => ({ key: col.columnName, @@ -133,32 +145,141 @@ export const V2ListConfigPanel: React.FC = ({ })); } - // 페이지네이션 변환 if (partialConfig.pagination !== undefined) { newConfig.pagination = partialConfig.pagination?.enabled; newConfig.pageSize = partialConfig.pagination?.pageSize || 10; } - // 필터 변환 if (partialConfig.filter !== undefined) { newConfig.filter = partialConfig.filter; } - // 데이터 필터 변환 if (partialConfig.dataFilter !== undefined) { newConfig.dataFilter = partialConfig.dataFilter; } - console.log("⚙️ V2ListConfigPanel handleConfigChange:", { partialConfig, newConfig }); onChange(newConfig); }; return ( - +
+ {/* ─── 1단계: 테이블 정보 ─── */} +
+
+ + 데이터 소스 +
+ + {tableName ? ( +
+

연결된 테이블

+

{tableName}

+ {columnCount > 0 && ( +

+ {columnCount}개의 컬럼이 설정되어 있어요 +

+ )} +
+ ) : ( +
+ +

+ 아직 테이블이 연결되지 않았어요 +

+

+ 아래 상세 설정에서 테이블을 선택해주세요 +

+
+ )} +
+ + {/* ─── 2단계: 기본 옵션 (Switch + 설명) ─── */} +
+
+
+

읽기 전용

+

+ 데이터 조회만 가능하고 수정할 수 없어요 +

+
+ updateConfig("isReadOnly", checked)} + /> +
+ +
+
+

페이지네이션

+

+ 데이터를 페이지 단위로 나눠서 보여줘요 +

+
+ { + updateConfig("pagination", checked); + }} + /> +
+ + {config.pagination !== false && ( +
+
+ 페이지당 행 수 + +
+
+ )} +
+ + {/* ─── 3단계: 상세 설정 (컬럼, 필터, 테이블 선택 등) ─── */} + + + + + +
+

+ 테이블 선택, 컬럼 구성, 필터 조건 등을 설정할 수 있어요 +

+ +
+
+
+
); };