From 2aa7b95a5a069fd6ae9c142d156e419aa0c9243b Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 21 Nov 2022 12:39:22 -0500 Subject: [PATCH] Device info: Show connected devices (#14421) --- .../ha-device-via-devices-card.ts | 124 ++++++++++++++++++ .../config/devices/ha-config-device-page.ts | 6 + src/translations/en.json | 4 + 3 files changed, 134 insertions(+) create mode 100644 src/panels/config/devices/device-detail/ha-device-via-devices-card.ts diff --git a/src/panels/config/devices/device-detail/ha-device-via-devices-card.ts b/src/panels/config/devices/device-detail/ha-device-via-devices-card.ts new file mode 100644 index 0000000000..3a0c276d6f --- /dev/null +++ b/src/panels/config/devices/device-detail/ha-device-via-devices-card.ts @@ -0,0 +1,124 @@ +import "@material/mwc-list/mwc-list-item"; +import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; +import { caseInsensitiveStringCompare } from "../../../../common/string/compare"; +import "../../../../components/ha-card"; +import "../../../../components/ha-icon-next"; +import { + computeDeviceName, + DeviceRegistryEntry, +} from "../../../../data/device_registry"; +import type { HomeAssistant } from "../../../../types"; + +const MAX_VISIBLE_VIA_DEVICES = 10; + +@customElement("ha-device-via-devices-card") +export class HaDeviceViaDevicesCard extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public deviceId!: string; + + @state() public _showAll = false; + + private _viaDevices = memoizeOne( + ( + deviceId: string, + devices: Record + ): DeviceRegistryEntry[] => + Object.values(devices) + .filter((device) => device.via_device_id === deviceId) + .sort((d1, d2) => + caseInsensitiveStringCompare( + computeDeviceName(d1, this.hass), + computeDeviceName(d2, this.hass) + ) + ) + ); + + protected render(): TemplateResult { + const viaDevices = this._viaDevices(this.deviceId, this.hass.devices); + + if (viaDevices.length === 0) { + return html``; + } + + return html` + +

+ ${this.hass.localize( + "ui.panel.config.devices.connected_devices.heading" + )} +

+ ${(this._showAll + ? viaDevices + : viaDevices.slice(0, MAX_VISIBLE_VIA_DEVICES) + ).map( + (viaDevice) => html` + + + ${computeDeviceName(viaDevice, this.hass)} + + + + ` + )} + ${!this._showAll && viaDevices.length > MAX_VISIBLE_VIA_DEVICES + ? html` + + ` + : ""} +
+ `; + } + + private _toggleShowAll() { + this._showAll = !this._showAll; + } + + static get styles(): CSSResultGroup { + return css` + :host { + display: block; + } + + .card-header { + padding-bottom: 0; + } + + a { + text-decoration: none; + color: var(--primary-text-color); + } + + button.show-more { + color: var(--primary-color); + text-align: left; + cursor: pointer; + background: none; + border-width: initial; + border-style: none; + border-color: initial; + border-image: initial; + padding: 16px; + font: inherit; + } + button.show-more:focus { + outline: none; + text-decoration: underline; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-device-via-devices-card": HaDeviceViaDevicesCard; + } +} diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts index 2e6fd4f8b4..9f184d3d12 100644 --- a/src/panels/config/devices/ha-config-device-page.ts +++ b/src/panels/config/devices/ha-config-device-page.ts @@ -7,6 +7,7 @@ import { mdiPencil, mdiPlusCircle, } from "@mdi/js"; +import "@material/mwc-list/mwc-list-item"; import "@polymer/paper-tooltip/paper-tooltip"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; @@ -67,6 +68,7 @@ import "../../logbook/ha-logbook"; import "../ha-config-section"; import "./device-detail/ha-device-entities-card"; import "./device-detail/ha-device-info-card"; +import "./device-detail/ha-device-via-devices-card"; import { showDeviceAutomationDialog } from "./device-detail/show-dialog-device-automation"; import { loadDeviceRegistryDetailDialog, @@ -825,6 +827,10 @@ export class HaConfigDevicePage extends LitElement { ` : "" )} +
${this.narrow ? [automationCard, sceneCard, scriptCard] : ""} diff --git a/src/translations/en.json b/src/translations/en.json index 2c283f2c73..f46100b1b2 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2689,6 +2689,10 @@ "download_diagnostics_integration": "Download {integration} diagnostics", "delete_device": "Delete", "delete_device_integration": "Remove device from {integration}", + "connected_devices": { + "heading": "Connected devices", + "show_more": "+{count} devices not shown" + }, "type": { "device_heading": "Device", "device": "device",