This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-1-test by this push:
new 9f16920714e [v3-1-test] Move row count and display toggle into
DataTable (#57680) (#60639)
9f16920714e is described below
commit 9f16920714e666d71330bc8ea4000ccb1279274c
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jan 16 16:41:07 2026 +0100
[v3-1-test] Move row count and display toggle into DataTable (#57680)
(#60639)
* add result count to dag run and ti tabs
* conditionally render filter count if count > 0
* remove unused translate
* add optional ToggleTableDisplay element to DataTable component
* move ToggleTableDisplay to DataTable
* make datatable showRowCountHeading default to true and change modelName
to required. update datatable users to disable the heading based on if they
have pluralizable model keys
(cherry picked from commit f59198a6db8967eac946412cf665f77f14b1e9f3)
Co-authored-by: Cameron Billy <[email protected]>
---
.../components/ActionAccordion/ActionAccordion.tsx | 2 +-
.../ui/src/components/Assets/AssetEvents.tsx | 2 +-
.../ui/src/components/DataTable/DataTable.test.tsx | 100 +++++++++++++++++++--
.../ui/src/components/DataTable/DataTable.tsx | 32 ++++++-
.../airflow/ui/src/pages/AssetsList/AssetsList.tsx | 4 +-
.../src/airflow/ui/src/pages/Configs/Configs.tsx | 2 +-
.../ui/src/pages/Connections/Connections.tsx | 2 +-
.../ui/src/pages/Dag/Backfills/Backfills.tsx | 2 +-
.../src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx | 4 +-
airflow-core/src/airflow/ui/src/pages/DagRuns.tsx | 2 +-
.../src/airflow/ui/src/pages/DagsList/DagsList.tsx | 13 +--
.../src/airflow/ui/src/pages/Events/Events.tsx | 3 +-
.../pages/HITLTaskInstances/HITLTaskInstances.tsx | 9 +-
airflow-core/src/airflow/ui/src/pages/Plugins.tsx | 3 +-
.../src/airflow/ui/src/pages/Pools/Pools.tsx | 2 +-
.../src/airflow/ui/src/pages/Providers.tsx | 3 +-
.../ui/src/pages/TaskInstances/TaskInstances.tsx | 2 +-
.../airflow/ui/src/pages/Variables/Variables.tsx | 2 +-
.../src/airflow/ui/src/pages/XCom/XCom.tsx | 3 +-
19 files changed, 154 insertions(+), 38 deletions(-)
diff --git
a/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
b/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
index a08b9744b51..498ada9f821 100644
---
a/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
+++
b/airflow-core/src/airflow/ui/src/components/ActionAccordion/ActionAccordion.tsx
@@ -64,7 +64,7 @@ const ActionAccordion = ({ affectedTasks, note, setNote }:
Props) => {
columns={columns}
data={affectedTasks.task_instances}
displayMode="table"
- modelName={translate("common:taskInstance_other")}
+ modelName="common:taskInstance"
noRowsMessage={translate("dags:runAndTaskActions.affectedTasks.noItemsFound")}
total={affectedTasks.total_entries}
/>
diff --git a/airflow-core/src/airflow/ui/src/components/Assets/AssetEvents.tsx
b/airflow-core/src/airflow/ui/src/components/Assets/AssetEvents.tsx
index 2ac242f297f..373dbb70b9d 100644
--- a/airflow-core/src/airflow/ui/src/components/Assets/AssetEvents.tsx
+++ b/airflow-core/src/airflow/ui/src/components/Assets/AssetEvents.tsx
@@ -113,7 +113,7 @@ export const AssetEvents = ({
displayMode="card"
initialState={tableUrlState}
isLoading={isLoading}
- modelName={translate("common:assetEvent_one")}
+ modelName="common:assetEvent"
noRowsMessage={translate("noAssetEvents")}
onStateChange={setTableUrlState}
skeletonCount={5}
diff --git
a/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.test.tsx
b/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.test.tsx
index e38bcc2de8a..a4713410f36 100644
--- a/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.test.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.test.tsx
@@ -51,6 +51,7 @@ describe("DataTable", () => {
columns={columns}
data={data}
initialState={{ pagination, sorting: [] }}
+ modelName="task"
onStateChange={onStateChange}
total={2}
/>,
@@ -69,6 +70,7 @@ describe("DataTable", () => {
columns={columns}
data={[{ name: "John Doe" }]}
initialState={{ pagination, sorting: [] }}
+ modelName="task"
onStateChange={onStateChange}
total={2}
/>,
@@ -89,6 +91,7 @@ describe("DataTable", () => {
pagination: { pageIndex: 0, pageSize: 10 },
sorting: [],
}}
+ modelName="task"
onStateChange={onStateChange}
total={2}
/>,
@@ -106,6 +109,7 @@ describe("DataTable", () => {
columns={columns}
data={data}
initialState={{ pagination, sorting: [] }}
+ modelName="task"
onStateChange={onStateChange}
total={2}
/>,
@@ -119,7 +123,7 @@ describe("DataTable", () => {
});
it("when isLoading renders skeleton columns", () => {
- render(<DataTable columns={columns} data={data} isLoading />, {
+ render(<DataTable columns={columns} data={data} isLoading modelName="task"
/>, {
wrapper: ChakraWrapper,
});
@@ -127,7 +131,7 @@ describe("DataTable", () => {
});
it("still displays table if mode is card but there is no cardDef", () => {
- render(<DataTable columns={columns} data={data} displayMode="card" />, {
+ render(<DataTable columns={columns} data={data} displayMode="card"
modelName="task" />, {
wrapper: ChakraWrapper,
});
@@ -135,9 +139,12 @@ describe("DataTable", () => {
});
it("displays cards if mode is card and there is cardDef", () => {
- render(<DataTable cardDef={cardDef} columns={columns} data={data}
displayMode="card" />, {
- wrapper: ChakraWrapper,
- });
+ render(
+ <DataTable cardDef={cardDef} columns={columns} data={data}
displayMode="card" modelName="task" />,
+ {
+ wrapper: ChakraWrapper,
+ },
+ );
expect(screen.getByText("My name is John Doe.")).toBeInTheDocument();
});
@@ -150,6 +157,7 @@ describe("DataTable", () => {
data={data}
displayMode="card"
isLoading
+ modelName="task"
skeletonCount={5}
/>,
{
@@ -159,4 +167,86 @@ describe("DataTable", () => {
expect(screen.getAllByTestId("skeleton")).toHaveLength(5);
});
+
+ it("renders row count heading by default when total > 0", () => {
+ render(
+ <DataTable
+ columns={columns}
+ data={data}
+ initialState={{ pagination, sorting: [] }}
+ modelName="task"
+ total={2}
+ />,
+ { wrapper: ChakraWrapper },
+ );
+
+ expect(screen.getByRole("heading")).toHaveTextContent("2 task");
+ });
+
+ it("does not render row count heading when showRowCountHeading is false", ()
=> {
+ render(
+ <DataTable
+ columns={columns}
+ data={data}
+ initialState={{ pagination, sorting: [] }}
+ modelName="task"
+ showRowCountHeading={false}
+ total={2}
+ />,
+ { wrapper: ChakraWrapper },
+ );
+
+ expect(screen.queryByRole("heading")).toBeNull();
+ });
+
+ it("uses translated zero-count model name in empty state", () => {
+ render(
+ <DataTable
+ columns={columns}
+ data={[]}
+ initialState={{ pagination, sorting: [] }}
+ modelName="task"
+ total={0}
+ />,
+ { wrapper: ChakraWrapper },
+ );
+
+ expect(screen.getByText(/noitemsFound/iu)).toBeInTheDocument();
+ });
+
+ it("renders display toggle when showDisplayToggle and onDisplayToggleChange
are provided", () => {
+ const handleToggle = vi.fn();
+
+ render(
+ <DataTable
+ columns={columns}
+ data={data}
+ displayMode="table"
+ initialState={{ pagination, sorting: [] }}
+ modelName="task"
+ onDisplayToggleChange={handleToggle}
+ showDisplayToggle
+ total={2}
+ />,
+ { wrapper: ChakraWrapper },
+ );
+
+ expect(screen.getByLabelText(/toggleTableView/iu)).toBeInTheDocument();
+ });
+
+ it("does not render display toggle without showDisplayToggle", () => {
+ render(
+ <DataTable
+ columns={columns}
+ data={data}
+ displayMode="table"
+ initialState={{ pagination, sorting: [] }}
+ modelName="task"
+ total={2}
+ />,
+ { wrapper: ChakraWrapper },
+ );
+
+ expect(screen.queryByLabelText(/toggleTableView/iu)).toBeNull();
+ });
});
diff --git a/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsx
b/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsx
index 84644621689..6f3a261a13b 100644
--- a/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DataTable/DataTable.tsx
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { HStack, Text } from "@chakra-ui/react";
+import { Heading, HStack, Text } from "@chakra-ui/react";
import {
getCoreRowModel,
getExpandedRowModel,
@@ -34,6 +34,7 @@ import { useTranslation } from "react-i18next";
import { CardList } from "src/components/DataTable/CardList";
import { TableList } from "src/components/DataTable/TableList";
+import { ToggleTableDisplay } from
"src/components/DataTable/ToggleTableDisplay";
import { createSkeletonMock } from "src/components/DataTable/skeleton";
import type { CardDef, MetaColumn, TableState } from
"src/components/DataTable/types";
import { ProgressBar, Pagination, Toaster } from "src/components/ui";
@@ -49,10 +50,13 @@ type DataTableProps<TData> = {
readonly initialState?: TableState;
readonly isFetching?: boolean;
readonly isLoading?: boolean;
- readonly modelName?: string;
+ readonly modelName: string;
readonly noRowsMessage?: ReactNode;
+ readonly onDisplayToggleChange?: (mode: "card" | "table") => void;
readonly onStateChange?: (state: TableState) => void;
readonly renderSubComponent?: (props: { row: Row<TData> }) =>
React.ReactElement;
+ readonly showDisplayToggle?: boolean;
+ readonly showRowCountHeading?: boolean;
readonly skeletonCount?: number;
readonly total?: number;
};
@@ -72,7 +76,10 @@ export const DataTable = <TData,>({
isLoading,
modelName,
noRowsMessage,
+ onDisplayToggleChange,
onStateChange,
+ showDisplayToggle,
+ showRowCountHeading = true,
skeletonCount = 10,
total = 0,
}: DataTableProps<TData>) => {
@@ -135,11 +142,30 @@ export const DataTable = <TData,>({
// Default to show columns filter only if there are actually many columns
displayed
const showColumnsFilter = allowFiltering ?? columns.length > 5;
+ const translateModelName = useCallback(
+ (count: number) => translate(modelName, { count }),
+ [modelName, translate],
+ );
+ const showRowCount = Boolean(
+ showRowCountHeading && !Boolean(isLoading) && !Boolean(isFetching) &&
total > 0,
+ );
+ const noRowsModelName = translateModelName(0);
+
+ const rowCountHeading = showRowCount ? (
+ <Heading py={3} size="md">
+ {`${total} ${translateModelName(total)}`}
+ </Heading>
+ ) : undefined;
+
return (
<>
<ProgressBar size="xs" visibility={Boolean(isFetching) &&
!Boolean(isLoading) ? "visible" : "hidden"} />
+ {showDisplayToggle && onDisplayToggleChange ? (
+ <ToggleTableDisplay display={display}
setDisplay={onDisplayToggleChange} />
+ ) : undefined}
<Toaster />
{errorMessage}
+ {rowCountHeading}
{hasRows && display === "table" ? (
<TableList allowFiltering={showColumnsFilter} table={table} />
) : undefined}
@@ -148,7 +174,7 @@ export const DataTable = <TData,>({
) : undefined}
{!hasRows && !Boolean(isLoading) && (
<Text as="div" pl={4} pt={1}>
- {noRowsMessage ?? translate("noItemsFound", { modelName })}
+ {noRowsMessage ?? translate("noItemsFound", { modelName:
noRowsModelName })}
</Text>
)}
{hasPagination ? (
diff --git a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
index 0d041b23a0d..f45520c765a 100644
--- a/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/AssetsList/AssetsList.tsx
@@ -163,7 +163,6 @@ export const AssetsList = () => {
<Heading py={3} size="md">
{data?.total_entries} {translate("common:asset", { count:
data?.total_entries })}
</Heading>
-
<ExpandCollapseButtons
collapseLabel={translate("common:collapseAllExtra")}
expandLabel={translate("common:expandAllExtra")}
@@ -179,8 +178,9 @@ export const AssetsList = () => {
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("common:asset_one")}
+ modelName="common:asset"
onStateChange={setTableURLState}
+ showRowCountHeading={false}
total={data?.total_entries}
/>
</Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
b/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
index f194da70113..ce83091f579 100644
--- a/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Configs/Configs.tsx
@@ -68,7 +68,7 @@ export const Configs = () => {
<Heading mb={4}>{translate("config.title")}</Heading>
<Separator />
{error === null ? (
- <DataTable columns={columns} data={render}
modelName={translate("common:admin.Config")} />
+ <DataTable columns={columns} data={render}
modelName="common:admin.Config" />
) : (
<ErrorAlert error={error} />
)}
diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
index 0a32dc613a9..2ce24264d89 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/Connections.tsx
@@ -198,7 +198,7 @@ export const Connections = () => {
initialState={tableURLState}
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("common:admin.Connections")}
+ modelName="admin:connections.connection"
noRowsMessage={<NothingFoundInfo />}
onStateChange={setTableURLState}
total={data?.total_entries ?? 0}
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
index 983daf46c4f..2e28f54949e 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Backfills/Backfills.tsx
@@ -131,7 +131,7 @@ export const Backfills = () => {
data={data ? data.backfills : []}
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("backfill_one")}
+ modelName="common:backfill"
onStateChange={setTableURLState}
total={data ? data.total_entries : 0}
/>
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
index e378b5c63ae..c74723ce775 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Tasks/Tasks.tsx
@@ -17,7 +17,6 @@
* under the License.
*/
import { Skeleton, Box } from "@chakra-ui/react";
-import { useTranslation } from "react-i18next";
import { useParams, useSearchParams } from "react-router-dom";
import { useTaskServiceGetTasks } from "openapi/queries";
@@ -40,7 +39,6 @@ const cardDef = (dagId: string): CardDef<TaskResponse> => ({
export const Tasks = () => {
const { dagId = "" } = useParams();
const { MAPPED, NAME_PATTERN, OPERATOR, RETRIES, TRIGGER_RULE } =
SearchParamsKeys;
- const { t: translate } = useTranslation();
const [searchParams] = useSearchParams();
const selectedOperators = searchParams.getAll(OPERATOR);
const selectedTriggerRules = searchParams.getAll(TRIGGER_RULE);
@@ -100,7 +98,7 @@ export const Tasks = () => {
displayMode="card"
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("task_one")}
+ modelName="common:task"
total={data ? data.total_entries : 0}
/>
</Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
index 1af0ffe1afb..7981f12ec1b 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagRuns.tsx
@@ -384,7 +384,7 @@ export const DagRuns = () => {
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("common:dagRun_other")}
+ modelName="common:dagRun"
onStateChange={setTableURLState}
total={data?.total_entries}
/>
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
index b5445058873..748cf5772bb 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
@@ -38,7 +38,6 @@ import DeleteDagButton from
"src/components/DagActions/DeleteDagButton";
import { FavoriteDagButton } from
"src/components/DagActions/FavoriteDagButton";
import DagRunInfo from "src/components/DagRunInfo";
import { DataTable } from "src/components/DataTable";
-import { ToggleTableDisplay } from
"src/components/DataTable/ToggleTableDisplay";
import type { CardDef } from "src/components/DataTable/types";
import { useTableURLState } from "src/components/DataTable/useTableUrlState";
import { ErrorAlert } from "src/components/ErrorAlert";
@@ -288,6 +287,8 @@ export const DagsList = () => {
[pagination, setTableURLState],
);
+ const totalEntries = data?.total_entries ?? 0;
+
return (
<DagsLayout>
<VStack alignItems="none">
@@ -301,7 +302,7 @@ export const DagsList = () => {
<HStack justifyContent="space-between">
<HStack>
<Heading py={3} size="md">
- {`${data?.total_entries ?? 0} ${translate("dag", { count:
data?.total_entries ?? 0 })}`}
+ {`${totalEntries} ${translate("dag", { count: totalEntries })}`}
</Heading>
<DAGImportErrors iconOnly />
</HStack>
@@ -310,7 +311,6 @@ export const DagsList = () => {
) : undefined}
</HStack>
</VStack>
- <ToggleTableDisplay display={display} setDisplay={setDisplay} />
<Box overflow="auto" pb={8}>
<DataTable
cardDef={cardDef}
@@ -320,10 +320,13 @@ export const DagsList = () => {
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("dag_one")}
+ modelName="common:dag"
+ onDisplayToggleChange={setDisplay}
onStateChange={setTableURLState}
+ showDisplayToggle
+ showRowCountHeading={false}
skeletonCount={display === "card" ? 5 : undefined}
- total={data?.total_entries ?? 0}
+ total={totalEntries}
/>
</Box>
</DagsLayout>
diff --git a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
index 339c4adb989..3685cc90bf9 100644
--- a/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Events/Events.tsx
@@ -236,8 +236,9 @@ export const Events = () => {
initialState={tableURLState}
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("auditLog.columns.event")}
+ modelName="browse:auditLog.columns.event"
onStateChange={setTableURLState}
+ showRowCountHeading={false}
skeletonCount={undefined}
total={data?.total_entries ?? 0}
/>
diff --git
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
index 36151ca155f..ad4d885cce6 100644
---
a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { Heading, Link, VStack } from "@chakra-ui/react";
+import { Link, VStack } from "@chakra-ui/react";
import type { ColumnDef } from "@tanstack/react-table";
import type { TFunction } from "i18next";
import { useCallback, useMemo } from "react";
@@ -192,11 +192,6 @@ export const HITLTaskInstances = () => {
return (
<VStack align="start">
- {!Boolean(dagId) && !Boolean(runId) && !Boolean(taskId) ? (
- <Heading size="md">
- {data?.total_entries} {translate("requiredAction", { count:
data?.total_entries })}
- </Heading>
- ) : undefined}
<HITLFilters onResponseChange={handleResponseChange} />
<DataTable
columns={columns}
@@ -204,7 +199,7 @@ export const HITLTaskInstances = () => {
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("requiredAction_other")}
+ modelName="hitl:requiredAction"
onStateChange={setTableURLState}
total={data?.total_entries}
/>
diff --git a/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
b/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
index 2829c05c311..3c146face8c 100644
--- a/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Plugins.tsx
@@ -58,7 +58,8 @@ export const Plugins = () => {
columns={columns}
data={data?.plugins ?? []}
errorMessage={<ErrorAlert error={error} />}
- modelName={translate("common:admin.Plugins")}
+ modelName="common:admin.Plugins"
+ showRowCountHeading={false}
total={data?.total_entries}
/>
</Box>
diff --git a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
index 8ab1cbfb493..c72311ca2b4 100644
--- a/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Pools/Pools.tsx
@@ -128,7 +128,7 @@ export const Pools = () => {
displayMode="card"
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("common:admin.Pools")}
+ modelName="admin:pools.pool"
noRowsMessage={translate("pools.noPoolsFound")}
onStateChange={setTableURLState}
total={data ? data.total_entries : 0}
diff --git a/airflow-core/src/airflow/ui/src/pages/Providers.tsx
b/airflow-core/src/airflow/ui/src/pages/Providers.tsx
index 9279fb648d9..4fdc6f2ca15 100644
--- a/airflow-core/src/airflow/ui/src/pages/Providers.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Providers.tsx
@@ -97,8 +97,9 @@ export const Providers = () => {
data={data?.providers ?? []}
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
- modelName={translate("common:admin.Providers")}
+ modelName="common:admin.Providers"
onStateChange={setTableURLState}
+ showRowCountHeading={false}
total={data?.total_entries}
/>
</Box>
diff --git
a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
index 911a03debe4..ca642bdca84 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstances/TaskInstances.tsx
@@ -285,7 +285,7 @@ export const TaskInstances = () => {
errorMessage={<ErrorAlert error={error} />}
initialState={tableURLState}
isLoading={isLoading}
- modelName={translate("common:taskInstance_other")}
+ modelName="common:taskInstance"
onStateChange={setTableURLState}
total={data?.total_entries}
/>
diff --git a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
index 7ea75da06ab..c6457fd50d1 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
@@ -211,7 +211,7 @@ export const Variables = () => {
initialState={tableURLState}
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("common:admin.Variables")}
+ modelName="admin:variables.variable"
noRowsMessage={translate("variables.noRowsMessage")}
onStateChange={setTableURLState}
total={data?.total_entries ?? 0}
diff --git a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
index 77cd572d5aa..e3b9f5c0719 100644
--- a/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/XCom/XCom.tsx
@@ -188,8 +188,9 @@ export const XCom = () => {
initialState={tableURLState}
isFetching={isFetching}
isLoading={isLoading}
- modelName={translate("xcom.title")}
+ modelName="browse:xcom.title"
onStateChange={setTableURLState}
+ showRowCountHeading={false}
skeletonCount={undefined}
total={data ? data.total_entries : 0}
/>