75 lines
6.0 KiB
HTML
75 lines
6.0 KiB
HTML
{% import "_ui.html" as ui %}
|
|||
|
|
{% if oob %}<div class="sub" id="dev-sub" hx-swap-oob="true">{% include "_dev_sub.html" %}</div>{% endif %}
|
||
|
|
<div class="table-wrap">
|
||
|
|
<table class="grid">
|
||
|
|
<colgroup><col style="width:44px"><col><col style="width:110px"><col style="width:110px"><col style="width:100px"><col style="width:120px"><col style="width:90px"><col style="width:120px"><col style="width:100px"><col style="width:150px"><col style="width:52px"></colgroup>
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th><input type="checkbox" id="check-all" aria-label="Выбрать все"></th>
|
||
|
|
<th>Устройство</th><th>Группа</th><th>Канал</th><th>ROS</th><th>Upgrade ROS</th><th>FW</th><th>Upgrade FW</th><th>Uptime</th><th>Запрос бэкапа (UTC)</th><th><span class="sr-only">Действия</span></th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{% for d in devices %}
|
||
|
|
{% set st = d.status %}{% set down = d.online is false %}
|
||
|
|
{% set ros_new = st.ros_latest and st.ros_installed and st.ros_latest != st.ros_installed %}
|
||
|
|
{% set fw_new = st.fw_current and st.fw_upgrade and st.fw_upgrade != st.fw_current %}
|
||
|
|
<tr>
|
||
|
|
<td><input type="checkbox" name="device_ids" value="{{ d.id }}" form="move-form" aria-label="Выбрать {{ d.name }}"></td>
|
||
|
|
<td>
|
||
|
|
<div class="dev">
|
||
|
|
<span class="dot {{ 'on' if d.online else ('off' if down else '') }}" title="{{ d.last_error or ('online, опрошено ' ~ (d.status_at|dt)) }}"></span>
|
||
|
|
<div style="min-width:0">
|
||
|
|
<div class="dev-name"><a class="dev-link" href="/devices/{{ d.id }}/edit" hx-get="/ui/dialog/device/{{ d.id }}" hx-target="#modal-body"
|
||
|
|
title="{{ d.note or 'Изменить устройство' }}">{{ d.name }}</a></div>
|
||
|
|
{% if down %}<div class="dev-sub bad" title="{{ d.last_error }}">Нет соединения</div>
|
||
|
|
{% else %}<div class="dev-sub">{{ d.host }}:{{ d.port }}{% if st.model %} · {{ st.model }}{% endif %}</div>{% endif %}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td class="muted">{{ group_names.get(d.group_id) or "—" }}</td>
|
||
|
|
<td>{% if down %}<span class="dash">—</span>{% else %}{{ st.channel or "—" }}{% endif %}</td>
|
||
|
|
<td class="c-mono">{% if down %}<span class="dash">—</span>{% else %}{{ st.ros_installed or st.ros_version or "—" }}{% endif %}</td>
|
||
|
|
<td>
|
||
|
|
{% if down or not (st.ros_latest and st.ros_installed) %}<span class="dash" title="{{ st.ros_check_error or 'Проверка обновлений ещё не выполнялась' }}">—</span>
|
||
|
|
{% elif ros_new %}<span class="badge warn" title="Доступно обновление ROS до {{ st.ros_latest }}">{{ ui.icon("up", 12, 2.2) }}{{ st.ros_latest }}</span>
|
||
|
|
{% else %}<span class="okmark">{{ ui.icon("check", 14, 2.2) }}актуально</span>{% endif %}
|
||
|
|
</td>
|
||
|
|
<td class="c-mono">{% if down %}<span class="dash">—</span>{% else %}{{ st.fw_current or "—" }}{% endif %}</td>
|
||
|
|
<td>
|
||
|
|
{% if down or not (st.fw_current and st.fw_upgrade) %}<span class="dash" title="Нет RouterBOARD firmware (например, CHR) или устройство не опрошено">—</span>
|
||
|
|
{% elif fw_new %}<span class="badge warn" title="Доступно обновление прошивки до {{ st.fw_upgrade }}">{{ ui.icon("up", 12, 2.2) }}{{ st.fw_upgrade }}</span>
|
||
|
|
{% else %}<span class="okmark">{{ ui.icon("check", 14, 2.2) }}актуально</span>{% endif %}
|
||
|
|
</td>
|
||
|
|
<td class="c-small">{% if down %}<span class="dash">—</span>{% else %}{{ st.uptime or "—" }}{% endif %}</td>
|
||
|
|
<td class="c-small">{{ d.last_backup_requested_at|dt }}</td>
|
||
|
|
<td class="c-menu">
|
||
|
|
<details class="menu right">
|
||
|
|
<summary class="btn ghost-n icon" aria-label="Действия для {{ d.name }}" title="Действия">{{ ui.icon("more") }}</summary>
|
||
|
|
<div class="menu-panel w270">
|
||
|
|
<button type="button" class="mi" hx-post="/ui/devices/{{ d.id }}/refresh" hx-include="#dev-filters" hx-target="#devices">Обновить статус</button>
|
||
|
|
<button type="button" class="mi" hx-post="/ui/devices/{{ d.id }}/backup" hx-target="#jobs">Создать бэкап</button>
|
||
|
|
<hr>
|
||
|
|
<button type="button" class="mi warn" hx-post="/ui/devices/{{ d.id }}/ros_update" hx-target="#jobs"
|
||
|
|
hx-confirm="Обновить ROS на {{ d.name }}? Устройство перезагрузится после скачивания.">Обновить ROS<small>Перезагрузка после скачивания</small></button>
|
||
|
|
<button type="button" class="mi warn" hx-post="/ui/devices/{{ d.id }}/fw_update" hx-target="#jobs"
|
||
|
|
hx-confirm="Обновить прошивку на {{ d.name }}? Устройство перезагрузится сразу после обновления.">Обновить FW<small>Перезагрузка сразу после обновления</small></button>
|
||
|
|
<hr>
|
||
|
|
<details class="sub">
|
||
|
|
<summary class="mi">Сменить канал…</summary>
|
||
|
|
<div class="sub-list">
|
||
|
|
{% for c in channels %}<button type="button" class="mi {{ 'on' if c == st.channel }}" hx-post="/ui/devices/{{ d.id }}/channel" hx-vals='{"channel": "{{ c }}"}' hx-include="#dev-filters" hx-target="#devices">{{ c }}</button>{% endfor %}
|
||
|
|
</div>
|
||
|
|
</details>
|
||
|
|
<button type="button" class="mi" hx-get="/ui/dialog/device/{{ d.id }}" hx-target="#modal-body">Изменить устройство</button>
|
||
|
|
</div>
|
||
|
|
</details>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
{% else %}
|
||
|
|
<tr><td colspan="11" class="empty">{{ "Нет устройств, подходящих под фильтр." if filtered else "Устройств пока нет. Добавьте первое." }}</td></tr>
|
||
|
|
{% endfor %}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
<div class="tfoot">Показано {{ devices|length }} из {{ total }} {{ total|plural("устройства", "устройств", "устройств") }}</div>
|