diff --git a/UI_CHECKLIST.md b/UI_CHECKLIST.md index dad6b86..6f09b2d 100644 --- a/UI_CHECKLIST.md +++ b/UI_CHECKLIST.md @@ -31,7 +31,7 @@ - [x] Зафиксировать набор статусов и цветов. - [x] Определить основные пользовательские сценарии. - [x] Определить структуру навигации и маршруты страниц. -- [ ] Определить desktop и mobile макеты. +- [~] Определить desktop и mobile макеты. ## Этап 1. Каркас и объекты @@ -44,12 +44,12 @@ - [x] Добавить фильтр по статусу. - [x] Добавить фильтр по группе. - [x] Добавить фильтр по наличию проблем. -- [ ] Добавить сортировку колонок. +- [x] Добавить сортировку колонок. - [x] Открывать объект кликом по строке. - [~] Показывать массовые действия только после выбора объектов. - [~] Добавить loading, empty и error states таблицы. - [ ] Проверить таблицу на 1366 px и 1920 px. -- [ ] Сделать мобильное представление списка объектов. +- [x] Сделать мобильное представление списка объектов. ## Этап 2. Карточка и обзор объекта @@ -154,7 +154,7 @@ - [ ] Добавить skeleton loading. - [~] Добавить единый компонент пустого состояния. - [ ] Добавить единый компонент ошибки. -- [ ] Добавить toast-уведомления. +- [x] Добавить toast-уведомления. - [~] Добавить единые диалоги подтверждения. - [ ] Показывать request ID в раскрываемых деталях ошибки. - [ ] Добавить tooltips для непонятных иконок. diff --git a/web/app.js b/web/app.js index 400c139..930aaed 100644 --- a/web/app.js +++ b/web/app.js @@ -606,8 +606,14 @@ function renderDevices() { ${escapeHtml(deviceModel(device))} ${escapeHtml([device.group || "", ...(device.tags || [])].filter(Boolean).join(" / ") || "Без группы")} - ${escapeHtml(wan.label)} - ${clients.total} +
+ WAN + ${escapeHtml(wan.label)} +
+
+ Clients + ${clients.total} +
${device.active_alerts ? `${device.active_alerts} активн.` : "Нет"} diff --git a/web/index.html b/web/index.html index e985dce..7c3726f 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,7 @@ OpenWrt RMM - +
@@ -671,6 +671,6 @@
- + diff --git a/web/styles.css b/web/styles.css index 144c04a..d603644 100644 --- a/web/styles.css +++ b/web/styles.css @@ -1267,6 +1267,20 @@ select { gap: 4px; } +.device-field { + display: grid; + gap: 4px; + min-width: 0; +} + +.device-field-label { + display: none; + color: var(--muted); + font-size: 11px; + font-weight: 700; + text-transform: uppercase; +} + .device-identity strong, .device-identity small, .device-context span, @@ -1800,3 +1814,135 @@ select { grid-template-columns: 1fr; } } + +@media (max-width: 720px) { + .workspace { + padding: 0 14px 20px; + } + + .topbar { + min-height: auto; + padding: 14px 0; + } + + .topbar, + .topbar-actions { + align-items: flex-start; + flex-direction: column; + } + + .status-line { + order: 2; + } + + .fleet-summary, + .fleet-toolbar { + grid-template-columns: 1fr; + } + + .fleet-table-shell { + overflow: visible; + border: 0; + background: transparent; + } + + .fleet-table-head { + display: none; + } + + .device-list { + gap: 10px; + } + + .device-item { + grid-template-columns: 1fr 1fr; + gap: 10px 12px; + min-width: 0; + min-height: auto; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--surface); + padding: 12px; + } + + .device-item:hover { + border-color: var(--accent); + } + + .device-item > .fleet-status, + .device-item > .device-identity, + .device-item > .device-context { + grid-column: 1 / -1; + } + + .device-item > .problem-count, + .device-item > .last-contact, + .device-item > .device-field { + display: grid; + gap: 4px; + min-width: 0; + align-content: start; + } + + .device-item > .problem-count::before, + .device-item > .last-contact::before { + color: var(--muted); + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + } + + .device-item > .problem-count::before { + content: "Проблемы"; + } + + .device-item > .last-contact::before { + content: "Последний контакт"; + } + + .device-field-label { + display: block; + } + + .device-item > .device-field:nth-child(5) .device-field-label { + font-size: 0; + } + + .device-item > .device-field:nth-child(5) .device-field-label::after { + content: "Клиенты"; + font-size: 11px; + } + + .device-item strong, + .device-item small, + .device-item span, + .last-contact, + .wan-state { + white-space: normal; + } + + .row-chevron { + display: none; + } + + .device-header-actions { + display: grid; + grid-template-columns: 1fr; + width: 100%; + } + + .device-header-actions .badge, + .device-header-actions button { + width: 100%; + justify-content: center; + } + + .device-tabs { + margin: 0 -14px 18px; + padding: 0 14px; + } + + .panel { + padding: 12px; + } +}