11import { BeakerIcon , BookOpenIcon } from "@heroicons/react/24/solid" ;
2- import { type MetaFunction , useNavigation } from "@remix-run/react" ;
2+ import { type MetaFunction , useNavigation , useRevalidator } from "@remix-run/react" ;
33import { type LoaderFunctionArgs } from "@remix-run/server-runtime" ;
44import { Suspense } from "react" ;
55import {
@@ -14,11 +14,12 @@ import { DevDisconnectedBanner, useDevPresence } from "~/components/DevPresence"
1414import { StepContentContainer } from "~/components/StepContentContainer" ;
1515import { MainCenteredContainer , PageBody } from "~/components/layout/AppLayout" ;
1616import { Badge } from "~/components/primitives/Badge" ;
17- import { LinkButton } from "~/components/primitives/Buttons" ;
17+ import { Button , LinkButton } from "~/components/primitives/Buttons" ;
1818import { Header1 } from "~/components/primitives/Headers" ;
1919import { InfoPanel } from "~/components/primitives/InfoPanel" ;
2020import { NavBar , PageAccessories , PageTitle } from "~/components/primitives/PageHeader" ;
2121import { Paragraph } from "~/components/primitives/Paragraph" ;
22+ import { PulsingDot } from "~/components/primitives/PulsingDot" ;
2223import {
2324 RESIZABLE_PANEL_ANIMATION ,
2425 ResizableHandle ,
@@ -64,6 +65,7 @@ import { throwNotFound } from "~/utils/httpErrors";
6465import { ListPagination } from "../../components/ListPagination" ;
6566import { CreateBulkActionInspector } from "../resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.bulkaction" ;
6667import { Callout } from "~/components/primitives/Callout" ;
68+ import { useRunsLiveReload } from "./useRunsLiveReload" ;
6769
6870export const meta : MetaFunction = ( ) => {
6971 return [
@@ -203,12 +205,36 @@ function RunsList({
203205 rootOnlyDefault : boolean ;
204206 filters : TaskRunListSearchFilters ;
205207} ) {
208+ const revalidator = useRevalidator ( ) ;
206209 const navigation = useNavigation ( ) ;
207210 const isLoading = navigation . state !== "idle" ;
208211 const organization = useOrganization ( ) ;
209212 const project = useProject ( ) ;
210213 const environment = useEnvironment ( ) ;
211214 const { has, replace } = useSearchParams ( ) ;
215+ const { visibleRuns, showNewRunsBanner, dismissNewRuns, childrenStatusesBasePath } =
216+ useRunsLiveReload ( {
217+ runs : list . runs ,
218+ hasAnyRuns : list . hasAnyRuns ,
219+ isLoading,
220+ organizationSlug : organization . slug ,
221+ projectSlug : project . slug ,
222+ environmentSlug : environment . slug ,
223+ } ) ;
224+
225+ const onClickShowNewRuns = ( ) => {
226+ const isPaginated = has ( "cursor" ) || has ( "direction" ) ;
227+ dismissNewRuns ( ) ;
228+ if ( isPaginated ) {
229+ replace ( {
230+ cursor : undefined ,
231+ direction : undefined ,
232+ } ) ;
233+ return ;
234+ }
235+
236+ revalidator . revalidate ( ) ;
237+ } ;
212238
213239 // Shortcut keys for bulk actions
214240 useShortcutKeys ( {
@@ -265,6 +291,18 @@ function RunsList({
265291 rootOnlyDefault = { rootOnlyDefault }
266292 />
267293 < div className = "flex items-center justify-end gap-x-2" >
294+ { showNewRunsBanner && (
295+ < Button
296+ variant = "secondary/small"
297+ className = "text-text-bright"
298+ onClick = { onClickShowNewRuns }
299+ LeadingIcon = { < PulsingDot className = "h-2 w-2" /> }
300+ tooltip = "Refresh to see new runs"
301+ aria-label = "New runs created. Refresh to see new runs."
302+ >
303+ New runs created
304+ </ Button >
305+ ) }
268306 { ! isShowingBulkActionInspector && (
269307 < LinkButton
270308 variant = "secondary/small"
@@ -303,10 +341,11 @@ function RunsList({
303341 </ div >
304342
305343 < TaskRunsTable
306- total = { list . runs . length }
344+ total = { visibleRuns . length }
307345 hasFilters = { list . hasFilters }
308346 filters = { list . filters }
309- runs = { list . runs }
347+ runs = { visibleRuns }
348+ childrenStatusesBasePath = { childrenStatusesBasePath }
310349 isLoading = { isLoading }
311350 allowSelection
312351 rootOnlyDefault = { rootOnlyDefault }
0 commit comments