diff --git a/ui/litellm-dashboard/src/components/team/EditMembership.tsx b/ui/litellm-dashboard/src/components/team/EditMembership.tsx index e201075cf41..e6d9ccad60b 100644 --- a/ui/litellm-dashboard/src/components/team/EditMembership.tsx +++ b/ui/litellm-dashboard/src/components/team/EditMembership.tsx @@ -1,6 +1,6 @@ import { Text, TextInput } from "@tremor/react"; import { Button as AntButton, Form, Modal, Select } from "antd"; -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import NumericalInput from "../shared/numerical_input"; interface BaseMember { @@ -48,6 +48,7 @@ const MemberModal = ({ config, }: MemberModalProps) => { const [form] = Form.useForm(); + const [isSubmitting, setIsSubmitting] = useState(false); console.log("Initial Data:", initialData); @@ -79,6 +80,7 @@ const MemberModal = ({ const handleSubmit = async (values: any) => { try { + setIsSubmitting(true); // Trim string values and clean up form data const formData = Object.entries(values).reduce((acc, [key, value]) => { if (typeof value === "string") { @@ -94,12 +96,14 @@ const MemberModal = ({ }, {}) as T; console.log("Submitting form data:", formData); - onSubmit(formData); + await Promise.resolve(onSubmit(formData)); form.resetFields(); // NotificationsManager.success(`Successfully ${mode === 'add' ? 'added' : 'updated'} member`); } catch (error) { // NotificationManager.fromBackend('Failed to submit form'); console.error("Form submission error:", error); + } finally { + setIsSubmitting(false); } }; @@ -217,11 +221,17 @@ const MemberModal = ({ ))}
- + Cancel - - {mode === "add" ? "Add Member" : "Save Changes"} + + {mode === "add" + ? isSubmitting + ? "Adding..." + : "Add Member" + : isSubmitting + ? "Saving..." + : "Save Changes"}
diff --git a/ui/litellm-dashboard/tests/setupTests.ts b/ui/litellm-dashboard/tests/setupTests.ts index 0a21f9dd4d5..cce37d79057 100644 --- a/ui/litellm-dashboard/tests/setupTests.ts +++ b/ui/litellm-dashboard/tests/setupTests.ts @@ -21,6 +21,10 @@ vi.mock("@tremor/react", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, + Button: React.forwardRef(({ children, ...props }, ref) => + // Render as a native button to avoid Tremor-specific behaviors in tests + React.createElement("button", { ...props, ref }, children), + ), Tooltip: ({ children, ..._props }: { children?: React.ReactNode; [key: string]: unknown }) => { // Return children directly without tooltip functionality to prevent flaky tests // This avoids issues with hover states, positioning, and DOM queries in tests