From 5b94858f7f4e16cfa146a9906e5eaee9a7962e58 Mon Sep 17 00:00:00 2001 From: NguyenND Date: Fri, 26 Jun 2026 13:54:13 -0400 Subject: [PATCH] Jun 26 - Update AI Analysis History bulk action for admin --- templates/ai_summary.html | 117 +++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/templates/ai_summary.html b/templates/ai_summary.html index b1f62c3..c52add7 100644 --- a/templates/ai_summary.html +++ b/templates/ai_summary.html @@ -123,19 +123,36 @@ + {% if is_admin %} +
+ + + +
+ {% endif %}
+ {% if is_admin %}{% endif %} + {% if is_admin %}{% endif %} {% for h in history %} + {% if is_admin %} + + {% endif %} @@ -146,9 +163,14 @@ {% else %}—{% endif %} + {% if is_admin %} + + {% endif %} {% else %} -
Date User Files Verdict
+ + {{ h.analyzed_at.strftime('%Y-%m-%d %H:%M') if h.analyzed_at else '—' }} {{ h.username or '—' }} {{ h.file_names[:50] }}{% if h.file_names|length > 50 %}…{% endif %} + +
+
🤖

No analyses yet. Upload a document above to get started.

@@ -435,6 +457,87 @@ document.querySelectorAll('.js-edit-criterion').forEach(function(btn) { }); }); +/* ─── Bulk & row-level delete (admin only) ──────────────────── */ +if (IS_ADMIN) { + // "Select all" checkbox + document.getElementById('cb-all').addEventListener('change', function() { + document.querySelectorAll('.hist-cb').forEach(function(cb) { + var row = cb.closest('.history-row'); + if (row && row.style.display !== 'none') cb.checked = this.checked; + }, this); + _updateBulkBar(); + }); + + // Individual checkboxes + document.addEventListener('change', function(e) { + if (e.target.classList.contains('hist-cb')) _updateBulkBar(); + }); + + // Row delete icon — delegated + document.addEventListener('click', function(e) { + var btn = e.target.closest('.js-delete-row'); + if (!btn) return; + e.stopPropagation(); + var id = btn.dataset.id; + if (!confirm('Delete this analysis? This cannot be undone.')) return; + _sendDeletes([id], function(ok) { + if (!ok) return; + var row = document.querySelector('.history-row[data-id="' + id + '"]'); + if (row) row.remove(); + _updateBulkBar(); + }); + }); +} + +function _updateBulkBar() { + var cbs = document.querySelectorAll('.hist-cb:checked'); + var count = cbs.length; + var barEl = document.getElementById('bulk-bar'); + var countEl = document.getElementById('bulk-count'); + var delBtn = document.getElementById('btn-bulk-delete'); + if (!barEl) return; + countEl.textContent = count + ' selected'; + delBtn.disabled = count === 0; +} + +function clearSelection() { + document.querySelectorAll('.hist-cb').forEach(function(cb) { cb.checked = false; }); + var cbAll = document.getElementById('cb-all'); + if (cbAll) cbAll.checked = false; + _updateBulkBar(); +} + +function _sendDeletes(ids, callback) { + Promise.all(ids.map(function(id) { + return fetch('/ai-summary/history/' + id + '/delete', { + method: 'POST', + headers: { 'X-CSRFToken': getCsrfToken() }, + }).then(function(r) { return r.json(); }); + })).then(function(results) { + var failed = results.filter(function(r) { return r.error; }); + if (failed.length) alert('Failed to delete ' + failed.length + ' item(s).'); + if (callback) callback(true); + }).catch(function() { + alert('Delete failed. Please try again.'); + if (callback) callback(false); + }); +} + +function bulkDelete() { + var checked = document.querySelectorAll('.hist-cb:checked'); + if (!checked.length) return; + var ids = Array.from(checked).map(function(cb) { return cb.dataset.id; }); + if (!confirm('Delete ' + ids.length + ' analysis record(s)? This cannot be undone.')) return; + _sendDeletes(ids, function(ok) { + if (!ok) return; + ids.forEach(function(id) { + var row = document.querySelector('.history-row[data-id="' + id + '"]'); + if (row) row.remove(); + }); + clearSelection(); + }); +} + /* ─── History rows ──────────────────────────────────────────── */ var _currentAnalysisId = null; @@ -622,6 +725,18 @@ function escHtml(str) { /* ── History ───────────────────────────────────────────────── */ .history-row:hover td{background:var(--bg-subtle)} +.ai-bulk-bar{ + display:flex;align-items:center;gap:.75rem; + padding:.55rem 1rem;background:var(--bg-subtle); + border-bottom:1px solid var(--border); +} +.btn-row-delete{ + background:none;border:none;padding:2px 6px;border-radius:var(--r-sm); + cursor:pointer;font-size:.85rem;color:var(--text-muted); + transition:color var(--t),background var(--t);opacity:0; +} +.history-row:hover .btn-row-delete{opacity:1} +.btn-row-delete:hover{color:var(--danger,#dc2626);background:var(--danger-bg,#fef2f2)} .ai-hist-filter{ background:none;border:1px solid var(--border); padding:.2rem .55rem;font-size:.72rem;border-radius:var(--r-sm);