mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
fix(ui): prepopulate team ID during team creation
This commit is contained in:
parent
11a02b9581
commit
c12bdfa81d
2 changed files with 25 additions and 4 deletions
|
|
@ -18,6 +18,7 @@ import Teams from "./Teams";
|
|||
import { chooseSelectOption } from "../../tests/test-utils";
|
||||
|
||||
const can = vi.fn();
|
||||
const UUID_V4_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
||||
vi.mock("@/app/(dashboard)/hooks/useCan", () => ({
|
||||
default: (...args: unknown[]) => can(...args),
|
||||
}));
|
||||
|
|
@ -1188,6 +1189,20 @@ describe("Teams - which fields reach the create payload depends on the open sect
|
|||
);
|
||||
});
|
||||
|
||||
it("prepopulates an editable UUID when the create form opens", async () => {
|
||||
await openCreateModal();
|
||||
fireEvent.change(screen.getByLabelText(/team name/i), { target: { value: "Generated ID Team" } });
|
||||
toggleAdditionalSettings();
|
||||
const teamIdInput = await screen.findByLabelText("Team ID");
|
||||
|
||||
const generatedTeamId = (teamIdInput as HTMLInputElement).value;
|
||||
expect(generatedTeamId).toMatch(UUID_V4_PATTERN);
|
||||
|
||||
const payload = await submit();
|
||||
|
||||
expect(payload.team_id).toBe(generatedTeamId);
|
||||
});
|
||||
|
||||
it("drops a value typed in Additional Settings when that section is closed again before saving", async () => {
|
||||
await openCreateModal();
|
||||
fireEvent.change(screen.getByLabelText(/team name/i), { target: { value: "Reclosed Team" } });
|
||||
|
|
@ -1318,7 +1333,7 @@ describe("Teams - the exact bytes the create call sends", () => {
|
|||
tpm_limit: undefined,
|
||||
rpm_limit: undefined,
|
||||
metadata: undefined,
|
||||
team_id: undefined,
|
||||
team_id: expect.stringMatching(UUID_V4_PATTERN),
|
||||
team_member_budget: undefined,
|
||||
team_member_key_duration: undefined,
|
||||
team_member_rpm_limit: undefined,
|
||||
|
|
@ -1339,6 +1354,7 @@ describe("Teams - the exact bytes the create call sends", () => {
|
|||
team_alias: "Byte Contract Team",
|
||||
organization_id: null,
|
||||
models: ["no-default-models"],
|
||||
team_id: expect.stringMatching(UUID_V4_PATTERN),
|
||||
mcp_tool_permissions: {},
|
||||
});
|
||||
});
|
||||
|
|
@ -1459,7 +1475,7 @@ describe("Teams - the exact bytes the create call sends", () => {
|
|||
tpm_limit: undefined,
|
||||
rpm_limit: undefined,
|
||||
metadata: undefined,
|
||||
team_id: undefined,
|
||||
team_id: expect.stringMatching(UUID_V4_PATTERN),
|
||||
team_member_budget: undefined,
|
||||
team_member_key_duration: undefined,
|
||||
team_member_rpm_limit: undefined,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|||
import { ChevronDown, Plus, Users } from "lucide-react";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { z } from "zod/v4";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { PageHeader } from "@/components/shared/PageHeader";
|
||||
import { Button as UIButton } from "@/components/ui/button";
|
||||
|
|
@ -77,7 +78,10 @@ const teamCreateFieldsSchema = z.object({
|
|||
tpm_limit: numericInputSchema,
|
||||
rpm_limit: numericInputSchema,
|
||||
metadata: metadataPairsSchema.optional(),
|
||||
team_id: z.string().optional(),
|
||||
team_id: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => (value?.trim() ? value : undefined)),
|
||||
team_member_budget: z.number().optional(),
|
||||
team_member_key_duration: z.string().optional(),
|
||||
team_member_rpm_limit: numericInputSchema,
|
||||
|
|
@ -314,6 +318,7 @@ const Teams: React.FC<TeamProps> = ({ accessToken, userID, userRole, premiumUser
|
|||
}, [accessToken, canViewPolicies]);
|
||||
|
||||
const openCreateTeamModal = () => {
|
||||
form.setValue("team_id", uuidv4());
|
||||
// Org admins must scope a team to an org, so with exactly one we preselect it.
|
||||
// Proxy admins can create org-less teams, so the field stays optional regardless of org count.
|
||||
if (isOrgAdmin && adminOrgs.length === 1) {
|
||||
|
|
@ -829,7 +834,7 @@ const Teams: React.FC<TeamProps> = ({ accessToken, userID, userRole, premiumUser
|
|||
control={form.control}
|
||||
name="team_id"
|
||||
label="Team ID"
|
||||
description="ID of the team you want to create. If not provided, it will be generated automatically."
|
||||
description="Leave blank to generate an ID when the team is created, or enter a custom ID."
|
||||
>
|
||||
{({ ref, value, ...field }) => <UIInput {...field} ref={ref} value={value ?? ""} />}
|
||||
</FormField>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue