refactor(scene): modularize sidebar and navbar loading

Refactored the scene script to extract the logic for loading sidebars
and navbars into separate, modular files. This change enhances code
maintainability and readability by compartmentalizing responsibilities
and clarifying function boundaries. Now, `navbar.js` and `sidebar.js`
handle the UI component rendering, allowing for easier updates and
potential reuse. Adjusted conditional rendering logic to ensure
exclusive navbar or sidebar presence, aligning UI behavior with design
expectations.

This commit signifies a step towards modular architecture in the
frontend codebase, facilitating future expansion and modification.
This commit is contained in:
Kumi 2024-03-16 11:16:26 +01:00
parent c463de0ada
commit 85c44f985d
Signed by: kumi
GPG key ID: ECBCC9082395383F
3 changed files with 149 additions and 140 deletions

View file

@ -1,4 +1,7 @@
import { getScene, getCategory } from "./api";
import { loadSidebar } from "./scene/sidebar";
import { loadNavbar } from "./scene/navbar";
import { Dropdown, Collapse } from "bootstrap";
import "../scss/frontend.scss";
@ -29,7 +32,7 @@ class QuackscapeScene extends HTMLElement {
loadNavbar(this.scene, this);
}
if (this.sidebar) {
else if (this.sidebar) {
loadSidebar(this.scene, this);
}
}
@ -41,132 +44,6 @@ document.addEventListener("contextmenu", function (event) {
customElements.define("quackscape-scene", QuackscapeScene);
// Function to add a sidebar to the destination object
async function loadSidebar(scene_id, destination) {
getScene(scene_id).then((scene) => {
getCategory(scene.obj.category).then((category) => {
var sidebar = document.createElement("div");
sidebar.setAttribute("class", "collapse show");
sidebar.setAttribute("id", "sceneSidebar");
var p = document.createElement("div");
p.setAttribute("class", "p-4");
var h5 = document.createElement("h5");
h5.setAttribute("class", "font-weight-bold");
h5.textContent = "Scenes";
var ul = document.createElement("ul");
ul.setAttribute("class", "nav flex-column");
category.obj.scenes.forEach((scene) => {
var li = document.createElement("li");
li.setAttribute("class", "nav-item");
var a = document.createElement("a");
a.setAttribute("href", "#");
a.setAttribute("class", "nav-link");
a.textContent = scene.title;
a.addEventListener("click", function () {
loadScene(scene.id, -1, -1, -1, destination);
});
li.appendChild(a);
ul.appendChild(li);
});
p.appendChild(h5);
p.appendChild(ul);
var button = document.createElement("button");
button.setAttribute("class", "btn-close-sidebar");
button.setAttribute("type", "button");
button.setAttribute("id", "btnCloseSidebar");
button.textContent = "Close Sidebar";
button.addEventListener("click", function () {
toggleSidebar();
});
sidebar.appendChild(button); // TODO: Make it prettier before enabling.
sidebar.appendChild(p);
var reopenButton = document.createElement("button");
reopenButton.setAttribute("class", "btn-open-sidebar hide");
reopenButton.textContent = "Open Sidebar";
reopenButton.addEventListener("click", function () {
toggleSidebar();
});
destination.prepend(reopenButton);
destination.prepend(sidebar);
});
});
}
// Function to add a navbar to the destination object
async function loadNavbar(scene_id, destination) {
getScene(scene_id).then((scene) => {
getCategory(scene.obj.category).then((category) => {
var nav = document.createElement("nav");
nav.setAttribute("class", "navbar navbar-expand-lg navbar-dark bg-dark");
nav.setAttribute("id", "sceneNavbar");
var container = document.createElement("div");
container.setAttribute("class", "container-fluid");
var dropdown = document.createElement("div");
dropdown.setAttribute("class", "dropdown");
var sceneSelector = document.createElement("button");
sceneSelector.setAttribute("class", "btn btn-secondary dropdown-toggle");
sceneSelector.setAttribute("type", "button");
sceneSelector.setAttribute("id", "sceneSelector");
sceneSelector.setAttribute("data-bs-toggle", "dropdown");
sceneSelector.setAttribute("aria-expanded", "true");
sceneSelector.textContent = "Select Scene";
var dropdownMenu = document.createElement("ul");
dropdownMenu.setAttribute("class", "dropdown-menu show");
dropdownMenu.setAttribute("aria-labelledby", "sceneSelector");
console.log(dropdownMenu);
category.obj.scenes.forEach((scene) => {
console.log(scene);
var sceneLink = document.createElement("a");
sceneLink.setAttribute("class", "dropdown-item");
sceneLink.setAttribute("href", "#");
sceneLink.textContent = scene.title;
sceneLink.addEventListener("click", function () {
loadScene(scene.id, -1, -1, -1, destination);
});
dropdownMenu.appendChild(sceneLink);
});
var sceneTitle = document.createElement("a");
sceneTitle.setAttribute("class", "navbar-brand");
sceneTitle.setAttribute("href", "#");
sceneTitle.setAttribute("id", "sceneTitle");
sceneTitle.textContent = scene.obj.title;
dropdown.appendChild(sceneSelector);
dropdown.appendChild(dropdownMenu);
console.log(dropdownMenu);
container.appendChild(dropdown);
container.appendChild(sceneTitle);
nav.appendChild(container);
destination.prepend(nav);
});
});
}
// Function to load a scene into a destination object
// x and y signify the initial looking direction, -1 for the scene's default
@ -280,19 +157,6 @@ async function loadScene(
});
}
function toggleSidebar() {
const sidebar = document.getElementById("sceneSidebar");
const reopenButton = document.querySelector(".btn-open-sidebar");
if (!sidebar.classList.contains("show")) {
sidebar.classList.add("show");
reopenButton.classList.add("hide");
} else {
sidebar.classList.remove("show");
reopenButton.classList.remove("hide");
}
}
window.loadScene = loadScene;

64
assets/js/scene/navbar.js Normal file
View file

@ -0,0 +1,64 @@
import { getScene, getCategory } from "../api";
// Function to add a navbar to the destination object
async function loadNavbar(scene_id, destination) {
getScene(scene_id).then((scene) => {
getCategory(scene.obj.category).then((category) => {
var nav = document.createElement("nav");
nav.setAttribute("class", "navbar navbar-expand-lg navbar-dark bg-dark");
nav.setAttribute("id", "sceneNavbar");
var container = document.createElement("div");
container.setAttribute("class", "container-fluid");
var dropdown = document.createElement("div");
dropdown.setAttribute("class", "dropdown");
var sceneSelector = document.createElement("button");
sceneSelector.setAttribute("class", "btn btn-secondary dropdown-toggle");
sceneSelector.setAttribute("type", "button");
sceneSelector.setAttribute("id", "sceneSelector");
sceneSelector.setAttribute("data-bs-toggle", "dropdown");
sceneSelector.setAttribute("aria-expanded", "true");
sceneSelector.textContent = "Select Scene";
var dropdownMenu = document.createElement("ul");
dropdownMenu.setAttribute("class", "dropdown-menu show");
dropdownMenu.setAttribute("aria-labelledby", "sceneSelector");
console.log(dropdownMenu);
category.obj.scenes.forEach((scene) => {
console.log(scene);
var sceneLink = document.createElement("a");
sceneLink.setAttribute("class", "dropdown-item");
sceneLink.setAttribute("href", "#");
sceneLink.textContent = scene.title;
sceneLink.addEventListener("click", function () {
loadScene(scene.id, -1, -1, -1, destination);
});
dropdownMenu.appendChild(sceneLink);
});
var sceneTitle = document.createElement("a");
sceneTitle.setAttribute("class", "navbar-brand");
sceneTitle.setAttribute("href", "#");
sceneTitle.setAttribute("id", "sceneTitle");
sceneTitle.textContent = scene.obj.title;
dropdown.appendChild(sceneSelector);
dropdown.appendChild(dropdownMenu);
console.log(dropdownMenu);
container.appendChild(dropdown);
container.appendChild(sceneTitle);
nav.appendChild(container);
destination.prepend(nav);
});
});
}
export { loadNavbar };

View file

@ -0,0 +1,81 @@
import { getScene, getCategory } from "../api";
// Function to add a sidebar to the destination object
async function loadSidebar(scene_id, destination) {
getScene(scene_id).then((scene) => {
getCategory(scene.obj.category).then((category) => {
var sidebar = document.createElement("div");
sidebar.setAttribute("class", "collapse show");
sidebar.setAttribute("id", "sceneSidebar");
var p = document.createElement("div");
p.setAttribute("class", "p-4");
var h5 = document.createElement("h5");
h5.setAttribute("class", "font-weight-bold");
h5.textContent = "Scenes";
var ul = document.createElement("ul");
ul.setAttribute("class", "nav flex-column");
category.obj.scenes.forEach((scene) => {
var li = document.createElement("li");
li.setAttribute("class", "nav-item");
var a = document.createElement("a");
a.setAttribute("href", "#");
a.setAttribute("class", "nav-link");
a.textContent = scene.title;
a.addEventListener("click", function () {
loadScene(scene.id, -1, -1, -1, destination);
});
li.appendChild(a);
ul.appendChild(li);
});
p.appendChild(h5);
p.appendChild(ul);
var button = document.createElement("button");
button.setAttribute("class", "btn-close-sidebar");
button.setAttribute("type", "button");
button.setAttribute("id", "btnCloseSidebar");
button.textContent = "Close Sidebar";
button.addEventListener("click", function () {
toggleSidebar();
});
sidebar.appendChild(button); // TODO: Make it prettier before enabling.
sidebar.appendChild(p);
var reopenButton = document.createElement("button");
reopenButton.setAttribute("class", "btn-open-sidebar hide");
reopenButton.textContent = "Open Sidebar";
reopenButton.addEventListener("click", function () {
toggleSidebar();
});
destination.prepend(reopenButton);
destination.prepend(sidebar);
});
});
}
function toggleSidebar() {
const sidebar = document.getElementById("sceneSidebar");
const reopenButton = document.querySelector(".btn-open-sidebar");
if (!sidebar.classList.contains("show")) {
sidebar.classList.add("show");
reopenButton.classList.add("hide");
} else {
sidebar.classList.remove("show");
reopenButton.classList.remove("hide");
}
}
export { loadSidebar, toggleSidebar };