Skip to content

Commit

Permalink
Merge pull request #1389 from FlowFuse/x-type-timestamp
Browse files Browse the repository at this point in the history
Chart: Add "timestamp" type for x-property
  • Loading branch information
joepavitt authored Oct 12, 2024
2 parents 5281dd1 + b8f6584 commit dfdfb39
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 16 deletions.
267 changes: 267 additions & 0 deletions cypress/fixtures/flows/dashboard-chart-timestamp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
[
{
"id": "node-red-tab-charts",
"type": "tab",
"label": "UI Chart",
"disabled": false,
"info": "",
"env": []
},
{
"id": "button-clear",
"type": "ui-button",
"z": "node-red-tab-charts",
"group": "dashboard-ui-group",
"name": "",
"label": "Button - Clear",
"order": 0,
"width": 0,
"height": 0,
"emulateClick": false,
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"iconPosition": "left",
"payload": "[]",
"payloadType": "json",
"topic": "topic",
"topicType": "msg",
"buttonColor": "",
"textColor": "",
"iconColor": "",
"enablePointerdown": false,
"pointerdownPayload": "",
"pointerdownPayloadType": "str",
"enablePointerup": false,
"pointerupPayload": "",
"pointerupPayloadType": "str",
"x": 370,
"y": 120,
"wires": [
[
"line-chart-timestamp",
"line-chart-empty-xProp"
]
]
},
{
"id": "button-send-payload",
"type": "ui-button",
"z": "node-red-tab-charts",
"group": "dashboard-ui-group",
"name": "",
"label": "Button - Number",
"order": 0,
"width": 0,
"height": 0,
"emulateClick": false,
"tooltip": "",
"color": "",
"bgcolor": "",
"className": "",
"icon": "",
"iconPosition": "left",
"payload": "2",
"payloadType": "num",
"topic": "topic",
"topicType": "msg",
"buttonColor": "",
"textColor": "",
"iconColor": "",
"enablePointerdown": false,
"pointerdownPayload": "",
"pointerdownPayloadType": "str",
"enablePointerup": false,
"pointerupPayload": "",
"pointerupPayloadType": "str",
"x": 370,
"y": 1120,
"wires": [
[
"line-chart-timestamp",
"line-chart-empty-xProp"
]
]
},
{
"id": "line-chart-timestamp",
"type": "ui-chart",
"z": "node-red-tab-charts",
"group": "dashboard-ui-group",
"name": "",
"label": "chart",
"order": 9007199254740991,
"chartType": "line",
"category": "topic",
"categoryType": "msg",
"xAxisLabel": "",
"xAxisProperty": "",
"xAxisPropertyType": "timestamp",
"xAxisType": "time",
"xAxisFormat": "",
"xAxisFormatType": "auto",
"xmin": "",
"xmax": "",
"yAxisLabel": "",
"yAxisProperty": "payload",
"yAxisPropertyType": "msg",
"ymin": "",
"ymax": "",
"bins": 10,
"action": "append",
"stackSeries": false,
"pointShape": "circle",
"pointRadius": 4,
"showLegend": true,
"removeOlder": 1,
"removeOlderUnit": "3600",
"removeOlderPoints": "",
"colors": [
"#0095ff",
"#ff0000",
"#ff7f0e",
"#2ca02c",
"#a347e1",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"textColor": [
"#666666"
],
"textColorDefault": true,
"gridColor": [
"#e5e5e5"
],
"gridColorDefault": true,
"width": 6,
"height": 8,
"className": "",
"x": 510,
"y": 1120,
"wires": [
[]
]
},
{
"id": "line-chart-empty-xProp",
"type": "ui-chart",
"z": "node-red-tab-charts",
"group": "dashboard-ui-group",
"name": "",
"label": "chart",
"order": 9007199254740991,
"chartType": "line",
"category": "topic",
"categoryType": "msg",
"xAxisLabel": "",
"xAxisProperty": "",
"xAxisPropertyType": "property",
"xAxisType": "time",
"xAxisFormat": "",
"xAxisFormatType": "auto",
"xmin": "",
"xmax": "",
"yAxisLabel": "",
"yAxisProperty": "payload",
"yAxisPropertyType": "msg",
"ymin": "",
"ymax": "",
"bins": 10,
"action": "append",
"stackSeries": false,
"pointShape": "circle",
"pointRadius": 4,
"showLegend": true,
"removeOlder": 1,
"removeOlderUnit": "3600",
"removeOlderPoints": "",
"colors": [
"#0095ff",
"#ff0000",
"#ff7f0e",
"#2ca02c",
"#a347e1",
"#d62728",
"#ff9896",
"#9467bd",
"#c5b0d5"
],
"textColor": [
"#666666"
],
"textColorDefault": true,
"gridColor": [
"#e5e5e5"
],
"gridColorDefault": true,
"width": 6,
"height": 8,
"className": "",
"x": 510,
"y": 120,
"wires": [
[]
]
},
{
"id": "dashboard-ui-group",
"type": "ui-group",
"name": "Group 1",
"page": "dashboard-ui-page-1",
"width": "12",
"height": "1",
"order": -1,
"showTitle": true,
"className": "",
"visible": "true",
"disabled": "false"
},
{
"id": "dashboard-ui-page-1",
"type": "ui-page",
"name": "Page 1",
"ui": "dashboard-ui-base",
"path": "/page1",
"icon": "",
"layout": "grid",
"theme": "dashboard-ui-theme",
"order": -1,
"className": "",
"visible": "true",
"disabled": false
},
{
"id": "dashboard-ui-base",
"type": "ui-base",
"name": "UI Name",
"path": "/dashboard",
"includeClientData": true,
"acceptsClientConfig": [
"ui-notification",
"ui-control"
]
},
{
"id": "dashboard-ui-theme",
"type": "ui-theme",
"name": "Default",
"colors": {
"surface": "#ffffff",
"primary": "#6771f4",
"bgPage": "#e5dcdc",
"groupBg": "#ffffff",
"groupOutline": "#d39292"
},
"sizes": {
"pagePadding": "6px",
"groupGap": "12px",
"groupBorderRadius": "4px",
"widgetGap": "6px",
"density": "default"
}
}
]
51 changes: 51 additions & 0 deletions cypress/tests/widgets/chart.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,55 @@ describe('Node/-RED Dashboard 2.0 - Chart - Data Sets', () => {
checkSeries(barChart.chart.config.data.datasets[3], 'Q4', [[2021, 163], [2022, 210], [2023, 138]])
})
})

it('renders charts correctly when x is set to "timestamp"', () => {
cy.deployFixture('dashboard-chart-timestamp')
cy.visit('/dashboard/page1')

// new (from 1.18.1)
cy.get('#nrdb-ui-widget-line-chart-timestamp > div > canvas').should('exist')

// legacy charts pre 1.18.1, which rendered time when xAxisProperty was empty
cy.get('#nrdb-ui-widget-line-chart-empty-xProp > div > canvas').should('exist')

// Clear both charts
cy.clickAndWait(cy.get('button').contains('Button - Clear'))

// Add 3 data points to BOTH charts, 200 milliseconds apart
cy.clickAndWait(cy.get('button').contains('Button - Number'), 200)
cy.clickAndWait(cy.get('button').contains('Button - Number'), 200)
cy.clickAndWait(cy.get('button').contains('Button - Number'), 200)

// eslint-disable-next-line promise/catch-or-return, promise/always-return
cy.window().then(win => {
should(win.uiCharts).is.not.empty()
const timestampXChart = win.uiCharts['line-chart-timestamp']
const emptyXChart = win.uiCharts['line-chart-empty-xProp']

// New Charts
should(timestampXChart.chart.config.data).be.an.Object()
should(timestampXChart.chart.config.data.datasets).be.an.Array()

// Legacy Charts
should(emptyXChart.chart.config.data).be.an.Object()
should(emptyXChart.chart.config.data.datasets).be.an.Array()

// Check data populated correctly
// New Charts
should(timestampXChart.chart.config.data.datasets[0].data).be.an.Array().and.have.length(3)

// Legacy Charts
should(emptyXChart.chart.config.data.datasets[0].data).be.an.Array().and.have.length(3)
// loop over the three data points
// eslint-disable-next-line promise/always-return
for (let i = 0; i < 3; i++) {
// New Charts
should(timestampXChart.chart.config.data.datasets[0].data[i]).have.property('x')
should(timestampXChart.chart.config.data.datasets[0].data[i]).have.property('y', 2)
// Legacy Charts
should(emptyXChart.chart.config.data.datasets[0].data[i]).have.property('x')
should(emptyXChart.chart.config.data.datasets[0].data[i]).have.property('y', 2)
}
})
})
})
8 changes: 4 additions & 4 deletions docs/nodes/widgets/ui-chart.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ props:
X-Axis Limit: Any data that is before the specific time limit (for time charts) or where there are more data points than the limit specified will be removed from the chart.
Properties:
<b>Series:</b> Controls how you want to set the Series of data stream into this widget. The default is <code>msg.topic</code>, where separate topics will render to a new line/bar in their respective plots.</br>
<b>X:</b> Only available for Line & Scatter Charts. This defines the key (which can be nested) of the value that should be plotted onto the x-axis. If left blank, the x-value will be calculated as the current timestamp.</br>
<b>Y:</b> Defines the key (which can be nested, e.g. <code>'nested.value'</code>) of the value that should be plotted onto the x-axis. This value is ignored if injecting single numerical values into the chart.
<b>X:</b> Defines which data to use when rendering the x-value of any data point.</br>
<b>Y:</b> Defines how to render the y-value of any data point.
Text Color: Option to override Chart.Js default color for text.
At moment overrides the text color for <code>Chart Title</code>, <code>Ticks Text</code>, <code>Axis Title</code> and <code>Legend Text</code></br>
It is possible to return to Chart.Js defaults by using the checkbox <code>Use ChartJs Default Text Colors</code>
Expand Down Expand Up @@ -99,8 +99,8 @@ To map your data to the chart, the most important properties to configure are:
_Example key mapping config for UI Chart_

- **Series**: Controls how you want to group your data. On a line chart, different series result in different lines for example, on a bar chart, different series result in different bars for a single x-value (stacked or grouped side-by-side).
- **X**: Define where to read the value to plot on the x-axis. If left blank, the x-value will be calculated as the current timestamp.
- **Y**: Define where to read the value to plot on the y-axis. If left blank, the y-value will be read from `msg.payload` directly, and assume it to be a number.
- **X**: Defines where to read the value to plot on the x-axis. This can be read from the `msg` object, as a `key` on an object, or generate a new `timestamp` for each data point being received to the node.
- **Y**: Define where to read the value to plot on the y-axis. This can be read as a property on the `msg` object, or as a `key` on objects in an array of data.

The next most important properties to configure are the "Chart Type" and "X-Axis Type".

Expand Down
4 changes: 2 additions & 2 deletions nodes/widgets/locales/en-US/ui_chart.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ <h3>Properties</h3>
<dt>Properties <span class="property-type">string</span></dt>
<dd>
<p><b>Series:</b> Controls how you want to set the Series of data stream into this widget. The default is <code>msg.topic</code>, where separate topics will render to a new line/bar in their respective plots. You can also provide a JSON array, which will plot multiple data points from a single msg object.</p>
<p><b>X:</b> Only available for Line & Scatter Charts. This defines the key (which can be nested) of the value that should be plotted onto the X-axis. If left blank, the X-value will be calculated as the current timestamp.</p>
<p><b>Y:</b> Defines the key (which can be nested, e.g. <code>'nested.value'</code>) of the value that should be plotted onto the X-axis. This value is ignored if injecting single numerical values into the chart.</p>
<p><b>X:</b> Defines which data to use when rendering the x-value of any data point.</p>
<p><b>Y:</b> Defines how to render the y-value of any data point.</p>
</dd>
</dl>
<h3>Input</h3>
Expand Down
1 change: 1 addition & 0 deletions nodes/widgets/locales/en-US/ui_chart.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"properties": "Properties",
"series": "Series:",
"key": "key:",
"timestamp": "timestamp",
"propertyPlaceholder": "property",
"pointStyle": "Point Style",
"pointShape": "Shape",
Expand Down
Loading

0 comments on commit dfdfb39

Please sign in to comment.