From 68cb5be979fa2d00042cc8e908615c069235b50d Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 18:37:57 -0400 Subject: [PATCH 1/3] fix: update bucket ingestion messages for clarity and consistency --- .../_components/ibm-cos-settings-dialog.tsx | 4 +-- .../_components/ibm-cos-settings-form.tsx | 4 +-- .../_components/s3-settings-dialog.tsx | 4 +-- .../settings/_components/s3-settings-form.tsx | 4 +-- frontend/app/upload/[provider]/page.tsx | 27 ++++++++++++++++++- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/frontend/app/settings/_components/ibm-cos-settings-dialog.tsx b/frontend/app/settings/_components/ibm-cos-settings-dialog.tsx index fcae96f5d..94a17320e 100644 --- a/frontend/app/settings/_components/ibm-cos-settings-dialog.tsx +++ b/frontend/app/settings/_components/ibm-cos-settings-dialog.tsx @@ -139,8 +139,8 @@ export default function IBMCOSSettingsDialog({ toast.success("IBM Cloud Object Storage configured", { description: selectedBuckets.length > 0 - ? `Will ingest from: ${selectedBuckets.join(", ")}` - : "Will auto-discover and ingest all accessible buckets.", + ? `Filtered to: ${selectedBuckets.join(", ")}` + : "All accessible buckets are included.", icon: , }); diff --git a/frontend/app/settings/_components/ibm-cos-settings-form.tsx b/frontend/app/settings/_components/ibm-cos-settings-form.tsx index 179e4de76..71b60e7ff 100644 --- a/frontend/app/settings/_components/ibm-cos-settings-form.tsx +++ b/frontend/app/settings/_components/ibm-cos-settings-form.tsx @@ -275,9 +275,9 @@ export function IBMCOSSettingsForm({
{buckets.length > 1 && ( diff --git a/frontend/app/settings/_components/s3-settings-dialog.tsx b/frontend/app/settings/_components/s3-settings-dialog.tsx index 942dcbdd0..5172be890 100644 --- a/frontend/app/settings/_components/s3-settings-dialog.tsx +++ b/frontend/app/settings/_components/s3-settings-dialog.tsx @@ -130,8 +130,8 @@ export default function S3SettingsDialog({ toast.success("Amazon S3 configured", { description: selectedBuckets.length > 0 - ? `Will ingest from: ${selectedBuckets.join(", ")}` - : "Will auto-discover and ingest all accessible buckets.", + ? `Filtered to: ${selectedBuckets.join(", ")}` + : "All accessible buckets are included.", icon: , }); diff --git a/frontend/app/settings/_components/s3-settings-form.tsx b/frontend/app/settings/_components/s3-settings-form.tsx index 523e8cf64..f8696a3f6 100644 --- a/frontend/app/settings/_components/s3-settings-form.tsx +++ b/frontend/app/settings/_components/s3-settings-form.tsx @@ -170,9 +170,9 @@ export function S3SettingsForm({
{buckets.length > 1 && ( diff --git a/frontend/app/upload/[provider]/page.tsx b/frontend/app/upload/[provider]/page.tsx index c964fef9c..1087ecac5 100644 --- a/frontend/app/upload/[provider]/page.tsx +++ b/frontend/app/upload/[provider]/page.tsx @@ -9,13 +9,15 @@ import { RefreshCw, } from "lucide-react"; import { useParams, useRouter } from "next/navigation"; -import { useRef, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { toast } from "sonner"; import { useSyncConnector } from "@/app/api/mutations/useSyncConnector"; import { useGetConnectorsQuery } from "@/app/api/queries/useGetConnectorsQuery"; import { useGetConnectorTokenQuery } from "@/app/api/queries/useGetConnectorTokenQuery"; import { useIBMCOSBucketStatusQuery } from "@/app/api/queries/useIBMCOSBucketStatusQuery"; +import { useIBMCOSDefaultsQuery } from "@/app/api/queries/useIBMCOSDefaultsQuery"; import { useS3BucketStatusQuery } from "@/app/api/queries/useS3BucketStatusQuery"; +import { useS3DefaultsQuery } from "@/app/api/queries/useS3DefaultsQuery"; import { type CloudFile, UnifiedCloudPicker } from "@/components/cloud-picker"; import { IngestSettings } from "@/components/cloud-picker/ingest-settings"; import { getIngestChunkSettingsError } from "@/components/cloud-picker/types"; @@ -49,6 +51,7 @@ function BucketView({ addTask, onBack, onDone, + initialSelectedBuckets, }: { connector: any; buckets: Array<{ name: string; ingested_count: number }> | undefined; @@ -60,17 +63,35 @@ function BucketView({ addTask: (id: string) => void; onBack: () => void; onDone: () => void; + initialSelectedBuckets?: string[]; }) { const queryClient = useQueryClient(); const [selectedBuckets, setSelectedBuckets] = useState>( new Set(), ); + const hasAppliedInitial = useRef(false); const [ingestSettings, setIngestSettings] = useSessionIngestSettings(); const [isSettingsOpen, setIsSettingsOpen] = useState(false); const [browseDialogBucket, setBrowseDialogBucket] = useState( null, ); + useEffect(() => { + if ( + !hasAppliedInitial.current && + buckets?.length && + initialSelectedBuckets?.length + ) { + const valid = initialSelectedBuckets.filter((name) => + buckets.some((b) => b.name === name), + ); + if (valid.length) { + setSelectedBuckets(new Set(valid)); + hasAppliedInitial.current = true; + } + } + }, [buckets, initialSelectedBuckets]); + const invalidate = () => { queryClient.invalidateQueries({ queryKey: invalidateQueryKey }); }; @@ -318,6 +339,7 @@ function IBMCOSBucketView({ isLoading, refetch, } = useIBMCOSBucketStatusQuery(connector.connectionId, { enabled: true }); + const { data: defaults } = useIBMCOSDefaultsQuery({ enabled: true }); return ( ); } @@ -356,6 +379,7 @@ function S3BucketView({ error: bucketsError, refetch, } = useS3BucketStatusQuery(connector.connectionId, { enabled: true }); + const { data: defaults } = useS3DefaultsQuery({ enabled: true }); return ( ); } From f94136d3133be6cd81b62173c3335b1a9db30958 Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 19:16:12 -0400 Subject: [PATCH 2/3] fix: guard bucket pre-selection against connection ID mismatch The defaults query returns the first S3/COS connection regardless of active status. Only pre-select saved bucket_names when the defaults connection_id matches the current connector.connectionId to avoid seeding the wrong buckets if a stale connection exists alongside the active one. Co-Authored-By: Claude Sonnet 4.6 --- frontend/app/upload/[provider]/page.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/app/upload/[provider]/page.tsx b/frontend/app/upload/[provider]/page.tsx index 1087ecac5..805312e62 100644 --- a/frontend/app/upload/[provider]/page.tsx +++ b/frontend/app/upload/[provider]/page.tsx @@ -351,7 +351,11 @@ function IBMCOSBucketView({ addTask={addTask} onBack={onBack} onDone={onDone} - initialSelectedBuckets={defaults?.bucket_names} + initialSelectedBuckets={ + defaults?.connection_id === connector.connectionId + ? defaults?.bucket_names + : undefined + } /> ); } @@ -392,7 +396,11 @@ function S3BucketView({ addTask={addTask} onBack={onBack} onDone={onDone} - initialSelectedBuckets={defaults?.bucket_names} + initialSelectedBuckets={ + defaults?.connection_id === connector.connectionId + ? defaults?.bucket_names + : undefined + } /> ); } From 4837f8b10636cae9ba9ed9c0cde79868b91af736 Mon Sep 17 00:00:00 2001 From: Rico Furtado Date: Mon, 22 Jun 2026 20:32:56 -0400 Subject: [PATCH 3/3] fix: prevent defaults from overwriting user bucket selections Two issues in the initial-selection effect: 1. hasAppliedInitial was only set when valid buckets were found, leaving the effect live across bucket refreshes and allowing stale defaults to overwrite selections made after a refetch. 2. No guard against the async race where buckets loads before initialSelectedBuckets: user clicks buckets, defaults arrive later and silently overwrite them. Fix: mark hasAppliedInitial unconditionally on first evaluation, and only apply defaults when selectedBuckets is still empty (user hasn't acted yet). Co-Authored-By: Claude Sonnet 4.6 --- frontend/app/upload/[provider]/page.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/app/upload/[provider]/page.tsx b/frontend/app/upload/[provider]/page.tsx index 805312e62..e36575d2a 100644 --- a/frontend/app/upload/[provider]/page.tsx +++ b/frontend/app/upload/[provider]/page.tsx @@ -82,15 +82,17 @@ function BucketView({ buckets?.length && initialSelectedBuckets?.length ) { - const valid = initialSelectedBuckets.filter((name) => - buckets.some((b) => b.name === name), - ); - if (valid.length) { - setSelectedBuckets(new Set(valid)); - hasAppliedInitial.current = true; + hasAppliedInitial.current = true; + if (selectedBuckets.size === 0) { + const valid = initialSelectedBuckets.filter((name) => + buckets.some((b) => b.name === name), + ); + if (valid.length) { + setSelectedBuckets(new Set(valid)); + } } } - }, [buckets, initialSelectedBuckets]); + }, [buckets, initialSelectedBuckets]); // eslint-disable-line react-hooks/exhaustive-deps const invalidate = () => { queryClient.invalidateQueries({ queryKey: invalidateQueryKey });