diff --git a/front/src/components/boxs/chart/Chart.jsx b/front/src/components/boxs/chart/Chart.jsx
index bbbf93b017..acdf0721d4 100644
--- a/front/src/components/boxs/chart/Chart.jsx
+++ b/front/src/components/boxs/chart/Chart.jsx
@@ -6,6 +6,7 @@ import { Text } from 'preact-i18n';
import style from './style.css';
import { WEBSOCKET_MESSAGE_TYPES } from '../../../../../server/utils/constants';
import get from 'get-value';
+import withIntlAsProp from '../../../utils/withIntlAsProp';
import ApexChartComponent from './ApexChartComponent';
const ONE_HOUR_IN_MINUTES = 60;
@@ -57,6 +58,8 @@ const calculateVariation = (firstValue, lastValue) => {
return Math.round(((lastValue - firstValue) / Math.abs(firstValue)) * 100);
};
+const allEqual = arr => arr.every(val => val === arr[0]);
+
class Chartbox extends Component {
toggleDropdown = () => {
this.setState({
@@ -136,9 +139,12 @@ class Chartbox extends Component {
let emptySeries = true;
- const series = data.map(oneFeature => {
+ const series = data.map((oneFeature, index) => {
+ const oneUnit = this.props.box.units ? this.props.box.units[index] : this.props.box.unit;
+ const oneUnitTranslated = oneUnit ? this.props.intl.dictionary.deviceFeatureUnitShort[oneUnit] : null;
+ const name = oneUnitTranslated ? `${oneFeature.device.name} (${oneUnitTranslated})` : oneFeature.device.name;
return {
- name: oneFeature.device.name,
+ name,
data: oneFeature.values.map(value => {
emptySeries = false;
return {
@@ -156,22 +162,44 @@ class Chartbox extends Component {
};
if (data.length > 0) {
- const lastValuesArray = [];
- const variationArray = [];
- data.forEach(oneFeature => {
+ // Before now, there was a "unit" attribute in this box instead of "units",
+ // so we need to support "unit" as some users may already have the box with that param
+ const unit = this.props.box.units ? this.props.box.units[0] : this.props.box.unit;
+ // We check if all deviceFeatures selected are in the same unit
+ const allUnitsAreSame = this.props.box.units ? allEqual(this.props.box.units) : false;
+
+ // If all deviceFeatures selected are in the same unit
+ // We do a average of all values
+ if (allUnitsAreSame) {
+ const lastValuesArray = [];
+ const variationArray = [];
+ data.forEach(oneFeature => {
+ const { values } = oneFeature;
+ if (values.length === 0) {
+ return;
+ }
+ const firstElement = values[0];
+ const lastElement = values[values.length - 1];
+ const variation = calculateVariation(firstElement.value, lastElement.value);
+ const lastValue = lastElement.value;
+ variationArray.push(variation);
+ lastValuesArray.push(lastValue);
+ });
+ newState.variation = average(variationArray);
+ newState.lastValueRounded = roundWith2DecimalIfNeeded(average(lastValuesArray));
+ newState.unit = unit;
+ } else {
+ // If not, we only display the first value
+ const oneFeature = data[0];
const { values } = oneFeature;
- if (values.length === 0) {
- return;
+ if (values.length > 0) {
+ const firstElement = values[0];
+ const lastElement = values[values.length - 1];
+ newState.variation = calculateVariation(firstElement.value, lastElement.value);
+ newState.lastValueRounded = roundWith2DecimalIfNeeded(lastElement.value);
+ newState.unit = unit;
}
- const firstElement = values[0];
- const lastElement = values[values.length - 1];
- const variation = calculateVariation(firstElement.value, lastElement.value);
- const lastValue = lastElement.value;
- variationArray.push(variation);
- lastValuesArray.push(lastValue);
- });
- newState.variation = average(variationArray);
- newState.lastValueRounded = roundWith2DecimalIfNeeded(average(lastValuesArray));
+ }
}
await this.setState(newState);
@@ -228,7 +256,7 @@ class Chartbox extends Component {
this.updateDeviceStateWebsocket
);
}
- render(props, { loading, series, labels, dropdown, variation, lastValueRounded, interval, emptySeries }) {
+ render(props, { loading, series, labels, dropdown, variation, lastValueRounded, interval, emptySeries, unit }) {
const displayVariation = props.box.display_variation;
return (
@@ -308,7 +336,7 @@ class Chartbox extends Component {
{notNullNotUndefined(lastValueRounded) && !Number.isNaN(lastValueRounded) && (
{lastValueRounded}
- {props.box.unit !== undefined && }
+ {unit !== undefined && }
)}
+
+
+
)}
{emptySeries === false && !props.box.display_axes && (
@@ -431,4 +462,4 @@ class Chartbox extends Component {
}
}
-export default connect('httpClient,session,user')(Chartbox);
+export default withIntlAsProp(connect('httpClient,session,user')(Chartbox));
diff --git a/front/src/components/boxs/chart/EditChart.jsx b/front/src/components/boxs/chart/EditChart.jsx
index cc9bff180f..9d809614cb 100644
--- a/front/src/components/boxs/chart/EditChart.jsx
+++ b/front/src/components/boxs/chart/EditChart.jsx
@@ -67,14 +67,19 @@ class EditChart extends Component {
const deviceFeaturesSelectors = selectedDeviceFeaturesOptions.map(
selectedDeviceFeaturesOption => selectedDeviceFeaturesOption.value
);
- const firstDeviceFeature = this.deviceFeatureBySelector.get(selectedDeviceFeaturesOptions[0].value);
+ const units = selectedDeviceFeaturesOptions.map(selectedDeviceFeaturesOption => {
+ const deviceFeature = this.deviceFeatureBySelector.get(selectedDeviceFeaturesOption.value);
+ return deviceFeature.unit;
+ });
this.props.updateBoxConfig(this.props.x, this.props.y, {
device_features: deviceFeaturesSelectors,
- unit: firstDeviceFeature && firstDeviceFeature.unit ? firstDeviceFeature.unit : undefined
+ units,
+ unit: undefined
});
} else {
this.props.updateBoxConfig(this.props.x, this.props.y, {
device_features: [],
+ units: [],
unit: undefined
});
}
@@ -138,8 +143,8 @@ class EditChart extends Component {
componentDidUpdate(previousProps) {
const deviceFeatureChanged = get(previousProps, 'box.device_feature') !== get(this.props, 'box.device_feature');
- const unitChanged = get(previousProps, 'box.unit') !== get(this.props, 'box.unit');
- if (deviceFeatureChanged || unitChanged) {
+ const unitsChanged = get(previousProps, 'box.units') !== get(this.props, 'box.units');
+ if (deviceFeatureChanged || unitsChanged) {
this.getDeviceFeatures();
}
}
diff --git a/front/src/components/boxs/chart/style.css b/front/src/components/boxs/chart/style.css
index 7fa3bb2ed4..7070bacbf7 100644
--- a/front/src/components/boxs/chart/style.css
+++ b/front/src/components/boxs/chart/style.css
@@ -124,5 +124,13 @@
.bigEmptyState {
margin-top: 0rem;
- margin-bottom: 2.2rem;
+ margin-bottom: 1rem;
+}
+
+.smallTextEmptyState {
+ margin-top: 1rem;
+ font-size: 12px;
+ padding-left: 1.5rem;
+ padding-right: 1.5rem;
+ text-align: justify;
}
diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json
index c3e75fae88..5a5f0f61e2 100644
--- a/front/src/config/i18n/en.json
+++ b/front/src/config/i18n/en.json
@@ -255,7 +255,8 @@
"lastThirtyDays": "Last 30 days",
"lastThreeMonths": "Last 3 months",
"lastYear": "Last year",
- "noValue": "No values recorded on this interval",
+ "noValue": "No values recorded on this interval.",
+ "noValueWarning": "Warning: if you just configured this device, it may take some time before you see something here as Gladys needs some time to collect enough data. For interval superior to 24h, it may take up to 24h before you see something here.",
"editNameLabel": "Enter the name of this box",
"editDeviceFeaturesLabel": "Select the device you want to display here",
"editRoomLabel": "Select the room you want to display here",
diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json
index 9107b74e83..13f46e9f5e 100644
--- a/front/src/config/i18n/fr.json
+++ b/front/src/config/i18n/fr.json
@@ -250,12 +250,13 @@
"chart": {
"defaultInterval": "Intervalle par défaut",
"lastHour": "Dernière heure",
- "lastDay": "Dernière 24h",
+ "lastDay": "Dernières 24h",
"lastSevenDays": "Derniers 7 jours",
"lastThirtyDays": "Derniers 30 jours",
"lastThreeMonths": "Derniers 3 mois",
"lastYear": "Dernière année",
- "noValue": "Pas de valeurs sur cet interval",
+ "noValue": "Pas de valeurs sur cet intervalle.",
+ "noValueWarning": "Attention, si vous venez de configurer cet appareil, les données peuvent mettre un certain temps avant d'être aggrégées. Pour les intervalles supérieurs à 24h, cela prend jusqu'à 24h le temps que Gladys collecte assez de données.",
"editNameLabel": "Entrez le nom de cette box",
"editNamePlaceholder": "Nom affiché sur le tableau de bord",
"editDeviceFeaturesLabel": "Sélectionnez les appareils que vous voulez afficher",
diff --git a/server/models/dashboard.js b/server/models/dashboard.js
index edd9dc09b0..3c0ab41e98 100644
--- a/server/models/dashboard.js
+++ b/server/models/dashboard.js
@@ -16,6 +16,7 @@ const boxesSchema = Joi.array().items(
device_features: Joi.array().items(Joi.string()),
device_feature: Joi.string(),
unit: Joi.string(),
+ units: Joi.array().items(Joi.string()),
title: Joi.string(),
interval: Joi.string(),
display_axes: Joi.boolean(),