This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new b11895dcd39 Add TIs tab to mapped task details (#50085)
b11895dcd39 is described below
commit b11895dcd39d0f33a91c4294d31665e0a862b60a
Author: Brent Bovenzi <[email protected]>
AuthorDate: Fri May 2 17:25:23 2025 -0400
Add TIs tab to mapped task details (#50085)
* Add TIs tab to mapped task details
* Adjust Tab title to total mapped count
---
.../MappedTaskInstance/MappedTaskInstance.tsx | 6 ++-
.../ui/src/pages/TaskInstance/TaskInstance.tsx | 43 ++++++++++++++++++++--
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git
a/airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/MappedTaskInstance.tsx
b/airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/MappedTaskInstance.tsx
index 770c6e9348d..9225610bc24 100644
---
a/airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/MappedTaskInstance.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/MappedTaskInstance/MappedTaskInstance.tsx
@@ -30,8 +30,6 @@ import { isStatePending, useAutoRefresh } from "src/utils";
import { Header } from "./Header";
-const tabs = [{ icon: <MdOutlineTask />, label: "Task Instances", value: "" }];
-
export const MappedTaskInstance = () => {
const { dagId = "", runId = "", taskId = "" } = useParams();
const refetchInterval = useAutoRefresh({ dagId });
@@ -74,6 +72,10 @@ export const MappedTaskInstance = () => {
.find((dr) => dr.dag_run_id === runId)
?.task_instances.find((ti) => ti.task_id === taskId);
+ const tabs = [
+ { icon: <MdOutlineTask />, label: `Task Instances
[${taskInstance?.task_count}]`, value: "" },
+ ];
+
return (
<ReactFlowProvider>
<DetailsLayout dag={dag} error={error ?? dagError} isLoading={isLoading
|| isDagLoading} tabs={tabs}>
diff --git
a/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
b/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
index f6993b87b27..8e19e7dbec2 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
@@ -18,11 +18,15 @@
*/
import { ReactFlowProvider } from "@xyflow/react";
import { FiCode } from "react-icons/fi";
-import { MdDetails, MdOutlineEventNote, MdReorder, MdSyncAlt } from
"react-icons/md";
+import { MdDetails, MdOutlineEventNote, MdOutlineTask, MdReorder, MdSyncAlt }
from "react-icons/md";
import { PiBracketsCurlyBold } from "react-icons/pi";
import { useParams } from "react-router-dom";
-import { useDagServiceGetDagDetails,
useTaskInstanceServiceGetMappedTaskInstance } from "openapi/queries";
+import {
+ useDagServiceGetDagDetails,
+ useGridServiceGridData,
+ useTaskInstanceServiceGetMappedTaskInstance,
+} from "openapi/queries";
import { DetailsLayout } from "src/layouts/Details/DetailsLayout";
import { isStatePending, useAutoRefresh } from "src/utils";
@@ -67,9 +71,42 @@ export const TaskInstance = () => {
},
);
+ // Filter grid data to get only a single dag run
+ const { data } = useGridServiceGridData(
+ {
+ dagId,
+ limit: 1,
+ offset: 0,
+ runAfterGte: taskInstance?.run_after,
+ runAfterLte: taskInstance?.run_after,
+ },
+ undefined,
+ {
+ enabled: taskInstance !== undefined,
+ },
+ );
+
+ const mappedTaskInstance = data?.dag_runs
+ .find((dr) => dr.dag_run_id === runId)
+ ?.task_instances.find((ti) => ti.task_id === taskId);
+
+ let newTabs = tabs;
+
+ if (taskInstance && taskInstance.map_index > -1) {
+ newTabs = [
+ ...tabs.slice(0, 1),
+ {
+ icon: <MdOutlineTask />,
+ label: `Task Instances [${mappedTaskInstance?.task_count ?? ""}]`,
+ value: "task_instances",
+ },
+ ...tabs.slice(1),
+ ];
+ }
+
return (
<ReactFlowProvider>
- <DetailsLayout dag={dag} error={error ?? dagError} isLoading={isLoading
|| isDagLoading} tabs={tabs}>
+ <DetailsLayout dag={dag} error={error ?? dagError} isLoading={isLoading
|| isDagLoading} tabs={newTabs}>
{taskInstance === undefined ? undefined : (
<Header
isRefreshing={Boolean(isStatePending(taskInstance.state) &&
Boolean(refetchInterval))}