[agent-pipeline] pipe-20260315091327-kxyf round-4
This commit is contained in:
parent
2cb736dac1
commit
beb95bf2aa
|
|
@ -22,6 +22,7 @@ import {
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import CreateScreenModal from "@/components/screen/CreateScreenModal";
|
import CreateScreenModal from "@/components/screen/CreateScreenModal";
|
||||||
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from "@/components/ui/sheet";
|
||||||
|
|
||||||
// 단계별 진행을 위한 타입 정의
|
// 단계별 진행을 위한 타입 정의
|
||||||
type Step = "list" | "design" | "template" | "v2-test";
|
type Step = "list" | "design" | "template" | "v2-test";
|
||||||
|
|
@ -39,6 +40,7 @@ export default function ScreenManagementPage() {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const [isCreateOpen, setIsCreateOpen] = useState(false);
|
const [isCreateOpen, setIsCreateOpen] = useState(false);
|
||||||
|
const [isDetailOpen, setIsDetailOpen] = useState(false);
|
||||||
|
|
||||||
const tableCount = useMemo(() => new Set(screens.map((s) => s.tableName).filter(Boolean)).size, [screens]);
|
const tableCount = useMemo(() => new Set(screens.map((s) => s.tableName).filter(Boolean)).size, [screens]);
|
||||||
|
|
||||||
|
|
@ -110,6 +112,7 @@ export default function ScreenManagementPage() {
|
||||||
// 화면 선택 핸들러 (개별 화면 선택 시 그룹 선택 해제)
|
// 화면 선택 핸들러 (개별 화면 선택 시 그룹 선택 해제)
|
||||||
const handleScreenSelect = (screen: ScreenDefinition) => {
|
const handleScreenSelect = (screen: ScreenDefinition) => {
|
||||||
setSelectedScreen(screen);
|
setSelectedScreen(screen);
|
||||||
|
setIsDetailOpen(true);
|
||||||
setSelectedGroup(null); // 그룹 선택 해제
|
setSelectedGroup(null); // 그룹 선택 해제
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -257,24 +260,6 @@ export default function ScreenManagementPage() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* 선택 미리보기 */}
|
|
||||||
{selectedScreen && (
|
|
||||||
<div className="flex-shrink-0 border-t border-border/50 p-3 bg-muted/5">
|
|
||||||
<div className="flex items-center gap-2 mb-2">
|
|
||||||
<Monitor className="h-4 w-4 text-primary" />
|
|
||||||
<span className="text-sm font-medium truncate">{selectedScreen.screenName}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-3 text-xs text-muted-foreground">
|
|
||||||
<span className="font-mono">{selectedScreen.screenCode}</span>
|
|
||||||
<span>{selectedScreen.tableName || "테이블 없음"}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 mt-2">
|
|
||||||
<Button size="sm" variant="outline" className="h-7 text-xs flex-1" onClick={() => handleDesignScreen(selectedScreen)}>
|
|
||||||
편집
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 오른쪽: 관계 시각화 (React Flow) */}
|
{/* 오른쪽: 관계 시각화 (React Flow) */}
|
||||||
|
|
@ -320,6 +305,38 @@ export default function ScreenManagementPage() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* 화면 디테일 Sheet */}
|
||||||
|
<Sheet open={isDetailOpen} onOpenChange={setIsDetailOpen}>
|
||||||
|
<SheetContent className="w-[420px] sm:max-w-[420px]">
|
||||||
|
<SheetHeader>
|
||||||
|
<SheetTitle className="text-base">{selectedScreen?.screenName || "화면 상세"}</SheetTitle>
|
||||||
|
<SheetDescription className="text-xs font-mono">{selectedScreen?.screenCode}</SheetDescription>
|
||||||
|
</SheetHeader>
|
||||||
|
{selectedScreen && (
|
||||||
|
<div className="mt-6 space-y-4">
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-xs text-muted-foreground">테이블</span>
|
||||||
|
<span className="text-xs font-mono">{selectedScreen.tableName || "없음"}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-xs text-muted-foreground">화면 ID</span>
|
||||||
|
<span className="text-xs font-mono">{selectedScreen.screenId}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 pt-4 border-t border-border/50">
|
||||||
|
<Button className="flex-1" onClick={() => { handleDesignScreen(selectedScreen); setIsDetailOpen(false); }}>
|
||||||
|
편집하기
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline" onClick={() => setIsDetailOpen(false)}>
|
||||||
|
닫기
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</SheetContent>
|
||||||
|
</Sheet>
|
||||||
|
|
||||||
{/* 화면 생성 모달 */}
|
{/* 화면 생성 모달 */}
|
||||||
<CreateScreenModal
|
<CreateScreenModal
|
||||||
open={isCreateOpen}
|
open={isCreateOpen}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import React, { useState, useEffect, useCallback } from "react";
|
||||||
import {
|
import {
|
||||||
ReactFlow,
|
ReactFlow,
|
||||||
Controls,
|
Controls,
|
||||||
|
MiniMap,
|
||||||
Background,
|
Background,
|
||||||
BackgroundVariant,
|
BackgroundVariant,
|
||||||
Node,
|
Node,
|
||||||
|
|
@ -2393,8 +2394,26 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId
|
||||||
</filter>
|
</filter>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
<Background variant={BackgroundVariant.Dots} gap={20} size={1} color="hsl(var(--border))" />
|
<Background id="bg-dots" variant={BackgroundVariant.Dots} gap={16} size={0.5} color="hsl(var(--border) / 0.3)" />
|
||||||
<Controls position="bottom-right" />
|
<Background id="bg-lines" variant={BackgroundVariant.Lines} gap={120} color="hsl(var(--border) / 0.08)" />
|
||||||
|
<Controls position="top-right" />
|
||||||
|
<MiniMap
|
||||||
|
position="bottom-right"
|
||||||
|
nodeColor={(node) => {
|
||||||
|
if (node.type === "screenNode") return "hsl(var(--primary))";
|
||||||
|
if (node.type === "tableNode") return "hsl(var(--warning))";
|
||||||
|
return "hsl(var(--muted-foreground))";
|
||||||
|
}}
|
||||||
|
nodeStrokeWidth={2}
|
||||||
|
zoomable
|
||||||
|
pannable
|
||||||
|
style={{
|
||||||
|
background: "hsl(var(--card) / 0.8)",
|
||||||
|
border: "1px solid hsl(var(--border) / 0.5)",
|
||||||
|
borderRadius: "8px",
|
||||||
|
marginBottom: "8px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/* 관계 범례 */}
|
{/* 관계 범례 */}
|
||||||
<div className="absolute bottom-4 left-4 z-10 rounded-lg border bg-card/90 backdrop-blur-sm p-3 shadow-md">
|
<div className="absolute bottom-4 left-4 z-10 rounded-lg border bg-card/90 backdrop-blur-sm p-3 shadow-md">
|
||||||
<p className="text-[10px] font-medium text-muted-foreground mb-2">관계 유형</p>
|
<p className="text-[10px] font-medium text-muted-foreground mb-2">관계 유형</p>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue