1
- import { ExclamationCircleIcon } from "@heroicons/react/20/solid" ;
1
+ import {
2
+ ArrowPathRoundedSquareIcon ,
3
+ ArrowRightIcon ,
4
+ ExclamationCircleIcon ,
5
+ } from "@heroicons/react/20/solid" ;
2
6
import { BookOpenIcon } from "@heroicons/react/24/solid" ;
3
- import { useNavigation } from "@remix-run/react" ;
7
+ import { useLocation , useNavigation } from "@remix-run/react" ;
4
8
import { LoaderFunctionArgs } from "@remix-run/server-runtime" ;
5
9
import { formatDuration } from "@trigger.dev/core/v3/utils/durations" ;
6
10
import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
7
11
import { ListPagination } from "~/components/ListPagination" ;
8
12
import { AdminDebugTooltip } from "~/components/admin/debugTooltip" ;
9
13
import { EnvironmentLabel } from "~/components/environments/EnvironmentLabel" ;
10
14
import { PageBody , PageContainer } from "~/components/layout/AppLayout" ;
11
- import { LinkButton } from "~/components/primitives/Buttons" ;
15
+ import { Button , LinkButton } from "~/components/primitives/Buttons" ;
12
16
import { DateTime } from "~/components/primitives/DateTime" ;
17
+ import { Dialog , DialogTrigger } from "~/components/primitives/Dialog" ;
13
18
import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
14
19
import { Paragraph } from "~/components/primitives/Paragraph" ;
20
+ import { PopoverMenuItem } from "~/components/primitives/Popover" ;
15
21
import { Spinner } from "~/components/primitives/Spinner" ;
16
22
import {
17
23
Table ,
18
24
TableBlankRow ,
19
25
TableBody ,
20
26
TableCell ,
27
+ TableCellMenu ,
21
28
TableHeader ,
22
29
TableHeaderCell ,
23
30
TableRow ,
@@ -29,12 +36,17 @@ import {
29
36
BatchStatusCombo ,
30
37
descriptionForBatchStatus ,
31
38
} from "~/components/runs/v3/BatchStatus" ;
39
+ import { CheckBatchCompletionDialog } from "~/components/runs/v3/CheckBatchCompletionDialog" ;
32
40
import { LiveTimer } from "~/components/runs/v3/LiveTimer" ;
33
41
import { useOrganization } from "~/hooks/useOrganizations" ;
34
42
import { useProject } from "~/hooks/useProject" ;
35
43
import { redirectWithErrorMessage } from "~/models/message.server" ;
36
44
import { findProjectBySlug } from "~/models/project.server" ;
37
- import { BatchList , BatchListPresenter } from "~/presenters/v3/BatchListPresenter.server" ;
45
+ import {
46
+ BatchList ,
47
+ BatchListItem ,
48
+ BatchListPresenter ,
49
+ } from "~/presenters/v3/BatchListPresenter.server" ;
38
50
import { requireUserId } from "~/services/session.server" ;
39
51
import { docsPath , ProjectParamSchema , v3BatchRunsPath } from "~/utils/pathBuilder" ;
40
52
@@ -150,19 +162,22 @@ function BatchesTable({ batches, hasFilters, filters }: BatchList) {
150
162
< TableHeaderCell > Duration</ TableHeaderCell >
151
163
< TableHeaderCell > Created</ TableHeaderCell >
152
164
< TableHeaderCell > Finished</ TableHeaderCell >
165
+ < TableHeaderCell >
166
+ < span className = "sr-only" > Go to batch</ span >
167
+ </ TableHeaderCell >
153
168
</ TableRow >
154
169
</ TableHeader >
155
170
< TableBody >
156
171
{ batches . length === 0 && ! hasFilters ? (
157
- < TableBlankRow colSpan = { 7 } >
172
+ < TableBlankRow colSpan = { 8 } >
158
173
{ ! isLoading && (
159
174
< div className = "flex items-center justify-center" >
160
175
< Paragraph className = "w-auto" > No batches</ Paragraph >
161
176
</ div >
162
177
) }
163
178
</ TableBlankRow >
164
179
) : batches . length === 0 ? (
165
- < TableBlankRow colSpan = { 7 } >
180
+ < TableBlankRow colSpan = { 8 } >
166
181
< div className = "flex items-center justify-center" >
167
182
< Paragraph className = "w-auto" > No batches match these filters</ Paragraph >
168
183
</ div >
@@ -215,13 +230,14 @@ function BatchesTable({ batches, hasFilters, filters }: BatchList) {
215
230
< TableCell to = { path } >
216
231
{ batch . finishedAt ? < DateTime date = { batch . finishedAt } /> : "–" }
217
232
</ TableCell >
233
+ < BatchActionsCell batch = { batch } path = { path } />
218
234
</ TableRow >
219
235
) ;
220
236
} )
221
237
) }
222
238
{ isLoading && (
223
239
< TableBlankRow
224
- colSpan = { 7 }
240
+ colSpan = { 8 }
225
241
className = "absolute left-0 top-0 flex h-full w-full items-center justify-center gap-2 bg-charcoal-900/90"
226
242
>
227
243
< Spinner /> < span className = "text-text-dimmed" > Loading…</ span >
@@ -231,3 +247,48 @@ function BatchesTable({ batches, hasFilters, filters }: BatchList) {
231
247
</ Table >
232
248
) ;
233
249
}
250
+
251
+ function BatchActionsCell ( { batch, path } : { batch : BatchListItem ; path : string } ) {
252
+ const location = useLocation ( ) ;
253
+
254
+ if ( batch . hasFinished ) return < TableCell to = { path } > { "" } </ TableCell > ;
255
+
256
+ return (
257
+ < TableCellMenu
258
+ isSticky
259
+ popoverContent = {
260
+ < >
261
+ < PopoverMenuItem
262
+ to = { path }
263
+ icon = { ArrowRightIcon }
264
+ leadingIconClassName = "text-blue-500"
265
+ title = "View batch"
266
+ />
267
+ { ! batch . hasFinished && (
268
+ < Dialog >
269
+ < DialogTrigger
270
+ asChild
271
+ className = "size-6 rounded-sm p-1 text-text-dimmed transition hover:bg-charcoal-700 hover:text-text-bright"
272
+ >
273
+ < Button
274
+ variant = "small-menu-item"
275
+ LeadingIcon = { ArrowPathRoundedSquareIcon }
276
+ leadingIconClassName = "text-success"
277
+ fullWidth
278
+ textAlignLeft
279
+ className = "w-full px-1.5 py-[0.9rem]"
280
+ >
281
+ Try and resume
282
+ </ Button >
283
+ </ DialogTrigger >
284
+ < CheckBatchCompletionDialog
285
+ batchId = { batch . id }
286
+ redirectPath = { `${ location . pathname } ${ location . search } ` }
287
+ />
288
+ </ Dialog >
289
+ ) }
290
+ </ >
291
+ }
292
+ />
293
+ ) ;
294
+ }
0 commit comments