feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 테이블 소스 노드 속성 편집
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import { useEffect, useState } from "react";
|
2025-10-24 14:11:12 +09:00
|
|
|
|
import { Check, ChevronsUpDown, Table, FileText } from "lucide-react";
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
import { Label } from "@/components/ui/label";
|
|
|
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
|
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
|
|
|
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
|
|
|
|
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
2025-10-24 14:11:12 +09:00
|
|
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
|
|
import { useFlowEditorStore } from "@/lib/stores/flowEditorStore";
|
|
|
|
|
|
import { tableTypeApi } from "@/lib/api/screen";
|
|
|
|
|
|
import type { TableSourceNodeData } from "@/types/node-editor";
|
|
|
|
|
|
|
|
|
|
|
|
interface TableSourcePropertiesProps {
|
|
|
|
|
|
nodeId: string;
|
|
|
|
|
|
data: TableSourceNodeData;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
interface TableOption {
|
|
|
|
|
|
tableName: string;
|
|
|
|
|
|
displayName: string;
|
|
|
|
|
|
description: string;
|
|
|
|
|
|
label: string; // 표시용 (라벨 또는 테이블명)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function TableSourceProperties({ nodeId, data }: TableSourcePropertiesProps) {
|
|
|
|
|
|
const { updateNode } = useFlowEditorStore();
|
|
|
|
|
|
|
|
|
|
|
|
const [displayName, setDisplayName] = useState(data.displayName || data.tableName);
|
|
|
|
|
|
const [tableName, setTableName] = useState(data.tableName);
|
2025-10-24 14:11:12 +09:00
|
|
|
|
|
|
|
|
|
|
// 🆕 데이터 소스 타입 (기본값: context-data)
|
|
|
|
|
|
const [dataSourceType, setDataSourceType] = useState<"context-data" | "table-all">(
|
|
|
|
|
|
(data as any).dataSourceType || "context-data"
|
|
|
|
|
|
);
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
|
|
|
|
|
|
// 테이블 선택 관련 상태
|
|
|
|
|
|
const [tables, setTables] = useState<TableOption[]>([]);
|
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 데이터 변경 시 로컬 상태 업데이트
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
setDisplayName(data.displayName || data.tableName);
|
|
|
|
|
|
setTableName(data.tableName);
|
2025-10-24 14:11:12 +09:00
|
|
|
|
setDataSourceType((data as any).dataSourceType || "context-data");
|
|
|
|
|
|
}, [data.displayName, data.tableName, (data as any).dataSourceType]);
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
|
|
|
|
|
|
// 테이블 목록 로딩
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
loadTables();
|
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 테이블 목록 로드
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadTables = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
console.log("🔍 테이블 목록 로딩 중...");
|
|
|
|
|
|
|
|
|
|
|
|
const tableList = await tableTypeApi.getTables();
|
|
|
|
|
|
|
|
|
|
|
|
// 테이블 목록 변환 (라벨 또는 displayName 우선 표시)
|
|
|
|
|
|
const options: TableOption[] = tableList.map((table) => {
|
|
|
|
|
|
// tableLabel이 있으면 우선 사용, 없으면 displayName, 그것도 없으면 tableName
|
|
|
|
|
|
const label = (table as any).tableLabel || table.displayName || table.tableName || "알 수 없는 테이블";
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
tableName: table.tableName,
|
|
|
|
|
|
displayName: table.displayName || table.tableName,
|
|
|
|
|
|
description: table.description || "",
|
|
|
|
|
|
label,
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
setTables(options);
|
|
|
|
|
|
console.log(`✅ 테이블 ${options.length}개 로딩 완료`);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("❌ 테이블 목록 로딩 실패:", error);
|
|
|
|
|
|
setTables([]);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 테이블 선택 핸들러 (즉시 노드 업데이트 + 컬럼 로드)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleTableSelect = async (selectedTableName: string) => {
|
|
|
|
|
|
const selectedTable = tables.find((t) => t.tableName === selectedTableName);
|
|
|
|
|
|
if (selectedTable) {
|
|
|
|
|
|
const newTableName = selectedTable.tableName;
|
|
|
|
|
|
const newDisplayName = selectedTable.label;
|
|
|
|
|
|
|
|
|
|
|
|
setTableName(newTableName);
|
|
|
|
|
|
setDisplayName(newDisplayName);
|
|
|
|
|
|
setOpen(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 컬럼 정보 로드
|
|
|
|
|
|
console.log(`🔍 테이블 "${newTableName}" 컬럼 로드 중...`);
|
|
|
|
|
|
try {
|
|
|
|
|
|
const columns = await tableTypeApi.getColumns(newTableName);
|
|
|
|
|
|
console.log("🔍 API에서 받은 컬럼 데이터:", columns);
|
|
|
|
|
|
|
|
|
|
|
|
const fields = columns.map((col: any) => ({
|
|
|
|
|
|
name: col.column_name || col.columnName,
|
|
|
|
|
|
type: col.data_type || col.dataType || "unknown",
|
|
|
|
|
|
nullable: col.is_nullable === "YES" || col.isNullable === true,
|
|
|
|
|
|
// displayName이 라벨입니다!
|
|
|
|
|
|
label: col.displayName || col.label_ko || col.columnLabel || col.column_label,
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`✅ ${fields.length}개 컬럼 로드 완료:`, fields);
|
|
|
|
|
|
|
|
|
|
|
|
// 필드 정보와 함께 노드 업데이트
|
|
|
|
|
|
updateNode(nodeId, {
|
|
|
|
|
|
displayName: newDisplayName,
|
|
|
|
|
|
tableName: newTableName,
|
|
|
|
|
|
fields,
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error("❌ 컬럼 로드 실패:", error);
|
|
|
|
|
|
|
|
|
|
|
|
// 실패해도 테이블 정보는 업데이트
|
|
|
|
|
|
updateNode(nodeId, {
|
|
|
|
|
|
displayName: newDisplayName,
|
|
|
|
|
|
tableName: newTableName,
|
|
|
|
|
|
fields: [],
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`✅ 테이블 선택: ${newTableName} (${newDisplayName})`);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 표시 이름 변경 핸들러
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleDisplayNameChange = (newDisplayName: string) => {
|
|
|
|
|
|
setDisplayName(newDisplayName);
|
|
|
|
|
|
updateNode(nodeId, {
|
|
|
|
|
|
displayName: newDisplayName,
|
|
|
|
|
|
tableName,
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-10-24 14:11:12 +09:00
|
|
|
|
/**
|
|
|
|
|
|
* 🆕 데이터 소스 타입 변경 핸들러
|
|
|
|
|
|
*/
|
|
|
|
|
|
const handleDataSourceTypeChange = (newType: "context-data" | "table-all") => {
|
|
|
|
|
|
setDataSourceType(newType);
|
|
|
|
|
|
updateNode(nodeId, {
|
|
|
|
|
|
dataSourceType: newType,
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log(`✅ 데이터 소스 타입 변경: ${newType}`);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
// 현재 선택된 테이블의 라벨 찾기
|
|
|
|
|
|
const selectedTableLabel = tables.find((t) => t.tableName === tableName)?.label || tableName;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2025-10-24 14:11:12 +09:00
|
|
|
|
<div className="space-y-4 p-4 pb-8">
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
{/* 기본 정보 */}
|
|
|
|
|
|
<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>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 테이블 선택 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>
|
|
|
|
|
|
|
2025-10-24 14:11:12 +09:00
|
|
|
|
{/* 🆕 데이터 소스 설정 */}
|
|
|
|
|
|
<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>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
{/* 필드 정보 */}
|
|
|
|
|
|
<div>
|
2025-10-24 14:11:12 +09:00
|
|
|
|
<h3 className="mb-3 text-sm font-semibold">
|
|
|
|
|
|
출력 필드 {data.fields && data.fields.length > 0 && `(${data.fields.length}개)`}
|
|
|
|
|
|
</h3>
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
{data.fields && data.fields.length > 0 ? (
|
2025-10-24 14:11:12 +09:00
|
|
|
|
<div className="max-h-[300px] space-y-1 overflow-y-auto rounded border bg-gray-50 p-2">
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
{data.fields.map((field) => (
|
2025-10-24 14:11:12 +09:00
|
|
|
|
<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>
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<div className="rounded border p-4 text-center text-xs text-gray-400">필드 정보가 없습니다</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-10-24 14:11:12 +09:00
|
|
|
|
</div>
|
feat: 노드 기반 데이터 플로우 시스템 구현
- 노드 에디터 UI 구현 (React Flow 기반)
- TableSource, DataTransform, INSERT, UPDATE, DELETE, UPSERT 노드
- 드래그앤드롭 노드 추가 및 연결
- 속성 패널을 통한 노드 설정
- 실시간 필드 라벨 표시 (column_labels 테이블 연동)
- 데이터 변환 노드 (DataTransform) 기능
- EXPLODE: 구분자로 1개 행 → 여러 행 확장
- UPPERCASE, LOWERCASE, TRIM, CONCAT, SPLIT, REPLACE 등 12가지 변환 타입
- In-place 변환 지원 (타겟 필드 생략 시 소스 필드 덮어쓰기)
- 변환된 필드가 하위 액션 노드에 자동 전달
- 노드 플로우 실행 엔진
- 위상 정렬을 통한 노드 실행 순서 결정
- 레벨별 병렬 실행 (Promise.allSettled)
- 부분 실패 허용 (한 노드 실패 시 연결된 하위 노드만 스킵)
- 트랜잭션 기반 안전한 데이터 처리
- UPSERT 액션 로직 구현
- DB 제약 조건 없이 SELECT → UPDATE or INSERT 방식
- 복합 충돌 키 지원 (예: sales_no + product_name)
- 파라미터 인덱스 정확한 매핑
- 데이터 소스 자동 감지
- 테이블 선택 데이터 (selectedRowsData) 자동 주입
- 폼 입력 데이터 (formData) 자동 주입
- TableSource 노드가 외부 데이터 우선 사용
- 버튼 컴포넌트 통합
- 기존 관계 실행 + 새 노드 플로우 실행 하이브리드 지원
- 노드 플로우 선택 UI 추가
- API 클라이언트 통합 (Axios)
- 개발 문서 작성
- 노드 기반 제어 시스템 개선 계획
- 노드 연결 규칙 설계
- 노드 실행 엔진 설계
- 노드 구조 개선안
- 버튼 통합 분석
2025-10-02 16:22:29 +09:00
|
|
|
|
);
|
|
|
|
|
|
}
|