fix(ui): отличать неизвестный RTT от отсутствия ответов Ping
This commit is contained in:
1 parent
30cc99c68e
commit
9680a6422b
6 files changed
+55
-10
No files matched your search
@@ -2279,7 +2279,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
|
|||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
width: viewAfterBtPing.rttMs == null
|
width: viewAfterBtPing.rttMs == null
|
||||||
? "100%"
|
? "0%"
|
||||||
: `${Math.max(Math.min((viewAfterBtPing.rttMs / 120) * 100, 100), 4)}%`,
|
: `${Math.max(Math.min((viewAfterBtPing.rttMs / 120) * 100, 100), 4)}%`,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -2290,7 +2290,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
|
|||||||
? "text-amber-600 dark:text-amber-400"
|
? "text-amber-600 dark:text-amber-400"
|
||||||
: "text-violet-600 dark:text-violet-400",
|
: "text-violet-600 dark:text-violet-400",
|
||||||
)}>
|
)}>
|
||||||
{viewAfterBtPing.rttMs == null ? "timeout" : `${viewAfterBtPing.rttMs} мс`}
|
{viewAfterBtPing.rttMs == null ? (viewAfterBtPing.lossPct === 100 ? "Нет ответов" : "RTT неизвестен") : `${viewAfterBtPing.rttMs} мс`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -2581,7 +2581,7 @@ function UptimePageContent({ selectedProbeId, allProbesHref }: { selectedProbeId
|
|||||||
</span>
|
</span>
|
||||||
) : linkedSp.lastPingAt ? (
|
) : linkedSp.lastPingAt ? (
|
||||||
<span className="text-[10px] text-amber-600 dark:text-amber-400 truncate">
|
<span className="text-[10px] text-amber-600 dark:text-amber-400 truncate">
|
||||||
ping timeout
|
{linkedSp.lastPingLossPct === 100 ? "ping: нет ответов" : "ping: RTT неизвестен"}
|
||||||
{linkedSp.lastPingLossPct != null && <span> · {linkedSp.lastPingLossPct}%</span>}
|
{linkedSp.lastPingLossPct != null && <span> · {linkedSp.lastPingLossPct}%</span>}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -191,7 +191,8 @@ function UptimeSpeedHistoryDataGrid({ runs, servers }: UptimeSpeedHistoryDataGri
|
|||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const run = row.original
|
const run = row.original
|
||||||
if (run.status !== "done") return <span className="text-xs">—</span>
|
if (run.status !== "done") return <span className="text-xs">—</span>
|
||||||
if (run.afterBtPing?.error) {
|
if (!run.afterBtPing) return <span className="text-xs text-muted-foreground">Нет данных</span>
|
||||||
|
if (run.afterBtPing.error) {
|
||||||
return (
|
return (
|
||||||
<span className="text-[var(--status-offline-fg)] text-xs font-mono" title={run.afterBtPing.error}>
|
<span className="text-[var(--status-offline-fg)] text-xs font-mono" title={run.afterBtPing.error}>
|
||||||
ошибка
|
ошибка
|
||||||
@@ -210,7 +211,7 @@ function UptimeSpeedHistoryDataGrid({ runs, servers }: UptimeSpeedHistoryDataGri
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<span className="font-mono tabular-nums whitespace-nowrap text-xs text-amber-600 dark:text-amber-400">
|
<span className="font-mono tabular-nums whitespace-nowrap text-xs text-amber-600 dark:text-amber-400">
|
||||||
timeout
|
{run.afterBtPing.lossPct === 100 ? "Нет ответов" : "RTT неизвестен"}
|
||||||
{run.afterBtPing?.lossPct != null && <span> · {run.afterBtPing.lossPct}%</span>}
|
{run.afterBtPing?.lossPct != null && <span> · {run.afterBtPing.lossPct}%</span>}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
# План реализации UX/UI по пятичасовым окнам
|
# План реализации UX/UI по пятичасовым окнам
|
||||||
|
|
||||||
Актуальное продолжение 2026-10-07: 12.3.82 завершён: server createdAt в POST receipt, отсутствие Ping не получает дату и старый результат; 76browser,4pure,HTTP/RBAC,types/lint и builds прошли. Следующий12.3.83: неизвестный RTT не считать timeout. Общие main1176/context221 относятся к прежним HEAD. Внешняя12.5 не выполнена.
|
Актуальное продолжение 2026-10-07: 12.3.83 завершён: missing/unknown/loss100/zero/error Ping разделены;81browser,types/lint и frontend build прошли. Следующий12.4.10: общая main регрессия на новом HEAD после speed API/UI delta, затем12.4.11 context. Внешняя12.5 не выполнена.
|
||||||
|
|
||||||
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
|
Общий план проекта MikrotikManager. Основан на согласованном плане из задачи; точка продолжения обновлена 2026-10-07. Источник фактического прогресса, проверок и ограничений — [журнал реализации](ux-ui-progress.md). Этот документ задаёт объём и критерии завершения, журнал фиксирует результат.
|
||||||
|
|
||||||
## Актуальная точка продолжения — 2026-10-07
|
## Актуальная точка продолжения — 2026-10-07
|
||||||
|
|
||||||
Этапы0–11 завершены в описанных локальных границах. Этап12 продолжается; блоки до12.3.82 отражены в журнале. Общие main12.4.8 на579e816:1176/1176 и context12.4.9 наa3fcba0:221/221 passed. Последующие изменения speed-test проверены профильными тестами; эти общие прогоны не относятся к новому HEAD. Внешняя12.5 и реальные интеграции не приняты. Точные результаты и ограничения: [ux-ui-stage-12.md](ux-ui-stage-12.md).
|
Этапы0–11 завершены в описанных локальных границах. Этап12 продолжается; блоки до12.3.83 отражены в журнале. Общие main12.4.8 на579e816:1176/1176 и context12.4.9 наa3fcba0:221/221 passed. Последующие изменения speed-test проверены профильными тестами; эти общие прогоны не относятся к новому HEAD. Внешняя12.5 и реальные интеграции не приняты. Точные результаты и ограничения: [ux-ui-stage-12.md](ux-ui-stage-12.md).
|
||||||
|
|
||||||
Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md).
|
Реальные pg_dump/pg_restore, PG rollback и остановка UDP worker требуют внешней приёмки. Датированные продолжения ниже — история; точный следующий шаг также указан в начале [журнала](ux-ui-progress.md).
|
||||||
|
|
||||||
|
|||||||
+10
-2
@@ -1,6 +1,6 @@
|
|||||||
# UX/UI: журнал реализации
|
# UX/UI: журнал реализации
|
||||||
|
|
||||||
Актуальное продолжение 2026-10-07: 12.3.82 завершён: server createdAt в POST receipt, отсутствие Ping не получает дату и старый результат; 76browser,4pure,HTTP/RBAC,types/lint и builds прошли. Следующий12.3.83: неизвестный RTT не считать timeout. Общие main1176/context221 относятся к прежним HEAD. Внешняя12.5 не выполнена.
|
Актуальное продолжение 2026-10-07: 12.3.83 завершён: missing/unknown/loss100/zero/error Ping разделены;81browser,types/lint и frontend build прошли. Следующий12.4.10: общая main регрессия на новом HEAD после speed API/UI delta, затем12.4.11 context. Внешняя12.5 не выполнена.
|
||||||
|
|
||||||
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
|
Общий план: [UX/UI по этапам и пятичасовым окнам](ux-ui-plan.md). План задаёт объём, этот журнал фиксирует выполненные блоки и ограничения. Записи расположены от новых к старым; подробная история этапа12 также сохранена в [ux-ui-stage-12.md](ux-ui-stage-12.md).
|
||||||
|
|
||||||
@@ -32,7 +32,15 @@
|
|||||||
| 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 |
|
| 10 | Маршрутизация, диагностика, карта и терминал | Завершён в границах локальной приёмки 2026-10-01; блоки 10.1–10.71, внешние ограничения в 10.71 |
|
||||||
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 |
|
| 11А | Пользователи, контейнеры, сертификаты и резервные копии | Завершён в границах локальной приёмки 2026-10-01; 11А.1–11А.33, внешние ограничения в 11А.33 |
|
||||||
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
|
| 11Б | Оповещения, сбор данных, интеграции, релизы и настройки | Завершён в границах локальной приёмки 2026-10-03; ограничения и evidence в11Б.7 |
|
||||||
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | В работе. Локальные блоки до12.3.82 завершены. Общая main1176/1176 на579e816 и context221/221 наa3fcba0 прошли; последующий функциональный delta проверен73browser/8context. Следующий12.3.83; внешняя12.5 не выполнена. |
|
| 12 | Итоговая доступность, адаптивность, производительность и регрессия | В работе. Локальные блоки до12.3.83 завершены. Общая main1176/1176 на579e816 и context221/221 наa3fcba0 прошли; последующий функциональный delta проверен73browser/8context. Следующий12.4.10; внешняя12.5 не выполнена. |
|
||||||
|
|
||||||
|
## 12.3.83 — неизвестный RTT и отсутствие ответов Ping (2026-10-07)
|
||||||
|
|
||||||
|
История показывает «Нет данных» без afterBtPing, «RTT неизвестен» при null RTT и неопределённых/частичных потерях, «Нет ответов» при подтверждённых100% потерь. Ошибка и измеренный0 остаются отдельными состояниями. Карточка speed-пробы и связанная Ping-проба используют те же смыслы. Для null RTT шкала не заполнена как измерение. ReUI Data Grid/Frame и сетевые команды сохранены.
|
||||||
|
|
||||||
|
81/81 browser uptime/large history passed, включая5 новых состояний missing/unknown/loss100/zero/error в истории и карточке, отсутствие старого99 и reflow320px. Targeted ESLint0errors/0warnings, non-incremental TypeScript и contracts/frontend production build прошли. Для простой подписи не добавлены повторяющие реализацию unit tests. Исторические3 PNG восстановлены. Backend/native parsing не изменены; реальные native loss/status требуют12.5.
|
||||||
|
|
||||||
|
Следующий12.4.10: общая main матрица на новом HEAD после блоков79–83; затем12.4.11context. Предыдущие main1176(579e816)/context221(a3fcba0) сохраняются как отдельные результаты, не доказательство нового HEAD. Внешняя12.5 остаётся открытой.
|
||||||
|
|
||||||
## 12.3.82 — серверное время результата и отсутствующий Ping (2026-10-07)
|
## 12.3.82 — серверное время результата и отсутствующий Ping (2026-10-07)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Этап 12: итоговая приёмка UX/UI
|
# Этап 12: итоговая приёмка UX/UI
|
||||||
|
|
||||||
Актуальное продолжение 2026-10-07: 12.3.82 завершён: server createdAt в POST receipt, отсутствие Ping не получает дату и старый результат; 76browser,4pure,HTTP/RBAC,types/lint и builds прошли. Следующий12.3.83: неизвестный RTT не считать timeout. Общие main1176/context221 относятся к прежним HEAD. Внешняя12.5 не выполнена.
|
Актуальное продолжение 2026-10-07: 12.3.83 завершён: missing/unknown/loss100/zero/error Ping разделены;81browser,types/lint и frontend build прошли. Следующий12.4.10: общая main регрессия на новом HEAD после speed API/UI delta, затем12.4.11 context. Внешняя12.5 не выполнена.
|
||||||
|
|
||||||
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
|
План: [ux-ui-plan.md](ux-ui-plan.md). Фактические результаты: [ux-ui-progress.md](ux-ui-progress.md). Подготовлен после сводных проверок 11Б; завершение каждого блока требует локального коммита без push.
|
||||||
|
|
||||||
@@ -928,3 +928,11 @@ Backend возвращает createdAt из того же pingNow, которы
|
|||||||
Без afterBtPing новая операция не получает lastPingAt; выбор нового done run не подставляет прежний Ping snapshot. Явный0 сохранён. 4 pure receipt проверки, HTTP/RBAC с server timestamp passthrough, types/lint и contracts/backend/frontend builds прошли. Финальный76/76 browser прошёл. Первый прогон остановлен после ошибки нового селектора: в selected-probe scope кнопка называется «Обновить данные»; исправлены только новые тесты, отдельно2/2 и затем полный76/76 passed. Проверены дата из сервера в таблице, старый99 не наложен, отсутствующий Ping и новый0. Исторические3 PNG восстановлены.
|
Без afterBtPing новая операция не получает lastPingAt; выбор нового done run не подставляет прежний Ping snapshot. Явный0 сохранён. 4 pure receipt проверки, HTTP/RBAC с server timestamp passthrough, types/lint и contracts/backend/frontend builds прошли. Финальный76/76 browser прошёл. Первый прогон остановлен после ошибки нового селектора: в selected-probe scope кнопка называется «Обновить данные»; исправлены только новые тесты, отдельно2/2 и затем полный76/76 passed. Проверены дата из сервера в таблице, старый99 не наложен, отсутствующий Ping и новый0. Исторические3 PNG восстановлены.
|
||||||
|
|
||||||
Проверка согласованности журналов до этого блока:104 одинаковых numbered records в обоих документах, все с датами, без пропусков/дублей. Следующий12.3.83: таблица и карточки пока выводят timeout при любом null RTT; неизвестный/отсутствующий результат должен быть отделён от подтверждённого отсутствия ответов. Внешняя12.5 открыта; общий main/context не объявлен проверкой нового HEAD.
|
Проверка согласованности журналов до этого блока:104 одинаковых numbered records в обоих документах, все с датами, без пропусков/дублей. Следующий12.3.83: таблица и карточки пока выводят timeout при любом null RTT; неизвестный/отсутствующий результат должен быть отделён от подтверждённого отсутствия ответов. Внешняя12.5 открыта; общий main/context не объявлен проверкой нового HEAD.
|
||||||
|
|
||||||
|
## 12.3.83 — неизвестный RTT и отсутствие ответов Ping (2026-10-07)
|
||||||
|
|
||||||
|
История показывает «Нет данных» без afterBtPing, «RTT неизвестен» при null RTT и неопределённых/частичных потерях, «Нет ответов» при подтверждённых100% потерь. Ошибка и измеренный0 остаются отдельными состояниями. Карточка speed-пробы и связанная Ping-проба используют те же смыслы. Для null RTT шкала не заполнена как измерение. ReUI Data Grid/Frame и сетевые команды сохранены.
|
||||||
|
|
||||||
|
81/81 browser uptime/large history passed, включая5 новых состояний missing/unknown/loss100/zero/error в истории и карточке, отсутствие старого99 и reflow320px. Targeted ESLint0errors/0warnings, non-incremental TypeScript и contracts/frontend production build прошли. Для простой подписи не добавлены повторяющие реализацию unit tests. Исторические3 PNG восстановлены. Backend/native parsing не изменены; реальные native loss/status требуют12.5.
|
||||||
|
|
||||||
|
Следующий12.4.10: общая main матрица на новом HEAD после блоков79–83; затем12.4.11context. Предыдущие main1176(579e816)/context221(a3fcba0) сохраняются как отдельные результаты, не доказательство нового HEAD. Внешняя12.5 остаётся открытой.
|
||||||
@@ -54,3 +54,31 @@ test("Speed-пробы: malformed каталог, cache/freshness и блоки
|
|||||||
await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:"docs/ux-ui/screens/speed-probes-error-320.png",fullPage:true,animations:"disabled"})
|
await page.addStyleTag({content:"nextjs-portal{display:none!important}"});await page.screenshot({path:"docs/ux-ui/screens/speed-probes-error-320.png",fullPage:true,animations:"disabled"})
|
||||||
raw={probes:[probe]};await refresh.click();await expect(alert).toHaveCount(0);await expect(toggle).toBeEnabled();expect(writes).toEqual([])
|
raw={probes:[probe]};await refresh.click();await expect(alert).toHaveCount(0);await expect(toggle).toBeEnabled();expect(writes).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const pingCases = [
|
||||||
|
{ name: "missing", value: undefined, label: "Нет данных" },
|
||||||
|
{ name: "unknown", value: { rttMs: null, lossPct: null, error: null }, label: "RTT неизвестен" },
|
||||||
|
{ name: "loss100", value: { rttMs: null, lossPct: 100, error: null }, label: "Нет ответов" },
|
||||||
|
{ name: "zero", value: { rttMs: 0, lossPct: 0, error: null }, label: "0 мс" },
|
||||||
|
{ name: "error", value: { rttMs: null, lossPct: null, error: "Ошибка Ping" }, label: "ошибка" },
|
||||||
|
]
|
||||||
|
for (const sample of pingCases) test("Ping после BT: данные, неизвестный RTT, отсутствие ответов и ошибка/" + sample.name, async ({ page }) => {
|
||||||
|
await page.route("**/health", route => route.fulfill({ json: { ok: true } }))
|
||||||
|
await page.route("**/api/**", route => {
|
||||||
|
const path = new URL(route.request().url()).pathname
|
||||||
|
return route.fulfill({ json: path === "/api/auth/config" ? { required: false } : path === "/api/servers" ? [server] : path === "/api/uptime/overview" ? { probes: [], resources: [] } : path === "/api/uptime/speed-probes" ? { probes: [{ id: "probe-1", srcServerId: "1", dstServerId: "2", srcInterface: "ether1", dstInterface: "ether1", protocol: "tcp", direction: "both", durationSec: "10", enabled: true, lastStatus: "done", lastRunAt: "2026-10-03T00:00:00Z", lastTxAvgMbps: 999, lastRxAvgMbps: 0, lastError: null, lastPingRttMs: 99, lastPingLossPct: 0, lastPingAt: "2026-10-03T00:00:00Z", lastPingError: null }] } : path === "/api/uptime/speed-test/runs" ? { runs: [{ ...run, afterBtPing: sample.value }] } : {} })
|
||||||
|
})
|
||||||
|
await page.goto("/uptime?tab=speed")
|
||||||
|
await page.getByRole("button", { name: "Пауза", exact: true }).click()
|
||||||
|
const history = page.locator('tr[data-row-id="history-1"]')
|
||||||
|
await expect(history).toContainText(sample.label)
|
||||||
|
const probe = page.getByRole("button", { name: "Запустить", exact: true }).locator("xpath=../../..")
|
||||||
|
await expect(probe).not.toContainText("99 мс")
|
||||||
|
if (sample.name === "missing") await expect(probe.getByText("Ping", { exact: true })).toHaveCount(0)
|
||||||
|
else await expect(probe).toContainText(sample.name === "error" ? "Ошибка Ping" : sample.label)
|
||||||
|
await expect(history).not.toContainText("timeout")
|
||||||
|
await expect(probe).not.toContainText("timeout")
|
||||||
|
if (sample.name === "loss100") await expect(history).toContainText("100%")
|
||||||
|
await page.setViewportSize({ width: 320, height: 1000 })
|
||||||
|
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
|
||||||
|
})
|
||||||
Reference in new issue
Block a user