From 365d51b1f6fbf9ade11f521f01ebf5dded81280d Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Thu, 1 Jan 2026 16:25:35 -0800 Subject: [PATCH] Model Page loading skeleton --- .../components/AllModelsTab.tsx | 161 ++++++++++-------- 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx index e5a1b683889..a85e6516585 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx @@ -1,17 +1,17 @@ +import { useModelCostMap } from "@/app/(dashboard)/hooks/models/useModelCostMap"; import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import { useModelCostMap } from "@/app/(dashboard)/hooks/models/useModelCostMap"; import { Team } from "@/components/key_team_helpers/key_list"; import { ModelDataTable } from "@/components/model_dashboard/table"; import { columns } from "@/components/molecules/models/columns"; import { getDisplayModelName } from "@/components/view_model/model_name_display"; -import { transformModelData } from "../utils/modelDataTransformer"; import { InfoCircleOutlined } from "@ant-design/icons"; import { PaginationState } from "@tanstack/react-table"; import { Grid, Select, SelectItem, TabPanel, Text } from "@tremor/react"; import { useEffect, useMemo, useState } from "react"; import { useModelsInfo } from "../../hooks/models/useModels"; - +import { transformModelData } from "../utils/modelDataTransformer"; +import { Skeleton } from "antd"; type ModelViewMode = "all" | "current_team"; interface AllModelsTabProps { @@ -31,8 +31,8 @@ const AllModelsTab = ({ setSelectedModelId, setSelectedTeamId, }: AllModelsTabProps) => { - const { data: rawModelData } = useModelsInfo(); - const { data: modelCostMapData } = useModelCostMap(); + const { data: rawModelData, isLoading: isLoadingModelsInfo } = useModelsInfo(); + const { data: modelCostMapData, isLoading: isLoadingModelCostMap } = useModelCostMap(); const { userId, userRole, premiumUser } = useAuthorized(); const { data: teams } = useTeams(); @@ -61,6 +61,8 @@ const AllModelsTab = ({ pageSize: 50, }); + const isLoading = isLoadingModelsInfo || isLoadingModelCostMap; + const filteredData = useMemo(() => { if (!modelData || !modelData.data || modelData.data.length === 0) { return []; @@ -125,63 +127,71 @@ const AllModelsTab = ({
Current Team: - + {isLoading ? ( + + ) : ( + + )}
View: - + {isLoading ? ( + + ) : ( + + )}
@@ -319,18 +329,23 @@ const AllModelsTab = ({ {/* Results Count and Pagination Controls */}
- - {filteredData.length > 0 - ? `Showing ${pagination.pageIndex * pagination.pageSize + 1} - ${Math.min( - (pagination.pageIndex + 1) * pagination.pageSize, - filteredData.length, - )} of ${filteredData.length} results` - : "Showing 0 results"} - + {isLoading ? ( + + ) : ( + + {filteredData.length > 0 + ? `Showing ${pagination.pageIndex * pagination.pageSize + 1} - ${Math.min( + (pagination.pageIndex + 1) * pagination.pageSize, + filteredData.length, + )} of ${filteredData.length} results` + : "Showing 0 results"} + + )} - {/* Pagination Controls */} - {filteredData.length > pagination.pageSize && ( -
+
+ {isLoading ? ( + + ) : ( + )} + {isLoading ? ( + + ) : ( -
- )} + )} +