@@ -55,9 +55,14 @@ import GoogleDriveIcon from "../../components/icons/google-drive-logo";
5555import IBMCOSIcon from "../../components/icons/ibm-cos-icon" ;
5656import OneDriveIcon from "../../components/icons/one-drive-logo" ;
5757import SharePointIcon from "../../components/icons/share-point-logo" ;
58+ import { SyncConfirmDialog } from "../../components/sync-confirm-dialog" ;
5859import { useDeleteDocument } from "../api/mutations/useDeleteDocument" ;
5960import { useRefreshOpenragDocs } from "../api/mutations/useRefreshOpenragDocs" ;
60- import { useSyncAllConnectors } from "../api/mutations/useSyncConnector" ;
61+ import {
62+ type SyncAllPreviewResponse ,
63+ useSyncAllConnectors ,
64+ useSyncAllConnectorsPreview ,
65+ } from "../api/mutations/useSyncConnector" ;
6166
6267/** List-files uses term filters; "*" means "any" in the UI — do not send it literally. */
6368function listFilesFilterParam ( values ?: string [ ] ) : string | undefined {
@@ -119,7 +124,51 @@ function SearchPage() {
119124
120125 const deleteDocumentMutation = useDeleteDocument ( ) ;
121126 const syncAllConnectorsMutation = useSyncAllConnectors ( ) ;
127+ const syncAllPreviewMutation = useSyncAllConnectorsPreview ( ) ;
122128 const refreshOpenragDocsMutation = useRefreshOpenragDocs ( ) ;
129+ const [ syncDialogOpen , setSyncDialogOpen ] = useState ( false ) ;
130+ const [ syncPreview , setSyncPreview ] = useState < SyncAllPreviewResponse | null > (
131+ null ,
132+ ) ;
133+
134+ const handleOpenSyncDialog = useCallback ( async ( ) => {
135+ setSyncPreview ( null ) ;
136+ setSyncDialogOpen ( true ) ;
137+ try {
138+ const preview = await syncAllPreviewMutation . mutateAsync ( ) ;
139+ setSyncPreview ( preview ) ;
140+ } catch ( error ) {
141+ setSyncDialogOpen ( false ) ;
142+ toast . error (
143+ error instanceof Error ? error . message : "Failed to preview sync" ,
144+ ) ;
145+ }
146+ } , [ syncAllPreviewMutation ] ) ;
147+
148+ const handleConfirmSync = useCallback ( async ( ) => {
149+ try {
150+ const result = await syncAllConnectorsMutation . mutateAsync ( ) ;
151+ if ( result . status === "no_files" ) {
152+ toast . info (
153+ result . message ||
154+ "No cloud files to sync. Add files from cloud connectors first." ,
155+ ) ;
156+ } else if (
157+ result . synced_connectors &&
158+ result . synced_connectors . length > 0
159+ ) {
160+ toast . success (
161+ `Sync started for ${ result . synced_connectors . join ( ", " ) } . Check task notifications for progress.` ,
162+ ) ;
163+ } else if ( result . errors && result . errors . length > 0 ) {
164+ toast . error ( "Some connectors failed to sync" ) ;
165+ }
166+ } catch ( error ) {
167+ toast . error (
168+ error instanceof Error ? error . message : "Failed to sync connectors" ,
169+ ) ;
170+ }
171+ } , [ syncAllConnectorsMutation ] ) ;
123172
124173 useEffect ( ( ) => {
125174 refreshTasks ( ) ;
@@ -761,36 +810,14 @@ function SearchPage() {
761810 type = "button"
762811 variant = "outline"
763812 className = "rounded-lg flex-shrink-0"
764- disabled = { syncAllConnectorsMutation . isPending }
765- onClick = { async ( ) => {
766- try {
767- toast . info ( "Syncing all cloud connectors..." ) ;
768- const result = await syncAllConnectorsMutation . mutateAsync ( ) ;
769- if ( result . status === "no_files" ) {
770- toast . info (
771- result . message ||
772- "No cloud files to sync. Add files from cloud connectors first." ,
773- ) ;
774- } else if (
775- result . synced_connectors &&
776- result . synced_connectors . length > 0
777- ) {
778- toast . success (
779- `Sync started for ${ result . synced_connectors . join ( ", " ) } . Check task notifications for progress.` ,
780- ) ;
781- } else if ( result . errors && result . errors . length > 0 ) {
782- toast . error ( "Some connectors failed to sync" ) ;
783- }
784- } catch ( error ) {
785- toast . error (
786- error instanceof Error
787- ? error . message
788- : "Failed to sync connectors" ,
789- ) ;
790- }
791- } }
813+ disabled = {
814+ syncAllConnectorsMutation . isPending ||
815+ syncAllPreviewMutation . isPending
816+ }
817+ onClick = { handleOpenSyncDialog }
792818 >
793- { syncAllConnectorsMutation . isPending ? (
819+ { syncAllConnectorsMutation . isPending ||
820+ syncAllPreviewMutation . isPending ? (
794821 < >
795822 < RefreshCw className = "h-4 w-4 mr-2 animate-spin" />
796823 Syncing...
@@ -961,6 +988,18 @@ function SearchPage() {
961988 < p className = "my-2" > Documents to be deleted:</ p >
962989 { formatFilesToDelete ( selectedRows ) }
963990 </ DeleteConfirmationDialog >
991+
992+ < SyncConfirmDialog
993+ open = { syncDialogOpen }
994+ onOpenChange = { setSyncDialogOpen }
995+ onConfirm = { handleConfirmSync }
996+ isLoading = { syncAllPreviewMutation . isPending || syncPreview === null }
997+ isSyncing = { syncAllConnectorsMutation . isPending }
998+ isSyncAll
999+ orphansByType = { syncPreview ?. orphans_by_type }
1000+ orphansAvailableByType = { syncPreview ?. orphans_available_by_type }
1001+ syncedCountByType = { syncPreview ?. synced_count_by_type }
1002+ />
9641003 </ >
9651004 ) ;
9661005}
0 commit comments