FILE / ScuroNeko/scuroneko.dev
js/workstations.js
Исходный файл и его история в репозитории.
145 lines
3.9 KiB
JavaScript
145 lines
3.9 KiB
JavaScript
let areWorkstationsExpanded = false;
|
|
|
|
const loadWorkstations = async () => {
|
|
const workstationContainer = document.getElementById("workstations");
|
|
const workstationToggle = document.getElementById("workstation-toggle");
|
|
|
|
if (!workstationContainer) {
|
|
return;
|
|
}
|
|
|
|
workstationsList = await fetchJson("./data/workstations.json");
|
|
renderWorkstations(workstationContainer);
|
|
|
|
if (
|
|
workstationToggle &&
|
|
workstationsList.some((workstation) => workstation.actual === false)
|
|
) {
|
|
workstationToggle.hidden = false;
|
|
workstationToggle.addEventListener("click", () => {
|
|
areWorkstationsExpanded = !areWorkstationsExpanded;
|
|
workstationToggle.textContent = areWorkstationsExpanded
|
|
? "Show less"
|
|
: "View all";
|
|
workstationToggle.setAttribute(
|
|
"aria-expanded",
|
|
String(areWorkstationsExpanded),
|
|
);
|
|
renderWorkstations(workstationContainer);
|
|
});
|
|
}
|
|
};
|
|
|
|
const renderWorkstations = (workstationContainer) => {
|
|
const workstationCards = workstationsList
|
|
.filter(
|
|
(workstation) => areWorkstationsExpanded || workstation.actual !== false,
|
|
)
|
|
.map(buildWorkstationCard);
|
|
workstationContainer.replaceChildren(...workstationCards);
|
|
};
|
|
|
|
const buildWorkstationCard = (workstation, index) => {
|
|
const card = document.createElement("article");
|
|
card.classList.add("workstation-card", `tone-${workstation.tone ?? "mint"}`);
|
|
|
|
const header = document.createElement("div");
|
|
header.classList.add("workstation-card__header");
|
|
|
|
const indexBadge = document.createElement("span");
|
|
indexBadge.classList.add("workstation-card__index");
|
|
indexBadge.textContent = formatIndex(index);
|
|
|
|
const key = document.createElement("span");
|
|
key.classList.add("workstation-card__key");
|
|
key.textContent = workstation.key;
|
|
|
|
const status = document.createElement("span");
|
|
status.classList.add(
|
|
"workstation-card__status",
|
|
workstation.actual
|
|
? "workstation-card__status--actual"
|
|
: "workstation-card__status--archive",
|
|
);
|
|
status.textContent = workstation.actual ? "active" : "archive";
|
|
|
|
const title = document.createElement("h3");
|
|
title.classList.add("workstation-card__title");
|
|
title.textContent = workstation.name;
|
|
|
|
const specs = document.createElement("dl");
|
|
specs.classList.add("workstation-card__specs");
|
|
|
|
appendSpec(specs, "CPU", workstation.specs?.cpu);
|
|
appendSpec(specs, "GPU", workstation.specs?.gpu);
|
|
appendSpec(specs, "RAM", workstation.specs?.ram);
|
|
appendSpec(specs, "OS", workstation.specs?.os);
|
|
|
|
const storage = buildChipGroup(
|
|
"Storage",
|
|
workstation.specs?.storage?.map(formatStorage) ?? [],
|
|
);
|
|
const devices = buildChipGroup(
|
|
"Devices",
|
|
workstation.devices?.map((device) => device.name) ?? [],
|
|
);
|
|
|
|
header.append(indexBadge, key, status);
|
|
card.append(header, title, specs);
|
|
|
|
if (storage) {
|
|
card.append(storage);
|
|
}
|
|
|
|
if (devices) {
|
|
card.append(devices);
|
|
}
|
|
|
|
return card;
|
|
};
|
|
|
|
const appendSpec = (list, label, value) => {
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
const term = document.createElement("dt");
|
|
term.textContent = label;
|
|
|
|
const description = document.createElement("dd");
|
|
description.textContent = value;
|
|
|
|
list.append(term, description);
|
|
};
|
|
|
|
const buildChipGroup = (label, items) => {
|
|
if (items.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const group = document.createElement("div");
|
|
group.classList.add("workstation-card__group");
|
|
|
|
const title = document.createElement("p");
|
|
title.classList.add("workstation-card__group-title");
|
|
title.textContent = label;
|
|
|
|
const chips = document.createElement("div");
|
|
chips.classList.add("workstation-card__chips");
|
|
chips.append(
|
|
...items.map((item) => {
|
|
const chip = document.createElement("span");
|
|
chip.textContent = item;
|
|
return chip;
|
|
}),
|
|
);
|
|
|
|
group.append(title, chips);
|
|
return group;
|
|
};
|
|
|
|
const formatStorage = (storage) => {
|
|
const parts = [storage.capacity, storage.name, storage.type].filter(Boolean);
|
|
return parts.join(" · ");
|
|
};
|