From 61cb428f5476e027d427be02fa38dbf7505039b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 30 Mar 2026 00:37:53 +0000 Subject: [PATCH] feat: add delete buttons to reports list and report detail pages - Add "Delete" button to reports list table (reports.html): clicking shows a confirmation dialog then calls the existing DELETE API. On success, the row is removed from the table without a page reload. Domain filter dropdown is pruned if the domain has no remaining reports. - Add "Delete Report" button to report detail page (report_detail.html): clicking shows a confirmation dialog then calls the DELETE API. On success, redirects to /reports. The backend DELETE endpoint and re-upload-after-delete (deduplication exemption) were already in place and covered by existing tests. Agent-Logs-Url: https://github.com/christianlouis/dmarq/sessions/d6c0078b-9338-49f0-87bd-32238fbde237 Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- backend/app/templates/report_detail.html | 25 ++++++++++++++ backend/app/templates/reports.html | 42 +++++++++++++++++++++--- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/backend/app/templates/report_detail.html b/backend/app/templates/report_detail.html index c623f6a..acc6813 100644 --- a/backend/app/templates/report_detail.html +++ b/backend/app/templates/report_detail.html @@ -51,6 +51,10 @@ Back to Domain + @@ -247,6 +251,27 @@ function reportDetailApp(reportId) { } }, + async deleteReport(domain, reportId) { + if (!confirm(`Delete report "${reportId}" for domain "${domain}"?\n\nThis will remove the report from the system. You can re-import it afterwards.`)) { + return; + } + try { + const response = await fetch( + `/api/v1/reports/domain/${encodeURIComponent(domain)}/reports/${encodeURIComponent(reportId)}`, + { method: 'DELETE' } + ); + if (response.ok) { + window.location.href = '/reports'; + } else { + const data = await response.json().catch(() => ({})); + alert('Failed to delete report: ' + (data.detail || response.statusText)); + } + } catch (error) { + console.error('Error deleting report:', error); + alert('Network error — could not delete report.'); + } + }, + formatDate(timestamp) { if (!timestamp) return '—'; return new Date(timestamp * 1000).toLocaleString(); diff --git a/backend/app/templates/reports.html b/backend/app/templates/reports.html index ed0bb71..087d70d 100644 --- a/backend/app/templates/reports.html +++ b/backend/app/templates/reports.html @@ -95,11 +95,17 @@ {% endcall %} {% call td("text-right") %} - - {% call button(variant="outline", size="sm") %} - View Details - {% endcall %} - +
+ + {% call button(variant="outline", size="sm") %} + View Details + {% endcall %} + + +
{% endcall %} {% endcall %} @@ -174,6 +180,32 @@ function reportsApp() { } finally { this.loading = false; } + }, + + async deleteReport(domain, reportId) { + if (!confirm(`Delete report "${reportId}" for domain "${domain}"?\n\nThis will remove the report from the system. You can re-import it afterwards.`)) { + return; + } + try { + const response = await fetch( + `/api/v1/reports/domain/${encodeURIComponent(domain)}/reports/${encodeURIComponent(reportId)}`, + { method: 'DELETE' } + ); + if (response.ok) { + this.reports = this.reports.filter( + r => !(r.domain === domain && r.report_id === reportId) + ); + if (!this.reports.some(r => r.domain === domain)) { + this.domains = this.domains.filter(d => d !== domain); + } + } else { + const data = await response.json().catch(() => ({})); + alert('Failed to delete report: ' + (data.detail || response.statusText)); + } + } catch (error) { + console.error('Error deleting report:', error); + alert('Network error — could not delete report.'); + } } } }