This is an automated email from the ASF dual-hosted git repository. kaxilnaik pushed a commit to branch v3-0-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 2fe9f018a9cd3879c6dcab83d2dce03476a8592b Author: LI,JHE-CHEN <[email protected]> AuthorDate: Tue May 13 06:12:00 2025 +0800 UI: Implement navigation on bar click (#50416) * UI: implement navigation on bar click * use default tooltip * fix: remove unnecessary type assertion and add TI overview click-to-navigate function * refactor: optimize hover handling in DurationChart * nit:Use switch statement and extract common path (cherry picked from commit 21ca3ce024f27e200be0864644000b77a6374a7c) --- .../airflow/ui/src/components/DurationChart.tsx | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/airflow-core/src/airflow/ui/src/components/DurationChart.tsx b/airflow-core/src/airflow/ui/src/components/DurationChart.tsx index 6a4e86ff1bd..a10af96f417 100644 --- a/airflow-core/src/airflow/ui/src/components/DurationChart.tsx +++ b/airflow-core/src/airflow/ui/src/components/DurationChart.tsx @@ -31,6 +31,7 @@ import type { PartialEventContext } from "chartjs-plugin-annotation"; import annotationPlugin from "chartjs-plugin-annotation"; import dayjs from "dayjs"; import { Bar } from "react-chartjs-2"; +import { useNavigate } from "react-router-dom"; import type { TaskInstanceResponse, DAGRunResponse } from "openapi/requests/types.gen"; import { system } from "src/theme"; @@ -64,6 +65,8 @@ export const DurationChart = ({ readonly entries: Array<RunResponse> | undefined; readonly kind: "Dag Run" | "Task Instance"; }) => { + const navigate = useNavigate(); + if (!entries) { return undefined; } @@ -141,6 +144,33 @@ export const DurationChart = ({ }} datasetIdKey="id" options={{ + onClick: (_event, elements) => { + const [element] = elements; + + if (!element) { + return; + } + + const entry = entries[element.index]; + const baseUrl = `/dags/${entry?.dag_id}/runs/${entry?.dag_run_id}`; + + switch (kind) { + case "Dag Run": { + navigate(baseUrl); + break; + } + case "Task Instance": { + const taskInstance = entry as TaskInstanceResponse; + + navigate(`${baseUrl}/tasks/${taskInstance.task_id}`); + break; + } + default: + } + }, + onHover: (_event, elements, chart) => { + chart.canvas.style.cursor = elements.length > 0 ? "pointer" : "default"; + }, plugins: { annotation: { annotations: { @@ -158,7 +188,6 @@ export const DurationChart = ({ }, title: { align: "end", display: true, text: "Run After" }, }, - y: { title: { align: "end", display: true, text: "Duration (seconds)" }, },
