diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index 836e699ff6..1d84b6efed 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -35,6 +35,7 @@ import { documentationUrl } from "../../util/documentation-url"; import { showAlertDialog } from "../generic/show-dialog-box"; import { DataEntryFlowDialogParams, + FlowHandlers, LoadingReason, } from "./show-dialog-data-entry-flow"; import "./step-flow-abort"; @@ -85,7 +86,7 @@ class DataEntryFlowDialog extends LitElement { @state() private _areas?: AreaRegistryEntry[]; - @state() private _handlers?: string[]; + @state() private _handlers?: FlowHandlers; @state() private _handler?: string; diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index 937dabdac2..53c92fd214 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -1,5 +1,4 @@ import { html } from "lit"; -import { caseInsensitiveStringCompare } from "../../common/string/compare"; import { createConfigFlow, deleteConfigFlow, @@ -23,17 +22,12 @@ export const showConfigFlowDialog = ( showFlowDialog(element, dialogParams, { loadDevicesAndAreas: true, getFlowHandlers: async (hass) => { - const [handlers] = await Promise.all([ + const [integrations, helpers] = await Promise.all([ getConfigFlowHandlers(hass, "integration"), + getConfigFlowHandlers(hass, "helper"), hass.loadBackendTranslation("title", undefined, true), ]); - - return handlers.sort((handlerA, handlerB) => - caseInsensitiveStringCompare( - domainToName(hass.localize, handlerA), - domainToName(hass.localize, handlerB) - ) - ); + return { integrations, helpers }; }, createFlow: async (hass, handler) => { const [step] = await Promise.all([ diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts index 78346468e5..35f6630216 100644 --- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts @@ -12,10 +12,14 @@ import { } from "../../data/data_entry_flow"; import { HomeAssistant } from "../../types"; +export interface FlowHandlers { + integrations: string[]; + helpers: string[]; +} export interface FlowConfig { loadDevicesAndAreas: boolean; - getFlowHandlers?: (hass: HomeAssistant) => Promise; + getFlowHandlers?: (hass: HomeAssistant) => Promise; createFlow(hass: HomeAssistant, handler: string): Promise; diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts index 0beb4ac26f..e40158dd97 100644 --- a/src/dialogs/config-flow/step-flow-pick-handler.ts +++ b/src/dialogs/config-flow/step-flow-pick-handler.ts @@ -26,11 +26,13 @@ import { HomeAssistant } from "../../types"; import { brandsUrl } from "../../util/brands-url"; import { documentationUrl } from "../../util/documentation-url"; import { configFlowContentStyles } from "./styles"; +import { FlowHandlers } from "./show-dialog-data-entry-flow"; interface HandlerObj { name: string; slug: string; is_add?: boolean; + is_helper?: boolean; } declare global { @@ -46,7 +48,7 @@ declare global { class StepFlowPickHandler extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; - @property({ attribute: false }) public handlers!: string[]; + @property({ attribute: false }) public handlers!: FlowHandlers; @property() public initialFilter?: string; @@ -57,8 +59,12 @@ class StepFlowPickHandler extends LitElement { private _height?: number; private _filterHandlers = memoizeOne( - (h: string[], filter?: string, _localize?: LocalizeFunc) => { - const handlers: HandlerObj[] = h.map((handler) => ({ + ( + h: FlowHandlers, + filter?: string, + _localize?: LocalizeFunc + ): [HandlerObj[], HandlerObj[]] => { + const integrations: HandlerObj[] = h.integrations.map((handler) => ({ name: domainToName(this.hass.localize, handler), slug: handler, })); @@ -70,17 +76,31 @@ class StepFlowPickHandler extends LitElement { minMatchCharLength: 2, threshold: 0.2, }; - const fuse = new Fuse(handlers, options); - return fuse.search(filter).map((result) => result.item); + const helpers: HandlerObj[] = h.helpers.map((handler) => ({ + name: domainToName(this.hass.localize, handler), + slug: handler, + is_helper: true, + })); + return [ + new Fuse(integrations, options) + .search(filter) + .map((result) => result.item), + new Fuse(helpers, options) + .search(filter) + .map((result) => result.item), + ]; } - return handlers.sort((a, b) => - caseInsensitiveStringCompare(a.name, b.name) - ); + return [ + integrations.sort((a, b) => + caseInsensitiveStringCompare(a.name, b.name) + ), + [], + ]; } ); protected render(): TemplateResult { - const handlers = this._getHandlers(); + const [integrations, helpers] = this._getHandlers(); const addDeviceRows: HandlerObj[] = ["zha", "zwave_js"] .filter((domain) => isComponentLoaded(this.hass, domain)) @@ -115,8 +135,8 @@ class StepFlowPickHandler extends LitElement { ` : ""} - ${handlers.length - ? handlers.map((handler) => this._renderRow(handler)) + ${integrations.length + ? integrations.map((handler) => this._renderRow(handler)) : html`

${this.hass.localize( @@ -139,6 +159,12 @@ class StepFlowPickHandler extends LitElement { >.

`} + ${helpers.length + ? html` + + ${helpers.map((handler) => this._renderRow(handler))} + ` + : ""} `; } @@ -162,7 +188,7 @@ class StepFlowPickHandler extends LitElement { })} referrerpolicy="no-referrer" /> - ${handler.name} + ${handler.name} ${handler.is_helper ? " (helper)" : ""} ${handler.is_add ? "" : html``} `; @@ -236,6 +262,13 @@ class StepFlowPickHandler extends LitElement { return; } + if (handler.is_helper) { + navigate(`/config/helpers/add?domain=${handler.slug}`); + // This closes dialog. + fireEvent(this, "flow-update"); + return; + } + fireEvent(this, "handler-picked", { handler: handler.slug, }); @@ -250,7 +283,7 @@ class StepFlowPickHandler extends LitElement { if (handlers.length > 0) { fireEvent(this, "handler-picked", { - handler: handlers[0].slug, + handler: handlers[0][0].slug, }); } }