diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index 980385bbf56..2cfb4a1f4c7 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -53,6 +53,7 @@ "src/components/agents/agent_card.tsx", "src/components/agents/agent_table.tsx", "src/components/view_users/columns.tsx", + "src/components/Projects/ProjectsPage.tsx", "src/components/permissions/VectorStorePermissions.tsx", "src/components/permissions/AgentPermissions.tsx", "src/components/permissions/MCPServerPermissions.tsx", diff --git a/ui/litellm-dashboard/src/components/Projects/ProjectsPage.tsx b/ui/litellm-dashboard/src/components/Projects/ProjectsPage.tsx index f0b593c2e49..95bf85a8416 100644 --- a/ui/litellm-dashboard/src/components/Projects/ProjectsPage.tsx +++ b/ui/litellm-dashboard/src/components/Projects/ProjectsPage.tsx @@ -1,32 +1,33 @@ -import { useProjects, ProjectResponse } from "@/app/(dashboard)/hooks/projects/useProjects"; -import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; -import { LoadingOutlined, PlusOutlined } from "@ant-design/icons"; import { - Button, - Card, - Flex, - Input, - Layout, - Pagination, - Space, - Spin, - Table, - Tag, - theme, + useProjects, + ProjectResponse, +} from "@/app/(dashboard)/hooks/projects/useProjects"; +import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Tooltip, - Typography, -} from "antd"; + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { Table } from "antd"; import type { ColumnsType } from "antd/es/table"; -import { LayersIcon, SearchIcon } from "lucide-react"; +import { + ChevronLeft, + ChevronRight, + Layers, + Loader2, + Plus, + Search, +} from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { CreateProjectModal } from "./ProjectModals/CreateProjectModal"; import { ProjectDetail } from "./ProjectDetailsPage"; -const { Title, Text } = Typography; -const { Content } = Layout; - export function ProjectsPage() { - const { token } = theme.useToken(); const { data: projects, isLoading } = useProjects(); const { data: teams, isLoading: isTeamsLoading } = useTeams(); @@ -73,16 +74,19 @@ export function ProjectsPage() { key: "project_id", width: 170, render: (id: string) => ( - - setSelectedProjectId(id)} - > - {id} - - + + + + setSelectedProjectId(id)} + className="text-blue-500 bg-blue-50 hover:bg-blue-100 dark:bg-blue-950/30 dark:hover:bg-blue-950/60 text-sm cursor-pointer px-2 py-0.5 rounded inline-block truncate max-w-[160px]" + > + {id} + + + {id} + + ), }, { @@ -104,7 +108,8 @@ export function ProjectsPage() { if (!record.team_id) return "—"; const alias = teamAliasMap.get(record.team_id); if (alias) return alias; - if (isTeamsLoading) return } size="small" />; + if (isTeamsLoading) + return ; return record.team_id; }, }, @@ -114,14 +119,19 @@ export function ProjectsPage() { render: (_: unknown, record: ProjectResponse) => { const models = record.models ?? []; return ( - 0 ? models.join(", ") : "No models"}> - - - - {models.length} - - - + + + + + + {models.length} + + + + {models.length > 0 ? models.join(", ") : "No models"} + + + ); }, }, @@ -130,9 +140,15 @@ export function ProjectsPage() { dataIndex: "blocked", key: "status", render: (blocked: boolean) => ( - + {blocked ? "Blocked" : "Active"} - + ), }, { @@ -161,59 +177,69 @@ export function ProjectsPage() { ); } + const totalPages = Math.max(1, Math.ceil(filteredProjects.length / pageSize)); + return ( - - - - - Projects - - +
+
+
+

Projects

+

Manage projects within your teams - - -

+ - +
- - - } - placeholder="Search projects by name, ID, description, or team..." - style={{ maxWidth: 400 }} - value={searchText} - onChange={(e) => setSearchText(e.target.value)} - allowClear - /> - setCurrentPage(page)} - size="small" - showTotal={(total) => `${total} projects`} - showSizeChanger={false} - /> - + +
+
+ + setSearchText(e.target.value)} + /> +
+
+ + {filteredProjects.length} projects + + + + {currentPage}/{totalPages} + + +
+
setIsCreateModalVisible(false)} /> - + ); }