Add change option to statistics chart (#14396)

This commit is contained in:
Bram Kragten 2022-11-16 18:09:54 +01:00 committed by GitHub
parent c5ec1797f6
commit 185d2f1d52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 38 deletions

View File

@ -32,7 +32,7 @@ import {
import type { HomeAssistant } from "../../types";
import "./ha-chart-base";
export type ExtendedStatisticType = StatisticType | "state";
export type ExtendedStatisticType = StatisticType | "state" | "change";
export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
mean: "mean",
@ -40,7 +40,9 @@ export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
max: "max",
sum: "sum",
state: "sum",
change: "sum",
};
@customElement("statistics-chart")
class StatisticsChart extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@ -361,6 +363,7 @@ class StatisticsChart extends LitElement {
let prevDate: Date | null = null;
// Process chart data.
let firstSum: number | null = null;
let prevSum: number | null = null;
stats.forEach((stat) => {
const date = new Date(stat.start);
@ -372,12 +375,19 @@ class StatisticsChart extends LitElement {
statTypes.forEach((type) => {
let val: number | null;
if (type === "sum") {
if (prevSum === null) {
if (firstSum === null) {
val = 0;
prevSum = stat.sum;
firstSum = stat.sum;
} else {
val = (stat.sum || 0) - prevSum;
val = (stat.sum || 0) - firstSum;
}
} else if (type === "change") {
if (prevSum === null) {
prevSum = stat.sum;
return;
}
val = (stat.sum || 0) - prevSum;
prevSum = stat.sum;
} else {
val = stat[type];
}
@ -386,9 +396,6 @@ class StatisticsChart extends LitElement {
pushData(date, dataValues);
});
// Add an entry for final values
pushData(endTime, prevValues);
// Concat two arrays
Array.prototype.push.apply(totalDataSets, statDataSets);
});

View File

@ -89,23 +89,25 @@ export class HaSelectSelector extends LitElement {
!this.value || this.value === "" ? [] : (this.value as string[]);
return html`
<ha-chip-set>
${value?.map(
(item, idx) =>
html`
<ha-chip hasTrailingIcon>
${options.find((option) => option.value === item)?.label ||
item}
<ha-svg-icon
slot="trailing-icon"
.path=${mdiClose}
.idx=${idx}
@click=${this._removeItem}
></ha-svg-icon>
</ha-chip>
`
)}
</ha-chip-set>
${value?.length
? html`<ha-chip-set>
${value.map(
(item, idx) =>
html`
<ha-chip hasTrailingIcon>
${options.find((option) => option.value === item)
?.label || item}
<ha-svg-icon
slot="trailing-icon"
.path=${mdiClose}
.idx=${idx}
@click=${this._removeItem}
></ha-svg-icon>
</ha-chip>
`
)}
</ha-chip-set>`
: ""}
<ha-combo-box
item-value-path="value"
@ -116,7 +118,7 @@ export class HaSelectSelector extends LitElement {
.disabled=${this.disabled}
.required=${this.required && !value.length}
.value=${this._filter}
.items=${options.filter(
.filteredItems=${options.filter(
(option) => !option.disabled && !value?.includes(option.value)
)}
@filter-changed=${this._filterChanged}

View File

@ -1,3 +1,4 @@
import { HassEntity } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
@ -18,6 +19,7 @@ import {
StatisticsMetaData,
} from "../../../data/recorder";
import { HomeAssistant } from "../../../types";
import { findEntities } from "../common/find-entities";
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
import { processConfigEntities } from "../common/process-config-entities";
import { LovelaceCard } from "../types";
@ -30,8 +32,25 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
return document.createElement("hui-statistics-graph-card-editor");
}
public static getStubConfig(): StatisticsGraphCardConfig {
return { type: "statistics-graph", entities: [] };
public static getStubConfig(
hass: HomeAssistant,
entities: string[],
entitiesFill: string[]
): StatisticsGraphCardConfig {
const includeDomains = ["sensor"];
const maxEntities = 1;
const foundEntities = findEntities(
hass,
maxEntities,
entities,
entitiesFill,
includeDomains,
(stateObj: HassEntity) => "state_class" in stateObj.attributes
);
return {
type: "statistics-graph",
entities: foundEntities.length ? [foundEntities[0]] : [],
};
}
@property({ attribute: false }) public hass?: HomeAssistant;

View File

@ -23,7 +23,10 @@ import { fireEvent } from "../../../../common/dom/fire_event";
import { ensureArray } from "../../../../common/ensure-array";
import type { LocalizeFunc } from "../../../../common/translations/localize";
import { deepEqual } from "../../../../common/util/deep-equal";
import { statTypeMap } from "../../../../components/chart/statistics-chart";
import {
ExtendedStatisticType,
statTypeMap,
} from "../../../../components/chart/statistics-chart";
import "../../../../components/entity/ha-statistics-picker";
import "../../../../components/ha-form/ha-form";
import type { HaFormSchema } from "../../../../components/ha-form/types";
@ -44,6 +47,7 @@ import { entitiesConfigStruct } from "../structs/entities-struct";
const statTypeStruct = union([
literal("state"),
literal("sum"),
literal("change"),
literal("min"),
literal("max"),
literal("mean"),
@ -71,7 +75,14 @@ const cardConfigStruct = assign(
);
const periods = ["5minute", "hour", "day", "week", "month"] as const;
const stat_types = ["mean", "min", "max", "sum", "state"] as const;
const stat_types = [
"mean",
"min",
"max",
"sum",
"state",
"change",
] as ExtendedStatisticType[];
@customElement("hui-statistics-graph-card-editor")
export class HuiStatisticsGraphCardEditor
@ -165,6 +176,7 @@ export class HuiStatisticsGraphCardEditor
selector: {
select: {
multiple: true,
mode: "list",
options: stat_types.map((stat_type) => ({
value: stat_type,
label: localize(
@ -222,13 +234,13 @@ export class HuiStatisticsGraphCardEditor
this._metaDatas
);
const configured_stat_types = this._config!.stat_types
? Array.isArray(this._config!.stat_types)
? this._config!.stat_types
: [this._config!.stat_types]
: stat_types.filter((stat_type) =>
this._metaDatas?.every((metaData) =>
statisticsMetaHasType(metaData, statTypeMap[stat_type])
)
? ensureArray(this._config.stat_types)
: stat_types.filter(
(stat_type) =>
stat_type !== "change" &&
this._metaDatas?.every((metaData) =>
statisticsMetaHasType(metaData, statTypeMap[stat_type])
)
);
const data = {
chart_type: "line",

View File

@ -525,7 +525,8 @@
"max": "max",
"mean": "mean",
"state": "state",
"sum": "sum"
"sum": "sum",
"change": "change"
}
},
"service-picker": {
@ -4063,7 +4064,8 @@
"min": "Min",
"max": "Max",
"state": "State",
"sum": "Sum (change during period)"
"sum": "Sum",
"change": "Change"
},
"chart_type": "Chart type",
"periods": {