This is an automated email from the ASF dual-hosted git repository.

pierrejeambrun pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new c280a3a3757 [v3-1-test] Fix group TI tab memory (#58288) (#58557)
c280a3a3757 is described below

commit c280a3a3757298a8231d0cf20536436332cd07c5
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Fri Nov 21 22:26:52 2025 +0800

    [v3-1-test] Fix group TI tab memory (#58288) (#58557)
    
    * fix: Prevent preserving tabs when navigating to Task Groups
    
    * refactor: Centralize keyboard navigation logic to use
    
    * test: update test,  Groups should not preserve tabs
    (cherry picked from commit 7b232c39200631448d5041d1577e03c5a3e5b140)
    
    Co-authored-by: LI,JHE-CHEN <[email protected]>
---
 .../ui/src/hooks/navigation/useNavigation.ts       | 22 ++++++++++------------
 .../src/airflow/ui/src/utils/links.test.ts         | 15 +++++++++++++--
 airflow-core/src/airflow/ui/src/utils/links.ts     |  3 ++-
 3 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/airflow-core/src/airflow/ui/src/hooks/navigation/useNavigation.ts 
b/airflow-core/src/airflow/ui/src/hooks/navigation/useNavigation.ts
index f8a63bc29ee..0c831ecb309 100644
--- a/airflow-core/src/airflow/ui/src/hooks/navigation/useNavigation.ts
+++ b/airflow-core/src/airflow/ui/src/hooks/navigation/useNavigation.ts
@@ -21,7 +21,7 @@ import { useLocation, useNavigate, useParams } from 
"react-router-dom";
 
 import type { GridRunsResponse } from "openapi/requests";
 import type { GridTask } from "src/layouts/Details/Grid/utils";
-import { getTaskInstanceAdditionalPath } from "src/utils/links";
+import { buildTaskInstanceUrl } from "src/utils/links";
 
 import type {
   NavigationDirection,
@@ -72,7 +72,6 @@ const buildPath = (params: {
 }): string => {
   const { dagId, mapIndex = "-1", mode, pathname, run, task } = params;
   const groupPath = task.isGroup ? "group/" : "";
-  const additionalPath = getTaskInstanceAdditionalPath(pathname);
 
   switch (mode) {
     case "run":
@@ -80,16 +79,15 @@ const buildPath = (params: {
     case "task":
       return `/dags/${dagId}/tasks/${groupPath}${task.id}`;
     case "TI":
-      if (task.is_mapped ?? false) {
-        if (mapIndex !== "-1") {
-          // For mapped tasks with specific map index, we need to construct 
the path manually
-          return 
`/dags/${dagId}/runs/${run.run_id}/tasks/${groupPath}${task.id}/mapped/${mapIndex}${additionalPath}`;
-        }
-
-        return 
`/dags/${dagId}/runs/${run.run_id}/tasks/${groupPath}${task.id}/mapped${additionalPath}`;
-      }
-
-      return 
`/dags/${dagId}/runs/${run.run_id}/tasks/${groupPath}${task.id}${additionalPath}`;
+      return buildTaskInstanceUrl({
+        currentPathname: pathname,
+        dagId,
+        isGroup: task.isGroup,
+        isMapped: task.is_mapped ?? false,
+        mapIndex,
+        runId: run.run_id,
+        taskId: task.id,
+      });
     default:
       return `/dags/${dagId}`;
   }
diff --git a/airflow-core/src/airflow/ui/src/utils/links.test.ts 
b/airflow-core/src/airflow/ui/src/utils/links.test.ts
index 2f4720897ee..47dd032ebc5 100644
--- a/airflow-core/src/airflow/ui/src/utils/links.test.ts
+++ b/airflow-core/src/airflow/ui/src/utils/links.test.ts
@@ -232,7 +232,18 @@ describe("buildTaskInstanceUrl", () => {
       }),
     ).toBe("/dags/my_dag/runs/run_123/tasks/mapped_task/mapped");
 
-    // Complex: group + mapped + sub-routes
+    // Groups should never preserve tabs (only have "Task Instances" tab)
+    expect(
+      buildTaskInstanceUrl({
+        currentPathname: 
"/dags/old/runs/old/tasks/old_task/rendered_templates",
+        dagId: "new_dag",
+        isGroup: true,
+        runId: "new_run",
+        taskId: "new_group",
+      }),
+    ).toBe("/dags/new_dag/runs/new_run/tasks/group/new_group");
+
+    // Groups should never preserve tabs even for mapped groups
     expect(
       buildTaskInstanceUrl({
         currentPathname: "/dags/old/runs/old/tasks/group/old_group/events",
@@ -243,6 +254,6 @@ describe("buildTaskInstanceUrl", () => {
         runId: "new_run",
         taskId: "new_group",
       }),
-    ).toBe("/dags/new_dag/runs/new_run/tasks/group/new_group/mapped/3/events");
+    ).toBe("/dags/new_dag/runs/new_run/tasks/group/new_group/mapped/3");
   });
 });
diff --git a/airflow-core/src/airflow/ui/src/utils/links.ts 
b/airflow-core/src/airflow/ui/src/utils/links.ts
index 80041700860..3beafb06afe 100644
--- a/airflow-core/src/airflow/ui/src/utils/links.ts
+++ b/airflow-core/src/airflow/ui/src/utils/links.ts
@@ -84,7 +84,8 @@ export const buildTaskInstanceUrl = (params: {
 }): string => {
   const { currentPathname, dagId, isGroup = false, isMapped = false, mapIndex, 
runId, taskId } = params;
   const groupPath = isGroup ? "group/" : "";
-  const additionalPath = getTaskInstanceAdditionalPath(currentPathname);
+  // Task groups only have "Task Instances" tab, so never preserve tabs for 
groups
+  const additionalPath = isGroup ? "" : 
getTaskInstanceAdditionalPath(currentPathname);
 
   let basePath = `/dags/${dagId}/runs/${runId}/tasks/${groupPath}${taskId}`;
 

Reply via email to