From 5ce7f7b312f508673ce83787409c4980e31aaa19 Mon Sep 17 00:00:00 2001 From: phact Date: Mon, 21 Jul 2025 12:44:36 -0400 Subject: [PATCH] drag and drop in ui --- frontend/src/app/chat/page.tsx | 142 +++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/chat/page.tsx b/frontend/src/app/chat/page.tsx index bb1124c0..f646fe0c 100644 --- a/frontend/src/app/chat/page.tsx +++ b/frontend/src/app/chat/page.tsx @@ -4,7 +4,7 @@ import { useState, useRef, useEffect } from "react" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Input } from "@/components/ui/input" -import { MessageCircle, Send, Loader2, User, Bot, Zap, Settings, ChevronDown, ChevronRight } from "lucide-react" +import { MessageCircle, Send, Loader2, User, Bot, Zap, Settings, ChevronDown, ChevronRight, Upload, FileText } from "lucide-react" interface Message { role: "user" | "assistant" @@ -40,6 +40,9 @@ export default function ChatPage() { chat: string | null langflow: string | null }>({ chat: null, langflow: null }) + const [isUploading, setIsUploading] = useState(false) + const [isDragOver, setIsDragOver] = useState(false) + const dragCounterRef = useRef(0) const messagesEndRef = useRef(null) const scrollToBottom = () => { @@ -53,6 +56,98 @@ export default function ChatPage() { setPreviousResponseIds({ chat: null, langflow: null }) } + const handleFileUpload = async (file: File) => { + if (isUploading) return + + setIsUploading(true) + + try { + const formData = new FormData() + formData.append('file', file) + formData.append('endpoint', endpoint) + + // Add previous_response_id if we have one for this endpoint + const currentResponseId = previousResponseIds[endpoint] + if (currentResponseId) { + formData.append('previous_response_id', currentResponseId) + } + + const response = await fetch('/api/upload_context', { + method: 'POST', + body: formData, + }) + + if (!response.ok) { + throw new Error(`Upload failed: ${response.status}`) + } + + const result = await response.json() + + // Add upload confirmation as a system message in the UI + const uploadMessage: Message = { + role: "assistant", + content: `📄 Document uploaded: **${result.filename}** (${result.pages} pages, ${result.content_length.toLocaleString()} characters)\n\n${result.confirmation}`, + timestamp: new Date() + } + + setMessages(prev => [...prev, uploadMessage]) + + // Update the response ID for this endpoint + if (result.response_id) { + setPreviousResponseIds(prev => ({ + ...prev, + [endpoint]: result.response_id + })) + } + + } catch (error) { + console.error('Upload failed:', error) + const errorMessage: Message = { + role: "assistant", + content: `❌ Upload failed: ${error instanceof Error ? error.message : 'Unknown error'}`, + timestamp: new Date() + } + setMessages(prev => [...prev, errorMessage]) + } finally { + setIsUploading(false) + } + } + + const handleDragEnter = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + dragCounterRef.current++ + if (dragCounterRef.current === 1) { + setIsDragOver(true) + } + } + + const handleDragOver = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + } + + const handleDragLeave = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + dragCounterRef.current-- + if (dragCounterRef.current === 0) { + setIsDragOver(false) + } + } + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + dragCounterRef.current = 0 + setIsDragOver(false) + + const files = Array.from(e.dataTransfer.files) + if (files.length > 0) { + handleFileUpload(files[0]) // Upload first file only + } + } + useEffect(() => { scrollToBottom() }, [messages, streamingMessage]) @@ -601,13 +696,40 @@ export default function ChatPage() { {/* Messages Area */} -
+
{messages.length === 0 && !streamingMessage ? (
- -

Start a conversation by asking a question!

-

I can help you find information in your documents.

+ {isDragOver ? ( + <> + +

Drop your document here

+

I'll process it and add it to our conversation context

+ + ) : isUploading ? ( + <> + +

Processing your document...

+

This may take a few moments

+ + ) : ( + <> + +

Start a conversation by asking a question!

+

I can help you find information in your documents.

+

💡 Tip: Drag & drop a document here to add context

+ + )}
) : ( @@ -706,6 +828,16 @@ export default function ChatPage() {
)} + + {/* Drag overlay for existing messages */} + {isDragOver && messages.length > 0 && ( +
+
+ +

Drop document to add context

+
+
+ )}
{/* Input Area */}