@@ -39,7 +39,7 @@ import {
39
39
import { ExternalImage } from "components/ExternalImage/ExternalImage" ;
40
40
import { useAuthenticated } from "hooks" ;
41
41
import { useExternalAuth } from "hooks/useExternalAuth" ;
42
- import { RotateCcwIcon , SendIcon } from "lucide-react" ;
42
+ import { RedoIcon , RotateCcwIcon , SendIcon } from "lucide-react" ;
43
43
import { AI_PROMPT_PARAMETER_NAME , type Task } from "modules/tasks/tasks" ;
44
44
import { WorkspaceAppStatus } from "modules/workspaces/WorkspaceAppStatus/WorkspaceAppStatus" ;
45
45
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName" ;
@@ -51,6 +51,12 @@ import TextareaAutosize from "react-textarea-autosize";
51
51
import { pageTitle } from "utils/page" ;
52
52
import { relativeTime } from "utils/time" ;
53
53
import { type UserOption , UsersCombobox } from "./UsersCombobox" ;
54
+ import {
55
+ Tooltip ,
56
+ TooltipContent ,
57
+ TooltipProvider ,
58
+ TooltipTrigger ,
59
+ } from "components/Tooltip/Tooltip" ;
54
60
55
61
type TasksFilter = {
56
62
user : UserOption | undefined ;
@@ -325,27 +331,55 @@ const ExternalAuthButtons: FC<ExternalAuthButtonProps> = ({
325
331
template,
326
332
missedExternalAuth,
327
333
} ) => {
328
- const { startPollingExternalAuth, isPollingExternalAuth } = useExternalAuth (
329
- template . active_version_id ,
330
- ) ;
334
+ const {
335
+ startPollingExternalAuth,
336
+ isPollingExternalAuth,
337
+ externalAuthPollingState,
338
+ } = useExternalAuth ( template . active_version_id ) ;
339
+ const shouldRetry = externalAuthPollingState === "abandoned" ;
331
340
332
341
return missedExternalAuth . map ( ( auth ) => {
333
342
return (
334
- < Button
335
- variant = "outline"
336
- key = { auth . id }
337
- size = "sm"
338
- disabled = { isPollingExternalAuth || auth . authenticated }
339
- onClick = { ( ) => {
340
- window . open ( auth . authenticate_url , "_blank" , "width=900,height=600" ) ;
341
- startPollingExternalAuth ( ) ;
342
- } }
343
- >
344
- < Spinner loading = { isPollingExternalAuth } >
345
- < ExternalImage src = { auth . display_icon } />
346
- </ Spinner >
347
- Connect to { auth . display_name }
348
- </ Button >
343
+ < div className = "flex items-center gap-2" key = { auth . id } >
344
+ < Button
345
+ variant = "outline"
346
+ size = "sm"
347
+ disabled = { isPollingExternalAuth || auth . authenticated }
348
+ onClick = { ( ) => {
349
+ window . open (
350
+ auth . authenticate_url ,
351
+ "_blank" ,
352
+ "width=900,height=600" ,
353
+ ) ;
354
+ startPollingExternalAuth ( ) ;
355
+ } }
356
+ >
357
+ < Spinner loading = { isPollingExternalAuth } >
358
+ < ExternalImage src = { auth . display_icon } />
359
+ </ Spinner >
360
+ Connect to { auth . display_name }
361
+ </ Button >
362
+
363
+ { shouldRetry && ! auth . authenticated && (
364
+ < TooltipProvider >
365
+ < Tooltip delayDuration = { 100 } >
366
+ < TooltipTrigger asChild >
367
+ < Button
368
+ variant = "outline"
369
+ size = "icon"
370
+ onClick = { startPollingExternalAuth }
371
+ >
372
+ < RedoIcon />
373
+ < span className = "sr-only" > Refresh external auth</ span >
374
+ </ Button >
375
+ </ TooltipTrigger >
376
+ < TooltipContent >
377
+ Retry connect to { auth . display_name }
378
+ </ TooltipContent >
379
+ </ Tooltip >
380
+ </ TooltipProvider >
381
+ ) }
382
+ </ div >
349
383
) ;
350
384
} ) ;
351
385
} ;
0 commit comments