diff --git a/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsPage.tsx b/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsPage.tsx index 30803d0a004..9dd0cb2ee50 100644 --- a/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsPage.tsx +++ b/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsPage.tsx @@ -2,9 +2,11 @@ import { Alert } from "antd"; import { useDeletedTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; +import { useTranslation } from "react-i18next"; import { DeletedTeamsTable } from "./DeletedTeamsTable/DeletedTeamsTable"; export default function DeletedTeamsPage() { + const { t } = useTranslation(); const { premiumUser } = useAuthorized(); const { data: teamsData, isPending: isLoading, isFetching } = useDeletedTeams(1, 100); @@ -15,8 +17,8 @@ export default function DeletedTeamsPage() { type="info" banner showIcon - message="Coming soon to Enterprise" - description="Deleted team auditing is graduating from beta into our Enterprise audit & compliance suite." + message={t("deletedTeams.deletedTeamsPage.comingSoonToEnterprise")} + description={t("deletedTeams.deletedTeamsPage.enterpriseAuditDescription")} /> )} diff --git a/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsTable/DeletedTeamsTable.tsx b/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsTable/DeletedTeamsTable.tsx index 57260f6bb2d..99083fa4870 100644 --- a/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsTable/DeletedTeamsTable.tsx +++ b/ui/litellm-dashboard/src/components/DeletedTeamsPage/DeletedTeamsTable/DeletedTeamsTable.tsx @@ -11,7 +11,8 @@ import { } from "@tanstack/react-table"; import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, Badge, Text } from "@tremor/react"; import { Tooltip } from "antd"; -import React, { useState } from "react"; +import React, { useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; import { DeletedTeam } from "@/app/(dashboard)/hooks/teams/useTeams"; import { getModelDisplayName } from "@/components/key_team_helpers/fetch_available_models_team_key"; @@ -22,6 +23,7 @@ interface DeletedTeamsTableProps { } export function DeletedTeamsTable({ teams, isLoading, isFetching }: DeletedTeamsTableProps) { + const { t } = useTranslation(); const [sorting, setSorting] = useState([ { id: "deleted_at", @@ -29,161 +31,164 @@ export function DeletedTeamsTable({ teams, isLoading, isFetching }: DeletedTeams }, ]); - const columns: ColumnDef[] = [ - { - id: "team_alias", - accessorKey: "team_alias", - header: "Team Name", - size: 150, - maxSize: 200, - cell: (info) => { - const value = info.getValue() as string; - return ( - - {value || "-"} - - ); - }, - }, - { - id: "team_id", - accessorKey: "team_id", - header: "Team ID", - size: 150, - maxSize: 250, - cell: (info) => { - const value = info.getValue() as string; - return ( - - {value || "-"} - - ); - }, - }, - { - id: "created_at", - accessorKey: "created_at", - header: "Created", - size: 120, - maxSize: 140, - cell: (info) => { - const value = info.getValue(); - return ( - {value ? new Date(value as string).toLocaleDateString() : "-"} - ); - }, - }, - { - id: "spend", - accessorKey: "spend", - header: "Spend (USD)", - size: 100, - maxSize: 140, - cell: (info) => { - const spend = (info.row.original as any).spend as number | undefined; - return ( - {spend !== undefined ? formatNumberWithCommas(spend, 4) : "-"} - ); - }, - }, - { - id: "max_budget", - accessorKey: "max_budget", - header: "Budget (USD)", - size: 110, - maxSize: 150, - cell: (info) => { - const maxBudget = info.getValue() as number | null; - return ( - - {maxBudget === null || maxBudget === undefined ? "No limit" : `$${formatNumberWithCommas(maxBudget)}`} - - ); - }, - }, - { - id: "models", - accessorKey: "models", - header: "Models", - size: 200, - maxSize: 300, - cell: (info) => { - const models = info.getValue() as string[]; - if (!Array.isArray(models) || models.length === 0) { + const columns: ColumnDef[] = useMemo( + () => [ + { + id: "team_alias", + accessorKey: "team_alias", + header: t("deletedTeams.deletedTeamsTable.colTeamName"), + size: 150, + maxSize: 200, + cell: (info) => { + const value = info.getValue() as string; return ( - - All Proxy Models - + + {value || "-"} + ); - } - return ( -
- {models.slice(0, 3).map((model: string, index: number) => - model === "all-proxy-models" ? ( - - All Proxy Models - - ) : ( - - - {model.length > 30 ? `${getModelDisplayName(model).slice(0, 30)}...` : getModelDisplayName(model)} - - - ), - )} - {models.length > 3 && ( - - - +{models.length - 3} {models.length - 3 === 1 ? "more model" : "more models"} - + }, + }, + { + id: "team_id", + accessorKey: "team_id", + header: t("deletedTeams.deletedTeamsTable.colTeamId"), + size: 150, + maxSize: 250, + cell: (info) => { + const value = info.getValue() as string; + return ( + + {value || "-"} + + ); + }, + }, + { + id: "created_at", + accessorKey: "created_at", + header: t("deletedTeams.deletedTeamsTable.colCreated"), + size: 120, + maxSize: 140, + cell: (info) => { + const value = info.getValue(); + return ( + {value ? new Date(value as string).toLocaleDateString() : "-"} + ); + }, + }, + { + id: "spend", + accessorKey: "spend", + header: t("deletedTeams.deletedTeamsTable.colSpend"), + size: 100, + maxSize: 140, + cell: (info) => { + const spend = (info.row.original as any).spend as number | undefined; + return ( + {spend !== undefined ? formatNumberWithCommas(spend, 4) : "-"} + ); + }, + }, + { + id: "max_budget", + accessorKey: "max_budget", + header: t("deletedTeams.deletedTeamsTable.colBudget"), + size: 110, + maxSize: 150, + cell: (info) => { + const maxBudget = info.getValue() as number | null; + return ( + + {maxBudget === null || maxBudget === undefined + ? t("deletedTeams.deletedTeamsTable.noLimit") + : `$${formatNumberWithCommas(maxBudget)}`} + + ); + }, + }, + { + id: "models", + accessorKey: "models", + header: t("deletedTeams.deletedTeamsTable.colModels"), + size: 200, + maxSize: 300, + cell: (info) => { + const models = info.getValue() as string[]; + if (!Array.isArray(models) || models.length === 0) { + return ( + + {t("deletedTeams.deletedTeamsTable.allProxyModels")} - )} -
- ); + ); + } + return ( +
+ {models.slice(0, 3).map((model: string, index: number) => + model === "all-proxy-models" ? ( + + {t("deletedTeams.deletedTeamsTable.allProxyModels")} + + ) : ( + + + {model.length > 30 ? `${getModelDisplayName(model).slice(0, 30)}...` : getModelDisplayName(model)} + + + ), + )} + {models.length > 3 && ( + + {t("deletedTeams.deletedTeamsTable.moreModels", { count: models.length - 3 })} + + )} +
+ ); + }, }, - }, - { - id: "organization_id", - accessorKey: "organization_id", - header: "Organization", - size: 150, - maxSize: 200, - cell: (info) => { - const value = info.getValue() as string; - return ( - - {value || "-"} - - ); + { + id: "organization_id", + accessorKey: "organization_id", + header: t("deletedTeams.deletedTeamsTable.colOrganization"), + size: 150, + maxSize: 200, + cell: (info) => { + const value = info.getValue() as string; + return ( + + {value || "-"} + + ); + }, }, - }, - { - id: "deleted_at", - accessorKey: "deleted_at", - header: "Deleted At", - size: 120, - maxSize: 140, - cell: (info) => { - const value = (info.row.original as any).deleted_at as string | null | undefined; - return {value ? new Date(value).toLocaleDateString() : "-"}; + { + id: "deleted_at", + accessorKey: "deleted_at", + header: t("deletedTeams.deletedTeamsTable.colDeletedAt"), + size: 120, + maxSize: 140, + cell: (info) => { + const value = (info.row.original as any).deleted_at as string | null | undefined; + return {value ? new Date(value).toLocaleDateString() : "-"}; + }, }, - }, - { - id: "deleted_by", - accessorKey: "deleted_by", - header: "Deleted By", - size: 120, - maxSize: 180, - cell: (info) => { - const value = (info.row.original as any).deleted_by as string | null | undefined; - return ( - - {value || "-"} - - ); + { + id: "deleted_by", + accessorKey: "deleted_by", + header: t("deletedTeams.deletedTeamsTable.colDeletedBy"), + size: 120, + maxSize: 180, + cell: (info) => { + const value = (info.row.original as any).deleted_by as string | null | undefined; + return ( + + {value || "-"} + + ); + }, }, - }, - ]; + ], + [t], + ); const table = useReactTable({ data: teams, @@ -205,10 +210,10 @@ export function DeletedTeamsTable({ teams, isLoading, isFetching }: DeletedTeams
{isLoading || isFetching ? ( - Loading... + {t("common.loading")} ) : ( - Showing {teams.length} {teams.length === 1 ? "team" : "teams"} + {t("deletedTeams.deletedTeamsTable.showingTeams", { count: teams.length })} )}
@@ -288,7 +293,7 @@ export function DeletedTeamsTable({ teams, isLoading, isFetching }: DeletedTeams
-

🚅 Loading teams...

+

{t("deletedTeams.deletedTeamsTable.loadingTeams")}

@@ -315,7 +320,7 @@ export function DeletedTeamsTable({ teams, isLoading, isFetching }: DeletedTeams
-

No deleted teams found

+

{t("deletedTeams.deletedTeamsTable.noDeletedTeams")}

diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index 3336722ede0..c08356d26d0 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -8048,5 +8048,30 @@ "loadingKeys": "🚅 Loading keys...", "noDeletedKeys": "No deleted keys found" } + }, + "deletedTeams": { + "deletedTeamsPage": { + "comingSoonToEnterprise": "Coming soon to Enterprise", + "enterpriseAuditDescription": "Deleted team auditing is graduating from beta into our Enterprise audit & compliance suite." + }, + "deletedTeamsTable": { + "colTeamName": "Team Name", + "colTeamId": "Team ID", + "colCreated": "Created", + "colSpend": "Spend (USD)", + "colBudget": "Budget (USD)", + "colModels": "Models", + "colOrganization": "Organization", + "colDeletedAt": "Deleted At", + "colDeletedBy": "Deleted By", + "noLimit": "No limit", + "allProxyModels": "All Proxy Models", + "moreModels_one": "+{{count}} more model", + "moreModels_other": "+{{count}} more models", + "showingTeams_one": "Showing {{count}} team", + "showingTeams_other": "Showing {{count}} teams", + "loadingTeams": "🚅 Loading teams...", + "noDeletedTeams": "No deleted teams found" + } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index d6a77e017ae..6a6c44e7672 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -8048,5 +8048,30 @@ "loadingKeys": "🚅 正在加载密钥...", "noDeletedKeys": "未找到已删除密钥" } + }, + "deletedTeams": { + "deletedTeamsPage": { + "comingSoonToEnterprise": "即将登陆企业版", + "enterpriseAuditDescription": "已删除团队审计功能正从 beta 版升级为企业版审计与合规套件的正式功能。" + }, + "deletedTeamsTable": { + "colTeamName": "团队名称", + "colTeamId": "团队 ID", + "colCreated": "创建时间", + "colSpend": "花费(USD)", + "colBudget": "预算(USD)", + "colModels": "模型", + "colOrganization": "组织", + "colDeletedAt": "删除时间", + "colDeletedBy": "删除人", + "noLimit": "无限制", + "allProxyModels": "所有代理模型", + "moreModels_one": "+{{count}} 个更多模型", + "moreModels_other": "+{{count}} 个更多模型", + "showingTeams_one": "显示 {{count}} 个团队", + "showingTeams_other": "显示 {{count}} 个团队", + "loadingTeams": "🚅 正在加载团队...", + "noDeletedTeams": "未找到已删除团队" + } } }