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

jscheffl 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 a69fd9b1a6a Fix filter in gantt and grid view (#55845)
a69fd9b1a6a is described below

commit a69fd9b1a6a215b7d716cbb0ab205a097b4061b1
Author: Guan Ming(Wesley) Chiu <[email protected]>
AuthorDate: Fri Sep 19 06:44:05 2025 +0800

    Fix filter in gantt and grid view (#55845)
---
 .../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)) ||

Reply via email to