+
@@ -346,6 +380,8 @@ function spcDashboard() {
subtasks: [],
// Data state
+ loadedSubtaskId: '', // #100 punto con cui sono stati caricati i dati (i pannelli dipendono da questo)
+ capabilityAll: [], // #100 con «Tutti i punti»: [{subtask, data}] una riga per punto
summary: null,
capability: null,
controlChart: null,
@@ -408,6 +444,8 @@ function spcDashboard() {
async onRecipeChange() {
this.selectedSubtaskId = '';
+ this.loadedSubtaskId = ''; // #100
+ this.capabilityAll = []; // #100
this.selectedRunId = ''; // #58
this.runs = [];
this.subtasks = [];
@@ -459,10 +497,11 @@ function spcDashboard() {
if (this.selectedRunId) params.set('production_run_id', this.selectedRunId); // #58
if (this.dateFrom) params.set('date_from', new Date(this.dateFrom + 'T00:00:00').toISOString());
if (this.dateTo) params.set('date_to', new Date(this.dateTo + 'T23:59:59.999').toISOString());
+ const requestedSubtaskId = this.selectedSubtaskId; // #100 punto richiesto da questa chiamata
try {
// Parallel fetch of all endpoints
- const [summaryResp, capabilityResp, controlResp, histogramResp] = await Promise.allSettled([
+ const [summaryResp, capabilityResp, controlResp, histogramResp, allResp] = await Promise.allSettled([
fetch('/statistics/api/summary?' + params.toString()).then(r => r.json()),
this.selectedSubtaskId
? fetch('/statistics/api/capability?' + params.toString()).then(r => r.json())
@@ -473,6 +512,17 @@ function spcDashboard() {
this.selectedSubtaskId
? fetch('/statistics/api/histogram?' + params.toString()).then(r => r.json())
: Promise.resolve(null),
+ // #100: senza punto scelto, capability di ogni punto della ricetta
+ requestedSubtaskId
+ ? Promise.resolve([])
+ : Promise.all(this.subtasks.map(st => {
+ const p = new URLSearchParams(params.toString());
+ p.set('subtask_id', st.id);
+ return fetch('/statistics/api/capability?' + p.toString())
+ .then(r => r.json())
+ .then(d => ({ subtask: st, data: (d && !d.error) ? d : null }))
+ .catch(() => ({ subtask: st, data: null }));
+ })),
]);
// Summary (always available)
@@ -505,6 +555,9 @@ function spcDashboard() {
this.histogram = null;
}
+ // #100: lista per-punto solo con «Tutti i punti»; con un punto resta il flusso di prima
+ this.capabilityAll = (allResp.status === 'fulfilled' && Array.isArray(allResp.value)) ? allResp.value : [];
+ this.loadedSubtaskId = requestedSubtaskId;
this.hasData = true;
// Render charts after DOM update
@@ -522,7 +575,7 @@ function spcDashboard() {
renderCharts() {
// Control chart
- if (this.controlChart && this.selectedSubtaskId) {
+ if (this.controlChart && this.loadedSubtaskId) { // #100
renderControlChart('control-chart', this.controlChart);
} else {
const el = document.getElementById('control-chart');
@@ -530,7 +583,7 @@ function spcDashboard() {
}
// Histogram
- if (this.histogram && this.selectedSubtaskId) {
+ if (this.histogram && this.loadedSubtaskId) { // #100
const tol = this.capability ? {
utl: this.capability.utl,
ltl: this.capability.ltl,
diff --git a/src/frontend/flask_app/tests/test_statistics.py b/src/frontend/flask_app/tests/test_statistics.py
index f51f6cf..0701aea 100644
--- a/src/frontend/flask_app/tests/test_statistics.py
+++ b/src/frontend/flask_app/tests/test_statistics.py
@@ -167,3 +167,11 @@ class TestRunTaskResultsProxy:
assert 'id="run-task-results"' in html
assert "loadTaskResults" in html
assert "/statistics/api/runs/" in html
+
+ def test_dashboard_all_points_overview(self, logged_in_client, mock_api_client):
+ # #100: con «Tutti i punti» la pagina ha tabella per-punto e select che ricarica da solo
+ mock_api_client.get.return_value = {"items": [], "total": 0, "pages": 1}
+ html = logged_in_client.get("/statistics/dashboard").get_data(as_text=True)
+ assert "capabilityAll" in html
+ assert "loadedSubtaskId" in html
+ assert '@change="loadData()"' in html
diff --git a/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po b/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
index b2f5b53..8cba33d 100644
--- a/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
+++ b/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
@@ -3485,3 +3485,7 @@ msgstr "Invalid camera address"
#: templates/admin/stations.html blueprints/admin.py (#88)
msgid "Risposta non valida dal servizio camera"
msgstr "Invalid response from the camera service"
+
+#: templates/statistics/dashboard.html (#100)
+msgid "Scegli un punto per carta di controllo e istogramma"
+msgstr "Choose a point for the control chart and histogram"