mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-12 08:42:18 +00:00
refactor(ui): migrate guardrails content tables to shared DataTable
This commit is contained in:
parent
243ade081c
commit
30fb400cbd
4 changed files with 119 additions and 117 deletions
|
|
@ -1,6 +1,8 @@
|
|||
import React from "react";
|
||||
import { Typography, Select, Table, Tag, Button } from "antd";
|
||||
import { Typography, Select, Tag, Button } from "antd";
|
||||
import { DeleteOutlined } from "@ant-design/icons";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { DataTable } from "@/components/shared/DataTable";
|
||||
|
||||
const { Text } = Typography;
|
||||
const { Option } = Select;
|
||||
|
|
@ -28,30 +30,32 @@ const CategoryTable: React.FC<CategoryTableProps> = ({
|
|||
onRemove,
|
||||
readOnly = false,
|
||||
}) => {
|
||||
const columns = [
|
||||
const columns: ColumnDef<ContentCategory>[] = [
|
||||
{
|
||||
title: "Category",
|
||||
dataIndex: "display_name",
|
||||
key: "display_name",
|
||||
render: (displayName: string, record: ContentCategory) => (
|
||||
<div>
|
||||
<Text strong>{displayName}</Text>
|
||||
{displayName !== record.category && (
|
||||
<div>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{record.category}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
header: "Category",
|
||||
accessorKey: "display_name",
|
||||
cell: ({ row }) => {
|
||||
const { category, display_name: displayName } = row.original;
|
||||
return (
|
||||
<div>
|
||||
<Text strong>{displayName}</Text>
|
||||
{displayName !== category && (
|
||||
<div>
|
||||
<Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{category}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Severity Threshold",
|
||||
dataIndex: "severity_threshold",
|
||||
key: "severity_threshold",
|
||||
width: 180,
|
||||
render: (severity: string, record: ContentCategory) => {
|
||||
header: "Severity Threshold",
|
||||
accessorKey: "severity_threshold",
|
||||
size: 180,
|
||||
cell: ({ row }) => {
|
||||
const { id, severity_threshold: severity } = row.original;
|
||||
if (readOnly) {
|
||||
const colorMap = {
|
||||
high: "red",
|
||||
|
|
@ -63,7 +67,7 @@ const CategoryTable: React.FC<CategoryTableProps> = ({
|
|||
return (
|
||||
<Select
|
||||
value={severity}
|
||||
onChange={(value) => onSeverityChange?.(record.id, value as "high" | "medium" | "low")}
|
||||
onChange={(value) => onSeverityChange?.(id, value as "high" | "medium" | "low")}
|
||||
style={{ width: 150 }}
|
||||
size="small"
|
||||
>
|
||||
|
|
@ -75,18 +79,18 @@ const CategoryTable: React.FC<CategoryTableProps> = ({
|
|||
},
|
||||
},
|
||||
{
|
||||
title: "Action",
|
||||
dataIndex: "action",
|
||||
key: "action",
|
||||
width: 150,
|
||||
render: (action: string, record: ContentCategory) => {
|
||||
header: "Action",
|
||||
accessorKey: "action",
|
||||
size: 150,
|
||||
cell: ({ row }) => {
|
||||
const { action, id } = row.original;
|
||||
if (readOnly) {
|
||||
return <Tag color={action === "BLOCK" ? "red" : "blue"}>{action}</Tag>;
|
||||
}
|
||||
return (
|
||||
<Select
|
||||
value={action}
|
||||
onChange={(value) => onActionChange?.(record.id, value as "BLOCK" | "MASK")}
|
||||
onChange={(value) => onActionChange?.(id, value as "BLOCK" | "MASK")}
|
||||
style={{ width: 120 }}
|
||||
size="small"
|
||||
>
|
||||
|
|
@ -100,22 +104,22 @@ const CategoryTable: React.FC<CategoryTableProps> = ({
|
|||
|
||||
if (!readOnly) {
|
||||
columns.push({
|
||||
title: "",
|
||||
key: "actions",
|
||||
width: 100,
|
||||
render: (_: any, record: ContentCategory) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove?.(record.id)}>
|
||||
header: "",
|
||||
id: "actions",
|
||||
size: 100,
|
||||
cell: ({ row }) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove?.(row.original.id)}>
|
||||
Delete
|
||||
</Button>
|
||||
),
|
||||
} as any);
|
||||
});
|
||||
}
|
||||
|
||||
if (categories.length === 0) {
|
||||
return <div style={{ textAlign: "center", padding: "40px 0", color: "#999" }}>No categories configured.</div>;
|
||||
}
|
||||
|
||||
return <Table dataSource={categories} columns={columns} rowKey="id" pagination={false} size="small" />;
|
||||
return <DataTable data={categories} columns={columns} getRowId={(row) => row.id} size="compact" />;
|
||||
};
|
||||
|
||||
export default CategoryTable;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import React from "react";
|
||||
import { Card, Typography, Select, Table, Tag, Collapse, Button } from "antd";
|
||||
import { Card, Typography, Select, Tag, Collapse, Button } from "antd";
|
||||
import { DeleteOutlined, PlusOutlined, FileTextOutlined } from "@ant-design/icons";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { getCategoryYaml } from "@/components/networking";
|
||||
import { DataTable } from "@/components/shared/DataTable";
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
const { Option } = Select;
|
||||
|
|
@ -160,16 +162,15 @@ const ContentCategoryConfiguration: React.FC<ContentCategoryConfigurationProps>
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [selectedCategoryName, accessToken]);
|
||||
|
||||
const columns = [
|
||||
const columns: ColumnDef<SelectedCategory>[] = [
|
||||
{
|
||||
title: "Category",
|
||||
dataIndex: "display_name",
|
||||
key: "display_name",
|
||||
render: (text: string, record: SelectedCategory) => {
|
||||
const category = availableCategories.find((c) => c.name === record.category);
|
||||
header: "Category",
|
||||
accessorKey: "display_name",
|
||||
cell: ({ row }) => {
|
||||
const category = availableCategories.find((c) => c.name === row.original.category);
|
||||
return (
|
||||
<div>
|
||||
<div style={{ fontWeight: 500 }}>{text}</div>
|
||||
<div style={{ fontWeight: 500 }}>{row.original.display_name}</div>
|
||||
{category?.description && (
|
||||
<div style={{ fontSize: "12px", color: "#888", marginTop: "4px" }}>{category.description}</div>
|
||||
)}
|
||||
|
|
@ -178,14 +179,13 @@ const ContentCategoryConfiguration: React.FC<ContentCategoryConfigurationProps>
|
|||
},
|
||||
},
|
||||
{
|
||||
title: "Action",
|
||||
dataIndex: "action",
|
||||
key: "action",
|
||||
width: 150,
|
||||
render: (action: string, record: SelectedCategory) => (
|
||||
header: "Action",
|
||||
accessorKey: "action",
|
||||
size: 150,
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
value={action}
|
||||
onChange={(value) => onCategoryUpdate(record.id, "action", value)}
|
||||
value={row.original.action}
|
||||
onChange={(value) => onCategoryUpdate(row.original.id, "action", value)}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Option value="BLOCK">
|
||||
|
|
@ -198,14 +198,13 @@ const ContentCategoryConfiguration: React.FC<ContentCategoryConfigurationProps>
|
|||
),
|
||||
},
|
||||
{
|
||||
title: "Severity Threshold",
|
||||
dataIndex: "severity_threshold",
|
||||
key: "severity_threshold",
|
||||
width: 180,
|
||||
render: (threshold: string, record: SelectedCategory) => (
|
||||
header: "Severity Threshold",
|
||||
accessorKey: "severity_threshold",
|
||||
size: 180,
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
value={threshold}
|
||||
onChange={(value) => onCategoryUpdate(record.id, "severity_threshold", value)}
|
||||
value={row.original.severity_threshold}
|
||||
onChange={(value) => onCategoryUpdate(row.original.id, "severity_threshold", value)}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Option value="low">Low</Option>
|
||||
|
|
@ -215,11 +214,11 @@ const ContentCategoryConfiguration: React.FC<ContentCategoryConfigurationProps>
|
|||
),
|
||||
},
|
||||
{
|
||||
title: "",
|
||||
key: "actions",
|
||||
width: 80,
|
||||
render: (_: any, record: SelectedCategory) => (
|
||||
<Button icon={<DeleteOutlined />} onClick={() => onCategoryRemove(record.id)} size="small">
|
||||
header: "",
|
||||
id: "actions",
|
||||
size: 80,
|
||||
cell: ({ row }) => (
|
||||
<Button icon={<DeleteOutlined />} onClick={() => onCategoryRemove(row.original.id)} size="small">
|
||||
Remove
|
||||
</Button>
|
||||
),
|
||||
|
|
@ -322,7 +321,7 @@ const ContentCategoryConfiguration: React.FC<ContentCategoryConfigurationProps>
|
|||
|
||||
{selectedCategories.length > 0 ? (
|
||||
<>
|
||||
<Table dataSource={selectedCategories} columns={columns} pagination={false} size="small" rowKey="id" />
|
||||
<DataTable data={selectedCategories} columns={columns} getRowId={(row) => row.id} size="compact" />
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Collapse
|
||||
activeKey={expandedYamlCategories}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { DeleteOutlined } from "@ant-design/icons";
|
||||
import { Button, Select, Table } from "antd";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { Button, Select } from "antd";
|
||||
import React from "react";
|
||||
import { DataTable } from "@/components/shared/DataTable";
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
|
|
@ -18,21 +20,19 @@ interface KeywordTableProps {
|
|||
}
|
||||
|
||||
const KeywordTable: React.FC<KeywordTableProps> = ({ keywords, onActionChange, onRemove }) => {
|
||||
const columns = [
|
||||
const columns: ColumnDef<BlockedWord>[] = [
|
||||
{
|
||||
title: "Keyword",
|
||||
dataIndex: "keyword",
|
||||
key: "keyword",
|
||||
header: "Keyword",
|
||||
accessorKey: "keyword",
|
||||
},
|
||||
{
|
||||
title: "Action",
|
||||
dataIndex: "action",
|
||||
key: "action",
|
||||
width: 150,
|
||||
render: (action: string, record: BlockedWord) => (
|
||||
header: "Action",
|
||||
accessorKey: "action",
|
||||
size: 150,
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
value={action}
|
||||
onChange={(value) => onActionChange(record.id, "action", value)}
|
||||
value={row.original.action}
|
||||
onChange={(value) => onActionChange(row.original.id, "action", value)}
|
||||
style={{ width: 120 }}
|
||||
size="small"
|
||||
>
|
||||
|
|
@ -42,17 +42,16 @@ const KeywordTable: React.FC<KeywordTableProps> = ({ keywords, onActionChange, o
|
|||
),
|
||||
},
|
||||
{
|
||||
title: "Description",
|
||||
dataIndex: "description",
|
||||
key: "description",
|
||||
render: (desc: string) => desc || "-",
|
||||
header: "Description",
|
||||
accessorKey: "description",
|
||||
cell: ({ row }) => row.original.description || "-",
|
||||
},
|
||||
{
|
||||
title: "",
|
||||
key: "actions",
|
||||
width: 100,
|
||||
render: (_: any, record: BlockedWord) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove(record.id)}>
|
||||
header: "",
|
||||
id: "actions",
|
||||
size: 100,
|
||||
cell: ({ row }) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove(row.original.id)}>
|
||||
Delete
|
||||
</Button>
|
||||
),
|
||||
|
|
@ -63,7 +62,7 @@ const KeywordTable: React.FC<KeywordTableProps> = ({ keywords, onActionChange, o
|
|||
return <div style={{ textAlign: "center", padding: "40px 0", color: "#999" }}>No keywords added.</div>;
|
||||
}
|
||||
|
||||
return <Table dataSource={keywords} columns={columns} rowKey="id" pagination={false} size="small" />;
|
||||
return <DataTable data={keywords} columns={columns} getRowId={(row) => row.id} size="compact" />;
|
||||
};
|
||||
|
||||
export default KeywordTable;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import React from "react";
|
||||
import { Typography, Select, Table, Tag, Button } from "antd";
|
||||
import { Typography, Select, Tag, Button } from "antd";
|
||||
import { DeleteOutlined } from "@ant-design/icons";
|
||||
import type { ColumnDef } from "@tanstack/react-table";
|
||||
import { DataTable } from "@/components/shared/DataTable";
|
||||
|
||||
const { Text } = Typography;
|
||||
const { Option } = Select;
|
||||
|
|
@ -21,44 +23,42 @@ interface PatternTableProps {
|
|||
}
|
||||
|
||||
const PatternTable: React.FC<PatternTableProps> = ({ patterns, onActionChange, onRemove }) => {
|
||||
const columns = [
|
||||
const columns: ColumnDef<Pattern>[] = [
|
||||
{
|
||||
title: "Type",
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: 100,
|
||||
render: (type: string) => (
|
||||
<Tag color={type === "prebuilt" ? "blue" : "green"}>{type === "prebuilt" ? "Prebuilt" : "Custom"}</Tag>
|
||||
header: "Type",
|
||||
accessorKey: "type",
|
||||
size: 100,
|
||||
cell: ({ row }) => (
|
||||
<Tag color={row.original.type === "prebuilt" ? "blue" : "green"}>
|
||||
{row.original.type === "prebuilt" ? "Prebuilt" : "Custom"}
|
||||
</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Pattern name",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
render: (_: string, record: Pattern) => record.display_name || record.name,
|
||||
header: "Pattern name",
|
||||
accessorKey: "name",
|
||||
cell: ({ row }) => row.original.display_name || row.original.name,
|
||||
},
|
||||
{
|
||||
title: "Regex pattern",
|
||||
dataIndex: "pattern",
|
||||
key: "pattern",
|
||||
render: (pattern: string) =>
|
||||
pattern ? (
|
||||
header: "Regex pattern",
|
||||
accessorKey: "pattern",
|
||||
cell: ({ row }) =>
|
||||
row.original.pattern ? (
|
||||
<Text code style={{ fontSize: 12 }}>
|
||||
{pattern.substring(0, 40)}...
|
||||
{row.original.pattern.substring(0, 40)}...
|
||||
</Text>
|
||||
) : (
|
||||
"-"
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "Action",
|
||||
dataIndex: "action",
|
||||
key: "action",
|
||||
width: 150,
|
||||
render: (action: string, record: Pattern) => (
|
||||
header: "Action",
|
||||
accessorKey: "action",
|
||||
size: 150,
|
||||
cell: ({ row }) => (
|
||||
<Select
|
||||
value={action}
|
||||
onChange={(value) => onActionChange(record.id, value as "BLOCK" | "MASK")}
|
||||
value={row.original.action}
|
||||
onChange={(value) => onActionChange(row.original.id, value as "BLOCK" | "MASK")}
|
||||
style={{ width: 120 }}
|
||||
size="small"
|
||||
>
|
||||
|
|
@ -68,11 +68,11 @@ const PatternTable: React.FC<PatternTableProps> = ({ patterns, onActionChange, o
|
|||
),
|
||||
},
|
||||
{
|
||||
title: "",
|
||||
key: "actions",
|
||||
width: 100,
|
||||
render: (_: any, record: Pattern) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove(record.id)}>
|
||||
header: "",
|
||||
id: "actions",
|
||||
size: 100,
|
||||
cell: ({ row }) => (
|
||||
<Button type="text" danger size="small" icon={<DeleteOutlined />} onClick={() => onRemove(row.original.id)}>
|
||||
Delete
|
||||
</Button>
|
||||
),
|
||||
|
|
@ -83,7 +83,7 @@ const PatternTable: React.FC<PatternTableProps> = ({ patterns, onActionChange, o
|
|||
return <div style={{ textAlign: "center", padding: "40px 0", color: "#999" }}>No patterns added.</div>;
|
||||
}
|
||||
|
||||
return <Table dataSource={patterns} columns={columns} rowKey="id" pagination={false} size="small" />;
|
||||
return <DataTable data={patterns} columns={columns} getRowId={(row) => row.id} size="compact" />;
|
||||
};
|
||||
|
||||
export default PatternTable;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue