mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Add change option to statistics chart (#14396)
This commit is contained in:
parent
c5ec1797f6
commit
185d2f1d52
@ -32,7 +32,7 @@ import {
|
|||||||
import type { HomeAssistant } from "../../types";
|
import type { HomeAssistant } from "../../types";
|
||||||
import "./ha-chart-base";
|
import "./ha-chart-base";
|
||||||
|
|
||||||
export type ExtendedStatisticType = StatisticType | "state";
|
export type ExtendedStatisticType = StatisticType | "state" | "change";
|
||||||
|
|
||||||
export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
|
export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
|
||||||
mean: "mean",
|
mean: "mean",
|
||||||
@ -40,7 +40,9 @@ export const statTypeMap: Record<ExtendedStatisticType, StatisticType> = {
|
|||||||
max: "max",
|
max: "max",
|
||||||
sum: "sum",
|
sum: "sum",
|
||||||
state: "sum",
|
state: "sum",
|
||||||
|
change: "sum",
|
||||||
};
|
};
|
||||||
|
|
||||||
@customElement("statistics-chart")
|
@customElement("statistics-chart")
|
||||||
class StatisticsChart extends LitElement {
|
class StatisticsChart extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -361,6 +363,7 @@ class StatisticsChart extends LitElement {
|
|||||||
|
|
||||||
let prevDate: Date | null = null;
|
let prevDate: Date | null = null;
|
||||||
// Process chart data.
|
// Process chart data.
|
||||||
|
let firstSum: number | null = null;
|
||||||
let prevSum: number | null = null;
|
let prevSum: number | null = null;
|
||||||
stats.forEach((stat) => {
|
stats.forEach((stat) => {
|
||||||
const date = new Date(stat.start);
|
const date = new Date(stat.start);
|
||||||
@ -372,12 +375,19 @@ class StatisticsChart extends LitElement {
|
|||||||
statTypes.forEach((type) => {
|
statTypes.forEach((type) => {
|
||||||
let val: number | null;
|
let val: number | null;
|
||||||
if (type === "sum") {
|
if (type === "sum") {
|
||||||
if (prevSum === null) {
|
if (firstSum === null) {
|
||||||
val = 0;
|
val = 0;
|
||||||
prevSum = stat.sum;
|
firstSum = stat.sum;
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
val = stat[type];
|
val = stat[type];
|
||||||
}
|
}
|
||||||
@ -386,9 +396,6 @@ class StatisticsChart extends LitElement {
|
|||||||
pushData(date, dataValues);
|
pushData(date, dataValues);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add an entry for final values
|
|
||||||
pushData(endTime, prevValues);
|
|
||||||
|
|
||||||
// Concat two arrays
|
// Concat two arrays
|
||||||
Array.prototype.push.apply(totalDataSets, statDataSets);
|
Array.prototype.push.apply(totalDataSets, statDataSets);
|
||||||
});
|
});
|
||||||
|
@ -89,23 +89,25 @@ export class HaSelectSelector extends LitElement {
|
|||||||
!this.value || this.value === "" ? [] : (this.value as string[]);
|
!this.value || this.value === "" ? [] : (this.value as string[]);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-chip-set>
|
${value?.length
|
||||||
${value?.map(
|
? html`<ha-chip-set>
|
||||||
(item, idx) =>
|
${value.map(
|
||||||
html`
|
(item, idx) =>
|
||||||
<ha-chip hasTrailingIcon>
|
html`
|
||||||
${options.find((option) => option.value === item)?.label ||
|
<ha-chip hasTrailingIcon>
|
||||||
item}
|
${options.find((option) => option.value === item)
|
||||||
<ha-svg-icon
|
?.label || item}
|
||||||
slot="trailing-icon"
|
<ha-svg-icon
|
||||||
.path=${mdiClose}
|
slot="trailing-icon"
|
||||||
.idx=${idx}
|
.path=${mdiClose}
|
||||||
@click=${this._removeItem}
|
.idx=${idx}
|
||||||
></ha-svg-icon>
|
@click=${this._removeItem}
|
||||||
</ha-chip>
|
></ha-svg-icon>
|
||||||
`
|
</ha-chip>
|
||||||
)}
|
`
|
||||||
</ha-chip-set>
|
)}
|
||||||
|
</ha-chip-set>`
|
||||||
|
: ""}
|
||||||
|
|
||||||
<ha-combo-box
|
<ha-combo-box
|
||||||
item-value-path="value"
|
item-value-path="value"
|
||||||
@ -116,7 +118,7 @@ export class HaSelectSelector extends LitElement {
|
|||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required && !value.length}
|
.required=${this.required && !value.length}
|
||||||
.value=${this._filter}
|
.value=${this._filter}
|
||||||
.items=${options.filter(
|
.filteredItems=${options.filter(
|
||||||
(option) => !option.disabled && !value?.includes(option.value)
|
(option) => !option.disabled && !value?.includes(option.value)
|
||||||
)}
|
)}
|
||||||
@filter-changed=${this._filterChanged}
|
@filter-changed=${this._filterChanged}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
@ -18,6 +19,7 @@ import {
|
|||||||
StatisticsMetaData,
|
StatisticsMetaData,
|
||||||
} from "../../../data/recorder";
|
} from "../../../data/recorder";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { findEntities } from "../common/find-entities";
|
||||||
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
|
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
|
||||||
import { processConfigEntities } from "../common/process-config-entities";
|
import { processConfigEntities } from "../common/process-config-entities";
|
||||||
import { LovelaceCard } from "../types";
|
import { LovelaceCard } from "../types";
|
||||||
@ -30,8 +32,25 @@ export class HuiStatisticsGraphCard extends LitElement implements LovelaceCard {
|
|||||||
return document.createElement("hui-statistics-graph-card-editor");
|
return document.createElement("hui-statistics-graph-card-editor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getStubConfig(): StatisticsGraphCardConfig {
|
public static getStubConfig(
|
||||||
return { type: "statistics-graph", entities: [] };
|
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;
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
@ -23,7 +23,10 @@ import { fireEvent } from "../../../../common/dom/fire_event";
|
|||||||
import { ensureArray } from "../../../../common/ensure-array";
|
import { ensureArray } from "../../../../common/ensure-array";
|
||||||
import type { LocalizeFunc } from "../../../../common/translations/localize";
|
import type { LocalizeFunc } from "../../../../common/translations/localize";
|
||||||
import { deepEqual } from "../../../../common/util/deep-equal";
|
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/entity/ha-statistics-picker";
|
||||||
import "../../../../components/ha-form/ha-form";
|
import "../../../../components/ha-form/ha-form";
|
||||||
import type { HaFormSchema } from "../../../../components/ha-form/types";
|
import type { HaFormSchema } from "../../../../components/ha-form/types";
|
||||||
@ -44,6 +47,7 @@ import { entitiesConfigStruct } from "../structs/entities-struct";
|
|||||||
const statTypeStruct = union([
|
const statTypeStruct = union([
|
||||||
literal("state"),
|
literal("state"),
|
||||||
literal("sum"),
|
literal("sum"),
|
||||||
|
literal("change"),
|
||||||
literal("min"),
|
literal("min"),
|
||||||
literal("max"),
|
literal("max"),
|
||||||
literal("mean"),
|
literal("mean"),
|
||||||
@ -71,7 +75,14 @@ const cardConfigStruct = assign(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const periods = ["5minute", "hour", "day", "week", "month"] as const;
|
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")
|
@customElement("hui-statistics-graph-card-editor")
|
||||||
export class HuiStatisticsGraphCardEditor
|
export class HuiStatisticsGraphCardEditor
|
||||||
@ -165,6 +176,7 @@ export class HuiStatisticsGraphCardEditor
|
|||||||
selector: {
|
selector: {
|
||||||
select: {
|
select: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
|
mode: "list",
|
||||||
options: stat_types.map((stat_type) => ({
|
options: stat_types.map((stat_type) => ({
|
||||||
value: stat_type,
|
value: stat_type,
|
||||||
label: localize(
|
label: localize(
|
||||||
@ -222,13 +234,13 @@ export class HuiStatisticsGraphCardEditor
|
|||||||
this._metaDatas
|
this._metaDatas
|
||||||
);
|
);
|
||||||
const configured_stat_types = this._config!.stat_types
|
const configured_stat_types = this._config!.stat_types
|
||||||
? Array.isArray(this._config!.stat_types)
|
? ensureArray(this._config.stat_types)
|
||||||
? this._config!.stat_types
|
: stat_types.filter(
|
||||||
: [this._config!.stat_types]
|
(stat_type) =>
|
||||||
: stat_types.filter((stat_type) =>
|
stat_type !== "change" &&
|
||||||
this._metaDatas?.every((metaData) =>
|
this._metaDatas?.every((metaData) =>
|
||||||
statisticsMetaHasType(metaData, statTypeMap[stat_type])
|
statisticsMetaHasType(metaData, statTypeMap[stat_type])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
const data = {
|
const data = {
|
||||||
chart_type: "line",
|
chart_type: "line",
|
||||||
|
@ -525,7 +525,8 @@
|
|||||||
"max": "max",
|
"max": "max",
|
||||||
"mean": "mean",
|
"mean": "mean",
|
||||||
"state": "state",
|
"state": "state",
|
||||||
"sum": "sum"
|
"sum": "sum",
|
||||||
|
"change": "change"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"service-picker": {
|
"service-picker": {
|
||||||
@ -4063,7 +4064,8 @@
|
|||||||
"min": "Min",
|
"min": "Min",
|
||||||
"max": "Max",
|
"max": "Max",
|
||||||
"state": "State",
|
"state": "State",
|
||||||
"sum": "Sum (change during period)"
|
"sum": "Sum",
|
||||||
|
"change": "Change"
|
||||||
},
|
},
|
||||||
"chart_type": "Chart type",
|
"chart_type": "Chart type",
|
||||||
"periods": {
|
"periods": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user