Openstatus www.openstatus.dev
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

๐Ÿง‘โ€๐ŸŽจ improve table (#885)

authored by

Thibault Le Ouay and committed by
GitHub
db12f7b2 7c4d7113

+140 -43
+65
apps/web/src/components/ping-response-analysis/columns.tsx
··· 1 + "use client"; 2 + 3 + import type { ColumnDef } from "@tanstack/react-table"; 4 + import { latencyFormatter, regionFormatter, type RegionChecker } from "./utils"; 5 + 6 + import { DataTableColumnHeader } from "../data-table/data-table-column-header"; 7 + import { StatusCodeBadge } from "../monitor/status-code-badge"; 8 + 9 + export const columns: ColumnDef<RegionChecker>[] = [ 10 + { 11 + accessorKey: "region", 12 + cell: ({ row }) => { 13 + return <div>{regionFormatter(row.original.region)}</div>; 14 + }, 15 + header: ({ column }) => { 16 + return <DataTableColumnHeader column={column} title="Region" />; 17 + }, 18 + }, 19 + { 20 + accessorKey: "status", 21 + header: "Status", 22 + cell: ({ row }) => { 23 + return <StatusCodeBadge statusCode={row.original.status} />; 24 + }, 25 + }, 26 + { 27 + id: "dns", 28 + header: ({ column }) => { 29 + return <DataTableColumnHeader column={column} title="DNS" />; 30 + }, 31 + accessorFn: (row) => `${row.timing.dnsDone - row.timing.dnsStart}`, 32 + }, 33 + { 34 + id: "connect", 35 + accessorFn: (row) => `${row.timing.connectDone - row.timing.connectStart}`, 36 + header: ({ column }) => { 37 + return <DataTableColumnHeader column={column} title="Connect" />; 38 + }, 39 + }, 40 + { 41 + id: "tls", 42 + accessorFn: (row) => 43 + `${row.timing.tlsHandshakeDone - row.timing.tlsHandshakeStart}`, 44 + header: ({ column }) => { 45 + return <DataTableColumnHeader column={column} title="TLS" />; 46 + }, 47 + }, 48 + { 49 + id: "ttfb", 50 + accessorFn: (row) => 51 + `${row.timing.firstByteDone - row.timing.firstByteStart}`, 52 + header: ({ column }) => { 53 + return <DataTableColumnHeader column={column} title="TTFB" />; 54 + }, 55 + }, 56 + { 57 + accessorKey: "latency", 58 + header: ({ column }) => { 59 + return <DataTableColumnHeader column={column} title="Latency" />; 60 + }, 61 + cell: ({ row }) => { 62 + return <div>{latencyFormatter(row.original.latency)}</div>; 63 + }, 64 + }, 65 + ];
+69 -38
apps/web/src/components/ping-response-analysis/multi-region-table.tsx
··· 1 + "use client"; 2 + 1 3 import { 2 4 Table, 3 5 TableBody, ··· 17 19 } from "./utils"; 18 20 import type { RegionChecker } from "./utils"; 19 21 22 + import { 23 + type ColumnDef, 24 + getCoreRowModel, 25 + useReactTable, 26 + flexRender, 27 + type SortingState, 28 + getSortedRowModel, 29 + } from "@tanstack/react-table"; 30 + import { useState } from "react"; 31 + 20 32 // TBD: add the popover infos about timing details 21 33 22 - export function MultiRegionTable({ regions }: { regions: RegionChecker[] }) { 34 + interface DataTableProps<TData, TValue> { 35 + columns: ColumnDef<TData, TValue>[]; 36 + data: TData[]; 37 + } 38 + 39 + export function MultiRegionTable<TData, TValue>({ 40 + columns, 41 + data, 42 + }: DataTableProps<TData, TValue>) { 43 + const [sorting, setSorting] = useState<SortingState>([]); 44 + 45 + const table = useReactTable({ 46 + data, 47 + columns, 48 + onSortingChange: setSorting, 49 + getCoreRowModel: getCoreRowModel(), 50 + getSortedRowModel: getSortedRowModel(), 51 + 52 + state: { 53 + sorting, 54 + }, 55 + }); 23 56 return ( 24 57 <Table> 25 58 <TableCaption>Multi Regions</TableCaption> 26 59 <TableHeader> 27 - <TableRow> 28 - <TableHead>Region</TableHead> 29 - <TableHead>Status</TableHead> 30 - <TableHead>DNS</TableHead> 31 - <TableHead>Connect</TableHead> 32 - <TableHead>TLS</TableHead> 33 - <TableHead>TTFB</TableHead> 34 - <TableHead>Total</TableHead> 35 - </TableRow> 60 + {table.getHeaderGroups().map((headerGroup) => ( 61 + <TableRow key={headerGroup.id}> 62 + {headerGroup.headers.map((header) => { 63 + return ( 64 + <TableHead key={header.id}> 65 + {header.isPlaceholder 66 + ? null 67 + : flexRender( 68 + header.column.columnDef.header, 69 + header.getContext() 70 + )} 71 + </TableHead> 72 + ); 73 + })} 74 + </TableRow> 75 + ))} 36 76 </TableHeader> 37 77 <TableBody> 38 - {regions.map(({ region, status, timing }) => { 39 - const { dns, connection, tls, ttfb } = getTimingPhases(timing); 40 - const total = getTotalLatency(timing); 41 - return ( 42 - <TableRow key={region}> 43 - <TableCell className="font-medium"> 44 - {regionFormatter(region)} 45 - </TableCell> 46 - <TableCell> 47 - <StatusCodeBadge statusCode={status} /> 48 - </TableCell> 49 - <TableCell className="text-muted-foreground"> 50 - <code>{latencyFormatter(dns)}</code> 51 - </TableCell> 52 - <TableCell className="text-muted-foreground"> 53 - <code>{latencyFormatter(connection)}</code> 54 - </TableCell> 55 - <TableCell className="text-muted-foreground"> 56 - <code>{latencyFormatter(tls)}</code> 57 - </TableCell> 58 - <TableCell className="text-muted-foreground"> 59 - <code>{latencyFormatter(ttfb)}</code> 60 - </TableCell> 61 - <TableCell> 62 - <code>{latencyFormatter(total)}</code> 63 - </TableCell> 78 + {table.getRowModel().rows?.length ? ( 79 + table.getRowModel().rows.map((row) => ( 80 + <TableRow 81 + key={row.id} 82 + data-state={row.getIsSelected() && "selected"} 83 + > 84 + {row.getVisibleCells().map((cell) => ( 85 + <TableCell key={cell.id}> 86 + {flexRender(cell.column.columnDef.cell, cell.getContext())} 87 + </TableCell> 88 + ))} 64 89 </TableRow> 65 - ); 66 - })} 90 + )) 91 + ) : ( 92 + <TableRow> 93 + <TableCell colSpan={columns.length} className="h-24 text-center"> 94 + No results. 95 + </TableCell> 96 + </TableRow> 97 + )} 67 98 </TableBody> 68 99 </Table> 69 100 );
+2 -1
apps/web/src/components/ping-response-analysis/multi-region-tabs.tsx
··· 3 3 import { MultiRegionChart } from "./multi-region-chart"; 4 4 import { MultiRegionTable } from "./multi-region-table"; 5 5 import type { RegionChecker } from "./utils"; 6 + import { columns } from "./columns"; 6 7 7 8 export function MultiRegionTabs({ regions }: { regions: RegionChecker[] }) { 8 9 return ( ··· 15 16 <MultiRegionChart regions={regions} /> 16 17 </TabsContent> 17 18 <TabsContent value="table"> 18 - <MultiRegionTable regions={regions} /> 19 + <MultiRegionTable data={regions} columns={columns} /> 19 20 </TabsContent> 20 21 </Tabs> 21 22 );
+4 -4
apps/web/src/components/ping-response-analysis/utils.ts
··· 15 15 16 16 export function regionFormatter( 17 17 region: MonitorFlyRegion, 18 - type: "short" | "long" = "short", 18 + type: "short" | "long" = "short" 19 19 ) { 20 20 const { code, flag, location } = flyRegionsDict[region]; 21 21 if (type === "short") return `${code} ${flag}`; ··· 118 118 method?: Method; 119 119 headers?: { value: string; key: string }[]; 120 120 body?: string; 121 - }, 121 + } 122 122 ): Promise<RegionChecker> { 123 123 // 124 124 const res = await fetch(`https://checker.openstatus.dev/ping/${region}`, { ··· 152 152 if (!data.success) { 153 153 console.log(json); 154 154 console.error( 155 - `something went wrong with result ${json} request to ${url} error ${data.error.message}`, 155 + `something went wrong with result ${json} request to ${url} error ${data.error.message}` 156 156 ); 157 157 throw new Error(data.error.message); 158 158 } ··· 169 169 flyRegions.map(async (region) => { 170 170 const check = await checkRegion(url, region, opts); 171 171 return check; 172 - }), 172 + }) 173 173 ); 174 174 } 175 175