Files
Wireguard_server/gui/templates/index.html
T
ruslan 0aead8c3ad feat(gui): inline peer rename
Click on peer name in the table to edit it inline.
Enter to save, Escape to cancel, blur also saves.
Saved via POST /peers/<id>/rename without page reload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 10:25:28 +03:00

132 lines
5.2 KiB
HTML

{% extends 'base.html' %}
{% block content %}
<div class="page-header">
<div>
<h2>Клиенты</h2>
<p class="meta-line">
<span class="meta-tag">{{ meta.get('WG_INTERFACE','wg0') }}</span>
<span class="meta-tag">{{ meta.get('WG_NETWORK','-') }}</span>
<span class="meta-tag">{{ meta.get('SERVER_PUBLIC_IP','-') }}:{{ meta.get('WG_PORT','-') }}</span>
</p>
</div>
<a href="{{ url_for('new_peer') }}" class="btn btn-primary">+ Добавить peer</a>
</div>
<div class="card">
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Имя</th>
<th>Статус</th>
<th>IP</th>
<th>Роуты</th>
<th>Endpoint</th>
<th>RX / TX</th>
<th>Публичный ключ</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for p in peers %}
<tr class="{{ 'row-disabled' if not p.enabled else '' }}">
<td>
{% if p.id %}
<span class="peer-name editable" onclick="startRename(this, {{ p.id }}, '{{ csrf_token() }}')" title="Нажмите чтобы переименовать">{{ p.name }}</span>
{% else %}
<span class="peer-name">{{ p.name }}</span>
{% endif %}
</td>
<td>
<span class="badge {{ p.status }}" title="{{ p.handshake_ago }}">
<i class="dot"></i>
<span>{{ p.status }}</span>
<span class="badge-ago">{{ p.handshake_ago }}</span>
</span>
</td>
<td class="mono-sm">{{ p.client_address }}</td>
<td class="mono-sm text-muted">{{ p.routes }}</td>
<td>
<span class="mono-sm text-muted">{{ p.endpoint }}</span>
{% if p.hostname %}<br><span class="hostname">{{ p.hostname }}</span>{% endif %}
</td>
<td class="text-muted traffic">
<span title="Получено">↓ {{ p.rx }}</span>
<span title="Отправлено">↑ {{ p.tx }}</span>
</td>
<td><span class="pubkey" title="{{ p.public_key }}">{{ p.public_key[:20] }}…</span></td>
<td>
<div class="actions">
{% if p.id %}
<a href="{{ url_for('peer_view', peer_id=p.id) }}" class="btn btn-sm">QR</a>
<a href="{{ url_for('peer_download', peer_id=p.id) }}" class="btn btn-sm">↓ .conf</a>
{% if p.enabled %}
<form method="post" action="{{ url_for('peer_disable', peer_id=p.id) }}" style="display:inline">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-sm btn-warn">Откл</button>
</form>
{% else %}
<form method="post" action="{{ url_for('peer_enable', peer_id=p.id) }}" style="display:inline">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-sm btn-ok">Вкл</button>
</form>
{% endif %}
<form method="post" action="{{ url_for('peer_delete', peer_id=p.id) }}" style="display:inline" onsubmit="return confirm('Удалить peer {{ p.name }}?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-sm btn-danger">Удалить</button>
</form>
{% else %}
<form method="post" action="{{ url_for('peer_delete_by_key') }}" style="display:inline" onsubmit="return confirm('Удалить peer?')">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="public_key" value="{{ p.public_key }}" />
<button type="submit" class="btn btn-sm btn-danger">Удалить</button>
</form>
{% endif %}
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="8" class="empty">Пиров нет. <a href="{{ url_for('new_peer') }}">Добавить первый</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<script>
function startRename(el, peerId, csrf) {
if (el.querySelector('input')) return;
const oldName = el.textContent.trim();
const inp = document.createElement('input');
inp.className = 'rename-input';
inp.value = oldName;
el.textContent = '';
el.appendChild(inp);
inp.focus();
inp.select();
function save() {
const name = inp.value.trim();
if (!name || name === oldName) { el.textContent = oldName; return; }
fetch(`/peers/${peerId}/rename`, {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: `name=${encodeURIComponent(name)}&csrf_token=${encodeURIComponent(csrf)}`
}).then(r => {
el.textContent = r.ok ? name : oldName;
}).catch(() => { el.textContent = oldName; });
}
inp.addEventListener('keydown', e => {
if (e.key === 'Enter') { e.preventDefault(); save(); }
if (e.key === 'Escape') { el.textContent = oldName; }
});
inp.addEventListener('blur', save);
}
</script>
{% endblock %}