Skip to content

Commit e8c086f

Browse files
author
Praveen Yadav
authored
feat: add console for playground (#5)
* feat(ui): add ui components using redix-ui * feat: add LLM studio playground * feat(console): add provider page * chore(console): fetch data from ai gateway server
1 parent 279e3ac commit e8c086f

66 files changed

Lines changed: 3425 additions & 737 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Button } from "@missingstudio/ui/button";
2+
import {
3+
DropdownMenu,
4+
DropdownMenuContent,
5+
DropdownMenuItem,
6+
DropdownMenuSeparator,
7+
DropdownMenuTrigger,
8+
} from "@missingstudio/ui/dropdown-menu";
9+
import {
10+
ArrowDownIcon,
11+
ArrowUpIcon,
12+
CaretSortIcon,
13+
EyeNoneIcon,
14+
} from "@radix-ui/react-icons";
15+
import { Column } from "@tanstack/react-table";
16+
import { cn } from "~/lib/utils";
17+
18+
interface DataTableColumnHeaderProps<TData, TValue>
19+
extends React.HTMLAttributes<HTMLDivElement> {
20+
column: Column<TData, TValue>;
21+
title: string;
22+
}
23+
24+
export function DataTableColumnHeader<TData, TValue>({
25+
column,
26+
title,
27+
className,
28+
}: DataTableColumnHeaderProps<TData, TValue>) {
29+
if (!column.getCanSort()) {
30+
return <div className={cn(className)}>{title}</div>;
31+
}
32+
33+
return (
34+
<div className={cn("flex items-center space-x-2", className)}>
35+
<DropdownMenu>
36+
<DropdownMenuTrigger asChild>
37+
<Button
38+
variant="ghost"
39+
size="sm"
40+
className="-ml-3 h-8 data-[state=open]:bg-accent"
41+
>
42+
<span>{title}</span>
43+
{column.getIsSorted() === "desc" ? (
44+
<ArrowDownIcon className="ml-2 h-4 w-4" />
45+
) : column.getIsSorted() === "asc" ? (
46+
<ArrowUpIcon className="ml-2 h-4 w-4" />
47+
) : (
48+
<CaretSortIcon className="ml-2 h-4 w-4" />
49+
)}
50+
</Button>
51+
</DropdownMenuTrigger>
52+
<DropdownMenuContent align="start">
53+
<DropdownMenuItem onClick={() => column.toggleSorting(false)}>
54+
<ArrowUpIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
55+
Asc
56+
</DropdownMenuItem>
57+
<DropdownMenuItem onClick={() => column.toggleSorting(true)}>
58+
<ArrowDownIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
59+
Desc
60+
</DropdownMenuItem>
61+
<DropdownMenuSeparator />
62+
<DropdownMenuItem onClick={() => column.toggleVisibility(false)}>
63+
<EyeNoneIcon className="mr-2 h-3.5 w-3.5 text-muted-foreground/70" />
64+
Hide
65+
</DropdownMenuItem>
66+
</DropdownMenuContent>
67+
</DropdownMenu>
68+
</div>
69+
);
70+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"use client";
2+
3+
import { ColumnDef } from "@tanstack/react-table";
4+
5+
import { Badge } from "@missingstudio/ui/badge";
6+
import { Checkbox } from "@missingstudio/ui/checkbox";
7+
8+
import { DataTableColumnHeader } from "~/app/(llm)/playground/components/datatable/columnheader";
9+
import { DataTableRowActions } from "~/app/(llm)/playground/components/datatable/rowactions";
10+
11+
export const columns: ColumnDef<any>[] = [
12+
{
13+
id: "select",
14+
header: ({ table }) => (
15+
<Checkbox
16+
checked={
17+
table.getIsAllPageRowsSelected() ||
18+
(table.getIsSomePageRowsSelected() && "indeterminate")
19+
}
20+
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
21+
aria-label="Select all"
22+
className="translate-y-[2px]"
23+
/>
24+
),
25+
cell: ({ row }) => (
26+
<Checkbox
27+
checked={row.getIsSelected()}
28+
onCheckedChange={(value) => row.toggleSelected(!!value)}
29+
aria-label="Select row"
30+
className="translate-y-[2px]"
31+
/>
32+
),
33+
enableSorting: false,
34+
enableHiding: false,
35+
},
36+
37+
{
38+
accessorKey: "model",
39+
header: ({ column }) => (
40+
<DataTableColumnHeader column={column} title="Model" />
41+
),
42+
cell: ({ row }) => {
43+
return (
44+
<div className="flex space-x-2">
45+
<Badge variant="outline">{row.original.provider}</Badge>
46+
<span className="max-w-[150px] truncate font-medium">
47+
{row.original.model}
48+
</span>
49+
</div>
50+
);
51+
},
52+
enableSorting: false,
53+
},
54+
55+
{
56+
accessorKey: "prompt_tokens",
57+
header: ({ column }) => (
58+
<DataTableColumnHeader column={column} title="Prompt Tokens" />
59+
),
60+
cell: ({ row }) => {
61+
return (
62+
<div className="flex space-x-2">
63+
<span className="max-w-[50px] truncate font-medium">
64+
{row.original.prompt_tokens}
65+
</span>
66+
</div>
67+
);
68+
},
69+
},
70+
{
71+
accessorKey: "completion_tokens",
72+
header: ({ column }) => (
73+
<DataTableColumnHeader column={column} title="Completion Tokens" />
74+
),
75+
cell: ({ row }) => {
76+
return (
77+
<div className="flex space-x-2">
78+
<span className="max-w-[50px] truncate font-medium">
79+
{row.original.completion_tokens}
80+
</span>
81+
</div>
82+
);
83+
},
84+
},
85+
{
86+
accessorKey: "total_tokens",
87+
header: ({ column }) => (
88+
<DataTableColumnHeader column={column} title="Total Tokens" />
89+
),
90+
cell: ({ row }) => {
91+
return (
92+
<div className="flex space-x-2">
93+
<span className="max-w-[50px] truncate font-medium">
94+
{row.original.total_tokens}
95+
</span>
96+
</div>
97+
);
98+
},
99+
},
100+
{
101+
accessorKey: "latency",
102+
header: ({ column }) => (
103+
<DataTableColumnHeader column={column} title="Latency" />
104+
),
105+
cell: ({ row }) => {
106+
return (
107+
<div className="flex space-x-2">
108+
<span className="max-w-[100px] truncate font-medium">
109+
{row.original.latency}
110+
</span>
111+
</div>
112+
);
113+
},
114+
},
115+
116+
{
117+
id: "actions",
118+
cell: ({ row }) => <DataTableRowActions row={row} />,
119+
},
120+
];
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"use client";
2+
3+
import {
4+
ColumnFiltersState,
5+
SortingState,
6+
VisibilityState,
7+
flexRender,
8+
getCoreRowModel,
9+
getFacetedRowModel,
10+
getFacetedUniqueValues,
11+
getFilteredRowModel,
12+
getPaginationRowModel,
13+
getSortedRowModel,
14+
useReactTable,
15+
} from "@tanstack/react-table";
16+
import * as React from "react";
17+
18+
import {
19+
Table,
20+
TableBody,
21+
TableCell,
22+
TableHead,
23+
TableHeader,
24+
TableRow,
25+
} from "@missingstudio/ui/table";
26+
27+
import { columns } from "~/app/(llm)/playground/components/datatable/columns";
28+
import { DataTablePagination } from "~/app/(llm)/playground/components/datatable/pagination";
29+
import { useLogsFetch } from "~/app/(llm)/playground/hooks/useLogsFetch";
30+
import { useStore } from "~/app/(llm)/playground/store";
31+
32+
export default function DataTable<TData, TValue>() {
33+
const [rowSelection, setRowSelection] = React.useState({});
34+
const [columnVisibility, setColumnVisibility] =
35+
React.useState<VisibilityState>({});
36+
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
37+
[]
38+
);
39+
const [sorting, setSorting] = React.useState<SortingState>([]);
40+
41+
useLogsFetch();
42+
const { logs } = useStore();
43+
44+
const table = useReactTable({
45+
data: logs,
46+
columns,
47+
state: {
48+
sorting,
49+
columnVisibility,
50+
rowSelection,
51+
columnFilters,
52+
},
53+
enableRowSelection: true,
54+
onRowSelectionChange: setRowSelection,
55+
onSortingChange: setSorting,
56+
onColumnFiltersChange: setColumnFilters,
57+
onColumnVisibilityChange: setColumnVisibility,
58+
getCoreRowModel: getCoreRowModel(),
59+
getFilteredRowModel: getFilteredRowModel(),
60+
getPaginationRowModel: getPaginationRowModel(),
61+
getSortedRowModel: getSortedRowModel(),
62+
getFacetedRowModel: getFacetedRowModel(),
63+
getFacetedUniqueValues: getFacetedUniqueValues(),
64+
});
65+
66+
return (
67+
<div className="space-y-4">
68+
<div className="rounded-md border">
69+
<Table>
70+
<TableHeader>
71+
{table.getHeaderGroups().map((headerGroup) => (
72+
<TableRow key={headerGroup.id}>
73+
{headerGroup.headers.map((header) => {
74+
return (
75+
<TableHead key={header.id} colSpan={header.colSpan}>
76+
{header.isPlaceholder
77+
? null
78+
: flexRender(
79+
header.column.columnDef.header,
80+
header.getContext()
81+
)}
82+
</TableHead>
83+
);
84+
})}
85+
</TableRow>
86+
))}
87+
</TableHeader>
88+
<TableBody>
89+
{table.getRowModel().rows?.length ? (
90+
table.getRowModel().rows.map((row) => (
91+
<TableRow
92+
key={row.id}
93+
data-state={row.getIsSelected() && "selected"}
94+
>
95+
{row.getVisibleCells().map((cell) => (
96+
<TableCell key={cell.id}>
97+
{flexRender(
98+
cell.column.columnDef.cell,
99+
cell.getContext()
100+
)}
101+
</TableCell>
102+
))}
103+
</TableRow>
104+
))
105+
) : (
106+
<TableRow>
107+
<TableCell
108+
colSpan={columns.length}
109+
className="h-24 text-center"
110+
>
111+
No results.
112+
</TableCell>
113+
</TableRow>
114+
)}
115+
</TableBody>
116+
</Table>
117+
</div>
118+
<DataTablePagination table={table} />
119+
</div>
120+
);
121+
}

0 commit comments

Comments
 (0)