2024-03-16 20:44:22 +00:00
|
|
|
import "../scss/frontend.scss";
|
|
|
|
import "../css/userarea.css";
|
2024-03-27 09:08:07 +00:00
|
|
|
import "@phosphor-icons/web/light";
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
|
2024-03-17 07:35:40 +00:00
|
|
|
import { getCategoryMedia, getCookie, getElementById } from "./api";
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
import { Tab } from "bootstrap";
|
|
|
|
import DataTable from "datatables.net-dt";
|
Enhance editor UI and user content management
Introduced significant updates to the user interface for editing VR
scenes, adding new CSS styles for a coherent and modern look.
Implemented data tables for robust content management in the user area,
now users can easily navigate through scenes and media with DataTables
integration. Expanded the API with category retrieval capabilities,
enabling dynamic content categorization.
The editor now seamlessly integrates into the UI with a sidebar for
properties editing, improving usability. The teleportation element
creation and modification logic has been significantly refined,
including a search-enabled dropdown for destination selection, making it
more user-friendly. Added thumbnail display for scenes and media in the
user area, enhancing content overview.
This update also introduced user area templates and routes, providing a
foundational structure for user content management functionality,
including categories and individual category views.
Refactored JavaScript imports to align with the new editor CSS and
adjusted scene loading to support embedded scenes, improving the
flexibility and usability of scene components.
2024-03-14 16:28:14 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
let mediaTable = new DataTable("#mediaTable");
|
|
|
|
let scenesTable = new DataTable("#scenesTable");
|
|
|
|
let permissionsTable = new DataTable("#permissionsTable");
|
2024-03-16 20:30:12 +00:00
|
|
|
|
|
|
|
/* Uploads */
|
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
document.querySelectorAll(".drop-zone__input").forEach((inputElement) => {
|
|
|
|
const dropZoneElement = inputElement.closest(".drop-zone");
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
dropZoneElement.addEventListener("click", (e) => {
|
|
|
|
inputElement.click();
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
dropZoneElement.addEventListener("dragover", (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
dropZoneElement.classList.add("drop-zone--over");
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
["dragleave", "dragend", "drop"].forEach((type) => {
|
|
|
|
dropZoneElement.addEventListener(type, (e) => {
|
|
|
|
dropZoneElement.classList.remove("drop-zone--over");
|
2024-03-16 20:30:12 +00:00
|
|
|
});
|
2024-03-16 20:44:22 +00:00
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
dropZoneElement.addEventListener("drop", (e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
if (e.dataTransfer.files.length) {
|
|
|
|
inputElement.files = e.dataTransfer.files;
|
|
|
|
handleFiles(inputElement.files);
|
|
|
|
}
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
inputElement.addEventListener("change", (e) => {
|
|
|
|
if (inputElement.files.length) {
|
|
|
|
handleFiles(inputElement.files);
|
|
|
|
}
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
function handleFiles(files) {
|
2024-03-16 20:44:22 +00:00
|
|
|
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");
|
2024-03-17 07:35:40 +00:00
|
|
|
thumbnail.src = ""; // TODO: Add a loading spinner or something here
|
2024-03-16 20:44:22 +00:00
|
|
|
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);
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function uploadFile(file, progressBar, thumbnail) {
|
2024-03-16 20:44:22 +00:00
|
|
|
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)}%`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
xhr.open("POST", document.location.href, true);
|
2024-03-16 20:30:12 +00:00
|
|
|
|
2024-03-16 20:44:22 +00:00
|
|
|
xhr.onload = () => {
|
|
|
|
if (xhr.status === 201) {
|
|
|
|
const response = JSON.parse(xhr.responseText);
|
2024-03-17 07:35:40 +00:00
|
|
|
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);
|
2024-03-16 20:30:12 +00:00
|
|
|
} else {
|
2024-03-16 20:44:22 +00:00
|
|
|
progressBar.classList.add("bg-danger");
|
|
|
|
progressBar.textContent = "Error!";
|
2024-03-16 20:30:12 +00:00
|
|
|
}
|
2024-03-16 20:44:22 +00:00
|
|
|
};
|
|
|
|
xhr.send(formData);
|
2024-03-16 20:30:12 +00:00
|
|
|
}
|