Skip to content

Commit 6713e44

Browse files
committed
get things working so we don't need to re-query the data when clicking onto a group or mapped ti. this requires passing state through the link. i have no clue how it works but it does (thanks chat gpt)
1 parent a16cc80 commit 6713e44

File tree

5 files changed

+54
-92
lines changed

5 files changed

+54
-92
lines changed

airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type { MouseEvent } from "react";
2121
import React from "react";
2222
import { Link, useParams } from "react-router-dom";
2323

24-
import type { TaskInstanceState } from "openapi/requests/types.gen";
24+
import type { LightGridTaskInstanceSummary, TaskInstanceState } from "openapi/requests/types.gen";
2525
import { StateIcon } from "src/components/StateIcon";
2626

2727
type Props = {
@@ -33,6 +33,7 @@ type Props = {
3333
readonly search: string;
3434
readonly state?: TaskInstanceState | null;
3535
readonly taskId: string;
36+
readonly taskInstance: LightGridTaskInstanceSummary;
3637
};
3738

3839
const onMouseEnter = (event: MouseEvent<HTMLDivElement>) => {
@@ -51,7 +52,7 @@ const onMouseLeave = (event: MouseEvent<HTMLDivElement>) => {
5152
});
5253
};
5354

54-
const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId }: Props) => {
55+
const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId, taskInstance }: Props) => {
5556
const { groupId: selectedGroupId, taskId: selectedTaskId } = useParams();
5657

5758
return (
@@ -71,6 +72,7 @@ const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId }: Pr
7172
>
7273
<Link
7374
replace
75+
state={{ taskInstance }}
7476
to={{
7577
pathname: `/dags/${dagId}/runs/${runId}/tasks/${isGroup ? "group/" : ""}${taskId}${isMapped ? "/mapped" : ""}`,
7678
search,

airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskInstancesColumn.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const TaskInstancesColumn = ({ nodes, runId, taskInstances }: Props) => {
5555
search={search}
5656
state={taskInstance.state}
5757
taskId={node.id}
58+
taskInstance={taskInstance}
5859
/>
5960
);
6061
});

airflow-core/src/airflow/ui/src/pages/GroupTaskInstance/GroupTaskInstance.tsx

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,35 @@
1818
*/
1919
import { ReactFlowProvider } from "@xyflow/react";
2020
import { MdOutlineTask } from "react-icons/md";
21-
import { useParams } from "react-router-dom";
21+
import { useLocation, useParams } from "react-router-dom";
2222

23-
import { useDagServiceGetDagDetails } from "openapi/queries";
23+
import type { LightGridTaskInstanceSummary } from "openapi/requests";
2424
import { DetailsLayout } from "src/layouts/Details/DetailsLayout";
25-
import { useGridTiSummaries } from "src/queries/useGridTISummaries.ts";
2625
import { isStatePending, useAutoRefresh } from "src/utils";
2726

2827
import { Header } from "./Header";
2928

30-
export const GroupTaskInstance = () => {
31-
const { dagId = "", groupId = "", runId = "" } = useParams();
32-
const refetchInterval = useAutoRefresh({ dagId });
33-
34-
const {
35-
data: dag,
36-
error: dagError,
37-
isLoading: isDagLoading,
38-
} = useDagServiceGetDagDetails({
39-
dagId,
40-
});
29+
type LocationState = {
30+
taskInstance: LightGridTaskInstanceSummary;
31+
};
4132

42-
const { data: gridTISummaries, error, isLoading } = useGridTiSummaries({ dagId, runId, state: undefined });
33+
export const GroupTaskInstance = () => {
34+
const { dagId = "" } = useParams();
4335

44-
const taskInstance = gridTISummaries?.task_instances.find((ti) => ti.task_id === groupId);
36+
const location = useLocation();
37+
const state = location.state as LocationState;
38+
const taskInstance: LightGridTaskInstanceSummary = state.taskInstance;
39+
const refetchInterval = useAutoRefresh({ dagId });
4540

4641
const tabs = [{ icon: <MdOutlineTask />, label: "Task Instances", value: "" }];
4742

4843
return (
4944
<ReactFlowProvider>
50-
<DetailsLayout dag={dag} error={error ?? dagError} isLoading={isLoading || isDagLoading} tabs={tabs}>
51-
{taskInstance === undefined ? undefined : (
52-
<Header
53-
isRefreshing={Boolean(isStatePending(taskInstance.state) && Boolean(refetchInterval))}
54-
taskInstance={taskInstance}
55-
/>
56-
)}
45+
<DetailsLayout tabs={tabs}>
46+
<Header
47+
isRefreshing={Boolean(isStatePending(taskInstance.state) && Boolean(refetchInterval))}
48+
taskInstance={taskInstance}
49+
/>
5750
</DetailsLayout>
5851
</ReactFlowProvider>
5952
);

airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/Header.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { Box } from "@chakra-ui/react";
2020
import type { ReactNode } from "react";
2121
import { MdOutlineTask } from "react-icons/md";
2222

23-
import type { GridTaskInstanceSummary } from "openapi/requests/types.gen";
23+
import type { LightGridTaskInstanceSummary } from "openapi/requests/types.gen";
2424
import { HeaderCard } from "src/components/HeaderCard";
2525
import Time from "src/components/Time";
2626
import { getDuration } from "src/utils";
@@ -30,23 +30,21 @@ export const Header = ({
3030
taskInstance,
3131
}: {
3232
readonly isRefreshing?: boolean;
33-
readonly taskInstance: GridTaskInstanceSummary;
33+
readonly taskInstance: LightGridTaskInstanceSummary;
3434
}) => {
3535
const entries: Array<{ label: string; value: number | ReactNode | string }> = [];
36+
let taskCount: number = 0;
3637

37-
if (taskInstance.child_states !== null) {
38-
Object.entries(taskInstance.child_states).forEach(([state, count]) => {
39-
if (count > 0) {
40-
entries.push({ label: `Total ${state}`, value: count });
41-
}
42-
});
43-
}
38+
Object.entries(taskInstance.child_states ?? {}).forEach(([state, count]) => {
39+
entries.push({ label: `Total ${state}`, value: count });
40+
taskCount += count;
41+
});
4442
const stats = [
4543
...entries,
46-
{ label: "Start", value: <Time datetime={taskInstance.start_date} /> },
47-
{ label: "End", value: <Time datetime={taskInstance.end_date} /> },
48-
...(Boolean(taskInstance.start_date)
49-
? [{ label: "Duration", value: getDuration(taskInstance.start_date, taskInstance.end_date) }]
44+
{ label: "Start", value: <Time datetime={taskInstance.min_start_date} /> },
45+
{ label: "End", value: <Time datetime={taskInstance.max_end_date} /> },
46+
...(Boolean(taskInstance.max_end_date)
47+
? [{ label: "Duration", value: getDuration(taskInstance.min_start_date, taskInstance.max_end_date) }]
5048
: []),
5149
];
5250

@@ -57,8 +55,8 @@ export const Header = ({
5755
isRefreshing={isRefreshing}
5856
state={taskInstance.state}
5957
stats={stats}
60-
subTitle={<Time datetime={taskInstance.start_date} />}
61-
title={`${taskInstance.task_id} [${taskInstance.task_count}]`}
58+
subTitle={<Time datetime={taskInstance.min_start_date} />}
59+
title={`${taskInstance.task_id} [${taskCount}]`}
6260
/>
6361
</Box>
6462
);

airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/MappedTaskInstance.tsx

Lines changed: 20 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,73 +18,41 @@
1818
*/
1919
import { ReactFlowProvider } from "@xyflow/react";
2020
import { MdOutlineTask } from "react-icons/md";
21-
import { useParams } from "react-router-dom";
21+
import { useLocation, useParams } from "react-router-dom";
2222

23-
import {
24-
useDagRunServiceGetDagRun,
25-
useDagServiceGetDagDetails,
26-
useGridServiceGridData,
27-
} from "openapi/queries";
23+
import type { LightGridTaskInstanceSummary } from "openapi/requests";
2824
import { DetailsLayout } from "src/layouts/Details/DetailsLayout";
2925
import { isStatePending, useAutoRefresh } from "src/utils";
3026

3127
import { Header } from "./Header";
3228

29+
type LocationState = {
30+
taskInstance: LightGridTaskInstanceSummary;
31+
};
32+
3333
export const MappedTaskInstance = () => {
34-
const { dagId = "", runId = "", taskId = "" } = useParams();
34+
const { dagId = "" } = useParams();
3535
const refetchInterval = useAutoRefresh({ dagId });
3636

37-
const {
38-
data: dag,
39-
error: dagError,
40-
isLoading: isDagLoading,
41-
} = useDagServiceGetDagDetails({
42-
dagId,
43-
});
37+
const location = useLocation();
38+
const state = location.state as LocationState;
39+
const taskInstance: LightGridTaskInstanceSummary = state.taskInstance;
4440

45-
const { data: dagRun } = useDagRunServiceGetDagRun(
46-
{
47-
dagId,
48-
dagRunId: runId,
49-
},
50-
undefined,
51-
{ enabled: runId !== "" },
52-
);
41+
let taskCount: number = 0;
5342

54-
// Filter grid data to get only a single dag run
55-
const { data, error, isLoading } = useGridServiceGridData(
56-
{
57-
dagId,
58-
limit: 1,
59-
offset: 0,
60-
runAfterGte: dagRun?.run_after,
61-
runAfterLte: dagRun?.run_after,
62-
},
63-
undefined,
64-
{
65-
enabled: dagRun !== undefined,
66-
refetchInterval: (query) =>
67-
query.state.data?.dag_runs.some((dr) => isStatePending(dr.state)) && refetchInterval,
68-
},
69-
);
70-
71-
const taskInstance = data?.dag_runs
72-
.find((dr) => dr.dag_run_id === runId)
73-
?.task_instances.find((ti) => ti.task_id === taskId);
43+
Object.entries(taskInstance.child_states ?? {}).forEach(([, count]) => {
44+
taskCount += count;
45+
});
7446

75-
const tabs = [
76-
{ icon: <MdOutlineTask />, label: `Task Instances [${taskInstance?.task_count}]`, value: "" },
77-
];
47+
const tabs = [{ icon: <MdOutlineTask />, label: `Task Instances [${taskCount}]`, value: "" }];
7848

7949
return (
8050
<ReactFlowProvider>
81-
<DetailsLayout dag={dag} error={error ?? dagError} isLoading={isLoading || isDagLoading} tabs={tabs}>
82-
{taskInstance === undefined ? undefined : (
83-
<Header
84-
isRefreshing={Boolean(isStatePending(taskInstance.state) && Boolean(refetchInterval))}
85-
taskInstance={taskInstance}
86-
/>
87-
)}
51+
<DetailsLayout tabs={tabs}>
52+
<Header
53+
isRefreshing={Boolean(isStatePending(taskInstance.state) && Boolean(refetchInterval))}
54+
taskInstance={taskInstance}
55+
/>
8856
</DetailsLayout>
8957
</ReactFlowProvider>
9058
);

0 commit comments

Comments
 (0)