From d8d4ecf79ff270def1397edb189e72af3baa72d0 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 29 Nov 2023 09:01:11 +0100 Subject: [PATCH] Refactor and clean up of device pages (#18796) --- .../device-detail/ha-device-info-card.ts | 27 ++---- .../config/devices/ha-config-device-page.ts | 57 ++++--------- .../devices/ha-config-devices-dashboard.ts | 85 +++++++++---------- .../config/devices/ha-config-devices.ts | 82 +----------------- 4 files changed, 64 insertions(+), 187 deletions(-) diff --git a/src/panels/config/devices/device-detail/ha-device-info-card.ts b/src/panels/config/devices/device-detail/ha-device-info-card.ts index 0a7de52392..524e57534a 100644 --- a/src/panels/config/devices/device-detail/ha-device-info-card.ts +++ b/src/panels/config/devices/device-detail/ha-device-info-card.ts @@ -1,15 +1,13 @@ import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; +import { titleCase } from "../../../../common/string/title-case"; import "../../../../components/ha-card"; -import { AreaRegistryEntry } from "../../../../data/area_registry"; import { computeDeviceName, DeviceRegistryEntry, } from "../../../../data/device_registry"; import { haStyle } from "../../../../resources/styles"; import { HomeAssistant } from "../../../../types"; -import { loadDeviceRegistryDetailDialog } from "../device-registry-detail/show-dialog-device-registry-detail"; -import { titleCase } from "../../../../common/string/title-case"; @customElement("ha-device-info-card") export class HaDeviceCard extends LitElement { @@ -17,10 +15,6 @@ export class HaDeviceCard extends LitElement { @property() public device!: DeviceRegistryEntry; - @property() public devices!: DeviceRegistryEntry[]; - - @property() public areas!: AreaRegistryEntry[]; - @property() public narrow!: boolean; protected render(): TemplateResult { @@ -37,7 +31,7 @@ export class HaDeviceCard extends LitElement { >
${this.device.model - ? html`
${this.device.model}
` + ? html`
${this.device.model}
` : ""} ${this.device.manufacturer ? html` @@ -58,10 +52,7 @@ export class HaDeviceCard extends LitElement { ${this._computeDeviceName( - this.devices, - this.device.via_device_id - )}${this._computeDeviceName(this.device.via_device_id)}
@@ -123,13 +114,8 @@ export class HaDeviceCard extends LitElement { ); } - protected firstUpdated(changedProps) { - super.firstUpdated(changedProps); - loadDeviceRegistryDetailDialog(); - } - - private _computeDeviceName(devices, deviceId) { - const device = devices.find((dev) => dev.id === deviceId); + private _computeDeviceName(deviceId) { + const device = this.hass.devices[deviceId]; return device ? computeDeviceName(device, this.hass) : `<${this.hass.localize( @@ -151,9 +137,6 @@ export class HaDeviceCard extends LitElement { .device { width: 30%; } - .area { - color: var(--primary-text-color); - } .extra-info { margin-top: 8px; word-wrap: break-word; diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 71fd2983b6..06bac5799d 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -35,7 +35,6 @@ import "../../../components/ha-button-menu"; import "../../../components/ha-icon-button"; import "../../../components/ha-icon-next"; import "../../../components/ha-svg-icon"; -import { AreaRegistryEntry } from "../../../data/area_registry"; import { getSignedPath } from "../../../data/auth"; import { ConfigEntry, @@ -109,14 +108,8 @@ export interface DeviceAlert { export class HaConfigDevicePage extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property({ attribute: false }) public devices!: DeviceRegistryEntry[]; - @property({ attribute: false }) public entries!: ConfigEntry[]; - @property({ attribute: false }) public entities!: EntityRegistryEntry[]; - - @property({ attribute: false }) public areas!: AreaRegistryEntry[]; - @property({ attribute: false }) public manifests!: IntegrationManifest[]; @property() public deviceId!: string; @@ -144,14 +137,6 @@ export class HaConfigDevicePage extends LitElement { private _logbookTime = { recent: 86400 }; - private _device = memoizeOne( - ( - deviceId: string, - devices: DeviceRegistryEntry[] - ): DeviceRegistryEntry | undefined => - devices ? devices.find((device) => device.id === deviceId) : undefined - ); - private _integrations = memoizeOne( ( device: DeviceRegistryEntry, @@ -234,15 +219,6 @@ export class HaConfigDevicePage extends LitElement { } ); - private _computeArea = memoizeOne( - (areas, device): AreaRegistryEntry | undefined => { - if (!areas || !device || !device.area_id) { - return undefined; - } - return areas.find((area) => area.area_id === device.area_id); - } - ); - private _batteryEntity = memoizeOne( (entities: EntityRegistryEntry[]): EntityRegistryEntry | undefined => findBatteryEntity(this.hass, entities) @@ -272,7 +248,6 @@ export class HaConfigDevicePage extends LitElement { this._deleteButtons && this._deviceActions && this._deviceAlerts) || - !this.devices || !this.deviceId || !this.entries ) { @@ -302,10 +277,10 @@ export class HaConfigDevicePage extends LitElement { } protected render() { - if (!this.devices || !this.deviceId) { + if (!this.hass || !this.deviceId) { return nothing; } - const device = this._device(this.deviceId, this.devices); + const device = this.hass.devices[this.deviceId]; if (!device) { return html` @@ -324,7 +299,7 @@ export class HaConfigDevicePage extends LitElement { this.entries, this.manifests ); - const entities = this._entities(this.deviceId, this.entities); + const entities = this._entities(this.deviceId, this._entityReg); const entitiesByCategory = this._entitiesByCategory(entities); const batteryEntity = this._batteryEntity(entities); const batteryChargingEntity = this._batteryChargingEntity(entities); @@ -336,7 +311,7 @@ export class HaConfigDevicePage extends LitElement { const batteryChargingState = batteryChargingEntity ? this.hass.states[batteryChargingEntity.entity_id] : undefined; - const area = this._computeArea(this.areas, device); + const area = device.area_id ? this.hass.areas[device.area_id] : undefined; const deviceInfo: TemplateResult[] = integrations.map( (integration) => @@ -636,7 +611,7 @@ export class HaConfigDevicePage extends LitElement {
${this._related.script.map((script) => { const entityState = this.hass.states[script]; - const entry = this.entities.find( + const entry = this._entityReg.find( (e) => e.entity_id === script ); let url = `/config/script/show/${entityState.entity_id}`; @@ -766,8 +741,6 @@ export class HaConfigDevicePage extends LitElement { } ${deviceInfo} @@ -940,7 +913,7 @@ export class HaConfigDevicePage extends LitElement { return; } - const device = this._device(this.deviceId, this.devices); + const device = this.hass.devices[this.deviceId]; if (!device) { return; @@ -1003,7 +976,7 @@ export class HaConfigDevicePage extends LitElement { } private _getDeleteActions() { - const device = this._device(this.deviceId, this.devices); + const device = this.hass.devices[this.deviceId]; if (!device) { return; @@ -1066,7 +1039,7 @@ export class HaConfigDevicePage extends LitElement { } private async _getDeviceActions() { - const device = this._device(this.deviceId, this.devices); + const device = this.hass.devices[this.deviceId]; if (!device) { return; @@ -1129,7 +1102,7 @@ export class HaConfigDevicePage extends LitElement { } private async _getDeviceAlerts() { - const device = this._device(this.deviceId, this.devices); + const device = this.hass.devices[this.deviceId]; if (!device) { return; @@ -1179,7 +1152,7 @@ export class HaConfigDevicePage extends LitElement { private _createScene() { const entities: SceneEntities = {}; - this._entities(this.deviceId, this.entities).forEach((entity) => { + this._entities(this.deviceId, this._entityReg).forEach((entity) => { entities[entity.entity_id] = ""; }); showSceneEditor({ @@ -1189,7 +1162,7 @@ export class HaConfigDevicePage extends LitElement { private _showScriptDialog() { showDeviceAutomationDialog(this, { - device: this._device(this.deviceId, this.devices)!, + device: this.hass.devices[this.deviceId], entityReg: this._entityReg, script: true, }); @@ -1197,7 +1170,7 @@ export class HaConfigDevicePage extends LitElement { private _showAutomationDialog() { showDeviceAutomationDialog(this, { - device: this._device(this.deviceId, this.devices)!, + device: this.hass.devices[this.deviceId], entityReg: this._entityReg, script: false, }); @@ -1232,7 +1205,7 @@ export class HaConfigDevicePage extends LitElement { } private async _showSettings() { - const device = this._device(this.deviceId, this.devices)!; + const device = this.hass.devices[this.deviceId]; showDeviceRegistryDetailDialog(this, { device, updateEntry: async (updates) => { @@ -1244,7 +1217,7 @@ export class HaConfigDevicePage extends LitElement { if (disabled) { for (const cnfg_entry of device.config_entries) { if ( - !this.devices.some( + !Object.values(this.hass.devices).some( (dvc) => dvc.id !== device.id && dvc.config_entries.includes(cnfg_entry) @@ -1315,7 +1288,7 @@ export class HaConfigDevicePage extends LitElement { ) { return; } - const entities = this._entities(this.deviceId, this.entities); + const entities = this._entities(this.deviceId, this._entityReg); const renameEntityid = this.showAdvanced && diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index 3ec2e99554..c586252c7d 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -1,3 +1,4 @@ +import { consume } from "@lit-labs/context"; import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js"; @@ -29,8 +30,8 @@ import "../../../components/ha-button-menu"; import "../../../components/ha-check-list-item"; import "../../../components/ha-fab"; import "../../../components/ha-icon-button"; -import { AreaRegistryEntry } from "../../../data/area_registry"; import { ConfigEntry, sortConfigEntries } from "../../../data/config_entries"; +import { fullEntitiesContext } from "../../../data/context"; import { DeviceEntityLookup, DeviceRegistryEntry, @@ -65,13 +66,11 @@ export class HaConfigDeviceDashboard extends LitElement { @property() public isWide = false; - @property() public devices!: DeviceRegistryEntry[]; - @property() public entries!: ConfigEntry[]; - @property() public entities!: EntityRegistryEntry[]; - - @property() public areas!: AreaRegistryEntry[]; + @state() + @consume({ context: fullEntitiesContext, subscribe: true }) + entities!: EntityRegistryEntry[]; @property() public manifests!: IntegrationManifest[]; @@ -87,28 +86,34 @@ export class HaConfigDeviceDashboard extends LitElement { private _ignoreLocationChange = false; - public constructor() { - super(); - window.addEventListener("location-changed", () => { - if (this._ignoreLocationChange) { - this._ignoreLocationChange = false; - return; - } - if ( - window.location.search.substring(1) !== this._searchParms.toString() - ) { - this._searchParms = new URLSearchParams(window.location.search); - } - }); - window.addEventListener("popstate", () => { - if ( - window.location.search.substring(1) !== this._searchParms.toString() - ) { - this._searchParms = new URLSearchParams(window.location.search); - } - }); + public connectedCallback() { + super.connectedCallback(); + window.addEventListener("location-changed", this._locationChanged); + window.addEventListener("popstate", this._popState); } + disconnectedCallback(): void { + super.disconnectedCallback(); + window.removeEventListener("location-changed", this._locationChanged); + window.removeEventListener("popstate", this._popState); + } + + private _locationChanged = () => { + if (this._ignoreLocationChange) { + this._ignoreLocationChange = false; + return; + } + if (window.location.search.substring(1) !== this._searchParms.toString()) { + this._searchParms = new URLSearchParams(window.location.search); + } + }; + + private _popState = () => { + if (window.location.search.substring(1) !== this._searchParms.toString()) { + this._searchParms = new URLSearchParams(window.location.search); + } + }; + private _activeFilters = memoizeOne( ( entries: ConfigEntry[], @@ -152,10 +157,10 @@ export class HaConfigDeviceDashboard extends LitElement { private _devicesAndFilterDomains = memoizeOne( ( - devices: DeviceRegistryEntry[], + devices: HomeAssistant["devices"], entries: ConfigEntry[], entities: EntityRegistryEntry[], - areas: AreaRegistryEntry[], + areas: HomeAssistant["areas"], manifests: IntegrationManifest[], filters: URLSearchParams, showDisabled: boolean, @@ -163,12 +168,7 @@ export class HaConfigDeviceDashboard extends LitElement { ) => { // Some older installations might have devices pointing at invalid entryIDs // So we guard for that. - let outputDevices: DeviceRowData[] = devices; - - const deviceLookup: { [deviceId: string]: DeviceRegistryEntry } = {}; - for (const device of devices) { - deviceLookup[device.id] = device; - } + let outputDevices: DeviceRowData[] = Object.values(devices); // If nothing gets filtered, this is our correct count of devices let startLength = outputDevices.length; @@ -189,11 +189,6 @@ export class HaConfigDeviceDashboard extends LitElement { entryLookup[entry.entry_id] = entry; } - const areaLookup: { [areaId: string]: AreaRegistryEntry } = {}; - for (const area of areas) { - areaLookup[area.area_id] = area; - } - const manifestLookup: { [domain: string]: IntegrationManifest } = {}; for (const manifest of manifests) { manifestLookup[manifest.domain] = manifest; @@ -251,8 +246,8 @@ export class HaConfigDeviceDashboard extends LitElement { device.manufacturer || `<${localize("ui.panel.config.devices.data_table.unknown")}>`, area: - device.area_id && areaLookup[device.area_id] - ? areaLookup[device.area_id].name + device.area_id && areas[device.area_id] + ? areas[device.area_id].name : "—", integration: deviceEntries.length ? deviceEntries @@ -438,10 +433,10 @@ export class HaConfigDeviceDashboard extends LitElement { protected render(): TemplateResult { const { devicesOutput } = this._devicesAndFilterDomains( - this.devices, + this.hass.devices, this.entries, this.entities, - this.areas, + this.hass.areas, this.manifests, this._searchParms, this._showDisabled, @@ -580,10 +575,10 @@ export class HaConfigDeviceDashboard extends LitElement { private _addDevice() { const { filteredConfigEntry, filteredDomains } = this._devicesAndFilterDomains( - this.devices, + this.hass.devices, this.entries, this.entities, - this.areas, + this.hass.areas, this.manifests, this._searchParms, this._showDisabled, diff --git a/src/panels/config/devices/ha-config-devices.ts b/src/panels/config/devices/ha-config-devices.ts index 08a5e0188d..8b3329cec1 100644 --- a/src/panels/config/devices/ha-config-devices.ts +++ b/src/panels/config/devices/ha-config-devices.ts @@ -1,19 +1,5 @@ -import { UnsubscribeFunc } from "home-assistant-js-websocket"; -import { PropertyValues } from "lit"; import { customElement, property, state } from "lit/decorators"; -import { - AreaRegistryEntry, - subscribeAreaRegistry, -} from "../../../data/area_registry"; import { ConfigEntry, getConfigEntries } from "../../../data/config_entries"; -import { - DeviceRegistryEntry, - subscribeDeviceRegistry, -} from "../../../data/device_registry"; -import { - EntityRegistryEntry, - subscribeEntityRegistry, -} from "../../../data/entity_registry"; import { IntegrationManifest, fetchIntegrationManifests, @@ -53,47 +39,9 @@ class HaConfigDevices extends HassRouterPage { @state() private _manifests: IntegrationManifest[] = []; - @state() - private _entityRegistryEntries: EntityRegistryEntry[] = []; - - @state() - private _deviceRegistryEntries: DeviceRegistryEntry[] = []; - - @state() private _areas: AreaRegistryEntry[] = []; - - private _unsubs?: UnsubscribeFunc[]; - - public connectedCallback() { - super.connectedCallback(); - - if (!this.hass) { - return; - } - this._loadData(); - } - - public disconnectedCallback() { - super.disconnectedCallback(); - if (this._unsubs) { - while (this._unsubs.length) { - this._unsubs.pop()!(); - } - this._unsubs = undefined; - } - } - protected firstUpdated(changedProps) { super.firstUpdated(changedProps); - this.addEventListener("hass-reload-entries", () => { - this._loadData(); - }); - } - - protected updated(changedProps: PropertyValues) { - super.updated(changedProps); - if (!this._unsubs && changedProps.has("hass")) { - this._loadData(); - } + this._loadData(); } protected updatePageEl(pageEl) { @@ -103,39 +51,17 @@ class HaConfigDevices extends HassRouterPage { pageEl.deviceId = this.routeTail.path.substr(1); } - pageEl.entities = this._entityRegistryEntries; pageEl.entries = this._configEntries; pageEl.manifests = this._manifests; - pageEl.devices = this._deviceRegistryEntries; - pageEl.areas = this._areas; pageEl.narrow = this.narrow; pageEl.isWide = this.isWide; pageEl.showAdvanced = this.showAdvanced; pageEl.route = this.routeTail; } - private _loadData() { - getConfigEntries(this.hass).then((configEntries) => { - this._configEntries = configEntries; - }); - fetchIntegrationManifests(this.hass).then((manifests) => { - this._manifests = manifests; - }); - - if (this._unsubs) { - return; - } - this._unsubs = [ - subscribeAreaRegistry(this.hass.connection, (areas) => { - this._areas = areas; - }), - subscribeEntityRegistry(this.hass.connection, (entries) => { - this._entityRegistryEntries = entries; - }), - subscribeDeviceRegistry(this.hass.connection, (entries) => { - this._deviceRegistryEntries = entries; - }), - ]; + private async _loadData() { + this._configEntries = await getConfigEntries(this.hass); + this._manifests = await fetchIntegrationManifests(this.hass); } }