282 lines
9.9 KiB
TypeScript
282 lines
9.9 KiB
TypeScript
"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>
|
|
);
|
|
};
|
|
|