1
+ import { flagsHooks } from '@/app/common/hooks/flags-hooks' ;
2
+ import { flowRunsApi } from '@/app/features/flow-runs/lib/flow-runs-api' ;
3
+ import { formatUtils } from '@/app/lib/utils' ;
1
4
import {
2
5
DataTableColumnHeader ,
3
6
DropdownMenu ,
4
7
DropdownMenuContent ,
5
8
DropdownMenuItem ,
6
9
DropdownMenuTrigger ,
7
10
INTERNAL_ERROR_TOAST ,
8
- PermissionNeededTooltip ,
9
11
RowDataWithActions ,
10
12
StatusIconWithText ,
11
13
toast ,
12
14
} from '@openops/components/ui' ;
13
- import { useMutation } from '@tanstack/react-query' ;
14
- import { ColumnDef } from '@tanstack/react-table' ;
15
- import { t } from 'i18next' ;
16
- import { EllipsisVertical , RefreshCw , RotateCcw } from 'lucide-react' ;
17
- import { useMemo } from 'react' ;
18
-
19
- import { useAuthorization } from '@/app/common/hooks/authorization-hooks' ;
20
- import { flagsHooks } from '@/app/common/hooks/flags-hooks' ;
21
- import { flowRunsApi } from '@/app/features/flow-runs/lib/flow-runs-api' ;
22
- import { formatUtils } from '@/app/lib/utils' ;
23
15
import {
24
16
FlagId ,
25
17
FlowRetryStrategy ,
26
18
FlowRun ,
19
+ FlowRunStatus ,
27
20
FlowRunTriggerSource ,
28
21
isFailedState ,
29
- Permission ,
22
+ isRunningState ,
30
23
} from '@openops/shared' ;
24
+ import { useMutation } from '@tanstack/react-query' ;
25
+ import { ColumnDef } from '@tanstack/react-table' ;
26
+ import { t } from 'i18next' ;
27
+ import {
28
+ CircleStop ,
29
+ EllipsisVertical ,
30
+ RefreshCw ,
31
+ RotateCcw ,
32
+ } from 'lucide-react' ;
33
+ import { useMemo , useState } from 'react' ;
31
34
32
35
import { RunType } from '@/app/features/flow-runs/components/run-type' ;
36
+ import { StopRunDialog } from '@/app/features/flow-runs/components/stop-run-dialog' ;
33
37
import { flowRunUtils } from '../lib/flow-run-utils' ;
34
38
35
39
type Column = ColumnDef < RowDataWithActions < FlowRun > > & {
36
40
accessorKey : string ;
37
41
} ;
38
42
39
43
export const useRunsTableColumns = ( ) : Column [ ] => {
40
- const { checkAccess } = useAuthorization ( ) ;
41
44
const durationEnabled = flagsHooks . useFlag < boolean > (
42
45
FlagId . SHOW_DURATION ,
43
46
) . data ;
44
47
45
- const userHasPermissionToRetryRun = checkAccess ( Permission . RETRY_RUN ) ;
46
48
const { mutate } = useMutation <
47
49
FlowRun ,
48
50
Error ,
@@ -58,6 +60,22 @@ export const useRunsTableColumns = (): Column[] => {
58
60
toast ( INTERNAL_ERROR_TOAST ) ;
59
61
} ,
60
62
} ) ;
63
+
64
+ const { mutate : stopRun } = useMutation <
65
+ void ,
66
+ Error ,
67
+ { row : RowDataWithActions < FlowRun > }
68
+ > ( {
69
+ mutationFn : ( data ) => flowRunsApi . abort ( data . row . id ) ,
70
+ onSuccess : ( _ , { row } ) => {
71
+ row . update ( { ...row , status : FlowRunStatus . STOPPED } ) ;
72
+ } ,
73
+ onError : ( error ) => {
74
+ console . error ( error ) ;
75
+ toast ( INTERNAL_ERROR_TOAST ) ;
76
+ } ,
77
+ } ) ;
78
+
61
79
return useMemo (
62
80
( ) =>
63
81
[
@@ -136,10 +154,16 @@ export const useRunsTableColumns = (): Column[] => {
136
154
header : ( ) => null ,
137
155
cell : ( { row } ) => {
138
156
const isFailed = isFailedState ( row . original . status ) ;
157
+ const isRunning = isRunningState ( row . original . status ) ;
158
+ const isStopped = row . original . status === FlowRunStatus . STOPPED ;
159
+
160
+ // eslint-disable-next-line react-hooks/rules-of-hooks
161
+ const [ isStopDialogOpen , setIsStopDialogOpen ] = useState ( false ) ;
139
162
140
163
if (
141
- ! isFailed ||
142
- row . original . triggerSource === FlowRunTriggerSource . TEST_RUN
164
+ ( ( isFailed || isStopped ) &&
165
+ row . original . triggerSource === FlowRunTriggerSource . TEST_RUN ) ||
166
+ ( ! isFailed && ! isRunning && ! isStopped )
143
167
) {
144
168
return < div className = "h-10" > </ div > ;
145
169
}
@@ -157,11 +181,8 @@ export const useRunsTableColumns = (): Column[] => {
157
181
< EllipsisVertical className = "h-10 w-10" />
158
182
</ DropdownMenuTrigger >
159
183
< DropdownMenuContent >
160
- < PermissionNeededTooltip
161
- hasPermission = { userHasPermissionToRetryRun }
162
- >
184
+ { ( isFailed || isStopped ) && (
163
185
< DropdownMenuItem
164
- disabled = { ! userHasPermissionToRetryRun }
165
186
onClick = { ( ) =>
166
187
mutate ( {
167
188
row : row . original ,
@@ -174,13 +195,9 @@ export const useRunsTableColumns = (): Column[] => {
174
195
< span > { t ( 'Retry on latest version' ) } </ span >
175
196
</ div >
176
197
</ DropdownMenuItem >
177
- </ PermissionNeededTooltip >
178
-
179
- < PermissionNeededTooltip
180
- hasPermission = { userHasPermissionToRetryRun }
181
- >
198
+ ) }
199
+ { isFailed && (
182
200
< DropdownMenuItem
183
- disabled = { ! userHasPermissionToRetryRun }
184
201
onClick = { ( ) =>
185
202
mutate ( {
186
203
row : row . original ,
@@ -193,7 +210,24 @@ export const useRunsTableColumns = (): Column[] => {
193
210
< span > { t ( 'Retry from failed step' ) } </ span >
194
211
</ div >
195
212
</ DropdownMenuItem >
196
- </ PermissionNeededTooltip >
213
+ ) }
214
+ { isRunning && (
215
+ < StopRunDialog
216
+ isStopDialogOpen = { isStopDialogOpen }
217
+ setIsStopDialogOpen = { setIsStopDialogOpen }
218
+ stopRun = { ( ) => {
219
+ stopRun ( { row : row . original } ) ;
220
+ setIsStopDialogOpen ( false ) ;
221
+ } }
222
+ >
223
+ < DropdownMenuItem onSelect = { ( e ) => e . preventDefault ( ) } >
224
+ < div className = "flex flex-row gap-2 items-center" >
225
+ < CircleStop className = "h-4 w-4" />
226
+ < span > { t ( 'Stop Run' ) } </ span >
227
+ </ div >
228
+ </ DropdownMenuItem >
229
+ </ StopRunDialog >
230
+ ) }
197
231
</ DropdownMenuContent >
198
232
</ DropdownMenu >
199
233
</ div >
@@ -203,6 +237,6 @@ export const useRunsTableColumns = (): Column[] => {
203
237
] . filter (
204
238
( column ) => durationEnabled || column . accessorKey !== 'duration' ,
205
239
) ,
206
- [ mutate , userHasPermissionToRetryRun ] ,
240
+ [ mutate , stopRun ] ,
207
241
) ;
208
242
} ;
0 commit comments