Review cards sort alphabetically within each section

Same reasoning as the Titles page: csv order is extraction order,
which reads as random. Matches, Editions, and Merges each sort by
title (case-insensitive); the sort is stable within a payload so the
keyboard cursor doesn't jump between polls.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jXZFSTZQKzAC8fqpWSz9g
This commit is contained in:
Eric Wagoner
2026-08-05 19:20:15 -04:00
co-authored by Claude Fable 5
parent 90e75daf98
commit 42ef34c3a7
4 changed files with 32 additions and 4 deletions
+8 -3
View File
@@ -141,17 +141,22 @@ function render() {
: `<p class="next">Next: run <b>diff</b> from the <a href="/">pipeline</a>, then check the <a href="/queue">queue</a>.</p>`}
</div>`;
}
// csv order is extraction order — alphabetize so a long session has a
// findable, predictable shape (stable within a payload, so the keyboard
// cursor stays put between polls)
const byTitle = (a, b) =>
a.title_raw.localeCompare(b.title_raw, undefined, { sensitivity: "base" });
if (s.pending.length) {
html += `<h2 id="matches">Matches <span class="count">— pick the game each photo shows</span></h2>`;
html += s.pending.map(matchCard).join("");
html += [...s.pending].sort(byTitle).map(matchCard).join("");
}
if (s.versions.length) {
html += `<h2 id="editions">Editions <span class="count">— optional pass, never blocks uploads</span></h2>`;
html += s.versions.map(versionCard).join("");
html += [...s.versions].sort(byTitle).map(versionCard).join("");
}
if (s.merges.length) {
html += `<h2 id="merges">Merges <span class="count">— duplicate reads folded into one game; veto if wrong</span></h2>`;
html += s.merges.map(mg => `
html += [...s.merges].sort(byTitle).map(mg => `
<section class="card merge actionable" data-kind="merge"
data-rowix="${mg.row_ix}"
data-title="${esc(mg.title_raw)}" data-photos="${esc(mg.source_photos)}">