diff --git a/src/common/integrations/protocolIntegrationPicked.ts b/src/common/integrations/protocolIntegrationPicked.ts index 558bee552d..d6125b172b 100644 --- a/src/common/integrations/protocolIntegrationPicked.ts +++ b/src/common/integrations/protocolIntegrationPicked.ts @@ -17,7 +17,7 @@ export const protocolIntegrationPicked = async ( element: HTMLElement, hass: HomeAssistant, domain: string, - options?: { brand?: string; domain?: string } + options?: { brand?: string; domain?: string; config_entry?: string } ) => { if (options?.domain) { const localize = await hass.loadBackendTranslation("title", options.domain); @@ -32,11 +32,16 @@ export const protocolIntegrationPicked = async ( } if (domain === "zwave_js") { - const entries = await getConfigEntries(hass, { - domain, - }); + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); - if (!isComponentLoaded(hass, "zwave_js") || !entries.length) { + if ( + !isComponentLoaded(hass, "zwave_js") || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( @@ -71,14 +76,19 @@ export const protocolIntegrationPicked = async ( } showZWaveJSAddNodeDialog(element, { - entry_id: entries[0].entry_id, + entry_id: options?.config_entry || entries![0].entry_id, }); } else if (domain === "zha") { - const entries = await getConfigEntries(hass, { - domain, - }); + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); - if (!isComponentLoaded(hass, "zha") || !entries.length) { + if ( + !isComponentLoaded(hass, "zha") || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( @@ -117,10 +127,15 @@ export const protocolIntegrationPicked = async ( navigate("/config/zha/add"); } else if (domain === "matter") { - const entries = await getConfigEntries(hass, { - domain, - }); - if (!isComponentLoaded(hass, domain) || !entries.length) { + const entries = options?.config_entry + ? undefined + : await getConfigEntries(hass, { + domain, + }); + if ( + !isComponentLoaded(hass, domain) || + (!options?.config_entry && !entries?.length) + ) { // If the component isn't loaded, ask them to load the integration first showConfirmationDialog(element, { title: hass.localize( diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts index bd1402d0e1..0a2a027e30 100644 --- a/src/panels/config/devices/ha-config-devices-dashboard.ts +++ b/src/panels/config/devices/ha-config-devices-dashboard.ts @@ -1,11 +1,15 @@ +import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js"; -import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { HASSDomEvent } from "../../../common/dom/fire_event"; import { computeStateDomain } from "../../../common/entity/compute_state_domain"; +import { + protocolIntegrationPicked, + PROTOCOL_INTEGRATIONS, +} from "../../../common/integrations/protocolIntegrationPicked"; import { navigate } from "../../../common/navigate"; import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import { LocalizeFunc } from "../../../common/translations/localize"; @@ -39,8 +43,6 @@ import { HomeAssistant, Route } from "../../../types"; import { brandsUrl } from "../../../util/brands-url"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; -import { showMatterAddDeviceDialog } from "../integrations/integration-panels/matter/show-dialog-add-matter-device"; -import { showZWaveJSAddNodeDialog } from "../integrations/integration-panels/zwave_js/show-dialog-zwave_js-add-node"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; interface DeviceRowData extends DeviceRegistryEntry { @@ -186,6 +188,8 @@ export class HaConfigDeviceDashboard extends LitElement { let filterConfigEntry: ConfigEntry | undefined; + const filteredDomains = new Set(); + filters.forEach((value, key) => { if (key === "config_entry") { outputDevices = outputDevices.filter((device) => @@ -193,6 +197,9 @@ export class HaConfigDeviceDashboard extends LitElement { ); startLength = outputDevices.length; filterConfigEntry = entries.find((entry) => entry.entry_id === value); + if (filterConfigEntry) { + filteredDomains.add(filterConfigEntry.domain); + } } if (key === "domain") { const entryIds = entries @@ -202,6 +209,7 @@ export class HaConfigDeviceDashboard extends LitElement { device.config_entries.some((entryId) => entryIds.includes(entryId)) ); startLength = outputDevices.length; + filteredDomains.add(value); } }); @@ -251,6 +259,7 @@ export class HaConfigDeviceDashboard extends LitElement { return { devicesOutput: outputDevices, filteredConfigEntry: filterConfigEntry, + filteredDomains, }; } ); @@ -546,25 +555,25 @@ export class HaConfigDeviceDashboard extends LitElement { } private _addDevice() { - const { filteredConfigEntry } = this._devicesAndFilterDomains( - this.devices, - this.entries, - this.entities, - this.areas, - this._searchParms, - this._showDisabled, - this.hass.localize - ); - if (filteredConfigEntry?.domain === "zha") { - navigate(`/config/zha/add`); - return; - } - if (filteredConfigEntry?.domain === "zwave_js") { - this._showZJSAddDeviceDialog(filteredConfigEntry); - return; - } - if (filteredConfigEntry?.domain === "matter") { - showMatterAddDeviceDialog(this); + const { filteredConfigEntry, filteredDomains } = + this._devicesAndFilterDomains( + this.devices, + this.entries, + this.entities, + this.areas, + this._searchParms, + this._showDisabled, + this.hass.localize + ); + if ( + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ) + ) { + protocolIntegrationPicked(this, this.hass, [...filteredDomains][0], { + config_entry: filteredConfigEntry?.entry_id, + }); return; } showAddIntegrationDialog(this, { @@ -572,12 +581,6 @@ export class HaConfigDeviceDashboard extends LitElement { }); } - private _showZJSAddDeviceDialog(filteredConfigEntry: ConfigEntry) { - showZWaveJSAddNodeDialog(this, { - entry_id: filteredConfigEntry!.entry_id, - }); - } - static get styles(): CSSResultGroup { return [ css` diff --git a/src/panels/config/entities/ha-config-entities.ts b/src/panels/config/entities/ha-config-entities.ts index 2afab3ca2c..fb4673059b 100644 --- a/src/panels/config/entities/ha-config-entities.ts +++ b/src/panels/config/entities/ha-config-entities.ts @@ -67,6 +67,11 @@ import { haStyle } from "../../../resources/styles"; import type { HomeAssistant, Route } from "../../../types"; import { configSections } from "../ha-panel-config"; import "../integrations/ha-integration-overflow-menu"; +import { + protocolIntegrationPicked, + PROTOCOL_INTEGRATIONS, +} from "../../../common/integrations/protocolIntegrationPicked"; +import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog"; export interface StateEntity extends Omit { @@ -348,7 +353,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { ? entities.concat(stateEntities) : entities; - const filteredDomains: string[] = []; + let filteredConfigEntry: ConfigEntry | undefined; + const filteredDomains = new Set(); filters.forEach((value, key) => { if (key === "config_entry") { @@ -373,7 +379,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { const configEntry = entries.find((entry) => entry.entry_id === value); if (configEntry) { - filteredDomains.push(configEntry.domain); + filteredDomains.add(configEntry.domain); + filteredConfigEntry = configEntry; } } if (key === "domain") { @@ -389,7 +396,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { entity.config_entry_id && entryIds.includes(entity.config_entry_id) ); - filteredDomains.push(value); + filteredDomains.add(value); startLength = filteredEntities.length; } }); @@ -444,7 +451,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { } this._numHiddenEntities = startLength - result.length; - return { filteredEntities: result, filteredDomains: filteredDomains }; + return { filteredEntities: result, filteredConfigEntry, filteredDomains }; } ); @@ -509,7 +516,11 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { this._entries ); - const includeZHAFab = filteredDomains.includes("zha"); + const includeAddDeviceFab = + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ); return html` `} - ${includeZHAFab - ? html` - - - - ` + ${includeAddDeviceFab + ? html` + + ` : nothing} `; @@ -959,6 +970,36 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) { this._showHidden = true; } + private _addDevice() { + const { filteredConfigEntry, filteredDomains } = + this._filteredEntitiesAndDomains( + this._entities!, + this._devices, + this._areas, + this._stateEntities, + this._searchParms, + this._showDisabled, + this._showUnavailable, + this._showReadOnly, + this._showHidden, + this._entries + ); + if ( + filteredDomains.size === 1 && + (PROTOCOL_INTEGRATIONS as ReadonlyArray).includes( + [...filteredDomains][0] + ) + ) { + protocolIntegrationPicked(this, this.hass, [...filteredDomains][0], { + config_entry: filteredConfigEntry?.entry_id, + }); + return; + } + showAddIntegrationDialog(this, { + domain: this._searchParms.get("domain") || undefined, + }); + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/panels/config/integrations/ha-config-integration-page.ts b/src/panels/config/integrations/ha-config-integration-page.ts index f9a9ad3aea..2764832b6f 100644 --- a/src/panels/config/integrations/ha-config-integration-page.ts +++ b/src/panels/config/integrations/ha-config-integration-page.ts @@ -427,13 +427,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {

${this.hass.localize( - `ui.panel.config.integrations.integration_page.entries` + "ui.panel.config.integrations.integration_page.entries" )}

${normalEntries.length === 0 ? html`
${this.hass.localize( - `ui.panel.config.integrations.integration_page.no_entries` + "ui.panel.config.integrations.integration_page.no_entries" )}
` : nothing} @@ -446,7 +446,10 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) { diff --git a/src/translations/en.json b/src/translations/en.json index d8ddbfbbbc..a0e763a48c 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3252,7 +3252,8 @@ "integration_page": { "entries": "Integration entries", "no_entries": "No entries", - "attention_entries": "Needs attention" + "attention_entries": "Needs attention", + "add": "Add {integration}" }, "config_entry": { "application_credentials": {