Skip to content

Commit 3216a18

Browse files
Replace inline Header with FlowRunHeader component (#20338)
1 parent 45e5764 commit 3216a18

File tree

2 files changed

+17
-154
lines changed

2 files changed

+17
-154
lines changed

ui-v2/src/components/flow-runs/flow-run-details-page/flow-run-details-page.test.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,21 @@ describe("FlowRunDetailsPage", () => {
101101
http.post(buildApiUrl("/logs/filter"), () => {
102102
return HttpResponse.json([]);
103103
}),
104+
http.get(buildApiUrl("/flows/:id"), () => {
105+
return HttpResponse.json({ id: "test-flow-id", name: "Test Flow" });
106+
}),
107+
http.get(buildApiUrl("/deployments/:id"), () => {
108+
return HttpResponse.json({
109+
id: "test-deployment-id",
110+
name: "Test Deployment",
111+
});
112+
}),
113+
http.post(buildApiUrl("/task_runs/count"), () => {
114+
return HttpResponse.json(5);
115+
}),
116+
http.post(buildApiUrl("/flow_runs/filter"), () => {
117+
return HttpResponse.json([]);
118+
}),
104119
);
105120
});
106121

ui-v2/src/components/flow-runs/flow-run-details-page/index.tsx

Lines changed: 2 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useQueryClient, useSuspenseQuery } from "@tanstack/react-query";
22
import { useRouter } from "@tanstack/react-router";
3-
import { MoreVertical } from "lucide-react";
43
import { Suspense, useCallback, useEffect, useState } from "react";
54
import { toast } from "sonner";
65
import { queryKeyFactory as artifactsQueryKeyFactory } from "@/api/artifacts";
@@ -9,44 +8,21 @@ import {
98
type FlowRun,
109
queryKeyFactory as flowRunsQueryKeyFactory,
1110
useDeleteFlowRun,
12-
useSetFlowRunState,
1311
} from "@/api/flow-runs";
1412
import { queryKeyFactory as logsQueryKeyFactory } from "@/api/logs";
1513
import { queryKeyFactory as taskRunsQueryKeyFactory } from "@/api/task-runs";
1614
import { FlowRunGraph } from "@/components/flow-runs/flow-run-graph";
17-
import {
18-
Breadcrumb,
19-
BreadcrumbItem,
20-
BreadcrumbLink,
21-
BreadcrumbList,
22-
BreadcrumbPage,
23-
BreadcrumbSeparator,
24-
} from "@/components/ui/breadcrumb";
2515
import { Button } from "@/components/ui/button";
2616
import { Card, CardContent } from "@/components/ui/card";
27-
import {
28-
ChangeStateDialog,
29-
useChangeStateDialog,
30-
} from "@/components/ui/change-state-dialog";
31-
import {
32-
DeleteConfirmationDialog,
33-
useDeleteConfirmationDialog,
34-
} from "@/components/ui/delete-confirmation-dialog";
35-
import {
36-
DropdownMenu,
37-
DropdownMenuContent,
38-
DropdownMenuItem,
39-
DropdownMenuTrigger,
40-
} from "@/components/ui/dropdown-menu";
4117
import { ErrorBoundary } from "@/components/ui/error-boundary";
4218
import { Icon } from "@/components/ui/icons";
4319
import { LazyJsonInput } from "@/components/ui/json-input-lazy";
4420
import { Skeleton } from "@/components/ui/skeleton";
45-
import { StateBadge } from "@/components/ui/state-badge";
4621
import { TabErrorState } from "@/components/ui/tab-error-state";
4722
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
4823
import { FlowRunArtifacts } from "./flow-run-artifacts";
4924
import { FlowRunDetails } from "./flow-run-details";
25+
import { FlowRunHeader } from "./flow-run-header";
5026
import { FlowRunLogs } from "./flow-run-logs";
5127
import { FlowRunSubflows } from "./flow-run-subflows";
5228
import { FlowRunTaskRuns } from "./flow-run-task-runs";
@@ -132,7 +108,7 @@ export const FlowRunDetailsPage = ({
132108
return (
133109
<div className="flex flex-col gap-4">
134110
<div className="flex flex-col gap-2">
135-
<Header flowRun={flowRun} onDeleteRunClicked={onDeleteRunClicked} />
111+
<FlowRunHeader flowRun={flowRun} onDeleteClick={onDeleteRunClicked} />
136112
</div>
137113
{!isPending && (
138114
<Card>
@@ -288,134 +264,6 @@ export const FlowRunDetailsPage = ({
288264
);
289265
};
290266

291-
const Header = ({
292-
flowRun,
293-
onDeleteRunClicked,
294-
}: {
295-
flowRun: FlowRun;
296-
onDeleteRunClicked: () => void;
297-
}) => {
298-
const [dialogState, confirmDelete] = useDeleteConfirmationDialog();
299-
const {
300-
open: isChangeStateOpen,
301-
onOpenChange: setChangeStateOpen,
302-
openDialog: openChangeState,
303-
} = useChangeStateDialog();
304-
const { setFlowRunState, isPending: isChangingState } = useSetFlowRunState();
305-
306-
const canChangeState =
307-
flowRun.state_type &&
308-
["COMPLETED", "FAILED", "CANCELLED", "CRASHED"].includes(
309-
flowRun.state_type,
310-
);
311-
312-
const handleChangeState = (newState: { type: string; message?: string }) => {
313-
setFlowRunState(
314-
{
315-
id: flowRun.id,
316-
state: {
317-
type: newState.type as
318-
| "COMPLETED"
319-
| "FAILED"
320-
| "CANCELLED"
321-
| "CRASHED",
322-
name: newState.type.charAt(0) + newState.type.slice(1).toLowerCase(),
323-
message: newState.message,
324-
},
325-
force: true,
326-
},
327-
{
328-
onSuccess: () => {
329-
toast.success("Flow run state changed");
330-
setChangeStateOpen(false);
331-
},
332-
onError: (error) => {
333-
toast.error(error.message || "Failed to change state");
334-
},
335-
},
336-
);
337-
};
338-
339-
return (
340-
<div className="flex flex-row justify-between">
341-
<Breadcrumb>
342-
<BreadcrumbList>
343-
<BreadcrumbItem>
344-
<BreadcrumbLink to="/runs" className="text-xl font-semibold">
345-
Runs
346-
</BreadcrumbLink>
347-
</BreadcrumbItem>
348-
<BreadcrumbSeparator />
349-
<BreadcrumbItem className="text-xl">
350-
<BreadcrumbPage className="font-semibold">
351-
{flowRun.name}
352-
</BreadcrumbPage>
353-
{flowRun.state && (
354-
<StateBadge
355-
type={flowRun.state.type}
356-
name={flowRun.state.name}
357-
className="ml-2"
358-
/>
359-
)}
360-
</BreadcrumbItem>
361-
</BreadcrumbList>
362-
</Breadcrumb>
363-
<DropdownMenu>
364-
<DropdownMenuTrigger asChild>
365-
<Button variant="outline" className="p-2">
366-
<MoreVertical className="w-4 h-4" />
367-
</Button>
368-
</DropdownMenuTrigger>
369-
<DropdownMenuContent>
370-
{canChangeState && (
371-
<DropdownMenuItem onClick={openChangeState}>
372-
Change state
373-
</DropdownMenuItem>
374-
)}
375-
<DropdownMenuItem
376-
onClick={() => {
377-
toast.success("Copied flow run ID to clipboard");
378-
void navigator.clipboard.writeText(flowRun.id);
379-
}}
380-
>
381-
Copy ID
382-
</DropdownMenuItem>
383-
<DropdownMenuItem
384-
onClick={() =>
385-
confirmDelete({
386-
title: "Delete Flow Run",
387-
description: `Are you sure you want to delete flow run ${flowRun.name}?`,
388-
onConfirm: onDeleteRunClicked,
389-
})
390-
}
391-
>
392-
Delete
393-
</DropdownMenuItem>
394-
</DropdownMenuContent>
395-
</DropdownMenu>
396-
<DeleteConfirmationDialog {...dialogState} />
397-
<ChangeStateDialog
398-
open={isChangeStateOpen}
399-
onOpenChange={setChangeStateOpen}
400-
currentState={
401-
flowRun.state
402-
? {
403-
type: flowRun.state.type,
404-
name:
405-
flowRun.state.name ??
406-
flowRun.state.type.charAt(0) +
407-
flowRun.state.type.slice(1).toLowerCase(),
408-
}
409-
: null
410-
}
411-
label="Flow Run"
412-
onConfirm={handleChangeState}
413-
isLoading={isChangingState}
414-
/>
415-
</div>
416-
);
417-
};
418-
419267
const TabsLayout = ({
420268
currentTab,
421269
onTabChange,

0 commit comments

Comments
 (0)