mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
feat: add reusable MemberTable AntD component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b61537cd0f
commit
14e8af94a9
1 changed files with 120 additions and 0 deletions
|
|
@ -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<Member>;
|
||||
showDeleteForMember?: (member: Member) => boolean;
|
||||
}
|
||||
|
||||
export default function MemberTable({
|
||||
members,
|
||||
canEdit,
|
||||
onEdit,
|
||||
onDelete,
|
||||
onAddMember,
|
||||
roleColumnTitle = "Role",
|
||||
roleTooltip,
|
||||
extraColumns = [],
|
||||
showDeleteForMember,
|
||||
}: MemberTableProps) {
|
||||
const baseColumns: ColumnsType<Member> = [
|
||||
{
|
||||
title: "User Email",
|
||||
dataIndex: "user_email",
|
||||
key: "user_email",
|
||||
render: (email: string | null) => <Text>{email || "-"}</Text>,
|
||||
},
|
||||
{
|
||||
title: "User ID",
|
||||
dataIndex: "user_id",
|
||||
key: "user_id",
|
||||
render: (userId: string | null) =>
|
||||
userId === "default_user_id" ? (
|
||||
<Tag color="blue">Default Proxy Admin</Tag>
|
||||
) : (
|
||||
<Text>{userId || "-"}</Text>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: roleTooltip ? (
|
||||
<Space direction="horizontal">
|
||||
{roleColumnTitle}
|
||||
<Tooltip title={roleTooltip}>
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
) : (
|
||||
roleColumnTitle
|
||||
),
|
||||
dataIndex: "role",
|
||||
key: "role",
|
||||
render: (role: string) => (
|
||||
<Space>
|
||||
{role?.toLowerCase() === "admin" || role?.toLowerCase() === "org_admin" ? (
|
||||
<CrownOutlined />
|
||||
) : (
|
||||
<UserOutlined />
|
||||
)}
|
||||
<Text style={{ textTransform: "capitalize" }}>{role || "-"}</Text>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
...extraColumns,
|
||||
{
|
||||
title: "Actions",
|
||||
key: "actions",
|
||||
fixed: "right" as const,
|
||||
width: 120,
|
||||
render: (_: unknown, record: Member) =>
|
||||
canEdit ? (
|
||||
<Space>
|
||||
<TableIconActionButton
|
||||
variant="Edit"
|
||||
tooltipText="Edit member"
|
||||
dataTestId="edit-member"
|
||||
onClick={() => onEdit(record)}
|
||||
/>
|
||||
{(!showDeleteForMember || showDeleteForMember(record)) && (
|
||||
<TableIconActionButton
|
||||
variant="Delete"
|
||||
tooltipText="Delete member"
|
||||
dataTestId="delete-member"
|
||||
onClick={() => onDelete(record)}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
) : null,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: "100%" }}>
|
||||
<Table
|
||||
columns={baseColumns}
|
||||
dataSource={members}
|
||||
rowKey={(record) => record.user_id ?? record.user_email ?? JSON.stringify(record)}
|
||||
pagination={false}
|
||||
size="small"
|
||||
scroll={{ x: "max-content" }}
|
||||
/>
|
||||
{onAddMember && canEdit && (
|
||||
<Button icon={<UserAddOutlined />} type="primary" onClick={onAddMember}>
|
||||
Add Member
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue