mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-07 23:02:39 +02:00
Merge remote-tracking branch 'upstream/dev' into fix/docker-dev
This commit is contained in:
commit
831ea5d34c
2 changed files with 104 additions and 46 deletions
|
|
@ -4,7 +4,7 @@ import { useAtomValue } from "jotai";
|
||||||
import { AlertTriangle, Cable, Settings } from "lucide-react";
|
import { AlertTriangle, Cable, Settings } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
import { type FC, useMemo } from "react";
|
import { type FC, forwardRef, useImperativeHandle, useMemo } from "react";
|
||||||
import { documentTypeCountsAtom } from "@/atoms/documents/document-query.atoms";
|
import { documentTypeCountsAtom } from "@/atoms/documents/document-query.atoms";
|
||||||
import {
|
import {
|
||||||
globalNewLLMConfigsAtom,
|
globalNewLLMConfigsAtom,
|
||||||
|
|
@ -37,7 +37,16 @@ import { AllConnectorsTab } from "./connector-popup/tabs/all-connectors-tab";
|
||||||
import { ConnectorAccountsListView } from "./connector-popup/views/connector-accounts-list-view";
|
import { ConnectorAccountsListView } from "./connector-popup/views/connector-accounts-list-view";
|
||||||
import { YouTubeCrawlerView } from "./connector-popup/views/youtube-crawler-view";
|
import { YouTubeCrawlerView } from "./connector-popup/views/youtube-crawler-view";
|
||||||
|
|
||||||
export const ConnectorIndicator: FC = () => {
|
export interface ConnectorIndicatorHandle {
|
||||||
|
open: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConnectorIndicatorProps {
|
||||||
|
showTrigger?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConnectorIndicator = forwardRef<ConnectorIndicatorHandle, ConnectorIndicatorProps>(
|
||||||
|
({ showTrigger = true }, ref) => {
|
||||||
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
const searchSpaceId = useAtomValue(activeSearchSpaceIdAtom);
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const { data: currentUser } = useAtomValue(currentUserAtom);
|
const { data: currentUser } = useAtomValue(currentUserAtom);
|
||||||
|
|
@ -189,38 +198,44 @@ export const ConnectorIndicator: FC = () => {
|
||||||
(connectors || []).map((c: SearchSourceConnector) => c.connector_type)
|
(connectors || []).map((c: SearchSourceConnector) => c.connector_type)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open: () => handleOpenChange(true),
|
||||||
|
}));
|
||||||
|
|
||||||
if (!searchSpaceId) return null;
|
if (!searchSpaceId) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isOpen} onOpenChange={handleOpenChange}>
|
<Dialog open={isOpen} onOpenChange={handleOpenChange}>
|
||||||
<TooltipIconButton
|
{showTrigger && (
|
||||||
data-joyride="connector-icon"
|
<TooltipIconButton
|
||||||
tooltip={hasConnectors ? `Manage ${activeConnectorsCount} connectors` : "Connect your data"}
|
data-joyride="connector-icon"
|
||||||
side="bottom"
|
tooltip={hasConnectors ? `Manage ${activeConnectorsCount} connectors` : "Connect your data"}
|
||||||
className={cn(
|
side="bottom"
|
||||||
"size-[34px] rounded-full p-1 flex items-center justify-center transition-colors relative",
|
className={cn(
|
||||||
"hover:bg-muted-foreground/15 dark:hover:bg-muted-foreground/30",
|
"size-[34px] rounded-full p-1 flex items-center justify-center transition-colors relative",
|
||||||
"outline-none focus:outline-none focus-visible:outline-none font-semibold text-xs",
|
"hover:bg-muted-foreground/15 dark:hover:bg-muted-foreground/30",
|
||||||
"border-0 ring-0 focus:ring-0 shadow-none focus:shadow-none"
|
"outline-none focus:outline-none focus-visible:outline-none font-semibold text-xs",
|
||||||
)}
|
"border-0 ring-0 focus:ring-0 shadow-none focus:shadow-none"
|
||||||
aria-label={
|
)}
|
||||||
hasConnectors ? `View ${activeConnectorsCount} connectors` : "Add your first connector"
|
aria-label={
|
||||||
}
|
hasConnectors ? `View ${activeConnectorsCount} connectors` : "Add your first connector"
|
||||||
onClick={() => handleOpenChange(true)}
|
}
|
||||||
>
|
onClick={() => handleOpenChange(true)}
|
||||||
{isLoading ? (
|
>
|
||||||
<Spinner size="sm" />
|
{isLoading ? (
|
||||||
) : (
|
<Spinner size="sm" />
|
||||||
<>
|
) : (
|
||||||
<Cable className="size-4 stroke-[1.5px]" />
|
<>
|
||||||
{activeConnectorsCount > 0 && (
|
<Cable className="size-4 stroke-[1.5px]" />
|
||||||
<span className="absolute -top-0.5 right-0 flex items-center justify-center min-w-[16px] h-4 px-1 text-[10px] font-medium rounded-full bg-primary text-primary-foreground shadow-sm select-none">
|
{activeConnectorsCount > 0 && (
|
||||||
{activeConnectorsCount > 99 ? "99+" : activeConnectorsCount}
|
<span className="absolute -top-0.5 right-0 flex items-center justify-center min-w-[16px] h-4 px-1 text-[10px] font-medium rounded-full bg-primary text-primary-foreground shadow-sm select-none">
|
||||||
</span>
|
{activeConnectorsCount > 99 ? "99+" : activeConnectorsCount}
|
||||||
)}
|
</span>
|
||||||
</>
|
)}
|
||||||
)}
|
</>
|
||||||
</TooltipIconButton>
|
)}
|
||||||
|
</TooltipIconButton>
|
||||||
|
)}
|
||||||
|
|
||||||
<DialogContent className="max-w-3xl w-[95vw] sm:w-full h-[75vh] sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border ring-0 dark:ring-0 bg-muted dark:bg-muted text-foreground focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 [&>button]:right-4 sm:[&>button]:right-12 [&>button]:top-6 sm:[&>button]:top-10 [&>button]:opacity-80 hover:[&>button]:opacity-100 [&>button_svg]:size-5 select-none">
|
<DialogContent className="max-w-3xl w-[95vw] sm:w-full h-[75vh] sm:h-[85vh] flex flex-col p-0 gap-0 overflow-hidden border border-border ring-0 dark:ring-0 bg-muted dark:bg-muted text-foreground focus:outline-none focus:ring-0 focus-visible:outline-none focus-visible:ring-0 [&>button]:right-4 sm:[&>button]:right-12 [&>button]:top-6 sm:[&>button]:top-10 [&>button]:opacity-80 hover:[&>button]:opacity-100 [&>button_svg]:size-5 select-none">
|
||||||
<DialogTitle className="sr-only">Manage Connectors</DialogTitle>
|
<DialogTitle className="sr-only">Manage Connectors</DialogTitle>
|
||||||
|
|
@ -429,4 +444,6 @@ export const ConnectorIndicator: FC = () => {
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
|
ConnectorIndicator.displayName = "ConnectorIndicator";
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import {
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
ArrowDownIcon,
|
ArrowDownIcon,
|
||||||
ArrowUpIcon,
|
ArrowUpIcon,
|
||||||
|
Cable,
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
ChevronLeftIcon,
|
ChevronLeftIcon,
|
||||||
ChevronRightIcon,
|
ChevronRightIcon,
|
||||||
|
|
@ -22,6 +23,7 @@ import {
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
RefreshCwIcon,
|
RefreshCwIcon,
|
||||||
SquareIcon,
|
SquareIcon,
|
||||||
|
SquareLibrary,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
import { type FC, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
@ -42,8 +44,10 @@ import {
|
||||||
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
|
||||||
import { AssistantMessage } from "@/components/assistant-ui/assistant-message";
|
import { AssistantMessage } from "@/components/assistant-ui/assistant-message";
|
||||||
import { ChatSessionStatus } from "@/components/assistant-ui/chat-session-status";
|
import { ChatSessionStatus } from "@/components/assistant-ui/chat-session-status";
|
||||||
import { ConnectorIndicator } from "@/components/assistant-ui/connector-popup";
|
import {
|
||||||
import { useDocumentUploadDialog } from "@/components/assistant-ui/document-upload-popup";
|
ConnectorIndicator,
|
||||||
|
type ConnectorIndicatorHandle,
|
||||||
|
} from "@/components/assistant-ui/connector-popup";
|
||||||
import {
|
import {
|
||||||
InlineMentionEditor,
|
InlineMentionEditor,
|
||||||
type InlineMentionEditorRef,
|
type InlineMentionEditorRef,
|
||||||
|
|
@ -62,6 +66,7 @@ import {
|
||||||
} from "@/components/new-chat/document-mention-picker";
|
} from "@/components/new-chat/document-mention-picker";
|
||||||
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
|
import type { ThinkingStep } from "@/components/tool-ui/deepagent-thinking";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||||
import type { Document } from "@/contracts/types/document.types";
|
import type { Document } from "@/contracts/types/document.types";
|
||||||
import { useBatchCommentsPreload } from "@/hooks/use-comments";
|
import { useBatchCommentsPreload } from "@/hooks/use-comments";
|
||||||
import { useCommentsElectric } from "@/hooks/use-comments-electric";
|
import { useCommentsElectric } from "@/hooks/use-comments-electric";
|
||||||
|
|
@ -474,7 +479,8 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
const mentionedDocuments = useAtomValue(mentionedDocumentsAtom);
|
const mentionedDocuments = useAtomValue(mentionedDocumentsAtom);
|
||||||
const sidebarDocs = useAtomValue(sidebarSelectedDocumentsAtom);
|
const sidebarDocs = useAtomValue(sidebarSelectedDocumentsAtom);
|
||||||
const setDocumentsSidebarOpen = useSetAtom(documentsSidebarOpenAtom);
|
const setDocumentsSidebarOpen = useSetAtom(documentsSidebarOpenAtom);
|
||||||
const { openDialog: openUploadDialog } = useDocumentUploadDialog();
|
const connectorRef = useRef<ConnectorIndicatorHandle>(null);
|
||||||
|
const [addMenuOpen, setAddMenuOpen] = useState(false);
|
||||||
|
|
||||||
const isComposerTextEmpty = useAssistantState(({ composer }) => {
|
const isComposerTextEmpty = useAssistantState(({ composer }) => {
|
||||||
const text = composer.text?.trim() || "";
|
const text = composer.text?.trim() || "";
|
||||||
|
|
@ -502,18 +508,53 @@ const ComposerAction: FC<ComposerActionProps> = ({ isBlockedByOtherUser = false
|
||||||
return (
|
return (
|
||||||
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
|
<div className="aui-composer-action-wrapper relative mx-2 mb-2 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<TooltipIconButton
|
<Popover open={addMenuOpen} onOpenChange={setAddMenuOpen}>
|
||||||
tooltip="Upload"
|
<PopoverTrigger asChild>
|
||||||
side="bottom"
|
<TooltipIconButton
|
||||||
variant="ghost"
|
tooltip="Configuration"
|
||||||
size="icon"
|
side="bottom"
|
||||||
className="size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30"
|
variant="ghost"
|
||||||
aria-label="Upload documents"
|
size="icon"
|
||||||
onClick={openUploadDialog}
|
className="size-[34px] rounded-full p-1 font-semibold text-xs hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30"
|
||||||
>
|
aria-label="Configuration"
|
||||||
<PlusIcon className="size-4" />
|
data-joyride="connector-icon"
|
||||||
</TooltipIconButton>
|
>
|
||||||
<ConnectorIndicator />
|
<PlusIcon className="size-4" />
|
||||||
|
</TooltipIconButton>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent
|
||||||
|
side="bottom"
|
||||||
|
align="start"
|
||||||
|
sideOffset={12}
|
||||||
|
className="w-[calc(100vw-2rem)] max-w-60 sm:w-60 p-2"
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-0.5">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||||
|
onClick={() => {
|
||||||
|
setAddMenuOpen(false);
|
||||||
|
setDocumentsSidebarOpen(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SquareLibrary className="size-4 shrink-0" />
|
||||||
|
Documents
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||||
|
onClick={() => {
|
||||||
|
setAddMenuOpen(false);
|
||||||
|
connectorRef.current?.open();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Cable className="size-4 shrink-0" />
|
||||||
|
Manage connectors
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
<ConnectorIndicator ref={connectorRef} showTrigger={false} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!hasModelConfigured && (
|
{!hasModelConfigured && (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue