fix(dashboard): preserve q-history details open state on SSE-triggered renderQuestions

When a question_added or question_resolved SSE event fires, the handler
calls renderQuestions() directly — bypassing the snapshotOpenDetails /
restoreOpenDetails pair that refreshState wraps around it. This caused
the answered-history <details> (data-restore-key="q-history") to
collapse every time a question arrived or was resolved while the
operator had it open.

Fix: call snapshotOpenDetails() at the start of renderQuestions() and
restoreOpenDetails() at the end. The double-restore in the refreshState
path is harmless — re-opening an already-open <details> is idempotent,
and restoreOpenDetails is a no-op when the snapshot set is empty.
This commit is contained in:
iris 2026-06-05 11:39:35 +02:00 committed by mara
commit 6c6d6f67e7

View file

@ -1564,6 +1564,13 @@ window.marked = marked;
// no-op when the section is missing. `question_added` /
// `question_resolved` SSE events route through here.
if (!root) return;
// Snapshot open <details> state before wiping the DOM so SSE-triggered
// calls (applyQuestionAdded / applyQuestionResolved) preserve it just
// as well as the full refreshState path. The double-restore that happens
// when renderQuestions is called from inside refreshState is harmless —
// restoreOpenDetails is a no-op when the set is empty, and re-opening an
// already-open <details> is idempotent.
const openDetails = snapshotOpenDetails();
root.replaceChildren();
const fmt = (n) => new Date(n * 1000).toISOString().replace('T', ' ').slice(0, 19);
const allPending = questionsState.pending;
@ -1741,6 +1748,7 @@ window.marked = marked;
details.append(hul);
root.append(details);
}
restoreOpenDetails(openDetails);
}
// Format a remaining-seconds count as the `⏳ …` TTL chip text on a