← back to Zendesk Chat Analyzer
Add CSV export of current filtered/arranged grid view (client-side, respects columns+filters)
590979c4c5406894cb5e68f1eb278256fabf29ba · 2026-08-11 09:32:26 -0700 · Steve
Files touched
M public/app.jsM public/index.html
Diff
commit 590979c4c5406894cb5e68f1eb278256fabf29ba
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Aug 11 09:32:26 2026 -0700
Add CSV export of current filtered/arranged grid view (client-side, respects columns+filters)
---
public/app.js | 12 ++++++++++++
public/index.html | 1 +
2 files changed, 13 insertions(+)
diff --git a/public/app.js b/public/app.js
index 35126ed..c6b8b70 100644
--- a/public/app.js
+++ b/public/app.js
@@ -240,6 +240,18 @@ document.getElementById('colBtn').onclick=e=>{ e.stopPropagation(); buildColMenu
document.addEventListener('click',()=>document.getElementById('colPop').classList.remove('on'));
document.getElementById('colPop').onclick=e=>e.stopPropagation();
document.getElementById('resetCols').onclick=()=>{ colOrder=DEF_ORDER.slice(); colHidden=new Set(DEF_HIDE); sortKey='ts';sortDir=-1; localStorage.removeItem('zca_cols');localStorage.removeItem('zca_sort'); table(); };
+document.getElementById('exportCsv').onclick=()=>{
+ let r=rows().slice();
+ const q=document.getElementById('search').value.toLowerCase().split(/\s+/).filter(Boolean);
+ if(q.length) r=r.filter(c=>{ const blob=COLDEFS.map(d=>d.p(c)).join(' ').toLowerCase(); return q.every(w=>blob.includes(w)); });
+ const sd=CMAP[sortKey]||CMAP.ts;
+ r.sort((a,b)=>{ let x=sd.p(a),y=sd.p(b); if(typeof x==='string')x=x.toLowerCase(); if(typeof y==='string')y=y.toLowerCase(); return (x>y?1:x<y?-1:0)*sortDir; });
+ const cols=visCols(), esc=v=>{ v=String(v==null?'':v); return /[",\n]/.test(v)?'"'+v.replace(/"/g,'""')+'"':v; };
+ const csv=[cols.map(k=>esc(CMAP[k].l)).join(',')].concat(r.map(c=>cols.map(k=>esc(CMAP[k].p(c))).join(','))).join('\r\n');
+ const a=document.createElement('a'); a.href=URL.createObjectURL(new Blob([csv],{type:'text/csv'}));
+ const f=[FILTER.theme,FILTER.brand,FILTER.country,FILTER.missed?'missed':''].filter(Boolean).join('-')||'all';
+ a.download=`dw-chats-${f}-${r.length}rows.csv`; a.click(); URL.revokeObjectURL(a.href);
+};
document.getElementById('search').oninput=table;
document.getElementById('density').oninput=e=>{ document.querySelectorAll('#tbl td,#tbl th').forEach(td=>td.style.padding=`${e.target.value*.7}px 9px`); };
diff --git a/public/index.html b/public/index.html
index 08dd4da..09be5b4 100644
--- a/public/index.html
+++ b/public/index.html
@@ -155,6 +155,7 @@ a{color:var(--acc);text-decoration:none}a:hover{text-decoration:underline}
<div class="colpop" id="colPop"></div>
</div>
<button id="resetCols">↺ Reset</button>
+ <button id="exportCsv">⭳ Export CSV</button>
<span class="mut" id="tableCount"></span>
</div>
<div class="mut" style="font-size:11px;margin:-4px 0 8px">Tip: click a header to sort · <b>drag a header to reorder</b> · use ▦ Columns to show/hide · choices are saved.</div>
← 0631d5f Clamp /api/recent HOURS to 1h..7d (abuse guard, Cody)
·
back to Zendesk Chat Analyzer
·
Add rule-based sentiment + urgency scoring (/bin/zsh local): d73376a →