[object Object]

← back to Approvals Viewer

approvals-viewer: implement openAudit() — Audit All button was a dead handler

c9833a1b4ed6cfcff403b2a3134434b18462f108 · 2026-09-14 13:58:24 -0700 · Steve

The "🔍 Audit All" button called openAudit(), which was defined nowhere
(confirmed live: PAGEERROR "openAudit is not defined" on click). Add a
read-only full-queue overlay that renders every loaded memo at once
(chip/date/rating/title/file + collapsible body via <details>), reusing
md()/fmtDate() and card styles. Esc or ✕ closes; swiper keys are
suppressed while open so arrow-keys can't fire decisions behind it.
Also add the missing .b-audit style. No new writes — purely client-side.

Verified in Chrome: typeof openAudit === 'function', overlay shows all 77
items, memo bodies expand, Esc closes, swiper state restored, no pageerror.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7mfnaSD5EB3DGZcaamU8A

Files touched

Diff

commit c9833a1b4ed6cfcff403b2a3134434b18462f108
Author: Steve <steve@designerwallcoverings.com>
Date:   Mon Sep 14 13:58:24 2026 -0700

    approvals-viewer: implement openAudit() — Audit All button was a dead handler
    
    The "🔍 Audit All" button called openAudit(), which was defined nowhere
    (confirmed live: PAGEERROR "openAudit is not defined" on click). Add a
    read-only full-queue overlay that renders every loaded memo at once
    (chip/date/rating/title/file + collapsible body via <details>), reusing
    md()/fmtDate() and card styles. Esc or ✕ closes; swiper keys are
    suppressed while open so arrow-keys can't fire decisions behind it.
    Also add the missing .b-audit style. No new writes — purely client-side.
    
    Verified in Chrome: typeof openAudit === 'function', overlay shows all 77
    items, memo bodies expand, Esc closes, swiper state restored, no pageerror.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01X7mfnaSD5EB3DGZcaamU8A
---
 public/index.html | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/public/index.html b/public/index.html
index 57b4485..d5752ed 100644
--- a/public/index.html
+++ b/public/index.html
@@ -57,6 +57,13 @@ button{border:0;border-radius:12px;padding:14px 22px;font-size:16px;font-weight:
 .hint{color:var(--mut);font-size:12px;text-align:center;margin-top:8px}
 .done{text-align:center;padding:60px 20px}.done h2{font-size:26px}
 .kbd{background:#23262f;border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-size:12px}
+/* Audit All — read-only full-queue overlay */
+.b-audit{background:#23262f;border:1px solid var(--line);color:var(--ink);min-width:auto;padding:5px 10px;font-size:13px;font-weight:500;border-radius:8px}
+.audit-ov{position:fixed;inset:0;background:var(--bg);z-index:20;display:none;overflow:auto}
+.audit-head{position:sticky;top:0;background:var(--bg);border-bottom:1px solid var(--line);padding:12px 16px;display:flex;align-items:center;justify-content:space-between;gap:10px;z-index:1}
+.audit-list{max-width:860px;margin:0 auto;padding:18px 16px 80px;display:flex;flex-direction:column;gap:14px}
+.audit-card .body{max-height:40vh}
+.audit-card summary{cursor:pointer;color:#3ea6ff;font-size:13px;margin-top:8px;list-style:none}
 </style>  <link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
 </head><body>
 <header>
@@ -70,6 +77,7 @@ button{border:0;border-radius:12px;padding:14px 22px;font-size:16px;font-weight:
    <option value=category>🗂 By Category</option>
    <option value=security>🔴 Security First</option>
  </select>
+ <button class=b-audit onclick=openAudit() title="Audit the full queue at once (read-only)">🔍 Audit All</button>
 </header>
 <main id=main><div class=card><div class=body>Loading…</div></div></main>
 <div class=actions id=actions style=display:flex>
@@ -79,7 +87,7 @@ button{border:0;border-radius:12px;padding:14px 22px;font-size:16px;font-weight:
  <button class=b-ok  onclick="decide('approve')">✅ Approve <span class=kbd>→</span></button>
 </div>
 <script>
-let memos=[],i=0,total=0,tally={approve:0,reject:0,defer:0},lastAction=null,currentSort='mtime';
+let memos=[],i=0,total=0,tally={approve:0,reject:0,defer:0},lastAction=null,currentSort='mtime',auditOpen=false;
 function md(s){
  s=s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
  s=s.replace(/```([\s\S]*?)```/g,(m,c)=>'<pre>'+c+'</pre>');
@@ -95,6 +103,26 @@ function md(s){
  return s;}
 function fmtDate(iso){return new Date(iso).toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});}
 
+// Audit All — render the WHOLE loaded queue at once, read-only (no decision writes).
+// memos[] is already fetched client-side, so this is a pure in-page view; toggling.
+function openAudit(){
+ if(auditOpen)return closeAudit();
+ auditOpen=true;
+ let ov=document.getElementById('auditOv');
+ if(!ov){ov=document.createElement('div');ov.id='auditOv';ov.className='audit-ov';document.body.appendChild(ov);}
+ const rows=memos.map(x=>{
+   const rb=x.rating>0?'<span class=rating-badge>'+x.rating+'★</span>':'';
+   return '<div class="card audit-card"><div><span class=chip>'+x.category.label+'</span><span class=when>🕓 '+fmtDate(x.mtime)+'</span>'+rb+'</div>'
+     +'<h1 class=title>'+x.title.replace(/</g,'&lt;')+'</h1><div class=file>'+x.file+'</div>'
+     +'<details><summary>▸ Show memo</summary><div class=body>'+md(x.body)+'</div></details></div>';
+ }).join('');
+ ov.innerHTML='<div class=audit-head><strong>🔍 Audit — full queue ('+memos.length+') · read-only</strong>'
+   +'<button class=b-audit onclick=closeAudit() title="Close (Esc)">✕ Close</button></div>'
+   +'<div class=audit-list>'+(memos.length?rows:'<p style="color:var(--mut);padding:24px">Queue is empty — nothing to audit.</p>')+'</div>';
+ ov.scrollTop=0;ov.style.display='block';
+}
+function closeAudit(){auditOpen=false;const ov=document.getElementById('auditOv');if(ov)ov.style.display='none';}
+
 function starsHtml(file,currentRating){
  let h='<div class=stars>';
  for(let s=1;s<=5;s++){
@@ -146,6 +174,7 @@ async function undo(){
 document.getElementById('undo').onclick=undo;
 document.getElementById('sortSel').onchange=function(){currentSort=this.value;load();};
 addEventListener('keydown',e=>{
+ if(auditOpen){if(e.key==='Escape')closeAudit();return;}
  if(i>=memos.length)return;
  if(e.key==='ArrowRight'||e.key==='y')decide('approve');
  else if(e.key==='ArrowLeft'||e.key==='n')decide('reject');

← c9cbd5f TK-11685: approval-time freshness re-check guard (read-only,  ·  back to Approvals Viewer  ·  (newest)