restapi 버튼 동작
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
Settings,
|
||||
GitBranch,
|
||||
Clock,
|
||||
Zap,
|
||||
Info
|
||||
} from "lucide-react";
|
||||
import { ComponentData, ButtonDataflowConfig } from "@/types/screen";
|
||||
import { apiClient } from "@/lib/api/client";
|
||||
|
||||
interface ImprovedButtonControlConfigPanelProps {
|
||||
component: ComponentData;
|
||||
onUpdateProperty: (path: string, value: any) => void;
|
||||
}
|
||||
|
||||
interface RelationshipOption {
|
||||
id: string;
|
||||
name: string;
|
||||
sourceTable: string;
|
||||
targetTable: string;
|
||||
category: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 🔥 단순화된 버튼 제어 설정 패널
|
||||
*
|
||||
* 관계 실행만 지원:
|
||||
* - 관계 선택 및 실행 타이밍 설정
|
||||
* - 관계 내부에 데이터 저장/외부호출 로직 포함
|
||||
*/
|
||||
export const ImprovedButtonControlConfigPanel: React.FC<ImprovedButtonControlConfigPanelProps> = ({
|
||||
component,
|
||||
onUpdateProperty,
|
||||
}) => {
|
||||
const config = component.webTypeConfig || {};
|
||||
const dataflowConfig = config.dataflowConfig || {};
|
||||
|
||||
// 🔥 State 관리
|
||||
const [relationships, setRelationships] = useState<RelationshipOption[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// 🔥 관계 목록 로딩
|
||||
useEffect(() => {
|
||||
if (config.enableDataflowControl) {
|
||||
loadRelationships();
|
||||
}
|
||||
}, [config.enableDataflowControl]);
|
||||
|
||||
/**
|
||||
* 🔥 전체 관계 목록 로드 (관계도별 구분 없이)
|
||||
*/
|
||||
const loadRelationships = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
console.log("🔍 전체 관계 목록 로딩...");
|
||||
|
||||
const response = await apiClient.get("/test-button-dataflow/relationships/all");
|
||||
|
||||
if (response.data.success && Array.isArray(response.data.data)) {
|
||||
const relationshipList = response.data.data.map((rel: any) => ({
|
||||
id: rel.id,
|
||||
name: rel.name || `${rel.sourceTable} → ${rel.targetTable}`,
|
||||
sourceTable: rel.sourceTable,
|
||||
targetTable: rel.targetTable,
|
||||
category: rel.category || "데이터 흐름",
|
||||
}));
|
||||
|
||||
setRelationships(relationshipList);
|
||||
console.log(`✅ 관계 ${relationshipList.length}개 로딩 완료`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ 관계 목록 로딩 실패:", error);
|
||||
setRelationships([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 🔥 관계 선택 핸들러
|
||||
*/
|
||||
const handleRelationshipSelect = (relationshipId: string) => {
|
||||
const selectedRelationship = relationships.find(r => r.id === relationshipId);
|
||||
if (selectedRelationship) {
|
||||
onUpdateProperty("webTypeConfig.dataflowConfig.relationshipConfig", {
|
||||
relationshipId: selectedRelationship.id,
|
||||
relationshipName: selectedRelationship.name,
|
||||
executionTiming: "after", // 기본값
|
||||
contextData: {},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 🔥 제어 타입 변경 핸들러
|
||||
*/
|
||||
const handleControlTypeChange = (controlType: string) => {
|
||||
// 기존 설정 초기화
|
||||
onUpdateProperty("webTypeConfig.dataflowConfig", {
|
||||
controlMode: controlType,
|
||||
relationshipConfig: controlType === "relationship" ? undefined : null,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* 🔥 제어관리 활성화 스위치 */}
|
||||
<div className="flex items-center justify-between rounded-lg border bg-blue-50 p-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Settings className="h-4 w-4 text-blue-600" />
|
||||
<div>
|
||||
<Label className="text-sm font-medium">🎮 고급 제어 기능</Label>
|
||||
<p className="mt-1 text-xs text-gray-600">버튼 클릭 시 추가 작업을 자동으로 실행합니다</p>
|
||||
</div>
|
||||
</div>
|
||||
<Switch
|
||||
checked={config.enableDataflowControl || false}
|
||||
onCheckedChange={(checked) => onUpdateProperty("webTypeConfig.enableDataflowControl", checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 🔥 제어관리가 활성화된 경우에만 설정 표시 */}
|
||||
{config.enableDataflowControl && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>버튼 제어 설정</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Tabs
|
||||
value={dataflowConfig.controlMode || "none"}
|
||||
onValueChange={handleControlTypeChange}
|
||||
>
|
||||
<TabsList className="grid w-full grid-cols-2">
|
||||
<TabsTrigger value="none">제어 없음</TabsTrigger>
|
||||
<TabsTrigger value="relationship">관계 실행</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="none" className="mt-4">
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
<Zap className="h-8 w-8 mx-auto mb-2 opacity-50" />
|
||||
<p>추가 제어 없이 기본 버튼 액션만 실행됩니다.</p>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="relationship" className="mt-4">
|
||||
<RelationshipSelector
|
||||
relationships={relationships}
|
||||
selectedRelationshipId={dataflowConfig.relationshipConfig?.relationshipId}
|
||||
onSelect={handleRelationshipSelect}
|
||||
loading={loading}
|
||||
/>
|
||||
|
||||
{dataflowConfig.relationshipConfig && (
|
||||
<div className="mt-4 space-y-4">
|
||||
<Separator />
|
||||
<ExecutionTimingSelector
|
||||
value={dataflowConfig.relationshipConfig.executionTiming}
|
||||
onChange={(timing) =>
|
||||
onUpdateProperty("webTypeConfig.dataflowConfig.relationshipConfig.executionTiming", timing)
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="rounded bg-blue-50 p-3">
|
||||
<div className="flex items-start space-x-2">
|
||||
<Info className="h-4 w-4 text-blue-600 mt-0.5" />
|
||||
<div className="text-xs text-blue-800">
|
||||
<p className="font-medium">관계 실행 정보:</p>
|
||||
<p className="mt-1">선택한 관계에 설정된 데이터 저장, 외부호출 등의 모든 액션이 자동으로 실행됩니다.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 🔥 관계 선택 컴포넌트
|
||||
*/
|
||||
const RelationshipSelector: React.FC<{
|
||||
relationships: RelationshipOption[];
|
||||
selectedRelationshipId?: string;
|
||||
onSelect: (relationshipId: string) => void;
|
||||
loading: boolean;
|
||||
}> = ({ relationships, selectedRelationshipId, onSelect, loading }) => {
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<GitBranch className="h-4 w-4 text-blue-600" />
|
||||
<Label>실행할 관계 선택</Label>
|
||||
</div>
|
||||
|
||||
<Select value={selectedRelationshipId || ""} onValueChange={onSelect}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="관계를 선택하세요" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{loading ? (
|
||||
<div className="p-4 text-center text-sm text-gray-500">관계 목록을 불러오는 중...</div>
|
||||
) : relationships.length === 0 ? (
|
||||
<div className="p-4 text-center text-sm text-gray-500">사용 가능한 관계가 없습니다</div>
|
||||
) : (
|
||||
relationships.map((rel) => (
|
||||
<SelectItem key={rel.id} value={rel.id}>
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">{rel.name}</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{rel.sourceTable} → {rel.targetTable}
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))
|
||||
)}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 🔥 실행 타이밍 선택 컴포넌트
|
||||
*/
|
||||
const ExecutionTimingSelector: React.FC<{
|
||||
value: string;
|
||||
onChange: (timing: "before" | "after" | "replace") => void;
|
||||
}> = ({ value, onChange }) => {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Clock className="h-4 w-4 text-orange-600" />
|
||||
<Label>실행 타이밍</Label>
|
||||
</div>
|
||||
|
||||
<Select value={value} onValueChange={onChange}>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="실행 타이밍을 선택하세요" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="before">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">Before (사전 실행)</span>
|
||||
<span className="text-xs text-muted-foreground">버튼 액션 실행 전에 제어를 실행합니다</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="after">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">After (사후 실행)</span>
|
||||
<span className="text-xs text-muted-foreground">버튼 액션 실행 후에 제어를 실행합니다</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="replace">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">Replace (대체 실행)</span>
|
||||
<span className="text-xs text-muted-foreground">버튼 액션 대신 제어만 실행합니다</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user