[object Object]

← back to Norma Platform

IG: delete-viewer cockpit generator — visual selectable board of old dupes, one-tap open-to-delete + progress tracking

05e1786748f0b90b10cc61f68836ca70a3dd587c · 2026-08-14 13:41:56 -0700 · Steve

Files touched

Diff

commit 05e1786748f0b90b10cc61f68836ca70a3dd587c
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Aug 14 13:41:56 2026 -0700

    IG: delete-viewer cockpit generator — visual selectable board of old dupes, one-tap open-to-delete + progress tracking
---
 agents/instagram-agent/gen-delete-viewer.js | 67 +++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/agents/instagram-agent/gen-delete-viewer.js b/agents/instagram-agent/gen-delete-viewer.js
new file mode 100644
index 0000000..c386e7f
--- /dev/null
+++ b/agents/instagram-agent/gen-delete-viewer.js
@@ -0,0 +1,67 @@
+const fs=require('fs');const path=require('path');
+const orig=fs.readFileSync('data/redo-originals-20260814.jsonl','utf8').trim().split('\n').map(l=>JSON.parse(l));
+const res=fs.existsSync('data/redo-results-20260814.jsonl')?fs.readFileSync('data/redo-results-20260814.jsonl','utf8').trim().split('\n').map(l=>JSON.parse(l)):[];
+const newBy={}; res.forEach(r=>{ if(r.old_permalink) newBy[r.old_permalink]=r.new_permalink; });
+// each OLD post = a dupe to delete (skip nothing; include archived orphan too)
+const posts=orig.map(o=>({handle:o.handle,title:(o.product_title||'').split('|')[0].trim(),img:o.image_url,old:o.permalink,neww:newBy[o.permalink]||null}));
+const data=JSON.stringify(posts);
+const html=`<!doctype html><html><head><meta charset=utf8><meta name=viewport content="width=device-width,initial-scale=1">
+<title>DW IG — Delete Old Dupes</title><style>
+:root{--b:#0c0f1a;--s:#131829;--e:#1c2237;--t:#f0f0f5;--m:#a1a1b5;--p:#10b981;--r:#f43f5e;--bd:#2a3048}
+*{box-sizing:border-box}body{margin:0;background:var(--b);color:var(--t);font:15px/1.4 -apple-system,system-ui,sans-serif}
+header{position:sticky;top:0;background:var(--s);padding:12px 16px;border-bottom:1px solid var(--bd);z-index:10;display:flex;gap:12px;align-items:center;flex-wrap:wrap}
+h1{font-size:16px;margin:0}.count{color:var(--m);font-size:13px}
+button{background:var(--e);color:var(--t);border:1px solid var(--bd);border-radius:8px;padding:8px 12px;font-size:13px;cursor:pointer}
+button.primary{background:var(--p);border-color:var(--p);color:#04120c;font-weight:600}
+button.danger{background:var(--r);border-color:var(--r);color:#fff}
+.acct{padding:14px 16px 4px;color:var(--m);font-size:13px;font-weight:600;text-transform:lowercase}
+.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px;padding:4px 16px 16px}
+.card{background:var(--s);border:1px solid var(--bd);border-radius:10px;overflow:hidden;position:relative}
+.card.done{opacity:.4}.card.done .thumb{filter:grayscale(1)}
+.card.sel{outline:2px solid var(--p)}
+.thumb{width:100%;aspect-ratio:1;object-fit:cover;background:var(--e);display:block}
+.meta{padding:8px}.ttl{font-size:12px;line-height:1.3;max-height:32px;overflow:hidden}
+.row{display:flex;gap:6px;padding:0 8px 8px}.row a,.row button{flex:1;text-align:center;text-decoration:none;font-size:12px;padding:6px;border-radius:6px}
+.open{background:var(--e);color:var(--t);border:1px solid var(--bd)}.mark{background:transparent;border:1px solid var(--p);color:var(--p)}
+.chk{position:absolute;top:6px;left:6px;width:20px;height:20px}
+.dupe{position:absolute;top:6px;right:6px;background:#0009;color:#fff;font-size:10px;padding:2px 5px;border-radius:4px}
+</style></head><body>
+<header><h1>🗑️ Delete Old Dupes</h1><span class=count id=count></span>
+<button class=primary onclick=openSel()>Open selected ↗</button>
+<button onclick=selAll()>Select all</button><button onclick=selNone()>Clear</button>
+<span class=count>Tip: check the ones you want, hit “Open selected”, delete each in IG (⋯→Delete), then tap ✓ done.</span></header>
+<div id=app></div>
+<script>
+const POSTS=${data};
+const done=JSON.parse(localStorage.getItem('dwDelDone')||'{}');
+const sel=new Set();
+function save(){localStorage.setItem('dwDelDone',JSON.stringify(done))}
+function render(){
+ const app=document.getElementById('app');app.innerHTML='';
+ const by={};POSTS.forEach((p,i)=>{(by[p.handle]=by[p.handle]||[]).push({...p,i})});
+ Object.keys(by).sort().forEach(h=>{
+  const a=document.createElement('div');a.className='acct';a.textContent='@'+h+' ('+by[h].length+')';app.appendChild(a);
+  const g=document.createElement('div');g.className='grid';
+  by[h].forEach(p=>{
+   const c=document.createElement('div');c.className='card'+(done[p.old]?' done':'')+(sel.has(p.i)?' sel':'');
+   c.innerHTML=\`<input type=checkbox class=chk \${sel.has(p.i)?'checked':''} onchange="toggle(\${p.i})">
+   \${p.neww?'<span class=dupe>dupe ✓ has new</span>':'<span class=dupe>archived</span>'}
+   <img class=thumb loading=lazy src="\${p.img||''}">
+   <div class=meta><div class=ttl>\${p.title||''}</div></div>
+   <div class=row><a class=open href="\${p.old}" target=_blank rel=noopener>Open ↗</a>
+   <button class=mark onclick="mark('\${p.old}')">\${done[p.old]?'undo':'✓ done'}</button></div>\`;
+   g.appendChild(c);
+  });app.appendChild(g);
+ });
+ const d=Object.keys(done).filter(k=>done[k]).length;
+ document.getElementById('count').textContent=d+' / '+POSTS.length+' marked deleted · '+sel.size+' selected';
+}
+function toggle(i){sel.has(i)?sel.delete(i):sel.add(i);render()}
+function mark(o){done[o]=!done[o];save();render()}
+function openSel(){[...sel].forEach((i,n)=>setTimeout(()=>window.open(POSTS[i].old,'_blank'),n*400))}
+function selAll(){POSTS.forEach((p,i)=>{if(!done[p.old])sel.add(i)});render()}
+function selNone(){sel.clear();render()}
+render();
+</script></body></html>`;
+fs.writeFileSync('public/delete-viewer.html',html);
+console.log('wrote public/delete-viewer.html ('+posts.length+' posts)');

← 9cc01ed IG fabric-friday reshare: match #fabricfriday posts against  ·  back to Norma Platform  ·  IG fabric-friday reshare: daily auto-mode — dedup, exclude o 0ba22ac →