Files
warpbox-dev/backend/static/js/20-storage-admin.js

128 lines
4.4 KiB
JavaScript
Raw Normal View History

(function () {
document.querySelectorAll("[data-storage-delete-warning]").forEach((button) => {
button.addEventListener("click", (event) => {
const name = button.getAttribute("data-storage-delete-warning") || "this storage backend";
const confirmed = window.confirm(
`Delete ${name}?\n\nAll boxes stored on this location will also be deleted. Any global defaults or user storage overrides pointing at it will be reset back to inherited local storage.`
);
if (!confirmed) {
event.preventDefault();
}
});
});
document.querySelectorAll("[data-storage-speed-open]").forEach((button) => {
button.addEventListener("click", () => {
const modal = document.querySelector("[data-storage-speed-modal]");
if (modal) {
modal.hidden = false;
}
});
});
document.querySelectorAll("[data-storage-modal-close]").forEach((button) => {
button.addEventListener("click", () => {
const modal = button.closest(".storage-modal");
if (modal) {
modal.hidden = true;
}
});
});
document.addEventListener("keydown", (event) => {
if (event.key !== "Escape") {
return;
}
document.querySelectorAll(".storage-modal").forEach((modal) => {
modal.hidden = true;
});
});
document.querySelectorAll(".storage-speed-form").forEach((form) => {
const customFields = form.querySelector("[data-storage-custom-fields]");
function syncCustomFields() {
if (!customFields) {
return;
}
const customSelected = form.querySelector('input[name="mode"]:checked')?.value === "custom";
customFields.hidden = !customSelected;
customFields.querySelectorAll("input").forEach((input) => {
input.disabled = !customSelected;
});
}
form.querySelectorAll('input[name="mode"]').forEach((input) => {
input.addEventListener("change", syncCustomFields);
});
syncCustomFields();
});
const testList = document.querySelector("[data-storage-tests-page]");
if (!testList) {
return;
}
function escapeHTML(value) {
return String(value || "").replace(/[&<>"']/g, (char) => ({
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': "&quot;",
"'": "&#39;",
})[char]);
}
function renderTest(test) {
const progress = Math.max(0, Math.min(100, Number(test.progress || 0)));
const error = test.error
? `<span class="storage-result-error"><strong>Error</strong>${escapeHTML(test.error)}</span>`
: "";
return `
<details class="storage-result-row" data-storage-test-id="${escapeHTML(test.id)}">
<summary>
<span>${escapeHTML(test.startedLabel)}</span>
<span>${escapeHTML(test.customLabel || test.modeLabel)}</span>
<span class="storage-result-status is-${escapeHTML(test.status)}">${escapeHTML(test.status)}</span>
</summary>
<div class="storage-test-progress" aria-label="Test progress">
<div class="storage-test-progress-bar"><span style="width: ${progress}%"></span></div>
<small>${progress}%${test.stage ? " · " + escapeHTML(test.stage) : ""}</small>
</div>
<div class="storage-result-detail">
<span><strong>Finished</strong>${escapeHTML(test.finishedLabel)}</span>
<span><strong>Files</strong>${escapeHTML(test.files)}</span>
<span><strong>Size</strong>${escapeHTML(test.sizeLabel)}</span>
<span><strong>Write</strong>${escapeHTML(test.writeSpeed)}</span>
<span><strong>Read</strong>${escapeHTML(test.readSpeed)}</span>
${error}
</div>
</details>`;
}
async function refreshTests() {
const url = testList.getAttribute("data-storage-tests-url");
if (!url) {
return;
}
const response = await fetch(url, { headers: { Accept: "application/json" } });
if (!response.ok) {
return;
}
const payload = await response.json();
const openIDs = new Set(Array.from(testList.querySelectorAll("details[open]")).map((row) => row.dataset.storageTestId));
const tests = payload.tests || [];
if (tests.length === 0) {
return;
}
testList.innerHTML = tests.map(renderTest).join("");
testList.querySelectorAll("details").forEach((row) => {
if (openIDs.has(row.dataset.storageTestId)) {
row.open = true;
}
});
}
setInterval(() => {
refreshTests().catch(() => {});
}, 1200);
})();