quackscape/assets/js/userarea.js
Kumi 6da2f19f42
feat: integrate media deletion and swap icon
library

- Implemented the media deletion functionality, allowing users to delete
media entries directly from the category view. This enhances the
manageability of content within the platform, providing a more intuitive
and streamlined experience for users managing their media.
- Transitioned from FontAwesome to Phosphor Icons, opting for a lighter
and more flexible icon library that better aligns with the design ethos
of the application. This change not only introduces a fresh aesthetic
but also contributes to slightly improved page load times due to the
decreased footprint of the icon library.
- Updated various UI elements across the platform to maintain a
consistent look and feel, including adjustments in the user area CSS to
ensure visual compatibility with the new icon set.
- Broadened the scope of `.gitignore` to cover all JavaScript files
within the static/js directory, eliminating potential version control
clutter caused by dynamically generated or dependency-included JS files.

These changes collectively aim to refine user interaction and ensure a
more cohesive visual presentation throughout the application.
2024-03-27 10:08:07 +01:00

153 lines
4.6 KiB
JavaScript

import "../scss/frontend.scss";
import "../css/userarea.css";
import "@phosphor-icons/web/light";
import { getCategoryMedia, getCookie, getElementById } from "./api";
import { Tab } from "bootstrap";
import DataTable from "datatables.net-dt";
let mediaTable = new DataTable("#mediaTable");
let scenesTable = new DataTable("#scenesTable");
let permissionsTable = new DataTable("#permissionsTable");
/* Uploads */
document.querySelectorAll(".drop-zone__input").forEach((inputElement) => {
const dropZoneElement = inputElement.closest(".drop-zone");
dropZoneElement.addEventListener("click", (e) => {
inputElement.click();
});
dropZoneElement.addEventListener("dragover", (e) => {
e.preventDefault();
dropZoneElement.classList.add("drop-zone--over");
});
["dragleave", "dragend", "drop"].forEach((type) => {
dropZoneElement.addEventListener(type, (e) => {
dropZoneElement.classList.remove("drop-zone--over");
});
});
dropZoneElement.addEventListener("drop", (e) => {
e.preventDefault();
if (e.dataTransfer.files.length) {
inputElement.files = e.dataTransfer.files;
handleFiles(inputElement.files);
}
});
inputElement.addEventListener("change", (e) => {
if (inputElement.files.length) {
handleFiles(inputElement.files);
}
});
});
function handleFiles(files) {
const uploadStatus = document.getElementById("uploadStatus");
Array.from(files).forEach((file) => {
const fileRow = document.createElement("div");
fileRow.classList.add(
"row",
"align-items-center",
"mb-2",
"file-upload-wrapper"
);
const thumbnailCol = document.createElement("div");
thumbnailCol.classList.add("col-2");
const thumbnail = document.createElement("img");
thumbnail.classList.add("img-fluid", "thumbnail");
thumbnail.src = ""; // TODO: Add a loading spinner or something here
thumbnailCol.appendChild(thumbnail);
const fileNameCol = document.createElement("div");
fileNameCol.classList.add("col-7");
const fileName = document.createElement("span");
fileName.classList.add("file-name");
fileName.textContent = file.name;
fileNameCol.appendChild(fileName);
const progressCol = document.createElement("div");
progressCol.classList.add("col-3");
const progressBar = document.createElement("div");
progressBar.classList.add("progress");
const progressBarInner = document.createElement("div");
progressBarInner.classList.add("progress-bar");
progressBarInner.setAttribute("role", "progressbar");
progressBarInner.setAttribute("aria-valuemin", "0");
progressBarInner.setAttribute("aria-valuemax", "100");
progressBarInner.style.width = "0%";
progressBar.appendChild(progressBarInner);
progressCol.appendChild(progressBar);
fileRow.appendChild(thumbnailCol);
fileRow.appendChild(fileNameCol);
fileRow.appendChild(progressCol);
uploadStatus.prepend(fileRow);
uploadFile(file, progressBarInner, thumbnail);
});
}
function uploadFile(file, progressBar, thumbnail) {
const xhr = new XMLHttpRequest();
const formData = new FormData();
formData.append("file", file);
formData.append("csrfmiddlewaretoken", getCookie("csrftoken"));
if (file.type.startsWith("image")) {
formData.append("media_type", "image");
} else if (file.type.startsWith("video")) {
formData.append("media_type", "video");
} else {
formData.append("media_type", "other");
}
formData.append("title", file.name);
xhr.upload.addEventListener("progress", (e) => {
if (e.lengthComputable) {
if (e.loaded == e.total) {
progressBar.style.width = "100%";
progressBar.textContent = "Processing...";
} else {
const percentComplete = (e.loaded / e.total) * 100;
progressBar.style.width = `${percentComplete}%`;
progressBar.textContent = `${Math.round(percentComplete)}%`;
}
}
});
xhr.open("POST", document.location.href, true);
xhr.onload = () => {
if (xhr.status === 201) {
const response = JSON.parse(xhr.responseText);
progressBar.textContent = "Converting...";
let thumbnailCheck = setInterval(() => {
getCategoryMedia(response.category, response.id).then((media) => {
if (media.obj.resolutions.length > 0) {
clearInterval(thumbnailCheck);
thumbnail.src = media.obj.resolutions[0].file;
progressBar.classList.add("bg-success");
progressBar.textContent = "Done!";
}
});
}, 2000);
} else {
progressBar.classList.add("bg-danger");
progressBar.textContent = "Error!";
}
};
xhr.send(formData);
}