From 17a4d4db1b5865e651adc5548998e08295bc2dab Mon Sep 17 00:00:00 2001 From: JiriUhlir <149317995+JiriUhlir@users.noreply.github.com> Date: Thu, 28 May 2026 13:33:22 +0200 Subject: [PATCH] copying, evidovat btn hidden --- app/routes/apps.py | 4 +- app/routes/backups.py | 4 -- app/static/portal.js | 85 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/app/routes/apps.py b/app/routes/apps.py index bb49f73..387e62d 100644 --- a/app/routes/apps.py +++ b/app/routes/apps.py @@ -94,13 +94,13 @@ def index(request: Request, user=Depends(require_user)):
- +
- +
diff --git a/app/routes/backups.py b/app/routes/backups.py index fe701b0..3bfb84c 100644 --- a/app/routes/backups.py +++ b/app/routes/backups.py @@ -45,10 +45,6 @@ def backups_page(request: Request, user=Depends(require_user)): -
- - -
Obnova je nebezpečná a musí se spustit ručně přes SSH.
diff --git a/app/static/portal.js b/app/static/portal.js index a48eab2..1c6f749 100644 --- a/app/static/portal.js +++ b/app/static/portal.js @@ -1,17 +1,84 @@ -function copyValue(id) { - const el = document.getElementById(id); - el.select(); - el.setSelectionRange(0, 99999); - navigator.clipboard.writeText(el.value); +function writeClipboard(value) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(value); + } + + const textarea = document.createElement("textarea"); + textarea.value = value; + textarea.setAttribute("readonly", ""); + textarea.style.position = "fixed"; + textarea.style.top = "-1000px"; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand("copy"); + document.body.removeChild(textarea); + return Promise.resolve(); } -function copyText(button) { - const value = button.dataset.copyValue || ""; - navigator.clipboard.writeText(value); +function nearestCopyValue(button) { + if (button.dataset.copyValue) { + return button.dataset.copyValue; + } + const scopes = [ + button.closest(".copy-row"), + button.closest(".cmd-row"), + button.closest("td"), + button.parentElement, + ]; + + for (const scope of scopes) { + if (!scope) { + continue; + } + + const target = scope.querySelector("input, textarea, pre, code"); + if (target) { + return "value" in target ? target.value : target.textContent; + } + } + + return ""; +} + +function showCopied(button, ok) { const label = button.textContent; - button.textContent = "Zkopírováno"; + button.textContent = ok ? "Zkopírováno" : "Nelze kopírovat"; window.setTimeout(() => { button.textContent = label; }, 1200); } + +function copyValue(idOrButton) { + const target = typeof idOrButton === "string" ? document.getElementById(idOrButton) : idOrButton; + if (!target) { + return false; + } + + const value = "value" in target ? target.value : nearestCopyValue(target); + if ("select" in target) { + target.select(); + target.setSelectionRange(0, target.value.length); + } + + writeClipboard(value) + .then(() => { + if (!("value" in target)) { + showCopied(target, true); + } + }) + .catch(() => { + if (!("value" in target)) { + showCopied(target, false); + } + }); + return false; +} + +function copyText(button) { + const value = nearestCopyValue(button); + writeClipboard(value) + .then(() => showCopied(button, true)) + .catch(() => showCopied(button, false)); + return false; +}