diff --git a/UI_CHECKLIST.md b/UI_CHECKLIST.md
index f0166cf..eb4ce82 100644
--- a/UI_CHECKLIST.md
+++ b/UI_CHECKLIST.md
@@ -114,13 +114,13 @@
## Этап 5. Сведения
-- [ ] Показать модель, плату и версию OpenWrt.
-- [ ] Показать hostname и идентификатор устройства.
-- [ ] Показать группу и теги.
-- [ ] Добавить редактирование группы и тегов.
-- [ ] Показать даты регистрации и последнего контакта.
+- [x] Показать модель, плату и версию OpenWrt.
+- [x] Показать hostname и идентификатор устройства.
+- [x] Показать группу и теги.
+- [x] Добавить редактирование группы и тегов.
+- [x] Показать даты регистрации и последнего контакта.
- [ ] Показать версию агента, когда она будет доступна.
-- [ ] Добавить копирование технических идентификаторов.
+- [x] Добавить копирование технических идентификаторов.
## Этап 5. Экспертный режим
@@ -132,7 +132,7 @@
- [ ] Сократить основные фильтры истории до «Все», «Выполняются», «Ошибка».
- [ ] Перенести дополнительные фильтры в меню.
- [x] Перенести аудит.
-- [ ] Добавить предупреждение перед опасными действиями.
+- [x] Добавить предупреждение перед опасными действиями.
- [ ] Подготовить экспертный режим к разграничению прав.
## Убираем и объединяем
diff --git a/web/app.js b/web/app.js
index d72973a..1d6aa5d 100644
--- a/web/app.js
+++ b/web/app.js
@@ -43,6 +43,18 @@ const els = {
deviceName: document.querySelector("#deviceName"),
deviceMeta: document.querySelector("#deviceMeta"),
deviceBadge: document.querySelector("#deviceBadge"),
+ informationStatus: document.querySelector("#informationStatus"),
+ infoHostname: document.querySelector("#infoHostname"),
+ infoModel: document.querySelector("#infoModel"),
+ infoOpenWrt: document.querySelector("#infoOpenWrt"),
+ infoTarget: document.querySelector("#infoTarget"),
+ infoSystem: document.querySelector("#infoSystem"),
+ infoKernel: document.querySelector("#infoKernel"),
+ infoCreatedAt: document.querySelector("#infoCreatedAt"),
+ infoLastSeenAt: document.querySelector("#infoLastSeenAt"),
+ infoDeviceId: document.querySelector("#infoDeviceId"),
+ infoBoardName: document.querySelector("#infoBoardName"),
+ infoRootfs: document.querySelector("#infoRootfs"),
healthSummary: document.querySelector("#healthSummary"),
lastSeen: document.querySelector("#lastSeen"),
loadAvg: document.querySelector("#loadAvg"),
@@ -424,11 +436,30 @@ function renderDeviceDetail(device) {
els.fleetGroup.value = device.group || "";
els.fleetTags.value = Array.isArray(device.tags) ? device.tags.join(", ") : "";
els.inventoryJson.textContent = JSON.stringify(device.inventory || {}, null, 2);
+ renderDeviceInformation(device);
renderHealthSummary(device);
renderClients(device);
renderInterfaceCounters(device);
}
+function renderDeviceInformation(device) {
+ const board = device.inventory && device.inventory.board ? device.inventory.board : {};
+ const release = board.release || {};
+ els.informationStatus.textContent = device.online ? "На связи" : "Не на связи";
+ els.informationStatus.className = `badge ${device.online ? "online" : "offline"}`;
+ els.infoHostname.textContent = deviceDisplayName(device);
+ els.infoModel.textContent = board.model || "-";
+ els.infoOpenWrt.textContent = release.description || device.openwrt_version || "-";
+ els.infoTarget.textContent = release.target || "-";
+ els.infoSystem.textContent = board.system || "-";
+ els.infoKernel.textContent = board.kernel || "-";
+ els.infoCreatedAt.textContent = formatDate(device.created_at);
+ els.infoLastSeenAt.textContent = formatDate(device.last_seen_at);
+ els.infoDeviceId.textContent = device.id || "-";
+ els.infoBoardName.textContent = board.board_name || "-";
+ els.infoRootfs.textContent = board.rootfs_type || "-";
+}
+
function formatMemory(memory) {
if (!memory || !memory.total_kb) return "-";
return `${kbToMb(memory.used_kb)} / ${kbToMb(memory.total_kb)} MB`;
@@ -1224,6 +1255,15 @@ els.copyCommandOutputBtn.addEventListener("click", async () => {
setStatus("Output copied");
});
+for (const button of document.querySelectorAll(".copy-info-btn")) {
+ button.addEventListener("click", async () => {
+ const source = document.querySelector(`#${button.dataset.copyInfo}`);
+ if (!source) return;
+ await navigator.clipboard.writeText(source.textContent);
+ setStatus("Значение скопировано");
+ });
+}
+
for (const button of document.querySelectorAll(".preset-btn")) {
button.addEventListener("click", () => {
sendPresetCommand(button.dataset.preset, button.dataset.action).catch((error) => setStatus(error.message));
diff --git a/web/index.html b/web/index.html
index 6f9765a..c6ed061 100644
--- a/web/index.html
+++ b/web/index.html
@@ -4,7 +4,7 @@
OpenWrt RMM
-
+
@@ -173,23 +173,95 @@
+
+
+
+
+
+
Технические реквизиты
+
Используются при диагностике и обращении в поддержку
+
+
+
+
+ ID устройства
+ -
+
+
+
+ Board name
+ -
+
+
+
+ Root filesystem
+ -
+
+
+
+
Последний контакт
@@ -229,6 +301,13 @@
+
+
+ Экспертный режим
+ Здесь находятся низкоуровневые команды и настройки OpenWrt. Ошибочное изменение может нарушить связь с роутером.
+
+
+