[Feat] UI - Allow sorting MCPs by created_at, Display name date (#22825)

* Add column sorting to MCP servers table

- Added sorting state management to DataTable component
- Enabled getSortedRowModel for tanstack/react-table
- Made column headers clickable with sort indicators (↑↓⇅)
- Added enableSorting: true to sortable columns in mcp_server_columns
- Columns now support ascending/descending sort by clicking headers
- Updated package-lock.json and tsconfig.json from build process

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

* Make table sorting opt-in to avoid conflicts with existing consumers

Address Greptile feedback (score 2/5):
- Added enableSorting prop to DataTable (defaults to false)
- Only enable sorting features when explicitly requested
- Pass enableSorting=true from MCP servers component
- This prevents unintended sorting on other DataTable consumers:
  * view_logs (has server-side sorting)
  * pass_through_settings
  * UsagePage
- Sorting UI (indicators, click handlers) only shown when enabled

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
This commit is contained in:
Ishaan Jaff 2026-03-04 17:47:01 -08:00 committed by GitHub
parent a33d3e035d
commit dd183a7fcb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 19 deletions

View File

@ -12984,21 +12984,6 @@
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/@next/swc-win32-ia32-msvc": {
"version": "14.2.33",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz",
"integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
}
}
}

View File

@ -15,6 +15,7 @@ export const mcpServerColumns = (
{
accessorKey: "server_id",
header: "Server ID",
enableSorting: true,
cell: ({ row }) => (
<button
onClick={() => onView(row.original.server_id)}
@ -27,10 +28,12 @@ export const mcpServerColumns = (
{
accessorKey: "server_name",
header: "Name",
enableSorting: true,
},
{
accessorKey: "alias",
header: "Alias",
enableSorting: true,
},
{
id: "url",
@ -47,6 +50,7 @@ export const mcpServerColumns = (
{
accessorKey: "transport",
header: "Transport",
enableSorting: true,
cell: ({ row }) => {
const transport = row.original.transport || "http";
const specPath = row.original.spec_path;
@ -58,6 +62,7 @@ export const mcpServerColumns = (
{
accessorKey: "auth_type",
header: "Auth Type",
enableSorting: true,
cell: ({ getValue }) => <span>{(getValue() as string) || "none"}</span>,
},
{
@ -166,6 +171,7 @@ export const mcpServerColumns = (
{
header: "Created At",
accessorKey: "created_at",
enableSorting: true,
sortingFn: "datetime",
cell: ({ row }) => {
const server = row.original;
@ -177,6 +183,7 @@ export const mcpServerColumns = (
{
header: "Updated At",
accessorKey: "updated_at",
enableSorting: true,
sortingFn: "datetime",
cell: ({ row }) => {
const server = row.original;

View File

@ -410,6 +410,7 @@ const MCPServers: React.FC<MCPServerProps> = ({ accessToken, userRole, userID })
isLoading={isLoadingServers}
noDataMessage="No MCP servers configured"
loadingMessage="🚅 Loading MCP servers..."
enableSorting={true}
/>
</div>
</div>

View File

@ -1,5 +1,5 @@
import { Fragment } from "react";
import { ColumnDef, flexRender, getCoreRowModel, getExpandedRowModel, Row, useReactTable } from "@tanstack/react-table";
import { Fragment, useState } from "react";
import { ColumnDef, flexRender, getCoreRowModel, getExpandedRowModel, Row, useReactTable, getSortedRowModel, SortingState } from "@tanstack/react-table";
import { Table, TableHead, TableHeaderCell, TableBody, TableRow, TableCell } from "@tremor/react";
@ -15,6 +15,8 @@ interface DataTableProps<TData, TValue> {
isLoading?: boolean;
loadingMessage?: string;
noDataMessage?: string;
/** Enable client-side column sorting (defaults to false to avoid conflicts with server-side sorting) */
enableSorting?: boolean;
}
export function DataTable<TData, TValue>({
@ -27,18 +29,28 @@ export function DataTable<TData, TValue>({
isLoading = false,
loadingMessage = "🚅 Loading logs...",
noDataMessage = "No logs found",
enableSorting = false,
}: DataTableProps<TData, TValue>) {
const supportsExpansion = !!(renderSubComponent || renderChildRows) && !!getRowCanExpand;
const [sorting, setSorting] = useState<SortingState>([]);
const table = useReactTable<TData>({
data,
columns,
...(enableSorting && {
state: {
sorting,
},
onSortingChange: setSorting,
enableSortingRemoval: false,
}),
...(supportsExpansion && { getRowCanExpand }),
getRowId: (row: TData, index: number) => {
const _row: any = row as any;
return _row?.request_id ?? String(index);
},
getCoreRowModel: getCoreRowModel(),
...(enableSorting && { getSortedRowModel: getSortedRowModel() }),
...(supportsExpansion && { getExpandedRowModel: getExpandedRowModel() }),
});
@ -49,9 +61,25 @@ export function DataTable<TData, TValue>({
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
const canSort = enableSorting && header.column.getCanSort();
const isSorted = header.column.getIsSorted();
return (
<TableHeaderCell key={header.id} className="py-1 h-8">
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
<TableHeaderCell
key={header.id}
className={`py-1 h-8 ${canSort ? 'cursor-pointer select-none hover:bg-gray-50' : ''}`}
onClick={canSort ? header.column.getToggleSortingHandler() : undefined}
>
{header.isPlaceholder ? null : (
<div className="flex items-center gap-1">
{flexRender(header.column.columnDef.header, header.getContext())}
{canSort && (
<span className="text-gray-400">
{isSorted === 'asc' ? '↑' : isSorted === 'desc' ? '↓' : '⇅'}
</span>
)}
</div>
)}
</TableHeaderCell>
);
})}