diff --git a/cypress/fixtures/flows/dashboard-chart-timestamp.json b/cypress/fixtures/flows/dashboard-chart-timestamp.json
new file mode 100644
index 000000000..9c0179139
--- /dev/null
+++ b/cypress/fixtures/flows/dashboard-chart-timestamp.json
@@ -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"
+ }
+ }
+]
\ No newline at end of file
diff --git a/cypress/tests/widgets/chart.spec.js b/cypress/tests/widgets/chart.spec.js
index 347269838..295407448 100644
--- a/cypress/tests/widgets/chart.spec.js
+++ b/cypress/tests/widgets/chart.spec.js
@@ -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)
+ }
+ })
+ })
})
diff --git a/docs/nodes/widgets/ui-chart.md b/docs/nodes/widgets/ui-chart.md
index cc3c0413b..5b920fc77 100644
--- a/docs/nodes/widgets/ui-chart.md
+++ b/docs/nodes/widgets/ui-chart.md
@@ -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:
Series: Controls how you want to set the Series of data stream into this widget. The default is msg.topic
, where separate topics will render to a new line/bar in their respective plots.
- X: 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.
- Y: Defines the key (which can be nested, e.g. 'nested.value'
) of the value that should be plotted onto the x-axis. This value is ignored if injecting single numerical values into the chart.
+ X: Defines which data to use when rendering the x-value of any data point.
+ Y: 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 Chart Title
, Ticks Text
, Axis Title
and Legend Text
It is possible to return to Chart.Js defaults by using the checkbox Use ChartJs Default Text Colors
@@ -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".
diff --git a/nodes/widgets/locales/en-US/ui_chart.html b/nodes/widgets/locales/en-US/ui_chart.html
index 21bb2dfb2..8fc1784ca 100644
--- a/nodes/widgets/locales/en-US/ui_chart.html
+++ b/nodes/widgets/locales/en-US/ui_chart.html
@@ -26,8 +26,8 @@
Series: Controls how you want to set the Series of data stream into this widget. The default is msg.topic
, 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.
X: 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.
-Y: Defines the key (which can be nested, e.g. 'nested.value'
) of the value that should be plotted onto the X-axis. This value is ignored if injecting single numerical values into the chart.
X: Defines which data to use when rendering the x-value of any data point.
+Y: Defines how to render the y-value of any data point.