Shyamnath's picture
Push UI dashboard and deployment files
c40c75a
import { Fragment, useEffect } from "react";
import {
ColumnDef,
flexRender,
getCoreRowModel,
getExpandedRowModel,
Row,
useReactTable,
} from "@tanstack/react-table";
import {
Table,
TableHead,
TableHeaderCell,
TableBody,
TableRow,
TableCell,
} from "@tremor/react";
interface DataTableProps<TData, TValue> {
data: TData[];
columns: ColumnDef<TData, TValue>[];
renderSubComponent: (props: { row: Row<TData> }) => React.ReactElement;
getRowCanExpand: (row: Row<TData>) => boolean;
isLoading?: boolean;
expandedRequestId?: string | null;
onRowExpand?: (requestId: string | null) => void;
setSelectedKeyIdInfoView?: (keyId: string | null) => void;
loadingMessage?: string;
noDataMessage?: string;
}
export function DataTable<TData extends { request_id: string }, TValue>({
data = [],
columns,
getRowCanExpand,
renderSubComponent,
isLoading = false,
expandedRequestId,
onRowExpand,
loadingMessage = "🚅 Loading logs...",
noDataMessage = "No logs found",
}: DataTableProps<TData, TValue>) {
const table = useReactTable({
data,
columns,
getRowCanExpand,
getCoreRowModel: getCoreRowModel(),
getExpandedRowModel: getExpandedRowModel(),
state: {
expanded: expandedRequestId
? data.reduce((acc, row, index) => {
if (row.request_id === expandedRequestId) {
acc[index] = true;
}
return acc;
}, {} as Record<string, boolean>)
: {},
},
onExpandedChange: (updater) => {
if (!onRowExpand) return;
// Get current expanded state
const currentExpanded = expandedRequestId
? data.reduce((acc, row, index) => {
if (row.request_id === expandedRequestId) {
acc[index] = true;
}
return acc;
}, {} as Record<string, boolean>)
: {};
// Calculate new expanded state
const newExpanded = typeof updater === 'function'
? updater(currentExpanded)
: updater;
// If empty, it means we're closing the expanded row
if (Object.keys(newExpanded).length === 0) {
onRowExpand(null);
return;
}
// Find the request_id of the expanded row
const expandedIndex = Object.keys(newExpanded)[0];
const expandedRow = expandedIndex !== undefined ? data[parseInt(expandedIndex)] : null;
// Call the onRowExpand callback with the request_id
onRowExpand(expandedRow ? expandedRow.request_id : null);
},
});
// No need for the useEffect here as we're handling everything in onExpandedChange
return (
<div className="rounded-lg custom-border">
<Table className="[&_td]:py-0.5 [&_th]:py-1">
<TableHead>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHeaderCell key={header.id} className="py-1 h-8">
{header.isPlaceholder ? null : (
flexRender(
header.column.columnDef.header,
header.getContext()
)
)}
</TableHeaderCell>
);
})}
</TableRow>
))}
</TableHead>
<TableBody>
{isLoading ?
<TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>{loadingMessage}</p>
</div>
</TableCell>
</TableRow>
: table.getRowModel().rows.length > 0 ?
table.getRowModel().rows.map((row) => (
<Fragment key={row.id}>
<TableRow className="h-8">
{row.getVisibleCells().map((cell) => (
<TableCell
key={cell.id}
className="py-0.5 max-h-8 overflow-hidden text-ellipsis whitespace-nowrap"
>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
{row.getIsExpanded() && (
<TableRow>
<TableCell colSpan={row.getVisibleCells().length}>
{renderSubComponent({ row })}
</TableCell>
</TableRow>
)}
</Fragment>
))
: <TableRow>
<TableCell colSpan={columns.length} className="h-8 text-center">
<div className="text-center text-gray-500">
<p>{noDataMessage}</p>
</div>
</TableCell>
</TableRow>
}
</TableBody>
</Table>
</div>
);
}