[object Object]

← back to Rentv

5x sweep 1: cap CRM render at 400 rows (was rendering all 5,013 into the DOM every render — slow paint + re-sort, exhausted the click-through browser); search/chips/sort narrow to find any contact

34e4fb84539fd329cdd3e8fa28ae2a77997f8a3e · 2026-08-12 18:57:48 -0700 · Steve Abrams

Files touched

Diff

commit 34e4fb84539fd329cdd3e8fa28ae2a77997f8a3e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 12 18:57:48 2026 -0700

    5x sweep 1: cap CRM render at 400 rows (was rendering all 5,013 into the DOM every render — slow paint + re-sort, exhausted the click-through browser); search/chips/sort narrow to find any contact
---
 public/crm.html | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/public/crm.html b/public/crm.html
index c949b847..ec9a4c91 100644
--- a/public/crm.html
+++ b/public/crm.html
@@ -400,6 +400,7 @@ async function render(){
   document.querySelectorAll('#modeToggle button').forEach(b=>b.classList.toggle('on',b.dataset.mode===S.mode));
   const {rows,hint}=await currentRows();
   const sorted=sortRows(rows);
+  const RENDER_CAP=400; const view=sorted.slice(0,RENDER_CAP); // cap DOM rows — search/chips/sort narrow to find anyone (5k-row render was slow)
   const content=document.querySelector('.content');
   content.classList.toggle('grid', S.mode==='grid');
   content.classList.toggle('tablemode', S.mode==='table');
@@ -408,9 +409,11 @@ async function render(){
     ? `${sorted.length.toLocaleString()} match${sorted.length===1?'':'es'} · ${typeLabel(S.type)} (registry search)`
     : `${sorted.length.toLocaleString()} of ${Number(DATA.counts[S.type]??DATA.counts.all??0).toLocaleString()} · ${S.type==='all'?'all contacts':typeLabel(S.type)}`;
   const npeople=sorted.filter(liPerson).length, nfirm=sorted.filter(c=>!liPerson(c)&&c.li_firm).length;
-  if(npeople||nfirm){ let extra=''; if(npeople) extra+=` · <span style="color:#8affc0;font-weight:800">🟢 ${npeople.toLocaleString()} you know</span>`; if(nfirm) extra+=` · <span style="color:#6fb1ff;font-weight:800">🏢 ${nfirm.toLocaleString()} at firms you follow</span>`; $('countline').innerHTML = esc($('countline').textContent)+extra; }
+  let capNote = sorted.length>RENDER_CAP ? ` · <span style="color:#c9a04a;font-weight:700">showing first ${RENDER_CAP} — search/filter to narrow</span>` : '';
+  if(npeople||nfirm){ let extra=''; if(npeople) extra+=` · <span style="color:#8affc0;font-weight:800">🟢 ${npeople.toLocaleString()} you know</span>`; if(nfirm) extra+=` · <span style="color:#6fb1ff;font-weight:800">🏢 ${nfirm.toLocaleString()} at firms you follow</span>`; capNote+=extra; }
+  if(capNote) $('countline').innerHTML = esc($('countline').textContent)+capNote;
   if(S.mode==='table'){
-    $('rows').innerHTML = sorted.length ? tableHTML(sorted) : (hint?'':'<div class="empty">No contacts match.</div>');
+    $('rows').innerHTML = view.length ? tableHTML(view) : (hint?'':'<div class="empty">No contacts match.</div>');
     $('rows').querySelectorAll('.tbl thead th[data-col]').forEach(th=>th.onclick=ev=>{
       if(ev.target.classList.contains('rsz')) return;            // clicking the resize handle isn't a sort
       const k=th.dataset.col; if(!k) return;
@@ -431,7 +434,7 @@ async function render(){
     $('rows').querySelectorAll('.tbl tbody tr').forEach(el=>el.onclick=()=>openDetail(el.dataset.id, sorted));
     $('rows').querySelectorAll('.xref[data-xref]').forEach(b=>b.onclick=e=>{ e.stopPropagation(); $('q').value=b.dataset.xref; S.q=b.dataset.xref; S.type='all'; document.querySelectorAll('#rail .chip').forEach(x=>x.classList.toggle('on',x.dataset.type==='all')); render(); });
   } else {
-    $('rows').innerHTML = sorted.length ? sorted.map(rowHTML).join('') : (hint?'':'<div class="empty">No contacts match.</div>');
+    $('rows').innerHTML = view.length ? view.map(rowHTML).join('') : (hint?'':'<div class="empty">No contacts match.</div>');
     document.querySelectorAll('#rows .row').forEach(el=>el.onclick=()=>openDetail(el.dataset.id, sorted));
   }
 }

← 530cac52 crm: harden green-highlight to admin credential only — requi  ·  back to Rentv  ·  5x sweep 2: 20s server-side cache for /api/crm (was rebuildi f356373e →