fix(ui): завершить локальную приёмку оптимизатора
This commit is contained in:
1 parent
5a23dfcfe6
commit
66fde3fc62
8 files changed
+41
-16
No files matched your search
@@ -221,7 +221,7 @@ function buildMockData(settings: OptimizerSettings): OptimizerData {
|
||||
function Chip({ children, color }: { children: React.ReactNode; color?: string }) {
|
||||
return (
|
||||
<span className={cn(
|
||||
"inline-flex items-center rounded px-1.5 py-0.5 text-[11px] font-medium border",
|
||||
"inline-flex shrink-0 whitespace-nowrap items-center rounded px-1.5 py-0.5 text-[11px] font-medium border",
|
||||
color ?? "bg-muted text-muted-foreground border-border",
|
||||
)}>{children}</span>
|
||||
)
|
||||
@@ -232,7 +232,7 @@ function ProbChip({ prob, best }: { prob: number; best?: boolean }) {
|
||||
<Chip color={best
|
||||
? "bg-success/10 text-success border-success/20"
|
||||
: "bg-muted text-muted-foreground border-border"
|
||||
}>{prob} б.</Chip>
|
||||
}><span className="sr-only">Индекс модели: </span>{prob} б.</Chip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ function ConfChip({ conf }: { conf: string }) {
|
||||
MEDIUM: "bg-warning/10 text-warning border-warning/20",
|
||||
LOW: "bg-destructive/10 text-destructive border-destructive/20",
|
||||
}
|
||||
return <Chip color={map[conf] ?? map.LOW}>{conf}</Chip>
|
||||
return <Chip color={map[conf] ?? map.LOW}><span className="sr-only">Категория модели: </span>{conf}</Chip>
|
||||
}
|
||||
|
||||
function NInput({ value, onChange, min, max, label, disabled }: { disabled?: boolean; label: string; value: number; onChange: (v: number) => void; min?: number; max?: number }) {
|
||||
@@ -289,21 +289,21 @@ function HomeRouterCard({ entry, jumpHosts, pinned, applied, applying, onPin, on
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-3 px-4 py-3 border-b flex-wrap">
|
||||
<MonitorIcon aria-hidden="true" className="size-4 text-muted-foreground shrink-0" />
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="min-w-0">
|
||||
<div className="flex items-center gap-2 flex-wrap min-w-0">
|
||||
<Flag code={home.country} />
|
||||
<span className="text-sm font-semibold font-mono">{home.label}</span>
|
||||
<span className="text-xs text-muted-foreground">{home.site}</span>
|
||||
<span className="text-[10px] text-muted-foreground border border-border rounded px-1.5 py-0.5 font-mono">{home.model}</span>
|
||||
<span className="text-sm font-semibold font-mono break-all">{home.label}</span>
|
||||
<span className="text-xs text-muted-foreground break-all">{home.site}</span>
|
||||
<span className="text-[10px] text-muted-foreground border border-border rounded px-1.5 py-0.5 font-mono break-all">{home.model}</span>
|
||||
</div>
|
||||
<div className="text-[11px] text-muted-foreground font-mono mt-0.5">
|
||||
<div className="text-[11px] text-muted-foreground font-mono mt-0.5 break-all">
|
||||
{home.wans.map(w => `${w.name} (${w.isp} · ${w.ip})`).join(" · ")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Best route summary */}
|
||||
{bestRoute && (
|
||||
<div className="flex items-center gap-1.5 ml-2 text-xs text-muted-foreground">
|
||||
<div className="flex items-center gap-1.5 ml-2 text-xs text-muted-foreground flex-wrap min-w-0 break-all">
|
||||
<span className="font-mono font-semibold text-info ">{bestRoute.wan.name}</span>
|
||||
<ArrowRightIcon aria-hidden="true" className="size-3" />
|
||||
<span>{bestRoute.jh.label}</span>
|
||||
@@ -312,7 +312,7 @@ function HomeRouterCard({ entry, jumpHosts, pinned, applied, applying, onPin, on
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<div className="ml-auto flex items-center gap-2 flex-wrap min-w-0 max-w-full">
|
||||
{switchCount > 0 && (
|
||||
<Chip color="bg-warning/10 text-warning border-warning/20">
|
||||
Рекомендаций: {switchCount}
|
||||
@@ -374,12 +374,12 @@ function TopologyBar() {
|
||||
<div className="flex items-center gap-3 text-xs text-muted-foreground flex-wrap">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<MonitorIcon aria-hidden="true" className="size-3.5" />
|
||||
<span>Home Router</span>
|
||||
<span>Схема: Home Router</span>
|
||||
</div>
|
||||
<span className="text-border">→</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<WifiIcon aria-hidden="true" className="size-3.5 text-info" />
|
||||
<span>WAN1 / WAN2</span>
|
||||
<span>WAN-аплинк</span>
|
||||
</div>
|
||||
<span className="text-border">→</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
|
||||
+2
-2
@@ -172,7 +172,7 @@ HTTP-фикстуры; локальная приёмка: 43 основных +
|
||||
|
||||
48 основных + 8 source E2E, backend recursive regression и production frontend прошли. HTTP-фикстуры; RouterOS/DB/JWT остаются внешней приёмкой. Далее оптимизатор по журналу.
|
||||
|
||||
## Оптимизатор — визуальная проверка 2026-09-30
|
||||
## Оптимизатор — локальная визуальная приёмка 2026-10-01
|
||||
|
||||
| Экран / референс | ПК | Телефон | Схема |
|
||||
| --- | --- | --- | --- |
|
||||
@@ -180,4 +180,4 @@ HTTP-фикстуры; локальная приёмка: 43 основных +
|
||||
| Настройки · [Settings 16](https://reui.io/preview/base/settings-16?ref=mcp) | [Снимок](ux-ui/screens/route-optimizer-settings-desktop.png) | [390 px](ux-ui/screens/route-optimizer-settings-mobile.png), [320 px](ux-ui/screens/route-optimizer-settings-narrow.png) | Пороги → вес → локальный пересчёт |
|
||||
| Community · [Data Grid Filtering 2](https://reui.io/preview/base/data-grid-filtering-2?ref=mcp) | [Снимок](ux-ui/screens/route-optimizer-community-desktop.png) | [390 px](ux-ui/screens/route-optimizer-community-mobile.png), [320 px](ux-ui/screens/route-optimizer-community-narrow.png) | Устройство → базовый расчёт → модельная рекомендация → закрепление |
|
||||
|
||||
35 E2E, TS/lint и production frontend прошли на HTTP-фикстурах. Это проверка layout; whole optimizer acceptance остаётся открытой по model provenance и URL/source-контексту. Точное продолжение — в журнале.
|
||||
47 основных + 8 source E2E, backend optimizer/live-maps, production frontend/backend прошли. Исходные значения отдельно от модели; Community apply недоступен, демо только симуляция. HTTP/DI фикстуры; реальный RouterOS/JWT/БД остаётся внешней приёмкой. Далее карта/терминал; ограничения и точное продолжение — в журнале.
|
||||
@@ -26,11 +26,19 @@
|
||||
| 7 | Серверы и мониторинг: детали, формы, URL-контекст, права | Завершён в границах локальной приёмки 2026-09-23; внешние ограничения ниже |
|
||||
| 8 | Трафик и статистика | Завершён 2026-09-28 в границах локальной приёмки; ограничения в блоке 8.13 |
|
||||
| 9 | VPN, Firewall и Filters | Завершён в границах локальной приёмки 2026-09-30; блоки 9.1–9.64, ограничения в 9.64 |
|
||||
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.43; единицы/Community scope исправлены, далее финальная локальная приёмка |
|
||||
| 10 | Маршрутизация, диагностика, карта и терминал | В работе: 10.1–10.44; оптимизатор принят локально, далее карта сети/терминал |
|
||||
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Не начат |
|
||||
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Не начат |
|
||||
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | Не начат |
|
||||
|
||||
## Блок 10.44 — локальная приёмка оптимизатора (2026-10-01)
|
||||
|
||||
- Схема расчёта использует общий WAN-аплинк, без утверждения о существующих WAN1/WAN2. Длинные имена/метаданные и badges переносятся; модельная категория/индекс имеют доступные подписи. Текст бейджей не сжимается/не переносится внутри них.
|
||||
- 46 основных E2E + отдельный новый long-name 320 px = 47 разных; 8 source E2E, backend optimizer suite/live-maps и обе production сборки прошли в блоках 10.39–10.44; TS/lint без новых ошибок (backend два прежних warning). ReUI checklist проверен, vendor/theme не менялись. Девять снимков обновлены и просмотрены в окончательной композиции; форма и keyboard/disabled поведение проверены на 1440/390/320 px.
|
||||
- Оптимизатор принят в локальных границах: Community live apply недоступен, demo receipt только симуляция; модельные chain/index/score явно отделены от измерений. Нет synthetic/mock WAN в live, чужих Community правил, неизвестных индексов как нулей. OSPF preview/apply full context/RBAC/receipt, optional observed контракт и Router ID ambiguity проверены на DI/HTTP фикстурах.
|
||||
- Ограничения: настоящие RouterOS/JWT/БД/физические пробы/сетевые изменения не тестировались; dynamic Router ID/отсутствующие flags требуют фактической проверки; timestamp скорости probe отсутствует; алгоритм ранжирования прежний. Home tabs/черновые ECMP/RPF/VRF не восстанавливаются из URL. Прежний intermittent readonly fixture teardown ECONNREFUSED не считать реальной интеграцией.
|
||||
- Следующий шаг: карта сети — согласованный snapshot servers/GRE/probes, сохранение last data, freshness/гонки/источник; затем Flow Map/DNS и unknown состояния графа. Терминал и этапы 11–12 ещё впереди.
|
||||
|
||||
## Блок 10.43 — смысл настроек и scope Community (2026-10-01)
|
||||
|
||||
- Порог выигрыша — баллы, не проценты; счётчик обозначает рекомендации, не выполненные переключения. Интервал обновляет расчёт, не запускает измерения. Неиспользуемый гистерезис недоступен и явно пояснён; значения сохранённых настроек совместимы.
|
||||
|
||||
@@ -224,3 +224,7 @@ Shared контракт и backend observed исходные значения/д
|
||||
## 10.43. Настройки/Community scope
|
||||
|
||||
Порог в баллах, обновление расчёта, инертный гистерезис недоступен; рекомендации только своего home. 4 unit, 10 E2E, TS/lint прошли. Девять снимков обновлены; header clipping ещё исправить перед acceptance.
|
||||
|
||||
## 10.44. Локальная приёмка оптимизатора
|
||||
|
||||
47 разных основных + 8 source E2E, backend optimizer/live-maps, production frontend/backend прошли; девять финальных снимков, ReUI audit/TS/lint. Исходные метрики отдельно от модели, full receipts/URL/source, без mock WAN/foreign Community. Внешние RouterOS/DB/JWT ограничения в журнале. Далее карта сети и терминал, этап 10 ещё открыт.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 161 KiB After Width: | Height: | Size: 161 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
@@ -27,3 +27,16 @@ for(const [device,width,height] of [["desktop",1440,1000],["mobile",390,844],["n
|
||||
await community.evaluate(element=>element.scrollIntoView({block:"start"}));
|
||||
await page.screenshot({path:"docs/ux-ui/screens/route-optimizer-community-"+device+".png",animations:"disabled"})
|
||||
})
|
||||
|
||||
test("Оптимизатор: длинное имя не обрезается на 320 px",async({page})=>{
|
||||
await page.setViewportSize({width:320,height:700})
|
||||
const name="Router"+"x".repeat(140)
|
||||
await page.route("**/health",r=>r.fulfill({json:{ok:true}}))
|
||||
await page.route("**/api/**",r=>{const p=new URL(r.request().url()).pathname;return r.fulfill({json:p==="/api/auth/config"?{required:false}:p==="/api/servers"?[{id:1,name,host:"192.0.2.1",type:"home-router",country:"RU",enabled:true,status:null}]:p==="/api/filters/rules"?{rulesets:[]}:p==="/api/uptime/speed-probes"?{probes:[]}:p==="/api/ospf/catalog"?{interfaces:[],instances:[],neighbors:[],bfdSessions:[],routes:[],failures:[]}:p.endsWith("/preview")?{serverId:1,serverName:name,pingWeight:60,interfacesTotal:0,changedCount:0,unchangedCount:0,interfaces:[],changes:[]}:{}})})
|
||||
await page.goto("/route-optimizer")
|
||||
const label=page.locator("span").filter({hasText:new RegExp("^"+name+"$")}).first()
|
||||
await expect(label).toBeVisible()
|
||||
const bounds=await label.boundingBox();expect(bounds).not.toBeNull();expect(bounds!.x+bounds!.width).toBeLessThanOrEqual(320)
|
||||
expect(await page.evaluate(()=>document.documentElement.scrollWidth<=innerWidth)).toBe(true)
|
||||
await expect(page.getByText("Нет WAN-аплинков для расчёта.",{exact:false})).toBeVisible()
|
||||
})
|
||||
Reference in new issue
Block a user