Improvements to stat charts (#14427)

This commit is contained in:
Bram Kragten 2022-11-24 10:54:01 +01:00 committed by GitHub
parent f95a3c75f6
commit 8b817b35b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 40 deletions

View File

@ -197,6 +197,7 @@ class StatisticsChart extends LitElement {
elements: {
line: {
tension: 0.4,
cubicInterpolationMode: "monotone",
borderWidth: 1.5,
},
bar: { borderWidth: 1.5, borderRadius: 4 },
@ -280,33 +281,38 @@ class StatisticsChart extends LitElement {
// array containing [value1, value2, etc]
let prevValues: Array<number | null> | null = null;
let prevEndTime: Date | undefined;
// The datasets for the current statistic
const statDataSets: ChartDataset<"line">[] = [];
const pushData = (
timestamp: Date,
start: Date,
end: Date,
dataValues: Array<number | null> | null
) => {
if (!dataValues) return;
if (timestamp > endTime) {
if (start > end) {
// Drop data points that are after the requested endTime. This could happen if
// endTime is "now" and client time is not in sync with server time.
return;
}
statDataSets.forEach((d, i) => {
if (dataValues[i] === null && prevValues && prevValues[i] !== null) {
// null data values show up as gaps in the chart.
// If the current value for the dataset is null and the previous
// value of the data set is not null, then add an 'end' point
// to the chart for the previous value. Otherwise the gap will
// be too big. It will go from the start of the previous data
// value until the start of the next data value.
d.data.push({ x: timestamp.getTime(), y: prevValues[i]! });
if (
prevEndTime &&
prevValues &&
prevEndTime.getTime() !== start.getTime()
) {
// if the end of the previous data doesn't match the start of the current data,
// we have to draw a gap so add a value at the end time, and then an empty value.
d.data.push({ x: prevEndTime.getTime(), y: prevValues[i]! });
// @ts-expect-error
d.data.push({ x: prevEndTime.getTime(), y: null });
}
d.data.push({ x: timestamp.getTime(), y: dataValues[i]! });
d.data.push({ x: start.getTime(), y: dataValues[i]! });
});
prevValues = dataValues;
prevEndTime = end;
};
const color = getGraphColorByIndex(colorIndex, this._computedStyle!);
@ -365,11 +371,11 @@ class StatisticsChart extends LitElement {
let firstSum: number | null | undefined = null;
let prevSum: number | null | undefined = null;
stats.forEach((stat) => {
const date = new Date(stat.start);
if (prevDate === date) {
const startDate = new Date(stat.start);
if (prevDate === startDate) {
return;
}
prevDate = date;
prevDate = startDate;
const dataValues: Array<number | null> = [];
statTypes.forEach((type) => {
let val: number | null | undefined;
@ -396,7 +402,7 @@ class StatisticsChart extends LitElement {
: null
);
});
pushData(date, dataValues);
pushData(startDate, new Date(stat.end), dataValues);
});
// Concat two arrays

View File

@ -85,13 +85,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
if (!this.hasUpdated) {
return;
}
this._getStatistics();
// statistics are created every hour
clearInterval(this._interval);
this._interval = window.setInterval(
() => this._getStatistics(),
this._intervalTimeout
);
this._setFetchStatisticsTimer();
}
public getCardSize(): number {
@ -138,10 +132,7 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
public willUpdate(changedProps: PropertyValues) {
super.willUpdate(changedProps);
if (
!this._config ||
(!changedProps.has("_config") && !changedProps.has("_metadata"))
) {
if (!this._config || !changedProps.has("_config")) {
return;
}
@ -153,27 +144,33 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
changedProps.has("_config") &&
oldConfig?.entities !== this._config.entities
) {
this._getStatisticsMetaData(this._entities);
this._getStatisticsMetaData(this._entities).then(() => {
this._setFetchStatisticsTimer();
});
return;
}
if (
changedProps.has("_metadata") ||
(changedProps.has("_config") &&
(oldConfig?.entities !== this._config.entities ||
oldConfig?.days_to_show !== this._config.days_to_show ||
oldConfig?.period !== this._config.period ||
oldConfig?.unit !== this._config.unit))
changedProps.has("_config") &&
(oldConfig?.entities !== this._config.entities ||
oldConfig?.days_to_show !== this._config.days_to_show ||
oldConfig?.period !== this._config.period ||
oldConfig?.unit !== this._config.unit)
) {
this._getStatistics();
// statistics are created every hour
clearInterval(this._interval);
this._interval = window.setInterval(
() => this._getStatistics(),
this._intervalTimeout
);
this._setFetchStatisticsTimer();
}
}
private _setFetchStatisticsTimer() {
this._getStatistics();
// statistics are created every hour
clearInterval(this._interval);
this._interval = window.setInterval(
() => this._getStatistics(),
this._intervalTimeout
);
}
protected render(): TemplateResult {
if (!this.hass || !this._config) {
return html``;