From 1fef4ee1dfd3e4f8907438a73baa1d84290d1dd5 Mon Sep 17 00:00:00 2001 From: Cole Goldsmith Date: Wed, 22 Oct 2025 15:26:12 -0500 Subject: [PATCH 1/4] Refactor knowledge menu icons and use shadcn dropdown --- frontend/components/knowledge-dropdown.tsx | 158 ++++++++----------- frontend/src/app/settings/icons/aws-icon.tsx | 31 ++++ 2 files changed, 93 insertions(+), 96 deletions(-) create mode 100644 frontend/src/app/settings/icons/aws-icon.tsx diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index 19ddc387..56aa7def 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -4,10 +4,11 @@ import { useQueryClient } from "@tanstack/react-query"; import { ChevronDown, Cloud, + File, + Folder, FolderOpen, Loader2, PlugZap, - Upload, } from "lucide-react"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; @@ -22,18 +23,26 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useTask } from "@/contexts/task-context"; -import { cn } from "@/lib/utils"; import type { File as SearchFile } from "@/src/app/api/queries/useGetSearchQuery"; +import GoogleDriveIcon from "@/app/settings/icons/google-drive-icon"; +import OneDriveIcon from "@/app/settings/icons/one-drive-icon"; +import SharePointIcon from "@/app/settings/icons/share-point-icon"; +import AwsIcon from "@/app/settings/icons/aws-icon"; export function KnowledgeDropdown() { const { addTask } = useTask(); const { refetch: refetchTasks } = useGetTasksQuery(); const queryClient = useQueryClient(); const router = useRouter(); - const [isOpen, setIsOpen] = useState(false); const [showFolderDialog, setShowFolderDialog] = useState(false); const [showS3Dialog, setShowS3Dialog] = useState(false); const [showDuplicateDialog, setShowDuplicateDialog] = useState(false); @@ -55,7 +64,6 @@ export function KnowledgeDropdown() { }; }>({}); const fileInputRef = useRef(null); - const dropdownRef = useRef(null); // Check AWS availability and cloud connectors on mount useEffect(() => { @@ -141,24 +149,6 @@ export function KnowledgeDropdown() { checkAvailability(); }, []); - // 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(); }; @@ -168,8 +158,7 @@ export function KnowledgeDropdown() { if (files && files.length > 0) { const file = files[0]; - // Close dropdown immediately after file selection - setIsOpen(false); + // File selection will close dropdown automatically try { // Check if filename already exists (using ORIGINAL filename) @@ -427,13 +416,19 @@ export function KnowledgeDropdown() { } }; + // Icon mapping for cloud connectors + const connectorIconMap = { + google_drive: GoogleDriveIcon, + onedrive: OneDriveIcon, + sharepoint: SharePointIcon, + }; + const cloudConnectorItems = Object.entries(cloudConnectors) .filter(([, info]) => info.available) .map(([type, info]) => ({ label: info.name, - icon: PlugZap, + icon: connectorIconMap[type as keyof typeof connectorIconMap] || PlugZap, onClick: async () => { - setIsOpen(false); if (info.connected && info.hasToken) { setIsNavigatingToCloud(true); try { @@ -448,36 +443,30 @@ export function KnowledgeDropdown() { } }, disabled: !info.connected || !info.hasToken, - tooltip: !info.connected - ? `Connect ${info.name} in Settings first` - : !info.hasToken - ? `Reconnect ${info.name} - access token required` - : undefined, })); const menuItems = [ { - label: "Add File", - icon: Upload, + label: "File", + icon: File, onClick: handleFileUpload, }, { - label: "Process Folder", - icon: FolderOpen, - onClick: () => { - setIsOpen(false); - setShowFolderDialog(true); - }, + label: "Folder", + icon: Folder, + onClick: () => setShowFolderDialog(true), + }, + { + label: "Amazon S3", + icon: AwsIcon, + onClick: () => setShowS3Dialog(true), }, ...(awsEnabled ? [ { - label: "Process S3 Bucket", - icon: Cloud, - onClick: () => { - setIsOpen(false); - setShowS3Dialog(true); - }, + label: "Amazon S3", + icon: AwsIcon, + onClick: () => setShowS3Dialog(true), }, ] : []), @@ -490,13 +479,9 @@ export function KnowledgeDropdown() { return ( <> -
- + {!isLoading && } + + + + {menuItems.map((item, index) => ( + + + {item.label} + + ))} + + - {isOpen && !isLoading && ( -
-
- {menuItems.map((item, index) => ( - - ))} -
-
- )} - - -
+ {/* Process Folder Dialog */} @@ -575,7 +541,7 @@ export function KnowledgeDropdown() { type="text" placeholder="/path/to/documents" value={folderPath} - onChange={e => setFolderPath(e.target.value)} + onChange={(e) => setFolderPath(e.target.value)} />
@@ -617,7 +583,7 @@ export function KnowledgeDropdown() { type="text" placeholder="s3://bucket/path" value={bucketUrl} - onChange={e => setBucketUrl(e.target.value)} + onChange={(e) => setBucketUrl(e.target.value)} />
diff --git a/frontend/src/app/settings/icons/aws-icon.tsx b/frontend/src/app/settings/icons/aws-icon.tsx new file mode 100644 index 00000000..f78457f4 --- /dev/null +++ b/frontend/src/app/settings/icons/aws-icon.tsx @@ -0,0 +1,31 @@ +const AwsIcon = ({ className }: { className?: string }) => { + return ( + + + + + + ); +}; + +export default AwsIcon; From e0fdb32843245868fa3c8a685da3b261a9ed3f75 Mon Sep 17 00:00:00 2001 From: Cole Goldsmith Date: Wed, 22 Oct 2025 15:33:55 -0500 Subject: [PATCH 2/4] remove test menuitem --- frontend/components/knowledge-dropdown.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index 56aa7def..19f52968 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -456,11 +456,6 @@ export function KnowledgeDropdown() { icon: Folder, onClick: () => setShowFolderDialog(true), }, - { - label: "Amazon S3", - icon: AwsIcon, - onClick: () => setShowS3Dialog(true), - }, ...(awsEnabled ? [ { From 3735b3a1889233a353b73d9d96b9d3f68b5ba57a Mon Sep 17 00:00:00 2001 From: Cole Goldsmith Date: Thu, 23 Oct 2025 10:05:31 -0500 Subject: [PATCH 3/4] rotate dropdown button --- frontend/components/knowledge-dropdown.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index 19f52968..12d1d178 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -37,12 +37,14 @@ import GoogleDriveIcon from "@/app/settings/icons/google-drive-icon"; import OneDriveIcon from "@/app/settings/icons/one-drive-icon"; import SharePointIcon from "@/app/settings/icons/share-point-icon"; import AwsIcon from "@/app/settings/icons/aws-icon"; +import { cn } from "@/lib/utils"; export function KnowledgeDropdown() { const { addTask } = useTask(); const { refetch: refetchTasks } = useGetTasksQuery(); const queryClient = useQueryClient(); const router = useRouter(); + const [isMenuOpen, setIsMenuOpen] = useState(false); const [showFolderDialog, setShowFolderDialog] = useState(false); const [showS3Dialog, setShowS3Dialog] = useState(false); const [showDuplicateDialog, setShowDuplicateDialog] = useState(false); @@ -474,7 +476,7 @@ export function KnowledgeDropdown() { return ( <> - + From b3104e021771290973bf7dfb4dc8e05bf81e2f85 Mon Sep 17 00:00:00 2001 From: Cole Goldsmith Date: Thu, 23 Oct 2025 10:21:21 -0500 Subject: [PATCH 4/4] fix aws icon in light mode --- frontend/components/knowledge-dropdown.tsx | 10 +++++++--- frontend/src/app/settings/icons/aws-icon.tsx | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frontend/components/knowledge-dropdown.tsx b/frontend/components/knowledge-dropdown.tsx index 12d1d178..1e42803f 100644 --- a/frontend/components/knowledge-dropdown.tsx +++ b/frontend/components/knowledge-dropdown.tsx @@ -450,12 +450,16 @@ export function KnowledgeDropdown() { const menuItems = [ { label: "File", - icon: File, + icon: ({ className }: { className?: string }) => ( + + ), onClick: handleFileUpload, }, { label: "Folder", - icon: Folder, + icon: ({ className }: { className?: string }) => ( + + ), onClick: () => setShowFolderDialog(true), }, ...(awsEnabled @@ -510,7 +514,7 @@ export function KnowledgeDropdown() { onClick={item.onClick} disabled={"disabled" in item ? item.disabled : false} > - + {item.label} ))} diff --git a/frontend/src/app/settings/icons/aws-icon.tsx b/frontend/src/app/settings/icons/aws-icon.tsx index f78457f4..502a1b81 100644 --- a/frontend/src/app/settings/icons/aws-icon.tsx +++ b/frontend/src/app/settings/icons/aws-icon.tsx @@ -10,7 +10,7 @@ const AwsIcon = ({ className }: { className?: string }) => { >