refactor: Consolidate density-related logic by moving densityRowClass and densityLabel to a dedicated data-table-density component, improving code organization and reusability across data table components
Build, Test, and Push CFDM Docker Image / test (push) Successful in 4m12s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Successful in 2m1s
Build, Test, and Push CFDM Docker Image / update-wiki (push) Successful in 6s
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped

This commit is contained in:
Denozordec
2026-06-25 17:27:39 +07:00
parent 4e536c3b7e
commit 063761539c
7 changed files with 68 additions and 56 deletions
@@ -0,0 +1,15 @@
export type Density = 'compact' | 'comfortable' | 'spacious'
export const densityRowClass: Record<Density, string> = {
compact: '[&_tr]:h-9 [&_tr_td]:py-1 [&_tr_th]:py-1 text-xs',
comfortable: '[&_tr]:h-10 [&_tr_td]:py-2 [&_tr_th]:py-2 text-sm',
spacious: '[&_tr]:h-12 [&_tr_td]:py-3 [&_tr_th]:py-3 text-sm',
}
export const densityLabel: Record<Density, string> = {
compact: 'Компактная',
comfortable: 'Обычная',
spacious: 'Просторная',
}
export const pageSizeOptions = [10, 20, 50] as const
+5 -19
View File
@@ -17,22 +17,11 @@ import {
DropdownMenuTrigger,
} from '@cfdm/ui/components/dropdown-menu'
import { AppButton } from '@/components/app-button'
type Density = 'compact' | 'comfortable' | 'spacious'
const densityRowClass: Record<Density, string> = {
compact: '[&_tr]:h-9 [&_tr_td]:py-1 [&_tr_th]:py-1 text-xs',
comfortable: '[&_tr]:h-10 [&_tr_td]:py-2 [&_tr_th]:py-2 text-sm',
spacious: '[&_tr]:h-12 [&_tr_td]:py-3 [&_tr_th]:py-3 text-sm',
}
const densityLabel: Record<Density, string> = {
compact: 'Компактная',
comfortable: 'Обычная',
spacious: 'Просторная',
}
const pageSizeOptions = [10, 20, 50] as const
import {
densityLabel,
pageSizeOptions,
type Density,
} from '@/components/data-table-density'
interface DataTableToolbarProps<TData> {
table: Table<TData>
@@ -137,6 +126,3 @@ export function DataTableToolbar<TData>({
</div>
)
}
export type { Density }
export { densityRowClass }
+2 -5
View File
@@ -17,11 +17,8 @@ import {
} from '@cfdm/ui/components/table'
import { cn } from '@cfdm/ui/lib/utils'
import { DataTablePagination } from '@/components/data-table-pagination'
import {
DataTableToolbar,
densityRowClass,
type Density,
} from '@/components/data-table-toolbar'
import { DataTableToolbar } from '@/components/data-table-toolbar'
import { densityRowClass, type Density } from '@/components/data-table-density'
interface DataTableViewProps<TData> {
table: TableType<TData>
@@ -16,7 +16,7 @@ import type { DomainListItem } from '@/lib/schemas'
import { AppBadge } from '@/components/app-badge'
import { AppButton } from '@/components/app-button'
import { DataTableView } from '@/components/data-table-view'
import type { Density } from '@/components/data-table-toolbar'
import type { Density } from '@/components/data-table-density'
import {
DropdownMenu,
DropdownMenuContent,
+43 -29
View File
@@ -1,3 +1,4 @@
import { useMemo, useState } from 'react'
import { ShieldCheckIcon } from 'lucide-react'
import type { Certificate } from '@/lib/schemas'
import { formatRelative } from '@/lib/format'
@@ -20,25 +21,43 @@ import {
import { ScrollArea } from '@cfdm/ui/components/scroll-area'
const WARN_DAYS = 14
const DAY_MS = 1000 * 60 * 60 * 24
interface ExpiringCertsCardProps {
certificates: Certificate[]
limit?: number
}
export function ExpiringCertsCard({ certificates, limit = 6 }: ExpiringCertsCardProps) {
const now = Date.now()
const upcoming = certificates
interface UpcomingEntry {
cert: Certificate
ts: number
expired: boolean
}
function selectUpcoming(
certificates: Certificate[],
limit: number,
now: number,
): UpcomingEntry[] {
return certificates
.filter((c) => c.expires_at)
.map((c) => ({ cert: c, ts: new Date(c.expires_at as string).getTime() }))
.map((c) => {
const ts = new Date(c.expires_at as string).getTime()
return { cert: c, ts, expired: ts < now }
})
.filter((entry) => Number.isNaN(entry.ts) === false)
.sort((a, b) => a.ts - b.ts)
.filter((entry) => {
const days = (entry.ts - now) / (1000 * 60 * 60 * 24)
return days <= WARN_DAYS
})
.filter((entry) => (entry.ts - now) / DAY_MS <= WARN_DAYS)
.slice(0, limit)
.map((entry) => entry.cert)
}
export function ExpiringCertsCard({ certificates, limit = 6 }: ExpiringCertsCardProps) {
const [now] = useState(() => Date.now())
const upcoming = useMemo(
() => selectUpcoming(certificates, limit, now),
[certificates, limit, now],
)
return (
<AppCard>
@@ -58,26 +77,21 @@ export function ExpiringCertsCard({ certificates, limit = 6 }: ExpiringCertsCard
) : (
<ScrollArea className="h-72">
<AppItemGroup className="gap-2 pr-3">
{upcoming.map((cert) => {
const expired = new Date(cert.expires_at as string).getTime() < now
return (
<AppItem key={cert.id} variant="outline" size="sm">
<AppItemContent className="flex flex-row items-center justify-between gap-3">
<div className="flex min-w-0 flex-col gap-0.5">
<AppItemTitle className="truncate font-medium">
{cert.hostname}
</AppItemTitle>
<AppItemDescription className="tabular-nums">
{formatRelative(cert.expires_at)}
</AppItemDescription>
</div>
<StatusBadge
status={expired ? 'expired' : cert.status}
/>
</AppItemContent>
</AppItem>
)
})}
{upcoming.map((entry) => (
<AppItem key={entry.cert.id} variant="outline" size="sm">
<AppItemContent className="flex flex-row items-center justify-between gap-3">
<div className="flex min-w-0 flex-col gap-0.5">
<AppItemTitle className="truncate font-medium">
{entry.cert.hostname}
</AppItemTitle>
<AppItemDescription className="tabular-nums">
{formatRelative(entry.cert.expires_at)}
</AppItemDescription>
</div>
<StatusBadge status={entry.expired ? 'expired' : entry.cert.status} />
</AppItemContent>
</AppItem>
))}
</AppItemGroup>
</ScrollArea>
)}
+1 -1
View File
@@ -12,7 +12,7 @@ import {
import { MoreHorizontalIcon } from 'lucide-react'
import { ConfirmDialog } from '@/components/confirm-dialog'
import { DataTableView } from '@/components/data-table-view'
import type { Density } from '@/components/data-table-toolbar'
import type { Density } from '@/components/data-table-density'
import type { SubdomainTableRow } from '@/hooks/use-domain-page'
import { formatSubdomainServiceLinks } from '@/hooks/use-domain-page'
import { formatDate } from '@/lib/format'
+1 -1
View File
@@ -24,7 +24,7 @@ import { EmptyState } from '@/components/empty-state'
import { StatusBadge } from '@/components/status-badge'
import { DataTableCard } from '@/components/data-table-card'
import { DataTableView } from '@/components/data-table-view'
import type { Density } from '@/components/data-table-toolbar'
import type { Density } from '@/components/data-table-density'
import { ChartCard } from '@/components/chart-card'
import { AppButton } from '@/components/app-button'
import {