wu981526092's picture
🚀 Deploy AgentGraph: Complete agent monitoring and knowledge graph system
c2ea5ed
import React, { useState, useCallback } from "react";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import { Upload, FileText, X } from "lucide-react";
import { useSystemNotifications } from "@/hooks/useSystemNotifications";
import { useAgentGraph } from "@/context/AgentGraphContext";
import { api } from "@/lib/api";
interface UploadDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function UploadDialog({ open, onOpenChange }: UploadDialogProps) {
const [isDragging, setIsDragging] = useState(false);
const [uploadProgress, setUploadProgress] = useState(0);
const [isUploading, setIsUploading] = useState(false);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const { notifySuccess, notifyError } = useSystemNotifications();
const { actions } = useAgentGraph();
const handleDragOver = useCallback((e: React.DragEvent) => {
e.preventDefault();
setIsDragging(true);
}, []);
const handleDragLeave = useCallback((e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
}, []);
const handleDrop = useCallback((e: React.DragEvent) => {
e.preventDefault();
setIsDragging(false);
const files = Array.from(e.dataTransfer.files);
if (files.length > 0) {
setSelectedFile(files[0] || null);
}
}, []);
const handleFileSelect = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const files = e.target.files;
if (files && files.length > 0) {
setSelectedFile(files[0] || null);
}
},
[]
);
const handleUpload = async () => {
if (!selectedFile) return;
setIsUploading(true);
setUploadProgress(0);
try {
const trace = await api.traces.upload(selectedFile, (progress) => {
setUploadProgress(progress);
});
notifySuccess(
"Upload Successful",
`${selectedFile.name} has been uploaded successfully.`
);
// Refresh traces list
const traces = await api.traces.list();
actions.setTraces(traces);
// Select the uploaded trace
actions.setSelectedTrace(trace);
// Close dialog
onOpenChange(false);
setSelectedFile(null);
setUploadProgress(0);
} catch (error) {
notifyError(
"Upload Failed",
error instanceof Error ? error.message : "Failed to upload file"
);
} finally {
setIsUploading(false);
}
};
const handleClose = () => {
if (!isUploading) {
onOpenChange(false);
setSelectedFile(null);
setUploadProgress(0);
}
};
return (
<Dialog open={open} onOpenChange={handleClose}>
<DialogContent className="sm:max-w-md max-w-[90vw] w-full">
<DialogHeader>
<DialogTitle>Upload Trace File</DialogTitle>
<DialogDescription>
Upload a trace file to analyze with AgentGraph pipeline
</DialogDescription>
</DialogHeader>
<div className="space-y-4 overflow-hidden">
{!selectedFile ? (
<div
className={`border-2 border-dashed rounded-lg p-8 text-center transition-colors ${
isDragging
? "border-primary bg-primary/5"
: "border-muted-foreground/25 hover:border-primary/50"
}`}
onDragOver={handleDragOver}
onDragLeave={handleDragLeave}
onDrop={handleDrop}
>
<Upload className="h-12 w-12 mx-auto mb-4 text-muted-foreground" />
<h4 className="text-lg font-medium mb-2">
Drop your trace file here
</h4>
<p className="text-sm text-muted-foreground mb-4">
or click to browse files
</p>
<Button variant="outline" asChild>
<label>
<input
type="file"
className="hidden"
accept=".json,.txt,.log"
onChange={handleFileSelect}
/>
Browse Files
</label>
</Button>
</div>
) : (
<div className="space-y-4">
<div className="flex items-center gap-3 p-3 border rounded-lg min-w-0">
<FileText className="h-8 w-8 text-primary flex-shrink-0" />
<div className="flex-1 min-w-0">
<p className="font-medium truncate" title={selectedFile.name}>
{selectedFile.name}
</p>
<p className="text-sm text-muted-foreground">
{(selectedFile.size / 1024 / 1024).toFixed(2)} MB
</p>
</div>
{!isUploading && (
<Button
variant="ghost"
size="sm"
onClick={() => setSelectedFile(null)}
className="flex-shrink-0"
>
<X className="h-4 w-4" />
</Button>
)}
</div>
{isUploading && (
<div className="space-y-2">
<Progress value={uploadProgress} />
<p className="text-sm text-center text-muted-foreground">
Uploading... {Math.round(uploadProgress)}%
</p>
</div>
)}
<div className="flex gap-2">
<Button
variant="outline"
onClick={() => setSelectedFile(null)}
disabled={isUploading}
className="flex-1"
>
Cancel
</Button>
<Button
onClick={handleUpload}
disabled={isUploading}
className="flex-1"
>
{isUploading ? "Uploading..." : "Upload"}
</Button>
</div>
</div>
)}
</div>
</DialogContent>
</Dialog>
);
}