stabilize dashboard card rendering to avoid constant article reloads
This commit is contained in:
parent
20568d2b3e
commit
c12952d4b2
1 changed files with 37 additions and 14 deletions
51
data.js
51
data.js
|
|
@ -147,16 +147,26 @@ function createCardElement(sim) {
|
||||||
return article;
|
return article;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setTextIfChanged(element, nextValue) {
|
||||||
|
if (!element) return;
|
||||||
|
if (element.textContent !== nextValue) {
|
||||||
|
element.textContent = nextValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateCardElement(card, sim) {
|
function updateCardElement(card, sim) {
|
||||||
card.querySelector('[data-role="title"]').textContent = sim.title;
|
setTextIfChanged(card.querySelector('[data-role="title"]'), sim.title);
|
||||||
card.querySelector('[data-role="idline"]').textContent = `sim-${sim.id} | ${sim.mode} | seed=${sim.seed}`;
|
setTextIfChanged(card.querySelector('[data-role="idline"]'), `sim-${sim.id} | ${sim.mode} | seed=${sim.seed}`);
|
||||||
card.querySelector('[data-role="progress"]').textContent = sim.progress;
|
setTextIfChanged(card.querySelector('[data-role="progress"]'), sim.progress);
|
||||||
card.querySelector('[data-role="scoreboard"]').textContent = sim.scoreboard;
|
setTextIfChanged(card.querySelector('[data-role="scoreboard"]'), sim.scoreboard);
|
||||||
card.querySelector('[data-role="outcome"]').textContent = sim.outcome;
|
setTextIfChanged(card.querySelector('[data-role="outcome"]'), sim.outcome);
|
||||||
|
|
||||||
const pill = card.querySelector('[data-role="pill"]');
|
const pill = card.querySelector('[data-role="pill"]');
|
||||||
pill.className = `pill ${sim.status}`;
|
const nextPillClass = `pill ${sim.status}`;
|
||||||
pill.textContent = sim.status;
|
if (pill.className !== nextPillClass) {
|
||||||
|
pill.className = nextPillClass;
|
||||||
|
}
|
||||||
|
setTextIfChanged(pill, sim.status);
|
||||||
|
|
||||||
if (card.dataset.status !== sim.status) {
|
if (card.dataset.status !== sim.status) {
|
||||||
card.dataset.status = sim.status;
|
card.dataset.status = sim.status;
|
||||||
|
|
@ -169,33 +179,46 @@ function renderDashboard() {
|
||||||
if (!root) return;
|
if (!root) return;
|
||||||
|
|
||||||
if (state.simulations.length === 0) {
|
if (state.simulations.length === 0) {
|
||||||
root.innerHTML = `<div class="empty" id="dashboardEmpty">No simulation instances yet. Create one to start the web simulation flow.</div>`;
|
for (const card of root.querySelectorAll("article.card")) {
|
||||||
|
card.remove();
|
||||||
|
}
|
||||||
|
if (!$("dashboardEmpty")) {
|
||||||
|
root.innerHTML = `<div class="empty" id="dashboardEmpty">No simulation instances yet. Create one to start the web simulation flow.</div>`;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emptyNode = $("dashboardEmpty");
|
||||||
|
if (emptyNode) {
|
||||||
|
emptyNode.remove();
|
||||||
|
}
|
||||||
|
|
||||||
const existingCards = new Map(
|
const existingCards = new Map(
|
||||||
[...root.querySelectorAll("article.card")].map((card) => [Number(card.dataset.id), card]),
|
[...root.querySelectorAll("article.card")].map((card) => [Number(card.dataset.id), card]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const activeIds = new Set(state.simulations.map((sim) => sim.id));
|
const activeIds = new Set(state.simulations.map((sim) => sim.id));
|
||||||
const fragment = document.createDocumentFragment();
|
|
||||||
|
|
||||||
for (const sim of state.simulations) {
|
for (let index = 0; index < state.simulations.length; index += 1) {
|
||||||
|
const sim = state.simulations[index];
|
||||||
let card = existingCards.get(sim.id);
|
let card = existingCards.get(sim.id);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
card = createCardElement(sim);
|
card = createCardElement(sim);
|
||||||
|
root.appendChild(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCardElement(card, sim);
|
updateCardElement(card, sim);
|
||||||
fragment.appendChild(card);
|
|
||||||
|
if (root.children[index] !== card) {
|
||||||
|
root.insertBefore(card, root.children[index] || null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [id, card] of existingCards.entries()) {
|
for (const [id, card] of existingCards.entries()) {
|
||||||
if (!activeIds.has(id) && card.parentElement === root) {
|
if (!activeIds.has(id)) {
|
||||||
card.remove();
|
card.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
root.replaceChildren(fragment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderStats() {
|
function renderStats() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue