import { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item-base"; import { css, html, LitElement } from "lit"; import { customElement, property } from "lit/decorators"; import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { fireEvent } from "../../../common/dom/fire_event"; import { protocolIntegrationPicked, PROTOCOL_INTEGRATIONS, } from "../../../common/integrations/protocolIntegrationPicked"; import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; import { navigate } from "../../../common/navigate"; import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import { localizeConfigFlowTitle } from "../../../data/config_flow"; import { DataEntryFlowProgress } from "../../../data/data_entry_flow"; import { domainToName, fetchIntegrationManifest, } from "../../../data/integration"; import { Brand, Integration } from "../../../data/integrations"; import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-config-flow"; import { haStyle } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; import "./ha-integration-list-item"; import { showYamlIntegrationDialog } from "./show-add-integration-dialog"; const standardToDomain = { zigbee: "zha", zwave: "zwave_js" } as const; @customElement("ha-domain-integrations") class HaDomainIntegrations extends LitElement { public hass!: HomeAssistant; @property() public domain!: string; @property({ attribute: false }) public integration?: Brand | Integration; @property({ attribute: false }) public flowsInProgress?: DataEntryFlowProgress[]; protected render() { return html` ${this.flowsInProgress?.length ? html`

${this.hass.localize("ui.panel.config.integrations.discovered")}

${this.flowsInProgress.map( (flow) => html` ${localizeConfigFlowTitle(this.hass.localize, flow)} ` )}
  • ${this.integration && "integrations" in this.integration && this.integration.integrations ? html`

    ${this.hass.localize( "ui.panel.config.integrations.available_integrations" )}

    ` : ""}` : ""} ${this.integration?.iot_standards ? this.integration.iot_standards .filter((standard) => (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( standardToDomain[standard] || standard ) ) .map((standard) => { const domain: (typeof PROTOCOL_INTEGRATIONS)[number] = standardToDomain[standard] || standard; return html` ${this.hass.localize( `ui.panel.config.integrations.add_${domain}_device` )} `; }) : ""} ${this.integration && "integrations" in this.integration && this.integration.integrations ? Object.entries(this.integration.integrations) .sort((a, b) => { if (a[1].config_flow && !b[1].config_flow) { return -1; } if (b[1].config_flow && !a[1].config_flow) { return 0; } return caseInsensitiveStringCompare( a[1].name || domainToName(this.hass.localize, a[0]), b[1].name || domainToName(this.hass.localize, b[0]), this.hass.locale.language ); }) .map( ([dom, val]) => html` ` ) : ""} ${(PROTOCOL_INTEGRATIONS as ReadonlyArray).includes(this.domain) ? html` ${this.hass.localize( `ui.panel.config.integrations.add_${ this.domain as (typeof PROTOCOL_INTEGRATIONS)[number] }_device` )} ` : ""} ${this.integration && "config_flow" in this.integration && this.integration.config_flow ? html`${this.flowsInProgress?.length ? html` ${this.hass.localize("ui.panel.config.integrations.new_flow", { integration: this.integration.name || domainToName(this.hass.localize, this.domain), })} ` : html` `}` : ""}
    `; } private async _integrationPicked(ev: CustomEvent) { if (!shouldHandleRequestSelectedEvent(ev)) { return; } const domain = (ev.currentTarget as any).domain; if ( ["cloud", "google_assistant", "alexa"].includes(domain) && isComponentLoaded(this.hass, "cloud") ) { fireEvent(this, "close-dialog"); navigate("/config/cloud"); return; } const integration = (ev.currentTarget as any).integration; if (integration.supported_by) { // @ts-ignore fireEvent(this, "supported-by", { integration }); return; } if (integration.iot_standards) { // @ts-ignore fireEvent(this, "select-brand", { brand: integration.domain, }); return; } if ( (domain === this.domain && (("integration_type" in this.integration! && !this.integration.config_flow) || (!("integration_type" in this.integration!) && (!this.integration!.integrations || !(domain in this.integration!.integrations))))) || // config_flow being undefined means its false (!("integration_type" in this.integration!) && !this.integration!.integrations?.[domain]?.config_flow) ) { const manifest = await fetchIntegrationManifest(this.hass, domain); showYamlIntegrationDialog(this, { manifest }); return; } const root = this.getRootNode(); showConfigFlowDialog( root instanceof ShadowRoot ? (root.host as HTMLElement) : this, { startFlowHandler: domain, showAdvanced: this.hass.userData?.showAdvanced, manifest: await fetchIntegrationManifest(this.hass, domain), } ); fireEvent(this, "close-dialog"); } private async _flowInProgressPicked(ev: CustomEvent) { if (!shouldHandleRequestSelectedEvent(ev)) { return; } const flow: DataEntryFlowProgress = (ev.currentTarget as any).flow; const root = this.getRootNode(); showConfigFlowDialog( root instanceof ShadowRoot ? (root.host as HTMLElement) : this, { continueFlowId: flow.flow_id, showAdvanced: this.hass.userData?.showAdvanced, manifest: await fetchIntegrationManifest(this.hass, flow.handler), } ); fireEvent(this, "close-dialog"); } private _standardPicked(ev: CustomEvent) { if (!shouldHandleRequestSelectedEvent(ev)) { return; } const domain = (ev.currentTarget as any).domain; const root = this.getRootNode(); fireEvent(this, "close-dialog"); protocolIntegrationPicked( root instanceof ShadowRoot ? (root.host as HTMLElement) : this, this.hass, domain, { brand: this.domain } ); } static styles = [ haStyle, css` :host { display: block; --mdc-list-item-graphic-size: 40px; --mdc-list-side-padding: 24px; } h3 { margin: 8px 24px 0; color: var(--secondary-text-color); font-size: 14px; font-weight: 500; } h3:first-of-type { margin-top: 0; } img { width: 40px; height: 40px; } li[divider] { margin-top: 8px; } `, ]; } declare global { interface HTMLElementTagNameMap { "ha-domain-integrations": HaDomainIntegrations; } }