"use client"; import { useAtomValue, useSetAtom } from "jotai"; import { AlertTriangle, Settings } from "lucide-react"; import { createContext, type FC, type ReactNode, useCallback, useContext, useRef, useState, } from "react"; import { globalNewLLMConfigsAtom, llmPreferencesAtom, } from "@/atoms/new-llm-config/new-llm-config-query.atoms"; import { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms"; import { searchSpaceSettingsDialogAtom } from "@/atoms/settings/settings-dialog.atoms"; import { DocumentUploadTab } from "@/components/sources/DocumentUploadTab"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; // Context for opening the dialog from anywhere interface DocumentUploadDialogContextType { openDialog: () => void; closeDialog: () => void; } const DocumentUploadDialogContext = createContext(null); export const useDocumentUploadDialog = () => { const context = useContext(DocumentUploadDialogContext); if (!context) { throw new Error("useDocumentUploadDialog must be used within DocumentUploadDialogProvider"); } return context; }; // Provider component export const DocumentUploadDialogProvider: FC<{ children: ReactNode }> = ({ children }) => { const [isOpen, setIsOpen] = useState(false); const isClosingRef = useRef(false); const openDialog = useCallback(() => { // Prevent opening if we just closed (debounce) if (isClosingRef.current) { return; } setIsOpen(true); }, []); const closeDialog = useCallback(() => { isClosingRef.current = true; setIsOpen(false); // Reset the flag after a short delay to allow for file picker to close setTimeout(() => { isClosingRef.current = false; }, 300); }, []); const handleOpenChange = useCallback( (open: boolean) => { if (!open) { // Only close if not already in closing state if (!isClosingRef.current) { closeDialog(); } } else { // Only open if not in the middle of closing if (!isClosingRef.current) { setIsOpen(true); } } }, [closeDialog] ); return ( {children} ); }; // Internal component that renders the dialog const DocumentUploadPopupContent: FC<{ isOpen: boolean; onOpenChange: (open: boolean) => void; }> = ({ isOpen, onOpenChange }) => { const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom); const setSearchSpaceSettingsDialog = useSetAtom(searchSpaceSettingsDialogAtom); const { data: preferences = {}, isFetching: preferencesLoading } = useAtomValue(llmPreferencesAtom); const { data: globalConfigs = [], isFetching: globalConfigsLoading } = useAtomValue(globalNewLLMConfigsAtom); if (!searchSpaceId) return null; const handleSuccess = () => { onOpenChange(false); }; // Check if document summary LLM is properly configured // - If ID is 0 (Auto mode), we need global configs to be available // - If ID is positive (user config) or negative (specific global config), it's configured // - If ID is null/undefined, it's not configured const docSummaryLlmId = preferences.document_summary_llm_id; const isAutoMode = docSummaryLlmId === 0; const hasGlobalConfigs = globalConfigs.length > 0; const hasDocumentSummaryLLM = docSummaryLlmId !== null && docSummaryLlmId !== undefined && // If it's Auto mode, we need global configs to actually be available (!isAutoMode || hasGlobalConfigs); const isLoading = preferencesLoading || globalConfigsLoading; return ( e.preventDefault()} onInteractOutside={(e) => e.preventDefault()} onEscapeKeyDown={(e) => e.preventDefault()} className="select-none max-w-4xl w-[95vw] sm:w-full h-[calc(100dvh-2rem)] sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border ring-0 bg-muted dark:bg-muted text-foreground [&>button]:right-3 sm:[&>button]:right-12 [&>button]:top-3 sm:[&>button]:top-10 [&>button]:opacity-80 hover:[&>button]:opacity-100 [&>button]:z-[100] [&>button_svg]:size-4 sm:[&>button_svg]:size-5" > Upload Document {/* Scrollable container for mobile */}
{/* Header - scrolls with content on mobile */}
{/* Upload header */}

Upload Documents

Upload and sync your documents to your search space

{/* Content */}
{!isLoading && !hasDocumentSummaryLLM ? ( LLM Configuration Required

{isAutoMode && !hasGlobalConfigs ? "Auto mode is selected but no global LLM configurations are available. Please configure a custom LLM in Settings to process and summarize your uploaded documents." : "You need to configure a Document Summary LLM before uploading files. This LLM is used to process and summarize your uploaded documents."}

) : ( )}
{/* Bottom fade shadow - hidden on very small screens */}
); };