feat(web): enhance debugging capabilities across components
Build, Test, and Push CFDM Docker Image / test (push) Failing after 46s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Has been skipped
Build, Test, and Push CFDM Docker Image / update-wiki (push) Has been skipped
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped

- Integrated debug logging in main application file to track boot process.
- Added layout width logging in PageShell and various ReUI components to monitor rendering dimensions.
- Implemented chart size logging in dashboard analytics components for better performance insights.
- Enhanced OpsDashboard and ResourcePage with width tracking to improve layout responsiveness.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-10 01:23:19 +07:00
co-authored by Cursor
parent 781c88175c
commit 9a87d0c82c
8 changed files with 192 additions and 11 deletions
@@ -1,4 +1,4 @@
import { useMemo } from 'react'
import { useMemo, useEffect, useRef } from 'react'
import { Bar, BarChart, CartesianGrid, Cell, Pie, PieChart, XAxis } from 'recharts'
import { StatusBadge } from '@/components/status-badge'
@@ -17,6 +17,34 @@ import {
} from '@cfdm/ui/components/chart'
import { Separator } from '@cfdm/ui/components/separator'
import { cn } from '@cfdm/ui/lib/utils'
import { debugAgentLog } from '@/lib/debug-agent-log'
function useChartSizeLog(chartId: string, dataLen: number) {
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
const el = ref.current
if (!el) return
const svg = el.querySelector('svg.recharts-surface')
const chartSlot = el.querySelector('[data-slot=chart]') as HTMLElement | null
debugAgentLog(
'dashboard-analytics.tsx:chart-mount',
'chart container dimensions',
{
chartId,
dataLen,
containerW: el.clientWidth,
containerH: el.clientHeight,
chartSlotW: chartSlot?.clientWidth ?? 0,
chartSlotH: chartSlot?.clientHeight ?? 0,
svgW: svg?.getAttribute('width') ?? null,
svgH: svg?.getAttribute('height') ?? null,
hasSvg: Boolean(svg),
},
'D',
)
}, [chartId, dataLen])
return ref
}
const statusChartConfig = {
count: { label: 'Сертификаты' },
@@ -45,6 +73,7 @@ interface CertStatusChartProps {
}
export function CertStatusChart({ data }: CertStatusChartProps) {
const chartRef = useChartSizeLog('cert-status', data.length)
const total = useMemo(
() => data.reduce((sum, entry) => sum + entry.count, 0),
[data],
@@ -60,7 +89,10 @@ export function CertStatusChart({ data }: CertStatusChartProps) {
{data.length === 0 ? (
<p className="text-muted-foreground text-sm">Нет данных о сертификатах</p>
) : (
<div className="grid w-full gap-6 @md:grid-cols-[9rem_minmax(0,1fr)] @md:items-center">
<div
ref={chartRef}
className="grid w-full gap-6 @md:grid-cols-[9rem_minmax(0,1fr)] @md:items-center"
>
<div className="relative mx-auto size-36 shrink-0">
<ChartContainer
config={statusChartConfig}
@@ -127,6 +159,8 @@ interface GroupDomainsChartProps {
}
export function GroupDomainsChart({ data }: GroupDomainsChartProps) {
const chartRef = useChartSizeLog('group-domains', data.length)
return (
<Frame dense spacing="sm" className="h-full w-full">
<FrameHeader>
@@ -137,7 +171,7 @@ export function GroupDomainsChart({ data }: GroupDomainsChartProps) {
{data.length === 0 ? (
<p className="text-muted-foreground text-sm">Нет групп с доменами</p>
) : (
<div className="flex w-full flex-col gap-4">
<div ref={chartRef} className="flex w-full flex-col gap-4">
<ChartContainer
config={groupChartConfig}
className="aspect-auto h-52 w-full min-h-52"
@@ -1,4 +1,4 @@
import type { ReactNode } from 'react'
import { useEffect, useRef, type ReactNode } from 'react'
import { Link } from '@tanstack/react-router'
import {
Frame,
@@ -8,6 +8,7 @@ import {
FrameTitle,
} from '@/components/reui/frame'
import { cn } from '@cfdm/ui/lib/utils'
import { debugAgentLog } from '@/lib/debug-agent-log'
import { Item, ItemMedia } from '@cfdm/ui/components/item'
export interface OpsKpiCard {
@@ -77,8 +78,28 @@ export function OpsDashboard({
charts,
queue,
}: OpsDashboardProps) {
const rootRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const el = rootRef.current
if (!el) return
debugAgentLog(
'ops-dashboard.tsx:mount',
'ops dashboard width',
{
clientWidth: el.clientWidth,
maxWidth: getComputedStyle(el).maxWidth,
className: el.className,
},
'A',
)
}, [])
return (
<div className="text-foreground @container mx-auto flex w-full max-w-7xl flex-col gap-4 md:gap-6">
<div
ref={rootRef}
className="text-foreground @container mx-auto flex w-full max-w-7xl flex-col gap-4 md:gap-6"
>
<header className="px-1">
<h1 className="text-xl font-semibold tracking-tight">{title}</h1>
<p className="text-muted-foreground max-w-2xl text-sm leading-relaxed">
@@ -1,4 +1,4 @@
import { useCallback, useMemo, useState, type ReactNode } from 'react'
import { useCallback, useMemo, useState, useEffect, useRef, type ReactNode } from 'react'
import {
getCoreRowModel,
getPaginationRowModel,
@@ -36,6 +36,7 @@ import { Tabs, TabsList, TabsTrigger } from '@cfdm/ui/components/tabs'
import { Alert, AlertDescription, AlertTitle } from '@cfdm/ui/components/alert'
import { EmptyState } from '@/components/empty-state'
import { applyFiltersToData } from './filter-utils'
import { debugAgentLog } from '@/lib/debug-agent-log'
export interface ResourcePageTab {
id: string
@@ -115,6 +116,7 @@ export function ResourcePage<T extends object>({
toolbarExtra,
hideHeader = false,
}: ResourcePageProps<T>) {
const frameRef = useRef<HTMLDivElement>(null)
const [internalTab, setInternalTab] = useState(tabs?.[0]?.id ?? 'all')
const activeTab = controlledTab ?? internalTab
@@ -225,7 +227,23 @@ export function ResourcePage<T extends object>({
const emptyMessage = 'Нет записей по выбранным фильтрам.'
useEffect(() => {
const el = frameRef.current
if (!el) return
debugAgentLog(
'resource-page.tsx:mount',
'resource page width',
{
title,
clientWidth: el.clientWidth,
maxWidth: getComputedStyle(el).maxWidth,
},
'A',
)
}, [title])
return (
<div ref={frameRef} className="w-full">
<DataGrid
table={table}
recordCount={filteredData.length}
@@ -339,5 +357,6 @@ export function ResourcePage<T extends object>({
</FramePanel>
</Frame>
</DataGrid>
</div>
)
}
@@ -1,10 +1,11 @@
import type { ReactNode } from 'react'
import { useEffect, useRef, type ReactNode } from 'react'
import { Link, Outlet, useRouterState } from '@tanstack/react-router'
import { SettingsIcon } from 'lucide-react'
import { useIsMobile } from '@cfdm/ui/hooks/use-mobile'
import { cn } from '@cfdm/ui/lib/utils'
import { PageShell } from '@/components/page-shell'
import { debugAgentLog } from '@/lib/debug-agent-log'
export interface SettingsTabConfig {
id: string
@@ -34,11 +35,28 @@ export function SettingsShell({
tabs = DEFAULT_TABS,
}: SettingsShellProps) {
const isMobile = useIsMobile()
const rootRef = useRef<HTMLDivElement>(null)
const pathname = useRouterState({ select: (s) => s.location.pathname })
useEffect(() => {
const el = rootRef.current
if (!el) return
debugAgentLog(
'settings-shell.tsx:mount',
'settings shell width',
{
pathname,
clientWidth: el.clientWidth,
maxWidth: getComputedStyle(el).maxWidth,
className: el.className,
},
'A',
)
}, [pathname])
return (
<PageShell>
<div className="mx-auto flex w-full max-w-4xl flex-col gap-6">
<div ref={rootRef} className="mx-auto flex w-full max-w-4xl flex-col gap-6">
<header className="px-1">
<h1 className="text-xl font-semibold tracking-tight">{title}</h1>
<p className="text-muted-foreground max-w-2xl text-sm leading-relaxed">