From 13512e7abd9214f6b52464edff21b34c3ad604a6 Mon Sep 17 00:00:00 2001 From: ryan-crabbe-berri Date: Tue, 26 May 2026 15:17:44 -0700 Subject: [PATCH] refactor(ui): remove dead App Router scaffolding in (dashboard)/* (#28891) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deletes 39 files across 12 unused subdirs under src/app/(dashboard)/. None of these routes are reachable: LEGACY_REDIRECTS in src/app/page.tsx is empty, the live UI renders everything via the legacy ?page=X switch, and no other code statically imports from these dirs. Kept api-reference, models-and-endpoints, organizations, playground, virtual-keys because they ARE imported by the legacy switch in src/app/page.tsx — they will be migrated properly in the App Router migration. Kept shared infra: layout.tsx, hooks/, components/, networking.ts, README.md — these are imported by live code. Clean baseline before the App Router migration (LIT-3128). --- .../experimental/api-playground/page.tsx | 12 - .../(dashboard)/experimental/budgets/page.tsx | 12 - .../(dashboard)/experimental/caching/page.tsx | 20 - .../experimental/claude-code-plugins/page.tsx | 17 - .../experimental/old-usage/page.tsx | 23 - .../(dashboard)/experimental/prompts/page.tsx | 12 - .../experimental/tag-management/page.tsx | 12 - .../src/app/(dashboard)/guardrails/page.tsx | 12 - .../src/app/(dashboard)/logs/page.tsx | 20 - .../src/app/(dashboard)/model-hub/page.tsx | 12 - .../src/app/(dashboard)/policies/page.tsx | 17 - .../settings/admin-settings/page.tsx | 13 - .../settings/logging-and-alerts/page.tsx | 12 - .../settings/router-settings/page.tsx | 12 - .../(dashboard)/settings/ui-theme/page.tsx | 12 - .../src/app/(dashboard)/skills/page.tsx | 17 - .../src/app/(dashboard)/teams/TeamsView.tsx | 370 -------- .../teams/components/TeamsFilters.test.tsx | 151 ---- .../teams/components/TeamsFilters.tsx | 141 --- .../teams/components/TeamsHeaderTabs.test.tsx | 54 -- .../teams/components/TeamsHeaderTabs.tsx | 38 - .../components/TeamsTable/ModelsCell.test.tsx | 146 ---- .../components/TeamsTable/ModelsCell.tsx | 107 --- .../components/TeamsTable/TeamsTable.test.tsx | 129 --- .../components/TeamsTable/TeamsTable.tsx | 166 ---- .../YourRoleCell/TeamRoleBadge.test.tsx | 38 - .../TeamsTable/YourRoleCell/TeamRoleBadge.tsx | 47 - .../YourRoleCell/YourRoleCell.test.tsx | 43 - .../TeamsTable/YourRoleCell/YourRoleCell.tsx | 22 - .../components/modals/CreateTeamModal.tsx | 822 ------------------ .../modals/DeleteTeamModal.test.tsx | 171 ---- .../components/modals/DeleteTeamModal.tsx | 96 -- .../(dashboard)/teams/hooks/useFetchTeams.ts | 30 - .../src/app/(dashboard)/teams/page.tsx | 31 - .../src/app/(dashboard)/test-key/page.tsx | 45 - .../(dashboard)/tools/mcp-servers/page.tsx | 12 - .../(dashboard)/tools/vector-stores/page.tsx | 12 - .../src/app/(dashboard)/usage/page.tsx | 14 - .../src/app/(dashboard)/users/page.tsx | 53 -- 39 files changed, 2973 deletions(-) delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/api-playground/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/budgets/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/caching/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/claude-code-plugins/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/old-usage/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/prompts/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/experimental/tag-management/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/model-hub/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/settings/admin-settings/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/settings/logging-and-alerts/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/settings/router-settings/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/settings/ui-theme/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/TeamsView.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsHeaderTabs.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsHeaderTabs.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/ModelsCell.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/ModelsCell.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/TeamsTable.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/TeamsTable.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/YourRoleCell/TeamRoleBadge.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/YourRoleCell/TeamRoleBadge.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/YourRoleCell/YourRoleCell.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsTable/YourRoleCell/YourRoleCell.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/DeleteTeamModal.test.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/DeleteTeamModal.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/hooks/useFetchTeams.ts delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/teams/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/test-key/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/tools/mcp-servers/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/tools/vector-stores/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/usage/page.tsx delete mode 100644 ui/litellm-dashboard/src/app/(dashboard)/users/page.tsx diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/api-playground/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/api-playground/page.tsx deleted file mode 100644 index 0948b7626d..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/api-playground/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import TransformRequestPanel from "@/components/transform_request"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const APIPlaygroundPage = () => { - const { accessToken } = useAuthorized(); - - return ; -}; - -export default APIPlaygroundPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/budgets/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/budgets/page.tsx deleted file mode 100644 index e49bd342c0..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/budgets/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import BudgetPanel from "@/components/budgets/budget_panel"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const BudgetsPage = () => { - const { accessToken } = useAuthorized(); - - return ; -}; - -export default BudgetsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/caching/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/caching/page.tsx deleted file mode 100644 index 6dcbcdc697..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/caching/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -"use client"; - -import CacheDashboard from "@/components/cache_dashboard"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const CachingPage = () => { - const { token, accessToken, userRole, userId, premiumUser } = useAuthorized(); - - return ( - - ); -}; - -export default CachingPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/claude-code-plugins/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/claude-code-plugins/page.tsx deleted file mode 100644 index c92c39639c..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/claude-code-plugins/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import ClaudeCodePluginsPanel from "@/components/claude_code_plugins"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const ClaudeCodePluginsPage = () => { - const { accessToken, userRole } = useAuthorized(); - - return ( - - ); -}; - -export default ClaudeCodePluginsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/old-usage/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/old-usage/page.tsx deleted file mode 100644 index 9521f4f69f..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/old-usage/page.tsx +++ /dev/null @@ -1,23 +0,0 @@ -"use client"; - -import Usage from "@/components/usage"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import { useState } from "react"; - -const OldUsagePage = () => { - const { accessToken, token, userRole, userId, premiumUser } = useAuthorized(); - const [keys, setKeys] = useState([]); - - return ( - - ); -}; - -export default OldUsagePage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/prompts/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/prompts/page.tsx deleted file mode 100644 index 0836a03b7e..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/prompts/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import PromptsPanel from "@/components/prompts"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const PromptsPage = () => { - const { accessToken } = useAuthorized(); - - return ; -}; - -export default PromptsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/experimental/tag-management/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/experimental/tag-management/page.tsx deleted file mode 100644 index 0e686387b3..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/experimental/tag-management/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import TagManagement from "@/components/tag_management"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const TagManagementPage = () => { - const { accessToken, userId, userRole } = useAuthorized(); - - return ; -}; - -export default TagManagementPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx deleted file mode 100644 index 50cee215eb..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import GuardrailsPanel from "@/components/guardrails"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const GuardrailsPage = () => { - const { accessToken } = useAuthorized(); - - return ; -}; - -export default GuardrailsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx deleted file mode 100644 index 43ce427131..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/logs/page.tsx +++ /dev/null @@ -1,20 +0,0 @@ -"use client"; - -import SpendLogsTable from "@/components/view_logs"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const LogsPage = () => { - const { accessToken, token, userRole, userId, premiumUser } = useAuthorized(); - - return ( - - ); -}; - -export default LogsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/model-hub/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/model-hub/page.tsx deleted file mode 100644 index c37a935976..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/model-hub/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import ModelHubTable from "@/components/AIHub/ModelHubTable"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const ModelHubPage = () => { - const { accessToken, premiumUser, userRole } = useAuthorized(); - - return ; -}; - -export default ModelHubPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx deleted file mode 100644 index c1f6ec51d7..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/policies/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import PoliciesPanel from "@/components/policies"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const PoliciesPage = () => { - const { accessToken, userRole } = useAuthorized(); - - return ( - - ); -}; - -export default PoliciesPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/settings/admin-settings/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/settings/admin-settings/page.tsx deleted file mode 100644 index 8dae33afe7..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/settings/admin-settings/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -"use client"; - -import AdminPanel from "@/components/AdminPanel"; - -const AdminSettings = () => { - - return ( - - ); -}; - -export default AdminSettings; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/settings/logging-and-alerts/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/settings/logging-and-alerts/page.tsx deleted file mode 100644 index b13e3c42f9..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/settings/logging-and-alerts/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import Settings from "@/components/settings"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const LoggingAndAlertsPage = () => { - const { accessToken, userRole, userId, premiumUser } = useAuthorized(); - - return ; -}; - -export default LoggingAndAlertsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/settings/router-settings/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/settings/router-settings/page.tsx deleted file mode 100644 index 2b5463cd81..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/settings/router-settings/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import GeneralSettings from "@/components/general_settings"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const RouterSettingsPage = () => { - const { accessToken, userRole, userId } = useAuthorized(); - - return ; -}; - -export default RouterSettingsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/settings/ui-theme/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/settings/ui-theme/page.tsx deleted file mode 100644 index c6826cf11d..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/settings/ui-theme/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import UIThemeSettings from "@/components/ui_theme_settings"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const UIThemePage = () => { - const { userId, userRole, accessToken } = useAuthorized(); - - return ; -}; - -export default UIThemePage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx deleted file mode 100644 index 47d2331bed..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/skills/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -"use client"; - -import ClaudeCodePluginsPanel from "@/components/claude_code_plugins"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const SkillsPage = () => { - const { accessToken, userRole } = useAuthorized(); - - return ( - - ); -}; - -export default SkillsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/TeamsView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/TeamsView.tsx deleted file mode 100644 index 94a0e03304..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/TeamsView.tsx +++ /dev/null @@ -1,370 +0,0 @@ -import React, { useState, useEffect } from "react"; -import { useQueryClient } from "@tanstack/react-query"; -import { organizationKeys } from "@/app/(dashboard)/hooks/organizations/useOrganizations"; -import { teamDeleteCall, Organization } from "@/components/networking"; -import { fetchTeams } from "@/components/common_components/fetch_teams"; -import { Form } from "antd"; -import TeamInfoView from "@/components/team/TeamInfo"; -import TeamSSOSettings from "@/components/TeamSSOSettings"; -import { isAdminRole } from "@/utils/roles"; -import { Card, Button, Col, Text, Grid, TabPanel } from "@tremor/react"; -import AvailableTeamsPanel from "@/components/team/available_teams"; -import type { KeyResponse, Team } from "@/components/key_team_helpers/key_list"; - -import { Member, v2TeamListCall } from "@/components/networking"; -import { updateExistingKeys } from "@/utils/dataUtils"; -import TeamsHeaderTabs from "@/app/(dashboard)/teams/components/TeamsHeaderTabs"; -import TeamsFilters from "@/app/(dashboard)/teams/components/TeamsFilters"; -import useFetchTeams from "@/app/(dashboard)/teams/hooks/useFetchTeams"; -import TeamsTable from "@/app/(dashboard)/teams/components/TeamsTable/TeamsTable"; -import DeleteTeamModal from "@/app/(dashboard)/teams/components/modals/DeleteTeamModal"; -import CreateTeamModal from "@/app/(dashboard)/teams/components/modals/CreateTeamModal"; - -interface TeamProps { - teams: Team[] | null; - accessToken: string | null; - setTeams: React.Dispatch>; - userID: string | null; - userRole: string | null; - organizations: Organization[] | null; - premiumUser?: boolean; -} - -interface FilterState { - team_id: string; - team_alias: string; - organization_id: string; - sort_by: string; - sort_order: "asc" | "desc"; -} - -interface TeamInfo { - members_with_roles: Member[]; -} - -interface PerTeamInfo { - keys: KeyResponse[]; - team_info: TeamInfo; -} - -const TeamsView: React.FC = ({ - teams, - accessToken, - setTeams, - userID, - userRole, - organizations, - premiumUser = false, -}) => { - const queryClient = useQueryClient(); - const [currentOrg, setCurrentOrg] = useState(null); - const [showFilters, setShowFilters] = useState(false); - const [filters, setFilters] = useState({ - team_id: "", - team_alias: "", - organization_id: "", - sort_by: "created_at", - sort_order: "desc", - }); - - const [form] = Form.useForm(); - const [memberForm] = Form.useForm(); - - const [selectedTeamId, setSelectedTeamId] = useState(null); - const [editTeam, setEditTeam] = useState(false); - - const [isTeamModalVisible, setIsTeamModalVisible] = useState(false); - const [isAddMemberModalVisible, setIsAddMemberModalVisible] = useState(false); - const [isEditMemberModalVisible, setIsEditMemberModalVisible] = useState(false); - const [userModels, setUserModels] = useState([]); - const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); - const [teamToDelete, setTeamToDelete] = useState(null); - const [perTeamInfo, setPerTeamInfo] = useState>({}); - - const [loggingSettings, setLoggingSettings] = useState([]); - const [modelAliases, setModelAliases] = useState<{ [key: string]: string }>({}); - const { lastRefreshed, onRefreshClick: handleRefreshClick } = useFetchTeams({ currentOrg, setTeams }); - - useEffect(() => { - const fetchTeamInfo = () => { - if (!teams) return; - - const newPerTeamInfo = teams.reduce( - (acc, team) => { - acc[team.team_id] = { - keys: team.keys || [], - team_info: { - members_with_roles: team.members_with_roles || [], - }, - }; - return acc; - }, - {} as Record, - ); - - setPerTeamInfo(newPerTeamInfo); - }; - - fetchTeamInfo(); - }, [teams]); - - const handleOk = () => { - setIsTeamModalVisible(false); - form.resetFields(); - setLoggingSettings([]); - setModelAliases({}); - }; - - const handleMemberOk = () => { - setIsAddMemberModalVisible(false); - setIsEditMemberModalVisible(false); - memberForm.resetFields(); - }; - - const handleCancel = () => { - setIsTeamModalVisible(false); - form.resetFields(); - setLoggingSettings([]); - setModelAliases({}); - }; - - const handleDelete = async (team_id: string) => { - // Set the team to delete and open the confirmation modal - setTeamToDelete(team_id); - setIsDeleteModalOpen(true); - }; - - const confirmDelete = async () => { - if (teamToDelete == null || teams == null || accessToken == null) { - return; - } - - try { - await teamDeleteCall(accessToken, teamToDelete); - queryClient.invalidateQueries({ queryKey: organizationKeys.all }); - // Successfully completed the deletion. Update the state to trigger a rerender. - fetchTeams(accessToken, userID, userRole, currentOrg, setTeams); - } catch (error) { - console.error("Error deleting the team:", error); - // Handle any error situations, such as displaying an error message to the user. - } - - // Close the confirmation modal and reset the teamToDelete - setIsDeleteModalOpen(false); - setTeamToDelete(null); - }; - - const cancelDelete = () => { - // Close the confirmation modal and reset the teamToDelete - setIsDeleteModalOpen(false); - setTeamToDelete(null); - }; - - const is_team_admin = (team: any) => { - if (team == null || team.members_with_roles == null) { - return false; - } - for (let i = 0; i < team.members_with_roles.length; i++) { - let member = team.members_with_roles[i]; - if (member.user_id == userID && member.role == "admin") { - return true; - } - } - return false; - }; - - const handleFilterChange = (key: keyof FilterState, value: string) => { - const newFilters = { ...filters, [key]: value }; - setFilters(newFilters); - // Call teamListCall with the new filters - if (accessToken) { - v2TeamListCall( - accessToken, - newFilters.organization_id || null, - null, - newFilters.team_id || null, - newFilters.team_alias || null, - ) - .then((response) => { - if (response && response.teams) { - setTeams(response.teams); - } - }) - .catch((error) => { - console.error("Error fetching teams:", error); - }); - } - }; - - const handleSortChange = (sortBy: string, sortOrder: "asc" | "desc") => { - const newFilters = { - ...filters, - sort_by: sortBy, - sort_order: sortOrder, - }; - setFilters(newFilters); - // Call teamListCall with the new sort parameters - if (accessToken) { - v2TeamListCall( - accessToken, - filters.organization_id || null, - null, - filters.team_id || null, - filters.team_alias || null, - ) - .then((response) => { - if (response && response.teams) { - setTeams(response.teams); - } - }) - .catch((error) => { - console.error("Error fetching teams:", error); - }); - } - }; - - const handleFilterReset = () => { - setFilters({ - team_id: "", - team_alias: "", - organization_id: "", - sort_by: "created_at", - sort_order: "desc", - }); - // Reset teams list - if (accessToken) { - v2TeamListCall(accessToken, null, userID || null, null, null) - .then((response) => { - if (response && response.teams) { - setTeams(response.teams); - } - }) - .catch((error) => { - console.error("Error fetching teams:", error); - }); - } - }; - - return ( -
- - - {(userRole == "Admin" || userRole == "Org Admin") && ( - - )} - {selectedTeamId ? ( - { - setTeams((teams) => { - if (teams == null) { - return teams; - } - const updated = teams.map((team) => { - if (data.team_id === team.team_id) { - return updateExistingKeys(team, data); - } - return team; - }); - // Minimal fix: refresh the full team list after an update - if (accessToken) { - fetchTeams(accessToken, userID, userRole, currentOrg, setTeams); - } - return updated; - }); - }} - onClose={() => { - setSelectedTeamId(null); - setEditTeam(false); - }} - accessToken={accessToken} - is_team_admin={is_team_admin(teams?.find((team) => team.team_id === selectedTeamId))} - is_proxy_admin={userRole == "Admin"} - is_org_admin={(() => { - const team = teams?.find((t) => t.team_id === selectedTeamId); - if (!team?.organization_id || !organizations || !userID) return false; - const org = organizations.find((o) => o.organization_id === team.organization_id); - return org?.members?.some((m: any) => m.user_id === userID && m.user_role === "org_admin") ?? false; - })()} - userModels={userModels} - editTeam={editTeam} - premiumUser={premiumUser} - /> - ) : ( - - - - Click on “Team ID” to view team details and manage team members. - - - - -
-
- -
-
- - {isDeleteModalOpen && ( - - )} -
- -
-
- - - - {isAdminRole(userRole || "") && ( - - - - )} -
- )} - {(userRole == "Admin" || userRole == "Org Admin") && ( - - )} - -
-
- ); -}; - -export default TeamsView; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.test.tsx deleted file mode 100644 index 9a818c2762..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.test.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { render, screen, within } from "@testing-library/react"; -import userEvent from "@testing-library/user-event"; -import React from "react"; -import { describe, expect, it, vi } from "vitest"; -import { Organization } from "@/components/networking"; -import TeamsFilters from "./TeamsFilters"; - -type FilterState = { - team_id: string; - team_alias: string; - organization_id: string; - sort_by: string; - sort_order: "asc" | "desc"; -}; - -const emptyFilters: FilterState = { - team_alias: "", - team_id: "", - organization_id: "", - sort_by: "", - sort_order: "asc", -}; - -const mockOrganizations: Organization[] = [ - { organization_id: "org-1", organization_alias: "Acme Corp" } as Organization, - { organization_id: "org-2", organization_alias: "Globex" } as Organization, -]; - -const renderFilters = (overrides: Partial[0]> = {}) => { - const defaults = { - filters: emptyFilters, - organizations: mockOrganizations, - showFilters: false, - onToggleFilters: vi.fn(), - onChange: vi.fn(), - onReset: vi.fn(), - }; - return render(); -}; - -describe("TeamsFilters", () => { - it("should render the team name search input, Filters button, and Reset Filters button", () => { - renderFilters(); - - expect(screen.getByPlaceholderText("Search by Team Name...")).toBeInTheDocument(); - expect(screen.getByRole("button", { name: /^filters$/i })).toBeInTheDocument(); - expect(screen.getByRole("button", { name: /reset filters/i })).toBeInTheDocument(); - }); - - it("should reflect the current team_alias filter value in the search input", () => { - renderFilters({ filters: { ...emptyFilters, team_alias: "Platform" } }); - - expect(screen.getByPlaceholderText("Search by Team Name...")).toHaveValue("Platform"); - }); - - it("should call onChange with 'team_alias' key when the search input changes", async () => { - const user = userEvent.setup(); - const onChange = vi.fn(); - renderFilters({ onChange }); - - await user.type(screen.getByPlaceholderText("Search by Team Name..."), "Dev"); - - expect(onChange).toHaveBeenCalledWith("team_alias", expect.stringContaining("D")); - }); - - it("should call onToggleFilters with the inverted boolean when the Filters button is clicked", async () => { - const user = userEvent.setup(); - const onToggleFilters = vi.fn(); - renderFilters({ showFilters: false, onToggleFilters }); - - await user.click(screen.getByRole("button", { name: /^filters$/i })); - - expect(onToggleFilters).toHaveBeenCalledWith(true); - }); - - it("should call onToggleFilters(false) when filters are currently expanded", async () => { - const user = userEvent.setup(); - const onToggleFilters = vi.fn(); - renderFilters({ showFilters: true, onToggleFilters }); - - await user.click(screen.getByRole("button", { name: /^filters$/i })); - - expect(onToggleFilters).toHaveBeenCalledWith(false); - }); - - it("should call onReset when the Reset Filters button is clicked", async () => { - const user = userEvent.setup(); - const onReset = vi.fn(); - renderFilters({ onReset }); - - await user.click(screen.getByRole("button", { name: /reset filters/i })); - - expect(onReset).toHaveBeenCalledTimes(1); - }); - - it("should not show the Team ID input when showFilters is false", () => { - renderFilters({ showFilters: false }); - - expect(screen.queryByPlaceholderText("Enter Team ID")).not.toBeInTheDocument(); - }); - - it("should show the Team ID input when showFilters is true", () => { - renderFilters({ showFilters: true }); - - expect(screen.getByPlaceholderText("Enter Team ID")).toBeInTheDocument(); - }); - - it("should call onChange with 'team_id' key when the Team ID input changes", async () => { - const user = userEvent.setup(); - const onChange = vi.fn(); - renderFilters({ showFilters: true, onChange }); - - await user.type(screen.getByPlaceholderText("Enter Team ID"), "abc"); - - expect(onChange).toHaveBeenCalledWith("team_id", expect.stringContaining("a")); - }); - - it("should reflect the current team_id filter value in the Team ID input", () => { - renderFilters({ showFilters: true, filters: { ...emptyFilters, team_id: "team-xyz" } }); - - expect(screen.getByPlaceholderText("Enter Team ID")).toHaveValue("team-xyz"); - }); - - it("should show the active filter indicator on the Filters button when team_alias is set", () => { - renderFilters({ filters: { ...emptyFilters, team_alias: "Platform" } }); - - const filtersButton = screen.getByRole("button", { name: /^filters$/i }); - expect(within(filtersButton).getByTestId("active-filter-indicator")).toBeInTheDocument(); - }); - - it("should show the active filter indicator on the Filters button when team_id is set", () => { - renderFilters({ filters: { ...emptyFilters, team_id: "team-123" } }); - - const filtersButton = screen.getByRole("button", { name: /^filters$/i }); - expect(within(filtersButton).getByTestId("active-filter-indicator")).toBeInTheDocument(); - }); - - it("should show the active filter indicator on the Filters button when organization_id is set", () => { - renderFilters({ filters: { ...emptyFilters, organization_id: "org-1" } }); - - const filtersButton = screen.getByRole("button", { name: /^filters$/i }); - expect(within(filtersButton).getByTestId("active-filter-indicator")).toBeInTheDocument(); - }); - - it("should not show the active filter indicator when all filters are empty", () => { - renderFilters({ filters: emptyFilters }); - - const filtersButton = screen.getByRole("button", { name: /^filters$/i }); - expect(within(filtersButton).queryByTestId("active-filter-indicator")).not.toBeInTheDocument(); - }); -}); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.tsx deleted file mode 100644 index 04c65ffe26..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsFilters.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { Select, SelectItem } from "@tremor/react"; -import React from "react"; -import { Organization } from "@/components/networking"; - -interface TeamsFiltersProps { - filters: FilterState; - organizations: Organization[] | null; - showFilters: boolean; - onToggleFilters: (toggle: boolean) => void; - onChange: (key: K, value: FilterState[K]) => void; - onReset: () => void; -} - -type FilterState = { - team_id: string; - team_alias: string; - organization_id: string; - sort_by: string; - sort_order: "asc" | "desc"; -}; - -const TeamsFilters = ({ - filters, - organizations, - showFilters, - onToggleFilters, - onChange, - onReset, -}: TeamsFiltersProps) => { - return ( -
- {/* Search and Filter Controls */} -
- {/* Team Alias Search */} -
- onChange("team_alias", e.target.value)} - /> - - - -
- - {/* Filter Button */} - - - {/* Reset Filters Button */} - -
- - {/* Additional Filters */} - {showFilters && ( -
- {/* Team ID Search */} -
- onChange("team_id", e.target.value)} - /> - - - -
- - {/* Organization Dropdown */} -
- -
-
- )} -
- ); -}; - -export default TeamsFilters; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsHeaderTabs.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsHeaderTabs.test.tsx deleted file mode 100644 index 50a7f10f04..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/TeamsHeaderTabs.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { render, screen } from "@testing-library/react"; -import React from "react"; -import { describe, expect, it, vi } from "vitest"; -import TeamsHeaderTabs from "./TeamsHeaderTabs"; - -vi.mock("@tremor/react", () => ({ - TabGroup: ({ children, ...props }: any) =>
{children}
, - TabList: ({ children, ...props }: any) =>
{children}
, - Tab: ({ children, ...props }: any) => , - TabPanels: ({ children, ...props }: any) =>
{children}
, - Text: ({ children, ...props }: any) => {children}, - Icon: ({ onClick, ...props }: any) => - -
- {keyCount > 0 && ( -
-
- -
-
-

- Warning: This team has {keyCount} associated key{keyCount > 1 ? "s" : ""}. -

-

- Deleting the team will also delete all associated keys. This action is irreversible. -

-
-
- )} -

- Are you sure you want to force delete this team and all its keys? -

-
- - setDeleteConfirmInput(e.target.value)} - placeholder="Enter team name exactly" - className="w-full px-4 py-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-base" - autoFocus - /> -
-
- -
- - -
- - - ); -}; - -export default DeleteTeamModal; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/hooks/useFetchTeams.ts b/ui/litellm-dashboard/src/app/(dashboard)/teams/hooks/useFetchTeams.ts deleted file mode 100644 index c02787896f..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/hooks/useFetchTeams.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; -import { fetchTeams } from "@/components/common_components/fetch_teams"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import { Organization, Team } from "@/components/networking"; - -interface useFetchTeamsProps { - currentOrg: Organization | null; - setTeams: (teams: Team[] | null) => void; -} - -const useFetchTeams = ({ currentOrg, setTeams }: useFetchTeamsProps) => { - const [lastRefreshed, setLastRefreshed] = useState(""); - const { accessToken, userId, userRole } = useAuthorized(); - - const onRefreshClick = useCallback(() => { - const currentDate = new Date(); - setLastRefreshed(currentDate.toLocaleString()); - }, []); - - useEffect(() => { - if (accessToken) { - fetchTeams(accessToken, userId, userRole, currentOrg, setTeams).then(); - } - onRefreshClick(); - }, [accessToken, currentOrg, lastRefreshed, onRefreshClick, setTeams, userId, userRole]); - - return { lastRefreshed, setLastRefreshed, onRefreshClick }; -}; - -export default useFetchTeams; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/page.tsx deleted file mode 100644 index 041c50dd32..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/page.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import TeamsView from "@/app/(dashboard)/teams/TeamsView"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import useTeams from "@/app/(dashboard)/hooks/useTeams"; -import { useEffect, useState } from "react"; -import { Organization } from "@/components/networking"; -import { fetchOrganizations } from "@/components/organizations"; - -const TeamsPage = () => { - const { accessToken, userId, userRole } = useAuthorized(); - const { teams, setTeams } = useTeams(); - const [organizations, setOrganizations] = useState([]); - - useEffect(() => { - fetchOrganizations(accessToken, setOrganizations).then(() => {}); - }, [accessToken]); - - return ( - - ); -}; - -export default TeamsPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/test-key/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/test-key/page.tsx deleted file mode 100644 index 0f984686c4..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/test-key/page.tsx +++ /dev/null @@ -1,45 +0,0 @@ -"use client"; - -import ChatUI from "@/components/playground/chat_ui/ChatUI"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import { useState, useEffect } from "react"; -import { fetchProxySettings } from "@/utils/proxyUtils"; - -interface ProxySettings { - PROXY_BASE_URL?: string; - LITELLM_UI_API_DOC_BASE_URL?: string | null; -} - -const TestKeyPage = () => { - const { token, accessToken, userRole, userId, disabledPersonalKeyCreation } = useAuthorized(); - const [proxySettings, setProxySettings] = useState(undefined); - - useEffect(() => { - const initializeProxySettings = async () => { - if (accessToken) { - const settings = await fetchProxySettings(accessToken); - if (settings) { - setProxySettings({ - PROXY_BASE_URL: settings.PROXY_BASE_URL || undefined, - LITELLM_UI_API_DOC_BASE_URL: settings.LITELLM_UI_API_DOC_BASE_URL, - }); - } - } - }; - - initializeProxySettings(); - }, [accessToken]); - - return ( - - ); -}; - -export default TestKeyPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/tools/mcp-servers/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/tools/mcp-servers/page.tsx deleted file mode 100644 index 9b94de6c9f..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/tools/mcp-servers/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import { MCPServers } from "@/components/mcp_tools"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const MCPServersPage = () => { - const { accessToken, userRole, userId } = useAuthorized(); - - return ; -}; - -export default MCPServersPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/tools/vector-stores/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/tools/vector-stores/page.tsx deleted file mode 100644 index 8516a0faa1..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/tools/vector-stores/page.tsx +++ /dev/null @@ -1,12 +0,0 @@ -"use client"; - -import VectorStoreManagement from "@/components/vector_store_management"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; - -const VectorStoresPage = () => { - const { accessToken, userId, userRole } = useAuthorized(); - - return ; -}; - -export default VectorStoresPage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/usage/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/usage/page.tsx deleted file mode 100644 index 477c1163ce..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/usage/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -"use client"; - -import UsagePageView from "@/components/UsagePage/components/UsagePageView"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import useTeams from "@/app/(dashboard)/hooks/useTeams"; - -const UsagePage = () => { - const { accessToken, userRole, userId, premiumUser } = useAuthorized(); - const { teams } = useTeams(); - - return ; -}; - -export default UsagePage; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/users/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/users/page.tsx deleted file mode 100644 index 9874dd4886..0000000000 --- a/ui/litellm-dashboard/src/app/(dashboard)/users/page.tsx +++ /dev/null @@ -1,53 +0,0 @@ -"use client"; - -import ViewUserDashboard from "@/components/view_users"; -import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; -import useTeams from "@/app/(dashboard)/hooks/useTeams"; -import { useOrganizations } from "@/app/(dashboard)/hooks/organizations/useOrganizations"; -import { isProxyAdminRole } from "@/utils/roles"; -import { useState, useMemo } from "react"; -import { Organization } from "@/components/networking"; - -const UsersPage = () => { - const { accessToken, userRole, userId, token } = useAuthorized(); - const [keys, setKeys] = useState([]); - - const { teams } = useTeams(); - const { data: organizations, isLoading: isOrgsLoading } = useOrganizations(); - - // Three states: - // - undefined: org data still loading (non-proxy-admin) — query should wait - // - null: proxy admin or no org filtering needed — query runs unfiltered - // - Array<{organization_id, organization_alias}>: org admin orgs — query runs filtered - const orgAdminOrgIds = useMemo((): Array<{organization_id: string, organization_alias: string}> | null | undefined => { - if (!userId || !userRole) return null; - // Proxy admins see all users — no org filtering - if (isProxyAdminRole(userRole)) return null; - - // Still loading org data — signal "not ready yet" - if (isOrgsLoading || !organizations) return undefined; - - const adminOrgs = organizations - .filter((org: Organization) => - org.members?.some((member) => member.user_id === userId && member.user_role === "org_admin") - ) - .map((org: Organization) => ({ organization_id: org.organization_id, organization_alias: org.organization_alias })); - - return adminOrgs.length > 0 ? adminOrgs : null; - }, [userId, organizations, userRole, isOrgsLoading]); - - return ( - - ); -}; - -export default UsersPage;