Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
5.4 kB ยท 184 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185"use client";
import type { RouterOutputs } from "@openstatus/api";import { type PageComponentImpact, worstImpact,} from "@openstatus/db/src/schema/page_components/constants";import { ChevronDown, ChevronUp } from "@openstatus/icons";import { Button } from "@openstatus/ui/components/ui/button";import { cn } from "@openstatus/ui/lib/utils";import type { ColumnDef } from "@tanstack/react-table";import Link from "next/link";
import { TableCellBadge } from "@/components/data-table/table-cell-badge";import { TableCellDate } from "@/components/data-table/table-cell-date";import { TableCellLink } from "@/components/data-table/table-cell-link";import { TableCellNumber } from "@/components/data-table/table-cell-number";import { DataTableColumnHeader } from "@/components/ui/data-table/data-table-column-header";import { colors, impactConfig, untriagedImpact,} from "@/data/status-report-updates.client";
import { DataTableRowActions } from "./data-table-row-actions";
type StatusReport = RouterOutputs["statusReport"]["list"][number];
// derived top-level impact = worst impact set by any update, not the// current one (a resolved report would always read "Operational");// legacy reports (no impact rows) read "Untriaged"function worstReportImpact(report: StatusReport) { const impacts = report.updates.flatMap((u) => u.componentImpacts.map((ci) => ci.impact), ); if (impacts.length === 0) return null; return worstImpact(impacts);}
export const columns: ColumnDef<StatusReport>[] = [ { id: "expander", header: () => null, cell: ({ row }) => { return row.getCanExpand() ? ( <Button {...{ className: "size-7 shadow-none text-muted-foreground", onClick: (e) => { e.stopPropagation(); row.toggleExpanded(); }, "aria-expanded": row.getIsExpanded(), "aria-label": row.getIsExpanded() ? `Collapse details for ${row.original.title}` : `Expand details for ${row.original.title}`, size: "icon", variant: "ghost", }} > {row.getIsExpanded() ? ( <ChevronUp className="opacity-60" size={16} aria-hidden="true" /> ) : ( <ChevronDown className="opacity-60" size={16} aria-hidden="true" /> )} </Button> ) : undefined; }, meta: { headerClassName: "w-7", }, }, { accessorKey: "title", header: "Title", cell: ({ row }) => { const { id, pageId } = row.original;
return ( <TableCellLink href={`/status-pages/${pageId}/status-reports/${id}`} onClick={(e) => { // avoid expanding the row e.stopPropagation(); }} value={row.getValue("title")} /> ); }, enableSorting: false, enableHiding: false, meta: { cellClassName: "max-w-[200px] truncate", }, }, { accessorKey: "status", header: "Current Status", cell: ({ row }) => { const value = String(row.getValue("status")); return ( <div className={cn( "font-mono capitalize", colors[value as keyof typeof colors], )} > {value} </div> ); }, enableSorting: false, enableHiding: false, }, { id: "impact", accessorFn: (row) => worstReportImpact(row), header: "Impact", cell: ({ row }) => { const impact = row.getValue<PageComponentImpact | null>("impact"); const config = impact ? impactConfig[impact] : untriagedImpact; return ( <div className={cn("max-w-[120px] truncate font-mono", config.color)}> {config.label} </div> ); }, enableSorting: false, }, { id: "updates", accessorFn: (row) => row.updates.length, header: "Updates", cell: ({ row }) => { const value = row.getValue("updates"); return <TableCellNumber value={value} />; }, }, { id: "pageComponents", accessorFn: (row) => row?.pageComponents, header: "Affected", cell: ({ row }) => { const value = row.getValue("pageComponents"); if (Array.isArray(value) && value.length > 0 && "name" in value[0]) { return ( <div className="flex flex-wrap gap-1"> {value.map((m) => m.monitorId ? ( <Link href={`/monitors/${m.monitorId}/overview`} key={m.id}> <TableCellBadge value={m.name} /> </Link> ) : ( <TableCellBadge value={m.name} key={m.id} /> ), )} </div> ); } return <div className="text-muted-foreground">-</div>; }, }, { id: "startedAt", accessorFn: (row) => row.updates.sort((a, b) => a.date.getTime() - b.date.getTime())[0] ?.date ?? row.createdAt, header: ({ column }) => ( <DataTableColumnHeader column={column} title="Started At" /> ), cell: ({ row }) => <TableCellDate value={row.getValue("startedAt")} />, enableHiding: false, meta: { cellClassName: "w-[170px]", }, }, { id: "actions", cell: ({ row }) => <DataTableRowActions row={row} />, meta: { cellClassName: "w-8", }, },];