diff --git a/papers/cli.mjs b/papers/cli.mjs index 5fa8c2b18c..598cf65f2b 100755 --- a/papers/cli.mjs +++ b/papers/cli.mjs @@ -502,8 +502,9 @@ function updateIndex(entries) { const createdStr = p.created ? fmtDate(p.created) : ""; const revStr = p.revisions > 0 ? `r${p.revisions}` : ""; const tKey = translationKey(p.dir); + const updatedISO = p.mtime.toISOString(); papersHtml += ` -
+
${detail}
${createdStr}${revStr}${fmtTime(p.mtime)}
diff --git a/system/public/papers.aesthetic.computer/index.html b/system/public/papers.aesthetic.computer/index.html index 20930f6c3d..d7d3991ccd 100644 --- a/system/public/papers.aesthetic.computer/index.html +++ b/system/public/papers.aesthetic.computer/index.html @@ -157,6 +157,29 @@ .sub { color: var(--dim); font-size: 0.8em; margin-bottom: 0.6em; } .sub a { color: var(--cyan); text-decoration: none; } + /* Sort bar */ + .sort-bar { + display: flex; + gap: 4px; + margin-bottom: 0.8em; + font-size: 11px; + flex-wrap: wrap; + } + .sort-btn { + cursor: pointer; + background: none; + border: 1px solid var(--box-border); + color: var(--dim); + font-family: inherit; + font-size: inherit; + padding: 3px 10px; + border-radius: 12px; + transition: all 0.15s; + user-select: none; + } + .sort-btn:hover { border-color: var(--pink); color: var(--text); } + .sort-btn.active { background: var(--pink); color: var(--bg); border-color: var(--pink); font-weight: 600; } + /* Papers grid */ .papers-grid { display: grid; @@ -427,147 +450,153 @@ +
+ + + +
+ -
+
A Mobile-First Runtime for Creative Computing · arXiv 5pp
03/21r2Mar 27 08:38
-
+
A Minimal Lisp for Generative Art on a Social Platform · arXiv 6pp
03/21r2Mar 27 08:38
-
+
Laptop Orchestras, PLOrk Heritage, and Aesthetic Computer · arXiv
03/21r2Mar 27 08:38
-
+
A Bare-Metal Creative Computing Operating System · arXiv 5pp
03/21r2Mar 27 08:38
-
+
Processing at the Core of the Piece API · arXiv 7pp
03/21r2Mar 27 08:38
-
+
Funding, Burnout, and Survival in Open-Source Creative Computing · arXiv 5pp
03/27r1Mar 27 08:38
-
+
The Piece as a Unit of Creative Cognition · arXiv 4pp
03/21r2Mar 27 08:38
-
+
From Keyboard Toy to System Front Door · arXiv 5pp
03/21r2Mar 27 08:38
-
+
Goodiepalian Approaches in Aesthetic Computer · arXiv 5pp
03/21r2Mar 27 08:38
-
+
Drawing, Singing, and the Graphic Score as Viral Form · arXiv 4pp
03/21r2Mar 27 08:38
-
+
Platform Hegemony, Critique-as-Content, and Anti-Environments · arXiv 5pp
03/21r2Mar 27 08:38
-
+
Dormant Paths, Evolutionary Branches, and Abandoned Approaches · arXiv 4pp
03/21r2Mar 27 08:38
-
+
Oral Tradition Meets the Browser Keyboard · arXiv
03/21r2Mar 27 08:38
-
+
Tracing the Evolution of AC Through Its Git History · arXiv 3pp · interactive timeline
03/21r2Mar 27 08:38
-
+
Who Uses Aesthetic Computer and What Do They Make? · arXiv 4pp
03/21r2Mar 27 08:38
-
+
118 Built-ins in 12 Categories · arXiv 4pp
03/21r2Mar 27 08:38
-
+
Diversity and Inclusion in AC Paper Citations · 4pp
03/21r2Mar 27 08:38
-
+ -
+
03/20r2Mar 27 08:38
-
+
03/21r2Mar 27 08:38
-
+ -
+
03/27r1Mar 27 08:38
-
+
03/21r2Mar 27 08:38
-
+
03/21r2Mar 27 08:38
@@ -959,25 +988,55 @@ }); }); - // Sort papers by hit count (most read first) and show counts + // === SORTING === + let hitTotals = {}; + + function sortPapers(mode) { + const container = document.querySelector('.p')?.parentElement; + if (!container) return; + const papers = [...container.querySelectorAll('.p')]; + + papers.sort((a, b) => { + if (mode === 'hits') { + return (hitTotals[b.dataset.paperId] || 0) - (hitTotals[a.dataset.paperId] || 0); + } else if (mode === 'updated') { + const ta = a.dataset.updated ? new Date(a.dataset.updated).getTime() : 0; + const tb = b.dataset.updated ? new Date(b.dataset.updated).getTime() : 0; + return tb - ta; + } else if (mode === 'created') { + const ca = a.dataset.created || '0'; + const cb = b.dataset.created || '0'; + return cb.localeCompare(ca); + } + return 0; + }); + for (const p of papers) container.appendChild(p); + } + + // Sort bar clicks + document.querySelectorAll('.sort-btn').forEach(btn => { + btn.addEventListener('click', () => { + document.querySelectorAll('.sort-btn').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + sortPapers(btn.dataset.sort); + }); + }); + + // Fetch hit counts, inject into meta rows, then apply default sort (async () => { try { const res = await fetch('https://aesthetic.computer/api/paper-hit'); if (!res.ok) return; const { stats } = await res.json(); - // Aggregate hits per paper (combine pdf + cards formats) - const totals = {}; for (const s of stats) { const id = s._id.paper; - totals[id] = (totals[id] || 0) + s.count; + hitTotals[id] = (hitTotals[id] || 0) + s.count; } const container = document.querySelector('.p')?.parentElement; if (!container) return; - const papers = [...container.querySelectorAll('.p')]; - // Inject hit counts into meta rows - for (const p of papers) { + for (const p of container.querySelectorAll('.p')) { const id = p.dataset.paperId; - const count = totals[id] || 0; + const count = hitTotals[id] || 0; const metaRow = p.querySelector('.meta-row'); if (metaRow && count > 0) { const span = document.createElement('span'); @@ -987,13 +1046,8 @@ metaRow.prepend(span); } } - // Sort descending by hits - papers.sort((a, b) => { - const ha = totals[a.dataset.paperId] || 0; - const hb = totals[b.dataset.paperId] || 0; - return hb - ha; - }); - for (const p of papers) container.appendChild(p); + // Apply default sort (top hits) + sortPapers('hits'); } catch {} })();