Allow adding Zigbee/Zwave device (#11650)

This commit is contained in:
Paulus Schoutsen 2022-02-11 10:49:16 -08:00 committed by GitHub
parent a9bfea233c
commit ee1fd3e865
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 41 deletions

View File

@ -1,5 +1,4 @@
import "@polymer/paper-item/paper-icon-item";
import "@polymer/paper-item/paper-item-body";
import "@material/mwc-list/mwc-list-item";
import Fuse from "fuse.js";
import {
css,
@ -12,12 +11,16 @@ import {
import { customElement, property, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { fireEvent } from "../../common/dom/fire_event";
import { navigate } from "../../common/navigate";
import "../../common/search/search-input";
import { caseInsensitiveStringCompare } from "../../common/string/compare";
import { LocalizeFunc } from "../../common/translations/localize";
import "../../components/ha-icon-next";
import { getConfigEntries } from "../../data/config_entries";
import { domainToName } from "../../data/integration";
import { showZWaveJSAddNodeDialog } from "../../panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-add-node";
import { HomeAssistant } from "../../types";
import { brandsUrl } from "../../util/brands-url";
import { documentationUrl } from "../../util/documentation-url";
@ -26,6 +29,7 @@ import { configFlowContentStyles } from "./styles";
interface HandlerObj {
name: string;
slug: string;
is_add?: boolean;
}
declare global {
@ -77,6 +81,17 @@ class StepFlowPickHandler extends LitElement {
protected render(): TemplateResult {
const handlers = this._getHandlers();
const addDeviceRows: HandlerObj[] = ["zha", "zwave_js"]
.filter((domain) => isComponentLoaded(this.hass, domain))
.map((domain) => ({
name: this.hass.localize(
`ui.panel.config.integrations.add_${domain}_device`
),
slug: domain,
is_add: true,
}))
.sort((a, b) => caseInsensitiveStringCompare(a.name, b.name));
return html`
<h2>${this.hass.localize("ui.panel.config.integrations.new")}</h2>
<search-input
@ -88,36 +103,20 @@ class StepFlowPickHandler extends LitElement {
@keypress=${this._maybeSubmit}
></search-input>
<div
class="container"
style=${styleMap({
width: `${this._width}px`,
height: `${this._height}px`,
})}
>
${addDeviceRows.length
? html`
${addDeviceRows.map((handler) => this._renderRow(handler))}
<div class="divider"></div>
`
: ""}
${handlers.length
? handlers.map(
(handler: HandlerObj) =>
html`
<paper-icon-item
@click=${this._handlerPicked}
.handler=${handler}
>
<img
slot="item-icon"
loading="lazy"
src=${brandsUrl({
domain: handler.slug,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
referrerpolicy="no-referrer"
/>
<paper-item-body> ${handler.name} </paper-item-body>
<ha-icon-next></ha-icon-next>
</paper-icon-item>
`
)
? handlers.map((handler) => this._renderRow(handler))
: html`
<p>
${this.hass.localize(
@ -144,6 +143,31 @@ class StepFlowPickHandler extends LitElement {
`;
}
private _renderRow(handler: HandlerObj) {
return html`
<mwc-list-item
graphic="medium"
.hasMeta=${!handler.is_add}
.handler=${handler}
@click=${this._handlerPicked}
>
<img
slot="graphic"
loading="lazy"
src=${brandsUrl({
domain: handler.slug,
type: "icon",
useFallback: true,
darkOptimized: this.hass.themes?.darkMode,
})}
referrerpolicy="no-referrer"
/>
<span>${handler.name}</span>
${handler.is_add ? "" : html`<ha-icon-next slot="meta"></ha-icon-next>`}
</mwc-list-item>
`;
}
public willUpdate(changedProps: PropertyValues): void {
if (this._filter === undefined && this.initialFilter !== undefined) {
this._filter = this.initialFilter;
@ -161,20 +185,17 @@ class StepFlowPickHandler extends LitElement {
protected updated(changedProps) {
super.updated(changedProps);
// Store the width and height so that when we search, box doesn't jump
const div = this.shadowRoot!.querySelector("div")!;
if (!this._width) {
const width = div.clientWidth;
if (width) {
this._width = width;
}
}
if (!this._height) {
const height = div.clientHeight;
if (height) {
this._height = height;
}
if (!changedProps.has("handlers")) {
return;
}
// Wait until list item initialized
const firstListItem = this.shadowRoot!.querySelector("mwc-list-item")!;
firstListItem.updateComplete.then(() => {
// Store the width and height so that when we search, box doesn't jump
const div = this.shadowRoot!.querySelector("div.container")!;
this._width = div.clientWidth;
this._height = div.clientHeight;
});
}
private _getHandlers() {
@ -190,8 +211,31 @@ class StepFlowPickHandler extends LitElement {
}
private async _handlerPicked(ev) {
const handler: HandlerObj = ev.currentTarget.handler;
if (handler.is_add) {
if (handler.slug === "zwave_js") {
const entries = await getConfigEntries(this.hass);
const entry = entries.find((ent) => ent.domain === "zwave_js");
if (!entry) {
return;
}
showZWaveJSAddNodeDialog(this, {
entry_id: entry.entry_id,
});
} else if (handler.slug === "zha") {
navigate("/config/zha/add");
}
// This closes dialog.
fireEvent(this, "flow-update");
return;
}
fireEvent(this, "handler-picked", {
handler: ev.currentTarget.handler.slug,
handler: handler.slug,
});
}
@ -219,7 +263,11 @@ class StepFlowPickHandler extends LitElement {
}
search-input {
display: block;
margin: -12px 16px 0;
margin-top: 8px;
}
.divider {
margin: 8px 0;
border-top: 1px solid var(--divider-color);
}
ha-icon-next {
margin-right: 8px;

View File

@ -2478,6 +2478,8 @@
"rename_dialog": "Edit the name of this config entry",
"rename_input_label": "Entry name",
"search": "Search integrations",
"add_zwave_js_device": "Add Z-Wave device",
"add_zha_device": "Add Zigbee device",
"disable": {
"show_disabled": "Show disabled integrations",
"disabled_integrations": "{number} disabled",