get요청 db 저장기능

This commit is contained in:
kjs
2025-09-29 13:32:59 +09:00
parent c9afdec09f
commit 0fca8cd90b
5 changed files with 287 additions and 76 deletions

View File

@@ -30,6 +30,7 @@ interface DataMappingSettingsProps {
httpMethod: string;
availableTables?: TableInfo[];
readonly?: boolean;
tablesLoading?: boolean;
}
export const DataMappingSettings: React.FC<DataMappingSettingsProps> = ({
@@ -38,6 +39,7 @@ export const DataMappingSettings: React.FC<DataMappingSettingsProps> = ({
httpMethod,
availableTables = [],
readonly = false,
tablesLoading = false,
}) => {
const [localConfig, setLocalConfig] = useState<DataMappingConfig>(config);
@@ -228,17 +230,27 @@ export const DataMappingSettings: React.FC<DataMappingSettingsProps> = ({
<Select
value={localConfig.inboundMapping?.targetTable || ""}
onValueChange={(value) => handleInboundMappingChange({ targetTable: value })}
disabled={readonly}
disabled={readonly || tablesLoading}
>
<SelectTrigger>
<SelectValue placeholder="저장할 테이블을 선택하세요" />
<SelectValue placeholder={tablesLoading ? "테이블 목록 로딩 중..." : "저장할 테이블을 선택하세요"} />
</SelectTrigger>
<SelectContent>
{availableTables.map((table) => (
<SelectItem key={table.name} value={table.name}>
{table.displayName || table.name}
{tablesLoading ? (
<SelectItem value="" disabled>
...
</SelectItem>
))}
) : availableTables.length === 0 ? (
<SelectItem value="" disabled>
</SelectItem>
) : (
availableTables.map((table) => (
<SelectItem key={table.name} value={table.name}>
{table.displayName || table.name}
</SelectItem>
))
)}
</SelectContent>
</Select>
</div>

View File

@@ -17,6 +17,10 @@ import {
} from "@/types/external-call/ExternalCallTypes";
import { DataMappingConfig, TableInfo } from "@/types/external-call/DataMappingTypes";
// API import
import { DataFlowAPI } from "@/lib/api/dataflow";
import { toast } from "sonner";
// 하위 컴포넌트 import
import RestApiSettings from "./RestApiSettings";
import ExternalCallTestPanel from "./ExternalCallTestPanel";
@@ -41,8 +45,14 @@ const ExternalCallPanel: React.FC<ExternalCallPanelProps> = ({
});
// 상태 관리
const [config, setConfig] = useState<ExternalCallConfig>(
() =>
initialSettings || {
() => {
if (initialSettings) {
console.log("🔄 [ExternalCallPanel] 기존 설정 로드:", initialSettings);
return initialSettings;
}
console.log("🔄 [ExternalCallPanel] 기본 설정 사용");
return {
callType: "rest-api",
restApiSettings: {
apiUrl: "",
@@ -63,7 +73,8 @@ const ExternalCallPanel: React.FC<ExternalCallPanelProps> = ({
timeout: 30000, // 30초
retryCount: 3,
},
},
};
},
);
const [activeTab, setActiveTab] = useState<string>("settings");
@@ -71,48 +82,69 @@ const ExternalCallPanel: React.FC<ExternalCallPanelProps> = ({
const [isConfigValid, setIsConfigValid] = useState<boolean>(false);
// 데이터 매핑 상태
const [dataMappingConfig, setDataMappingConfig] = useState<DataMappingConfig>(() => ({
direction: "none",
}));
const [dataMappingConfig, setDataMappingConfig] = useState<DataMappingConfig>(() => {
// initialSettings에서 데이터 매핑 정보 불러오기
if (initialSettings?.dataMappingConfig) {
console.log("🔄 [ExternalCallPanel] 기존 데이터 매핑 설정 로드:", initialSettings.dataMappingConfig);
return initialSettings.dataMappingConfig;
}
console.log("🔄 [ExternalCallPanel] 기본 데이터 매핑 설정 사용");
return {
direction: "none",
};
});
// 사용 가능한 테이블 목록 (임시 데이터)
const [availableTables] = useState<TableInfo[]>([
{
name: "customers",
displayName: "고객",
fields: [
{ name: "id", dataType: "number", nullable: false, isPrimaryKey: true },
{ name: "name", dataType: "string", nullable: false },
{ name: "email", dataType: "string", nullable: true },
{ name: "phone", dataType: "string", nullable: true },
{ name: "created_at", dataType: "date", nullable: false },
],
},
{
name: "orders",
displayName: "주문",
fields: [
{ name: "id", dataType: "number", nullable: false, isPrimaryKey: true },
{ name: "customer_id", dataType: "number", nullable: false },
{ name: "product_name", dataType: "string", nullable: false },
{ name: "quantity", dataType: "number", nullable: false },
{ name: "price", dataType: "number", nullable: false },
{ name: "status", dataType: "string", nullable: false },
{ name: "order_date", dataType: "date", nullable: false },
],
},
{
name: "products",
displayName: "제품",
fields: [
{ name: "id", dataType: "number", nullable: false, isPrimaryKey: true },
{ name: "name", dataType: "string", nullable: false },
{ name: "price", dataType: "number", nullable: false },
{ name: "stock", dataType: "number", nullable: false },
{ name: "category", dataType: "string", nullable: true },
],
},
]);
// 사용 가능한 테이블 목록 (실제 API에서 로드)
const [availableTables, setAvailableTables] = useState<TableInfo[]>([]);
const [tablesLoading, setTablesLoading] = useState(false);
// 테이블 목록 로드
useEffect(() => {
const loadTables = async () => {
try {
setTablesLoading(true);
const tables = await DataFlowAPI.getTables();
// 테이블 정보를 TableInfo 형식으로 변환
const tableInfos: TableInfo[] = await Promise.all(
tables.map(async (table) => {
try {
const columns = await DataFlowAPI.getTableColumns(table.tableName);
return {
name: table.tableName,
displayName: table.displayName || table.tableName,
fields: columns.map((col) => ({
name: col.columnName,
dataType: col.dataType,
nullable: col.nullable,
isPrimaryKey: col.isPrimaryKey || false,
})),
};
} catch (error) {
console.warn(`테이블 ${table.tableName} 컬럼 정보 로드 실패:`, error);
return {
name: table.tableName,
displayName: table.displayName || table.tableName,
fields: [],
};
}
})
);
setAvailableTables(tableInfos);
} catch (error) {
console.error("테이블 목록 로드 실패:", error);
toast.error("테이블 목록을 불러오는데 실패했습니다.");
// 실패 시 빈 배열로 설정
setAvailableTables([]);
} finally {
setTablesLoading(false);
}
};
loadTables();
}, []);
// 설정 변경 핸들러
const handleRestApiSettingsChange = useCallback(
@@ -136,6 +168,22 @@ const ExternalCallPanel: React.FC<ExternalCallPanelProps> = ({
[config, onSettingsChange, dataMappingConfig],
);
// 데이터 매핑 설정 변경 핸들러
const handleDataMappingConfigChange = useCallback(
(newMappingConfig: DataMappingConfig) => {
console.log("🔄 [ExternalCallPanel] 데이터 매핑 설정 변경:", newMappingConfig);
setDataMappingConfig(newMappingConfig);
// 전체 설정에 데이터 매핑 정보 포함하여 상위로 전달
onSettingsChange({
...config,
dataMappingConfig: newMappingConfig,
});
},
[config, onSettingsChange],
);
// 테스트 결과 핸들러
const handleTestResult = useCallback((result: ApiTestResult) => {
setLastTestResult(result);
@@ -225,10 +273,11 @@ const ExternalCallPanel: React.FC<ExternalCallPanelProps> = ({
<TabsContent value="mapping" className="flex-1 space-y-2 overflow-y-auto">
<DataMappingSettings
config={dataMappingConfig}
onConfigChange={setDataMappingConfig}
onConfigChange={handleDataMappingConfigChange}
httpMethod={config.restApiSettings?.httpMethod || "GET"}
availableTables={availableTables}
readonly={readonly}
tablesLoading={tablesLoading}
/>
</TabsContent>