This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 466c3992091 Create util for TI links, improve positioning of empty 
states (#45093)
466c3992091 is described below

commit 466c39920919900fd2cb1a1d3718f47beef7fa61
Author: Brent Bovenzi <[email protected]>
AuthorDate: Thu Dec 19 15:46:52 2024 -0500

    Create util for TI links, improve positioning of empty states (#45093)
---
 .../components/ClearRun/ClearRunTaskAccordion.tsx  |  5 ++---
 airflow/ui/src/components/DataTable/DataTable.tsx  |  6 +++---
 airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx        |  5 ++---
 airflow/ui/src/pages/Dag/Tasks/TaskRecentRuns.tsx  |  5 ++---
 airflow/ui/src/pages/Run/TaskInstances.tsx         |  5 ++---
 airflow/ui/src/pages/Task/Instances.tsx            |  9 ++++-----
 airflow/ui/src/pages/TaskInstance/Logs.tsx         |  4 +++-
 airflow/ui/src/pages/TaskInstance/TaskInstance.tsx |  2 +-
 airflow/ui/src/utils/links.ts                      | 22 ++++++++++++++++++++++
 9 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/airflow/ui/src/components/ClearRun/ClearRunTaskAccordion.tsx 
b/airflow/ui/src/components/ClearRun/ClearRunTaskAccordion.tsx
index 5073d124bf2..5f0291e7760 100644
--- a/airflow/ui/src/components/ClearRun/ClearRunTaskAccordion.tsx
+++ b/airflow/ui/src/components/ClearRun/ClearRunTaskAccordion.tsx
@@ -27,6 +27,7 @@ import type {
 } from "openapi/requests/types.gen";
 import { DataTable } from "src/components/DataTable";
 import { Status } from "src/components/ui";
+import { getTaskInstanceLink } from "src/utils/links";
 
 import { Accordion } from "../ui";
 
@@ -35,9 +36,7 @@ const columns: Array<ColumnDef<TaskInstanceResponse>> = [
     accessorKey: "task_display_name",
     cell: ({ row: { original } }) => (
       <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink
-          
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}/tasks/${original.task_id}${original.map_index
 > -1 ? `?map_index=${original.map_index}` : ""}`}
-        >
+        <RouterLink to={getTaskInstanceLink(original)}>
           {original.task_display_name}
         </RouterLink>
       </Link>
diff --git a/airflow/ui/src/components/DataTable/DataTable.tsx 
b/airflow/ui/src/components/DataTable/DataTable.tsx
index 4bcb7c7d066..ee7c07db27a 100644
--- a/airflow/ui/src/components/DataTable/DataTable.tsx
+++ b/airflow/ui/src/components/DataTable/DataTable.tsx
@@ -130,13 +130,13 @@ export const DataTable = <TData,>({
       />
       <Toaster />
       {errorMessage}
-      {!Boolean(isLoading) && !rows.length && (
-        <Text pt={1}>{noRowsMessage ?? `No ${modelName}s found.`}</Text>
-      )}
       {display === "table" && <TableList table={table} />}
       {display === "card" && cardDef !== undefined && (
         <CardList cardDef={cardDef} isLoading={isLoading} table={table} />
       )}
+      {!Boolean(isLoading) && !rows.length && (
+        <Text pt={1}>{noRowsMessage ?? `No ${modelName}s found.`}</Text>
+      )}
       <Pagination.Root
         count={table.getRowCount()}
         my={2}
diff --git a/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx 
b/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx
index d8a2ffe158c..89aa9157792 100644
--- a/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx
+++ b/airflow/ui/src/pages/Dag/Tasks/TaskCard.tsx
@@ -26,6 +26,7 @@ import type {
 import TaskInstanceTooltip from "src/components/TaskInstanceTooltip";
 import Time from "src/components/Time";
 import { Status } from "src/components/ui";
+import { getTaskInstanceLink } from "src/utils/links.ts";
 
 import { TaskRecentRuns } from "./TaskRecentRuns.tsx";
 
@@ -70,9 +71,7 @@ export const TaskCard = ({ dagId, task, taskInstances }: 
Props) => (
         {taskInstances[0] ? (
           <TaskInstanceTooltip taskInstance={taskInstances[0]}>
             <Link asChild color="fg.info" fontSize="sm">
-              <RouterLink
-                
to={`/dags/${dagId}/runs/${taskInstances[0].dag_run_id}/tasks/${task.task_id}`}
-              >
+              <RouterLink to={getTaskInstanceLink(taskInstances[0])}>
                 <Time datetime={taskInstances[0].start_date} />
                 {taskInstances[0].state === null ? undefined : (
                   <Status state={taskInstances[0].state}>
diff --git a/airflow/ui/src/pages/Dag/Tasks/TaskRecentRuns.tsx 
b/airflow/ui/src/pages/Dag/Tasks/TaskRecentRuns.tsx
index 86c125db639..63ae1c07de9 100644
--- a/airflow/ui/src/pages/Dag/Tasks/TaskRecentRuns.tsx
+++ b/airflow/ui/src/pages/Dag/Tasks/TaskRecentRuns.tsx
@@ -23,6 +23,7 @@ import { Link } from "react-router-dom";
 
 import type { TaskInstanceResponse } from "openapi/requests/types.gen";
 import TaskInstanceTooltip from "src/components/TaskInstanceTooltip";
+import { getTaskInstanceLink } from "src/utils/links";
 import { stateColor } from "src/utils/stateColor";
 
 dayjs.extend(duration);
@@ -61,9 +62,7 @@ export const TaskRecentRuns = ({
             key={taskInstance.dag_run_id}
             taskInstance={taskInstance}
           >
-            <Link
-              
to={`/dags/${taskInstance.dag_id}/runs/${taskInstance.dag_run_id}/tasks/${taskInstance.task_id}?map_index=${taskInstance.map_index}`}
-            >
+            <Link to={getTaskInstanceLink(taskInstance)}>
               <Box p={1}>
                 <Box
                   bg={stateColor[taskInstance.state]}
diff --git a/airflow/ui/src/pages/Run/TaskInstances.tsx 
b/airflow/ui/src/pages/Run/TaskInstances.tsx
index c6cef5cf653..ca4817041ab 100644
--- a/airflow/ui/src/pages/Run/TaskInstances.tsx
+++ b/airflow/ui/src/pages/Run/TaskInstances.tsx
@@ -28,15 +28,14 @@ import { ErrorAlert } from "src/components/ErrorAlert";
 import Time from "src/components/Time";
 import { Status } from "src/components/ui";
 import { getDuration } from "src/utils";
+import { getTaskInstanceLink } from "src/utils/links";
 
 const columns: Array<ColumnDef<TaskInstanceResponse>> = [
   {
     accessorKey: "task_display_name",
     cell: ({ row: { original } }) => (
       <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink
-          
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}/tasks/${original.task_id}${original.map_index
 > -1 ? `?map_index=${original.map_index}` : ""}`}
-        >
+        <RouterLink to={getTaskInstanceLink(original)}>
           {original.task_display_name}
         </RouterLink>
       </Link>
diff --git a/airflow/ui/src/pages/Task/Instances.tsx 
b/airflow/ui/src/pages/Task/Instances.tsx
index 7a74a434d01..abf248f1143 100644
--- a/airflow/ui/src/pages/Task/Instances.tsx
+++ b/airflow/ui/src/pages/Task/Instances.tsx
@@ -18,7 +18,6 @@
  */
 import { Box, Link } from "@chakra-ui/react";
 import type { ColumnDef } from "@tanstack/react-table";
-import dayjs from "dayjs";
 import { Link as RouterLink, useParams } from "react-router-dom";
 
 import {
@@ -31,6 +30,8 @@ import { useTableURLState } from 
"src/components/DataTable/useTableUrlState";
 import { ErrorAlert } from "src/components/ErrorAlert";
 import Time from "src/components/Time";
 import { Status } from "src/components/ui";
+import { getDuration } from "src/utils";
+import { getTaskInstanceLink } from "src/utils/links";
 
 const columns = (
   isMapped?: boolean,
@@ -39,9 +40,7 @@ const columns = (
     accessorKey: "dag_run_id",
     cell: ({ row: { original } }) => (
       <Link asChild color="fg.info" fontWeight="bold">
-        <RouterLink
-          
to={`/dags/${original.dag_id}/runs/${original.dag_run_id}/tasks/${original.task_id}`}
-        >
+        <RouterLink to={getTaskInstanceLink(original)}>
           {original.dag_run_id}
         </RouterLink>
       </Link>
@@ -84,7 +83,7 @@ const columns = (
   },
   {
     cell: ({ row: { original } }) =>
-      
`${dayjs.duration(dayjs(original.end_date).diff(original.start_date)).asSeconds().toFixed(2)}s`,
+      `${getDuration(original.start_date, original.end_date)}s`,
     header: "Duration",
   },
 ];
diff --git a/airflow/ui/src/pages/TaskInstance/Logs.tsx 
b/airflow/ui/src/pages/TaskInstance/Logs.tsx
index 6069dc7c716..95a168f4d80 100644
--- a/airflow/ui/src/pages/TaskInstance/Logs.tsx
+++ b/airflow/ui/src/pages/TaskInstance/Logs.tsx
@@ -81,7 +81,9 @@ export const Logs = () => {
   return (
     <Box p={2}>
       <HStack justifyContent="space-between" mb={2}>
-        {taskInstance === undefined ? (
+        {taskInstance === undefined ||
+        tryNumber === undefined ||
+        tryNumber <= 1 ? (
           <div />
         ) : (
           <TaskTrySelect
diff --git a/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx 
b/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
index f665bbdd4fa..e3b14364c6f 100644
--- a/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
+++ b/airflow/ui/src/pages/TaskInstance/TaskInstance.tsx
@@ -74,7 +74,7 @@ export const TaskInstance = () => {
   ];
 
   if (mapIndexParam !== null) {
-    links.push({ label: mapIndexParam });
+    links.push({ label: taskInstance?.rendered_map_index ?? mapIndexParam });
   }
 
   return (
diff --git a/airflow/ui/src/utils/links.ts b/airflow/ui/src/utils/links.ts
new file mode 100644
index 00000000000..18be2bb642b
--- /dev/null
+++ b/airflow/ui/src/utils/links.ts
@@ -0,0 +1,22 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import type { TaskInstanceResponse } from "openapi/requests/types.gen";
+
+export const getTaskInstanceLink = (ti: TaskInstanceResponse) =>
+  `/dags/${ti.dag_id}/runs/${ti.dag_run_id}/tasks/${ti.task_id}${ti.map_index 
>= 0 ? `?map_index=${ti.map_index}` : ""}`;

Reply via email to