From 164e433592dea87a358ab5a9f17feaa2e429a684 Mon Sep 17 00:00:00 2001 From: "David F. Mulcahey" Date: Wed, 4 Sep 2019 12:40:47 -0400 Subject: [PATCH] ZHA device info dialog (#3529) * zha device info dialog * cleanup * quick hack to make this work * remove hack * add mixin for zha device info dialog * fix potential exception * cleanup * review comments * lint * remove unused import * lint * review coments * review comments * translations and css --- src/data/zha.ts | 9 ++ .../dialog-zha-device-info.ts | 115 ++++++++++++++++++ .../show-dialog-zha-device-info.ts | 19 +++ src/panels/config/zha/zha-add-devices-page.ts | 12 +- src/panels/config/zha/zha-device-card.ts | 32 ++--- src/panels/config/zha/zha-node.ts | 13 +- src/state/hass-element.ts | 2 + src/state/zha-dialog-mixin.ts | 29 +++++ src/translations/en.json | 24 ++-- 9 files changed, 217 insertions(+), 38 deletions(-) create mode 100644 src/dialogs/zha-device-info-dialog/dialog-zha-device-info.ts create mode 100644 src/dialogs/zha-device-info-dialog/show-dialog-zha-device-info.ts create mode 100644 src/state/zha-dialog-mixin.ts diff --git a/src/data/zha.ts b/src/data/zha.ts index 9c10944f8b..4ae16c680a 100644 --- a/src/data/zha.ts +++ b/src/data/zha.ts @@ -80,6 +80,15 @@ export const fetchDevices = (hass: HomeAssistant): Promise => type: "zha/devices", }); +export const fetchZHADevice = ( + hass: HomeAssistant, + ieeeAddress: string +): Promise => + hass.callWS({ + type: "zha/device", + ieee: ieeeAddress, + }); + export const fetchBindableDevices = ( hass: HomeAssistant, ieeeAddress: string diff --git a/src/dialogs/zha-device-info-dialog/dialog-zha-device-info.ts b/src/dialogs/zha-device-info-dialog/dialog-zha-device-info.ts new file mode 100644 index 0000000000..6d4abc4e66 --- /dev/null +++ b/src/dialogs/zha-device-info-dialog/dialog-zha-device-info.ts @@ -0,0 +1,115 @@ +import { + LitElement, + html, + css, + CSSResult, + TemplateResult, + customElement, + property, +} from "lit-element"; +import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable"; +import "../../components/dialog/ha-paper-dialog"; +// Not duplicate, is for typing +// tslint:disable-next-line +import { HaPaperDialog } from "../../components/dialog/ha-paper-dialog"; +import "../../panels/config/zha/zha-device-card"; + +import { PolymerChangedEvent } from "../../polymer-types"; +import { haStyleDialog } from "../../resources/styles"; +import { HomeAssistant } from "../../types"; +import { ZHADeviceInfoDialogParams } from "./show-dialog-zha-device-info"; +import { ZHADevice, fetchZHADevice } from "../../data/zha"; + +@customElement("dialog-zha-device-info") +class DialogZHADeviceInfo extends LitElement { + @property() public hass!: HomeAssistant; + @property() private _params?: ZHADeviceInfoDialogParams; + @property() private _error?: string; + @property() private _device?: ZHADevice; + + public async showDialog(params: ZHADeviceInfoDialogParams): Promise { + this._params = params; + this._device = await fetchZHADevice(this.hass, params.ieee); + await this.updateComplete; + this._dialog.open(); + } + + protected render(): TemplateResult | void { + if (!this._params || !this._device) { + return html``; + } + + return html` + + ${this._error + ? html` +
${this._error}
+ ` + : html` + + `} +
+ `; + } + + private _openedChanged(ev: PolymerChangedEvent): void { + if (!ev.detail.value) { + this._params = undefined; + this._error = undefined; + this._device = undefined; + } + } + + private _onDeviceRemoved(): void { + this._closeDialog(); + } + + private get _dialog(): HaPaperDialog { + return this.shadowRoot!.querySelector("ha-paper-dialog")!; + } + + private _closeDialog() { + this._dialog.close(); + } + + static get styles(): CSSResult[] { + return [ + haStyleDialog, + css` + ha-paper-dialog > * { + margin: 0; + display: block; + padding: 0; + } + .card { + box-sizing: border-box; + display: flex; + flex: 1 0 300px; + min-width: 0; + max-width: 600px; + word-wrap: break-word; + } + .error { + color: var(--google-red-500); + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "dialog-zha-device-info": DialogZHADeviceInfo; + } +} diff --git a/src/dialogs/zha-device-info-dialog/show-dialog-zha-device-info.ts b/src/dialogs/zha-device-info-dialog/show-dialog-zha-device-info.ts new file mode 100644 index 0000000000..aff1ee5447 --- /dev/null +++ b/src/dialogs/zha-device-info-dialog/show-dialog-zha-device-info.ts @@ -0,0 +1,19 @@ +import { fireEvent } from "../../common/dom/fire_event"; + +export interface ZHADeviceInfoDialogParams { + ieee: string; +} + +export const loadZHADeviceInfoDialog = () => + import(/* webpackChunkName: "dialog-zha-device-info" */ "./dialog-zha-device-info"); + +export const showZHADeviceInfoDialog = ( + element: HTMLElement, + zhaDeviceInfoParams: ZHADeviceInfoDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "dialog-zha-device-info", + dialogImport: loadZHADeviceInfoDialog, + dialogParams: zhaDeviceInfoParams, + }); +}; diff --git a/src/panels/config/zha/zha-add-devices-page.ts b/src/panels/config/zha/zha-add-devices-page.ts index 5adb181fd4..ff020d8a3e 100644 --- a/src/panels/config/zha/zha-add-devices-page.ts +++ b/src/panels/config/zha/zha-add-devices-page.ts @@ -113,12 +113,12 @@ class ZHAAddDevicesPage extends LitElement { (device) => html` ` )} diff --git a/src/panels/config/zha/zha-device-card.ts b/src/panels/config/zha/zha-device-card.ts index b34a720bff..886fb6c2f4 100644 --- a/src/panels/config/zha/zha-device-card.ts +++ b/src/panels/config/zha/zha-device-card.ts @@ -55,11 +55,11 @@ declare global { @customElement("zha-device-card") class ZHADeviceCard extends LitElement { @property() public hass!: HomeAssistant; - @property() public narrow?: boolean; @property() public device?: ZHADevice; - @property() public showHelp: boolean = false; - @property() public showActions?: boolean; - @property() public isJoinPage?: boolean; + @property({ type: Boolean }) public narrow?: boolean; + @property({ type: Boolean }) public showHelp?: boolean = false; + @property({ type: Boolean }) public showActions?: boolean; + @property({ type: Boolean }) public isJoinPage?: boolean; @property() private _serviceData?: NodeServiceData; @property() private _areas: AreaRegistryEntry[] = []; @property() private _selectedAreaIndex: number = -1; @@ -139,7 +139,7 @@ class ZHADeviceCard extends LitElement {
${this.device!.model}
${this.hass!.localize( - "ui.panel.config.integrations.config_entry.manuf", + "ui.dialogs.zha_device_info.manuf", "manufacturer", this.device!.manufacturer )} @@ -206,14 +206,14 @@ class ZHADeviceCard extends LitElement { @change="${this._saveCustomName}" .value="${this._userGivenName}" placeholder="${this.hass!.localize( - "ui.panel.config.zha.device_card.device_name_placeholder" + "ui.dialogs.zha_device_info.zha_device_card.device_name_placeholder" )}" >
@@ -223,9 +223,7 @@ class ZHADeviceCard extends LitElement { @iron-select="${this._selectedAreaChanged}" > - ${this.hass!.localize( - "ui.panel.config.integrations.config_entry.no_area" - )} + ${this.hass!.localize("ui.dialogs.zha_device_info.no_area")} ${this._areas.map( @@ -247,7 +245,7 @@ class ZHADeviceCard extends LitElement { ? html`
${this.hass!.localize( - "ui.panel.config.zha.services.reconfigure" + "ui.dialogs.zha_device_info.services.reconfigure" )}
` @@ -264,7 +262,7 @@ class ZHADeviceCard extends LitElement { ? html`
${this.hass!.localize( - "ui.panel.config.zha.services.remove" + "ui.dialogs.zha_device_info.services.remove" )}
` @@ -381,6 +379,7 @@ class ZHADeviceCard extends LitElement { } .device .manuf { color: var(--secondary-text-color); + margin-bottom: 20px; } .extra-info { margin-top: 8px; @@ -393,14 +392,17 @@ class ZHADeviceCard extends LitElement { .info { margin-left: 16px; } + dl { + display: grid; + grid-template-columns: 125px 1fr; + } dl dt { padding-left: 12px; float: left; - width: 100px; text-align: left; } - dt dd { - text-align: left; + dl dd { + max-width: 200px; } paper-icon-item { cursor: pointer; diff --git a/src/panels/config/zha/zha-node.ts b/src/panels/config/zha/zha-node.ts index e665a79ddd..01a7b5c57a 100644 --- a/src/panels/config/zha/zha-node.ts +++ b/src/panels/config/zha/zha-node.ts @@ -105,13 +105,12 @@ export class ZHANode extends LitElement { ? html` ` : ""} diff --git a/src/state/hass-element.ts b/src/state/hass-element.ts index c837aafecf..da67ba1385 100644 --- a/src/state/hass-element.ts +++ b/src/state/hass-element.ts @@ -3,6 +3,7 @@ import AuthMixin from "./auth-mixin"; import TranslationsMixin from "./translations-mixin"; import ThemesMixin from "./themes-mixin"; import MoreInfoMixin from "./more-info-mixin"; +import ZHADialogMixin from "./zha-dialog-mixin"; import SidebarMixin from "./sidebar-mixin"; import { dialogManagerMixin } from "./dialog-manager-mixin"; import { connectionMixin } from "./connection-mixin"; @@ -25,4 +26,5 @@ export class HassElement extends ext(HassBaseMixin(LitElement), [ NotificationMixin, dialogManagerMixin, urlSyncMixin, + ZHADialogMixin, ]) {} diff --git a/src/state/zha-dialog-mixin.ts b/src/state/zha-dialog-mixin.ts new file mode 100644 index 0000000000..600c9c4972 --- /dev/null +++ b/src/state/zha-dialog-mixin.ts @@ -0,0 +1,29 @@ +import { Constructor, LitElement } from "lit-element"; +import { HassBaseEl } from "./hass-base-mixin"; +import { + showZHADeviceInfoDialog, + ZHADeviceInfoDialogParams, +} from "../dialogs/zha-device-info-dialog/show-dialog-zha-device-info"; +import { HASSDomEvent } from "../common/dom/fire_event"; + +declare global { + // for fire event + interface HASSDomEvents { + "zha-show-device-dialog": { + ieee: string; + }; + } +} + +export default (superClass: Constructor) => + class extends superClass { + protected firstUpdated(changedProps) { + super.firstUpdated(changedProps); + this.addEventListener("zha-show-device-dialog", (e) => + showZHADeviceInfoDialog( + e.target as HTMLElement, + (e as HASSDomEvent).detail + ) + ); + } + }; diff --git a/src/translations/en.json b/src/translations/en.json index aa3f678043..1d94f08219 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -554,6 +554,20 @@ "title": "System Options", "enable_new_entities_label": "Enable newly added entities.", "enable_new_entities_description": "If disabled, newly discovered entities will not be automatically added to Home Assistant." + }, + "zha_device_info": { + "manuf": "by {manufacturer}", + "no_area": "No Area", + "services": { + "reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.", + "updateDeviceName": "Set a custom name for this device in the device registry.", + "remove": "Remove a device from the ZigBee network." + }, + "zha_device_card": { + "device_name_placeholder": "User given name", + "area_picker_label": "Area", + "update_name_button": "Update Name" + } } }, "duration": { @@ -942,16 +956,6 @@ "zha": { "caption": "ZHA", "description": "Zigbee Home Automation network management", - "services": { - "reconfigure": "Reconfigure ZHA device (heal device). Use this if you are having issues with the device. If the device in question is a battery powered device please ensure it is awake and accepting commands when you use this service.", - "updateDeviceName": "Set a custom name for this device in the device registry.", - "remove": "Remove a device from the ZigBee network." - }, - "device_card": { - "device_name_placeholder": "User given name", - "area_picker_label": "Area", - "update_name_button": "Update Name" - }, "add_device_page": { "header": "Zigbee Home Automation - Add Devices", "spinner": "Searching for ZHA Zigbee devices...",