From 9a87d0c82cb6215504d1866f2208152b2e744cf0 Mon Sep 17 00:00:00 2001 From: Denozordec Date: Fri, 10 Jul 2026 01:23:19 +0700 Subject: [PATCH] feat(web): enhance debugging capabilities across components - 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 --- apps/web/src/components/page-shell.tsx | 39 +++++++++++++++++- .../reui-kit/dashboard-analytics.tsx | 40 +++++++++++++++++-- .../src/components/reui-kit/ops-dashboard.tsx | 25 +++++++++++- .../src/components/reui-kit/resource-page.tsx | 21 +++++++++- .../components/reui-kit/settings-shell.tsx | 22 +++++++++- apps/web/src/lib/debug-agent-log.ts | 28 +++++++++++++ apps/web/src/main.tsx | 6 +++ apps/web/src/routes/_auth/index.tsx | 22 +++++++++- 8 files changed, 192 insertions(+), 11 deletions(-) create mode 100644 apps/web/src/lib/debug-agent-log.ts diff --git a/apps/web/src/components/page-shell.tsx b/apps/web/src/components/page-shell.tsx index da746c7..0824993 100644 --- a/apps/web/src/components/page-shell.tsx +++ b/apps/web/src/components/page-shell.tsx @@ -1,5 +1,7 @@ -import type { ReactNode } from 'react' +import { useEffect, useRef, type ReactNode } from 'react' +import { useRouterState } from '@tanstack/react-router' import { cn } from '@cfdm/ui/lib/utils' +import { DEBUG_BUILD_STAMP, debugAgentLog } from '@/lib/debug-agent-log' interface PageShellProps { children: ReactNode @@ -7,5 +9,38 @@ interface PageShellProps { } export function PageShell({ children, className }: PageShellProps) { - return
{children}
+ const ref = useRef(null) + const pathname = useRouterState({ select: (s) => s.location.pathname }) + + useEffect(() => { + const el = ref.current + if (!el) return + const main = el.closest('main') + const mainWidth = main?.clientWidth ?? 0 + const shellWidth = el.clientWidth + const child = el.firstElementChild as HTMLElement | null + const childWidth = child?.clientWidth ?? 0 + const childMaxWidth = child ? getComputedStyle(child).maxWidth : 'none' + debugAgentLog( + 'page-shell.tsx:mount', + 'page layout widths', + { + buildStamp: DEBUG_BUILD_STAMP, + pathname, + mainWidth, + shellWidth, + childWidth, + childMaxWidth, + shellClass: el.className, + childClass: child?.className ?? null, + }, + 'A', + ) + }, [pathname]) + + return ( +
+ {children} +
+ ) } diff --git a/apps/web/src/components/reui-kit/dashboard-analytics.tsx b/apps/web/src/components/reui-kit/dashboard-analytics.tsx index c6f5cc2..4fb0d12 100644 --- a/apps/web/src/components/reui-kit/dashboard-analytics.tsx +++ b/apps/web/src/components/reui-kit/dashboard-analytics.tsx @@ -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(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 ? (

Нет данных о сертификатах

) : ( -
+
@@ -137,7 +171,7 @@ export function GroupDomainsChart({ data }: GroupDomainsChartProps) { {data.length === 0 ? (

Нет групп с доменами

) : ( -
+
(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 ( -
+

{title}

diff --git a/apps/web/src/components/reui-kit/resource-page.tsx b/apps/web/src/components/reui-kit/resource-page.tsx index 50dc86d..776e1bc 100644 --- a/apps/web/src/components/reui-kit/resource-page.tsx +++ b/apps/web/src/components/reui-kit/resource-page.tsx @@ -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({ toolbarExtra, hideHeader = false, }: ResourcePageProps) { + const frameRef = useRef(null) const [internalTab, setInternalTab] = useState(tabs?.[0]?.id ?? 'all') const activeTab = controlledTab ?? internalTab @@ -225,7 +227,23 @@ export function ResourcePage({ 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 ( +

({ +
) } diff --git a/apps/web/src/components/reui-kit/settings-shell.tsx b/apps/web/src/components/reui-kit/settings-shell.tsx index 86b0bab..0257d6a 100644 --- a/apps/web/src/components/reui-kit/settings-shell.tsx +++ b/apps/web/src/components/reui-kit/settings-shell.tsx @@ -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(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 ( -
+

{title}

diff --git a/apps/web/src/lib/debug-agent-log.ts b/apps/web/src/lib/debug-agent-log.ts new file mode 100644 index 0000000..04b1c2a --- /dev/null +++ b/apps/web/src/lib/debug-agent-log.ts @@ -0,0 +1,28 @@ +/** Debug session 943716 — remove after layout/chart investigation */ +export const DEBUG_BUILD_STAMP = 'layout-charts-v1' + +export function debugAgentLog( + location: string, + message: string, + data: Record, + hypothesisId: string, +) { + // #region agent log + fetch('http://127.0.0.1:7580/ingest/5c1b60ca-3f59-41ce-8435-d25bcc12c3cf', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Debug-Session-Id': '943716', + }, + body: JSON.stringify({ + sessionId: '943716', + location, + message, + data, + hypothesisId, + timestamp: Date.now(), + runId: 'pre-fix', + }), + }).catch(() => {}) + // #endregion +} diff --git a/apps/web/src/main.tsx b/apps/web/src/main.tsx index a6d17d0..8c4307e 100644 --- a/apps/web/src/main.tsx +++ b/apps/web/src/main.tsx @@ -8,6 +8,12 @@ import { Toaster } from '@cfdm/ui/components/sonner' import { routeTree } from './routeTree.gen' import { queryClient } from './lib/queryClient' import '@cfdm/ui/globals.css' +import { DEBUG_BUILD_STAMP, debugAgentLog } from '@/lib/debug-agent-log' + +debugAgentLog('main.tsx:boot', 'app boot', { + buildStamp: DEBUG_BUILD_STAMP, + href: typeof window !== 'undefined' ? window.location.href : '', +}, 'B') const router = createRouter({ routeTree, diff --git a/apps/web/src/routes/_auth/index.tsx b/apps/web/src/routes/_auth/index.tsx index 773e13d..4416772 100644 --- a/apps/web/src/routes/_auth/index.tsx +++ b/apps/web/src/routes/_auth/index.tsx @@ -1,6 +1,6 @@ import { createFileRoute, Link } from '@tanstack/react-router' import { useQuery } from '@tanstack/react-query' -import { useMemo, useState } from 'react' +import { useMemo, useState, useEffect } from 'react' import { AlertTriangleIcon, FolderTreeIcon, @@ -30,6 +30,7 @@ import { ItemTitle, } from '@cfdm/ui/components/item' import { formatRelative } from '@/lib/format' +import { DEBUG_BUILD_STAMP, debugAgentLog } from '@/lib/debug-agent-log' export const Route = createFileRoute('/_auth/')({ loader: ({ context: { queryClient } }) => @@ -109,6 +110,25 @@ function DashboardPage() { const certWarnings = countByStatus(summary, ['warning', 'expired', 'error']) const certOk = countByStatus(summary, ['active', 'ok']) + useEffect(() => { + if (isLoading) return + debugAgentLog( + 'index.tsx:dashboard-data', + 'dashboard chart inputs', + { + buildStamp: DEBUG_BUILD_STAMP, + summaryRaw: summary ?? null, + statusChartLen: statusChartData.length, + statusChartData, + groupChartLen: groupChartData.length, + groupChartData, + domainsLen: domains?.length ?? 0, + groupsLen: groups?.length ?? 0, + }, + 'C', + ) + }, [isLoading, summary, statusChartData, groupChartData, domains, groups]) + const kpiCards = [ { id: 'domains',