Show entities on area page (#8980)

Co-authored-by: Philip Allgaier <mail@spacegaier.de>
This commit is contained in:
Paulus Schoutsen 2021-04-28 08:01:43 -07:00 committed by GitHub
parent 9690434cac
commit 7962130a0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 137 additions and 14 deletions

View File

@ -22,12 +22,16 @@ import {
import {
computeDeviceName,
DeviceRegistryEntry,
devicesInArea,
} from "../../../data/device_registry";
import {
computeEntityRegistryName,
EntityRegistryEntry,
} from "../../../data/entity_registry";
import { findRelated, RelatedResult } from "../../../data/search";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../resources/styles";
import { HomeAssistant, Route } from "../../../types";
import { showEntityEditorDialog } from "../entities/show-dialog-entity-editor";
import { configSections } from "../ha-panel-config";
import {
loadAreaRegistryDetailDialog,
@ -44,6 +48,8 @@ class HaConfigAreaPage extends LitElement {
@property() public devices!: DeviceRegistryEntry[];
@property() public entities!: EntityRegistryEntry[];
@property({ type: Boolean, reflect: true }) public narrow!: boolean;
@property() public isWide!: boolean;
@ -58,9 +64,39 @@ class HaConfigAreaPage extends LitElement {
| AreaRegistryEntry
| undefined => areas.find((area) => area.area_id === areaId));
private _devices = memoizeOne(
(areaId: string, devices: DeviceRegistryEntry[]): DeviceRegistryEntry[] =>
devicesInArea(devices, areaId)
private _memberships = memoizeOne(
(
areaId: string,
registryDevices: DeviceRegistryEntry[],
registryEntities: EntityRegistryEntry[]
) => {
const devices = new Map();
for (const device of registryDevices) {
if (device.area_id === areaId) {
devices.set(device.id, device);
}
}
const entities: EntityRegistryEntry[] = [];
const indirectEntities: EntityRegistryEntry[] = [];
for (const entity of registryEntities) {
if (entity.area_id) {
if (entity.area_id === areaId) {
entities.push(entity);
}
} else if (devices.has(entity.device_id)) {
indirectEntities.push(entity);
}
}
return {
devices: Array.from(devices.values()),
entities,
indirectEntities,
};
}
);
protected firstUpdated(changedProps) {
@ -87,7 +123,11 @@ class HaConfigAreaPage extends LitElement {
`;
}
const devices = this._devices(this.areaId, this.devices);
const { devices, entities } = this._memberships(
this.areaId,
this.devices,
this.entities
);
return html`
<hass-tabs-subpage
@ -144,6 +184,33 @@ class HaConfigAreaPage extends LitElement {
>
`}
</ha-card>
<ha-card
.header=${this.hass.localize(
"ui.panel.config.areas.editor.linked_entities_caption"
)}
>${entities.length
? entities.map(
(entity) =>
html`
<paper-item
@click=${this._openEntity}
.entity=${entity}
>
<paper-item-body>
${computeEntityRegistryName(this.hass, entity)}
</paper-item-body>
<ha-icon-next></ha-icon-next>
</paper-item>
`
)
: html`
<paper-item class="no-link"
>${this.hass.localize(
"ui.panel.config.areas.editor.no_linked_entities"
)}</paper-item
>
`}
</ha-card>
</div>
<div class="column">
${isComponentLoaded(this.hass, "automation")
@ -299,6 +366,14 @@ class HaConfigAreaPage extends LitElement {
this._openDialog(entry);
}
private _openEntity(ev) {
const entry: EntityRegistryEntry = (ev.currentTarget as any).entity;
showEntityEditorDialog(this, {
entity_id: entry.entity_id,
entry,
});
}
private _openDialog(entry?: AreaRegistryEntry) {
showAreaRegistryDetailDialog(this, {
entry,

View File

@ -24,10 +24,8 @@ import {
AreaRegistryEntry,
createAreaRegistryEntry,
} from "../../../data/area_registry";
import {
DeviceRegistryEntry,
devicesInArea,
} from "../../../data/device_registry";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { showAlertDialog } from "../../../dialogs/generic/show-dialog-box";
import "../../../layouts/hass-loading-screen";
import "../../../layouts/hass-tabs-subpage-data-table";
@ -53,12 +51,39 @@ export class HaConfigAreasDashboard extends LitElement {
@property() public devices!: DeviceRegistryEntry[];
@property() public entities!: EntityRegistryEntry[];
private _areas = memoizeOne(
(areas: AreaRegistryEntry[], devices: DeviceRegistryEntry[]) => {
(
areas: AreaRegistryEntry[],
devices: DeviceRegistryEntry[],
entities: EntityRegistryEntry[]
) => {
return areas.map((area) => {
const devicesInArea = new Set();
for (const device of devices) {
if (device.area_id === area.area_id) {
devicesInArea.add(device.id);
}
}
let entitiesInArea = 0;
for (const entity of entities) {
if (
entity.area_id
? entity.area_id === area.area_id
: devicesInArea.has(entity.device_id)
) {
entitiesInArea++;
}
}
return {
...area,
devices: devicesInArea(devices, area.area_id).length,
devices: devicesInArea.size,
entities: entitiesInArea,
};
});
}
@ -97,6 +122,15 @@ export class HaConfigAreasDashboard extends LitElement {
width: "20%",
direction: "asc",
},
entities: {
title: this.hass.localize(
"ui.panel.config.areas.data_table.entities"
),
sortable: true,
type: "numeric",
width: "20%",
direction: "asc",
},
}
);
@ -110,7 +144,7 @@ export class HaConfigAreasDashboard extends LitElement {
.tabs=${configSections.integrations}
.route=${this.route}
.columns=${this._columns(this.narrow)}
.data=${this._areas(this.areas, this.devices)}
.data=${this._areas(this.areas, this.devices, this.entities)}
@row-click=${this._handleRowClicked}
.noDataText=${this.hass.localize(
"ui.panel.config.areas.picker.no_areas"

View File

@ -15,6 +15,10 @@ import {
DeviceRegistryEntry,
subscribeDeviceRegistry,
} from "../../../data/device_registry";
import {
EntityRegistryEntry,
subscribeEntityRegistry,
} from "../../../data/entity_registry";
import {
HassRouterPage,
RouterOptions,
@ -51,6 +55,9 @@ class HaConfigAreas extends HassRouterPage {
@internalProperty()
private _deviceRegistryEntries: DeviceRegistryEntry[] = [];
@internalProperty()
private _entityRegistryEntries: EntityRegistryEntry[] = [];
@internalProperty() private _areas: AreaRegistryEntry[] = [];
private _unsubs?: UnsubscribeFunc[];
@ -90,6 +97,7 @@ class HaConfigAreas extends HassRouterPage {
pageEl.entries = this._configEntries;
pageEl.devices = this._deviceRegistryEntries;
pageEl.entities = this._entityRegistryEntries;
pageEl.areas = this._areas;
pageEl.narrow = this.narrow;
pageEl.isWide = this.isWide;
@ -113,6 +121,9 @@ class HaConfigAreas extends HassRouterPage {
subscribeDeviceRegistry(this.hass.connection, (entries) => {
this._deviceRegistryEntries = entries;
}),
subscribeEntityRegistry(this.hass.connection, (entries) => {
this._entityRegistryEntries = entries;
}),
];
}
}

View File

@ -905,7 +905,8 @@
"description": "Group devices and entities into areas",
"data_table": {
"area": "Area",
"devices": "Devices"
"devices": "Devices",
"entities": "Entities"
},
"picker": {
"header": "Areas",
@ -923,7 +924,9 @@
"name": "Name",
"name_required": "Name is required",
"area_id": "Area ID",
"unknown_error": "Unknown error"
"unknown_error": "Unknown error",
"linked_entities_caption": "Entities",
"no_linked_entities": "There are no entities linked to this area."
},
"delete": {
"confirmation_title": "Are you sure you want to delete this area?",