Files
ruslan 3bfb650b80 feat: route commands for peer clients (Linux/Windows) + footer signature
- scripts page: new card with Linux/macOS and Windows route commands
  per peer that has advertised_routes, with OS tab switcher and copy buttons
- Made by Galyaviev moved from sidebar to bottom-center page footer on all pages
- page-footer style: Dancing Script 20px, clickable mailto:ruslan@ipcom.su

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

103 lines
4.2 KiB
HTML

{% extends 'base.html' %}
{% block content %}
<div class="page-header">
<h2>Скрипты и пути</h2>
</div>
<div class="card">
<h3>Команды</h3>
<div class="script-list">
{% for key, cmd in commands.items() %}
<div class="script-item">
<div class="script-label">{{ key }}</div>
<div class="script-cmd-wrap">
<pre class="script-cmd">{{ cmd }}</pre>
<button class="btn btn-sm copy-btn" onclick="copyText(this, {{ cmd | tojson }})">Копировать</button>
</div>
</div>
{% endfor %}
</div>
</div>
{% if route_peers %}
<div class="card">
<h3>Маршруты к клиентам за peer</h3>
<p style="font-size:13px;color:var(--text-muted);margin-bottom:18px;">
Команды для других VPN-клиентов, чтобы они могли достучаться до сетей за peer-ом.
</p>
<div class="os-tabs" style="display:flex;gap:6px;margin-bottom:18px;">
<button class="btn btn-sm os-tab active" data-os="linux" onclick="switchOS('linux', this)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
Linux / macOS
</button>
<button class="btn btn-sm os-tab" data-os="windows" onclick="switchOS('windows', this)">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="8" height="8"/><rect x="13" y="3" width="8" height="8"/><rect x="3" y="13" width="8" height="8"/><rect x="13" y="13" width="8" height="8"/></svg>
Windows
</button>
</div>
<div class="script-list">
{% for peer in route_peers %}
<div class="script-item">
<div class="script-label">{{ peer.name }} &nbsp;<span style="font-weight:400;opacity:.7">— WG IP: {{ peer.wg_ip }}</span></div>
{% for route in peer.routes %}
<div class="script-cmd-wrap" style="margin-bottom:6px;">
<pre class="script-cmd os-cmd linux">sudo ip route add {{ route.cidr }} via {{ peer.wg_ip }}</pre>
<pre class="script-cmd os-cmd windows" style="display:none">route add {{ route.net }} mask {{ route.mask }} {{ peer.wg_ip }}</pre>
<button class="btn btn-sm copy-btn"
data-linux="sudo ip route add {{ route.cidr }} via {{ peer.wg_ip }}"
data-windows="route add {{ route.net }} mask {{ route.mask }} {{ peer.wg_ip }}"
onclick="copyOS(this)">Копировать</button>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
<div style="margin-top:16px;padding:12px 14px;background:#fffbeb;border:1px solid #fcd34d;border-radius:8px;font-size:12.5px;color:#92400e;line-height:1.6;">
<strong>Постоянные маршруты:</strong><br>
Linux: добавьте в <code>/etc/rc.local</code> или конфиг интерфейса.<br>
Windows: добавьте флаг <code>-p</code><code>route -p add ...</code> — маршрут сохранится после перезагрузки.
</div>
</div>
{% endif %}
<div class="card">
<h3>Важные пути</h3>
<ul class="path-list">
{% for path in paths %}
<li class="mono-sm">{{ path }}</li>
{% endfor %}
</ul>
</div>
<script>
var currentOS = 'linux';
function switchOS(os, btn) {
currentOS = os;
document.querySelectorAll('.os-tab').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.os-cmd.linux').forEach(el => el.style.display = os === 'linux' ? '' : 'none');
document.querySelectorAll('.os-cmd.windows').forEach(el => el.style.display = os === 'windows' ? '' : 'none');
}
function copyOS(btn) {
var text = btn.getAttribute('data-' + currentOS);
navigator.clipboard.writeText(text).then(() => {
btn.textContent = 'Скопировано!';
setTimeout(() => btn.textContent = 'Копировать', 2000);
});
}
function copyText(btn, text) {
navigator.clipboard.writeText(text).then(() => {
btn.textContent = 'Скопировано!';
setTimeout(() => btn.textContent = 'Копировать', 2000);
});
}
</script>
{% endblock %}