[agent-pipeline] pipe-20260311122226-4dkx round-2
This commit is contained in:
parent
49f7bb9937
commit
b2d3c6c688
|
|
@ -2,33 +2,51 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V2List 설정 패널
|
* V2List 설정 패널
|
||||||
* TableListConfigPanel을 래핑하여 동일한 설정 기능을 제공합니다.
|
* 토스식 단계별 UX: 테이블 정보 표시 -> 기본 옵션(Switch) -> 상세 설정(Collapsible)
|
||||||
* 카드 표시는 별도의 card-display 컴포넌트를 사용합니다.
|
* 컬럼/필터 등 복잡한 설정은 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 { TableListConfigPanel } from "@/lib/registry/components/table-list/TableListConfigPanel";
|
||||||
import { TableListConfig } from "@/lib/registry/components/table-list/types";
|
import { TableListConfig } from "@/lib/registry/components/table-list/types";
|
||||||
|
|
||||||
interface V2ListConfigPanelProps {
|
interface V2ListConfigPanelProps {
|
||||||
config: Record<string, any>;
|
config: Record<string, any>;
|
||||||
onChange: (config: Record<string, any>) => void;
|
onChange: (config: Record<string, any>) => void;
|
||||||
/** 현재 화면의 테이블명 */
|
|
||||||
currentTableName?: string;
|
currentTableName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* V2List 설정 패널
|
|
||||||
* TableListConfigPanel과 동일한 기능을 제공
|
|
||||||
*/
|
|
||||||
export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
||||||
config,
|
config,
|
||||||
onChange,
|
onChange,
|
||||||
currentTableName,
|
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(() => {
|
const tableListConfig: TableListConfig = useMemo(() => {
|
||||||
// 컬럼 형식 변환: V2List columns -> TableList columns
|
|
||||||
const columns = (config.columns || []).map((col: any, index: number) => ({
|
const columns = (config.columns || []).map((col: any, index: number) => ({
|
||||||
columnName: col.key || col.columnName || col.field || "",
|
columnName: col.key || col.columnName || col.field || "",
|
||||||
displayName: col.title || col.header || col.displayName || 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,
|
columns,
|
||||||
useCustomTable: config.useCustomTable,
|
useCustomTable: config.useCustomTable,
|
||||||
customTableName: config.customTableName,
|
customTableName: config.customTableName,
|
||||||
isReadOnly: config.isReadOnly !== false, // V2List는 기본적으로 읽기 전용
|
isReadOnly: config.isReadOnly !== false,
|
||||||
displayMode: "table", // 테이블 모드 고정 (카드는 card-display 컴포넌트 사용)
|
displayMode: "table",
|
||||||
pagination: config.pagination !== false ? {
|
pagination: config.pagination !== false ? {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
pageSize: config.pageSize || 10,
|
pageSize: config.pageSize || 10,
|
||||||
|
|
@ -84,28 +102,23 @@ export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
||||||
};
|
};
|
||||||
}, [config, currentTableName]);
|
}, [config, currentTableName]);
|
||||||
|
|
||||||
// TableListConfig 변경을 V2List config 형식으로 변환
|
// ─── TableListConfig 변경 → V2List config 변환 (기존 로직 100% 유지) ───
|
||||||
const handleConfigChange = (partialConfig: Partial<TableListConfig>) => {
|
const handleConfigChange = (partialConfig: Partial<TableListConfig>) => {
|
||||||
const newConfig: Record<string, any> = { ...config };
|
const newConfig: Record<string, any> = { ...config };
|
||||||
|
|
||||||
// 테이블 설정 변환
|
|
||||||
if (partialConfig.selectedTable !== undefined) {
|
if (partialConfig.selectedTable !== undefined) {
|
||||||
newConfig.tableName = partialConfig.selectedTable;
|
newConfig.tableName = partialConfig.selectedTable;
|
||||||
if (!newConfig.dataSource) {
|
if (!newConfig.dataSource) newConfig.dataSource = {};
|
||||||
newConfig.dataSource = {};
|
|
||||||
}
|
|
||||||
newConfig.dataSource.table = partialConfig.selectedTable;
|
newConfig.dataSource.table = partialConfig.selectedTable;
|
||||||
}
|
}
|
||||||
if (partialConfig.tableName !== undefined) {
|
if (partialConfig.tableName !== undefined) {
|
||||||
newConfig.tableName = partialConfig.tableName;
|
newConfig.tableName = partialConfig.tableName;
|
||||||
if (!newConfig.dataSource) {
|
if (!newConfig.dataSource) newConfig.dataSource = {};
|
||||||
newConfig.dataSource = {};
|
|
||||||
}
|
|
||||||
newConfig.dataSource.table = partialConfig.tableName;
|
newConfig.dataSource.table = partialConfig.tableName;
|
||||||
}
|
}
|
||||||
if (partialConfig.useCustomTable !== undefined) {
|
if (partialConfig.useCustomTable !== undefined) {
|
||||||
newConfig.useCustomTable = partialConfig.useCustomTable;
|
newConfig.useCustomTable = partialConfig.useCustomTable;
|
||||||
}
|
}
|
||||||
if (partialConfig.customTableName !== undefined) {
|
if (partialConfig.customTableName !== undefined) {
|
||||||
newConfig.customTableName = partialConfig.customTableName;
|
newConfig.customTableName = partialConfig.customTableName;
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +126,6 @@ export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
||||||
newConfig.isReadOnly = partialConfig.isReadOnly;
|
newConfig.isReadOnly = partialConfig.isReadOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 컬럼 형식 변환: TableList columns -> V2List columns
|
|
||||||
if (partialConfig.columns !== undefined) {
|
if (partialConfig.columns !== undefined) {
|
||||||
newConfig.columns = partialConfig.columns.map((col: any) => ({
|
newConfig.columns = partialConfig.columns.map((col: any) => ({
|
||||||
key: col.columnName,
|
key: col.columnName,
|
||||||
|
|
@ -133,32 +145,141 @@ export const V2ListConfigPanel: React.FC<V2ListConfigPanelProps> = ({
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 페이지네이션 변환
|
|
||||||
if (partialConfig.pagination !== undefined) {
|
if (partialConfig.pagination !== undefined) {
|
||||||
newConfig.pagination = partialConfig.pagination?.enabled;
|
newConfig.pagination = partialConfig.pagination?.enabled;
|
||||||
newConfig.pageSize = partialConfig.pagination?.pageSize || 10;
|
newConfig.pageSize = partialConfig.pagination?.pageSize || 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 필터 변환
|
|
||||||
if (partialConfig.filter !== undefined) {
|
if (partialConfig.filter !== undefined) {
|
||||||
newConfig.filter = partialConfig.filter;
|
newConfig.filter = partialConfig.filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 데이터 필터 변환
|
|
||||||
if (partialConfig.dataFilter !== undefined) {
|
if (partialConfig.dataFilter !== undefined) {
|
||||||
newConfig.dataFilter = partialConfig.dataFilter;
|
newConfig.dataFilter = partialConfig.dataFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("⚙️ V2ListConfigPanel handleConfigChange:", { partialConfig, newConfig });
|
|
||||||
onChange(newConfig);
|
onChange(newConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableListConfigPanel
|
<div className="space-y-4">
|
||||||
config={tableListConfig}
|
{/* ─── 1단계: 테이블 정보 ─── */}
|
||||||
onChange={handleConfigChange}
|
<div className="rounded-lg border bg-muted/30 p-4 space-y-3">
|
||||||
screenTableName={currentTableName}
|
<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