You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ka...@apache.org on 2025/05/06 13:25:29 UTC
(airflow) 18/25: Added focus view on grid and graph on second click (#50125)
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 44bb1010372eaabb39a87a232d97531888b82f09
Author: Dominic Leung <le...@gmail.com>
AuthorDate: Sat May 3 05:31:37 2025 +0800
Added focus view on grid and graph on second click (#50125)
(cherry picked from commit e28d460d9fbfe8fc9679ed4bcce5b84872925ec2)
---
.../ui/src/layouts/Details/DetailsLayout.tsx | 12 ++++++--
.../ui/src/layouts/Details/PanelButtons.tsx | 35 ++++++++++++++++++++--
2 files changed, 42 insertions(+), 5 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 69d32034fc4..bae001db6f3 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
@@ -18,6 +18,7 @@
*/
import { Box, HStack, Flex, useDisclosure } from "@chakra-ui/react";
import { useReactFlow } from "@xyflow/react";
+import { useRef } from "react";
import type { PropsWithChildren, ReactNode } from "react";
import { LuFileWarning } from "react-icons/lu";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
@@ -53,6 +54,7 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => {
const { data: dag } = useDagServiceGetDag({ dagId });
const [defaultDagView] = useLocalStorage<"graph" | "grid">("default_dag_view", "grid");
+ const panelGroupRef = useRef(null);
const [dagView, setDagView] = useLocalStorage<"graph" | "grid">(`dag_view-${dagId}`, defaultDagView);
const [limit, setLimit] = useLocalStorage<number>(`dag_runs_limit-${dagId}`, 10);
@@ -75,10 +77,16 @@ export const DetailsLayout = ({ children, error, isLoading, tabs }: Props) => {
<Toaster />
<BackfillBanner dagId={dagId} />
<Box flex={1} minH={0}>
- <PanelGroup autoSaveId={dagId} direction="horizontal">
+ <PanelGroup autoSaveId={dagId} direction="horizontal" ref={panelGroupRef}>
<Panel defaultSize={dagView === "graph" ? 70 : 20} minSize={6}>
<Box height="100%" overflowY="auto" position="relative" pr={2}>
- <PanelButtons dagView={dagView} limit={limit} setDagView={setDagView} setLimit={setLimit} />
+ <PanelButtons
+ dagView={dagView}
+ limit={limit}
+ panelGroupRef={panelGroupRef}
+ setDagView={setDagView}
+ setLimit={setLimit}
+ />
{dagView === "graph" ? <Graph /> : <Grid limit={limit} />}
</Box>
</Panel>
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
index 384eaa407c2..4d18f87d921 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
@@ -26,6 +26,7 @@ import {
Portal,
Select,
} from "@chakra-ui/react";
+import { useReactFlow } from "@xyflow/react";
import { FiChevronDown, FiGrid } from "react-icons/fi";
import { MdOutlineAccountTree } from "react-icons/md";
import { useParams } from "react-router-dom";
@@ -41,6 +42,7 @@ import { ToggleGroups } from "./ToggleGroups";
type Props = {
readonly dagView: string;
readonly limit: number;
+ readonly panelGroupRef: React.RefObject<{ setLayout?: (layout: Array<number>) => void } & HTMLDivElement>;
readonly setDagView: (x: "graph" | "grid") => void;
readonly setLimit: React.Dispatch<React.SetStateAction<number>>;
};
@@ -68,8 +70,9 @@ const deps = ["all", "immediate", "tasks"];
type Dependency = (typeof deps)[number];
-export const PanelButtons = ({ dagView, limit, setDagView, setLimit }: Props) => {
+export const PanelButtons = ({ dagView, limit, panelGroupRef, setDagView, setLimit }: Props) => {
const { dagId = "" } = useParams();
+ const { fitView } = useReactFlow();
const [dependencies, setDependencies, removeDependencies] = useLocalStorage<Dependency>(
`dependencies-${dagId}`,
"tasks",
@@ -97,13 +100,34 @@ export const PanelButtons = ({ dagView, limit, setDagView, setLimit }: Props) =>
}
};
+ const handleFocus = (view: string) => {
+ if (panelGroupRef.current) {
+ const panelGroup = panelGroupRef.current;
+
+ if (typeof panelGroup.setLayout === "function") {
+ const newLayout = view === "graph" ? [70, 30] : [30, 70];
+
+ panelGroup.setLayout(newLayout);
+ // Used setTimeout to ensure DOM has been updated
+ setTimeout(() => {
+ void fitView();
+ }, 1);
+ }
+ }
+ };
+
return (
<Flex justifyContent="space-between" position="absolute" top={1} width="100%" zIndex={1}>
<ButtonGroup attached size="sm" variant="outline">
<IconButton
aria-label="Show Grid"
colorPalette="blue"
- onClick={() => setDagView("grid")}
+ onClick={() => {
+ setDagView("grid");
+ if (dagView === "grid") {
+ handleFocus("grid");
+ }
+ }}
title="Show Grid"
variant={dagView === "grid" ? "solid" : "outline"}
>
@@ -112,7 +136,12 @@ export const PanelButtons = ({ dagView, limit, setDagView, setLimit }: Props) =>
<IconButton
aria-label="Show Graph"
colorPalette="blue"
- onClick={() => setDagView("graph")}
+ onClick={() => {
+ setDagView("graph");
+ if (dagView === "graph") {
+ handleFocus("graph");
+ }
+ }}
title="Show Graph"
variant={dagView === "graph" ? "solid" : "outline"}
>