// Revision Stats Exporter - Extracts DataTable to HTML clipboard
let html = "", rows = "", first = 1;
const cfg = {
warning: {i: '⚠️', c: '#ffc107'},
error: {i: '❌', c: '#dc3545'},
confirm: {i: '❓', c: '#28a745'},
success: {i: '✅', c: '#28a745'}
};
function dialog(title, msg, type = 'warning', onOk, onNo) {
const d = document.getElementById('d');
d && d.remove();
const c = cfg[type] || cfg.warning;
const dialogEl = document.createElement('div');
dialogEl.id = 'd';
dialogEl.innerHTML =
`
${c.i}
${title}
${msg}
${type === 'confirm' ?
`
` :
``
}
`;
document.body.appendChild(dialogEl);
// Add proper event listeners (no global variables needed)
const okBtn = document.getElementById('okBtn');
const cancelBtn = document.getElementById('cancelBtn');
okBtn.onclick = () => { closeD(); onOk && onOk(); };
if (cancelBtn) cancelBtn.onclick = () => { closeD(); onNo && onNo(); };
}
function closeD() {
const d = document.getElementById('d');
d && d.remove();
}
function start() {
dialog("Export Revision Statistics",
"Ready to create your revision statistics table!\n\nClick OK to start.",
"confirm", gather);
}
function makeRow(r) {
try {
const a = r.advisor?.display_name || "N/A",
e = r.advisor?.email || "N/A",
d = r.site?.settings?.domains?.join(", ") || "N/A",
t = r.advisor?.settings?.broker_tags?.map(x => x.name)?.join(", ") || "N/A",
rt = r.location || "N/A",
rn = (r?.meta?.name ? r.meta.name + " - " : "") + r.title || "N/A",
s = r.state || "N/A",
rb = r.reviewed_by?.display_name || "N/A",
sd = r.site?.submitted_at ? new Date(r.site.submitted_at).toLocaleString().replace(",", "") : "N/A",
rd = r.created_at ? new Date(r.created_at).toLocaleString().replace(",", "") : "N/A",
ni = r.internal_notes?.replace(/<\/*[^>]*>?/gm, " ") || "",
rj = r.notes?.replace(/<\/*[^>]*>?/gm, " ") || "";
return `${a} ${e} | ${d} | ${t} | ${rt} | ${rn} | ${s} | ${rb} | ${sd} | ${rd} | ${ni} | ${rj} |
`;
} catch(e) {
return "";
}
}
function makeTable() {
return `
| Advisor | Domain | Tags | Revision Type | Revision Title |
Status | Reviewed By | Submitted Date | Reviewed Date | Notes | Rejection Notes |
${rows}
`;
}
async function copy(h) {
try {
await navigator.clipboard.writeText(h);
dialog("Export Complete!", "Table copied to clipboard!\n\nPaste into Excel, Word, etc.", "success");
} catch(e) {
const t = document.createElement('textarea');
Object.assign(t.style, {
position: 'fixed', top: '10%', left: '10%', width: '80%', height: '70%',
zIndex: '10001', background: 'white', border: '2px solid #333',
borderRadius: '8px', padding: '10px', fontFamily: 'monospace', fontSize: '12px'
});
t.value = h;
document.body.appendChild(t);
t.select();
dialog("Manual Copy Required", "Auto-copy failed.\n\nHTML selected in textarea.\nPress Ctrl+C, then OK.",
"warning", () => document.body.removeChild(t));
}
}
function loaded() {
const p = document.getElementById('revisions-list_processing');
return !p || getComputedStyle(p).display === 'none';
}
function wait() {
return new Promise(resolve => {
const check = () => loaded() ? resolve() : setTimeout(check, 100);
first ? (first = 0, resolve()) : check();
});
}
async function gather() {
try {
await wait();
const dt = $(".dataTable").DataTable(),
d = dt.data();
if (!d || !d.length) return done();
d.each(r => {
const rh = makeRow(r);
rh && (rows += rh);
});
const n = $(".next");
n.length && !n.hasClass('disabled') ? (n.click(), gather()) : done();
} catch(e) {
dialog("Processing Error", "Error: " + e.message, "error");
}
}
function done() {
if (!rows.trim())
return dialog("No Data", "No data found.\n\nCheck DataTable has data.", "warning");
html = makeTable();
copy(html);
}
// Start the export process
start();