mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-18 23:06:40 +00:00
Show entities on area page (#8980)
Co-authored-by: Philip Allgaier <mail@spacegaier.de>
This commit is contained in:
parent
9690434cac
commit
7962130a0c
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -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?",
|
||||
|
Loading…
x
Reference in New Issue
Block a user