Fixes to device page (#3756)

* Fixes to device page

* Cache page with data page
This commit is contained in:
Paulus Schoutsen 2019-09-18 12:38:27 -07:00 committed by GitHub
parent b6fbf4da3a
commit c898db5010
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 68 deletions

View File

@ -35,6 +35,8 @@ import { EntityRegistryEntry } from "../../../data/entity_registry";
import { ConfigEntry } from "../../../data/config_entries";
import { AreaRegistryEntry } from "../../../data/area_registry";
import { navigate } from "../../../common/navigate";
import { LocalizeFunc } from "../../../common/translations/localize";
import computeStateName from "../../../common/entity/compute_state_name";
interface DeviceRowData extends DeviceRegistryEntry {
device?: DeviceRowData;
@ -43,6 +45,10 @@ interface DeviceRowData extends DeviceRegistryEntry {
battery_entity?: string;
}
interface DeviceEntityLookup {
[deviceId: string]: EntityRegistryEntry[];
}
@customElement("ha-config-devices-dashboard")
export class HaConfigDeviceDashboard extends LitElement {
@property() public hass!: HomeAssistant;
@ -59,37 +65,73 @@ export class HaConfigDeviceDashboard extends LitElement {
entries: ConfigEntry[],
entities: EntityRegistryEntry[],
areas: AreaRegistryEntry[],
domain: string
domain: string,
localize: LocalizeFunc
) => {
// 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;
}
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);
}
const entryLookup: { [entryId: string]: ConfigEntry } = {};
for (const entry of entries) {
entryLookup[entry.entry_id] = entry;
}
const areaLookup: { [areaId: string]: AreaRegistryEntry } = {};
for (const area of areas) {
areaLookup[area.area_id] = area;
}
if (domain) {
outputDevices = outputDevices.filter(
(device) =>
entries.find((entry) =>
device.config_entries.includes(entry.entry_id)
)!.domain === domain
outputDevices = outputDevices.filter((device) =>
device.config_entries.find(
(entryId) =>
entryId in entryLookup && entryLookup[entryId].domain === domain
)
);
}
outputDevices = outputDevices.map((device) => {
const output = { ...device };
output.name = device.name_by_user || device.name || "No name";
output.area =
!areas || !device || !device.area_id
? "No area"
: areas.find((area) => area.area_id === device.area_id)!.name;
output.integration =
!entries || !device || !device.config_entries
? "No integration"
: entries.find((entry) =>
device.config_entries.includes(entry.entry_id)
)!.domain;
output.battery_entity = this._batteryEntity(device, entities);
return output;
return {
...device,
name:
device.name_by_user ||
device.name ||
this._fallbackDeviceName(device.id, deviceEntityLookup) ||
"No name",
model: device.model || "<unknown>",
manufacturer: device.manufacturer || "<unknown>",
area: device.area_id ? areaLookup[device.area_id].name : "No area",
integration: device.config_entries.length
? device.config_entries
.filter((entId) => entId in entryLookup)
.map(
(entId) =>
localize(
`component.${entryLookup[entId].domain}.config.title`
) || entryLookup[entId].domain
)
.join(", ")
: "No integration",
battery_entity: this._batteryEntity(device.id, deviceEntityLookup),
};
});
return outputDevices;
@ -171,7 +213,7 @@ export class HaConfigDeviceDashboard extends LitElement {
></ha-state-icon>
`
: html`
n/a
-
`;
},
},
@ -190,7 +232,8 @@ export class HaConfigDeviceDashboard extends LitElement {
this.entries,
this.entities,
this.areas,
this.domain
this.domain,
this.hass.localize
).map((device: DeviceRowData) => {
// We don't need a lot of this data for mobile view, but kept it for filtering...
const data: DataTabelRowData = {
@ -214,10 +257,12 @@ export class HaConfigDeviceDashboard extends LitElement {
`;
}
private _batteryEntity(device, entities): string | undefined {
const batteryEntity = entities.find(
private _batteryEntity(
deviceId: string,
deviceEntityLookup: DeviceEntityLookup
): string | undefined {
const batteryEntity = (deviceEntityLookup[deviceId] || []).find(
(entity) =>
entity.device_id === device.id &&
this.hass.states[entity.entity_id] &&
this.hass.states[entity.entity_id].attributes.device_class === "battery"
);
@ -225,6 +270,20 @@ export class HaConfigDeviceDashboard extends LitElement {
return batteryEntity ? batteryEntity.entity_id : undefined;
}
private _fallbackDeviceName(
deviceId: string,
deviceEntityLookup: DeviceEntityLookup
): string | undefined {
for (const entity of deviceEntityLookup[deviceId] || []) {
const stateObj = this.hass.states[entity.entity_id];
if (stateObj) {
return computeStateName(stateObj);
}
}
return undefined;
}
private _handleRowClicked(ev: CustomEvent) {
const deviceId = (ev.detail as RowClickedEvent).id;
navigate(this, `/config/devices/device/${deviceId}`);

View File

@ -34,6 +34,7 @@ class HaConfigDevices extends HassRouterPage {
routes: {
dashboard: {
tag: "ha-config-devices-dashboard",
cache: true,
},
device: {
tag: "ha-config-device-page",
@ -41,10 +42,10 @@ class HaConfigDevices extends HassRouterPage {
},
};
@property() private _configEntries?: ConfigEntry[];
@property() private _entityRegistryEntries?: EntityRegistryEntry[];
@property() private _deviceRegistryEntries?: DeviceRegistryEntry[];
@property() private _areas?: AreaRegistryEntry[];
@property() private _configEntries: ConfigEntry[] = [];
@property() private _entityRegistryEntries: EntityRegistryEntry[] = [];
@property() private _deviceRegistryEntries: DeviceRegistryEntry[] = [];
@property() private _areas: AreaRegistryEntry[] = [];
private _unsubs?: UnsubscribeFunc[];

View File

@ -37,25 +37,24 @@ import { HomeAssistant } from "../../../types";
import { ConfigEntry } from "../../../data/config_entries";
import { fireEvent } from "../../../common/dom/fire_event";
import { EntityRegistryEntry } from "../../../data/entity_registry";
import { DataEntryFlowProgress } from "../../../data/data_entry_flow";
@customElement("ha-config-entries-dashboard")
export class HaConfigManagerDashboard extends LitElement {
@property() public hass!: HomeAssistant;
@property() public isWide = false;
@property() private entries = [];
@property() private configEntries!: ConfigEntry[];
/**
* Entity Registry entries.
*/
@property() private entities: EntityRegistryEntry[] = [];
@property() private entityRegistryEntries!: EntityRegistryEntry[];
/**
* Current flows that are in progress and have not been started by a user.
* For example, can be discovered devices that require more config.
*/
@property() private progress = [];
@property() private configEntriesInProgress!: DataEntryFlowProgress[];
public connectedCallback() {
super.connectedCallback();
@ -67,7 +66,7 @@ export class HaConfigManagerDashboard extends LitElement {
<hass-subpage
header=${this.hass.localize("ui.panel.config.integrations.caption")}
>
${this.progress.length
${this.configEntriesInProgress.length
? html`
<ha-config-section>
<span slot="header"
@ -76,7 +75,7 @@ export class HaConfigManagerDashboard extends LitElement {
)}</span
>
<ha-card>
${this.progress.map(
${this.configEntriesInProgress.map(
(flow) => html`
<div class="config-entry-row">
<paper-item-body>
@ -102,8 +101,8 @@ export class HaConfigManagerDashboard extends LitElement {
)}</span
>
<ha-card>
${this.entities.length
? this.entries.map(
${this.entityRegistryEntries.length
? this.configEntries.map(
(item: any, idx) => html`
<a
href="/config/integrations/config_entry/${item.entry_id}"
@ -155,7 +154,6 @@ export class HaConfigManagerDashboard extends LitElement {
title=${this.hass.localize("ui.panel.config.integrations.new")}
@click=${this._createFlow}
?rtl=${computeRTL(this.hass!)}
?isWide=${this.isWide}
></ha-fab>
</hass-subpage>
`;
@ -175,11 +173,11 @@ export class HaConfigManagerDashboard extends LitElement {
}
private _getEntities(configEntry: ConfigEntry): HassEntity[] {
if (!this.entities) {
if (!this.entityRegistryEntries) {
return [];
}
const states: HassEntity[] = [];
this.entities.forEach((entity) => {
this.entityRegistryEntries.forEach((entity) => {
if (
entity.config_entry_id === configEntry.entry_id &&
entity.entity_id in this.hass.states
@ -217,21 +215,10 @@ export class HaConfigManagerDashboard extends LitElement {
z-index: 1;
}
ha-fab[is-wide] {
bottom: 24px;
right: 24px;
}
ha-fab[rtl] {
right: auto;
left: 16px;
}
ha-fab[rtl][is-wide] {
bottom: 24px;
right: auto;
left: 24px;
}
`;
}
}

View File

@ -1,4 +1,5 @@
import "@polymer/app-route/app-route";
import { property, customElement, PropertyValues } from "lit-element";
import "./ha-config-entries-dashboard";
import "./config-entry/ha-config-entry-page";
@ -11,7 +12,6 @@ import {
HassRouterPage,
RouterOptions,
} from "../../../layouts/hass-router-page";
import { property, customElement, PropertyValues } from "lit-element";
import { HomeAssistant } from "../../../types";
import { ConfigEntry, getConfigEntries } from "../../../data/config_entries";
import {
@ -42,7 +42,6 @@ class HaConfigIntegrations extends HassRouterPage {
protected routerOptions: RouterOptions = {
defaultPage: "dashboard",
preloadAll: true,
routes: {
dashboard: {
tag: "ha-config-entries-dashboard",
@ -53,11 +52,11 @@ class HaConfigIntegrations extends HassRouterPage {
},
};
@property() private _configEntries?: ConfigEntry[];
@property() private _configEntriesInProgress?: DataEntryFlowProgress[];
@property() private _entityRegistryEntries?: EntityRegistryEntry[];
@property() private _deviceRegistryEntries?: DeviceRegistryEntry[];
@property() private _areas?: AreaRegistryEntry[];
@property() private _configEntries: ConfigEntry[] = [];
@property() private _configEntriesInProgress: DataEntryFlowProgress[] = [];
@property() private _entityRegistryEntries: EntityRegistryEntry[] = [];
@property() private _deviceRegistryEntries: DeviceRegistryEntry[] = [];
@property() private _areas: AreaRegistryEntry[] = [];
private _unsubs?: UnsubscribeFunc[];
@ -98,15 +97,14 @@ class HaConfigIntegrations extends HassRouterPage {
protected updatePageEl(pageEl) {
pageEl.hass = this.hass;
pageEl.entityRegistryEntries = this._entityRegistryEntries;
pageEl.configEntries = this._configEntries;
if (this._currentPage === "dashboard") {
pageEl.entities = this._entityRegistryEntries;
pageEl.entries = this._configEntries;
pageEl.progress = this._configEntriesInProgress;
pageEl.configEntriesInProgress = this._configEntriesInProgress;
return;
}
pageEl.entityRegistryEntries = this._entityRegistryEntries;
pageEl.configEntries = this._configEntries;
pageEl.configEntryId = this.routeTail.path.substr(1);
pageEl.deviceRegistryEntries = this._deviceRegistryEntries;
pageEl.areas = this._areas;