Add search to key edit team dropdown

This commit is contained in:
yuneng-jiang 2026-01-14 15:47:50 -08:00
parent dcac090de0
commit a4fecc74fb
2 changed files with 40 additions and 22 deletions

View file

@ -1,8 +1,8 @@
import { waitFor } from "@testing-library/react";
import { renderWithProviders } from "../../../tests/test-utils";
import { fireEvent, waitFor } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { KeyEditView } from "./key_edit_view";
import { renderWithProviders } from "../../../tests/test-utils";
import { KeyResponse } from "../key_team_helpers/key_list";
import { KeyEditView } from "./key_edit_view";
// Mock window.matchMedia
Object.defineProperty(window, "matchMedia", {
@ -143,4 +143,28 @@ describe("KeyEditView", () => {
expect(metadataTextarea).toHaveValue("{}");
});
});
it("should call onCancel when cancel button is clicked", async () => {
const onCancelMock = vi.fn();
const { getByText } = renderWithProviders(
<KeyEditView
keyData={MOCK_KEY_DATA}
onCancel={onCancelMock}
onSubmit={async () => {}}
accessToken={""}
userID={""}
userRole={""}
premiumUser={false}
/>,
);
await waitFor(() => {
expect(getByText("Cancel")).toBeInTheDocument();
});
const cancelButton = getByText("Cancel");
fireEvent.click(cancelButton);
expect(onCancelMock).toHaveBeenCalledTimes(1);
});
});

View file

@ -1,7 +1,9 @@
import GuardrailSelector from "@/components/guardrails/GuardrailSelector";
import { InfoCircleOutlined } from "@ant-design/icons";
import { TextInput, Button as TremorButton } from "@tremor/react";
import { Form, Input, Select, Switch, Tooltip } from "antd";
import { useEffect, useState } from "react";
import AgentSelector from "../agent_management/AgentSelector";
import { mapInternalToDisplayNames } from "../callback_info_helpers";
import KeyLifecycleSettings from "../common_components/KeyLifecycleSettings";
import PassThroughRoutesSelector from "../common_components/PassThroughRoutesSelector";
@ -10,15 +12,13 @@ import { extractLoggingSettings, formatMetadataForDisplay, stripTagsFromMetadata
import { KeyResponse } from "../key_team_helpers/key_list";
import MCPServerSelector from "../mcp_server_management/MCPServerSelector";
import MCPToolPermissions from "../mcp_server_management/MCPToolPermissions";
import AgentSelector from "../agent_management/AgentSelector";
import NotificationsManager from "../molecules/notifications_manager";
import { fetchMCPAccessGroups, getPromptsList, modelAvailableCall, tagListCall } from "../networking";
import { getPromptsList, modelAvailableCall, tagListCall } from "../networking";
import { fetchTeamModels } from "../organisms/create_key_button";
import NumericalInput from "../shared/numerical_input";
import { Tag } from "../tag_management/types";
import EditLoggingSettings from "../team/EditLoggingSettings";
import VectorStoreSelector from "../vector_store_management/VectorStoreSelector";
import { InfoCircleOutlined } from "@ant-design/icons";
interface KeyEditViewProps {
keyData: KeyResponse;
@ -82,13 +82,10 @@ export function KeyEditView({
premiumUser = false,
}: KeyEditViewProps) {
const [form] = Form.useForm();
const [userModels, setUserModels] = useState<string[]>([]);
const [promptsList, setPromptsList] = useState<string[]>([]);
const [tagsList, setTagsList] = useState<Record<string, Tag>>({});
const team = teams?.find((team) => team.team_id === keyData.team_id);
const [availableModels, setAvailableModels] = useState<string[]>([]);
const [mcpAccessGroups, setMcpAccessGroups] = useState<string[]>([]);
const [mcpAccessGroupsLoaded, setMcpAccessGroupsLoaded] = useState(false);
const [disabledCallbacks, setDisabledCallbacks] = useState<string[]>(
Array.isArray(keyData.metadata?.litellm_disabled_callbacks)
? mapInternalToDisplayNames(keyData.metadata.litellm_disabled_callbacks)
@ -98,18 +95,6 @@ export function KeyEditView({
const [rotationInterval, setRotationInterval] = useState<string>(keyData.rotation_interval || "");
const [isKeySaving, setIsKeySaving] = useState(false);
const fetchMcpAccessGroups = async () => {
if (!accessToken) return;
if (mcpAccessGroupsLoaded) return;
try {
const groups = await fetchMCPAccessGroups(accessToken);
setMcpAccessGroups(groups);
setMcpAccessGroupsLoaded(true);
} catch (error) {
console.error("Failed to fetch MCP access groups:", error);
}
};
useEffect(() => {
const fetchModels = async () => {
if (!userID || !userRole || !accessToken) return;
@ -526,7 +511,16 @@ export function KeyEditView({
</Form.Item>
<Form.Item label="Team ID" name="team_id">
<Select placeholder="Select team" style={{ width: "100%" }}>
<Select
placeholder="Select team"
showSearch
style={{ width: "100%" }}
filterOption={(input, option) => {
const team = teams?.find((t) => t.team_id === option?.value);
if (!team) return false;
return team.team_alias?.toLowerCase().includes(input.toLowerCase()) ?? false;
}}
>
{/* Only show All Team Models if team has models */}
{teams?.map((team) => (
<Select.Option key={team.team_id} value={team.team_id}>