mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-12 23:01:41 +00:00
Reusable Duration Select and update team member budget UI
This commit is contained in:
parent
6078f4687e
commit
8b3782b06a
3 changed files with 78 additions and 0 deletions
|
|
@ -0,0 +1,49 @@
|
|||
import { render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import DurationSelect from "./DurationSelect";
|
||||
|
||||
describe("DurationSelect", () => {
|
||||
it("should render", () => {
|
||||
render(<DurationSelect />);
|
||||
expect(screen.getByRole("combobox")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should render all three duration options", async () => {
|
||||
const user = userEvent.setup();
|
||||
render(<DurationSelect />);
|
||||
|
||||
const select = screen.getByRole("combobox");
|
||||
await user.click(select);
|
||||
|
||||
expect(screen.getByText("Daily")).toBeInTheDocument();
|
||||
expect(screen.getByText("Weekly")).toBeInTheDocument();
|
||||
expect(screen.getByText("Monthly")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should apply className prop", () => {
|
||||
render(<DurationSelect className="test-class" />);
|
||||
const select = screen.getByRole("combobox");
|
||||
expect(select.closest(".test-class")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should call onChange when an option is selected", async () => {
|
||||
const user = userEvent.setup();
|
||||
const onChange = vi.fn();
|
||||
render(<DurationSelect onChange={onChange} />);
|
||||
|
||||
const select = screen.getByRole("combobox");
|
||||
await user.click(select);
|
||||
|
||||
const dailyOption = screen.getByText("Daily");
|
||||
await user.click(dailyOption);
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith("24h", expect.any(Object));
|
||||
});
|
||||
|
||||
it("should accept and pass value prop to Select", () => {
|
||||
render(<DurationSelect value="7d" />);
|
||||
const select = screen.getByRole("combobox");
|
||||
expect(select).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { Select } from "antd";
|
||||
|
||||
interface DurationSelectProps {
|
||||
className?: string;
|
||||
value?: string;
|
||||
onChange?: (value: string) => void;
|
||||
}
|
||||
|
||||
export default function DurationSelect({ className, value, onChange }: DurationSelectProps) {
|
||||
return (
|
||||
<Select className={className} value={value} onChange={onChange}>
|
||||
<Select.Option value="24h">Daily</Select.Option>
|
||||
<Select.Option value="7d">Weekly</Select.Option>
|
||||
<Select.Option value="30d">Monthly</Select.Option>
|
||||
</Select>
|
||||
);
|
||||
}
|
||||
|
|
@ -48,6 +48,7 @@ import EditLoggingSettings from "./EditLoggingSettings";
|
|||
import MemberModal from "./EditMembership";
|
||||
import MemberPermissions from "./member_permissions";
|
||||
import TeamMembersComponent from "./team_member_view";
|
||||
import DurationSelect from "../common_components/DurationSelect";
|
||||
|
||||
export interface TeamMembership {
|
||||
user_id: string;
|
||||
|
|
@ -413,6 +414,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
};
|
||||
|
||||
updateData.max_budget = mapEmptyStringToNull(updateData.max_budget);
|
||||
updateData.team_member_budget_duration = values.team_member_budget_duration;
|
||||
|
||||
if (values.team_member_budget !== undefined) {
|
||||
updateData.team_member_budget = Number(values.team_member_budget);
|
||||
|
|
@ -650,6 +652,8 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
budget_duration: info.budget_duration,
|
||||
team_member_tpm_limit: info.team_member_budget_table?.tpm_limit,
|
||||
team_member_rpm_limit: info.team_member_budget_table?.rpm_limit,
|
||||
team_member_budget: info.team_member_budget_table?.max_budget,
|
||||
team_member_budget_duration: info.team_member_budget_table?.budget_duration,
|
||||
guardrails: info.metadata?.guardrails || [],
|
||||
disable_global_guardrails: info.metadata?.disable_global_guardrails || false,
|
||||
metadata: info.metadata
|
||||
|
|
@ -747,6 +751,13 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<NumericalInput step={0.01} precision={2} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Team Member Budget Duration" name="team_member_budget_duration">
|
||||
<DurationSelect
|
||||
onChange={(value) => form.setFieldValue("team_member_budget_duration", value)}
|
||||
value={form.getFieldValue("team_member_budget_duration")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Team Member Key Duration (eg: 1d, 1mo)"
|
||||
name="team_member_key_duration"
|
||||
|
|
@ -991,6 +1002,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
</Tooltip>
|
||||
</Text>
|
||||
<div>Max Budget: {info.team_member_budget_table?.max_budget || "No Limit"}</div>
|
||||
<div>Budget Duration: {info.team_member_budget_table?.budget_duration || "No Limit"}</div>
|
||||
<div>Key Duration: {info.metadata?.team_member_key_duration || "No Limit"}</div>
|
||||
<div>TPM Limit: {info.team_member_budget_table?.tpm_limit || "No Limit"}</div>
|
||||
<div>RPM Limit: {info.team_member_budget_table?.rpm_limit || "No Limit"}</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue