[object Object]

← back to Ticket System

board: add Non-DW nav tab (filters out DW wallcoverings + vendor lines)

1e7ae145aa0593f72c59d62bdae462f8cca7bfd6 · 2026-09-17 09:53:52 -0700 · Steve Abrams

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

Files touched

Diff

commit 1e7ae145aa0593f72c59d62bdae462f8cca7bfd6
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Sep 17 09:53:52 2026 -0700

    board: add Non-DW nav tab (filters out DW wallcoverings + vendor lines)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01TmvM611X4duoLdp1cFmpy2
---
 board.html | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/board.html b/board.html
index 8b8bbb82..2c849b80 100644
--- a/board.html
+++ b/board.html
@@ -118,7 +118,7 @@
 </style></head><body>
 <div class="stickytop">
 <div class="topnav">
-  <nav class="globalnav" aria-label="Fleet viewer"><button data-section="all">All</button><button data-section="open">Open</button><button data-section="blocked">Blocked</button><button data-section="doing">Doing</button><button data-section="agents">Agents</button><button data-section="skills">Skills</button></nav>
+  <nav class="globalnav" aria-label="Fleet viewer"><button data-section="all">All</button><button data-section="open">Open</button><button data-section="blocked">Blocked</button><button data-section="doing">Doing</button><button data-section="nondw" title="Tickets NOT related to Designer Wallcoverings">Non-DW</button><button data-section="agents">Agents</button><button data-section="skills">Skills</button></nav>
   <button id="navPosBtn" class="navpos" title="Move nav bar below the toolbar" aria-label="Toggle nav bar position">⤓ Nav</button>
 </div>
 <header>
@@ -227,7 +227,7 @@ const LS=(k,d)=>{try{return JSON.parse(localStorage.getItem(k))??d}catch(e){retu
 let DATA=[], AGENTS=[], SKILLS=[], q='';
 const URLSTATE=new URLSearchParams(location.search);
 let SECTION=URLSTATE.get('section')||LS('tkSection','blocked'), LAYOUT=URLSTATE.get('layout')||LS('tkLayout','grid');
-if(!['all','open','blocked','doing','agents','skills'].includes(SECTION))SECTION='blocked';if(!['grid','kv'].includes(LAYOUT))LAYOUT='grid';
+if(!['all','open','blocked','doing','agents','skills','nondw'].includes(SECTION))SECTION='blocked';if(!['grid','kv'].includes(LAYOUT))LAYOUT='grid';
 let CATALOG_SORT=LS('tkCatalogSort','name'), CATALOG_DIR=LS('tkCatalogDir',1), CATALOG_COLS=LS('tkCatalogCols',4);
 let sortKey=LS('tkSortKey','created_at'), sortDir=LS('tkSortDir',-1); if(!CK.includes(sortKey))sortKey='created_at';
 let VIEW=LS('tkView','task');
@@ -282,7 +282,17 @@ function renderHead(){
   }
   $('#selall').onclick=e=>{const on=e.target.checked;const vis=DATA.filter(match);if(on)for(const t of vis)SEL.add(t.id);else for(const t of vis)SEL.delete(t.id);render();syncBar();};
 }
-function match(t){if(VIEW!=='all'&&(t.kind||'task')!==VIEW)return false;if(['open','blocked','doing'].includes(SECTION)&&t.status!==SECTION)return false;if(!q)return true;
+// ── DW (Designer Wallcoverings) scope detector — EDIT the sets/patterns below to reclassify ──
+// DW = every dw-* project, the wallcovering sister-sites, AND all DW vendor lines.
+// The "Non-DW" nav tab shows every ticket where isDW(t) is false (any status).
+// To move a project: add it to DW_DENY (force NON-DW) or DW_EXTRA (force DW), or add a vendor token.
+const DW_DENY=new Set(['wallpapersback','abramsego','pattern-vault']); // look wallpaper-ish but are SEPARATE businesses
+const DW_RE=/designerwallcoverings|designer-wallcoverings|dw_unified|(^|[^a-z])dw($|[^a-z])|(^|[^a-z])dw-/i;
+const DW_KW=/wallcover|wallpaper/i;                                    // DW wallcovering sister-sites (architectural/contract/hospitality/goldleaf)
+const DW_VENDOR=/(^|[^a-z])(sanderson|stroheim|muralsource|kravet|greenland|malibu|gracie|astek|fabricut|groundworks|rebel-walls|thibaut|schumacher|koroseal|scalamandre|maya-?romanoff|winfield|phillip-?jeffries|brewster|wallquest|carnegie|designtex|momentum|versa|elitis|fromental|fentucci|hollywood|novasuede|philipperomano|mdc)($|[^a-z])/i;
+const DW_EXTRA=new Set(['norma','greenland-onboard','sample-followup','sample-followup-sweep','interiordesignershowroom','marketing-command-center','all-designerwallcoverings','consulting-designerwallcoverings-com','mfr-review-viewer','mfr-review-viewer-corruption','designersalesreps','vendor-command-center','discontinued-agent']);
+function isDW(t){const p=String(t.project||'').toLowerCase().trim();if(!p||DW_DENY.has(p))return false;return DW_EXTRA.has(p)||DW_RE.test(p)||DW_VENDOR.test(p)||DW_KW.test(p);}
+function match(t){if(VIEW!=='all'&&(t.kind||'task')!==VIEW)return false;if(['open','blocked','doing'].includes(SECTION)&&t.status!==SECTION)return false;if(SECTION==='nondw'&&isDW(t))return false;if(!q)return true;
   // search the FULL thread — every comment (note/win/challenge/cody incl.) + every action — not just lastText
   const thread=[...(t.comments||[]).map(c=>c.text),...(t.actions||[]).map(a=>a.text)].join(' ');
   const hay=(t.id+' '+t.title+' '+(t.project||'')+' '+(t.assignee||'')+' '+t.status+' '+(t.kind||'task')+' '+JSON.stringify(t.schedule||{})+' '+thread).toLowerCase();
@@ -354,7 +364,7 @@ function renderCatalog(){
 function syncUrl(){const u=new URL(location.href);u.searchParams.set('section',SECTION);u.searchParams.set('layout',LAYOUT);history.replaceState(null,'',u);}
 function setSection(section){SECTION=section;save('tkSection',SECTION);syncUrl();q='';$('#q').value='';document.querySelectorAll('[data-section]').forEach(b=>b.classList.toggle('on',b.dataset.section===SECTION));render();}
 function initSectionTabs(){
-  const nav=$('.globalnav'),keys=['all','open','blocked','doing','agents','skills'];
+  const nav=$('.globalnav'),keys=['all','open','blocked','doing','nondw','agents','skills'];
   let order=LS('tkSectionOrder',keys).filter(k=>keys.includes(k));for(const k of keys)if(!order.includes(k))order.push(k);
   const apply=()=>{for(const k of order){const b=nav.querySelector(`[data-section="${k}"]`);if(b)nav.appendChild(b);}};apply();
   nav.querySelectorAll('[data-section]').forEach(b=>{b.draggable=true;b.title='Drag to reorder tabs';

← 668b98f6 Record bounded open-ticket monitoring cycle and verified gat  ·  back to Ticket System  ·  Record bounded ticket monitoring and worsening disk evidence f82d1804 →