mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-04 21:32:39 +02:00
feat: add LLM configuration alerts in connector and document upload popups
This commit is contained in:
parent
8301e0169c
commit
bf3bbce0e6
2 changed files with 102 additions and 7 deletions
|
|
@ -1,12 +1,19 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { Cable } from "lucide-react";
|
import { AlertTriangle, Cable, Settings } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
import type { FC } from "react";
|
import type { FC } 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 { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||||
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
||||||
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
import { TooltipIconButton } from "@/components/assistant-ui/tooltip-icon-button";
|
||||||
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||||
import { Spinner } from "@/components/ui/spinner";
|
import { Spinner } from "@/components/ui/spinner";
|
||||||
import { Tabs, TabsContent } from "@/components/ui/tabs";
|
import { Tabs, TabsContent } from "@/components/ui/tabs";
|
||||||
|
|
@ -34,6 +41,26 @@ export const ConnectorIndicator: FC = () => {
|
||||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const { data: currentUser } = useAtomValue(currentUserAtom);
|
const { data: currentUser } = useAtomValue(currentUserAtom);
|
||||||
|
const { data: preferences = {}, isFetching: preferencesLoading } =
|
||||||
|
useAtomValue(llmPreferencesAtom);
|
||||||
|
const { data: globalConfigs = [], isFetching: globalConfigsLoading } =
|
||||||
|
useAtomValue(globalNewLLMConfigsAtom);
|
||||||
|
|
||||||
|
// 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 llmConfigLoading = preferencesLoading || globalConfigsLoading;
|
||||||
|
|
||||||
// Fetch document type counts using Electric SQL + PGlite for real-time updates
|
// Fetch document type counts using Electric SQL + PGlite for real-time updates
|
||||||
const { documentTypeCounts, loading: documentTypesLoading } = useDocumentsElectric(searchSpaceId);
|
const { documentTypeCounts, loading: documentTypesLoading } = useDocumentsElectric(searchSpaceId);
|
||||||
|
|
@ -329,6 +356,27 @@ export const ConnectorIndicator: FC = () => {
|
||||||
<div className="flex-1 min-h-0 relative overflow-hidden">
|
<div className="flex-1 min-h-0 relative overflow-hidden">
|
||||||
<div className="h-full overflow-y-auto" onScroll={handleScroll}>
|
<div className="h-full overflow-y-auto" onScroll={handleScroll}>
|
||||||
<div className="px-4 sm:px-12 py-4 sm:py-8 pb-12 sm:pb-16">
|
<div className="px-4 sm:px-12 py-4 sm:py-8 pb-12 sm:pb-16">
|
||||||
|
{/* LLM Configuration Warning */}
|
||||||
|
{!llmConfigLoading && !hasDocumentSummaryLLM && (
|
||||||
|
<Alert variant="destructive" className="mb-6">
|
||||||
|
<AlertTriangle className="h-4 w-4" />
|
||||||
|
<AlertTitle>LLM Configuration Required</AlertTitle>
|
||||||
|
<AlertDescription className="mt-2">
|
||||||
|
<p className="mb-3">
|
||||||
|
{isAutoMode && !hasGlobalConfigs
|
||||||
|
? "Auto mode is selected but no global LLM configurations are available. Please configure a custom LLM in Settings to process and summarize documents from your connected sources."
|
||||||
|
: "You need to configure a Document Summary LLM before adding connectors. This LLM is used to process and summarize documents from your connected sources."}
|
||||||
|
</p>
|
||||||
|
<Button asChild size="sm" variant="outline">
|
||||||
|
<Link href={`/dashboard/${searchSpaceId}/settings`}>
|
||||||
|
<Settings className="mr-2 h-4 w-4" />
|
||||||
|
Go to Settings
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
<TabsContent value="all" className="m-0">
|
<TabsContent value="all" className="m-0">
|
||||||
<AllConnectorsTab
|
<AllConnectorsTab
|
||||||
searchQuery={searchQuery}
|
searchQuery={searchQuery}
|
||||||
|
|
@ -338,10 +386,10 @@ export const ConnectorIndicator: FC = () => {
|
||||||
allConnectors={connectors}
|
allConnectors={connectors}
|
||||||
documentTypeCounts={documentTypeCounts}
|
documentTypeCounts={documentTypeCounts}
|
||||||
indexingConnectorIds={indexingConnectorIds}
|
indexingConnectorIds={indexingConnectorIds}
|
||||||
onConnectOAuth={handleConnectOAuth}
|
onConnectOAuth={hasDocumentSummaryLLM ? handleConnectOAuth : () => {}}
|
||||||
onConnectNonOAuth={handleConnectNonOAuth}
|
onConnectNonOAuth={hasDocumentSummaryLLM ? handleConnectNonOAuth : () => {}}
|
||||||
onCreateWebcrawler={handleCreateWebcrawler}
|
onCreateWebcrawler={hasDocumentSummaryLLM ? handleCreateWebcrawler : () => {}}
|
||||||
onCreateYouTubeCrawler={handleCreateYouTubeCrawler}
|
onCreateYouTubeCrawler={hasDocumentSummaryLLM ? handleCreateYouTubeCrawler : () => {}}
|
||||||
onManage={handleStartEdit}
|
onManage={handleStartEdit}
|
||||||
onViewAccountsList={handleViewAccountsList}
|
onViewAccountsList={handleViewAccountsList}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { Upload } from "lucide-react";
|
import { AlertTriangle, Settings, Upload } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
createContext,
|
createContext,
|
||||||
type FC,
|
type FC,
|
||||||
|
|
@ -11,8 +12,14 @@ import {
|
||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} 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 { activeSearchSpaceIdAtom } from "@/atoms/search-spaces/search-space-query.atoms";
|
||||||
import { DocumentUploadTab } from "@/components/sources/DocumentUploadTab";
|
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";
|
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||||
|
|
||||||
// Context for opening the dialog from anywhere
|
// Context for opening the dialog from anywhere
|
||||||
|
|
@ -84,6 +91,10 @@ const DocumentUploadPopupContent: FC<{
|
||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
}> = ({ isOpen, onOpenChange }) => {
|
}> = ({ isOpen, onOpenChange }) => {
|
||||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||||
|
const { data: preferences = {}, isFetching: preferencesLoading } =
|
||||||
|
useAtomValue(llmPreferencesAtom);
|
||||||
|
const { data: globalConfigs = [], isFetching: globalConfigsLoading } =
|
||||||
|
useAtomValue(globalNewLLMConfigsAtom);
|
||||||
|
|
||||||
if (!searchSpaceId) return null;
|
if (!searchSpaceId) return null;
|
||||||
|
|
||||||
|
|
@ -91,6 +102,22 @@ const DocumentUploadPopupContent: FC<{
|
||||||
onOpenChange(false);
|
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 (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
||||||
<DialogContent className="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 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">
|
<DialogContent className="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 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">
|
||||||
|
|
@ -118,7 +145,27 @@ const DocumentUploadPopupContent: FC<{
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="px-4 sm:px-12 pb-4 sm:pb-16">
|
<div className="px-4 sm:px-12 pb-4 sm:pb-16">
|
||||||
<DocumentUploadTab searchSpaceId={searchSpaceId} onSuccess={handleSuccess} />
|
{!isLoading && !hasDocumentSummaryLLM ? (
|
||||||
|
<Alert variant="destructive" className="mb-4">
|
||||||
|
<AlertTriangle className="h-4 w-4" />
|
||||||
|
<AlertTitle>LLM Configuration Required</AlertTitle>
|
||||||
|
<AlertDescription className="mt-2">
|
||||||
|
<p className="mb-3">
|
||||||
|
{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."}
|
||||||
|
</p>
|
||||||
|
<Button asChild size="sm" variant="outline">
|
||||||
|
<Link href={`/dashboard/${searchSpaceId}/settings`}>
|
||||||
|
<Settings className="mr-2 h-4 w-4" />
|
||||||
|
Go to Settings
|
||||||
|
</Link>
|
||||||
|
</Button>
|
||||||
|
</AlertDescription>
|
||||||
|
</Alert>
|
||||||
|
) : (
|
||||||
|
<DocumentUploadTab searchSpaceId={searchSpaceId} onSuccess={handleSuccess} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue