mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-11 08:42:39 +02:00
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:
parent
a3112a24fe
commit
7af3d1bc1a
6 changed files with 74 additions and 13 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -219,12 +219,25 @@ export const ConnectorEditView: FC<ConnectorEditViewProps> = ({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Periodic sync - shown for all indexable connectors */}
|
{/* Periodic sync - shown for all indexable connectors */}
|
||||||
<PeriodicSyncConfig
|
{(() => {
|
||||||
enabled={periodicEnabled}
|
// Check if Google Drive has folders/files selected
|
||||||
frequencyMinutes={frequencyMinutes}
|
const isGoogleDrive = connector.connector_type === "GOOGLE_DRIVE_CONNECTOR";
|
||||||
onEnabledChange={onPeriodicEnabledChange}
|
const selectedFolders = (connector.config?.selected_folders as Array<{ id: string; name: string }> | undefined) || [];
|
||||||
onFrequencyChange={onFrequencyChange}
|
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
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue