데이터 관계도 삭제, 복사 구현
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
@@ -12,6 +12,14 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/components/ui/dialog";
|
||||
import { MoreHorizontal, Trash2, Copy, Plus, Search, Network, Database, Calendar, User } from "lucide-react";
|
||||
import { DataFlowAPI, DataFlowDiagram } from "@/lib/api/dataflow";
|
||||
import { toast } from "sonner";
|
||||
@@ -30,49 +38,86 @@ export default function DataFlowList({ onDiagramSelect, selectedDiagram, onDesig
|
||||
const [totalPages, setTotalPages] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
// 모달 상태
|
||||
const [showCopyModal, setShowCopyModal] = useState(false);
|
||||
const [showDeleteModal, setShowDeleteModal] = useState(false);
|
||||
const [selectedDiagramForAction, setSelectedDiagramForAction] = useState<DataFlowDiagram | null>(null);
|
||||
|
||||
// 목록 로드 함수 분리
|
||||
const loadDiagrams = useCallback(async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await DataFlowAPI.getDataFlowDiagrams(currentPage, 20, searchTerm);
|
||||
setDiagrams(response.diagrams || []);
|
||||
setTotal(response.total || 0);
|
||||
setTotalPages(Math.max(1, Math.ceil((response.total || 0) / 20)));
|
||||
} catch (error) {
|
||||
console.error("관계도 목록 조회 실패", error);
|
||||
toast.error("관계도 목록을 불러오는데 실패했습니다.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [currentPage, searchTerm]);
|
||||
|
||||
// 관계도 목록 로드
|
||||
useEffect(() => {
|
||||
let abort = false;
|
||||
const load = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await DataFlowAPI.getDataFlowDiagrams(currentPage, 20, searchTerm);
|
||||
if (abort) return;
|
||||
|
||||
setDiagrams(response.diagrams || []);
|
||||
setTotal(response.total || 0);
|
||||
setTotalPages(Math.max(1, Math.ceil((response.total || 0) / 20)));
|
||||
} catch (error) {
|
||||
console.error("관계도 목록 조회 실패", error);
|
||||
setDiagrams([]);
|
||||
setTotalPages(1);
|
||||
setTotal(0);
|
||||
toast.error("관계도 목록을 불러오는데 실패했습니다.");
|
||||
} finally {
|
||||
if (!abort) setLoading(false);
|
||||
}
|
||||
};
|
||||
load();
|
||||
return () => {
|
||||
abort = true;
|
||||
};
|
||||
}, [currentPage, searchTerm]);
|
||||
loadDiagrams();
|
||||
}, [loadDiagrams]);
|
||||
|
||||
const handleDiagramSelect = (diagram: DataFlowDiagram) => {
|
||||
onDiagramSelect(diagram);
|
||||
};
|
||||
|
||||
const handleDelete = (diagram: DataFlowDiagram) => {
|
||||
if (confirm(`"${diagram.diagramName}" 관계도를 삭제하시겠습니까?`)) {
|
||||
// 삭제 API 호출
|
||||
console.log("삭제:", diagram);
|
||||
toast.info("삭제 기능은 아직 구현되지 않았습니다.");
|
||||
}
|
||||
setSelectedDiagramForAction(diagram);
|
||||
setShowDeleteModal(true);
|
||||
};
|
||||
|
||||
const handleCopy = (diagram: DataFlowDiagram) => {
|
||||
console.log("복사:", diagram);
|
||||
toast.info("복사 기능은 아직 구현되지 않았습니다.");
|
||||
setSelectedDiagramForAction(diagram);
|
||||
setShowCopyModal(true);
|
||||
};
|
||||
|
||||
// 복사 확인
|
||||
const handleConfirmCopy = async () => {
|
||||
if (!selectedDiagramForAction) return;
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
const newDiagramName = await DataFlowAPI.copyDiagram(selectedDiagramForAction.diagramName);
|
||||
toast.success(`관계도가 성공적으로 복사되었습니다: ${newDiagramName}`);
|
||||
|
||||
// 목록 새로고침
|
||||
await loadDiagrams();
|
||||
} catch (error) {
|
||||
console.error("관계도 복사 실패:", error);
|
||||
toast.error("관계도 복사에 실패했습니다.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setShowCopyModal(false);
|
||||
setSelectedDiagramForAction(null);
|
||||
}
|
||||
};
|
||||
|
||||
// 삭제 확인
|
||||
const handleConfirmDelete = async () => {
|
||||
if (!selectedDiagramForAction) return;
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
const deletedCount = await DataFlowAPI.deleteDiagram(selectedDiagramForAction.diagramName);
|
||||
toast.success(`관계도가 삭제되었습니다 (${deletedCount}개 관계 삭제)`);
|
||||
|
||||
// 목록 새로고침
|
||||
await loadDiagrams();
|
||||
} catch (error) {
|
||||
console.error("관계도 삭제 실패:", error);
|
||||
toast.error("관계도 삭제에 실패했습니다.");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setShowDeleteModal(false);
|
||||
setSelectedDiagramForAction(null);
|
||||
}
|
||||
};
|
||||
|
||||
// 연결 타입에 따른 배지 색상
|
||||
@@ -291,6 +336,52 @@ export default function DataFlowList({ onDiagramSelect, selectedDiagram, onDesig
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 복사 확인 모달 */}
|
||||
<Dialog open={showCopyModal} onOpenChange={setShowCopyModal}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>관계도 복사</DialogTitle>
|
||||
<DialogDescription>
|
||||
“{selectedDiagramForAction?.diagramName}” 관계도를 복사하시겠습니까?
|
||||
<br />
|
||||
새로운 관계도는 원본 이름 뒤에 (1), (2), (3)... 형태로 생성됩니다.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowCopyModal(false)}>
|
||||
취소
|
||||
</Button>
|
||||
<Button onClick={handleConfirmCopy} disabled={loading}>
|
||||
{loading ? "복사 중..." : "복사"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* 삭제 확인 모달 */}
|
||||
<Dialog open={showDeleteModal} onOpenChange={setShowDeleteModal}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-red-600">관계도 삭제</DialogTitle>
|
||||
<DialogDescription>
|
||||
“{selectedDiagramForAction?.diagramName}” 관계도를 완전히 삭제하시겠습니까?
|
||||
<br />
|
||||
<span className="font-medium text-red-600">
|
||||
이 작업은 되돌릴 수 없으며, 모든 관계 정보가 영구적으로 삭제됩니다.
|
||||
</span>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowDeleteModal(false)}>
|
||||
취소
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={handleConfirmDelete} disabled={loading}>
|
||||
{loading ? "삭제 중..." : "삭제"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user