Generate dashboards for an entire parent-child subtree from a single root
registration (pre-order, cycle/diamond-safe), so wiring only the subtree root
(e.g. pumpingStation) to dashboardAPI yields dashboards for every descendant.
Fix two contract drifts that left generated panels blank against live telemetry:
- _measurement var now mirrors outputUtils.formatMsg (general.name ||
<softwareType>_<id>); previously it always used the fallback form, so any
named node's dashboard queried a non-existent series.
- pumpingStation template field keys realigned to emitted telemetry
(flow.*.{upstream,out,overflow}, netFlowRate.measured, inflowLevel/
outflowLevel/overflowLevel, maxVolAtOverflow/minVolAt{Inflow,Outflow}).
Adds template alias resolution (softwareType -> shared template file) and
locks parity with slice44/45/46 tests + output manifest. 67/67 pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
63 lines
2.1 KiB
JavaScript
63 lines
2.1 KiB
JavaScript
// The dashboard's `_measurement` templating var MUST equal the InfluxDB
|
|
// measurement name that outputUtils.formatMsg writes telemetry under, or every
|
|
// panel queries a non-existent series and renders blank.
|
|
//
|
|
// outputUtils convention (generalFunctions/src/helper/outputUtils.js):
|
|
// measurement = config.general.name || `${softwareType}_${config.general.id}`
|
|
//
|
|
// buildDashboard must mirror it exactly.
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const DashboardApi = require('../../src/specificClass');
|
|
|
|
function makeApi() {
|
|
return new DashboardApi({
|
|
general: { name: 'dapi', logging: { enabled: false, logLevel: 'error' } },
|
|
grafanaConnector: { protocol: 'http', host: 'localhost', port: 3000, bearerToken: '' },
|
|
});
|
|
}
|
|
|
|
function measurementVar(dash) {
|
|
return dash.dashboard.templating.list.find((v) => v.name === 'measurement').current.value;
|
|
}
|
|
|
|
test('measurement var uses general.name when set (matches outputUtils)', () => {
|
|
const api = makeApi();
|
|
const dash = api.buildDashboard({
|
|
nodeConfig: {
|
|
general: { id: '248ba213d44df5b9', name: 'pumpingStation' },
|
|
functionality: { softwareType: 'pumpingstation' },
|
|
},
|
|
positionVsParent: 'atequipment',
|
|
});
|
|
assert.equal(dash.measurementName, 'pumpingStation');
|
|
assert.equal(measurementVar(dash), 'pumpingStation');
|
|
});
|
|
|
|
test('measurement var falls back to <softwareType>_<id> when name is empty', () => {
|
|
const api = makeApi();
|
|
const dash = api.buildDashboard({
|
|
nodeConfig: {
|
|
general: { id: '693ebd559017d39f', name: '' },
|
|
functionality: { softwareType: 'rotatingmachine' },
|
|
},
|
|
positionVsParent: 'atequipment',
|
|
});
|
|
assert.equal(dash.measurementName, 'rotatingmachine_693ebd559017d39f');
|
|
assert.equal(measurementVar(dash), 'rotatingmachine_693ebd559017d39f');
|
|
});
|
|
|
|
test('fallback id segment is the node id, not the title', () => {
|
|
const api = makeApi();
|
|
const dash = api.buildDashboard({
|
|
nodeConfig: {
|
|
general: { id: 'abc123' },
|
|
functionality: { softwareType: 'measurement' },
|
|
},
|
|
positionVsParent: 'upstream',
|
|
});
|
|
assert.equal(dash.measurementName, 'measurement_abc123');
|
|
});
|