[agent-pipeline] pipe-20260311122226-4dkx round-2
This commit is contained in:
parent
49f7bb9937
commit
b2d3c6c688
|
|
@ -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<string, any>;
|
||||
onChange: (config: Record<string, any>) => void;
|
||||
/** 현재 화면의 테이블명 */
|
||||
currentTableName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* V2List 설정 패널
|
||||
* TableListConfigPanel과 동일한 기능을 제공
|
||||
*/
|
||||
export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
||||
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<V2ListConfigPanelProps> = ({
|
|||
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<V2ListConfigPanelProps> = ({
|
|||
};
|
||||
}, [config, currentTableName]);
|
||||
|
||||
// TableListConfig 변경을 V2List config 형식으로 변환
|
||||
// ─── TableListConfig 변경 → V2List config 변환 (기존 로직 100% 유지) ───
|
||||
const handleConfigChange = (partialConfig: Partial<TableListConfig>) => {
|
||||
const newConfig: Record<string, any> = { ...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<V2ListConfigPanelProps> = ({
|
|||
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<V2ListConfigPanelProps> = ({
|
|||
}));
|
||||
}
|
||||
|
||||
// 페이지네이션 변환
|
||||
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 (
|
||||
<TableListConfigPanel
|
||||
config={tableListConfig}
|
||||
onChange={handleConfigChange}
|
||||
screenTableName={currentTableName}
|
||||
/>
|
||||
<div className="space-y-4">
|
||||
{/* ─── 1단계: 테이블 정보 ─── */}
|
||||
<div className="rounded-lg border bg-muted/30 p-4 space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<Table2 className="h-4 w-4 text-primary" />
|
||||
<span className="text-sm font-medium">데이터 소스</span>
|
||||
</div>
|
||||
|
||||
{tableName ? (
|
||||
<div className="rounded-md border bg-background p-3">
|
||||
<p className="text-xs text-muted-foreground">연결된 테이블</p>
|
||||
<p className="mt-0.5 text-sm font-medium">{tableName}</p>
|
||||
{columnCount > 0 && (
|
||||
<p className="mt-1 text-[11px] text-muted-foreground">
|
||||
{columnCount}개의 컬럼이 설정되어 있어요
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-md border-2 border-dashed p-4 text-center">
|
||||
<Table2 className="mx-auto mb-2 h-8 w-8 opacity-30 text-muted-foreground" />
|
||||
<p className="text-sm text-muted-foreground">
|
||||
아직 테이블이 연결되지 않았어요
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
아래 상세 설정에서 테이블을 선택해주세요
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ─── 2단계: 기본 옵션 (Switch + 설명) ─── */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<div>
|
||||
<p className="text-sm">읽기 전용</p>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
데이터 조회만 가능하고 수정할 수 없어요
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={config.isReadOnly !== false}
|
||||
onCheckedChange={(checked) => updateConfig("isReadOnly", checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<div>
|
||||
<p className="text-sm">페이지네이션</p>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
데이터를 페이지 단위로 나눠서 보여줘요
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={config.pagination !== false}
|
||||
onCheckedChange={(checked) => {
|
||||
updateConfig("pagination", checked);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{config.pagination !== false && (
|
||||
<div className="ml-4 border-l-2 border-primary/20 pl-3">
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<span className="text-xs text-muted-foreground">페이지당 행 수</span>
|
||||
<Select
|
||||
value={String(config.pageSize || 10)}
|
||||
onValueChange={(v) => updateConfig("pageSize", Number(v))}
|
||||
>
|
||||
<SelectTrigger className="h-8 w-[180px] text-sm">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="5">5개</SelectItem>
|
||||
<SelectItem value="10">10개</SelectItem>
|
||||
<SelectItem value="20">20개</SelectItem>
|
||||
<SelectItem value="50">50개</SelectItem>
|
||||
<SelectItem value="100">100개</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* ─── 3단계: 상세 설정 (컬럼, 필터, 테이블 선택 등) ─── */}
|
||||
<Collapsible open={detailOpen} onOpenChange={setDetailOpen}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full items-center justify-between rounded-lg border bg-muted/30 px-4 py-2.5 text-left transition-colors hover:bg-muted/50"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Settings className="h-4 w-4 text-muted-foreground" />
|
||||
<span className="text-sm font-medium">컬럼 및 상세 설정</span>
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={cn(
|
||||
"h-4 w-4 text-muted-foreground transition-transform duration-200",
|
||||
detailOpen && "rotate-180",
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<div className="rounded-b-lg border border-t-0 p-2">
|
||||
<p className="text-xs text-muted-foreground px-2 pb-2">
|
||||
테이블 선택, 컬럼 구성, 필터 조건 등을 설정할 수 있어요
|
||||
</p>
|
||||
<TableListConfigPanel
|
||||
config={tableListConfig}
|
||||
onChange={handleConfigChange}
|
||||
screenTableName={currentTableName}
|
||||
/>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue