DesertWolf's picture
Upload folder using huggingface_hub
447ebeb verified
import React, { useState } from "react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeaderCell,
TableRow,
Icon,
Button,
} from "@tremor/react";
import {
TrashIcon,
SwitchVerticalIcon,
ChevronUpIcon,
ChevronDownIcon,
} from "@heroicons/react/outline";
import { Tooltip } from "antd";
import {
ColumnDef,
flexRender,
getCoreRowModel,
getSortedRowModel,
SortingState,
useReactTable,
} from "@tanstack/react-table";
import { getGuardrailLogoAndName, guardrail_provider_map } from "./guardrail_info_helpers";
import EditGuardrailForm from "./edit_guardrail_form";
import GuardrailInfoView from "./guardrail_info";
interface GuardrailItem {
guardrail_id?: string;
guardrail_name: string | null;
litellm_params: {
guardrail: string;
mode: string;
default_on: boolean;
pii_entities_config?: {[key: string]: string};
[key: string]: any;
};
guardrail_info: Record<string, any> | null;
created_at?: string;
updated_at?: string;
}
interface GuardrailTableProps {
guardrailsList: GuardrailItem[];
isLoading: boolean;
onDeleteClick: (guardrailId: string, guardrailName: string) => void;
accessToken: string | null;
onGuardrailUpdated: () => void;
isAdmin?: boolean;
onShowGuardrailInfo?: (isVisible: boolean) => void;
}
const GuardrailTable: React.FC<GuardrailTableProps> = ({
guardrailsList,
isLoading,
onDeleteClick,
accessToken,
onGuardrailUpdated,
isAdmin = false,
onShowGuardrailInfo,
}) => {
const [sorting, setSorting] = useState<SortingState>([
{ id: "created_at", desc: true }
]);
const [editModalVisible, setEditModalVisible] = useState(false);
const [selectedGuardrail, setSelectedGuardrail] = useState<GuardrailItem | null>(null);
const [showGuardrailInfo, setShowGuardrailInfo] = useState(false);
const [selectedGuardrailId, setSelectedGuardrailId] = useState<string | null>(null);
// Format date helper function
const formatDate = (dateString?: string) => {
if (!dateString) return "-";
const date = new Date(dateString);
return date.toLocaleString();
};
const handleEditClick = (guardrail: GuardrailItem) => {
setSelectedGuardrail(guardrail);
setEditModalVisible(true);
};
const handleEditSuccess = () => {
setEditModalVisible(false);
setSelectedGuardrail(null);
onGuardrailUpdated();
};
const handleGuardrailIdClick = (guardrailId: string) => {
setSelectedGuardrailId(guardrailId);
setShowGuardrailInfo(true);
onShowGuardrailInfo?.(true);
};
const handleGuardrailInfoClose = () => {
setShowGuardrailInfo(false);
setSelectedGuardrailId(null);
onShowGuardrailInfo?.(false);
};
const handleGuardrailDeleted = () => {
setShowGuardrailInfo(false);
setSelectedGuardrailId(null);
onShowGuardrailInfo?.(false);
onGuardrailUpdated();
};
const columns: ColumnDef<GuardrailItem>[] = [
{
header: "Guardrail ID",
accessorKey: "guardrail_id",
cell: (info: any) => (
<Tooltip title={String(info.getValue() || "")}>
<Button
size="xs"
variant="light"
className="font-mono text-blue-500 bg-blue-50 hover:bg-blue-100 text-xs font-normal px-2 py-0.5 text-left overflow-hidden truncate max-w-[200px]"
onClick={() => info.getValue() && handleGuardrailIdClick(info.getValue())}
>
{info.getValue() ? `${String(info.getValue()).slice(0, 7)}...` : ""}
</Button>
</Tooltip>
),
},
{
header: "Name",
accessorKey: "guardrail_name",
cell: ({ row }) => {
const guardrail = row.original;
return (
<Tooltip title={guardrail.guardrail_name}>
<span className="text-xs font-medium">
{guardrail.guardrail_name || "-"}
</span>
</Tooltip>
);
},
},
{
header: "Provider",
accessorKey: "litellm_params.guardrail",
cell: ({ row }) => {
const guardrail = row.original;
const { logo, displayName } = getGuardrailLogoAndName(guardrail.litellm_params.guardrail);
return (
<div className="flex items-center space-x-2">
{logo && (
<img
src={logo}
alt={`${displayName} logo`}
className="w-4 h-4"
onError={(e) => {
// Hide broken image
(e.target as HTMLImageElement).style.display = 'none';
}}
/>
)}
<span className="text-xs">{displayName}</span>
</div>
);
},
},
{
header: "Mode",
accessorKey: "litellm_params.mode",
cell: ({ row }) => {
const guardrail = row.original;
return (
<span className="text-xs">
{guardrail.litellm_params.mode}
</span>
);
},
},
{
header: "Created At",
accessorKey: "created_at",
cell: ({ row }) => {
const guardrail = row.original;
return (
<Tooltip title={guardrail.created_at}>
<span className="text-xs">
{formatDate(guardrail.created_at)}
</span>
</Tooltip>
);
},
},
{
header: "Updated At",
accessorKey: "updated_at",
cell: ({ row }) => {
const guardrail = row.original;
return (
<Tooltip title={guardrail.updated_at}>
<span className="text-xs">
{formatDate(guardrail.updated_at)}
</span>
</Tooltip>
);
},
},
{
id: "actions",
header: "",
cell: ({ row }) => {
const guardrail = row.original;
return (
<div className="flex space-x-2">
<Icon
icon={TrashIcon}
size="sm"
onClick={() => guardrail.guardrail_id && onDeleteClick(guardrail.guardrail_id, guardrail.guardrail_name || 'Unnamed Guardrail')}
className="cursor-pointer hover:text-red-500"
tooltip="Delete guardrail"
/>
</div>
);
},
},
];
const table = useReactTable({
data: guardrailsList,
columns,
state: {
sorting,
},
onSortingChange: setSorting,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
enableSorting: true,
});
// If showing guardrail info, render the GuardrailInfoView
if (showGuardrailInfo && selectedGuardrailId) {
return (
<GuardrailInfoView
guardrailId={selectedGuardrailId}
onClose={handleGuardrailInfoClose}
accessToken={accessToken}
isAdmin={isAdmin}
/>
);
}
return (
<div className="rounded-lg custom-border relative">
<div className="overflow-x-auto">
<Table className="[&_td]:py-0.5 [&_th]:py-1">
<TableHead>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHeaderCell
key={header.id}
className={`py-1 h-8 ${
header.id === 'actions'
? 'sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]'
: ''
}`}
onClick={header.column.getToggleSortingHandler()}
>
<div className="flex items-center justify-between gap-2">
<div className="flex items-center">
{header.isPlaceholder ? null : (
flexRender(
header.column.columnDef.header,
header.getContext()
)
)}
</div>
{header.id !== 'actions' && (
<div className="w-4">
{header.column.getIsSorted() ? (
{
asc: <ChevronUpIcon className="h-4 w-4 text-blue-500" />,
desc: <ChevronDownIcon className="h-4 w-4 text-blue-500" />
}[header.column.getIsSorted() as string]
) : (
<SwitchVerticalIcon className="h-4 w-4 text-gray-400" />
)}
</div>
)}
</div>
</TableHeaderCell>
))}
</TableRow>
))}
</TableHead>
<TableBody>
{isLoading ? (
<TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>Loading...</p>
</div>
</TableCell>
</TableRow>
) : guardrailsList.length > 0 ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} className="h-8">
{row.getVisibleCells().map((cell) => (
<TableCell
key={cell.id}
className={`py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap ${
cell.column.id === 'actions'
? 'sticky right-0 bg-white shadow-[-4px_0_8px_-6px_rgba(0,0,0,0.1)]'
: ''
}`}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>No guardrails found</p>
</div>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
{/* Edit Modal */}
{selectedGuardrail && (
<EditGuardrailForm
visible={editModalVisible}
onClose={() => setEditModalVisible(false)}
accessToken={accessToken}
onSuccess={handleEditSuccess}
guardrailId={selectedGuardrail.guardrail_id || ''}
initialValues={{
guardrail_name: selectedGuardrail.guardrail_name || '',
provider: Object.keys(guardrail_provider_map).find(
key => guardrail_provider_map[key] === selectedGuardrail?.litellm_params.guardrail
) || '',
mode: selectedGuardrail.litellm_params.mode,
default_on: selectedGuardrail.litellm_params.default_on,
pii_entities_config: selectedGuardrail.litellm_params.pii_entities_config,
...selectedGuardrail.guardrail_info
}}
/>
)}
</div>
);
};
export default GuardrailTable;