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>

Reply via email to