← back to Rentv
RENTV closings+deals editors: drill-down on every datum — badge→type, txn badge→txn, location & parties→search filters (href-everything rule), v0.20.1 — TK-10255
dbc79b26c1d1b761b541aa9be707442e30931219 · 2026-08-05 14:47:32 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M package-lock.jsonM package.jsonM public/closings.htmlM public/deals.html
Diff
commit dbc79b26c1d1b761b541aa9be707442e30931219
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Aug 5 14:47:32 2026 -0700
RENTV closings+deals editors: drill-down on every datum — badge→type, txn badge→txn, location & parties→search filters (href-everything rule), v0.20.1 — TK-10255
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
package-lock.json | 4 ++--
package.json | 2 +-
public/closings.html | 12 ++++++++++--
public/deals.html | 17 +++++++++++++----
4 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 084a89ac..70719ec0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "rentv",
- "version": "0.20.0",
+ "version": "0.20.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rentv",
- "version": "0.20.0",
+ "version": "0.20.1",
"dependencies": {
"express": "^4.21.2",
"pg": "^8.22.0"
diff --git a/package.json b/package.json
index e99df0b5..4410cd46 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "rentv",
- "version": "0.20.0",
+ "version": "0.20.1",
"private": true,
"main": "server.js",
"scripts": {
diff --git a/public/closings.html b/public/closings.html
index c670c503..c7dea5a6 100644
--- a/public/closings.html
+++ b/public/closings.html
@@ -64,6 +64,7 @@
.card .meta.parties{font-size:11px;gap:3px 8px}
.card .meta.parties span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}
.card .meta.parties .party{cursor:pointer;border-radius:4px}.card .meta.parties .party:hover{text-decoration:underline;color:var(--red)}
+ .drill{cursor:pointer}.badge.drill:hover{filter:brightness(1.25)}.card .meta .drill:hover{text-decoration:underline;color:var(--red)}
.card .cardfoot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--line)}
.card .more{font-size:12px;font-weight:700;color:var(--red);text-transform:uppercase;letter-spacing:.04em}
.card .acts{display:flex;gap:6px}
@@ -225,7 +226,7 @@ function render(){
<div class="ph" style="${ph}">
<div class="badges">
<span class="badge txn">Closed</span>
- ${d.property_type?`<span class="badge">${esc(d.property_type)}</span>`:''}
+ ${d.property_type?`<span class="badge drill" data-filt="type" data-val="${esc(d.property_type)}" title="Filter by ${esc(d.property_type)}">${esc(d.property_type)}</span>`:''}
${man?'<span class="badge man">Manual</span>':''}
${edited?'<span class="badge edt">Edited</span>':''}
${hidden?'<span class="badge hid">Hidden</span>':''}
@@ -235,7 +236,7 @@ function render(){
</div>
<div class="body">
<div class="addr">${esc(d.address||d.title)}</div>
- ${loc?`<div class="meta"><span>📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
+ ${loc?`<div class="meta"><span class="drill" data-filt="q" data-val="${esc(loc)}" title="Filter by ${esc(loc)}">📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span class="party" data-party="${esc(d.buyer)}" title="Buyer — click to see this party's deals">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span class="party" data-party="${esc(d.seller)}" title="Seller — click to filter">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span class="party" data-party="${esc(d.broker)}" title="Broker — click to filter">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
${(d.address&&d.title)?`<h3>${esc(d.title)}</h3>`:''}
<div class="cardfoot">
@@ -260,6 +261,13 @@ function render(){
$('#grid').querySelectorAll('.party[data-party]').forEach(el=>{
el.onclick=(e)=>{e.stopPropagation();const p=(el.getAttribute('data-party')||'').trim();fQ=p.toLowerCase();$('#q').value=p;render();};
});
+ // Datum drilldown — property-type badge → type filter, location → search (href-everything rule).
+ $('#grid').querySelectorAll('.drill').forEach(el=>{
+ el.onclick=(e)=>{e.stopPropagation();const f=el.dataset.filt,v=(el.dataset.val||'').trim();
+ if(f==='type'){fType=v;pills();}
+ else if(f==='q'){fQ=v.toLowerCase();$('#q').value=v;}
+ render();};
+ });
}
// ── editor modal ──
diff --git a/public/deals.html b/public/deals.html
index 2b4d4928..a20c65a3 100644
--- a/public/deals.html
+++ b/public/deals.html
@@ -63,6 +63,7 @@
.card .meta b{color:var(--ink)}
.card .meta.parties{font-size:11px;gap:3px 8px}
.card .meta.parties span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block}
+ .drill{cursor:pointer}.badge.drill:hover{filter:brightness(1.25)}.card .meta .drill:hover{text-decoration:underline;color:var(--red)}
.card .cardfoot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:10px;border-top:1px solid var(--line)}
.card .more{font-size:12px;font-weight:700;color:var(--red);text-transform:uppercase;letter-spacing:.04em}
.card .acts{display:flex;gap:6px}
@@ -253,8 +254,8 @@ function render(){
return `<div class="card ${hidden?'hid':''} ${man?'man':''}" data-id="${esc(String(d.id))}">
<div class="ph" style="${ph}">
<div class="badges">
- ${d.txn_type?`<span class="badge txn">${esc(d.txn_type)}</span>`:'<span class="badge txn">Deal</span>'}
- ${d.property_type?`<span class="badge">${esc(d.property_type)}</span>`:''}
+ ${d.txn_type?`<span class="badge txn drill" data-filt="txn" data-val="${esc(d.txn_type)}" title="Filter by ${esc(d.txn_type)}">${esc(d.txn_type)}</span>`:'<span class="badge txn">Deal</span>'}
+ ${d.property_type?`<span class="badge drill" data-filt="type" data-val="${esc(d.property_type)}" title="Filter by ${esc(d.property_type)}">${esc(d.property_type)}</span>`:''}
${man?'<span class="badge man">Manual</span>':''}
${edited?'<span class="badge edt">Edited</span>':''}
${hidden?'<span class="badge hid">Hidden</span>':''}
@@ -264,8 +265,8 @@ function render(){
</div>
<div class="body">
<div class="addr">${esc(d.address||d.title)}</div>
- ${loc?`<div class="meta"><span>📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
- ${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span title="Buyer">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span title="Seller">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span title="Broker">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
+ ${loc?`<div class="meta"><span class="drill" data-filt="q" data-val="${esc(loc)}" title="Filter by ${esc(loc)}">📍 <b>${esc(loc)}</b></span>${d.size_label?`<span>📐 ${esc(d.size_label)}</span>`:''}${d.year_built?`<span>🏗 ${esc(d.year_built)}</span>`:''}</div>`:''}
+ ${(d.buyer||d.seller||d.broker)?`<div class="meta parties">${d.buyer?`<span class="drill" data-filt="q" data-val="${esc(d.buyer)}" title="Buyer — filter by ${esc(d.buyer)}">🟢 <b>${esc(d.buyer)}</b></span>`:''}${d.seller?`<span class="drill" data-filt="q" data-val="${esc(d.seller)}" title="Seller — filter by ${esc(d.seller)}">🔴 ${esc(d.seller)}</span>`:''}${d.broker?`<span class="drill" data-filt="q" data-val="${esc(d.broker)}" title="Broker — filter by ${esc(d.broker)}">🤝 ${esc(d.broker)}</span>`:''}</div>`:''}
${(d.address&&d.title)?`<h3>${esc(d.title)}</h3>`:''}
<div class="cardfoot">
${story}
@@ -286,6 +287,14 @@ function render(){
if(act==='restore')return restoreDeal(id);
};
});
+ // Datum drilldown — txn badge → txn filter, property badge → type filter, location/parties → search (href-everything rule).
+ $('#grid').querySelectorAll('.drill').forEach(el=>{
+ el.onclick=(e)=>{e.stopPropagation();const f=el.dataset.filt,v=(el.dataset.val||'').trim();
+ if(f==='txn'){fTxn=v;renderPills();}
+ else if(f==='type'){fType=v;renderPills();}
+ else if(f==='q'){fQ=v.toLowerCase();$('#q').value=v;}
+ render();};
+ });
}
// ── editor modal ──
← 1b924b35 closings: FIX enrichment merge — feed deals now gap-fill buy
·
back to Rentv
·
PR intel: tighten LinkedIn slug guard to require surname (Co 676a7464 →