diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts
index 38257e66aa22..cd0652bcc275 100644
--- a/src/dialogs/config-flow/step-flow-pick-handler.ts
+++ b/src/dialogs/config-flow/step-flow-pick-handler.ts
@@ -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`
${this.hass.localize("ui.panel.config.integrations.new")}
+ ${addDeviceRows.length
+ ? html`
+ ${addDeviceRows.map((handler) => this._renderRow(handler))}
+
+ `
+ : ""}
${handlers.length
- ? handlers.map(
- (handler: HandlerObj) =>
- html`
-
-
-
- ${handler.name}
-
-
- `
- )
+ ? handlers.map((handler) => this._renderRow(handler))
: html`
${this.hass.localize(
@@ -144,6 +143,31 @@ class StepFlowPickHandler extends LitElement {
`;
}
+ private _renderRow(handler: HandlerObj) {
+ return html`
+
+
+ ${handler.name}
+ ${handler.is_add ? "" : html``}
+
+ `;
+ }
+
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;
diff --git a/src/translations/en.json b/src/translations/en.json
index 547d8ff918a0..cafd39ed58b6 100755
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -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",