team settings soft budget and alerting emails
This commit is contained in:
parent
51af66fdb2
commit
e968e3798c
@ -3,7 +3,7 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbo",
|
||||
"dev": "next dev --webpack",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
|
||||
@ -573,4 +573,63 @@ describe("TeamInfoView", () => {
|
||||
expect(teamNameElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it("should display soft budget in settings view when present", async () => {
|
||||
const user = userEvent.setup();
|
||||
vi.mocked(networking.teamInfoCall).mockResolvedValue(
|
||||
createMockTeamData({
|
||||
soft_budget: 500.75,
|
||||
max_budget: 1000,
|
||||
})
|
||||
);
|
||||
|
||||
renderWithProviders(<TeamInfoView {...defaultProps} />);
|
||||
|
||||
await waitFor(() => {
|
||||
const teamNameElements = screen.queryAllByText("Test Team");
|
||||
expect(teamNameElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
const settingsTab = screen.getByRole("tab", { name: "Settings" });
|
||||
await user.click(settingsTab);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Team Settings")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Soft Budget:/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/\$500\.75/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("should display soft budget alerting emails in settings view when present", async () => {
|
||||
const user = userEvent.setup();
|
||||
vi.mocked(networking.teamInfoCall).mockResolvedValue(
|
||||
createMockTeamData({
|
||||
metadata: {
|
||||
soft_budget_alerting_emails: ["alert1@test.com", "alert2@test.com"],
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
renderWithProviders(<TeamInfoView {...defaultProps} />);
|
||||
|
||||
await waitFor(() => {
|
||||
const teamNameElements = screen.queryAllByText("Test Team");
|
||||
expect(teamNameElements.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
const settingsTab = screen.getByRole("tab", { name: "Settings" });
|
||||
await user.click(settingsTab);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Team Settings")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText(/Soft Budget Alerting Emails:/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/alert1@test\.com, alert2@test\.com/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -85,6 +85,7 @@ export interface TeamData {
|
||||
tpm_limit: number | null;
|
||||
rpm_limit: number | null;
|
||||
max_budget: number | null;
|
||||
soft_budget?: number | null;
|
||||
budget_duration: string | null;
|
||||
models: string[];
|
||||
blocked: boolean;
|
||||
@ -424,7 +425,10 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
|
||||
let parsedMetadata = {};
|
||||
try {
|
||||
parsedMetadata = values.metadata ? JSON.parse(values.metadata) : {};
|
||||
const rawMetadata = values.metadata ? JSON.parse(values.metadata) : {};
|
||||
// Exclude soft_budget_alerting_emails from parsed metadata since it's handled separately
|
||||
const { soft_budget_alerting_emails, ...rest } = rawMetadata;
|
||||
parsedMetadata = rest;
|
||||
} catch (e) {
|
||||
NotificationsManager.fromBackend("Invalid JSON in metadata field");
|
||||
return;
|
||||
@ -457,12 +461,20 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
tpm_limit: sanitizeNumeric(values.tpm_limit),
|
||||
rpm_limit: sanitizeNumeric(values.rpm_limit),
|
||||
max_budget: values.max_budget,
|
||||
soft_budget: sanitizeNumeric(values.soft_budget),
|
||||
budget_duration: values.budget_duration,
|
||||
metadata: {
|
||||
...parsedMetadata,
|
||||
guardrails: values.guardrails || [],
|
||||
logging: values.logging_settings || [],
|
||||
disable_global_guardrails: values.disable_global_guardrails || false,
|
||||
soft_budget_alerting_emails:
|
||||
typeof values.soft_budget_alerting_emails === "string"
|
||||
? values.soft_budget_alerting_emails
|
||||
.split(",")
|
||||
.map((email: string) => email.trim())
|
||||
.filter((email: string) => email.length > 0)
|
||||
: values.soft_budget_alerting_emails || [],
|
||||
...(secretManagerSettings !== undefined ? { secret_manager_settings: secretManagerSettings } : {}),
|
||||
},
|
||||
policies: values.policies || [],
|
||||
@ -754,6 +766,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
tpm_limit: info.tpm_limit,
|
||||
rpm_limit: info.rpm_limit,
|
||||
max_budget: info.max_budget,
|
||||
soft_budget: info.soft_budget,
|
||||
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,
|
||||
@ -762,9 +775,13 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
guardrails: info.metadata?.guardrails || [],
|
||||
policies: info.policies || [],
|
||||
disable_global_guardrails: info.metadata?.disable_global_guardrails || false,
|
||||
soft_budget_alerting_emails:
|
||||
Array.isArray(info.metadata?.soft_budget_alerting_emails)
|
||||
? info.metadata.soft_budget_alerting_emails.join(", ")
|
||||
: "",
|
||||
metadata: info.metadata
|
||||
? JSON.stringify(
|
||||
(({ logging, secret_manager_settings, ...rest }) => rest)(info.metadata),
|
||||
(({ logging, secret_manager_settings, soft_budget_alerting_emails, ...rest }) => rest)(info.metadata),
|
||||
null,
|
||||
2,
|
||||
)
|
||||
@ -821,6 +838,18 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
<NumericalInput step={0.01} precision={2} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Soft Budget (USD)" name="soft_budget">
|
||||
<NumericalInput step={0.01} precision={2} style={{ width: "100%" }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Soft Budget Alerting Emails"
|
||||
name="soft_budget_alerting_emails"
|
||||
tooltip="Comma-separated email addresses to receive alerts when the soft budget is reached"
|
||||
>
|
||||
<Input placeholder="example1@test.com, example2@test.com" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Team Member Budget (USD)"
|
||||
name="team_member_budget"
|
||||
@ -1096,7 +1125,20 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
||||
Max Budget:{" "}
|
||||
{info.max_budget !== null ? `$${formatNumberWithCommas(info.max_budget, 4)}` : "No Limit"}
|
||||
</div>
|
||||
<div>
|
||||
Soft Budget:{" "}
|
||||
{info.soft_budget !== null && info.soft_budget !== undefined
|
||||
? `$${formatNumberWithCommas(info.soft_budget, 4)}`
|
||||
: "No Limit"}
|
||||
</div>
|
||||
<div>Budget Reset: {info.budget_duration || "Never"}</div>
|
||||
{info.metadata?.soft_budget_alerting_emails &&
|
||||
Array.isArray(info.metadata.soft_budget_alerting_emails) &&
|
||||
info.metadata.soft_budget_alerting_emails.length > 0 && (
|
||||
<div>
|
||||
Soft Budget Alerting Emails: {info.metadata.soft_budget_alerting_emails.join(", ")}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Text className="font-medium">
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"jsx": "react-jsx",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user