From 1126c8a7000b7722f7d6486c480b2606bb8e347a Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Fri, 13 Mar 2026 15:13:30 +0000 Subject: [PATCH] Fix history: correct score field name + add delete button - api.php: read accessibility_score (not score) from result.json - api.php: handleDelete() also removes .dismissed.json, .overrides.json, .error.log - js/app.js: add Delete button to each history row with confirm dialog - css/styles.css: red hover style for delete button Co-Authored-By: Claude Sonnet 4.6 --- api.php | 13 ++++++++----- css/styles.css | 5 +++++ js/app.js | 29 ++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/api.php b/api.php index c94271e..2ab0d27 100644 --- a/api.php +++ b/api.php @@ -715,9 +715,9 @@ function handleList() { if (file_exists($result_file)) { $job_data['status'] = 'completed'; $result = json_decode(file_get_contents($result_file), true); - $job_data['score'] = $result['score'] ?? null; - $job_data['grade'] = $result['grade'] ?? null; - $job_data['total_issues'] = $result['total_issues'] ?? null; + $job_data['score'] = $result['accessibility_score'] ?? ($result['score'] ?? null); + $job_data['grade'] = $result['grade'] ?? null; + $job_data['total_issues'] = $result['total_issues'] ?? null; $job_data['critical_count'] = $result['severity_counts']['critical'] ?? 0; $job_data['error_count'] = $result['severity_counts']['error'] ?? 0; } @@ -752,10 +752,13 @@ function handleDelete() { $job_data = json_decode(file_get_contents($meta_file), true); - // Delete files - @unlink($job_data['filepath']); + // Delete all files associated with this job + @unlink($job_data['filepath'] ?? ''); @unlink($meta_file); @unlink(RESULTS_DIR . '/' . $job_id . '.result.json'); + @unlink(RESULTS_DIR . '/' . $job_id . '.dismissed.json'); + @unlink(RESULTS_DIR . '/' . $job_id . '.overrides.json'); + @unlink(RESULTS_DIR . '/' . $job_id . '.error.log'); success(['message' => 'Job deleted']); } diff --git a/css/styles.css b/css/styles.css index f76fcc6..2f31f4d 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1658,6 +1658,11 @@ h1::before { color: var(--accent); } +.history-action-delete:hover { + border-color: var(--error); + color: var(--error); +} + /* ── Reduced Motion ── */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { diff --git a/js/app.js b/js/app.js index 9a56b7e..ccd4227 100644 --- a/js/app.js +++ b/js/app.js @@ -155,6 +155,7 @@ function renderHistory(jobs) { const jsonBtn = j.status === 'completed' ? `JSON` : ''; + const deleteBtn = ``; return ` ${name} @@ -162,7 +163,7 @@ function renderHistory(jobs) { ${status} ${score}${j.score != null ? '/100' : ''} ${grade} ${critical > 0 ? `${critical} crit` : ''} ${errors > 0 ? `${errors} err` : ''}${!critical && !errors ? '✓ Clean' : ''} - ${openBtn}${htmlBtn}${pdfBtn}${jsonBtn} + ${openBtn}${htmlBtn}${pdfBtn}${jsonBtn}${deleteBtn} `; }).join(''); @@ -194,6 +195,32 @@ function escapeHtml(str) { .replace(/"/g, '"'); } +async function deleteHistoryJob(jobId, btn) { + if (!confirm('Delete this document and its report?')) return; + btn.disabled = true; + try { + const formData = new FormData(); + formData.append('job_id', jobId); + const data = await apiCall('delete', { method: 'POST', body: formData }); + if (data.success) { + btn.closest('tr').remove(); + // Show empty state if no rows left + const tbody = document.querySelector('.history-table tbody'); + if (tbody && !tbody.querySelector('tr')) { + document.querySelector('.history-table').remove(); + const empty = document.getElementById('historyEmpty'); + if (empty) empty.style.display = ''; + } + } else { + alert('Delete failed: ' + (data.error || 'Unknown error')); + btn.disabled = false; + } + } catch (e) { + alert('Delete failed.'); + btn.disabled = false; + } +} + async function openHistoryJob(jobId) { // Show results section and load the job — reuse the existing display flow currentJobId = jobId;