From 1fe796cebea370fe5ecfa5841880331de7e47b23 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 23 Apr 2026 10:55:23 +0000 Subject: [PATCH] feat(ui): migrate permissions views + DeletedKeys/Teams pages - VectorStorePermissions / AgentPermissions: @tremor Text/Badge + @heroicons Database/UserGroup + antd Tooltip \u2192 shadcn Badge + Tooltip + lucide Database/Users. Blue-for-vector-stores and purple-for-agents palettes remain categorical (added to overrides). - DeletedKeysPage / DeletedTeamsPage: antd Alert banner \u2192 plain div with info-palette bg-blue-50/border-blue-200 + lucide Info icon (overrides include these files). Gates: TS \u2713 | Build \u2713. Co-authored-by: yuneng-jiang --- ui/litellm-dashboard/.eslintrc.json | 6 +- .../DeletedKeysPage/DeletedKeysPage.tsx | 19 +++-- .../DeletedTeamsPage/DeletedTeamsPage.tsx | 19 +++-- .../permissions/AgentPermissions.tsx | 84 +++++++++++-------- .../permissions/VectorStorePermissions.tsx | 36 ++++---- 5 files changed, 100 insertions(+), 64 deletions(-) diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index ac7ad5575ef..a7526b0748d 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -49,7 +49,11 @@ "src/components/common_components/DeleteResourceModal.tsx", "src/components/common_components/PremiumLoggingSettings.tsx", "src/components/common_components/AutoRotationView.tsx", - "src/components/agents/agent_card.tsx" + "src/components/agents/agent_card.tsx", + "src/components/permissions/VectorStorePermissions.tsx", + "src/components/permissions/AgentPermissions.tsx", + "src/components/DeletedKeysPage/DeletedKeysPage.tsx", + "src/components/DeletedTeamsPage/DeletedTeamsPage.tsx" ], "rules": { "litellm-ui/no-banned-ui-imports": "off", diff --git a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.tsx b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.tsx index 3d6389e5485..ed2fa0f9bdd 100644 --- a/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.tsx +++ b/ui/litellm-dashboard/src/components/DeletedKeysPage/DeletedKeysPage.tsx @@ -1,6 +1,6 @@ "use client"; import { useState } from "react"; -import { Alert } from "antd"; +import { Info } from "lucide-react"; import { useDeletedKeys } from "@/app/(dashboard)/hooks/keys/useKeys"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; import { DeletedKeysTable } from "./DeletedKeysTable/DeletedKeysTable"; @@ -19,13 +19,16 @@ export default function DeletedKeysPage() { return (
{!premiumUser && ( - +
+ +
+
Coming soon to Enterprise
+
+ Deleted key auditing is graduating from beta into our Enterprise + audit & compliance suite. +
+
+
)} {!premiumUser && ( - +
+ +
+
Coming soon to Enterprise
+
+ Deleted team auditing is graduating from beta into our Enterprise + audit & compliance suite. +
+
+
)} ; + // eslint-disable-next-line @typescript-eslint/no-explicit-any agent_card_params?: Record; } @@ -17,14 +24,13 @@ interface AgentPermissionsProps { accessToken?: string | null; } -export function AgentPermissions({ - agents, - agentAccessGroups = [], - accessToken +export function AgentPermissions({ + agents, + agentAccessGroups = [], + accessToken, }: AgentPermissionsProps) { const [agentDetails, setAgentDetails] = useState([]); - // Fetch agent details when component mounts useEffect(() => { const fetchAgentDetails = async () => { if (accessToken && agents.length > 0) { @@ -41,53 +47,64 @@ export function AgentPermissions({ fetchAgentDetails(); }, [accessToken, agents.length]); - // Function to get display name for agent const getAgentDisplayName = (agentId: string) => { - const agentDetail = agentDetails.find((agent) => agent.agent_id === agentId); + const agentDetail = agentDetails.find((a) => a.agent_id === agentId); if (agentDetail) { - const truncatedId = agentId.length > 7 ? `${agentId.slice(0, 3)}...${agentId.slice(-4)}` : agentId; + const truncatedId = + agentId.length > 7 + ? `${agentId.slice(0, 3)}...${agentId.slice(-4)}` + : agentId; return `${agentDetail.agent_name} (${truncatedId})`; } return agentId; }; - // Merge agents and access groups into one list const mergedItems = [ ...agents.map((agent) => ({ type: "agent", value: agent })), - ...agentAccessGroups.map((group) => ({ type: "accessGroup", value: group })), + ...agentAccessGroups.map((group) => ({ + type: "accessGroup", + value: group, + })), ]; const totalCount = mergedItems.length; return (
- - Agents - + + Agents + {totalCount}
- + {totalCount > 0 ? (
{mergedItems.map((item, index) => (
-
+
{item.type === "agent" ? ( - -
- - {getAgentDisplayName(item.value)} -
-
+ + + +
+ + + {getAgentDisplayName(item.value)} + +
+
+ Full ID: {item.value} +
+
) : (
- - {item.value} - + + + {item.value} + + Group
@@ -98,9 +115,11 @@ export function AgentPermissions({ ))}
) : ( -
- - No agents or access groups configured +
+ + + No agents or access groups configured +
)}
@@ -108,4 +127,3 @@ export function AgentPermissions({ } export default AgentPermissions; - diff --git a/ui/litellm-dashboard/src/components/permissions/VectorStorePermissions.tsx b/ui/litellm-dashboard/src/components/permissions/VectorStorePermissions.tsx index 8541d65e11f..399d085b71f 100644 --- a/ui/litellm-dashboard/src/components/permissions/VectorStorePermissions.tsx +++ b/ui/litellm-dashboard/src/components/permissions/VectorStorePermissions.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; -import { Text, Badge } from "@tremor/react"; -import { DatabaseIcon } from "@heroicons/react/outline"; +import { Badge } from "@/components/ui/badge"; +import { Database } from "lucide-react"; import { vectorStoreListCall } from "../networking"; interface VectorStoreDetails { @@ -13,10 +13,14 @@ interface VectorStorePermissionsProps { accessToken?: string | null; } -export function VectorStorePermissions({ vectorStores, accessToken }: VectorStorePermissionsProps) { - const [vectorStoreDetails, setVectorStoreDetails] = useState([]); +export function VectorStorePermissions({ + vectorStores, + accessToken, +}: VectorStorePermissionsProps) { + const [vectorStoreDetails, setVectorStoreDetails] = useState< + VectorStoreDetails[] + >([]); - // Fetch vector store details when component mounts useEffect(() => { const fetchVectorStores = async () => { if (!accessToken || vectorStores.length === 0) return; @@ -25,6 +29,7 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor const response = await vectorStoreListCall(accessToken); if (response.data) { setVectorStoreDetails( + // eslint-disable-next-line @typescript-eslint/no-explicit-any response.data.map((store: any) => ({ vector_store_id: store.vector_store_id, vector_store_name: store.vector_store_name, @@ -39,9 +44,10 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor fetchVectorStores(); }, [accessToken, vectorStores.length]); - // Function to get display name for vector store const getVectorStoreDisplayName = (storeId: string) => { - const storeDetail = vectorStoreDetails.find((store) => store.vector_store_id === storeId); + const storeDetail = vectorStoreDetails.find( + (store) => store.vector_store_id === storeId, + ); if (storeDetail) { return `${storeDetail.vector_store_name || storeDetail.vector_store_id} (${storeDetail.vector_store_id})`; } @@ -51,9 +57,9 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor return (
- - Vector Stores - + + Vector Stores + {vectorStores.length}
@@ -63,16 +69,18 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor {vectorStores.map((store, index) => (
{getVectorStoreDisplayName(store)}
))}
) : ( -
- - No vector stores configured +
+ + + No vector stores configured +
)}