mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Some Updates to the History Panel (#13095)
This commit is contained in:
parent
b285fda61b
commit
5038f9c3c6
@ -573,6 +573,8 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
.horizontal-container {
|
.horizontal-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
min-height: 56px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.mdc-chip {
|
.mdc-chip {
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
|
@ -10,9 +10,12 @@ import {
|
|||||||
startOfWeek,
|
startOfWeek,
|
||||||
startOfYesterday,
|
startOfYesterday,
|
||||||
} from "date-fns/esm";
|
} from "date-fns/esm";
|
||||||
|
import { UnsubscribeFunc } from "home-assistant-js-websocket/dist/types";
|
||||||
import { css, html, LitElement, PropertyValues } from "lit";
|
import { css, html, LitElement, PropertyValues } from "lit";
|
||||||
import { property, state } from "lit/decorators";
|
import { property, state } from "lit/decorators";
|
||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket/dist/types";
|
import { LocalStorage } from "../../common/decorators/local-storage";
|
||||||
|
import { computeDomain } from "../../common/entity/compute_domain";
|
||||||
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { navigate } from "../../common/navigate";
|
import { navigate } from "../../common/navigate";
|
||||||
import {
|
import {
|
||||||
createSearchParam,
|
createSearchParam,
|
||||||
@ -20,45 +23,43 @@ import {
|
|||||||
} from "../../common/url/search-params";
|
} from "../../common/url/search-params";
|
||||||
import { computeRTL } from "../../common/util/compute_rtl";
|
import { computeRTL } from "../../common/util/compute_rtl";
|
||||||
import "../../components/chart/state-history-charts";
|
import "../../components/chart/state-history-charts";
|
||||||
import "../../components/ha-target-picker";
|
|
||||||
import "../../components/ha-circular-progress";
|
import "../../components/ha-circular-progress";
|
||||||
import "../../components/ha-date-range-picker";
|
import "../../components/ha-date-range-picker";
|
||||||
import type { DateRangePickerRanges } from "../../components/ha-date-range-picker";
|
import type { DateRangePickerRanges } from "../../components/ha-date-range-picker";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
import "../../components/ha-menu-button";
|
import "../../components/ha-menu-button";
|
||||||
import { computeHistory, fetchDateWS } from "../../data/history";
|
import "../../components/ha-target-picker";
|
||||||
import "../../layouts/ha-app-layout";
|
|
||||||
import { haStyle } from "../../resources/styles";
|
|
||||||
import { HomeAssistant } from "../../types";
|
|
||||||
import {
|
|
||||||
EntityRegistryEntry,
|
|
||||||
subscribeEntityRegistry,
|
|
||||||
} from "../../data/entity_registry";
|
|
||||||
import {
|
import {
|
||||||
DeviceRegistryEntry,
|
DeviceRegistryEntry,
|
||||||
subscribeDeviceRegistry,
|
subscribeDeviceRegistry,
|
||||||
} from "../../data/device_registry";
|
} from "../../data/device_registry";
|
||||||
|
import {
|
||||||
|
EntityRegistryEntry,
|
||||||
|
subscribeEntityRegistry,
|
||||||
|
} from "../../data/entity_registry";
|
||||||
|
import { computeHistory, fetchDateWS } from "../../data/history";
|
||||||
|
import "../../layouts/ha-app-layout";
|
||||||
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { haStyle } from "../../resources/styles";
|
||||||
import { computeDomain } from "../../common/entity/compute_domain";
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
class HaPanelHistory extends SubscribeMixin(LitElement) {
|
class HaPanelHistory extends SubscribeMixin(LitElement) {
|
||||||
@property() hass!: HomeAssistant;
|
@property({ attribute: false }) hass!: HomeAssistant;
|
||||||
|
|
||||||
@property({ reflect: true, type: Boolean }) narrow!: boolean;
|
@property({ reflect: true, type: Boolean }) narrow!: boolean;
|
||||||
|
|
||||||
@property() _startDate: Date;
|
|
||||||
|
|
||||||
@property() _endDate: Date;
|
|
||||||
|
|
||||||
@property() _targetPickerValue?;
|
|
||||||
|
|
||||||
@property() _isLoading = false;
|
|
||||||
|
|
||||||
@property() _stateHistory?;
|
|
||||||
|
|
||||||
@property({ reflect: true, type: Boolean }) rtl = false;
|
@property({ reflect: true, type: Boolean }) rtl = false;
|
||||||
|
|
||||||
|
@state() private _startDate: Date;
|
||||||
|
|
||||||
|
@state() private _endDate: Date;
|
||||||
|
|
||||||
|
@LocalStorage("historyPickedValue", true, false) private _targetPickerValue?;
|
||||||
|
|
||||||
|
@state() private _isLoading = false;
|
||||||
|
|
||||||
|
@state() private _stateHistory?;
|
||||||
|
|
||||||
@state() private _ranges?: DateRangePickerRanges;
|
@state() private _ranges?: DateRangePickerRanges;
|
||||||
|
|
||||||
@state() private _devices?: { [deviceId: string]: DeviceRegistryEntry };
|
@state() private _devices?: { [deviceId: string]: DeviceRegistryEntry };
|
||||||
@ -154,14 +155,18 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
.narrow=${this.narrow}
|
.narrow=${this.narrow}
|
||||||
></ha-menu-button>
|
></ha-menu-button>
|
||||||
<div main-title>${this.hass.localize("panel.history")}</div>
|
<div main-title>${this.hass.localize("panel.history")}</div>
|
||||||
|
${this._targetPickerValue
|
||||||
|
? html`
|
||||||
|
<ha-icon-button
|
||||||
|
@click=${this._removeAll}
|
||||||
|
.disabled=${this._isLoading}
|
||||||
|
.path=${mdiCollapseAll}
|
||||||
|
.label=${this.hass.localize("ui.panel.history.remove_all")}
|
||||||
|
></ha-icon-button>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
@click=${this._removeAll}
|
@click=${this._getHistory}
|
||||||
.disabled=${this._isLoading}
|
|
||||||
.path=${mdiCollapseAll}
|
|
||||||
.label=${this.hass.localize("ui.panel.history.remove_all")}
|
|
||||||
></ha-icon-button>
|
|
||||||
<ha-icon-button
|
|
||||||
@click=${this._refreshHistory}
|
|
||||||
.disabled=${this._isLoading}
|
.disabled=${this._isLoading}
|
||||||
.path=${mdiRefresh}
|
.path=${mdiRefresh}
|
||||||
.label=${this.hass.localize("ui.common.refresh")}
|
.label=${this.hass.localize("ui.common.refresh")}
|
||||||
@ -252,69 +257,75 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
if (
|
if (
|
||||||
changedProps.has("_startDate") ||
|
this._targetPickerValue &&
|
||||||
changedProps.has("_endDate") ||
|
(changedProps.has("_startDate") ||
|
||||||
changedProps.has("_targetPickerValue")
|
changedProps.has("_endDate") ||
|
||||||
|
changedProps.has("_targetPickerValue") ||
|
||||||
|
(!this._stateHistory &&
|
||||||
|
(changedProps.has("_entities") ||
|
||||||
|
changedProps.has("_devices") ||
|
||||||
|
changedProps.has("_stateEntities") ||
|
||||||
|
changedProps.has("_deviceIdToEntities") ||
|
||||||
|
changedProps.has("_areaIdToEntities") ||
|
||||||
|
changedProps.has("_areaIdToDevices"))))
|
||||||
) {
|
) {
|
||||||
this._getHistory();
|
this._getHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changedProps.has("hass") || changedProps.has("_entities")) {
|
if (!changedProps.has("hass") && !changedProps.has("_entities")) {
|
||||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
return;
|
||||||
if (!oldHass || oldHass.language !== this.hass.language) {
|
}
|
||||||
this.rtl = computeRTL(this.hass);
|
|
||||||
}
|
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||||
if (this._entities) {
|
if (!oldHass || oldHass.language !== this.hass.language) {
|
||||||
const stateEntities: { [entityId: string]: EntityRegistryEntry } = {};
|
this.rtl = computeRTL(this.hass);
|
||||||
const regEntityIds = new Set(Object.keys(this._entities));
|
}
|
||||||
for (const entityId of Object.keys(this.hass.states)) {
|
|
||||||
if (regEntityIds.has(entityId)) {
|
if (this._entities) {
|
||||||
continue;
|
const stateEntities: { [entityId: string]: EntityRegistryEntry } = {};
|
||||||
}
|
const regEntityIds = new Set(Object.keys(this._entities));
|
||||||
stateEntities[entityId] = {
|
for (const entityId of Object.keys(this.hass.states)) {
|
||||||
name: computeStateName(this.hass.states[entityId]),
|
if (regEntityIds.has(entityId)) {
|
||||||
entity_id: entityId,
|
continue;
|
||||||
platform: computeDomain(entityId),
|
|
||||||
disabled_by: null,
|
|
||||||
hidden_by: null,
|
|
||||||
area_id: null,
|
|
||||||
config_entry_id: null,
|
|
||||||
device_id: null,
|
|
||||||
icon: null,
|
|
||||||
entity_category: null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
this._stateEntities = stateEntities;
|
stateEntities[entityId] = {
|
||||||
|
name: computeStateName(this.hass.states[entityId]),
|
||||||
|
entity_id: entityId,
|
||||||
|
platform: computeDomain(entityId),
|
||||||
|
disabled_by: null,
|
||||||
|
hidden_by: null,
|
||||||
|
area_id: null,
|
||||||
|
config_entry_id: null,
|
||||||
|
device_id: null,
|
||||||
|
icon: null,
|
||||||
|
entity_category: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
this._stateEntities = stateEntities;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _removeAll() {
|
private _removeAll() {
|
||||||
this._targetPickerValue = undefined;
|
this._targetPickerValue = undefined;
|
||||||
}
|
this._updatePath();
|
||||||
|
|
||||||
private _refreshHistory() {
|
|
||||||
this._getHistory();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _shouldShowEntityByLargerSelection(
|
|
||||||
entity: EntityRegistryEntry
|
|
||||||
): boolean {
|
|
||||||
return entity.entity_category === null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _getHistory() {
|
private async _getHistory() {
|
||||||
this._isLoading = true;
|
this._isLoading = true;
|
||||||
const entityIds = this._getEntityIds();
|
const entityIds = this._getEntityIds();
|
||||||
const dateHistory =
|
|
||||||
entityIds.length === 0
|
if (!entityIds.length) {
|
||||||
? {}
|
this._stateHistory = undefined;
|
||||||
: await fetchDateWS(
|
return;
|
||||||
this.hass,
|
}
|
||||||
this._startDate,
|
|
||||||
this._endDate,
|
const dateHistory = await fetchDateWS(
|
||||||
entityIds
|
this.hass,
|
||||||
);
|
this._startDate,
|
||||||
|
this._endDate,
|
||||||
|
entityIds
|
||||||
|
);
|
||||||
|
|
||||||
this._stateHistory = computeHistory(
|
this._stateHistory = computeHistory(
|
||||||
this.hass,
|
this.hass,
|
||||||
dateHistory,
|
dateHistory,
|
||||||
@ -341,19 +352,24 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
device_id: searchingDeviceId,
|
device_id: searchingDeviceId,
|
||||||
entity_id: searchingEntityId,
|
entity_id: searchingEntityId,
|
||||||
} = this._targetPickerValue;
|
} = this._targetPickerValue;
|
||||||
|
|
||||||
if (searchingAreaId !== undefined) {
|
if (searchingAreaId !== undefined) {
|
||||||
if (typeof searchingAreaId === "string") {
|
searchingAreaId =
|
||||||
searchingAreaId = [searchingAreaId];
|
typeof searchingAreaId === "string"
|
||||||
}
|
? [searchingAreaId]
|
||||||
|
: searchingAreaId;
|
||||||
for (const singleSearchingAreaId of searchingAreaId) {
|
for (const singleSearchingAreaId of searchingAreaId) {
|
||||||
const foundEntities = this._areaIdToEntities[singleSearchingAreaId];
|
const foundEntities = this._areaIdToEntities[singleSearchingAreaId];
|
||||||
if (foundEntities !== undefined) {
|
if (!foundEntities) {
|
||||||
for (const foundEntity of foundEntities) {
|
continue;
|
||||||
if (this._shouldShowEntityByLargerSelection(foundEntity)) {
|
}
|
||||||
entityIds.add(foundEntity.entity_id);
|
|
||||||
}
|
for (const foundEntity of foundEntities) {
|
||||||
|
if (foundEntity.entity_category === null) {
|
||||||
|
entityIds.add(foundEntity.entity_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const foundDevices = this._areaIdToDevices[singleSearchingAreaId];
|
const foundDevices = this._areaIdToDevices[singleSearchingAreaId];
|
||||||
if (foundDevices !== undefined) {
|
if (foundDevices !== undefined) {
|
||||||
for (const foundDevice of foundDevices) {
|
for (const foundDevice of foundDevices) {
|
||||||
@ -363,7 +379,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
if (
|
if (
|
||||||
(!foundDeviceEntity.area_id ||
|
(!foundDeviceEntity.area_id ||
|
||||||
foundDeviceEntity.area_id === singleSearchingAreaId) &&
|
foundDeviceEntity.area_id === singleSearchingAreaId) &&
|
||||||
this._shouldShowEntityByLargerSelection(foundDeviceEntity)
|
foundDeviceEntity.entity_category === null
|
||||||
) {
|
) {
|
||||||
entityIds.add(foundDeviceEntity.entity_id);
|
entityIds.add(foundDeviceEntity.entity_id);
|
||||||
}
|
}
|
||||||
@ -372,25 +388,31 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchingDeviceId !== undefined) {
|
if (searchingDeviceId !== undefined) {
|
||||||
if (typeof searchingDeviceId === "string") {
|
searchingDeviceId =
|
||||||
searchingDeviceId = [searchingDeviceId];
|
typeof searchingDeviceId === "string"
|
||||||
}
|
? [searchingDeviceId]
|
||||||
|
: searchingDeviceId;
|
||||||
for (const singleSearchingDeviceId of searchingDeviceId) {
|
for (const singleSearchingDeviceId of searchingDeviceId) {
|
||||||
const foundEntities = this._deviceIdToEntities[singleSearchingDeviceId];
|
const foundEntities = this._deviceIdToEntities[singleSearchingDeviceId];
|
||||||
if (foundEntities !== undefined) {
|
if (!foundEntities) {
|
||||||
for (const foundEntity of foundEntities) {
|
continue;
|
||||||
if (this._shouldShowEntityByLargerSelection(foundEntity)) {
|
}
|
||||||
entityIds.add(foundEntity.entity_id);
|
|
||||||
}
|
for (const foundEntity of foundEntities) {
|
||||||
|
if (foundEntity.entity_category === null) {
|
||||||
|
entityIds.add(foundEntity.entity_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchingEntityId !== undefined) {
|
if (searchingEntityId !== undefined) {
|
||||||
if (typeof searchingEntityId === "string") {
|
searchingEntityId =
|
||||||
searchingEntityId = [searchingEntityId];
|
typeof searchingEntityId === "string"
|
||||||
}
|
? [searchingEntityId]
|
||||||
|
: searchingEntityId;
|
||||||
for (const singleSearchingEntityId of searchingEntityId) {
|
for (const singleSearchingEntityId of searchingEntityId) {
|
||||||
entityIds.add(singleSearchingEntityId);
|
entityIds.add(singleSearchingEntityId);
|
||||||
}
|
}
|
||||||
@ -412,7 +434,6 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
private _entitiesChanged(ev) {
|
private _entitiesChanged(ev) {
|
||||||
this._targetPickerValue = ev.detail.value;
|
this._targetPickerValue = ev.detail.value;
|
||||||
|
|
||||||
this._updatePath();
|
this._updatePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,3 +553,9 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("ha-panel-history", HaPanelHistory);
|
customElements.define("ha-panel-history", HaPanelHistory);
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-panel-history": HaPanelHistory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user