This is an automated email from the ASF dual-hosted git repository. vatsrahul1001 pushed a commit to branch backport-322-65626 in repository https://gitbox.apache.org/repos/asf/airflow.git
commit fb24af4431fc9b49eba030c29fb1ab020cc3191d Author: PrithviBadiga <[email protected]> AuthorDate: Wed Apr 22 08:57:22 2026 -0700 Adds the DAG run ID to the grid bar tooltip and also surfaces it in the task instance tooltip in the grid view. (#65626) * Add run ID to grid tooltips * Format GridTI after run ID tooltip update --------- Co-authored-by: Prithvi Badiga <[email protected]> (cherry picked from commit 2d4eb59b352affcd488344096080748bd691f004) --- .../ui/src/components/TaskInstanceTooltip.test.tsx | 21 +++++++++ .../ui/src/components/TaskInstanceTooltip.tsx | 7 +-- .../src/layouts/Details/Grid/GridButton.test.tsx | 55 ++++++++++++++++++++++ .../ui/src/layouts/Details/Grid/GridButton.tsx | 2 + .../airflow/ui/src/layouts/Details/Grid/GridTI.tsx | 7 ++- 5 files changed, 88 insertions(+), 4 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx index 51058868003..3f3d17a95de 100644 --- a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx +++ b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.test.tsx @@ -196,4 +196,25 @@ describe("TaskInstanceTooltip", () => { expect(screen.getAllByText(/state/iu).length).toBeGreaterThan(0); expect(screen.getByText(/startDate/iu)).toBeInTheDocument(); }); + + it("shows run ID when provided explicitly for grid summaries", () => { + const taskInstance: LightGridTaskInstanceSummary = { + child_states: null, + max_end_date: "2025-01-01T02:00:00Z", + min_start_date: "2025-01-01T00:00:00Z", + state: "success", + task_display_name: "My Task", + task_id: "my_task", + }; + + render( + <TaskInstanceTooltip open runId="manual__2025-01-01T00:00:00+00:00" taskInstance={taskInstance}> + <span>trigger</span> + </TaskInstanceTooltip>, + { wrapper: Wrapper }, + ); + + expect(screen.getByText(/runId/iu)).toBeInTheDocument(); + expect(screen.getByText(/manual__2025-01-01T00:00:00\+00:00/iu)).toBeInTheDocument(); + }); }); diff --git a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx index 8162c02a7c3..8f89c910247 100644 --- a/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx +++ b/airflow-core/src/airflow/ui/src/components/TaskInstanceTooltip.tsx @@ -29,11 +29,12 @@ import { Tooltip, type TooltipProps } from "src/components/ui"; import { getDuration, renderDuration, sortStateEntries } from "src/utils"; type Props = { + readonly runId?: string | null; readonly taskInstance?: LightGridTaskInstanceSummary | TaskInstanceHistoryResponse | TaskInstanceResponse; readonly tooltip?: string | null; } & Omit<TooltipProps, "content">; -const TaskInstanceTooltip = ({ children, positioning, taskInstance, tooltip, ...rest }: Props) => { +const TaskInstanceTooltip = ({ children, positioning, runId, taskInstance, tooltip, ...rest }: Props) => { const { t: translate } = useTranslation("common"); const hasTooltip = tooltip !== undefined && tooltip !== null; @@ -62,9 +63,9 @@ const TaskInstanceTooltip = ({ children, positioning, taskInstance, tooltip, ... ? translate(`common:states.${taskInstance.state}`) : translate("common:states.no_status")} </Text> - {"dag_run_id" in taskInstance ? ( + {"dag_run_id" in taskInstance || (runId !== undefined && runId !== null && runId !== "") ? ( <Text> - {translate("runId")}: {taskInstance.dag_run_id} + {translate("runId")}: {"dag_run_id" in taskInstance ? taskInstance.dag_run_id : runId} </Text> ) : undefined} {"start_date" in taskInstance ? ( diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx new file mode 100644 index 00000000000..6164573e68c --- /dev/null +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.test.tsx @@ -0,0 +1,55 @@ +/*! + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import "@testing-library/jest-dom"; +import { act, fireEvent, render, screen } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; + +import { Wrapper } from "src/utils/Wrapper"; + +import { GridButton } from "./GridButton"; + +describe("GridButton", () => { + it("shows run ID in the grid tooltip", () => { + vi.useFakeTimers(); + + render( + <GridButton + dagId="example_dag" + label="2026-04-21T00:00:00+00:00" + runId="manual__2026-04-21T00:00:00+00:00" + searchParams="" + state="success" + > + <span>bar</span> + </GridButton>, + { wrapper: Wrapper }, + ); + + act(() => { + fireEvent.mouseEnter(screen.getByText("bar")); + vi.advanceTimersByTime(500); + }); + + expect(screen.getByTestId("basic-tooltip")).toHaveTextContent( + "common:runId: manual__2026-04-21T00:00:00+00:00", + ); + + vi.useRealTimers(); + }); +}); diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx index c452cf43a79..488ccffd0d0 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridButton.tsx @@ -50,6 +50,8 @@ export const GridButton = ({ <> {label} <br /> + {translate("common:runId")}: {runId} + <br /> {translate("state")}:{" "} {state ? translate(`common:states.${state}`) : translate("common:states.no_status")} </> diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx index ede81eccbb0..6cd21d252f9 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx @@ -80,7 +80,12 @@ export const GridTI = ({ dagId, instance, isGroup, isMapped, onClick, runId, tas py={0} transition="background-color 0.2s" > - <TaskInstanceTooltip openDelay={500} positioning={{ placement: "bottom" }} taskInstance={instance}> + <TaskInstanceTooltip + openDelay={500} + positioning={{ placement: "bottom" }} + runId={runId} + taskInstance={instance} + > <Box as="span" display="inline-block"> <Link data-testid={`grid-${runId}-${taskId}`}
