This is an automated email from the ASF dual-hosted git repository. kaxilnaik pushed a commit to branch v3-1-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 8115e36743aca18194435a875dfb621d24b8eaa7 Author: Guan Ming(Wesley) Chiu <[email protected]> AuthorDate: Fri Sep 19 06:44:05 2025 +0800 Fix filter in gantt and grid view (#55845) (cherry picked from commit a69fd9b1a6a215b7d716cbb0ab205a097b4061b1) --- .../airflow/ui/src/layouts/Details/DetailsLayout.tsx | 4 +++- .../airflow/ui/src/layouts/Details/Gantt/Gantt.tsx | 20 ++++++++++++++------ .../src/airflow/ui/src/layouts/Details/Grid/Grid.tsx | 8 +++++++- .../ui/src/layouts/Details/Grid/TaskNames.tsx | 3 ++- .../src/airflow/ui/src/queries/useGridTISummaries.ts | 4 +++- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx index c19d621ba9a..f7d4662ca05 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx @@ -153,7 +153,9 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => { showGantt={Boolean(runId) && showGantt} triggeringUser={triggeringUserFilter} /> - {showGantt ? <Gantt limit={limit} /> : undefined} + {showGantt ? ( + <Gantt limit={limit} runType={runTypeFilter} triggeringUser={triggeringUserFilter} /> + ) : undefined} </HStack> )} </Box> diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx index ff522f06376..57121c1921b 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx @@ -40,6 +40,7 @@ import { useTranslation } from "react-i18next"; import { useParams, useNavigate, useLocation } from "react-router-dom"; import { useTaskInstanceServiceGetTaskInstances } from "openapi/queries"; +import type { DagRunType } from "openapi/requests/types.gen"; import { useColorMode } from "src/context/colorMode"; import { useHover } from "src/context/hover"; import { useOpenGroups } from "src/context/openGroups"; @@ -70,13 +71,15 @@ ChartJS.register( type Props = { readonly limit: number; + readonly runType?: DagRunType | undefined; + readonly triggeringUser?: string | undefined; }; const CHART_PADDING = 36; const CHART_ROW_HEIGHT = 20; const MIN_BAR_WIDTH = 10; -export const Gantt = ({ limit }: Props) => { +export const Gantt = ({ limit, runType, triggeringUser }: Props) => { const { dagId = "", groupId: selectedGroupId, runId = "", taskId: selectedTaskId } = useParams(); const { openGroupIds } = useOpenGroups(); const deferredOpenGroupIds = useDeferredValue(openGroupIds); @@ -99,14 +102,19 @@ export const Gantt = ({ limit }: Props) => { const selectedItemColor = colorMode === "light" ? lightSelectedColor : darkSelectedColor; const hoveredItemColor = colorMode === "light" ? lightHoverColor : darkHoverColor; - const { data: gridRuns, isLoading: runsLoading } = useGridRuns({ limit }); - const { data: dagStructure, isLoading: structureLoading } = useGridStructure({ limit }); + const { data: gridRuns, isLoading: runsLoading } = useGridRuns({ limit, runType, triggeringUser }); + const { data: dagStructure, isLoading: structureLoading } = useGridStructure({ + limit, + runType, + triggeringUser, + }); const selectedRun = gridRuns?.find((run) => run.run_id === runId); const refetchInterval = useAutoRefresh({ dagId }); // Get grid summaries for groups (which have min/max times) const { data: gridTiSummaries, isLoading: summariesLoading } = useGridTiSummaries({ dagId, + enabled: Boolean(selectedRun), runId, state: selectedRun?.state, }); @@ -120,7 +128,7 @@ export const Gantt = ({ limit }: Props) => { }, undefined, { - enabled: Boolean(dagId) && Boolean(runId), + enabled: Boolean(dagId) && Boolean(runId) && Boolean(selectedRun), refetchInterval: (query) => query.state.data?.task_instances.some((ti) => isStatePending(ti.state)) ? refetchInterval : false, }, @@ -205,14 +213,14 @@ export const Gantt = ({ limit }: Props) => { datasets: [ { backgroundColor: data.map((dataItem) => stateColorMap[dataItem.state ?? "none"]), - data, + data: Boolean(selectedRun) ? data : [], maxBarThickness: CHART_ROW_HEIGHT, minBarLength: MIN_BAR_WIDTH, }, ], labels: flatNodes.map((node) => node.id), }), - [data, flatNodes, stateColorMap], + [data, flatNodes, stateColorMap, selectedRun], ); const fixedHeight = flatNodes.length * CHART_ROW_HEIGHT + CHART_PADDING; diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx index 6e47a4fc4f6..8c2537aa29f 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/Grid.tsx @@ -56,6 +56,7 @@ export const Grid = ({ limit, runType, showGantt, triggeringUser }: Props) => { const { dagId = "", runId = "" } = useParams(); const { data: gridRuns, isLoading } = useGridRuns({ limit, runType, triggeringUser }); + const selectedRun = gridRuns?.find((run) => run.run_id === runId); // Check if the selected dag run is inside of the grid response, if not, we'll update the grid filters // Eventually we should redo the api endpoint to make this work better @@ -109,7 +110,12 @@ export const Grid = ({ limit, runType, showGantt, triggeringUser }: Props) => { tabIndex={0} width={showGantt ? "1/2" : "full"} > - <Box flexGrow={1} minWidth={7} position="relative" top="100px"> + <Box + flexGrow={1} + minWidth={7} + position="relative" + top={Boolean(runId) && !Boolean(selectedRun) ? "50px" : "100px"} + > <TaskNames nodes={flatNodes} onRowClick={() => setMode("task")} /> </Box> <Box position="relative"> diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx index 05bf16c83c9..c807458c771 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/TaskNames.tsx @@ -67,11 +67,12 @@ export const TaskNames = ({ nodes, onRowClick }: Props) => { const { dagId = "", groupId, taskId } = useParams(); const [searchParams] = useSearchParams(); - return nodes.map((node) => ( + return nodes.map((node, index) => ( <Box bg={node.id === taskId || node.id === groupId ? "info.muted" : undefined} borderBottomWidth={1} borderColor={node.isGroup ? "border.emphasized" : "border"} + borderTopWidth={index === 0 ? 1 : 0} cursor="pointer" id={node.id.replaceAll(".", "-")} key={node.id} diff --git a/airflow-core/src/airflow/ui/src/queries/useGridTISummaries.ts b/airflow-core/src/airflow/ui/src/queries/useGridTISummaries.ts index 877719a0ab7..51f07ce99e5 100644 --- a/airflow-core/src/airflow/ui/src/queries/useGridTISummaries.ts +++ b/airflow-core/src/airflow/ui/src/queries/useGridTISummaries.ts @@ -22,10 +22,12 @@ import { isStatePending, useAutoRefresh } from "src/utils"; export const useGridTiSummaries = ({ dagId, + enabled, runId, state, }: { dagId: string; + enabled?: boolean; runId: string; state?: TaskInstanceState | null | undefined; }) => { @@ -38,7 +40,7 @@ export const useGridTiSummaries = ({ }, undefined, { - enabled: Boolean(runId) && Boolean(dagId), + enabled: Boolean(runId) && Boolean(dagId) && enabled, placeholderData: (prev) => prev, refetchInterval: (query) => ((state !== undefined && isStatePending(state)) ||
