← back to Rentv Sheet Enrich
Live console: show Last Modified date+time directly under the Status chip; stamp it on status-pick and drag-drop writes too
95c5ba3a2f45ee69ccd83b60ffb040a192116d34 · 2026-08-13 17:17:09 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 95c5ba3a2f45ee69ccd83b60ffb040a192116d34
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 13 17:17:09 2026 -0700
Live console: show Last Modified date+time directly under the Status chip; stamp it on status-pick and drag-drop writes too
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public_live/index.html | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/public_live/index.html b/public_live/index.html
index 9ecf60b..e840887 100644
--- a/public_live/index.html
+++ b/public_live/index.html
@@ -110,6 +110,7 @@
td.statuscell{cursor:pointer} td.statuscell:hover{background:var(--rowhover)}
.statuschip{display:inline-block;max-width:100%;padding:2px 10px;border-radius:12px;font-size:.92em;font-weight:600;line-height:1.55;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
td.statuscell.empty{color:var(--dim);font-size:.9em}
+ td.statuscell .chipdate{display:block;margin-top:3px;color:var(--dim);font-size:.72em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-variant-numeric:tabular-nums}
.statusmenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:0 12px 34px #000a;padding:5px;min-width:230px;max-height:70vh;overflow:auto}
.statusmenu .smhead{color:var(--dim);font-size:10px;text-transform:uppercase;letter-spacing:.5px;padding:5px 8px 6px}
.smi{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:7px;cursor:pointer;font-size:13px}
@@ -528,6 +529,13 @@ function statusColor(v){ return (STATUS_COLORS&&STATUS_COLORS[v]) || STATUS_DEFA
function txtOn(color){ const m=color.match(/^#([0-9a-f]{6})$/i); if(!m)return '#111'; // hsl fallbacks are light -> dark text
const n=parseInt(m[1],16), r=n>>16, g=(n>>8)&255, b=n&255; return (0.299*r+0.587*g+0.114*b)>150?'#111':'#fff'; }
function isStatusCol(ci){ return STATUS_FIELD && DATA.headers[ci]===STATUS_FIELD; }
+function lmCol(){ return DATA.headers.findIndex(h=>/^last modified$/i.test(String(h).trim())); }
+async function stampLastMod(r){ // write "now" to the row's Last Modified cell (shown under the status chip)
+ const lm=lmCol(); if(lm<0)return null;
+ const ts=new Date().toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});
+ try{ await postWrite(r,lm,ts); DATA.rows[r][lm]=ts; GREENSET.add(r+','+lm); }catch(e){}
+ return ts;
+}
function openStatusPicker(td){
closeStatusPicker();
const r=+td.dataset.r, c=+td.dataset.c, cur=(DATA.rows[r]&&DATA.rows[r][c])||'';
@@ -542,7 +550,7 @@ function openStatusPicker(td){
m.style.top=Math.min(b.bottom+4, window.innerHeight-m.offsetHeight-10)+'px';
m.querySelectorAll('.smi').forEach(el=>el.onclick=async()=>{ const v=el.dataset.v; closeStatusPicker();
try{ const res=await postWrite(r,c,v); if(!res.ok)throw new Error(res.error||'write failed');
- DATA.rows[r][c]=v; if(v)GREENSET.add(r+','+c); render(); setSync('ok'); }
+ DATA.rows[r][c]=v; if(v)GREENSET.add(r+','+c); await stampLastMod(r); render(); setSync('ok'); }
catch(err){ setSync('err'); alert('Status write failed: '+err.message); } });
setTimeout(()=>document.addEventListener('mousedown',closeStatusPickerOutside),0);
}
@@ -551,10 +559,12 @@ function closeStatusPickerOutside(e){ if(!e.target.closest('#statusmenu')&&!e.ta
function cellTD(ri,ci,val,isN,gr){
const cls=[isN?'namecell':'',gr?'enriched':''].filter(Boolean).join(' ');
const s=String(val==null?'':val);
- if(isStatusCol(ci)){ // color-coded status chip + click-to-set picker
- if(!s) return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" class="statuscell empty ${cls}" title="Click to set status">+ set status</td>`;
+ if(isStatusCol(ci)){ // color-coded status chip + date/time under it + click-to-set picker
+ const lm=lmCol(), dt=(lm>=0 && DATA.rows[ri] && DATA.rows[ri][lm])||'';
+ const dtHtml=dt?`<div class="chipdate" title="Last modified">🕓 ${esc(String(dt))}</div>`:'';
+ if(!s) return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" class="statuscell empty ${cls}" title="Click to set status">+ set status${dtHtml}</td>`;
const col=statusColor(s);
- return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" class="statuscell ${cls}" title="Click to change status"><span class="statuschip" style="background:${col};color:${txtOn(col)}">${esc(s)}</span></td>`;
+ return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" class="statuscell ${cls}" title="Click to change status"><span class="statuschip" style="background:${col};color:${txtOn(col)}">${esc(s)}</span>${dtHtml}</td>`;
}
const em=emailOf(s);
if(em){ return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" data-mail="${esc(em)}" title="Email ${esc(em)}" class="mailcell ${cls}"><span class="cicon">${ICON.mail}</span><span class="linkval">${esc(em)}</span></td>`; }
@@ -612,7 +622,7 @@ function wireGrid(){
if(isNotes && String(cur).includes(txt))return; // don't append a duplicate note
const newVal=isNotes ? (String(cur).trim() ? String(cur).replace(/\s+$/,'')+'\n'+txt : txt) : txt; // Notes appends, everything else replaces
try{ const res=await postWrite(r,c,newVal); if(!res.ok)throw new Error(res.error||'write failed');
- DATA.rows[r][c]=newVal; GREENSET.add(r+','+c); render(); setSync('ok'); }
+ DATA.rows[r][c]=newVal; GREENSET.add(r+','+c); await stampLastMod(r); render(); setSync('ok'); }
catch(err){ setSync('err'); alert('Drop write failed: '+err.message); } });
}
$$('.card').forEach(c=>c.onclick=()=>openDraft(+c.dataset.r));
← fe7b566 Live console: row-number gutter down the left; drag-to-fill
·
back to Rentv Sheet Enrich
·
rentv :9797: paint EXACT original sheet cell colors in the g ca6b2ac →