[object Object]

← back to Wallco Live Viewer

viewer: state filter (All/Published/Staged/Removed/Awaiting DB) + per-state counts in header; select-all scoped to visible

f1c90e224cdf92a7fd5105a59da71d1e51ca4955 · 2026-06-09 12:07:15 -0700 · Steve Abrams

Files touched

Diff

commit f1c90e224cdf92a7fd5105a59da71d1e51ca4955
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jun 9 12:07:15 2026 -0700

    viewer: state filter (All/Published/Staged/Removed/Awaiting DB) + per-state counts in header; select-all scoped to visible
---
 server.js | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/server.js b/server.js
index 4a69008..9c5869e 100644
--- a/server.js
+++ b/server.js
@@ -182,6 +182,15 @@ main{padding:16px 18px}
  </div>
  <span class="spacer"></span>
  <div class="ctrl"><label><input type="checkbox" id="selall"> select all</label></div>
+ <div class="ctrl">view
+  <select id="view">
+   <option value="all">All</option>
+   <option value="pub">Published</option>
+   <option value="unpub">Staged</option>
+   <option value="gone">Removed</option>
+   <option value="norow">Awaiting DB</option>
+  </select>
+ </div>
  <div class="ctrl">sort
   <select id="sort">
    <option value="newest">Newest</option>
@@ -200,10 +209,13 @@ main{padding:16px 18px}
 const grid=document.getElementById('grid'), gEmpty=document.getElementById('empty');
 let seen=new Set(), first=true, last=[], sel=new Set(), states={};
 const LS=k=>localStorage.getItem('wlv:'+k), setLS=(k,v)=>localStorage.setItem('wlv:'+k,v);
-const colsEl=document.getElementById('cols'), sortEl=document.getElementById('sort');
-colsEl.value=LS('cols')||5; sortEl.value=LS('sort')||'newest';
+const colsEl=document.getElementById('cols'), sortEl=document.getElementById('sort'), viewEl=document.getElementById('view');
+colsEl.value=LS('cols')||5; sortEl.value=LS('sort')||'newest'; viewEl.value=LS('view')||'all';
 function applyCols(){document.documentElement.style.setProperty('--cols',colsEl.value);setLS('cols',colsEl.value);}
 colsEl.oninput=applyCols; sortEl.onchange=()=>{setLS('sort',sortEl.value);render(last);}; applyCols();
+viewEl.onchange=()=>{setLS('view',viewEl.value);render(last);};
+function stateOf(d){return states[d.dbId]||d.state||'norow';}
+function viewFilter(items){const v=viewEl.value;return v==='all'?items:items.filter(d=>stateOf(d)===v);}
 function fmt(ms){return new Date(ms).toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit',second:'2-digit'});}
 function toast(msg,cls){const t=document.createElement('div');t.className='toast '+(cls||'');t.textContent=msg;
  document.getElementById('toasts').appendChild(t);setTimeout(()=>t.remove(),6000);}
@@ -267,12 +279,19 @@ function syncBulk(){const b=document.getElementById('bulk');b.classList.toggle('
 function togglePick(cb,id){cb.checked?sel.add(id):sel.delete(id);syncBulk();
  cb.closest('.card').classList.toggle('sel',cb.checked);}
 document.getElementById('selall').onchange=function(){
- if(this.checked){last.forEach(d=>{if(d.dbId)sel.add(d.dbId);});}else sel.clear();
+ if(this.checked){viewFilter(last).forEach(d=>{if(d.dbId)sel.add(d.dbId);});}else sel.clear();
  syncBulk();render(last);};
 
 function render(items){last=items;
- if(!items.length){grid.innerHTML='';gEmpty.style.display='block';return;} gEmpty.style.display='none';
- const sorted=sortItems(items);
+ const visible=viewFilter(items);
+ const cts={pub:0,unpub:0,gone:0,norow:0};items.forEach(d=>cts[stateOf(d)]++);
+ document.getElementById('count').textContent=
+   visible.length+(viewEl.value==='all'?'':'/'+items.length)+' shown · '+
+   cts.pub+' pub · '+cts.unpub+' staged · '+cts.gone+' removed · '+cts.norow+' no-row';
+ if(!visible.length){grid.innerHTML='';gEmpty.style.display='block';
+  gEmpty.textContent=items.length?'Nothing matches this view filter.':'No patterns yet — waiting for the next generator tick…';
+  return;} gEmpty.style.display='none';
+ const sorted=sortItems(visible);
  grid.innerHTML=sorted.map(d=>{
    const isNew=!first&&!seen.has(d.file);
    const id=d.dbId;
@@ -307,7 +326,6 @@ async function tick(){
   const st=document.getElementById('status'),tx=document.getElementById('statustxt'),dot=st.querySelector('.dot');
   if(d.live&&d.live.generating){dot.className='dot live';tx.textContent='generating now…';}
   else{dot.className='dot idle';tx.textContent='idle (cron armed)';}
-  document.getElementById('count').textContent=d.items.length+' patterns';
   document.getElementById('latest').textContent=d.items.length?('latest '+fmt(d.items[0].created)):'—';
   render(d.items);
  }catch(e){document.getElementById('statustxt').textContent='offline';}

← 7a2ef4e live viewer: full per-SKU action suite (publish/unpublish/re  ·  back to Wallco Live Viewer  ·  viewer: documented settlement-override publish path 97cff8e →