feat(dashboardapi): no-data-duplication rule for parent dashboards (#39)
When generateDashboardsForGraph builds a root dashboard for a parent (e.g. pumpingStation) and a set of child dashboards (e.g. measurements), it now removes any non-row panel from the root whose meta.emittedFields are fully covered by panels declared in any child dashboard. Result: the parent shows only metrics its children don't already plot, eliminating redundant rendering of the same series in two dashboards. - config/pumpingStation.json: 11 non-row panels annotated with meta.emittedFields (Direction, Time Left, Flow Source, Fill %, Level (x2), Volume, Net Flow Rate, Inflow+Outflow, Heights, Volume Limits). - src/specificClass.js: generateDashboardsForGraph runs the parent-panel filter after composing children; row panels always kept; panels without emittedFields declaration always kept (no silent removal). - test/basic/slice39-no-duplication.basic.test.js: 4 cases — annotation presence, child-covered removal, no-overlap preservation, row preservation. Closes #39
This commit is contained in:
@@ -228,6 +228,32 @@ class DashboardApi {
|
||||
if (childDash) results.push(childDash);
|
||||
}
|
||||
|
||||
// No-data-duplication rule (PRD F-5, #39): remove root panels whose
|
||||
// emittedFields are fully covered by panels on child dashboards. The
|
||||
// parent then shows only metrics its children don't already plot,
|
||||
// avoiding redundant rendering of the same series in two places.
|
||||
if (children.length > 0 && rootDash.dashboard) {
|
||||
const childCoveredFields = new Set();
|
||||
for (const dash of results.slice(1)) {
|
||||
for (const f of this.collectEmittedFields(dash.dashboard)) childCoveredFields.add(f);
|
||||
}
|
||||
const before = rootDash.dashboard.panels.length;
|
||||
rootDash.dashboard.panels = rootDash.dashboard.panels.filter((p) => {
|
||||
if (p.type === 'row') return true; // never drop rows
|
||||
const fields = p?.meta?.emittedFields;
|
||||
if (!Array.isArray(fields) || fields.length === 0) return true; // no declaration, keep
|
||||
return !fields.every((f) => childCoveredFields.has(f));
|
||||
});
|
||||
if (this.logger?.debug && before !== rootDash.dashboard.panels.length) {
|
||||
this.logger.debug({
|
||||
event: 'parent-panels-deduped',
|
||||
before,
|
||||
after: rootDash.dashboard.panels.length,
|
||||
rootTitle: rootDash.title,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add links from the root dashboard to children dashboards (when possible)
|
||||
if (children.length > 0) {
|
||||
rootDash.dashboard.links = Array.isArray(rootDash.dashboard.links) ? rootDash.dashboard.links : [];
|
||||
|
||||
Reference in New Issue
Block a user