diff --git a/.cursor/debug-c10bcb.log b/.cursor/debug-c10bcb.log new file mode 100644 index 0000000..21c07cc --- /dev/null +++ b/.cursor/debug-c10bcb.log @@ -0,0 +1,11 @@ +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605101206} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605101204} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605138640} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605138642} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605143758} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605144457} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605145907} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605152669} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605152671} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605222064} +{"sessionId":"c10bcb","runId":"post-fix","hypothesisId":"H1","location":"badge-tabs.tsx:useEffect","message":"BadgeTabs layout metrics","data":{"flexDirection":"column","orientation":"horizontal","listLeft":280,"panelLeft":280,"stacked":true},"timestamp":1783605222067} diff --git a/apps/web/src/components/badge-tabs.tsx b/apps/web/src/components/badge-tabs.tsx index 208ef0e..cb0bbab 100644 --- a/apps/web/src/components/badge-tabs.tsx +++ b/apps/web/src/components/badge-tabs.tsx @@ -1,4 +1,5 @@ import type { ComponentProps, ReactNode } from 'react' +import { useEffect, useRef } from 'react' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@evobgp/ui/components/tabs' import { cn } from '@evobgp/ui/lib/utils' @@ -35,34 +36,67 @@ export function BadgeTabs({ listClassName, contentClassName, }: BadgeTabsProps) { + const tabsRef = useRef(null) + + useEffect(() => { + const el = tabsRef.current?.querySelector('[data-slot=tabs]') + if (!el || !(el instanceof HTMLElement)) return + const flexDirection = getComputedStyle(el).flexDirection + const listRect = el.querySelector('[data-slot=tabs-list]')?.getBoundingClientRect() + const panelRect = el.querySelector('[data-slot=tabs-content]')?.getBoundingClientRect() + // #region agent log + fetch('http://127.0.0.1:7311/ingest/6b35c3ae-1bcd-4c9c-81eb-f157c9347393', { + method: 'POST', + headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': 'c10bcb' }, + body: JSON.stringify({ + sessionId: 'c10bcb', + runId: 'post-fix', + hypothesisId: 'H1', + location: 'badge-tabs.tsx:useEffect', + message: 'BadgeTabs layout metrics', + data: { + flexDirection, + orientation: el.getAttribute('data-orientation'), + listLeft: listRect?.left, + panelLeft: panelRect?.left, + stacked: flexDirection === 'column', + }, + timestamp: Date.now(), + }), + }).catch(() => {}) + // #endregion + }, [value, defaultValue]) + return ( - - + - {items.map((item) => ( - - {item.icon} - {item.label} - {item.count !== undefined ? ( - - {item.count} - - ) : null} - - ))} - -
{children}
-
+ + {items.map((item) => ( + + {item.icon} + {item.label} + {item.count !== undefined ? ( + + {item.count} + + ) : null} + + ))} + +
{children}
+ + ) } diff --git a/apps/web/src/routes/_auth.tsx b/apps/web/src/routes/_auth.tsx index 4708472..91ab327 100644 --- a/apps/web/src/routes/_auth.tsx +++ b/apps/web/src/routes/_auth.tsx @@ -9,7 +9,7 @@ export const Route = createFileRoute('/_auth')({ const raw = typeof window !== 'undefined' ? window.localStorage.getItem(TOKEN_STORAGE_KEY) : null if (!raw || !normalizeApiToken(raw)) { - throw redirect({ to: '/settings' }) + throw redirect({ to: '/settings', search: { reason: 'token-required' } }) } }, component: AuthLayout, diff --git a/apps/web/src/routes/_auth/settings.tsx b/apps/web/src/routes/_auth/settings.tsx index 7c3470c..88c332c 100644 --- a/apps/web/src/routes/_auth/settings.tsx +++ b/apps/web/src/routes/_auth/settings.tsx @@ -1,7 +1,8 @@ -import { createFileRoute, useNavigate } from '@tanstack/react-router' +import { createFileRoute, useNavigate, useRouterState } from '@tanstack/react-router' import { useQuery, useQueryClient } from '@tanstack/react-query' import { Button } from '@evobgp/ui/components/button' +import { Alert, AlertDescription } from '@evobgp/ui/components/alert' import { PanelCard } from '@/components/panel-card' import { Input } from '@evobgp/ui/components/input' import { Label } from '@evobgp/ui/components/label' @@ -28,6 +29,9 @@ const THEME_SELECT_ITEMS = [ function SettingsComponent() { const navigate = useNavigate() + const tokenRequired = useRouterState({ + select: (s) => new URLSearchParams(s.location.search).get('reason') === 'token-required', + }) const qc = useQueryClient() const { data: session, isError: sessionError, error: sessionQueryError } = useQuery({ ...authSessionQueryOptions(), @@ -69,6 +73,14 @@ function SettingsComponent() { description="Параметры интерфейса и подключения браузера к API." /> + {tokenRequired ? ( + + + Для доступа к разделу нужен API-токен. Сохраните токен ниже или нажмите «Использовать dev». + + + ) : null} +