mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-21 18:55:16 +02:00
feat: add support for Local Folder connector in UI components and configuration
This commit is contained in:
parent
28f556224a
commit
e2f946b7c0
9 changed files with 72 additions and 52 deletions
|
|
@ -17,6 +17,7 @@ import { DocumentUploadDialogProvider } from "@/components/assistant-ui/document
|
|||
import { LayoutDataProvider } from "@/components/layout";
|
||||
import { OnboardingTour } from "@/components/onboarding-tour";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { useFolderSync } from "@/hooks/use-folder-sync";
|
||||
import { useGlobalLoadingEffect } from "@/hooks/use-global-loading";
|
||||
|
||||
export function DashboardClientLayout({
|
||||
|
|
@ -159,6 +160,9 @@ export function DashboardClientLayout({
|
|||
// Use global loading screen - spinner animation won't reset
|
||||
useGlobalLoadingEffect(shouldShowLoading);
|
||||
|
||||
// Wire desktop app file watcher -> single-file re-index API
|
||||
useFolderSync();
|
||||
|
||||
if (shouldShowLoading) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ const FORM_ID_MAP: Record<string, string> = {
|
|||
CIRCLEBACK_CONNECTOR: "circleback-connect-form",
|
||||
MCP_CONNECTOR: "mcp-connect-form",
|
||||
OBSIDIAN_CONNECTOR: "obsidian-connect-form",
|
||||
LOCAL_FOLDER_CONNECTOR: "local-folder-connect-form",
|
||||
};
|
||||
|
||||
interface ConnectorConnectViewProps {
|
||||
|
|
|
|||
|
|
@ -272,13 +272,14 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
|||
{/* AI Summary toggle */}
|
||||
<SummaryConfig enabled={enableSummary} onEnabledChange={onEnableSummaryChange} />
|
||||
|
||||
{/* Date range selector - not shown for file-based connectors (Drive, Dropbox, OneDrive), Webcrawler, or GitHub (indexes full repo snapshots) */}
|
||||
{/* Date range selector - not shown for file-based connectors (Drive, Dropbox, OneDrive), Webcrawler, GitHub, or Local Folder */}
|
||||
{connector.connector_type !== "GOOGLE_DRIVE_CONNECTOR" &&
|
||||
connector.connector_type !== "COMPOSIO_GOOGLE_DRIVE_CONNECTOR" &&
|
||||
connector.connector_type !== "DROPBOX_CONNECTOR" &&
|
||||
connector.connector_type !== "ONEDRIVE_CONNECTOR" &&
|
||||
connector.connector_type !== "WEBCRAWLER_CONNECTOR" &&
|
||||
connector.connector_type !== "GITHUB_CONNECTOR" && (
|
||||
connector.connector_type !== "GITHUB_CONNECTOR" &&
|
||||
connector.connector_type !== "LOCAL_FOLDER_CONNECTOR" && (
|
||||
<DateRangeSelector
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
|
|
@ -293,39 +294,39 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* Periodic sync - shown for all indexable connectors */}
|
||||
{(() => {
|
||||
// Check if Google Drive (regular or Composio) has folders/files selected
|
||||
const isGoogleDrive = connector.connector_type === "GOOGLE_DRIVE_CONNECTOR";
|
||||
const isComposioGoogleDrive =
|
||||
connector.connector_type === "COMPOSIO_GOOGLE_DRIVE_CONNECTOR";
|
||||
const requiresFolderSelection = isGoogleDrive || isComposioGoogleDrive;
|
||||
const selectedFolders =
|
||||
(connector.config?.selected_folders as
|
||||
| Array<{ id: string; name: string }>
|
||||
| undefined) || [];
|
||||
const selectedFiles =
|
||||
(connector.config?.selected_files as
|
||||
| Array<{ id: string; name: string }>
|
||||
| undefined) || [];
|
||||
const hasItemsSelected = selectedFolders.length > 0 || selectedFiles.length > 0;
|
||||
const isDisabled = requiresFolderSelection && !hasItemsSelected;
|
||||
{/* Periodic sync - shown for all indexable connectors except Local Folder */}
|
||||
{connector.connector_type !== "LOCAL_FOLDER_CONNECTOR" &&
|
||||
(() => {
|
||||
const isGoogleDrive = connector.connector_type === "GOOGLE_DRIVE_CONNECTOR";
|
||||
const isComposioGoogleDrive =
|
||||
connector.connector_type === "COMPOSIO_GOOGLE_DRIVE_CONNECTOR";
|
||||
const requiresFolderSelection = isGoogleDrive || isComposioGoogleDrive;
|
||||
const selectedFolders =
|
||||
(connector.config?.selected_folders as
|
||||
| Array<{ id: string; name: string }>
|
||||
| undefined) || [];
|
||||
const selectedFiles =
|
||||
(connector.config?.selected_files as
|
||||
| Array<{ id: string; name: string }>
|
||||
| undefined) || [];
|
||||
const hasItemsSelected = selectedFolders.length > 0 || selectedFiles.length > 0;
|
||||
const isDisabled = requiresFolderSelection && !hasItemsSelected;
|
||||
|
||||
return (
|
||||
<PeriodicSyncConfig
|
||||
enabled={periodicEnabled}
|
||||
frequencyMinutes={frequencyMinutes}
|
||||
onEnabledChange={onPeriodicEnabledChange}
|
||||
onFrequencyChange={onFrequencyChange}
|
||||
disabled={isDisabled}
|
||||
disabledMessage={
|
||||
isDisabled
|
||||
? "Select at least one folder or file above to enable periodic sync"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
return (
|
||||
<PeriodicSyncConfig
|
||||
enabled={periodicEnabled}
|
||||
frequencyMinutes={frequencyMinutes}
|
||||
onEnabledChange={onPeriodicEnabledChange}
|
||||
onFrequencyChange={onFrequencyChange}
|
||||
disabled={isDisabled}
|
||||
disabledMessage={
|
||||
isDisabled
|
||||
? "Select at least one folder or file above to enable periodic sync"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
})()}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -158,13 +158,14 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
|
|||
{/* AI Summary toggle */}
|
||||
<SummaryConfig enabled={enableSummary} onEnabledChange={onEnableSummaryChange} />
|
||||
|
||||
{/* Date range selector - not shown for file-based connectors (Drive, Dropbox, OneDrive), Webcrawler, or GitHub (indexes full repo snapshots) */}
|
||||
{/* Date range selector - not shown for file-based connectors (Drive, Dropbox, OneDrive), Webcrawler, GitHub, or Local Folder */}
|
||||
{config.connectorType !== "GOOGLE_DRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "COMPOSIO_GOOGLE_DRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "DROPBOX_CONNECTOR" &&
|
||||
config.connectorType !== "ONEDRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "WEBCRAWLER_CONNECTOR" &&
|
||||
config.connectorType !== "GITHUB_CONNECTOR" && (
|
||||
config.connectorType !== "GITHUB_CONNECTOR" &&
|
||||
config.connectorType !== "LOCAL_FOLDER_CONNECTOR" && (
|
||||
<DateRangeSelector
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
|
|
@ -179,9 +180,12 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
|
|||
/>
|
||||
)}
|
||||
|
||||
{/* Periodic sync - not shown for Google Drive (regular and Composio) */}
|
||||
{/* Periodic sync - not shown for file-based connectors (Drive, Dropbox, OneDrive) or Local Folder in initial setup; configured in edit view instead */}
|
||||
{config.connectorType !== "GOOGLE_DRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "COMPOSIO_GOOGLE_DRIVE_CONNECTOR" && (
|
||||
config.connectorType !== "COMPOSIO_GOOGLE_DRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "DROPBOX_CONNECTOR" &&
|
||||
config.connectorType !== "ONEDRIVE_CONNECTOR" &&
|
||||
config.connectorType !== "LOCAL_FOLDER_CONNECTOR" && (
|
||||
<PeriodicSyncConfig
|
||||
enabled={periodicEnabled}
|
||||
frequencyMinutes={frequencyMinutes}
|
||||
|
|
|
|||
|
|
@ -184,6 +184,14 @@ export const OTHER_CONNECTORS = [
|
|||
connectorType: EnumConnectorName.OBSIDIAN_CONNECTOR,
|
||||
selfHostedOnly: true,
|
||||
},
|
||||
{
|
||||
id: "local-folder-connector",
|
||||
title: "Local Folder",
|
||||
description: "Watch and sync local folders (desktop only)",
|
||||
connectorType: EnumConnectorName.LOCAL_FOLDER_CONNECTOR,
|
||||
selfHostedOnly: true,
|
||||
desktopOnly: true,
|
||||
},
|
||||
] as const;
|
||||
|
||||
// Composio Connectors - Individual entries for each supported toolkit
|
||||
|
|
|
|||
|
|
@ -76,29 +76,26 @@ export const AllConnectorsTab: FC<AllConnectorsTabProps> = ({
|
|||
}) => {
|
||||
// Check if self-hosted mode (for showing self-hosted only connectors)
|
||||
const selfHosted = isSelfHosted();
|
||||
const isDesktop = typeof window !== "undefined" && !!window.electronAPI;
|
||||
|
||||
const matchesSearch = (title: string, description: string) =>
|
||||
title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
description.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
|
||||
const passesDeploymentFilter = (c: { selfHostedOnly?: boolean; desktopOnly?: boolean }) =>
|
||||
(!c.selfHostedOnly || selfHosted) && (!c.desktopOnly || isDesktop);
|
||||
|
||||
// Filter connectors based on search and deployment mode
|
||||
const filteredOAuth = OAUTH_CONNECTORS.filter(
|
||||
(c) =>
|
||||
// Filter by search query
|
||||
(c.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
c.description.toLowerCase().includes(searchQuery.toLowerCase())) &&
|
||||
// Filter self-hosted only connectors in cloud mode
|
||||
(!("selfHostedOnly" in c) || !c.selfHostedOnly || selfHosted)
|
||||
(c) => matchesSearch(c.title, c.description) && passesDeploymentFilter(c)
|
||||
);
|
||||
|
||||
const filteredCrawlers = CRAWLERS.filter(
|
||||
(c) =>
|
||||
(c.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
c.description.toLowerCase().includes(searchQuery.toLowerCase())) &&
|
||||
(!("selfHostedOnly" in c) || !c.selfHostedOnly || selfHosted)
|
||||
(c) => matchesSearch(c.title, c.description) && passesDeploymentFilter(c)
|
||||
);
|
||||
|
||||
const filteredOther = OTHER_CONNECTORS.filter(
|
||||
(c) =>
|
||||
(c.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
c.description.toLowerCase().includes(searchQuery.toLowerCase())) &&
|
||||
(!("selfHostedOnly" in c) || !c.selfHostedOnly || selfHosted)
|
||||
(c) => matchesSearch(c.title, c.description) && passesDeploymentFilter(c)
|
||||
);
|
||||
|
||||
// Filter Composio connectors
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export enum EnumConnectorName {
|
|||
YOUTUBE_CONNECTOR = "YOUTUBE_CONNECTOR",
|
||||
CIRCLEBACK_CONNECTOR = "CIRCLEBACK_CONNECTOR",
|
||||
OBSIDIAN_CONNECTOR = "OBSIDIAN_CONNECTOR",
|
||||
LOCAL_FOLDER_CONNECTOR = "LOCAL_FOLDER_CONNECTOR",
|
||||
DROPBOX_CONNECTOR = "DROPBOX_CONNECTOR",
|
||||
MCP_CONNECTOR = "MCP_CONNECTOR",
|
||||
COMPOSIO_GOOGLE_DRIVE_CONNECTOR = "COMPOSIO_GOOGLE_DRIVE_CONNECTOR",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
BookOpen,
|
||||
File,
|
||||
FileText,
|
||||
FolderSync,
|
||||
Globe,
|
||||
Microscope,
|
||||
Search,
|
||||
|
|
@ -75,6 +76,8 @@ export const getConnectorIcon = (connectorType: EnumConnectorName | string, clas
|
|||
return <Image src="/connectors/circleback.svg" alt="Circleback" {...imgProps} />;
|
||||
case EnumConnectorName.MCP_CONNECTOR:
|
||||
return <Image src="/connectors/modelcontextprotocol.svg" alt="MCP" {...imgProps} />;
|
||||
case EnumConnectorName.LOCAL_FOLDER_CONNECTOR:
|
||||
return <FolderSync {...iconProps} />;
|
||||
case EnumConnectorName.OBSIDIAN_CONNECTOR:
|
||||
return <Image src="/connectors/obsidian.svg" alt="Obsidian" {...imgProps} />;
|
||||
case EnumConnectorName.COMPOSIO_GOOGLE_DRIVE_CONNECTOR:
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export const searchSourceConnectorTypeEnum = z.enum([
|
|||
"DROPBOX_CONNECTOR",
|
||||
"MCP_CONNECTOR",
|
||||
"OBSIDIAN_CONNECTOR",
|
||||
"LOCAL_FOLDER_CONNECTOR",
|
||||
"COMPOSIO_GOOGLE_DRIVE_CONNECTOR",
|
||||
"COMPOSIO_GMAIL_CONNECTOR",
|
||||
"COMPOSIO_GOOGLE_CALENDAR_CONNECTOR",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue