From ca22e08eae3d862d52f4a9dbde409861c70832cd Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Thu, 22 Jan 2026 14:53:13 -0800 Subject: [PATCH 1/2] Add reusable model select to update organization page --- .../components/ModelSelect/ModelSelect.tsx | 12 ++----- .../organization/organization_view.tsx | 36 +++++++++---------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx index b3881350448..78ccdddd81b 100644 --- a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx +++ b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx @@ -62,14 +62,8 @@ const contextFilters: Record { - if (!selectedOrganization) return []; - - if (selectedOrganization.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value)) { - return allProxyModels; - } - - return allProxyModels.filter((model) => selectedOrganization.models.includes(model)); + organization: ({ allProxyModels }) => { + return allProxyModels; }, }; @@ -102,8 +96,6 @@ export const ModelSelect = (props: ModelSelectProps) => { const hasSpecialOptionSelected = value.some(isSpecialOption); const isLoading = isLoadingAllProxyModels || isLoadingTeam || isLoadingOrganization || isCurrentUserLoading; const organizationHasAllProxyModels = organization?.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value) || organization?.models.length === 0; - console.log("organization:", organization); - console.log("organizationHasAllProxyModels:", organizationHasAllProxyModels); const shouldShowAllProxyModels = showAllProxyModelsOverride || (organizationHasAllProxyModels && includeSpecialOptions); diff --git a/ui/litellm-dashboard/src/components/organization/organization_view.tsx b/ui/litellm-dashboard/src/components/organization/organization_view.tsx index 91b2b4ce59b..9b4e9080f2f 100644 --- a/ui/litellm-dashboard/src/components/organization/organization_view.tsx +++ b/ui/litellm-dashboard/src/components/organization/organization_view.tsx @@ -1,4 +1,6 @@ +import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; import { formatNumberWithCommas, copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils"; +import { createTeamAliasMap } from "@/utils/teamUtils"; import { ArrowLeftIcon, PencilAltIcon, TrashIcon } from "@heroicons/react/outline"; import { Badge, @@ -23,10 +25,10 @@ import { } from "@tremor/react"; import { Button, Form, Input, Select } from "antd"; import { CheckIcon, CopyIcon } from "lucide-react"; -import React, { useEffect, useState, useMemo } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import UserSearchModal from "../common_components/user_search_modal"; -import { getModelDisplayName } from "../key_team_helpers/fetch_available_models_team_key"; import MCPServerSelector from "../mcp_server_management/MCPServerSelector"; +import { ModelSelect } from "../ModelSelect/ModelSelect"; import NotificationsManager from "../molecules/notifications_manager"; import { Member, @@ -41,8 +43,6 @@ import ObjectPermissionsView from "../object_permissions_view"; import NumericalInput from "../shared/numerical_input"; import MemberModal from "../team/EditMembership"; import VectorStoreSelector from "../vector_store_management/VectorStoreSelector"; -import { useTeams } from "@/app/(dashboard)/hooks/teams/useTeams"; -import { createTeamAliasMap } from "@/utils/teamUtils"; interface OrganizationInfoProps { organizationId: string; @@ -239,11 +239,10 @@ const OrganizationInfoView: React.FC = ({ size="small" icon={copiedStates["org-id"] ? : } onClick={() => copyToClipboard(orgData.organization_id, "org-id")} - className={`left-2 z-10 transition-all duration-200 ${ - copiedStates["org-id"] - ? "text-green-600 bg-green-50 border-green-200" - : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" - }`} + className={`left-2 z-10 transition-all duration-200 ${copiedStates["org-id"] + ? "text-green-600 bg-green-50 border-green-200" + : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" + }`} /> @@ -452,16 +451,15 @@ const OrganizationInfoView: React.FC = ({ - + form.setFieldValue("models", values)} + context="organization" + options={{ + includeSpecialOptions: true, + showAllProxyModelsOverride: true, + }} + /> From 9fe3e420e934ad2f614a82454d0f18049b88deba Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Thu, 22 Jan 2026 15:01:06 -0800 Subject: [PATCH 2/2] Fixing tests --- .../src/components/ModelSelect/ModelSelect.test.tsx | 4 ++-- ui/litellm-dashboard/vitest.config.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.test.tsx b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.test.tsx index 80acf5d75ff..3052f790098 100644 --- a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.test.tsx +++ b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.test.tsx @@ -405,7 +405,7 @@ describe("ModelSelect", () => { }); }); - it("should filter models when organization has specific models", async () => { + it("should show all models when organization context is used", async () => { const mockOrganization: Organization = { organization_id: "org-1", organization_alias: "Test Org", @@ -433,7 +433,7 @@ describe("ModelSelect", () => { await waitFor(() => { expect(screen.getByText("gpt-4")).toBeInTheDocument(); - expect(screen.queryByText("claude-3")).not.toBeInTheDocument(); + expect(screen.getByText("claude-3")).toBeInTheDocument(); }); }); diff --git a/ui/litellm-dashboard/vitest.config.ts b/ui/litellm-dashboard/vitest.config.ts index 108f0715704..7c52b88d3b6 100644 --- a/ui/litellm-dashboard/vitest.config.ts +++ b/ui/litellm-dashboard/vitest.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ setupFiles: ["tests/setupTests.ts"], globals: true, css: true, // lets you import CSS/modules without extra mocks + testTimeout: 10000, coverage: { provider: "v8", reporter: ["text", "lcov"],