diff --git a/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx b/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx index 97a9272f1e..7e9901d8bd 100644 --- a/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/RequestResponsePanel.tsx @@ -96,7 +96,9 @@ export function RequestResponsePanel({
- +
+ +
@@ -131,7 +133,9 @@ export function RequestResponsePanel({
{hasResponse ? ( - +
+ +
) : (
Response data not available
)} diff --git a/ui/litellm-dashboard/src/components/view_users/user_info_view.test.tsx b/ui/litellm-dashboard/src/components/view_users/user_info_view.test.tsx index 8d5927124a..3dd814143e 100644 --- a/ui/litellm-dashboard/src/components/view_users/user_info_view.test.tsx +++ b/ui/litellm-dashboard/src/components/view_users/user_info_view.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import UserInfoView from "./user_info_view"; @@ -41,19 +41,24 @@ describe("UserInfoView", () => { possibleUIRoles: null, }; - it("should render the loading state and then the user email", async () => { - const { getByText, findAllByText } = render(); + it("should render the loading state", () => { + render(); - expect(getByText("Loading user data...")).toBeInTheDocument(); - - const emails = await findAllByText("test@example.com"); - expect(emails.length).toBeGreaterThan(0); + expect(screen.getByText("Loading user data...")).toBeInTheDocument(); }); - it("should render the user alias", async () => { - const { findAllByText } = render(); + it("should render the user email after loading", async () => { + render(); - const aliases = await findAllByText("Test Alias"); + const emails = await screen.findAllByText("test@example.com"); + expect(emails.length).toBeGreaterThan(0); + expect(screen.queryByText("Loading user data...")).not.toBeInTheDocument(); + }); + + it("should render the user alias after loading", async () => { + render(); + + const aliases = await screen.findAllByText("Test Alias"); expect(aliases.length).toBeGreaterThan(0); }); }); diff --git a/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx b/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx index 2caae7d861..c377b9c4cd 100644 --- a/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx +++ b/ui/litellm-dashboard/src/components/view_users/user_info_view.tsx @@ -17,6 +17,7 @@ import { formatNumberWithCommas, copyToClipboard as utilCopyToClipboard } from " import { CopyIcon, CheckIcon } from "lucide-react"; import NotificationsManager from "../molecules/notifications_manager"; import { getBudgetDurationLabel } from "../common_components/budget_duration_dropdown"; +import DeleteResourceModal from "../common_components/DeleteResourceModal"; interface UserInfoViewProps { userId: string; @@ -60,6 +61,7 @@ export default function UserInfoView({ }: UserInfoViewProps) { const [userData, setUserData] = useState(null); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [isDeletingUser, setIsDeletingUser] = useState(false); const [isLoading, setIsLoading] = useState(true); const [isEditing, setIsEditing] = useState(startInEditMode); const [userModels, setUserModels] = useState([]); @@ -115,6 +117,7 @@ export default function UserInfoView({ const handleDelete = async () => { try { if (!accessToken) return; + setIsDeletingUser(true); await userDeleteCall(accessToken, [userId]); NotificationsManager.success("User deleted successfully"); if (onDelete) { @@ -124,9 +127,16 @@ export default function UserInfoView({ } catch (error) { console.error("Error deleting user:", error); NotificationsManager.fromBackend("Failed to delete user"); + } finally { + setIsDeleteModalOpen(false); + setIsDeletingUser(false); } }; + const cancelDelete = () => { + setIsDeleteModalOpen(false); + }; + const handleUserUpdate = async (formValues: Record) => { try { if (!accessToken || !userData) return; @@ -219,7 +229,7 @@ export default function UserInfoView({ icon={TrashIcon} variant="secondary" onClick={() => setIsDeleteModalOpen(true)} - className="flex items-center" + className="flex items-center text-red-500 border-red-500 hover:text-red-600 hover:border-red-600" > Delete User @@ -227,39 +237,33 @@ export default function UserInfoView({ )}
- {/* Delete Confirmation Modal */} - {isDeleteModalOpen && ( -
-
- - - - -
-
-
-
-

Delete User

-
-

Are you sure you want to delete this user?

-
-
-
-
-
- - -
-
-
-
- )} +