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;
+}
|