function togglePortalNav() { const wrap = document.getElementById("portal-nav"); if (wrap) { wrap.classList.toggle("open"); } return false; } 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 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 = 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; } function openResourceModal(id) { const modal = document.getElementById(id); if (!modal) { return false; } if (typeof modal.showModal === "function") { modal.showModal(); } else { modal.setAttribute("open", ""); } return false; } function closeResourceModal(id) { const modal = document.getElementById(id); if (!modal) { return false; } if (typeof modal.close === "function") { modal.close(); } else { modal.removeAttribute("open"); } return false; } document.addEventListener("click", (event) => { const modal = event.target; if (typeof HTMLDialogElement !== "undefined" && modal instanceof HTMLDialogElement && modal.classList.contains("resource-modal")) { modal.close(); } }); function setFormDisabled(form, disabled) { for (const field of form.querySelectorAll("input, select, textarea, button")) { field.disabled = disabled; } } function extractMainHtml(responseText) { const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const main = doc.querySelector("main"); return main ? main.innerHTML : ""; } document.addEventListener("DOMContentLoaded", () => { const form = document.querySelector('[data-ajax-form="new-app"]'); if (!form) { return; } const loader = document.getElementById("new-app-loader"); const status = document.getElementById("new-app-status"); const result = document.getElementById("new-app-result"); // ID služby musí být vždy lowercase (Docker image/container, Gitea repo, URL). // Přepisujeme rovnou při psaní, ať uživatel vidí skutečnou hodnotu, která se odešle. const appIdInput = form.querySelector('input[name="app_id"]'); if (appIdInput) { appIdInput.addEventListener("input", () => { const lowered = appIdInput.value.toLowerCase(); if (appIdInput.value !== lowered) { const cursor = appIdInput.selectionStart; appIdInput.value = lowered; appIdInput.setSelectionRange(cursor, cursor); } }); } form.addEventListener("submit", async (event) => { event.preventDefault(); const formData = new FormData(form); if (status) { status.className = "async-status"; status.textContent = "Vytv\u00e1\u0159\u00edm slu\u017ebu, neobnovujte str\u00e1nku."; } if (result) { result.innerHTML = ""; } if (loader) { loader.hidden = false; } setFormDisabled(form, true); try { const response = await fetch(form.action, { method: "POST", body: formData, headers: { "X-Requested-With": "fetch", }, }); const responseText = await response.text(); const mainHtml = extractMainHtml(responseText); if (mainHtml) { const main = document.querySelector("main"); if (main) { main.innerHTML = mainHtml; } return; } if (!response.ok) { throw new Error(responseText || "Vytvo\u0159en\u00ed slu\u017eby selhalo."); } if (result) { result.innerHTML = responseText; } if (status) { status.textContent = ""; } } catch (error) { if (status) { status.className = "async-status async-status-error"; status.textContent = error.message || "Vytvo\u0159en\u00ed slu\u017eby selhalo."; } setFormDisabled(form, false); } finally { if (loader) { loader.hidden = true; } } }); });