Files
WarpBox/static/js/app.js

137 lines
3.6 KiB
JavaScript
Raw Normal View History

const fileInput = document.querySelector("#file-upload");
const fileCount = document.querySelector("#upload-file-count");
const fileList = document.querySelector(".upload-file-list");
const dropzone = document.querySelector(".upload-dropzone");
const uploadForm = document.querySelector(".upload-form");
const uploadStatus = document.querySelector(".upload-statusbar span:first-child");
function formatBytes(bytes) {
const units = ["B", "KB", "MB", "GB"];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex += 1;
}
if (unitIndex === 0) {
return `${size} ${units[unitIndex]}`;
}
return `${size.toFixed(1)} ${units[unitIndex]}`;
}
function updateStatus(message) {
if (uploadStatus) {
uploadStatus.textContent = message;
}
}
function updateSelectedFiles(files) {
const selectedFiles = Array.from(files || []);
if (fileCount) {
fileCount.textContent = `${selectedFiles.length} ${selectedFiles.length === 1 ? "file" : "files"}`;
}
if (!fileList) {
return;
}
fileList.replaceChildren();
if (!selectedFiles.length) {
const emptyState = document.createElement("p");
emptyState.className = "upload-empty-state";
emptyState.textContent = "No files selected";
fileList.append(emptyState);
updateStatus("Ready");
return;
}
const fragment = document.createDocumentFragment();
selectedFiles.forEach((file) => {
const row = document.createElement("div");
row.className = "upload-file-row";
const icon = document.createElement("span");
icon.className = "upload-file-icon";
icon.setAttribute("aria-hidden", "true");
const name = document.createElement("span");
name.className = "upload-file-name";
name.textContent = file.name;
name.title = file.name;
const size = document.createElement("span");
size.className = "upload-file-size";
size.textContent = formatBytes(file.size);
row.append(icon, name, size);
fragment.append(row);
});
fileList.append(fragment);
updateStatus("Files selected");
}
if (fileInput) {
fileInput.addEventListener("change", () => {
updateSelectedFiles(fileInput.files);
});
}
if (fileInput && dropzone) {
dropzone.addEventListener("dragover", (event) => {
event.preventDefault();
dropzone.classList.add("is-dragging");
});
dropzone.addEventListener("dragleave", () => {
dropzone.classList.remove("is-dragging");
});
dropzone.addEventListener("drop", (event) => {
event.preventDefault();
dropzone.classList.remove("is-dragging");
if (!event.dataTransfer.files.length) {
return;
}
fileInput.files = event.dataTransfer.files;
updateSelectedFiles(fileInput.files);
});
}
if (uploadForm && fileInput) {
uploadForm.addEventListener("submit", async (event) => {
event.preventDefault();
if (!fileInput.files.length) {
updateStatus("Choose files first");
return;
}
updateStatus("Uploading...");
try {
const response = await fetch(uploadForm.action, {
method: "POST",
body: new FormData(uploadForm),
});
if (!response.ok) {
throw new Error("Upload failed");
}
const result = await response.json();
updateStatus(`Uploaded to ${result.box_url}`);
} catch (error) {
updateStatus("Upload failed");
}
});
}