mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-05 08:07:05 +00:00
Merge pull request #19192 from BerriAI/litellm_ui_team_member_table
[Refactor] UI - Team Member Icon Buttons
This commit is contained in:
commit
416ad7ea35
2 changed files with 44 additions and 19 deletions
|
|
@ -20,6 +20,7 @@ vi.mock("@/utils/roles", () => ({
|
|||
|
||||
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { isProxyAdminRole, isUserTeamAdminForSingleTeam } from "@/utils/roles";
|
||||
|
||||
describe("TeamMembersComponent", () => {
|
||||
const mockHandleMemberDelete = vi.fn();
|
||||
|
|
@ -162,4 +163,31 @@ describe("TeamMembersComponent", () => {
|
|||
|
||||
expect(screen.getByText("Add Member")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should show delete button for proxy admin when canEditTeam is true", () => {
|
||||
vi.mocked(isProxyAdminRole).mockReturnValue(true);
|
||||
vi.mocked(isUserTeamAdminForSingleTeam).mockReturnValue(false);
|
||||
|
||||
const { container } = renderWithProviders(
|
||||
<TeamMembersComponent
|
||||
teamData={mockTeamData}
|
||||
canEditTeam={true}
|
||||
handleMemberDelete={mockHandleMemberDelete}
|
||||
setSelectedEditMember={mockSetSelectedEditMember}
|
||||
setIsEditMemberModalVisible={mockSetIsEditMemberModalVisible}
|
||||
setIsAddMemberModalVisible={mockSetIsAddMemberModalVisible}
|
||||
/>,
|
||||
);
|
||||
|
||||
// Verify that action buttons are rendered when canEditTeam is true
|
||||
// For proxy admin, both edit and delete buttons should be visible
|
||||
// Check for clickable icon elements (Tremor Icon components with cursor-pointer class)
|
||||
const clickableIcons = container.querySelectorAll('[class*="cursor-pointer"]');
|
||||
// Should have at least 4 icons: 2 edit buttons + 2 delete buttons for 2 members
|
||||
expect(clickableIcons.length).toBeGreaterThanOrEqual(4);
|
||||
|
||||
// Verify members are rendered
|
||||
expect(screen.getAllByText("user1@test.com").length).toBeGreaterThan(0);
|
||||
expect(screen.getAllByText("user2@test.com").length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,25 +1,24 @@
|
|||
import React from "react";
|
||||
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { Member } from "@/components/networking";
|
||||
import { formatNumberWithCommas } from "@/utils/dataUtils";
|
||||
import { isProxyAdminRole, isUserTeamAdminForSingleTeam } from "@/utils/roles";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import {
|
||||
Card,
|
||||
Table,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableHeaderCell,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableRow,
|
||||
Text,
|
||||
Icon,
|
||||
Button as TremorButton,
|
||||
} from "@tremor/react";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Tooltip } from "antd";
|
||||
import React from "react";
|
||||
import TableIconActionButton from "../common_components/IconActionButton/TableIconActionButtons/TableIconActionButton";
|
||||
import { TeamData } from "./team_info";
|
||||
import { PencilAltIcon, TrashIcon } from "@heroicons/react/outline";
|
||||
import { formatNumberWithCommas } from "@/utils/dataUtils";
|
||||
import { useUISettings } from "@/app/(dashboard)/hooks/uiSettings/useUISettings";
|
||||
import { isUserTeamAdminForSingleTeam, isProxyAdminRole } from "@/utils/roles";
|
||||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
interface TeamMembersComponentProps {
|
||||
teamData: TeamData;
|
||||
|
|
@ -154,9 +153,9 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
|||
<TableCell className="sticky right-0 bg-white z-10 border-l border-gray-200">
|
||||
{canEditTeam && (
|
||||
<div className="flex gap-2">
|
||||
<Icon
|
||||
icon={PencilAltIcon}
|
||||
size="sm"
|
||||
<TableIconActionButton
|
||||
variant="Edit"
|
||||
tooltipText="Edit member"
|
||||
onClick={() => {
|
||||
// Get budget and rate limit data from team membership
|
||||
const membership = teamData.team_memberships.find((tm) => tm.user_id === member.user_id);
|
||||
|
|
@ -169,14 +168,12 @@ const TeamMembersComponent: React.FC<TeamMembersComponentProps> = ({
|
|||
setSelectedEditMember(enhancedMember);
|
||||
setIsEditMemberModalVisible(true);
|
||||
}}
|
||||
className="cursor-pointer hover:text-blue-600"
|
||||
/>
|
||||
{(isProxyAdmin || (isUserTeamAdmin && !disableTeamAdminDeleteTeamUser)) && (
|
||||
<Icon
|
||||
icon={TrashIcon}
|
||||
size="sm"
|
||||
<TableIconActionButton
|
||||
variant="Delete"
|
||||
tooltipText="Delete member"
|
||||
onClick={() => handleMemberDelete(member)}
|
||||
className="cursor-pointer hover:text-red-600"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue