fix: improve SPC dashboard UX — hover toolbar, visible report errors

- Change Plotly modebar to hover-only mode to avoid overlapping chart content
- Remove redundant Plotly titles (container headers already provide them)
- Add Content-Type check and inline error display for report downloads
- Fix setup login validation and seed idempotency for existing data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Adriano
2026-02-24 16:42:47 +01:00
parent e07a4e4f89
commit 429c94da94
4 changed files with 53 additions and 9 deletions
+23 -3
View File
@@ -108,6 +108,12 @@
{{ _("Applica filtri") }}
</button>
</div>
<!-- Inline report error (shown below buttons row) -->
<div x-show="reportError" x-cloak
class="mt-2 text-sm text-red-600 dark:text-red-400 flex items-center gap-1"
x-text="reportError"
x-transition>
</div>
</div>
<!-- Nessuna ricetta selezionata -->
@@ -266,6 +272,7 @@ function spcDashboard() {
loading: false,
hasData: false,
errorMessage: '',
reportError: '',
downloadingReport: false,
init() {
@@ -387,7 +394,7 @@ function spcDashboard() {
renderHistogram('histogram-chart', this.histogram, tol);
} else {
const el = document.getElementById('histogram-chart');
if (el) el.innerHTML = '<p class="text-center text-steel py-12">{{ _("Seleziona un punto di misura per l\'istogramma") }}</p>';
if (el) el.innerHTML = '<p class="text-center text-steel py-12">' + {{ _("Seleziona un punto di misura per l'istogramma")|tojson }} + '</p>';
}
// Capability gauge
@@ -404,6 +411,7 @@ function spcDashboard() {
},
async downloadReport(type) {
this.reportError = '';
this.downloadingReport = type;
try {
const params = new URLSearchParams();
@@ -417,7 +425,19 @@ function spcDashboard() {
if (!resp.ok) {
const errData = await resp.json().catch(() => ({}));
this.errorMessage = errData.detail || '{{ _("Errore nella generazione del report") }}';
const msg = errData.detail || '{{ _("Errore nella generazione del report") }}';
console.error('Report download failed (' + resp.status + '):', msg, errData);
this.reportError = msg;
return;
}
// Check Content-Type: server may return JSON error with 200 status
const contentType = resp.headers.get('Content-Type') || '';
if (!contentType.includes('application/pdf')) {
const errData = await resp.json().catch(() => ({}));
const msg = errData.detail || '{{ _("Errore nella generazione del report") }}';
console.error('Report returned non-PDF content-type "' + contentType + '":', msg, errData);
this.reportError = msg;
return;
}
@@ -434,7 +454,7 @@ function spcDashboard() {
URL.revokeObjectURL(a.href);
} catch (e) {
console.error('Error downloading report:', e);
this.errorMessage = '{{ _("Errore di connessione al server") }}';
this.reportError = '{{ _("Errore di connessione al server") }}';
} finally {
this.downloadingReport = false;
}