You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2025/02/27 19:48:08 UTC

(airflow) branch main updated: Create list backfills tab in dag page (#46772)

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 33aaa34f063 Create list backfills tab in dag page (#46772)
33aaa34f063 is described below

commit 33aaa34f063e1553d57d1d1f82a66c1ef5828383
Author: Aritra Basu <24...@users.noreply.github.com>
AuthorDate: Fri Feb 28 01:18:02 2025 +0530

    Create list backfills tab in dag page (#46772)
    
    * WIP: List Backfills
    
    * Resolve review comments
    
    * Removed id and split dates into from-to
    
    * Updated duration
    
    * Append s to duration field
    
    * Remove sorting and adding new columns
    
    * Updated icon in dag
---
 airflow/ui/src/pages/Dag/Backfills/Backfills.tsx | 135 +++++++++++++++++++++++
 airflow/ui/src/pages/Dag/Backfills/index.ts      |  20 ++++
 airflow/ui/src/pages/Dag/Dag.tsx                 |   3 +-
 airflow/ui/src/router.tsx                        |   2 +
 4 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx b/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
new file mode 100644
index 00000000000..30dc9649b23
--- /dev/null
+++ b/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
@@ -0,0 +1,135 @@
+/*!
+ * 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 { Box, Heading, Text } from "@chakra-ui/react";
+import type { ColumnDef } from "@tanstack/react-table";
+import { useParams } from "react-router-dom";
+
+import { useBackfillServiceListBackfills } from "openapi/queries";
+import type { BackfillResponse } from "openapi/requests/types.gen";
+import { DataTable } from "src/components/DataTable";
+import { useTableURLState } from "src/components/DataTable/useTableUrlState";
+import { ErrorAlert } from "src/components/ErrorAlert";
+import Time from "src/components/Time";
+import { reprocessBehaviors } from "src/constants/reprocessBehaviourParams";
+import { getDuration, pluralize } from "src/utils";
+
+const columns: Array<ColumnDef<BackfillResponse>> = [
+  {
+    accessorKey: "reprocess_behavior",
+    cell: ({ row }) => (
+      <Text>
+        {
+          reprocessBehaviors.find((rb: { value: string }) => rb.value === row.original.reprocess_behavior)
+            ?.label
+        }
+      </Text>
+    ),
+    enableSorting: false,
+    header: "Reprocess Behavior",
+  },
+  {
+    accessorKey: "max_active_runs",
+    enableSorting: false,
+    header: "Max Active Runs",
+  },
+  {
+    accessorKey: "created_at",
+    cell: ({ row }) => (
+      <Text>
+        <Time datetime={row.original.created_at} />
+      </Text>
+    ),
+    enableSorting: false,
+    header: "Created at",
+  },
+  {
+    accessorKey: "completed_at",
+    cell: ({ row }) => (
+      <Text>
+        <Time datetime={row.original.completed_at} />
+      </Text>
+    ),
+    enableSorting: false,
+    header: "Completed at",
+  },
+  {
+    accessorKey: "date_from",
+    cell: ({ row }) => (
+      <Text>
+        <Time datetime={row.original.from_date} />
+      </Text>
+    ),
+    enableSorting: false,
+    header: "From",
+  },
+  {
+    accessorKey: "date_to",
+    cell: ({ row }) => (
+      <Text>
+        <Time datetime={row.original.to_date} />
+      </Text>
+    ),
+    enableSorting: false,
+    header: "To",
+  },
+  {
+    accessorKey: "duration",
+    cell: ({ row }) => (
+      <Text>
+        {row.original.completed_at === null
+          ? ""
+          : `${getDuration(row.original.created_at, row.original.completed_at)}s`}
+      </Text>
+    ),
+    enableSorting: false,
+    header: "Duration",
+  },
+];
+
+export const Backfills = () => {
+  const { setTableURLState, tableURLState } = useTableURLState();
+
+  const { pagination } = tableURLState;
+
+  const { dagId = "" } = useParams();
+
+  const { data, error, isFetching, isLoading } = useBackfillServiceListBackfills({
+    dagId,
+    limit: pagination.pageSize,
+    offset: pagination.pageIndex * pagination.pageSize,
+  });
+
+  return (
+    <Box>
+      <ErrorAlert error={error} />
+      <Heading my={1} size="md">
+        {pluralize("Backfill", data ? data.total_entries : 0)}
+      </Heading>
+      <DataTable
+        columns={columns}
+        data={data ? data.backfills : []}
+        isFetching={isFetching}
+        isLoading={isLoading}
+        modelName="Backfill"
+        onStateChange={setTableURLState}
+        total={data ? data.total_entries : 0}
+      />
+    </Box>
+  );
+};
diff --git a/airflow/ui/src/pages/Dag/Backfills/index.ts b/airflow/ui/src/pages/Dag/Backfills/index.ts
new file mode 100644
index 00000000000..bf74d95d550
--- /dev/null
+++ b/airflow/ui/src/pages/Dag/Backfills/index.ts
@@ -0,0 +1,20 @@
+/*!
+ * 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.
+ */
+
+export { Backfills } from "./Backfills";
diff --git a/airflow/ui/src/pages/Dag/Dag.tsx b/airflow/ui/src/pages/Dag/Dag.tsx
index 4f5372689ab..da86ada2c93 100644
--- a/airflow/ui/src/pages/Dag/Dag.tsx
+++ b/airflow/ui/src/pages/Dag/Dag.tsx
@@ -17,7 +17,7 @@
  * under the License.
  */
 import { ReactFlowProvider } from "@xyflow/react";
-import { FiBarChart, FiCode } from "react-icons/fi";
+import { FiBarChart, FiCode, FiRotateCcw } from "react-icons/fi";
 import { LuChartColumn } from "react-icons/lu";
 import { MdOutlineEventNote } from "react-icons/md";
 import { useParams } from "react-router-dom";
@@ -33,6 +33,7 @@ const tabs = [
   { icon: <LuChartColumn />, label: "Overview", value: "" },
   { icon: <FiBarChart />, label: "Runs", value: "runs" },
   { icon: <TaskIcon />, label: "Tasks", value: "tasks" },
+  { icon: <FiRotateCcw />, label: "Backfills", value: "backfills" },
   { icon: <MdOutlineEventNote />, label: "Events", value: "events" },
   { icon: <FiCode />, label: "Code", value: "code" },
 ];
diff --git a/airflow/ui/src/router.tsx b/airflow/ui/src/router.tsx
index d8e0228a77b..38f5332f809 100644
--- a/airflow/ui/src/router.tsx
+++ b/airflow/ui/src/router.tsx
@@ -25,6 +25,7 @@ import { BaseLayout } from "src/layouts/BaseLayout";
 import { DagsLayout } from "src/layouts/DagsLayout";
 import { AssetsList } from "src/pages/AssetsList";
 import { Dag } from "src/pages/Dag";
+import { Backfills } from "src/pages/Dag/Backfills";
 import { Code } from "src/pages/Dag/Code";
 import { Overview } from "src/pages/Dag/Overview";
 import { Tasks } from "src/pages/Dag/Tasks";
@@ -120,6 +121,7 @@ export const routerConfig = [
           { element: <Overview />, index: true },
           { element: <DagRuns />, path: "runs" },
           { element: <Tasks />, path: "tasks" },
+          { element: <Backfills />, path: "backfills" },
           { element: <Events />, path: "events" },
           { element: <Code />, path: "code" },
         ],