@@ -73,13 +73,26 @@ export function ConnectorsSection({
7373 isLoading,
7474 canEdit,
7575} : ConnectorsSectionProps ) {
76- const { mutate : triggerSync , isPending : isSyncing } = useTriggerSync ( )
77- const { mutate : updateConnector , isPending : isUpdating } = useUpdateConnector ( )
76+ const { mutate : triggerSync } = useTriggerSync ( )
77+ const { mutate : updateConnector } = useUpdateConnector ( )
7878 const { mutate : deleteConnector , isPending : isDeleting } = useDeleteConnector ( )
7979 const [ deleteTarget , setDeleteTarget ] = useState < string | null > ( null )
8080 const [ editingConnector , setEditingConnector ] = useState < ConnectorData | null > ( null )
8181 const [ error , setError ] = useState < string | null > ( null )
82- const [ syncingConnectorId , setSyncingConnectorId ] = useState < string | null > ( null )
82+ const [ syncingIds , setSyncingIds ] = useState < Set < string > > ( ( ) => new Set ( ) )
83+ const [ updatingIds , setUpdatingIds ] = useState < Set < string > > ( ( ) => new Set ( ) )
84+
85+ const addToSet = useCallback ( ( setter : typeof setSyncingIds , id : string ) => {
86+ setter ( ( prev ) => new Set ( prev ) . add ( id ) )
87+ } , [ ] )
88+
89+ const removeFromSet = useCallback ( ( setter : typeof setSyncingIds , id : string ) => {
90+ setter ( ( prev ) => {
91+ const next = new Set ( prev )
92+ next . delete ( id )
93+ return next
94+ } )
95+ } , [ ] )
8396
8497 const syncTriggeredAt = useRef < Record < string , number > > ( { } )
8598 const cooldownTimers = useRef < Set < ReturnType < typeof setTimeout > > > ( new Set ( ) )
@@ -104,14 +117,13 @@ export function ConnectorsSection({
104117 if ( isSyncOnCooldown ( connectorId ) ) return
105118
106119 syncTriggeredAt . current [ connectorId ] = Date . now ( )
107- setSyncingConnectorId ( connectorId )
120+ addToSet ( setSyncingIds , connectorId )
108121
109122 triggerSync (
110123 { knowledgeBaseId, connectorId } ,
111124 {
112125 onSuccess : ( ) => {
113126 setError ( null )
114- setSyncingConnectorId ( null )
115127 const timer = setTimeout ( ( ) => {
116128 cooldownTimers . current . delete ( timer )
117129 forceUpdate ( ( n ) => n + 1 )
@@ -121,14 +133,38 @@ export function ConnectorsSection({
121133 onError : ( err ) => {
122134 logger . error ( 'Sync trigger failed' , { error : err . message } )
123135 setError ( err . message )
124- setSyncingConnectorId ( null )
125136 delete syncTriggeredAt . current [ connectorId ]
126137 forceUpdate ( ( n ) => n + 1 )
127138 } ,
139+ onSettled : ( ) => removeFromSet ( setSyncingIds , connectorId ) ,
140+ }
141+ )
142+ } ,
143+ [ knowledgeBaseId , triggerSync , isSyncOnCooldown , addToSet , removeFromSet ]
144+ )
145+
146+ const handleTogglePause = useCallback (
147+ ( connector : ConnectorData ) => {
148+ addToSet ( setUpdatingIds , connector . id )
149+ updateConnector (
150+ {
151+ knowledgeBaseId,
152+ connectorId : connector . id ,
153+ updates : {
154+ status : connector . status === 'paused' ? 'active' : 'paused' ,
155+ } ,
156+ } ,
157+ {
158+ onSettled : ( ) => removeFromSet ( setUpdatingIds , connector . id ) ,
159+ onSuccess : ( ) => setError ( null ) ,
160+ onError : ( err ) => {
161+ logger . error ( 'Toggle pause failed' , { error : err . message } )
162+ setError ( err . message )
163+ } ,
128164 }
129165 )
130166 } ,
131- [ knowledgeBaseId , triggerSync , isSyncOnCooldown ]
167+ [ knowledgeBaseId , updateConnector , addToSet , removeFromSet ]
132168 )
133169
134170 if ( connectors . length === 0 && ! canEdit && ! isLoading ) return null
@@ -167,29 +203,11 @@ export function ConnectorsSection({
167203 workspaceId = { workspaceId }
168204 knowledgeBaseId = { knowledgeBaseId }
169205 canEdit = { canEdit }
170- isSyncing = { isSyncing }
171- isSyncPending = { syncingConnectorId === connector . id }
172- isUpdating = { isUpdating }
206+ isSyncPending = { syncingIds . has ( connector . id ) }
207+ isUpdating = { updatingIds . has ( connector . id ) }
173208 syncCooldown = { isSyncOnCooldown ( connector . id ) }
174209 onSync = { ( ) => handleSync ( connector . id ) }
175- onTogglePause = { ( ) =>
176- updateConnector (
177- {
178- knowledgeBaseId,
179- connectorId : connector . id ,
180- updates : {
181- status : connector . status === 'paused' ? 'active' : 'paused' ,
182- } ,
183- } ,
184- {
185- onSuccess : ( ) => setError ( null ) ,
186- onError : ( err ) => {
187- logger . error ( 'Toggle pause failed' , { error : err . message } )
188- setError ( err . message )
189- } ,
190- }
191- )
192- }
210+ onTogglePause = { ( ) => handleTogglePause ( connector ) }
193211 onEdit = { ( ) => setEditingConnector ( connector ) }
194212 onDelete = { ( ) => setDeleteTarget ( connector . id ) }
195213 />
@@ -260,7 +278,6 @@ interface ConnectorCardProps {
260278 workspaceId : string
261279 knowledgeBaseId : string
262280 canEdit : boolean
263- isSyncing : boolean
264281 isSyncPending : boolean
265282 isUpdating : boolean
266283 syncCooldown : boolean
@@ -275,7 +292,6 @@ function ConnectorCard({
275292 workspaceId,
276293 knowledgeBaseId,
277294 canEdit,
278- isSyncing,
279295 isSyncPending,
280296 isUpdating,
281297 syncCooldown,
@@ -368,7 +384,7 @@ function ConnectorCard({
368384 variant = 'ghost'
369385 className = 'h-7 w-7 p-0'
370386 onClick = { onSync }
371- disabled = { connector . status === 'syncing' || isSyncing || syncCooldown }
387+ disabled = { connector . status === 'syncing' || isSyncPending || syncCooldown }
372388 >
373389 < RefreshCw
374390 className = { cn (
0 commit comments