import { flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, type ColumnDef, type PaginationState, type SortingState, } from '@tanstack/react-table' import { ChevronLeft, ChevronRight, RotateCcw, Search } from 'lucide-react' import { useEffect, useState, type ReactNode } from 'react' import { Badge, Button, Card, CardContent, CardFooter, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from 'ui' import { TimestampInfo } from 'ui-patterns' import { Input } from 'ui-patterns/DataInputs/Input' import { TanStackTableHeadSort } from 'ui-patterns/Table' import type { WebhookDelivery, WebhookEndpoint } from './PlatformWebhooks.types' import { statusBadgeVariant } from './PlatformWebhooksView.utils' import { getStatusLevel } from '@/components/interfaces/UnifiedLogs/UnifiedLogs.utils' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import { DataTableColumnStatusCode } from '@/components/ui/DataTable/DataTableColumn/DataTableColumnStatusCode' interface DetailItemProps { label: string children: ReactNode ddClassName?: string } const DetailItem = ({ label, children, ddClassName = 'text-sm' }: DetailItemProps) => (
{label}
{children}
) interface PlatformWebhooksEndpointDetailsProps { deliverySearch: string filteredDeliveries: WebhookDelivery[] selectedEndpoint: WebhookEndpoint onDeliverySearchChange: (value: string) => void onOpenDelivery: (deliveryId: string) => void onRetryDelivery: (deliveryId: string) => void } const DELIVERIES_PAGE_SIZE = 5 const DELIVERY_ACTIONS_COLUMN_ID = 'actions' const DEFAULT_DELIVERY_SORTING: SortingState = [{ id: 'attemptAt', desc: true }] const DELIVERY_COLUMNS: ColumnDef[] = [ { accessorKey: 'status', header: ({ column }) => Status, cell: ({ row }) => ( {row.original.status} ), }, { accessorKey: 'eventType', header: ({ column }) => ( Event type ), cell: ({ row }) => {row.original.eventType}, }, { accessorKey: 'responseCode', header: ({ column }) => Response, sortingFn: (rowA, rowB, columnId) => { const responseA = rowA.getValue(columnId) ?? -1 const responseB = rowB.getValue(columnId) ?? -1 return responseA - responseB }, cell: ({ row }) => row.original.responseCode != null ? ( ) : ( ), }, { accessorKey: 'attemptAt', header: ({ column }) => ( Attempted ), cell: ({ row }) => ( ), }, { id: DELIVERY_ACTIONS_COLUMN_ID, enableSorting: false, header: () => Actions, cell: ({ row, table }) => { const { onRetryDelivery } = table.options.meta as { onRetryDelivery: (deliveryId: string) => void } return (
{row.original.status !== 'success' ? ( } aria-label={`Retry ${row.original.id}`} tooltip={{ content: { side: 'top', text: 'Retry' } }} onClick={(event) => { event.stopPropagation() onRetryDelivery(row.original.id) }} onKeyDown={(event) => event.stopPropagation()} /> ) : (
) }, }, ] export const PlatformWebhooksEndpointDetails = ({ deliverySearch, filteredDeliveries, selectedEndpoint, onDeliverySearchChange, onOpenDelivery, onRetryDelivery, }: PlatformWebhooksEndpointDetailsProps) => { const hasCustomHeaders = selectedEndpoint.customHeaders.length > 0 const hasName = selectedEndpoint.name.trim().length > 0 const hasDescription = selectedEndpoint.description.trim().length > 0 const [sorting, setSorting] = useState(DEFAULT_DELIVERY_SORTING) const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: DELIVERIES_PAGE_SIZE, }) const table = useReactTable({ data: filteredDeliveries, columns: DELIVERY_COLUMNS, state: { pagination, sorting }, meta: { onRetryDelivery }, getRowId: (row) => row.id, onPaginationChange: setPagination, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), }) const paginatedDeliveries = table.getRowModel().rows const deliveryStartIndex = table.getState().pagination.pageIndex * table.getState().pagination.pageSize const deliveryRangeStart = filteredDeliveries.length === 0 ? 0 : deliveryStartIndex + 1 const deliveryRangeEnd = Math.min( deliveryStartIndex + table.getState().pagination.pageSize, filteredDeliveries.length ) useEffect(() => { setPagination((currentPagination) => ({ ...currentPagination, pageIndex: 0 })) }, [deliverySearch, selectedEndpoint.id]) return (

Overview

{hasName && {selectedEndpoint.name}} {selectedEndpoint.url} {hasDescription && ( {selectedEndpoint.description} )} {(selectedEndpoint.eventTypes.includes('*') ? ['All events (*)'] : selectedEndpoint.eventTypes ).map((eventType) => ( {eventType} ))} {hasCustomHeaders && (
{selectedEndpoint.customHeaders.map((header) => (
{header.key}: {header.value}
))}
)} {selectedEndpoint.createdBy}

Deliveries

} value={deliverySearch} className="w-full lg:w-52" onChange={(event) => onDeliverySearchChange(event.target.value)} />
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { const columnId = header.column.id const sort = header.column.getIsSorted() return ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ) })} ))} {paginatedDeliveries.length > 0 ? ( paginatedDeliveries.map((row) => ( onOpenDelivery(row.original.id)} onKeyDown={(event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault() onOpenDelivery(row.original.id) } }} tabIndex={0} > {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} )) ) : (

No deliveries found

Try adjusting your search to see more webhook attempts.

)}
{filteredDeliveries.length > 0 && (

Showing {deliveryRangeStart} to {deliveryRangeEnd} of {filteredDeliveries.length}{' '} deliveries

)}
) }