Register apps before queued deployment

This commit is contained in:
JiriUhlir
2026-06-03 10:38:23 +02:00
parent 0a37507d86
commit 46f8024d4e
4 changed files with 334 additions and 15 deletions
+82
View File
@@ -117,3 +117,85 @@ document.addEventListener("click", (event) => {
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");
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;
}
}
});
});
+50
View File
@@ -489,6 +489,56 @@ textarea {
grid-column: 2;
}
button:disabled,
input:disabled,
select:disabled,
textarea:disabled {
cursor: wait;
opacity: 0.72;
}
.form-loader {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-weight: 700;
}
.form-loader[hidden] {
display: none;
}
.spinner {
width: 16px;
height: 16px;
border: 2px solid var(--border);
border-top-color: var(--primary);
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
.async-status {
grid-column: 2;
min-height: 22px;
color: var(--muted);
font-weight: 700;
}
.async-status-error {
color: var(--danger);
}
#new-app-result {
margin-top: 18px;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.detail-tabs {
display: flex;
flex-wrap: wrap;