Merge pull request #13138 from home-assistant/dev

This commit is contained in:
Bram Kragten 2022-07-07 15:29:24 +02:00 committed by GitHub
commit ee9ca16eb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 143 deletions

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "home-assistant-frontend" name = "home-assistant-frontend"
version = "20220706.0" version = "20220707.0"
license = {text = "Apache-2.0"} license = {text = "Apache-2.0"}
description = "The Home Assistant frontend" description = "The Home Assistant frontend"
readme = "README.md" readme = "README.md"

View File

@ -3,6 +3,8 @@ import { Store } from "home-assistant-js-websocket/dist/store";
import { stringCompare } from "../common/string/compare"; import { stringCompare } from "../common/string/compare";
import { debounce } from "../common/util/debounce"; import { debounce } from "../common/util/debounce";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import { DeviceRegistryEntry } from "./device_registry";
import { EntityRegistryEntry } from "./entity_registry";
export interface AreaRegistryEntry { export interface AreaRegistryEntry {
area_id: string; area_id: string;
@ -10,6 +12,14 @@ export interface AreaRegistryEntry {
picture: string | null; picture: string | null;
} }
export interface AreaEntityLookup {
[areaId: string]: EntityRegistryEntry[];
}
export interface AreaDeviceLookup {
[areaId: string]: DeviceRegistryEntry[];
}
export interface AreaRegistryEntryMutableParams { export interface AreaRegistryEntryMutableParams {
name: string; name: string;
picture?: string | null; picture?: string | null;
@ -79,3 +89,35 @@ export const subscribeAreaRegistry = (
conn, conn,
onChange onChange
); );
export const getAreaEntityLookup = (
entities: EntityRegistryEntry[]
): AreaEntityLookup => {
const areaEntityLookup: AreaEntityLookup = {};
for (const entity of entities) {
if (!entity.area_id) {
continue;
}
if (!(entity.area_id in areaEntityLookup)) {
areaEntityLookup[entity.area_id] = [];
}
areaEntityLookup[entity.area_id].push(entity);
}
return areaEntityLookup;
};
export const getAreaDeviceLookup = (
devices: DeviceRegistryEntry[]
): AreaDeviceLookup => {
const areaDeviceLookup: AreaDeviceLookup = {};
for (const device of devices) {
if (!device.area_id) {
continue;
}
if (!(device.area_id in areaDeviceLookup)) {
areaDeviceLookup[device.area_id] = [];
}
areaDeviceLookup[device.area_id].push(device);
}
return areaDeviceLookup;
};

View File

@ -126,3 +126,19 @@ export const sortDeviceRegistryByName = (entries: DeviceRegistryEntry[]) =>
entries.sort((entry1, entry2) => entries.sort((entry1, entry2) =>
caseInsensitiveStringCompare(entry1.name || "", entry2.name || "") caseInsensitiveStringCompare(entry1.name || "", entry2.name || "")
); );
export const getDeviceEntityLookup = (
entities: EntityRegistryEntry[]
): DeviceEntityLookup => {
const deviceEntityLookup: DeviceEntityLookup = {};
for (const entity of entities) {
if (!entity.device_id) {
continue;
}
if (!(entity.device_id in deviceEntityLookup)) {
deviceEntityLookup[entity.device_id] = [];
}
deviceEntityLookup[entity.device_id].push(entity);
}
return deviceEntityLookup;
};

View File

@ -99,6 +99,13 @@ export const getZwaveDeviceActions = async (
), ),
action: async () => { action: async () => {
if ( if (
isNodeFirmwareUpdateInProgress ||
(await fetchZwaveNodeIsFirmwareUpdateInProgress(hass, device.id))
) {
showZWaveJUpdateFirmwareNodeDialog(el, {
device,
});
} else if (
await showConfirmationDialog(el, { await showConfirmationDialog(el, {
text: hass.localize( text: hass.localize(
"ui.panel.config.zwave_js.update_firmware.warning" "ui.panel.config.zwave_js.update_firmware.warning"

View File

@ -18,12 +18,10 @@ import { css, html, LitElement, PropertyValues } from "lit";
import { property, state } from "lit/decorators"; import { property, state } from "lit/decorators";
import { LocalStorage } from "../../common/decorators/local-storage"; import { LocalStorage } from "../../common/decorators/local-storage";
import { ensureArray } from "../../common/ensure-array"; import { ensureArray } from "../../common/ensure-array";
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,
extractSearchParam, extractSearchParamsObject,
} 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";
@ -34,13 +32,17 @@ import "../../components/ha-icon-button";
import "../../components/ha-menu-button"; import "../../components/ha-menu-button";
import "../../components/ha-target-picker"; import "../../components/ha-target-picker";
import { import {
DeviceRegistryEntry, AreaDeviceLookup,
AreaEntityLookup,
getAreaDeviceLookup,
getAreaEntityLookup,
} from "../../data/area_registry";
import {
DeviceEntityLookup,
getDeviceEntityLookup,
subscribeDeviceRegistry, subscribeDeviceRegistry,
} from "../../data/device_registry"; } from "../../data/device_registry";
import { import { subscribeEntityRegistry } from "../../data/entity_registry";
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../../data/entity_registry";
import { computeHistory, fetchDateWS } from "../../data/history"; import { computeHistory, fetchDateWS } from "../../data/history";
import "../../layouts/ha-app-layout"; import "../../layouts/ha-app-layout";
import { SubscribeMixin } from "../../mixins/subscribe-mixin"; import { SubscribeMixin } from "../../mixins/subscribe-mixin";
@ -67,23 +69,11 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
@state() private _ranges?: DateRangePickerRanges; @state() private _ranges?: DateRangePickerRanges;
@state() private _devices?: { [deviceId: string]: DeviceRegistryEntry }; @state() private _deviceEntityLookup?: DeviceEntityLookup;
@state() private _entities?: { [entityId: string]: EntityRegistryEntry }; @state() private _areaEntityLookup?: AreaEntityLookup;
@state() private _stateEntities?: { [entityId: string]: EntityRegistryEntry }; @state() private _areaDeviceLookup?: AreaDeviceLookup;
@state() private _deviceIdToEntities?: {
[deviceId: string]: EntityRegistryEntry[];
};
@state() private _areaIdToEntities?: {
[areaId: string]: EntityRegistryEntry[];
};
@state() private _areaIdToDevices?: {
[areaId: string]: DeviceRegistryEntry[];
};
public constructor() { public constructor() {
super(); super();
@ -100,52 +90,11 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
public hassSubscribe(): UnsubscribeFunc[] { public hassSubscribe(): UnsubscribeFunc[] {
return [ return [
subscribeEntityRegistry(this.hass.connection!, (entities) => { subscribeEntityRegistry(this.hass.connection!, (entities) => {
this._entities = entities.reduce((accumulator, current) => { this._deviceEntityLookup = getDeviceEntityLookup(entities);
accumulator[current.entity_id] = current; this._areaEntityLookup = getAreaEntityLookup(entities);
return accumulator;
}, {});
this._deviceIdToEntities = entities.reduce((accumulator, current) => {
if (!current.device_id) {
return accumulator;
}
let found = accumulator[current.device_id];
if (found === undefined) {
found = [];
accumulator[current.device_id] = found;
}
found.push(current);
return accumulator;
}, {});
this._areaIdToEntities = entities.reduce((accumulator, current) => {
if (!current.area_id) {
return accumulator;
}
let found = accumulator[current.area_id];
if (found === undefined) {
found = [];
accumulator[current.area_id] = found;
}
found.push(current);
return accumulator;
}, {});
}), }),
subscribeDeviceRegistry(this.hass.connection!, (devices) => { subscribeDeviceRegistry(this.hass.connection!, (devices) => {
this._devices = devices.reduce((accumulator, current) => { this._areaDeviceLookup = getAreaDeviceLookup(devices);
accumulator[current.id] = current;
return accumulator;
}, {});
this._areaIdToDevices = devices.reduce((accumulator, current) => {
if (!current.area_id) {
return accumulator;
}
let found = accumulator[current.area_id];
if (found === undefined) {
found = [];
accumulator[current.area_id] = found;
}
found.push(current);
return accumulator;
}, {});
}), }),
]; ];
} }
@ -172,7 +121,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
: ""} : ""}
<ha-icon-button <ha-icon-button
@click=${this._getHistory} @click=${this._getHistory}
.disabled=${this._isLoading} .disabled=${this._isLoading || !this._targetPickerValue}
.path=${mdiRefresh} .path=${mdiRefresh}
.label=${this.hass.localize("ui.common.refresh")} .label=${this.hass.localize("ui.common.refresh")}
></ha-icon-button> ></ha-icon-button>
@ -246,9 +195,10 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
[addDays(weekStart, -7), addDays(weekEnd, -7)], [addDays(weekStart, -7), addDays(weekEnd, -7)],
}; };
const entityIds = extractSearchParam("entity_id"); const searchParams = extractSearchParamsObject();
const deviceIds = extractSearchParam("device_id"); const entityIds = searchParams.entity_id;
const areaIds = extractSearchParam("area_id"); const deviceIds = searchParams.device_id;
const areaIds = searchParams.area_id;
if (entityIds || deviceIds || areaIds) { if (entityIds || deviceIds || areaIds) {
this._targetPickerValue = {}; this._targetPickerValue = {};
} }
@ -265,11 +215,11 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._targetPickerValue!.area_id = splitIds; this._targetPickerValue!.area_id = splitIds;
} }
const startDate = extractSearchParam("start_date"); const startDate = searchParams.start_date;
if (startDate) { if (startDate) {
this._startDate = new Date(startDate); this._startDate = new Date(startDate);
} }
const endDate = extractSearchParam("end_date"); const endDate = searchParams.end_date;
if (endDate) { if (endDate) {
this._endDate = new Date(endDate); this._endDate = new Date(endDate);
} }
@ -282,12 +232,9 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
changedProps.has("_endDate") || changedProps.has("_endDate") ||
changedProps.has("_targetPickerValue") || changedProps.has("_targetPickerValue") ||
(!this._stateHistory && (!this._stateHistory &&
(changedProps.has("_entities") || (changedProps.has("_deviceEntityLookup") ||
changedProps.has("_devices") || changedProps.has("_areaEntityLookup") ||
changedProps.has("_stateEntities") || changedProps.has("_areaDeviceLookup"))))
changedProps.has("_deviceIdToEntities") ||
changedProps.has("_areaIdToEntities") ||
changedProps.has("_areaIdToDevices"))))
) { ) {
this._getHistory(); this._getHistory();
} }
@ -300,29 +247,6 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
if (!oldHass || oldHass.language !== this.hass.language) { if (!oldHass || oldHass.language !== this.hass.language) {
this.rtl = computeRTL(this.hass); this.rtl = computeRTL(this.hass);
} }
if (this._entities) {
const stateEntities: { [entityId: string]: EntityRegistryEntry } = {};
const regEntityIds = new Set(Object.keys(this._entities));
for (const entityId of Object.keys(this.hass.states)) {
if (regEntityIds.has(entityId)) {
continue;
}
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() {
@ -331,10 +255,14 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
} }
private async _getHistory() { private async _getHistory() {
if (!this._targetPickerValue) {
return;
}
this._isLoading = true; this._isLoading = true;
const entityIds = this._getEntityIds(); const entityIds = this._getEntityIds();
if (entityIds === undefined) { if (entityIds === undefined) {
this._isLoading = false;
this._stateHistory = undefined; this._stateHistory = undefined;
return; return;
} }
@ -344,34 +272,34 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
this._stateHistory = []; this._stateHistory = [];
return; return;
} }
try {
const dateHistory = await fetchDateWS(
this.hass,
this._startDate,
this._endDate,
entityIds
);
const dateHistory = await fetchDateWS( this._stateHistory = computeHistory(
this.hass, this.hass,
this._startDate, dateHistory,
this._endDate, this.hass.localize
entityIds );
); } finally {
this._isLoading = false;
this._stateHistory = computeHistory( }
this.hass,
dateHistory,
this.hass.localize
);
this._isLoading = false;
} }
private _getEntityIds(): string[] | undefined { private _getEntityIds(): string[] | undefined {
if ( if (
!this._targetPickerValue || !this._targetPickerValue ||
this._entities === undefined || this._deviceEntityLookup === undefined ||
this._stateEntities === undefined || this._areaEntityLookup === undefined ||
this._devices === undefined || this._areaDeviceLookup === undefined
this._deviceIdToEntities === undefined ||
this._areaIdToEntities === undefined ||
this._areaIdToDevices === undefined
) { ) {
return undefined; return undefined;
} }
const entityIds = new Set<string>(); const entityIds = new Set<string>();
let { let {
area_id: searchingAreaId, area_id: searchingAreaId,
@ -382,7 +310,7 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
if (searchingAreaId) { if (searchingAreaId) {
searchingAreaId = ensureArray(searchingAreaId); searchingAreaId = ensureArray(searchingAreaId);
for (const singleSearchingAreaId of searchingAreaId) { for (const singleSearchingAreaId of searchingAreaId) {
const foundEntities = this._areaIdToEntities[singleSearchingAreaId]; const foundEntities = this._areaEntityLookup[singleSearchingAreaId];
if (foundEntities?.length) { if (foundEntities?.length) {
for (const foundEntity of foundEntities) { for (const foundEntity of foundEntities) {
if (foundEntity.entity_category === null) { if (foundEntity.entity_category === null) {
@ -391,19 +319,24 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
} }
} }
const foundDevices = this._areaIdToDevices[singleSearchingAreaId]; const foundDevices = this._areaDeviceLookup[singleSearchingAreaId];
if (foundDevices) { if (!foundDevices?.length) {
for (const foundDevice of foundDevices) { continue;
const foundDeviceEntities = }
this._deviceIdToEntities[foundDevice.id];
for (const foundDeviceEntity of foundDeviceEntities) { for (const foundDevice of foundDevices) {
if ( const foundDeviceEntities = this._deviceEntityLookup[foundDevice.id];
(!foundDeviceEntity.area_id || if (!foundDeviceEntities?.length) {
foundDeviceEntity.area_id === singleSearchingAreaId) && continue;
foundDeviceEntity.entity_category === null }
) {
entityIds.add(foundDeviceEntity.entity_id); for (const foundDeviceEntity of foundDeviceEntities) {
} if (
(!foundDeviceEntity.area_id ||
foundDeviceEntity.area_id === singleSearchingAreaId) &&
foundDeviceEntity.entity_category === null
) {
entityIds.add(foundDeviceEntity.entity_id);
} }
} }
} }
@ -413,18 +346,20 @@ class HaPanelHistory extends SubscribeMixin(LitElement) {
if (searchingDeviceId) { if (searchingDeviceId) {
searchingDeviceId = ensureArray(searchingDeviceId); searchingDeviceId = ensureArray(searchingDeviceId);
for (const singleSearchingDeviceId of searchingDeviceId) { for (const singleSearchingDeviceId of searchingDeviceId) {
const foundEntities = this._deviceIdToEntities[singleSearchingDeviceId]; const foundEntities = this._deviceEntityLookup[singleSearchingDeviceId];
if (foundEntities?.length) { if (!foundEntities?.length) {
for (const foundEntity of foundEntities) { continue;
if (foundEntity.entity_category === null) { }
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) {
searchingEntityId = ensureArray(searchingEntityId); searchingEntityId = ensureArray(searchingEntityId);
for (const singleSearchingEntityId of searchingEntityId) { for (const singleSearchingEntityId of searchingEntityId) {
entityIds.add(singleSearchingEntityId); entityIds.add(singleSearchingEntityId);