feat: enhance Google Drive connector functionality and UI

- Added support for selecting both folders and files in the Google Drive connector configuration.
- Updated the UI to reflect the selection of files alongside folders, improving user clarity.
- Introduced a quick indexing feature for connectors, allowing users to start indexing without date selection.
- Adjusted periodic sync settings to be disabled for Google Drive connectors, ensuring proper functionality.
- Improved styling and accessibility across various components in the connector popup.
This commit is contained in:
Anish Sarkar 2026-01-01 21:22:34 +05:30
parent 543daa0434
commit b909032e32
7 changed files with 160 additions and 68 deletions

View file

@ -17,15 +17,19 @@ export const GoogleDriveConfig: FC<ConnectorConfigProps> = ({
connector,
onConfigChange,
}) => {
// Initialize with existing selected folders from connector config
// Initialize with existing selected folders and files from connector config
const existingFolders = (connector.config?.selected_folders as SelectedFolder[] | undefined) || [];
const existingFiles = (connector.config?.selected_files as SelectedFolder[] | undefined) || [];
const [selectedFolders, setSelectedFolders] = useState<SelectedFolder[]>(existingFolders);
const [selectedFiles, setSelectedFiles] = useState<SelectedFolder[]>(existingFiles);
const [showFolderSelector, setShowFolderSelector] = useState(false);
// Update selected folders when connector config changes
// Update selected folders and files when connector config changes
useEffect(() => {
const folders = (connector.config?.selected_folders as SelectedFolder[] | undefined) || [];
const files = (connector.config?.selected_files as SelectedFolder[] | undefined) || [];
setSelectedFolders(folders);
setSelectedFiles(files);
}, [connector.config]);
const handleSelectFolders = (folders: SelectedFolder[]) => {
@ -35,28 +39,50 @@ export const GoogleDriveConfig: FC<ConnectorConfigProps> = ({
onConfigChange({
...connector.config,
selected_folders: folders,
selected_files: selectedFiles, // Preserve existing files
});
}
};
const handleSelectFiles = (files: SelectedFolder[]) => {
setSelectedFiles(files);
if (onConfigChange) {
// Store file IDs and names in config for indexing
onConfigChange({
...connector.config,
selected_folders: selectedFolders, // Preserve existing folders
selected_files: files,
});
}
};
const totalSelected = selectedFolders.length + selectedFiles.length;
return (
<div className="rounded-xl border border-border bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6 space-y-3 sm:space-y-4">
<div className="space-y-1 sm:space-y-2">
<h3 className="font-medium text-sm sm:text-base">Folder Selection</h3>
<h3 className="font-medium text-sm sm:text-base">Folder & File Selection</h3>
<p className="text-xs sm:text-sm text-muted-foreground">
Select specific folders to index. Only files directly in each folder will be processedsubfolders must be selected separately.
Select specific folders and/or individual files to index. Only files directly in each folder will be processedsubfolders must be selected separately.
</p>
</div>
{selectedFolders.length > 0 && (
{totalSelected > 0 && (
<div className="p-2 sm:p-3 bg-muted rounded-lg text-xs sm:text-sm space-y-1 sm:space-y-2">
<p className="font-medium">
Selected {selectedFolders.length} folder{selectedFolders.length > 1 ? "s" : ""}:
Selected {totalSelected} item{totalSelected > 1 ? "s" : ""}:
{selectedFolders.length > 0 && ` ${selectedFolders.length} folder${selectedFolders.length > 1 ? "s" : ""}`}
{selectedFiles.length > 0 && ` ${selectedFiles.length} file${selectedFiles.length > 1 ? "s" : ""}`}
</p>
<div className="max-h-20 sm:max-h-24 overflow-y-auto">
<div className="max-h-20 sm:max-h-24 overflow-y-auto space-y-1">
{selectedFolders.map((folder) => (
<p key={folder.id} className="text-xs sm:text-sm text-muted-foreground truncate" title={folder.name}>
{folder.name}
📁 {folder.name}
</p>
))}
{selectedFiles.map((file) => (
<p key={file.id} className="text-xs sm:text-sm text-muted-foreground truncate" title={file.name}>
📄 {file.name}
</p>
))}
</div>
@ -69,6 +95,8 @@ export const GoogleDriveConfig: FC<ConnectorConfigProps> = ({
connectorId={connector.id}
selectedFolders={selectedFolders}
onSelectFolders={handleSelectFolders}
selectedFiles={selectedFiles}
onSelectFiles={handleSelectFiles}
/>
<Button
type="button"
@ -87,14 +115,14 @@ export const GoogleDriveConfig: FC<ConnectorConfigProps> = ({
onClick={() => setShowFolderSelector(true)}
className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 hover:bg-slate-400/10 dark:hover:bg-white/10 text-xs sm:text-sm h-8 sm:h-9"
>
{selectedFolders.length > 0 ? "Change Folder Selection" : "Select Folders"}
{totalSelected > 0 ? "Change Selection" : "Select Folders & Files"}
</Button>
)}
<Alert className="bg-slate-400/5 dark:bg-white/5 border-slate-400/20 p-2 sm:p-3 flex items-center gap-2 [&>svg]:relative [&>svg]:left-0 [&>svg]:top-0 [&>svg+div]:translate-y-0">
<Info className="h-3 w-3 sm:h-4 sm:w-4 shrink-0" />
<AlertDescription className="text-[10px] sm:text-xs !pl-0">
Folder selection is used when indexing. You can change this selection when you start indexing.
Folder and file selection is used when indexing. You can change this selection when you start indexing.
</AlertDescription>
</Alert>
</div>

View file

@ -1,6 +1,6 @@
"use client";
import { ArrowLeft, Info, Loader2, Trash2 } from "lucide-react";
import { ArrowLeft, Info, Loader2, RefreshCw, Trash2 } from "lucide-react";
import { type FC, useState, useCallback, useRef, useEffect, useMemo } from "react";
import { Button } from "@/components/ui/button";
import { getConnectorIcon } from "@/contracts/enums/connectorIcons";
@ -18,6 +18,7 @@ interface ConnectorEditViewProps {
frequencyMinutes: string;
isSaving: boolean;
isDisconnecting: boolean;
isIndexing?: boolean;
onStartDateChange: (date: Date | undefined) => void;
onEndDateChange: (date: Date | undefined) => void;
onPeriodicEnabledChange: (enabled: boolean) => void;
@ -25,6 +26,7 @@ interface ConnectorEditViewProps {
onSave: () => void;
onDisconnect: () => void;
onBack: () => void;
onQuickIndex?: () => void;
onConfigChange?: (config: Record<string, unknown>) => void;
onNameChange?: (name: string) => void;
}
@ -37,6 +39,7 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
frequencyMinutes,
isSaving,
isDisconnecting,
isIndexing = false,
onStartDateChange,
onEndDateChange,
onPeriodicEnabledChange,
@ -44,6 +47,7 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
onSave,
onDisconnect,
onBack,
onQuickIndex,
onConfigChange,
onNameChange,
}) => {
@ -120,18 +124,42 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
</button>
{/* Connector header */}
<div className="flex items-center gap-4 mb-6">
<div className="flex h-14 w-14 items-center justify-center rounded-xl bg-primary/10 border border-primary/20">
{getConnectorIcon(connector.connector_type, "size-7")}
</div>
<div className="flex-1">
<h2 className="text-xl sm:text-2xl font-semibold tracking-tight">
{connector.name}
</h2>
<p className="text-xs sm:text-base text-muted-foreground mt-1">
Manage your connector settings and sync configuration
</p>
<div className="flex flex-col sm:flex-row items-start sm:items-center gap-4 mb-6">
<div className="flex items-center gap-4 flex-1 w-full sm:w-auto">
<div className="flex h-14 w-14 items-center justify-center rounded-xl bg-primary/10 border border-primary/20 flex-shrink-0">
{getConnectorIcon(connector.connector_type, "size-7")}
</div>
<div className="flex-1 min-w-0">
<h2 className="text-xl sm:text-2xl font-semibold tracking-tight">
{connector.name}
</h2>
<p className="text-xs sm:text-base text-muted-foreground mt-1">
Manage your connector settings and sync configuration
</p>
</div>
</div>
{/* Quick Index Button - only show for indexable connectors, but not for Google Drive (requires folder selection) */}
{connector.is_indexable && onQuickIndex && connector.connector_type !== "GOOGLE_DRIVE_CONNECTOR" && (
<Button
variant="secondary"
size="sm"
onClick={onQuickIndex}
disabled={isIndexing || isSaving || isDisconnecting}
className="text-xs sm:text-sm bg-slate-400/10 dark:bg-white/10 hover:bg-slate-400/20 dark:hover:bg-white/20 border-slate-400/20 dark:border-white/20 w-full sm:w-auto"
>
{isIndexing ? (
<>
<RefreshCw className="mr-2 h-4 w-4 animate-spin" />
Indexing...
</>
) : (
<>
<RefreshCw className="mr-2 h-4 w-4" />
Quick Index
</>
)}
</Button>
)}
</div>
</div>
@ -165,12 +193,15 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
/>
)}
<PeriodicSyncConfig
enabled={periodicEnabled}
frequencyMinutes={frequencyMinutes}
onEnabledChange={onPeriodicEnabledChange}
onFrequencyChange={onFrequencyChange}
/>
{/* Periodic sync - not shown for Google Drive */}
{connector.connector_type !== "GOOGLE_DRIVE_CONNECTOR" && (
<PeriodicSyncConfig
enabled={periodicEnabled}
frequencyMinutes={frequencyMinutes}
onEnabledChange={onPeriodicEnabledChange}
onFrequencyChange={onFrequencyChange}
/>
)}
</>
)}

View file

@ -146,12 +146,15 @@ export const IndexingConfigurationView: FC<IndexingConfigurationViewProps> = ({
/>
)}
<PeriodicSyncConfig
enabled={periodicEnabled}
frequencyMinutes={frequencyMinutes}
onEnabledChange={onPeriodicEnabledChange}
onFrequencyChange={onFrequencyChange}
/>
{/* Periodic sync - not shown for Google Drive */}
{config.connectorType !== "GOOGLE_DRIVE_CONNECTOR" && (
<PeriodicSyncConfig
enabled={periodicEnabled}
frequencyMinutes={frequencyMinutes}
onEnabledChange={onPeriodicEnabledChange}
onFrequencyChange={onFrequencyChange}
/>
)}
</>
)}