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.
4.2 kB ยท 155 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156"use client";
import type { RouterOutputs } from "@openstatus/api";import { detectWebhookFlavor } from "@openstatus/subscriptions/client";import { Badge } from "@openstatus/ui/components/ui/badge";import { Tooltip, TooltipContent, TooltipTrigger,} from "@openstatus/ui/components/ui/tooltip";import type { ColumnDef } from "@tanstack/react-table";
import { formatDate } from "@/lib/formatter";
import { DataTableRowActions } from "./data-table-row-actions";
type Subscriber = RouterOutputs["pageSubscriber"]["list"][number];
const FLAVOR_LABELS = { slack: "Slack", discord: "Discord", generic: "Webhook",} as const;
function detectFlavorBadge(url: string | null) { if (!url) return null; return FLAVOR_LABELS[detectWebhookFlavor(url)];}
export const columns: ColumnDef<Subscriber>[] = [ { id: "destination", header: "Destination", enableSorting: false, enableHiding: false, cell: ({ row }) => { const sub = row.original; const raw = sub.channelType === "email" ? sub.email : sub.webhookUrl; const display = sub.name ?? raw ?? ""; const flavor = sub.channelType === "webhook" ? detectFlavorBadge(sub.webhookUrl) : sub.channelType === "slack" ? "Slack" : null;
return ( <div className="flex items-center gap-2"> <span className="max-w-[280px] truncate">{display}</span> {flavor ? ( <Badge variant="outline" className="text-xs"> {flavor} </Badge> ) : null} </div> ); }, }, { id: "source", accessorFn: (row) => row.source, header: "Source", enableSorting: false, enableHiding: false, filterFn: (row, id, filterValue: string[]) => { if (!filterValue?.length) return true; return filterValue.includes(row.getValue(id) as string); }, cell: ({ row }) => { const source = row.original.source; const label = source === "vendor" ? "Vendor" : source === "import" ? "Import" : "Self-signup"; return ( <Badge variant="outline" className="text-xs"> {label} </Badge> ); }, }, { id: "components", header: "Components", enableSorting: false, enableHiding: false, cell: ({ row }) => { const { components, isEntirePage } = row.original; if (isEntirePage) { return ( <span className="text-muted-foreground text-xs">Entire page</span> ); } return ( <Tooltip> <TooltipTrigger asChild> <span className="text-xs">{components.length} components</span> </TooltipTrigger> <TooltipContent> {components.map((c) => c.name).join(", ")} </TooltipContent> </Tooltip> ); }, }, { id: "status", accessorFn: (row) => { if (row.unsubscribedAt) return "unsubscribed"; if (!row.acceptedAt) return "pending"; return "active"; }, header: "Status", enableSorting: false, enableHiding: false, filterFn: (row, id, filterValue: string[]) => { if (!filterValue?.length) return true; return filterValue.includes(row.getValue(id) as string); }, cell: ({ row }) => { const status = row.getValue("status") as string; if (status === "unsubscribed") { return <Badge variant="destructive">Unsubscribed</Badge>; } if (status === "pending") { return <Badge variant="outline">Pending</Badge>; } return <Badge variant="secondary">Active</Badge>; }, }, { accessorKey: "createdAt", header: "Created At", enableSorting: false, enableHiding: false, cell: ({ row }) => { const value = row.getValue("createdAt"); if (value instanceof Date) return formatDate(value); if (!value) return "-"; return value; }, meta: { cellClassName: "font-mono", }, }, { id: "actions", cell: ({ row }) => <DataTableRowActions row={row} />, meta: { cellClassName: "w-8", }, },];