track requesters for builds releases deployments and migrations
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -6,6 +6,7 @@ export type DataTableColumn<T> = {
|
||||
key: string;
|
||||
header: string;
|
||||
className?: string;
|
||||
width?: number;
|
||||
cell: (row: T) => ReactNode;
|
||||
};
|
||||
|
||||
@@ -16,6 +17,25 @@ export type DataTableFilter<T> = {
|
||||
getValue: (row: T) => string;
|
||||
};
|
||||
|
||||
const spacingWidthPattern = /\bw-(?:\[(\d+)px\]|(\d+))\b/;
|
||||
const widthClassPattern = /\bw-(?:\[[^\]]+\]|\d+)\b/g;
|
||||
|
||||
function getColumnWidth<T>(column: DataTableColumn<T>) {
|
||||
if (column.key === 'no') return 75;
|
||||
if (column.width) return column.width;
|
||||
|
||||
const widthMatch = column.className?.match(spacingWidthPattern);
|
||||
if (widthMatch?.[1]) return Number(widthMatch[1]);
|
||||
if (widthMatch?.[2]) return Number(widthMatch[2]) * 4;
|
||||
if (column.key === 'actions') return 80;
|
||||
|
||||
return 160;
|
||||
}
|
||||
|
||||
function stripWidthClass(className?: string) {
|
||||
return className?.replace(widthClassPattern, '').replace(/\s+/g, ' ').trim();
|
||||
}
|
||||
|
||||
export function DataTableCard<T>({
|
||||
title,
|
||||
description,
|
||||
@@ -66,6 +86,7 @@ export function DataTableCard<T>({
|
||||
const totalPages = Math.max(1, Math.ceil(filteredRows.length / pageSize));
|
||||
const currentPage = Math.min(page, totalPages);
|
||||
const pageRows = filteredRows.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
||||
const flexibleColumnIndex = columns[0]?.key === 'no' && columns.length > 1 ? 1 : -1;
|
||||
|
||||
const updateFilter = (key: string, value: string) => {
|
||||
setFilterValues((prev) => ({ ...prev, [key]: value }));
|
||||
@@ -116,11 +137,36 @@ export function DataTableCard<T>({
|
||||
</div>
|
||||
</div>
|
||||
<div className="max-h-[560px] overflow-x-auto overflow-y-auto">
|
||||
<table className="w-full text-left text-sm" style={{ minWidth }}>
|
||||
<table className="w-full table-fixed text-left text-sm" style={{ minWidth }}>
|
||||
<colgroup>
|
||||
{columns.map((column, columnIndex) => (
|
||||
<col
|
||||
key={column.key}
|
||||
style={
|
||||
columnIndex === flexibleColumnIndex
|
||||
? { width: '100%' }
|
||||
: { width: getColumnWidth(column) }
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</colgroup>
|
||||
<thead className="sticky top-0 z-10 border-b border-border bg-card text-xs text-muted-foreground">
|
||||
<tr>
|
||||
{columns.map((column) => (
|
||||
<th key={column.key} className={column.className ?? 'px-5 py-3 font-medium'}>
|
||||
{columns.map((column, columnIndex) => (
|
||||
<th
|
||||
key={column.key}
|
||||
className={
|
||||
column.key === 'no'
|
||||
? 'py-3 text-center font-medium'
|
||||
: columnIndex === flexibleColumnIndex
|
||||
? stripWidthClass(column.className) || 'px-5 py-3 font-medium'
|
||||
: column.className ?? 'px-5 py-3 font-medium'
|
||||
}
|
||||
style={{
|
||||
...(column.key === 'no' ? { boxSizing: 'border-box', width: 75, minWidth: 75, maxWidth: 75, paddingLeft: 0, paddingRight: 0 } : columnIndex === flexibleColumnIndex ? { width: '100%' } : { width: getColumnWidth(column) }),
|
||||
...(columnIndex === flexibleColumnIndex ? { paddingLeft: 12 } : {}),
|
||||
}}
|
||||
>
|
||||
{column.header}
|
||||
</th>
|
||||
))}
|
||||
@@ -129,9 +175,25 @@ export function DataTableCard<T>({
|
||||
<tbody className="divide-y divide-border">
|
||||
{!loading && pageRows.map((row) => (
|
||||
<tr key={getRowKey(row)} className="hover:bg-muted/20">
|
||||
{columns.map((column) => (
|
||||
<td key={column.key} className="px-5 py-3">
|
||||
{column.cell(row)}
|
||||
{columns.map((column, columnIndex) => (
|
||||
<td
|
||||
key={column.key}
|
||||
className={column.key === 'no' ? 'py-3 text-center font-medium' : columns[0]?.key === 'no' && columnIndex === 1 ? 'py-3 pl-3 pr-5' : 'px-5 py-3'}
|
||||
style={
|
||||
column.key === 'no'
|
||||
? { boxSizing: 'border-box', width: 75, minWidth: 75, maxWidth: 75, paddingLeft: 0, paddingRight: 0 }
|
||||
: columnIndex === flexibleColumnIndex
|
||||
? { width: '100%' }
|
||||
: { width: getColumnWidth(column) }
|
||||
}
|
||||
>
|
||||
{column.key === 'no' ? (
|
||||
<span className="block w-full text-center font-semibold">
|
||||
{String((row as { no?: unknown }).no ?? '')}
|
||||
</span>
|
||||
) : (
|
||||
column.cell(row)
|
||||
)}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user