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 <[email protected]> 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"} >
