1
- import { Button , Text } from '@adobe/react-spectrum' ;
1
+ import { Button , ButtonGroup , Content , Dialog , DialogTrigger , Divider , Heading , Text } from '@adobe/react-spectrum' ;
2
2
import { ToastQueue } from '@react-spectrum/toast' ;
3
3
import Cancel from '@spectrum-icons/workflow/Cancel' ;
4
+ import StopCircle from '@spectrum-icons/workflow/StopCircle' ;
4
5
import React , { useState } from 'react' ;
6
+ import { useDeepCompareEffect } from 'react-use' ;
5
7
import { appState } from '../hooks/app.ts' ;
6
8
import { pollExecutionPending } from '../hooks/execution' ;
7
9
import { apiRequest } from '../utils/api' ;
@@ -14,8 +16,16 @@ interface ExecutionAbortButtonProps {
14
16
}
15
17
16
18
const ExecutionAbortButton : React . FC < ExecutionAbortButtonProps > = ( { execution, onComplete } ) => {
19
+ const [ showDialog , setShowDialog ] = useState ( false ) ;
17
20
const [ isAborting , setIsAborting ] = useState ( false ) ;
18
21
22
+ // Auto-close dialog if execution is no longer pending
23
+ useDeepCompareEffect ( ( ) => {
24
+ if ( showDialog && ( ! execution || ! isExecutionPending ( execution . status ) ) ) {
25
+ setShowDialog ( false ) ;
26
+ }
27
+ } , [ execution , showDialog ] ) ;
28
+
19
29
const onAbort = async ( ) => {
20
30
if ( ! execution ?. id ) {
21
31
console . warn ( 'Code execution cannot be aborted as it is not running!' ) ;
@@ -49,14 +59,41 @@ const ExecutionAbortButton: React.FC<ExecutionAbortButtonProps> = ({ execution,
49
59
} ) ;
50
60
} finally {
51
61
setIsAborting ( false ) ;
62
+ setShowDialog ( false ) ;
52
63
}
53
64
} ;
54
65
66
+ const renderAbortDialog = ( ) => (
67
+ < >
68
+ < Heading >
69
+ < Text > Confirmation</ Text >
70
+ </ Heading >
71
+ < Divider />
72
+ < Content >
73
+ < p > This action will abort current code execution.</ p >
74
+ < p > Be aware that aborting execution may leave data in an inconsistent state.</ p >
75
+ </ Content >
76
+ < ButtonGroup >
77
+ < Button variant = "secondary" onPress = { ( ) => setShowDialog ( false ) } isDisabled = { isAborting } >
78
+ < Cancel />
79
+ < Text > Cancel</ Text >
80
+ </ Button >
81
+ < Button variant = "negative" style = "fill" onPress = { onAbort } isPending = { isAborting } >
82
+ < StopCircle />
83
+ < Text > Abort</ Text >
84
+ </ Button >
85
+ </ ButtonGroup >
86
+ </ >
87
+ ) ;
88
+
55
89
return (
56
- < Button variant = "negative" isDisabled = { ! execution || ! isExecutionPending ( execution . status ) || isAborting } onPress = { onAbort } >
57
- < Cancel />
58
- < Text > Abort</ Text >
59
- </ Button >
90
+ < DialogTrigger isOpen = { showDialog } onOpenChange = { setShowDialog } >
91
+ < Button variant = "negative" isDisabled = { ! execution || ! isExecutionPending ( execution . status ) || isAborting } onPress = { ( ) => setShowDialog ( true ) } >
92
+ < StopCircle />
93
+ < Text > Abort</ Text >
94
+ </ Button >
95
+ < Dialog > { renderAbortDialog ( ) } </ Dialog >
96
+ </ DialogTrigger >
60
97
) ;
61
98
} ;
62
99
0 commit comments