feat: copy buttons for the install commands, icons on the file bar buttons; the path title back on the left, the upload figures sliding, dialogs focused without a ring

This commit is contained in:
redtea committed 2026-10-14 20:12:03 +03:00
1 parent 55c37a0097
commit 89d5bfd3ab
2 files changed
+66 -18

No files matched your search

+37 -3
View File
@@ -5,6 +5,14 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Настройки - LPRA</title>
<link rel="stylesheet" href="{{asset "app.css"}}">
<style>
/* An install command, with a button to copy it at its right. */
.copybox { position:relative; }
.copybox pre { padding-right:48px; }
.copybox .copy { position:absolute; top:7px; right:7px; width:30px; height:30px; padding:0;
display:inline-flex; align-items:center; justify-content:center; background:var(--panel); }
.copybox .copy.done { color:var(--ok); border-color:var(--ok); }
</style>
</head>
<body>
<header class="topbar">
@@ -27,14 +35,14 @@
поставит сервис и зарегистрирует машину.</p>
<label>Короткая команда (секрет уже вшит в ссылку)</label>
<pre id="short">{{.InstallShort}}</pre>
<div class="copybox"><pre id="short">{{.InstallShort}}</pre><button type="button" class="btn ghost small icon sq copy" data-copy="short" title="Скопировать" aria-label="Скопировать"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1"/></svg></button></div>
<details style="margin-top:10px">
<summary class="muted" style="cursor:pointer">Полные варианты (секрет в команде)</summary>
<label>curl</label>
<pre id="curl">{{.InstallCurl}}</pre>
<div class="copybox"><pre id="curl">{{.InstallCurl}}</pre><button type="button" class="btn ghost small icon sq copy" data-copy="curl" title="Скопировать" aria-label="Скопировать"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1"/></svg></button></div>
<label>wget</label>
<pre id="wget">{{.InstallWget}}</pre>
<div class="copybox"><pre id="wget">{{.InstallWget}}</pre><button type="button" class="btn ghost small icon sq copy" data-copy="wget" title="Скопировать" aria-label="Скопировать"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v1"/></svg></button></div>
<p class="muted">Без переменных окружения скрипт спросит секрет интерактивно:
<code>curl -fsSL {{.Host}}/install.sh | sudo sh</code></p>
</details>
@@ -176,5 +184,31 @@
<p class="muted" style="font-size:12px; text-align:center">LPRA сервер · версия {{.ServerVersion}}</p>
</div>
<script>
// Copy an install command: the clipboard API on https, the old way otherwise.
(function () {
var CHECK = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
function copy(text) {
if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
var ta = document.createElement('textarea');
ta.value = text;
ta.style.cssText = 'position:fixed;top:0;left:0;opacity:0';
document.body.appendChild(ta);
ta.select();
var ok = document.execCommand('copy');
ta.remove();
return ok ? Promise.resolve() : Promise.reject(new Error('нет доступа к буферу'));
}
document.querySelectorAll('.copybox .copy').forEach(function (b) {
var icon = b.innerHTML;
b.onclick = function () {
copy(document.getElementById(b.dataset.copy).textContent.trim()).then(function () {
b.innerHTML = CHECK; b.classList.add('done'); b.title = 'Скопировано';
setTimeout(function () { b.innerHTML = icon; b.classList.remove('done'); b.title = 'Скопировать'; }, 1500);
}, function (e) { alert('Не скопировалось: ' + e.message); });
};
});
})();
</script>
</body>
</html>