diff --git a/ui/litellm-dashboard/.eslintrc.json b/ui/litellm-dashboard/.eslintrc.json index 2a742806f48..19a56de12d3 100644 --- a/ui/litellm-dashboard/.eslintrc.json +++ b/ui/litellm-dashboard/.eslintrc.json @@ -56,6 +56,7 @@ "src/components/Projects/ProjectsPage.tsx", "src/components/pass_through_settings.tsx", "src/components/policies/attachment_table.tsx", + "src/components/claude_code_plugins/plugin_table.tsx", "src/components/permissions/VectorStorePermissions.tsx", "src/components/permissions/AgentPermissions.tsx", "src/components/permissions/MCPServerPermissions.tsx", diff --git a/ui/litellm-dashboard/src/components/claude_code_plugins/plugin_table.tsx b/ui/litellm-dashboard/src/components/claude_code_plugins/plugin_table.tsx index 06341eb2dd7..cf4fe093e5d 100644 --- a/ui/litellm-dashboard/src/components/claude_code_plugins/plugin_table.tsx +++ b/ui/litellm-dashboard/src/components/claude_code_plugins/plugin_table.tsx @@ -1,10 +1,3 @@ -import { CopyOutlined } from "@ant-design/icons"; -import { - ChevronDownIcon, - ChevronUpIcon, - SwitchVerticalIcon, - TrashIcon, -} from "@heroicons/react/outline"; import { ColumnDef, flexRender, @@ -13,9 +6,8 @@ import { SortingState, useReactTable, } from "@tanstack/react-table"; +// eslint-disable-next-line litellm-ui/no-banned-ui-imports import { - Badge, - Button, Table, TableBody, TableCell, @@ -23,12 +15,25 @@ import { TableHeaderCell, TableRow, } from "@tremor/react"; -import { Tooltip } from "antd"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { cn } from "@/lib/utils"; +import { + ArrowUpDown, + ChevronDown, + ChevronUp, + Copy, + Trash2, +} from "lucide-react"; import React, { useState } from "react"; import NotificationsManager from "../molecules/notifications_manager"; -import { - getCategoryBadgeColor -} from "./helpers"; +import { getCategoryBadgeColor } from "./helpers"; import { Plugin } from "./types"; interface PluginTableProps { @@ -40,10 +45,32 @@ interface PluginTableProps { onPluginClick: (pluginId: string) => void; } +// Map tremor-style badge color tokens to Tailwind palette classes. +const BADGE_COLOR_CLASSES: Record = { + gray: "bg-muted text-muted-foreground", + green: + "bg-emerald-100 text-emerald-700 dark:bg-emerald-950 dark:text-emerald-300", + red: "bg-red-100 text-red-700 dark:bg-red-950 dark:text-red-300", + blue: "bg-blue-100 text-blue-700 dark:bg-blue-950 dark:text-blue-300", + indigo: "bg-indigo-100 text-indigo-700 dark:bg-indigo-950 dark:text-indigo-300", + purple: "bg-purple-100 text-purple-700 dark:bg-purple-950 dark:text-purple-300", + orange: "bg-orange-100 text-orange-700 dark:bg-orange-950 dark:text-orange-300", + amber: "bg-amber-100 text-amber-700 dark:bg-amber-950 dark:text-amber-300", + yellow: "bg-amber-100 text-amber-700 dark:bg-amber-950 dark:text-amber-300", + cyan: "bg-cyan-100 text-cyan-700 dark:bg-cyan-950 dark:text-cyan-300", + pink: "bg-pink-100 text-pink-700 dark:bg-pink-950 dark:text-pink-300", + rose: "bg-rose-100 text-rose-700 dark:bg-rose-950 dark:text-rose-300", + teal: "bg-teal-100 text-teal-700 dark:bg-teal-950 dark:text-teal-300", +}; + +const badgeClasses = (color: string): string => + BADGE_COLOR_CLASSES[color] || BADGE_COLOR_CLASSES.gray; + const PluginTable: React.FC = ({ pluginsList, isLoading, onDeleteClick, + // eslint-disable-next-line @typescript-eslint/no-unused-vars accessToken, isAdmin, onPluginClick, @@ -72,25 +99,38 @@ const PluginTable: React.FC = ({ const name = plugin.name || ""; return (
- - - - - { - e.stopPropagation(); - copyToClipboard(plugin.id); - }} - className="cursor-pointer text-gray-500 hover:text-blue-500 text-xs" - /> - + + + + + + {name} + + + + + + + + Copy Plugin ID + +
); }, @@ -98,10 +138,11 @@ const PluginTable: React.FC = ({ { header: "Version", accessorKey: "version", - cell: ({ row }) => { - const version = row.original.version || "N/A"; - return {version}; - }, + cell: ({ row }) => ( + + {row.original.version || "N/A"} + + ), }, { header: "Description", @@ -109,11 +150,16 @@ const PluginTable: React.FC = ({ cell: ({ row }) => { const description = row.original.description || "No description"; return ( - - - {description} - - + + + + + {description} + + + {description} + + ); }, }, @@ -124,14 +170,14 @@ const PluginTable: React.FC = ({ const category = row.original.category; if (!category) { return ( - + Uncategorized ); } const badgeColor = getCategoryBadgeColor(category); return ( - + {category} ); @@ -144,9 +190,10 @@ const PluginTable: React.FC = ({ const plugin = row.original; return ( {plugin.enabled ? "Yes" : "No"} @@ -159,50 +206,58 @@ const PluginTable: React.FC = ({ cell: ({ row }) => { const plugin = row.original; return ( - - {formatDate(plugin.created_at)} - + + + + {formatDate(plugin.created_at)} + + {plugin.created_at} + + ); }, }, ...(isAdmin ? [ - { - header: "Actions", - id: "actions", - enableSorting: false, - cell: ({ row }: any) => { - const plugin = row.original; - - return ( -
- -
- ); + { + header: "Actions", + id: "actions", + enableSorting: false, + cell: ({ row }: { row: { original: Plugin } }) => { + const plugin = row.original; + return ( +
+ + + + + + Delete skill + + +
+ ); + }, }, - }, - ] + ] : []), ]; const table = useReactTable({ data: pluginsList, columns, - state: { - sorting, - }, + state: { sorting }, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), @@ -219,10 +274,11 @@ const PluginTable: React.FC = ({ {headerGroup.headers.map((header) => ( = ({ {header.isPlaceholder ? null : flexRender( - header.column.columnDef.header, - header.getContext() - )} + header.column.columnDef.header, + header.getContext(), + )} {header.column.getCanSort() && (
{header.column.getIsSorted() ? ( { asc: ( - + ), desc: ( - + ), }[header.column.getIsSorted() as string] ) : ( - + )}
)} @@ -263,8 +319,11 @@ const PluginTable: React.FC = ({ {isLoading ? ( - -
+ +

Loading...

@@ -273,20 +332,21 @@ const PluginTable: React.FC = ({ table.getRowModel().rows.map((row) => ( onPluginClick(row.original.id)} > {row.getVisibleCells().map((cell) => ( {flexRender( cell.column.columnDef.cell, - cell.getContext() + cell.getContext(), )} ))} @@ -294,8 +354,11 @@ const PluginTable: React.FC = ({ )) ) : ( - -
+ +

No skills found. Add one to get started.