"use client" import { useState, useEffect, useRef } from "react" import { useRouter } from "next/navigation" import { ChevronDown, Upload, FolderOpen, Cloud, PlugZap, Plus } from "lucide-react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { cn } from "@/lib/utils" import { useTask } from "@/contexts/task-context" interface KnowledgeDropdownProps { active?: boolean variant?: 'navigation' | 'button' } export function KnowledgeDropdown({ active, variant = 'navigation' }: KnowledgeDropdownProps) { const router = useRouter() const { addTask } = useTask() const [isOpen, setIsOpen] = useState(false) const [showFolderDialog, setShowFolderDialog] = useState(false) const [showS3Dialog, setShowS3Dialog] = useState(false) const [awsEnabled, setAwsEnabled] = useState(false) const [folderPath, setFolderPath] = useState("/app/documents/") const [bucketUrl, setBucketUrl] = useState("s3://") const [folderLoading, setFolderLoading] = useState(false) const [s3Loading, setS3Loading] = useState(false) const fileInputRef = useRef(null) const dropdownRef = useRef(null) // Check AWS availability on mount useEffect(() => { const checkAws = async () => { try { const res = await fetch("/api/upload_options") if (res.ok) { const data = await res.json() setAwsEnabled(Boolean(data.aws)) } } catch (err) { console.error("Failed to check AWS availability", err) } } checkAws() }, []) // Handle click outside to close dropdown useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { setIsOpen(false) } } if (isOpen) { document.addEventListener("mousedown", handleClickOutside) return () => document.removeEventListener("mousedown", handleClickOutside) } }, [isOpen]) const handleFileUpload = () => { fileInputRef.current?.click() } const handleFileChange = async (e: React.ChangeEvent) => { const files = e.target.files if (files && files.length > 0) { // Trigger the same file upload event as the chat page window.dispatchEvent(new CustomEvent('fileUploadStart', { detail: { filename: files[0].name } })) try { const formData = new FormData() formData.append('file', files[0]) const response = await fetch('/api/upload', { method: 'POST', body: formData, }) const result = await response.json() if (response.ok) { window.dispatchEvent(new CustomEvent('fileUploaded', { detail: { file: files[0], result } })) } else { window.dispatchEvent(new CustomEvent('fileUploadError', { detail: { filename: files[0].name, error: result.error || 'Upload failed' } })) } } catch (error) { window.dispatchEvent(new CustomEvent('fileUploadError', { detail: { filename: files[0].name, error: error instanceof Error ? error.message : 'Upload failed' } })) } finally { window.dispatchEvent(new CustomEvent('fileUploadComplete')) } } // Reset file input if (fileInputRef.current) { fileInputRef.current.value = '' } setIsOpen(false) } const handleFolderUpload = async () => { if (!folderPath.trim()) return setFolderLoading(true) try { const response = await fetch("/api/upload_path", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ path: folderPath }), }) const result = await response.json() if (response.status === 201) { const taskId = result.task_id || result.id if (!taskId) { throw new Error("No task ID received from server") } addTask(taskId) setFolderPath("") setShowFolderDialog(false) } else if (response.ok) { setFolderPath("") setShowFolderDialog(false) } else { console.error("Folder upload failed:", result.error) } } catch (error) { console.error("Folder upload error:", error) } finally { setFolderLoading(false) } } const handleS3Upload = async () => { if (!bucketUrl.trim()) return setS3Loading(true) try { const response = await fetch("/api/upload_bucket", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ s3_url: bucketUrl }), }) const result = await response.json() if (response.status === 201) { const taskId = result.task_id || result.id if (!taskId) { throw new Error("No task ID received from server") } addTask(taskId) setBucketUrl("s3://") setShowS3Dialog(false) } else { console.error("S3 upload failed:", result.error) } } catch (error) { console.error("S3 upload error:", error) } finally { setS3Loading(false) } } const menuItems = [ { label: "Add File", icon: Upload, onClick: handleFileUpload }, { label: "Process Folder", icon: FolderOpen, onClick: () => { setIsOpen(false) setShowFolderDialog(true) } }, ...(awsEnabled ? [{ label: "Process S3 Bucket", icon: Cloud, onClick: () => { setIsOpen(false) setShowS3Dialog(true) } }] : []), { label: "Cloud Connectors", icon: PlugZap, onClick: () => { setIsOpen(false) router.push("/settings") } } ] return ( <>
{isOpen && (
{menuItems.map((item, index) => ( ))}
)}
{/* Process Folder Dialog */} Process Folder Process all documents in a folder path
setFolderPath(e.target.value)} />
{/* Process S3 Bucket Dialog */} Process S3 Bucket Process all documents from an S3 bucket. AWS credentials must be configured.
setBucketUrl(e.target.value)} />
) }