From 63ea8e65687391b159048dd2a793371eb7a0e399 Mon Sep 17 00:00:00 2001 From: Zack Barett Date: Mon, 25 Jul 2022 04:35:13 -0500 Subject: [PATCH] Allows for My to support Supported Brands (#13256) --- .../integrations/protocolIntegrationPicked.ts | 88 +++++++++++++++ src/data/supported_brands.ts | 19 ++++ .../config-flow/step-flow-pick-handler.ts | 79 +------------ .../integrations/ha-config-integrations.ts | 106 ++++++++++++------ 4 files changed, 183 insertions(+), 109 deletions(-) create mode 100644 src/common/integrations/protocolIntegrationPicked.ts diff --git a/src/common/integrations/protocolIntegrationPicked.ts b/src/common/integrations/protocolIntegrationPicked.ts new file mode 100644 index 0000000000..ff62cacbd9 --- /dev/null +++ b/src/common/integrations/protocolIntegrationPicked.ts @@ -0,0 +1,88 @@ +import { html } from "lit"; +import { getConfigEntries } from "../../data/config_entries"; +import { showConfirmationDialog } from "../../dialogs/generic/show-dialog-box"; +import { showZWaveJSAddNodeDialog } from "../../panels/config/integrations/integration-panels/zwave_js/show-dialog-zwave_js-add-node"; +import type { HomeAssistant } from "../../types"; +import { documentationUrl } from "../../util/documentation-url"; +import { isComponentLoaded } from "../config/is_component_loaded"; +import { fireEvent } from "../dom/fire_event"; +import { navigate } from "../navigate"; + +export const protocolIntegrationPicked = async ( + element: HTMLElement, + hass: HomeAssistant, + slug: string +) => { + if (slug === "zwave_js") { + const entries = await getConfigEntries(hass, { + domain: "zwave_js", + }); + + if (!entries.length) { + // If the component isn't loaded, ask them to load the integration first + showConfirmationDialog(element, { + text: hass.localize( + "ui.panel.config.integrations.config_flow.missing_zwave_zigbee", + { + integration: "Z-Wave", + supported_hardware_link: html`${hass.localize( + "ui.panel.config.integrations.config_flow.supported_hardware" + )}`, + } + ), + confirmText: hass.localize( + "ui.panel.config.integrations.config_flow.proceed" + ), + confirm: () => { + fireEvent(element, "handler-picked", { + handler: "zwave_js", + }); + }, + }); + return; + } + + showZWaveJSAddNodeDialog(element, { + entry_id: entries[0].entry_id, + }); + } else if (slug === "zha") { + // If the component isn't loaded, ask them to load the integration first + if (!isComponentLoaded(hass, "zha")) { + showConfirmationDialog(element, { + text: hass.localize( + "ui.panel.config.integrations.config_flow.missing_zwave_zigbee", + { + integration: "Zigbee", + supported_hardware_link: html`${hass.localize( + "ui.panel.config.integrations.config_flow.supported_hardware" + )}`, + } + ), + confirmText: hass.localize( + "ui.panel.config.integrations.config_flow.proceed" + ), + confirm: () => { + fireEvent(element, "handler-picked", { + handler: "zha", + }); + }, + }); + return; + } + + navigate("/config/zha/add"); + } +}; diff --git a/src/data/supported_brands.ts b/src/data/supported_brands.ts index ef5994e871..8f0afcf884 100644 --- a/src/data/supported_brands.ts +++ b/src/data/supported_brands.ts @@ -1,3 +1,4 @@ +import { SupportedBrandObj } from "../dialogs/config-flow/step-flow-pick-handler"; import type { HomeAssistant } from "../types"; export type SupportedBrandHandler = Record; @@ -6,3 +7,21 @@ export const getSupportedBrands = (hass: HomeAssistant) => hass.callWS>({ type: "supported_brands", }); + +export const getSupportedBrandsLookup = ( + supportedBrands: Record +): Record> => { + const supportedBrandsIntegrations: Record< + string, + Partial + > = {}; + for (const [d, domainBrands] of Object.entries(supportedBrands)) { + for (const [slug, name] of Object.entries(domainBrands)) { + supportedBrandsIntegrations[slug] = { + name, + supported_flows: [d], + }; + } + } + return supportedBrandsIntegrations; +}; diff --git a/src/dialogs/config-flow/step-flow-pick-handler.ts b/src/dialogs/config-flow/step-flow-pick-handler.ts index d0afab3efb..fdd0e12ebc 100644 --- a/src/dialogs/config-flow/step-flow-pick-handler.ts +++ b/src/dialogs/config-flow/step-flow-pick-handler.ts @@ -14,14 +14,13 @@ 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 { protocolIntegrationPicked } from "../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../common/navigate"; import { caseInsensitiveStringCompare } from "../../common/string/compare"; import { LocalizeFunc } from "../../common/translations/localize"; import "../../components/ha-icon-next"; import "../../components/search-input"; -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"; @@ -36,7 +35,7 @@ interface HandlerObj { is_helper?: boolean; } -interface SupportedBrandObj extends HandlerObj { +export interface SupportedBrandObj extends HandlerObj { supported_flows: string[]; } @@ -300,79 +299,7 @@ class StepFlowPickHandler extends LitElement { } private async _handleAddPicked(slug: string): Promise { - if (slug === "zwave_js") { - const entries = await getConfigEntries(this.hass, { - domain: "zwave_js", - }); - - if (!entries.length) { - // If the component isn't loaded, ask them to load the integration first - showConfirmationDialog(this, { - text: this.hass.localize( - "ui.panel.config.integrations.config_flow.missing_zwave_zigbee", - { - integration: "Z-Wave", - supported_hardware_link: html`${this.hass.localize( - "ui.panel.config.integrations.config_flow.supported_hardware" - )}`, - } - ), - confirmText: this.hass.localize( - "ui.panel.config.integrations.config_flow.proceed" - ), - confirm: () => { - fireEvent(this, "handler-picked", { - handler: "zwave_js", - }); - }, - }); - return; - } - - showZWaveJSAddNodeDialog(this, { - entry_id: entries[0].entry_id, - }); - } else if (slug === "zha") { - // If the component isn't loaded, ask them to load the integration first - if (!isComponentLoaded(this.hass, "zha")) { - showConfirmationDialog(this, { - text: this.hass.localize( - "ui.panel.config.integrations.config_flow.missing_zwave_zigbee", - { - integration: "Zigbee", - supported_hardware_link: html`${this.hass.localize( - "ui.panel.config.integrations.config_flow.supported_hardware" - )}`, - } - ), - confirmText: this.hass.localize( - "ui.panel.config.integrations.config_flow.proceed" - ), - confirm: () => { - fireEvent(this, "handler-picked", { - handler: "zha", - }); - }, - }); - return; - } - - navigate("/config/zha/add"); - } - + await protocolIntegrationPicked(this, this.hass, slug); // This closes dialog. fireEvent(this, "flow-update"); } diff --git a/src/panels/config/integrations/ha-config-integrations.ts b/src/panels/config/integrations/ha-config-integrations.ts index beb0bb0cb0..82ce8bf60f 100644 --- a/src/panels/config/integrations/ha-config-integrations.ts +++ b/src/panels/config/integrations/ha-config-integrations.ts @@ -14,7 +14,8 @@ import { customElement, property, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import memoizeOne from "memoize-one"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; -import type { HASSDomEvent } from "../../../common/dom/fire_event"; +import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event"; +import { protocolIntegrationPicked } from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import type { LocalizeFunc } from "../../../common/translations/localize"; @@ -49,6 +50,10 @@ import { fetchIntegrationManifests, IntegrationManifest, } from "../../../data/integration"; +import { + getSupportedBrands, + getSupportedBrandsLookup, +} from "../../../data/supported_brands"; import { scanUSBDevices } from "../../../data/usb"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; import { @@ -677,49 +682,84 @@ class HaConfigIntegrations extends SubscribeMixin(LitElement) { if (!domain) { return; } + const handlers = await getConfigFlowHandlers(this.hass, "integration"); - if (!handlers.includes(domain)) { - if (HELPER_DOMAINS.includes(domain)) { - navigate(`/config/helpers/add?domain=${domain}`, { - replace: true, - }); + // Integration exists, so we can just create a flow + if (handlers.includes(domain)) { + const localize = await localizePromise; + if ( + !(await showConfirmationDialog(this, { + title: localize("ui.panel.config.integrations.confirm_new", { + integration: domainToName(localize, domain), + }), + })) + ) { return; } - const helpers = await getConfigFlowHandlers(this.hass, "helper"); - if (helpers.includes(domain)) { - navigate(`/config/helpers/add?domain=${domain}`, { - replace: true, - }); - return; - } - showAlertDialog(this, { - title: this.hass.localize( - "ui.panel.config.integrations.config_flow.error" - ), + showConfigFlowDialog(this, { + dialogClosedCallback: () => { + this._handleFlowUpdated(); + }, + startFlowHandler: domain, + manifest: this._manifests[domain], + showAdvanced: this.hass.userData?.showAdvanced, + }); + } + + const supportedBrands = await getSupportedBrands(this.hass); + const supportedBrandsIntegrations = + getSupportedBrandsLookup(supportedBrands); + + // Supported brand exists, so we can just create a flow + if (Object.keys(supportedBrandsIntegrations).includes(domain)) { + const brand = supportedBrandsIntegrations[domain]; + const slug = brand.supported_flows![0]; + + showConfirmationDialog(this, { text: this.hass.localize( - "ui.panel.config.integrations.config_flow.no_config_flow" + "ui.panel.config.integrations.config_flow.supported_brand_flow", + { + supported_brand: brand.name, + flow_domain_name: domainToName(this.hass.localize, slug), + } ), + confirm: () => { + if (["zha", "zwave_js"].includes(slug)) { + protocolIntegrationPicked(this, this.hass, slug); + return; + } + + fireEvent(this, "handler-picked", { + handler: slug, + }); + }, + }); + + return; + } + + // If not an integration or supported brand, try helper else show alert + if (HELPER_DOMAINS.includes(domain)) { + navigate(`/config/helpers/add?domain=${domain}`, { + replace: true, }); return; } - const localize = await localizePromise; - if ( - !(await showConfirmationDialog(this, { - title: localize("ui.panel.config.integrations.confirm_new", { - integration: domainToName(localize, domain), - }), - })) - ) { + const helpers = await getConfigFlowHandlers(this.hass, "helper"); + if (helpers.includes(domain)) { + navigate(`/config/helpers/add?domain=${domain}`, { + replace: true, + }); return; } - showConfigFlowDialog(this, { - dialogClosedCallback: () => { - this._handleFlowUpdated(); - }, - startFlowHandler: domain, - manifest: this._manifests[domain], - showAdvanced: this.hass.userData?.showAdvanced, + showAlertDialog(this, { + title: this.hass.localize( + "ui.panel.config.integrations.config_flow.error" + ), + text: this.hass.localize( + "ui.panel.config.integrations.config_flow.no_config_flow" + ), }); }