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 d5812660b1e34e9d67dfec97822f1d9ba853564d Author: Brent Bovenzi <[email protected]> AuthorDate: Thu May 1 11:32:21 2025 -0400 Restore hover+selection crosshairs to grid view (#50050) (cherry picked from commit 359447665af41b43913f8cf7a22d9b9b353a7cf9) --- .../airflow/ui/src/layouts/Details/Grid/Grid.tsx | 2 +- .../airflow/ui/src/layouts/Details/Grid/GridTI.tsx | 105 +++++++++++---------- .../ui/src/layouts/Details/Grid/TaskNames.tsx | 22 ++++- 3 files changed, 76 insertions(+), 53 deletions(-) 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 ba4ecad0b01..75fe7209dc8 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 @@ -72,7 +72,7 @@ export const Grid = ({ limit }: Props) => { return ( <Flex justifyContent="flex-start" position="relative" pt={50} width="100%"> - <Box flexGrow={1} minWidth={7} mr={3} position="relative" top="100px"> + <Box flexGrow={1} minWidth={7} position="relative" top="100px"> <TaskNames nodes={flatNodes} /> </Box> <Box position="relative"> diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx index 85a8342d8ac..08a17ea9e75 100644 --- a/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx +++ b/airflow-core/src/airflow/ui/src/layouts/Details/Grid/GridTI.tsx @@ -19,7 +19,7 @@ import { Badge, Flex } from "@chakra-ui/react"; import type { MouseEvent } from "react"; import React from "react"; -import { Link } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import type { TaskInstanceState } from "openapi/requests/types.gen"; import { StateIcon } from "src/components/StateIcon"; @@ -36,7 +36,7 @@ type Props = { }; const onMouseEnter = (event: MouseEvent<HTMLDivElement>) => { - const tasks = document.querySelectorAll<HTMLDivElement>(`#name-${event.currentTarget.id}`); + const tasks = document.querySelectorAll<HTMLDivElement>(`#${event.currentTarget.id}`); tasks.forEach((task) => { task.style.backgroundColor = "var(--chakra-colors-blue-subtle)"; @@ -44,56 +44,32 @@ const onMouseEnter = (event: MouseEvent<HTMLDivElement>) => { }; const onMouseLeave = (event: MouseEvent<HTMLDivElement>) => { - const tasks = document.querySelectorAll<HTMLDivElement>(`#name-${event.currentTarget.id}`); + const tasks = document.querySelectorAll<HTMLDivElement>(`#${event.currentTarget.id}`); tasks.forEach((task) => { task.style.backgroundColor = ""; }); }; -const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId }: Props) => ( - <Flex - alignItems="center" - height="20px" - id={taskId.replaceAll(".", "-")} - justifyContent="center" - key={taskId} - onMouseEnter={onMouseEnter} - onMouseLeave={onMouseLeave} - px="2px" - py={0} - transition="background-color 0.2s" - zIndex={1} - > - {isGroup ? ( - <Badge - borderRadius={4} - colorPalette={state === null ? "none" : state} - height="14px" - minH={0} - opacity={state === "success" ? 0.6 : 1} - p={0} - variant="solid" - width="14px" - > - {state === undefined ? undefined : ( - <StateIcon - size={10} - state={state} - style={{ - marginLeft: "2px", - }} - /> - )} - </Badge> - ) : ( - <Link - replace - to={{ - pathname: `/dags/${dagId}/runs/${runId}/tasks/${taskId}${isMapped ? "/mapped" : ""}`, - search, - }} - > +const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId }: Props) => { + const { taskId: selectedTaskId } = useParams(); + + return ( + <Flex + alignItems="center" + bg={selectedTaskId === taskId ? "blue.muted" : undefined} + height="20px" + id={taskId.replaceAll(".", "-")} + justifyContent="center" + key={taskId} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + px="2px" + py={0} + transition="background-color 0.2s" + zIndex={1} + > + {isGroup ? ( <Badge borderRadius={4} colorPalette={state === null ? "none" : state} @@ -114,9 +90,38 @@ const Instance = ({ dagId, isGroup, isMapped, runId, search, state, taskId }: Pr /> )} </Badge> - </Link> - )} - </Flex> -); + ) : ( + <Link + replace + to={{ + pathname: `/dags/${dagId}/runs/${runId}/tasks/${taskId}${isMapped ? "/mapped" : ""}`, + search, + }} + > + <Badge + borderRadius={4} + colorPalette={state === null ? "none" : state} + height="14px" + minH={0} + opacity={state === "success" ? 0.6 : 1} + p={0} + variant="solid" + width="14px" + > + {state === undefined ? undefined : ( + <StateIcon + size={10} + state={state} + style={{ + marginLeft: "2px", + }} + /> + )} + </Badge> + </Link> + )} + </Flex> + ); +}; export const GridTI = React.memo(Instance); 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 4fe7420c8a9..60105579223 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 @@ -17,6 +17,7 @@ * under the License. */ import { Box, chakra, Flex, Link } from "@chakra-ui/react"; +import type { MouseEvent } from "react"; import { FiChevronUp } from "react-icons/fi"; import { Link as RouterLink, useParams, useSearchParams } from "react-router-dom"; @@ -30,6 +31,22 @@ type Props = { nodes: Array<GridTask>; }; +const onMouseEnter = (event: MouseEvent<HTMLDivElement>) => { + const tasks = document.querySelectorAll<HTMLDivElement>(`#${event.currentTarget.id}`); + + tasks.forEach((task) => { + task.style.backgroundColor = "var(--chakra-colors-blue-subtle)"; + }); +}; + +const onMouseLeave = (event: MouseEvent<HTMLDivElement>) => { + const tasks = document.querySelectorAll<HTMLDivElement>(`#${event.currentTarget.id}`); + + tasks.forEach((task) => { + task.style.backgroundColor = ""; + }); +}; + export const TaskNames = ({ nodes }: Props) => { const { toggleGroupId } = useOpenGroups(); const { dagId = "", taskId } = useParams(); @@ -37,13 +54,14 @@ export const TaskNames = ({ nodes }: Props) => { return nodes.map((node) => ( <Box - _hover={{ bg: "blue.subtle" }} bg={node.id === taskId ? "blue.muted" : undefined} borderBottomWidth={1} borderColor={node.isGroup ? "border.emphasized" : "border.muted"} - id={`name-${node.id.replaceAll(".", "-")}`} + id={node.id.replaceAll(".", "-")} key={node.id} maxHeight="20px" + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} transition="background-color 0.2s" > {node.isGroup ? (
