feat: improve Google Drive connector handling and UI feedback

- Added logic to refresh connector and notification attributes after indexing to ensure up-to-date information.
- Enhanced periodic sync configuration to disable the option when no folders or files are selected for Google Drive, providing user feedback through a message.
- Updated the connector edit view to reflect the new disabled state for periodic sync based on selected items.
- Implemented validation in the connector dialog to prevent enabling periodic sync without selected items, improving user experience.
This commit is contained in:
Anish Sarkar 2026-01-17 12:59:18 +05:30
parent a3112a24fe
commit 7af3d1bc1a
6 changed files with 74 additions and 13 deletions

View file

@ -1840,6 +1840,8 @@ async def run_google_drive_indexing(
# Update notification on completion # Update notification on completion
if notification: if notification:
# Refresh notification to reload attributes that may have been expired by earlier commits
await session.refresh(notification)
await NotificationService.connector_indexing.notify_indexing_completed( await NotificationService.connector_indexing.notify_indexing_completed(
session=session, session=session,
notification=notification, notification=notification,

View file

@ -111,10 +111,10 @@ async def _check_and_trigger_schedules():
# Special handling for Google Drive - uses config for folder/file selection # Special handling for Google Drive - uses config for folder/file selection
if connector.connector_type == SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR: if connector.connector_type == SearchSourceConnectorType.GOOGLE_DRIVE_CONNECTOR:
config = connector.config or {} connector_config = connector.config or {}
selected_folders = config.get("selected_folders", []) selected_folders = connector_config.get("selected_folders", [])
selected_files = config.get("selected_files", []) selected_files = connector_config.get("selected_files", [])
indexing_options = config.get("indexing_options", { indexing_options = connector_config.get("indexing_options", {
"max_files_per_folder": 100, "max_files_per_folder": 100,
"incremental_sync": True, "incremental_sync": True,
"include_subfolders": True, "include_subfolders": True,
@ -132,9 +132,17 @@ async def _check_and_trigger_schedules():
}, },
) )
else: else:
logger.warning( # No folders/files selected - skip indexing but still update next_scheduled_at
f"Google Drive connector {connector.id} has no folders or files selected, skipping periodic indexing" # to prevent checking every minute
logger.info(
f"Google Drive connector {connector.id} has no folders or files selected, "
"skipping periodic indexing (will check again at next scheduled time)"
) )
from datetime import timedelta
connector.next_scheduled_at = now + timedelta(
minutes=connector.indexing_frequency_minutes
)
await session.commit()
continue continue
else: else:
task.delay( task.delay(

View file

@ -172,6 +172,9 @@ async def index_google_drive_files(
if new_token and not token_error: if new_token and not token_error:
from sqlalchemy.orm.attributes import flag_modified from sqlalchemy.orm.attributes import flag_modified
# Refresh connector to reload attributes that may have been expired by earlier commits
await session.refresh(connector)
if "folder_tokens" not in connector.config: if "folder_tokens" not in connector.config:
connector.config["folder_tokens"] = {} connector.config["folder_tokens"] = {}
connector.config["folder_tokens"][target_folder_id] = new_token connector.config["folder_tokens"][target_folder_id] = new_token

View file

@ -1,6 +1,7 @@
"use client"; "use client";
import type { FC } from "react"; import type { FC } from "react";
import { AlertCircle } from "lucide-react";
import { Label } from "@/components/ui/label"; import { Label } from "@/components/ui/label";
import { import {
Select, Select,
@ -16,6 +17,8 @@ interface PeriodicSyncConfigProps {
frequencyMinutes: string; frequencyMinutes: string;
onEnabledChange: (enabled: boolean) => void; onEnabledChange: (enabled: boolean) => void;
onFrequencyChange: (frequency: string) => void; onFrequencyChange: (frequency: string) => void;
disabled?: boolean;
disabledMessage?: string;
} }
export const PeriodicSyncConfig: FC<PeriodicSyncConfigProps> = ({ export const PeriodicSyncConfig: FC<PeriodicSyncConfigProps> = ({
@ -23,6 +26,8 @@ export const PeriodicSyncConfig: FC<PeriodicSyncConfigProps> = ({
frequencyMinutes, frequencyMinutes,
onEnabledChange, onEnabledChange,
onFrequencyChange, onFrequencyChange,
disabled = false,
disabledMessage,
}) => { }) => {
return ( return (
<div className="rounded-xl bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6"> <div className="rounded-xl bg-slate-400/5 dark:bg-white/5 p-3 sm:p-6">
@ -33,9 +38,21 @@ export const PeriodicSyncConfig: FC<PeriodicSyncConfigProps> = ({
Automatically re-index at regular intervals Automatically re-index at regular intervals
</p> </p>
</div> </div>
<Switch checked={enabled} onCheckedChange={onEnabledChange} /> <Switch
checked={enabled}
onCheckedChange={onEnabledChange}
disabled={disabled}
/>
</div> </div>
{/* Show disabled message when periodic sync can't be enabled */}
{disabled && disabledMessage && (
<div className="mt-3 flex items-start gap-2 text-amber-600 dark:text-amber-400">
<AlertCircle className="size-4 mt-0.5 shrink-0" />
<p className="text-xs sm:text-sm">{disabledMessage}</p>
</div>
)}
{enabled && ( {enabled && (
<div className="mt-4 pt-4 border-t border-slate-400/20 space-y-3"> <div className="mt-4 pt-4 border-t border-slate-400/20 space-y-3">
<div className="space-y-2"> <div className="space-y-2">

View file

@ -219,12 +219,25 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
)} )}
{/* Periodic sync - shown for all indexable connectors */} {/* Periodic sync - shown for all indexable connectors */}
{(() => {
// Check if Google Drive has folders/files selected
const isGoogleDrive = connector.connector_type === "GOOGLE_DRIVE_CONNECTOR";
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 = isGoogleDrive && !hasItemsSelected;
return (
<PeriodicSyncConfig <PeriodicSyncConfig
enabled={periodicEnabled} enabled={periodicEnabled}
frequencyMinutes={frequencyMinutes} frequencyMinutes={frequencyMinutes}
onEnabledChange={onPeriodicEnabledChange} onEnabledChange={onPeriodicEnabledChange}
onFrequencyChange={onFrequencyChange} onFrequencyChange={onFrequencyChange}
disabled={isDisabled}
disabledMessage={isDisabled ? "Select at least one folder or file above to enable periodic sync" : undefined}
/> />
);
})()}
</> </>
)} )}

View file

@ -1038,6 +1038,24 @@ export const useConnectorDialog = () => {
return; return;
} }
// Prevent periodic indexing for Google Drive without folders/files selected
if (periodicEnabled && editingConnector.connector_type === "GOOGLE_DRIVE_CONNECTOR") {
const selectedFolders = (connectorConfig || editingConnector.config)?.selected_folders as
| Array<{ id: string; name: string }>
| undefined;
const selectedFiles = (connectorConfig || editingConnector.config)?.selected_files as
| Array<{ id: string; name: string }>
| undefined;
const hasItemsSelected =
(selectedFolders && selectedFolders.length > 0) ||
(selectedFiles && selectedFiles.length > 0);
if (!hasItemsSelected) {
toast.error("Select at least one folder or file to enable periodic sync");
return;
}
}
// Validate frequency minutes if periodic is enabled (only for indexable connectors) // Validate frequency minutes if periodic is enabled (only for indexable connectors)
if (periodicEnabled && editingConnector.is_indexable) { if (periodicEnabled && editingConnector.is_indexable) {
const frequencyValidation = frequencyMinutesSchema.safeParse(frequencyMinutes); const frequencyValidation = frequencyMinutesSchema.safeParse(frequencyMinutes);