-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add react-table dependency * Add shadcn Tasks components * Expose PopoverClose * Add adapted filters for future tags * Add useDebounce hook * Add txs columns * Add filters toolbar * Add txs table
- Loading branch information
Showing
4 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
"use client"; | ||
|
||
import { useTxs } from "@/hooks/api"; | ||
import { useDebounce } from "@/hooks/use-debounce"; | ||
import { Tx } from "@/types/txs"; | ||
import { | ||
ColumnDef, | ||
ColumnFiltersState, | ||
SortingState, | ||
VisibilityState, | ||
getCoreRowModel, | ||
getFacetedRowModel, | ||
getFacetedUniqueValues, | ||
getFilteredRowModel, | ||
getPaginationRowModel, | ||
getSortedRowModel, | ||
useReactTable, | ||
} from "@tanstack/react-table"; | ||
import { useState } from "react"; | ||
import { DataTable } from "../data-table"; | ||
import { DataTableColumnHeader } from "../data-table/data-table-column-header"; | ||
import { DataTablePagination } from "../data-table/data-table-pagination"; | ||
import { txsColumns } from "./txs-columns"; | ||
import { DataTableToolbar } from "./txs-table-toolbar"; | ||
|
||
export function TxsTable() { | ||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({ | ||
tags: false, | ||
}); | ||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]); | ||
const [sorting, setSorting] = useState<SortingState>([]); | ||
|
||
const operationNameValue = columnFilters.find( | ||
(filter) => filter.id === "operationName", | ||
)?.value; | ||
const operationName = useDebounce( | ||
typeof operationNameValue === "string" && operationNameValue.length | ||
? operationNameValue | ||
: "execute_tx", | ||
); | ||
|
||
const tags = | ||
(columnFilters.find((filter) => filter.id === "tags")?.value as | ||
| Map<string, string> | ||
| undefined) ?? undefined; | ||
|
||
const tagsColumns: ColumnDef<Tx>[] = Array.from(tags?.keys() ?? []).map( | ||
(tagKey) => ({ | ||
accessorKey: tagKey, | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title={tagKey} /> | ||
), | ||
cell: ({ row }) => ( | ||
<div className="max-w-[500px] truncate font-medium"> | ||
{(row.getValue("tags") as Map<string, string>).get(tagKey)} | ||
</div> | ||
), | ||
//NOTE - Don't UI filter, query API | ||
filterFn: () => true, | ||
}), | ||
); | ||
|
||
const columns = [...txsColumns, ...tagsColumns]; | ||
|
||
const { isPending, error, data: txs } = useTxs(operationName, tags); | ||
const data = (txs ?? []) as Tx[]; | ||
|
||
const table = useReactTable({ | ||
columns, | ||
data, | ||
state: { columnVisibility, columnFilters, sorting }, | ||
onColumnVisibilityChange: setColumnVisibility, | ||
onColumnFiltersChange: setColumnFilters, | ||
onSortingChange: setSorting, | ||
getCoreRowModel: getCoreRowModel(), | ||
getFacetedRowModel: getFacetedRowModel(), | ||
getFacetedUniqueValues: getFacetedUniqueValues(), | ||
getFilteredRowModel: getFilteredRowModel(), | ||
getPaginationRowModel: getPaginationRowModel(), | ||
getSortedRowModel: getSortedRowModel(), | ||
}); | ||
|
||
return ( | ||
<div className="space-y-4"> | ||
<DataTableToolbar table={table} /> | ||
<div className="rounded-md border"> | ||
<DataTable | ||
status={{ isPending, error }} | ||
table={table} | ||
rowLink={{ url: "/", field: "traceId" }} | ||
/> | ||
</div> | ||
<DataTablePagination table={table} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { Tx } from "@/types/txs"; | ||
import { ColumnDef } from "@tanstack/react-table"; | ||
import { DataTableColumnHeader } from "../data-table/data-table-column-header"; | ||
|
||
export const txsColumns: ColumnDef<Tx>[] = [ | ||
{ | ||
accessorKey: "traceId", | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title="Trace" /> | ||
), | ||
cell: ({ row }) => ( | ||
<div className="max-w-[500px] font-medium">{row.getValue("traceId")}</div> | ||
), | ||
enableSorting: false, | ||
enableHiding: false, | ||
}, | ||
{ | ||
accessorKey: "spanId", | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title="Span" /> | ||
), | ||
cell: ({ row }) => ( | ||
<div className="max-w-[500px] font-medium">{row.getValue("spanId")}</div> | ||
), | ||
enableSorting: false, | ||
enableHiding: false, | ||
}, | ||
{ | ||
accessorKey: "operationName", | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title="Operation" /> | ||
), | ||
cell: ({ row }) => ( | ||
<div className="max-w-[500px] font-medium"> | ||
{row.getValue("operationName")} | ||
</div> | ||
), | ||
//NOTE - Don't UI filter, query API | ||
filterFn: () => true, | ||
}, | ||
{ | ||
accessorKey: "tags", | ||
header: ({ column }) => ( | ||
<DataTableColumnHeader column={column} title="Tags" /> | ||
), | ||
cell: ({ row }) => ( | ||
<div className="max-w-[500px] truncate font-medium"> | ||
{Array.from((row.getValue("tags") as Map<string, string>).keys()).join( | ||
", ", | ||
)} | ||
</div> | ||
), | ||
//NOTE - Don't UI filter, query API | ||
filterFn: () => true, | ||
enableHiding: false, | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
import { Button } from "@/components/ui/button"; | ||
import { Input } from "@/components/ui/input"; | ||
import { | ||
Select, | ||
SelectContent, | ||
SelectGroup, | ||
SelectItem, | ||
SelectLabel, | ||
SelectTrigger, | ||
SelectValue, | ||
} from "@/components/ui/select"; | ||
import { Cross2Icon } from "@radix-ui/react-icons"; | ||
import { Table } from "@tanstack/react-table"; | ||
import { DataTableKvFilter } from "../data-table/data-table-kv-filter"; | ||
import { DataTableViewOptions } from "../data-table/data-table-view-options"; | ||
|
||
const getSelectedValue = <TData,>(table: Table<TData>) => { | ||
if ( | ||
!table.getColumn("operationName")?.getFilterValue() && | ||
!table.getColumn("tags")?.getFilterValue() | ||
) { | ||
return "empty"; | ||
} | ||
|
||
if ((table.getColumn("operationName")?.getFilterValue() as string) ?? "") { | ||
return "custom"; | ||
} | ||
|
||
const tags = table.getColumn("tags")?.getFilterValue() as | ||
| Map<string, string> | ||
| undefined; | ||
|
||
if (tags?.size === 1 && tags?.get("raw_tx") === "*") { | ||
return "simulations"; | ||
} | ||
|
||
if (tags?.size === 1 && tags?.get("tx_hash") === "*") { | ||
return "broadcasted"; | ||
} | ||
|
||
return "custom"; | ||
}; | ||
|
||
interface DataTableToolbarProps<TData> { | ||
table: Table<TData>; | ||
} | ||
|
||
export function DataTableToolbar<TData>({ | ||
table, | ||
}: DataTableToolbarProps<TData>) { | ||
return ( | ||
<div className="flex justify-between"> | ||
<div className="flex flex-wrap gap-2"> | ||
<Select | ||
value={getSelectedValue(table)} | ||
onValueChange={(value) => { | ||
switch (value) { | ||
case "simulations": { | ||
table | ||
.getColumn("tags") | ||
?.setFilterValue(new Map([["raw_tx", "*"]])); | ||
break; | ||
} | ||
case "broadcasted": { | ||
table | ||
.getColumn("tags") | ||
?.setFilterValue(new Map([["tx_hash", "*"]])); | ||
break; | ||
} | ||
default: { | ||
table.resetColumnFilters(); | ||
} | ||
} | ||
}} | ||
> | ||
<SelectTrigger className="w-[220px]"> | ||
<SelectValue /> | ||
</SelectTrigger> | ||
<SelectContent> | ||
<SelectGroup> | ||
<SelectLabel>Filters</SelectLabel> | ||
<SelectItem | ||
value="empty" | ||
className="hidden" | ||
disabled | ||
aria-disabled | ||
> | ||
Empty filter | ||
</SelectItem> | ||
<SelectItem | ||
value="custom" | ||
className="hidden" | ||
disabled | ||
aria-disabled | ||
> | ||
Custom filter | ||
</SelectItem> | ||
<SelectItem value="simulations">Failed simulations</SelectItem> | ||
<SelectItem value="broadcasted"> | ||
Broadcasted transactions | ||
</SelectItem> | ||
</SelectGroup> | ||
</SelectContent> | ||
</Select> | ||
<Input | ||
placeholder="Filter operation…" | ||
value={ | ||
(table.getColumn("operationName")?.getFilterValue() as string) ?? "" | ||
} | ||
onChange={(event) => | ||
table.getColumn("operationName")?.setFilterValue(event.target.value) | ||
} | ||
className="h-8 w-[150px] lg:w-[250px]" | ||
/> | ||
{table.getColumn("tags") && ( | ||
<DataTableKvFilter column={table.getColumn("tags")} title="Tag" /> | ||
)} | ||
{table.getState().columnFilters.length > 0 && ( | ||
<Button | ||
variant="ghost" | ||
onClick={() => table.resetColumnFilters()} | ||
className="h-8 px-2 lg:px-3" | ||
> | ||
Reset | ||
<Cross2Icon className="ml-2 h-4 w-4" /> | ||
</Button> | ||
)} | ||
</div> | ||
<DataTableViewOptions table={table} /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
export function useDebounce<T>(value: T, delay = 1000): T { | ||
const [debouncedValue, setDebouncedValue] = useState(value); | ||
|
||
useEffect(() => { | ||
const timeout = setTimeout(() => { | ||
setDebouncedValue(value); | ||
}, delay); | ||
|
||
return () => { | ||
clearTimeout(timeout); | ||
}; | ||
}, [value, delay]); | ||
|
||
return debouncedValue; | ||
} |