diff --git a/ui/litellm-dashboard/src/components/common_components/MemberTable.tsx b/ui/litellm-dashboard/src/components/common_components/MemberTable.tsx new file mode 100644 index 00000000000..3392158afe8 --- /dev/null +++ b/ui/litellm-dashboard/src/components/common_components/MemberTable.tsx @@ -0,0 +1,120 @@ +import { Member } from "@/components/networking"; +import { CrownOutlined, InfoCircleOutlined, UserAddOutlined, UserOutlined } from "@ant-design/icons"; +import { Button, Space, Table, Tag, Tooltip, Typography } from "antd"; +import type { ColumnsType } from "antd/es/table"; +import React from "react"; +import TableIconActionButton from "./IconActionButton/TableIconActionButtons/TableIconActionButton"; + +const { Text } = Typography; + +export interface MemberTableProps { + members: Member[]; + canEdit: boolean; + onEdit: (member: Member) => void; + onDelete: (member: Member) => void; + onAddMember?: () => void; + roleColumnTitle?: string; + roleTooltip?: string; + extraColumns?: ColumnsType; + showDeleteForMember?: (member: Member) => boolean; +} + +export default function MemberTable({ + members, + canEdit, + onEdit, + onDelete, + onAddMember, + roleColumnTitle = "Role", + roleTooltip, + extraColumns = [], + showDeleteForMember, +}: MemberTableProps) { + const baseColumns: ColumnsType = [ + { + title: "User Email", + dataIndex: "user_email", + key: "user_email", + render: (email: string | null) => {email || "-"}, + }, + { + title: "User ID", + dataIndex: "user_id", + key: "user_id", + render: (userId: string | null) => + userId === "default_user_id" ? ( + Default Proxy Admin + ) : ( + {userId || "-"} + ), + }, + { + title: roleTooltip ? ( + + {roleColumnTitle} + + + + + ) : ( + roleColumnTitle + ), + dataIndex: "role", + key: "role", + render: (role: string) => ( + + {role?.toLowerCase() === "admin" || role?.toLowerCase() === "org_admin" ? ( + + ) : ( + + )} + {role || "-"} + + ), + }, + ...extraColumns, + { + title: "Actions", + key: "actions", + fixed: "right" as const, + width: 120, + render: (_: unknown, record: Member) => + canEdit ? ( + + onEdit(record)} + /> + {(!showDeleteForMember || showDeleteForMember(record)) && ( + onDelete(record)} + /> + )} + + ) : null, + }, + ]; + + return ( + + record.user_id ?? record.user_email ?? JSON.stringify(record)} + pagination={false} + size="small" + scroll={{ x: "max-content" }} + /> + {onAddMember && canEdit && ( + + )} + + ); +}