diff --git a/ui/litellm-dashboard/src/components/model_dashboard/columns.tsx b/ui/litellm-dashboard/src/components/model_dashboard/columns.tsx
index 2602761a5b..18b1f97410 100644
--- a/ui/litellm-dashboard/src/components/model_dashboard/columns.tsx
+++ b/ui/litellm-dashboard/src/components/model_dashboard/columns.tsx
@@ -23,18 +23,14 @@ export const columns = (
cell: ({ row }) => {
const model = row.original;
return (
-
-
-
-
-
+
+ setSelectedModelId(model.model_info.id)}
+ >
+ {model.model_info.id}
+
+
);
},
},
@@ -45,9 +41,9 @@ export const columns = (
const displayName = getDisplayModelName(row.original) || "-";
return (
-
- {displayName.length > 20 ? displayName.slice(0, 20) + "..." : displayName}
-
+
+ {displayName}
+
);
},
@@ -88,11 +84,9 @@ export const columns = (
const model = row.original;
return (
-
- {model.litellm_model_name
- ? model.litellm_model_name.slice(0, 20) + (model.litellm_model_name.length > 20 ? "..." : "")
- : "-"}
-
+
+ {model.litellm_model_name || "-"}
+
);
},
diff --git a/ui/litellm-dashboard/src/components/model_dashboard/table.tsx b/ui/litellm-dashboard/src/components/model_dashboard/table.tsx
index 7499c9094c..48661ad15e 100644
--- a/ui/litellm-dashboard/src/components/model_dashboard/table.tsx
+++ b/ui/litellm-dashboard/src/components/model_dashboard/table.tsx
@@ -6,6 +6,8 @@ import {
getSortedRowModel,
SortingState,
useReactTable,
+ ColumnResizeMode,
+ VisibilityState,
} from "@tanstack/react-table";
import React from "react";
import {
@@ -16,7 +18,7 @@ import {
TableRow,
TableCell,
} from "@tremor/react";
-import { SwitchVerticalIcon, ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/outline";
+import { SwitchVerticalIcon, ChevronUpIcon, ChevronDownIcon, TableIcon } from "@heroicons/react/outline";
interface ModelDataTableProps {
data: TData[];
@@ -32,100 +34,205 @@ export function ModelDataTable({
const [sorting, setSorting] = React.useState([
{ id: "model_info.created_at", desc: true }
]);
+ const [columnResizeMode] = React.useState("onChange");
+ const [columnSizing, setColumnSizing] = React.useState({});
+ const [columnVisibility, setColumnVisibility] = React.useState({});
+ const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
+ const dropdownRef = React.useRef(null);
+
+ React.useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
+ setIsDropdownOpen(false);
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => document.removeEventListener('mousedown', handleClickOutside);
+ }, []);
const table = useReactTable({
data,
columns,
state: {
sorting,
+ columnSizing,
+ columnVisibility,
},
+ columnResizeMode,
onSortingChange: setSorting,
+ onColumnSizingChange: setColumnSizing,
+ onColumnVisibilityChange: setColumnVisibility,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
enableSorting: true,
+ enableColumnResizing: true,
+ defaultColumn: {
+ minSize: 40,
+ maxSize: 500,
+ },
});
+ const getHeaderText = (header: any): string => {
+ if (typeof header === 'string') {
+ return header;
+ }
+ if (typeof header === 'function') {
+ const headerElement = header();
+ if (headerElement && headerElement.props && headerElement.props.children) {
+ const children = headerElement.props.children;
+ if (typeof children === 'string') {
+ return children;
+ }
+ if (children.props && children.props.children) {
+ return children.props.children;
+ }
+ }
+ }
+ return '';
+ };
+
return (
-
-
-
-
- {table.getHeaderGroups().map((headerGroup) => (
-
- {headerGroup.headers.map((header) => (
-
-
-
- {header.isPlaceholder ? null : (
- flexRender(
- header.column.columnDef.header,
- header.getContext()
- )
- )}
-
- {header.id !== 'actions' && (
-
- {header.column.getIsSorted() ? (
- {
- asc:
,
- desc:
- }[header.column.getIsSorted() as string]
- ) : (
-
+
+
+
+
+ {isDropdownOpen && (
+
+
+ {table.getAllLeafColumns().map((column) => {
+ if (column.id === 'actions') return null;
+ return (
+
column.toggleVisibility()}
+ >
+ column.toggleVisibility()}
+ className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
+ />
+ {getHeaderText(column.columnDef.header)}
+
+ );
+ })}
+
+
+ )}
+
+
+
+
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => (
+
+
+
+ {header.isPlaceholder ? null : (
+ flexRender(
+ header.column.columnDef.header,
+ header.getContext()
+ )
+ )}
+
+ {header.id !== 'actions' && (
+
+ {header.column.getIsSorted() ? (
+ {
+ asc: ,
+ desc:
+ }[header.column.getIsSorted() as string]
+ ) : (
+
+ )}
+
)}
- )}
-
-
+ {header.column.getCanResize() && (
+
+ )}
+
+ ))}
+
))}
-
- ))}
-
-
- {isLoading ? (
-
-
-
-
🚅 Loading models...
-
-
-
- ) : table.getRowModel().rows.length > 0 ? (
- table.getRowModel().rows.map((row) => (
-
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+
+ {isLoading ? (
+
+
+
+
🚅 Loading models...
+
- ))}
-
- ))
- ) : (
-
-
-
-
-
- )}
-
-
+
+ ) : table.getRowModel().rows.length > 0 ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+ ))}
+
+ ))
+ ) : (
+
+
+
+
+
+ )}
+
+
+
+
);