ui: restore ⟳/✕ actions in edit mode only; shrink toggles; uniform 22px rows
The camera table actions column is back as the 9th column but stays empty in the normal view — restart (⟳) and delete (✕) buttons render only on existing cameras while bulk-editing. Restart in bulk mode no longer reloads the table (keeps pending edits); delete reloads as before. Row height is now truly uniform: cams-fixed cells use line-height:1 with vertically-centred controls, the Вкл/Запись toggles shrink to 30×16, and selects/inputs/action buttons cap at 20px so filled rows match empty slots. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,7 +47,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<table class="cams cams-fixed">
|
<table class="cams cams-fixed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th style="width:48px">ID</th><th>Камера</th><th>IP</th><th>Потоки</th><th style="width:56px">Вкл</th><th style="width:64px">Запись</th><th style="width:150px">Хранилище</th><th data-bulk-label="Логин / пароль">Статус</th></tr>
|
<tr><th style="width:48px">ID</th><th>Камера</th><th>IP</th><th>Потоки</th><th style="width:56px">Вкл</th><th style="width:64px">Запись</th><th style="width:150px">Хранилище</th><th data-bulk-label="Логин / пароль">Статус</th><th style="width:62px"></th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="cam-rows"></tbody>
|
<tbody id="cam-rows"></tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
+17
-4
@@ -1257,6 +1257,12 @@ const CamSettings = {
|
|||||||
`<td class="cell-dual">` +
|
`<td class="cell-dual">` +
|
||||||
`<input class="cell-in" type="text" data-f="user" value="${user}" title="Логин">` +
|
`<input class="cell-in" type="text" data-f="user" value="${user}" title="Логин">` +
|
||||||
`<input class="cell-in" type="password" data-f="password" value="${password}" title="Пароль" placeholder="пароль">` +
|
`<input class="cell-in" type="password" data-f="password" value="${password}" title="Пароль" placeholder="пароль">` +
|
||||||
|
`</td>` +
|
||||||
|
`<td class="actions">` +
|
||||||
|
(cam
|
||||||
|
? `<button data-act="restart" data-id="${cam.id}" title="Перезапустить камеру">⟳</button> ` +
|
||||||
|
`<button data-act="delete" data-id="${cam.id}" title="Удалить камеру (записи архива сохранятся)">✕</button>`
|
||||||
|
: "") +
|
||||||
`</td>`
|
`</td>`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -1328,7 +1334,7 @@ const CamSettings = {
|
|||||||
const v = (x) => this.esc(x);
|
const v = (x) => this.esc(x);
|
||||||
const isEdit = !!cam;
|
const isEdit = !!cam;
|
||||||
return (
|
return (
|
||||||
`<td colspan="8" class="cam-edit">` +
|
`<td colspan="9" class="cam-edit">` +
|
||||||
`<div class="cam-edit-grid">` +
|
`<div class="cam-edit-grid">` +
|
||||||
`<label>ID<input type="text" id="e-id" value="${cam ? v(cam.id) : ""}" ${isEdit ? "disabled" : ""} placeholder="cam${slotNo}"></label>` +
|
`<label>ID<input type="text" id="e-id" value="${cam ? v(cam.id) : ""}" ${isEdit ? "disabled" : ""} placeholder="cam${slotNo}"></label>` +
|
||||||
`<label>Имя<input type="text" id="e-name" value="${cam ? v(cam.name) : ""}" placeholder="Камера ${slotNo}"></label>` +
|
`<label>Имя<input type="text" id="e-name" value="${cam ? v(cam.name) : ""}" placeholder="Камера ${slotNo}"></label>` +
|
||||||
@@ -1444,7 +1450,8 @@ const CamSettings = {
|
|||||||
`<td><input type="checkbox" class="en-toggle" data-id="${c.id}" title="Камера включена (выкл — не работает совсем)" ${c.enabled ? "checked" : ""}></td>` +
|
`<td><input type="checkbox" class="en-toggle" data-id="${c.id}" title="Камера включена (выкл — не работает совсем)" ${c.enabled ? "checked" : ""}></td>` +
|
||||||
`<td><input type="checkbox" class="rec-toggle" data-id="${c.id}" title="Запись на диск (выкл — только просмотр)" ${c.record ? "checked" : ""} ${c.enabled ? "" : "disabled"}></td>` +
|
`<td><input type="checkbox" class="rec-toggle" data-id="${c.id}" title="Запись на диск (выкл — только просмотр)" ${c.record ? "checked" : ""} ${c.enabled ? "" : "disabled"}></td>` +
|
||||||
`<td><select class="stor-sel" data-id="${c.id}" title="В какое хранилище писать">${this.storageOptions(c.storage_id)}</select></td>` +
|
`<td><select class="stor-sel" data-id="${c.id}" title="В какое хранилище писать">${this.storageOptions(c.storage_id)}</select></td>` +
|
||||||
`<td>${statusCell}</td>`;
|
`<td>${statusCell}</td>` +
|
||||||
|
`<td class="actions"></td>`;
|
||||||
tb.appendChild(tr);
|
tb.appendChild(tr);
|
||||||
} else {
|
} else {
|
||||||
tr.className = "slot-empty";
|
tr.className = "slot-empty";
|
||||||
@@ -1452,7 +1459,8 @@ const CamSettings = {
|
|||||||
tr.innerHTML =
|
tr.innerHTML =
|
||||||
`<td class="muted">${i + 1}</td>` +
|
`<td class="muted">${i + 1}</td>` +
|
||||||
`<td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td>` +
|
`<td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td><td class="muted">—</td>` +
|
||||||
`<td class="muted">пусто</td>`;
|
`<td class="muted">пусто</td>` +
|
||||||
|
`<td></td>`;
|
||||||
tb.appendChild(tr);
|
tb.appendChild(tr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1473,9 +1481,14 @@ const CamSettings = {
|
|||||||
} else if (act === "delete") {
|
} else if (act === "delete") {
|
||||||
this.remove(id, this.byId[id] ? this.byId[id].name : id);
|
this.remove(id, this.byId[id] ? this.byId[id].name : id);
|
||||||
} else if (act === "restart") {
|
} else if (act === "restart") {
|
||||||
btn.disabled = true; btn.textContent = "…";
|
const prev = btn.textContent; btn.disabled = true; btn.textContent = "…";
|
||||||
await post(`/api/cameras/${id}/restart`);
|
await post(`/api/cameras/${id}/restart`);
|
||||||
|
if (this.bulk) { // в массовом режиме строки не перерисовываем (правки не теряем)
|
||||||
|
btn.textContent = "✓";
|
||||||
|
setTimeout(() => { btn.textContent = prev; btn.disabled = false; }, 1500);
|
||||||
|
} else {
|
||||||
setTimeout(() => this.load(), 1500);
|
setTimeout(() => this.load(), 1500);
|
||||||
|
}
|
||||||
} else if (act === "log") {
|
} else if (act === "log") {
|
||||||
const box = document.getElementById("log-" + id);
|
const box = document.getElementById("log-" + id);
|
||||||
if (!box.hidden) { box.hidden = true; return; }
|
if (!box.hidden) { box.hidden = true; return; }
|
||||||
|
|||||||
@@ -425,9 +425,25 @@ table.cams th, table.cams td {
|
|||||||
table.cams th { color: var(--text-dim); font-weight: 500; font-size: 11px; padding: 4px 10px; }
|
table.cams th { color: var(--text-dim); font-weight: 500; font-size: 11px; padding: 4px 10px; }
|
||||||
table.cams td.actions { white-space: nowrap; text-align: right; }
|
table.cams td.actions { white-space: nowrap; text-align: right; }
|
||||||
table.cams tr.slot-empty td { opacity: .5; }
|
table.cams tr.slot-empty td { opacity: .5; }
|
||||||
/* камеры: жёстко фиксированная высота строки 22px (плотная таблица) */
|
/* камеры: жёстко фиксированная высота строки 22px независимо от контролов.
|
||||||
|
line-height:1 + контролы по центру и ниже 22px → строки не распирает. */
|
||||||
table.cams.cams-fixed td, table.cams.cams-fixed th {
|
table.cams.cams-fixed td, table.cams.cams-fixed th {
|
||||||
height: 22px; padding-top: 0; padding-bottom: 0; line-height: 22px;
|
height: 22px; padding-top: 0; padding-bottom: 0; line-height: 1;
|
||||||
|
}
|
||||||
|
table.cams.cams-fixed td > * { vertical-align: middle; }
|
||||||
|
/* тумблеры «Вкл»/«Запись» в строке — компактные (30×16) */
|
||||||
|
table.cams.cams-fixed td input[type="checkbox"] {
|
||||||
|
width: 30px; height: 16px; border-radius: 8px;
|
||||||
|
}
|
||||||
|
table.cams.cams-fixed td input[type="checkbox"]::before { width: 12px; height: 12px; top: 1px; left: 1px; }
|
||||||
|
table.cams.cams-fixed td input[type="checkbox"]:checked::before { transform: translateX(14px); }
|
||||||
|
/* селекты и инпуты в строке — на 2px ниже строки, по центру */
|
||||||
|
table.cams.cams-fixed td select.stor-sel,
|
||||||
|
table.cams.cams-fixed td select.cell-sel,
|
||||||
|
table.cams.cams-fixed td input.cell-in { height: 20px; }
|
||||||
|
/* кнопки действий ⟳/✕ (режим редактирования) — компактные */
|
||||||
|
table.cams.cams-fixed td.actions button {
|
||||||
|
height: 20px; padding: 0 6px; font-size: 13px; line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Инлайн-редактор строки (вместо всплывающего окна) ── */
|
/* ── Инлайн-редактор строки (вместо всплывающего окна) ── */
|
||||||
|
|||||||
Reference in New Issue
Block a user