api요청정보 수정
This commit is contained in:
@@ -12,6 +12,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useFlowEditorStore } from "@/lib/stores/flowEditorStore";
|
||||
import { tableTypeApi } from "@/lib/api/screen";
|
||||
@@ -34,10 +35,10 @@ export function TableSourceProperties({ nodeId, data }: TableSourcePropertiesPro
|
||||
|
||||
const [displayName, setDisplayName] = useState(data.displayName || data.tableName);
|
||||
const [tableName, setTableName] = useState(data.tableName);
|
||||
|
||||
|
||||
// 🆕 데이터 소스 타입 (기본값: context-data)
|
||||
const [dataSourceType, setDataSourceType] = useState<"context-data" | "table-all">(
|
||||
(data as any).dataSourceType || "context-data"
|
||||
(data as any).dataSourceType || "context-data",
|
||||
);
|
||||
|
||||
// 테이블 선택 관련 상태
|
||||
@@ -167,171 +168,168 @@ export function TableSourceProperties({ nodeId, data }: TableSourcePropertiesPro
|
||||
|
||||
return (
|
||||
<div className="space-y-4 p-4 pb-8">
|
||||
{/* 기본 정보 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">기본 정보</h3>
|
||||
{/* 기본 정보 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">기본 정보</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<Label htmlFor="displayName" className="text-xs">
|
||||
표시 이름
|
||||
</Label>
|
||||
<Input
|
||||
id="displayName"
|
||||
value={displayName}
|
||||
onChange={(e) => handleDisplayNameChange(e.target.value)}
|
||||
className="mt-1"
|
||||
placeholder="노드 표시 이름"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<Label htmlFor="displayName" className="text-xs">
|
||||
표시 이름
|
||||
</Label>
|
||||
<Input
|
||||
id="displayName"
|
||||
value={displayName}
|
||||
onChange={(e) => handleDisplayNameChange(e.target.value)}
|
||||
className="mt-1"
|
||||
placeholder="노드 표시 이름"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 테이블 선택 Combobox */}
|
||||
<div>
|
||||
<Label className="text-xs">테이블 선택</Label>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="mt-1 w-full justify-between"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<span className="text-muted-foreground">로딩 중...</span>
|
||||
) : tableName ? (
|
||||
<span className="truncate">{selectedTableLabel}</span>
|
||||
) : (
|
||||
<span className="text-muted-foreground">테이블을 선택하세요</span>
|
||||
)}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[320px] p-0" align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder="테이블 검색..." className="h-9" />
|
||||
<CommandList>
|
||||
<CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<ScrollArea className="h-[300px]">
|
||||
{tables.map((table) => (
|
||||
<CommandItem
|
||||
key={table.tableName}
|
||||
value={`${table.label} ${table.tableName} ${table.description}`}
|
||||
onSelect={() => handleTableSelect(table.tableName)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
tableName === table.tableName ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{table.label}</span>
|
||||
{table.label !== table.tableName && (
|
||||
<span className="text-muted-foreground text-xs">{table.tableName}</span>
|
||||
)}
|
||||
{table.description && (
|
||||
<span className="text-muted-foreground text-xs">{table.description}</span>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{tableName && selectedTableLabel !== tableName && (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
실제 테이블명: <code className="rounded bg-gray-100 px-1 py-0.5">{tableName}</code>
|
||||
</p>
|
||||
{/* 테이블 선택 Combobox */}
|
||||
<div>
|
||||
<Label className="text-xs">테이블 선택</Label>
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="mt-1 w-full justify-between"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<span className="text-muted-foreground">로딩 중...</span>
|
||||
) : tableName ? (
|
||||
<span className="truncate">{selectedTableLabel}</span>
|
||||
) : (
|
||||
<span className="text-muted-foreground">테이블을 선택하세요</span>
|
||||
)}
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[320px] p-0" align="start">
|
||||
<Command>
|
||||
<CommandInput placeholder="테이블 검색..." className="h-9" />
|
||||
<CommandList>
|
||||
<CommandEmpty>검색 결과가 없습니다.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
<ScrollArea className="h-[300px]">
|
||||
{tables.map((table) => (
|
||||
<CommandItem
|
||||
key={table.tableName}
|
||||
value={`${table.label} ${table.tableName} ${table.description}`}
|
||||
onSelect={() => handleTableSelect(table.tableName)}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-4 w-4",
|
||||
tableName === table.tableName ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{table.label}</span>
|
||||
{table.label !== table.tableName && (
|
||||
<span className="text-muted-foreground text-xs">{table.tableName}</span>
|
||||
)}
|
||||
{table.description && (
|
||||
<span className="text-muted-foreground text-xs">{table.description}</span>
|
||||
)}
|
||||
</div>
|
||||
</CommandItem>
|
||||
))}
|
||||
</ScrollArea>
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
{tableName && selectedTableLabel !== tableName && (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
실제 테이블명: <code className="rounded bg-gray-100 px-1 py-0.5">{tableName}</code>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 🆕 데이터 소스 설정 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">데이터 소스 설정</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<Label className="text-xs">데이터 소스 타입</Label>
|
||||
<Select value={dataSourceType} onValueChange={handleDataSourceTypeChange}>
|
||||
<SelectTrigger className="mt-1">
|
||||
<SelectValue placeholder="데이터 소스 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="context-data">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileText className="h-4 w-4" />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">컨텍스트 데이터</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
버튼에서 전달된 데이터 사용 (폼, 선택 항목 등)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="table-all">
|
||||
<div className="flex items-center gap-2">
|
||||
<Table className="h-4 w-4" />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">테이블 전체 데이터</span>
|
||||
<span className="text-muted-foreground text-xs">선택한 테이블의 모든 행 조회 (페이징 무관)</span>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* 설명 텍스트 */}
|
||||
<div className="mt-2 rounded bg-blue-50 p-3 text-xs text-blue-700">
|
||||
{dataSourceType === "context-data" ? (
|
||||
<>
|
||||
<p className="mb-1 font-medium">💡 컨텍스트 데이터 모드</p>
|
||||
<p>버튼 실행 시 전달된 데이터(폼 데이터, 테이블 선택 항목 등)를 사용합니다.</p>
|
||||
<p className="mt-1 text-blue-600">• 폼 데이터: 1개 레코드</p>
|
||||
<p className="text-blue-600">• 테이블 선택: N개 레코드</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className="mb-1 font-medium">📊 테이블 전체 데이터 모드</p>
|
||||
<p>선택한 테이블의 **모든 행**을 직접 조회합니다.</p>
|
||||
<p className="mt-1 font-medium text-orange-600">⚠️ 대량 데이터 시 성능 주의</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 🆕 데이터 소스 설정 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">데이터 소스 설정</h3>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<Label className="text-xs">데이터 소스 타입</Label>
|
||||
<Select value={dataSourceType} onValueChange={handleDataSourceTypeChange}>
|
||||
<SelectTrigger className="mt-1">
|
||||
<SelectValue placeholder="데이터 소스 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="context-data">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileText className="h-4 w-4" />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">컨텍스트 데이터</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
버튼에서 전달된 데이터 사용 (폼, 선택 항목 등)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="table-all">
|
||||
<div className="flex items-center gap-2">
|
||||
<Table className="h-4 w-4" />
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">테이블 전체 데이터</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
선택한 테이블의 모든 행 조회 (페이징 무관)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
{/* 설명 텍스트 */}
|
||||
<div className="mt-2 rounded bg-blue-50 p-3 text-xs text-blue-700">
|
||||
{dataSourceType === "context-data" ? (
|
||||
<>
|
||||
<p className="font-medium mb-1">💡 컨텍스트 데이터 모드</p>
|
||||
<p>버튼 실행 시 전달된 데이터(폼 데이터, 테이블 선택 항목 등)를 사용합니다.</p>
|
||||
<p className="mt-1 text-blue-600">• 폼 데이터: 1개 레코드</p>
|
||||
<p className="text-blue-600">• 테이블 선택: N개 레코드</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className="font-medium mb-1">📊 테이블 전체 데이터 모드</p>
|
||||
<p>선택한 테이블의 **모든 행**을 직접 조회합니다.</p>
|
||||
<p className="mt-1 text-orange-600 font-medium">⚠️ 대량 데이터 시 성능 주의</p>
|
||||
</>
|
||||
)}
|
||||
{/* 필드 정보 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">
|
||||
출력 필드 {data.fields && data.fields.length > 0 && `(${data.fields.length}개)`}
|
||||
</h3>
|
||||
{data.fields && data.fields.length > 0 ? (
|
||||
<div className="max-h-[300px] space-y-1 overflow-y-auto rounded border bg-gray-50 p-2">
|
||||
{data.fields.map((field) => (
|
||||
<div key={field.name} className="flex items-center justify-between rounded bg-white px-2 py-1.5 text-xs">
|
||||
<span className="truncate font-mono text-gray-700" title={field.name}>
|
||||
{field.name}
|
||||
</span>
|
||||
<span className="ml-2 shrink-0 text-gray-400">{field.type}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 필드 정보 */}
|
||||
<div>
|
||||
<h3 className="mb-3 text-sm font-semibold">
|
||||
출력 필드 {data.fields && data.fields.length > 0 && `(${data.fields.length}개)`}
|
||||
</h3>
|
||||
{data.fields && data.fields.length > 0 ? (
|
||||
<div className="max-h-[300px] space-y-1 overflow-y-auto rounded border bg-gray-50 p-2">
|
||||
{data.fields.map((field) => (
|
||||
<div key={field.name} className="flex items-center justify-between rounded bg-white px-2 py-1.5 text-xs">
|
||||
<span className="truncate font-mono text-gray-700" title={field.name}>
|
||||
{field.name}
|
||||
</span>
|
||||
<span className="ml-2 shrink-0 text-gray-400">{field.type}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded border p-4 text-center text-xs text-gray-400">필드 정보가 없습니다</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
) : (
|
||||
<div className="rounded border p-4 text-center text-xs text-gray-400">필드 정보가 없습니다</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user