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 0000000000000..30dc9649b2350 --- /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> = [ + { + accessorKey: "reprocess_behavior", + cell: ({ row }) => ( + + { + reprocessBehaviors.find((rb: { value: string }) => rb.value === row.original.reprocess_behavior) + ?.label + } + + ), + enableSorting: false, + header: "Reprocess Behavior", + }, + { + accessorKey: "max_active_runs", + enableSorting: false, + header: "Max Active Runs", + }, + { + accessorKey: "created_at", + cell: ({ row }) => ( + + + ), + enableSorting: false, + header: "Created at", + }, + { + accessorKey: "completed_at", + cell: ({ row }) => ( + + + ), + enableSorting: false, + header: "Completed at", + }, + { + accessorKey: "date_from", + cell: ({ row }) => ( + + + ), + enableSorting: false, + header: "From", + }, + { + accessorKey: "date_to", + cell: ({ row }) => ( + + + ), + enableSorting: false, + header: "To", + }, + { + accessorKey: "duration", + cell: ({ row }) => ( + + {row.original.completed_at === null + ? "" + : `${getDuration(row.original.created_at, row.original.completed_at)}s`} + + ), + 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 ( + + + + {pluralize("Backfill", data ? data.total_entries : 0)} + + + + ); +}; 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 0000000000000..bf74d95d55056 --- /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 4f5372689ab27..da86ada2c93d3 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: , label: "Overview", value: "" }, { icon: , label: "Runs", value: "runs" }, { icon: , label: "Tasks", value: "tasks" }, + { icon: , label: "Backfills", value: "backfills" }, { icon: , label: "Events", value: "events" }, { icon: , label: "Code", value: "code" }, ]; diff --git a/airflow/ui/src/router.tsx b/airflow/ui/src/router.tsx index c33feb6bbefd4..f291393a985a4 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"; @@ -109,6 +110,7 @@ export const routerConfig = [ { element: , index: true }, { element: , path: "runs" }, { element: , path: "tasks" }, + { element: , path: "backfills" }, { element: , path: "events" }, { element: , path: "code" }, ],