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 9dae52a3d3b588dd154d13146aef0a434463d0c2 Author: Jason <[email protected]> AuthorDate: Thu Apr 24 00:36:44 2025 +0700 feature(ui): Make entire task box clickable to select the task in Air… (#49299) * feature(ui): Make entire task node clickable to select the task * Add z-index to TogglePause for clickability * Remove link component * Remove unnecessary onClick handler from LinkOverlay * Forward ref from LinkOverlay (cherry picked from commit 20bdf5fc82415b6d67237794fd49174703af9230) --- .../airflow/ui/src/components/Graph/AssetNode.tsx | 6 ++--- .../airflow/ui/src/components/Graph/DagNode.tsx | 13 +++++++---- .../airflow/ui/src/components/Graph/TaskLink.tsx | 27 +++++++++++----------- .../airflow/ui/src/components/Graph/TaskNode.tsx | 22 ++++++++++-------- 4 files changed, 37 insertions(+), 31 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/components/Graph/AssetNode.tsx b/airflow-core/src/airflow/ui/src/components/Graph/AssetNode.tsx index 3d4539caf01..b95faf0fd86 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/AssetNode.tsx +++ b/airflow-core/src/airflow/ui/src/components/Graph/AssetNode.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Flex, Heading, HStack, Link, Text } from "@chakra-ui/react"; +import { Flex, Heading, HStack, LinkOverlay, Text } from "@chakra-ui/react"; import type { NodeProps, Node as NodeType } from "@xyflow/react"; import { FiDatabase } from "react-icons/fi"; import { useParams, Link as RouterLink } from "react-router-dom"; @@ -69,9 +69,9 @@ export const AssetNode = ({ <Heading ml={-2} size="sm"> <FiDatabase /> </Heading> - <Link asChild color="fg.info"> + <LinkOverlay asChild> <RouterLink to={`/assets/${assetId}`}>{label}</RouterLink> - </Link> + </LinkOverlay> </HStack> {assetEvent === undefined ? undefined : ( <> diff --git a/airflow-core/src/airflow/ui/src/components/Graph/DagNode.tsx b/airflow-core/src/airflow/ui/src/components/Graph/DagNode.tsx index 73dfaf537f4..83b3db2d4d0 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/DagNode.tsx +++ b/airflow-core/src/airflow/ui/src/components/Graph/DagNode.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Flex, HStack, Link } from "@chakra-ui/react"; +import { Flex, HStack, LinkOverlay } from "@chakra-ui/react"; import type { NodeProps, Node as NodeType } from "@xyflow/react"; import { Link as RouterLink } from "react-router-dom"; @@ -47,11 +47,16 @@ export const DagNode = ({ > <HStack alignItems="center" justifyContent="space-between"> <DagIcon /> - <TogglePause dagId={dag?.dag_id ?? label} disabled={!Boolean(dag)} isPaused={dag?.is_paused} /> + <TogglePause + dagId={dag?.dag_id ?? label} + disabled={!Boolean(dag)} + isPaused={dag?.is_paused} + style={{ zIndex: 2 }} + /> </HStack> - <Link asChild color="fg.info" mb={2}> + <LinkOverlay asChild> <RouterLink to={`/dags/${dag?.dag_id ?? label}`}>{dag?.dag_display_name ?? label}</RouterLink> - </Link> + </LinkOverlay> </Flex> </NodeWrapper> ); diff --git a/airflow-core/src/airflow/ui/src/components/Graph/TaskLink.tsx b/airflow-core/src/airflow/ui/src/components/Graph/TaskLink.tsx index 685e79737ec..278c6af3092 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/TaskLink.tsx +++ b/airflow-core/src/airflow/ui/src/components/Graph/TaskLink.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Link } from "@chakra-ui/react"; +import { forwardRef } from "react"; import { useParams, useSearchParams, Link as RouterLink } from "react-router-dom"; import { TaskName, type TaskNameProps } from "src/components/TaskName"; @@ -25,7 +25,7 @@ type Props = { readonly id: string; } & TaskNameProps; -export const TaskLink = ({ id, isGroup, isMapped, ...rest }: Props) => { +export const TaskLink = forwardRef<HTMLAnchorElement, Props>(({ id, isGroup, isMapped, ...rest }, ref) => { const { dagId = "", runId, taskId } = useParams(); const [searchParams] = useSearchParams(); @@ -35,16 +35,15 @@ export const TaskLink = ({ id, isGroup, isMapped, ...rest }: Props) => { } return ( - <Link asChild data-testid={id}> - <RouterLink - to={{ - // Do not include runId if there is no selected run, clicking a second time will deselect a task id - pathname: `/dags/${dagId}/${runId === undefined ? "" : `runs/${runId}/`}${taskId === id ? "" : `tasks/${id}`}${isMapped && taskId !== id && runId !== undefined ? "/mapped" : ""}`, - search: searchParams.toString(), - }} - > - <TaskName isMapped={isMapped} {...rest} /> - </RouterLink> - </Link> + <RouterLink + ref={ref} + to={{ + // Do not include runId if there is no selected run, clicking a second time will deselect a task id + pathname: `/dags/${dagId}/${runId === undefined ? "" : `runs/${runId}/`}${taskId === id ? "" : `tasks/${id}`}${isMapped && taskId !== id && runId !== undefined ? "/mapped" : ""}`, + search: searchParams.toString(), + }} + > + <TaskName isMapped={isMapped} {...rest} /> + </RouterLink> ); -}; +}); diff --git a/airflow-core/src/airflow/ui/src/components/Graph/TaskNode.tsx b/airflow-core/src/airflow/ui/src/components/Graph/TaskNode.tsx index 657b6d51cd1..6f513066a13 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/TaskNode.tsx +++ b/airflow-core/src/airflow/ui/src/components/Graph/TaskNode.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { Box, Button, Flex, HStack, Text } from "@chakra-ui/react"; +import { Box, Button, Flex, HStack, LinkOverlay, Text } from "@chakra-ui/react"; import type { NodeProps, Node as NodeType } from "@xyflow/react"; import { CgRedo } from "react-icons/cg"; @@ -78,15 +78,17 @@ export const TaskNode = ({ width={`${width + (isSelected ? 4 : 0)}px`} > <Box> - <TaskLink - childCount={taskInstance?.task_count} - id={id} - isGroup={isGroup} - isMapped={isMapped} - isOpen={isOpen} - label={label} - setupTeardownType={setupTeardownType} - /> + <LinkOverlay asChild> + <TaskLink + childCount={taskInstance?.task_count} + id={id} + isGroup={isGroup} + isMapped={isMapped} + isOpen={isOpen} + label={label} + setupTeardownType={setupTeardownType} + /> + </LinkOverlay> <Text color="fg.muted" fontSize="sm" textTransform="capitalize"> {isGroup ? "Task Group" : operator} </Text>
