Improve protocol integration add device / integration (#16767)

This commit is contained in:
Bram Kragten 2023-06-05 16:08:55 +02:00 committed by GitHub
parent e044ddcb57
commit 10ee8fda5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 62 deletions

View File

@ -17,7 +17,7 @@ export const protocolIntegrationPicked = async (
element: HTMLElement, element: HTMLElement,
hass: HomeAssistant, hass: HomeAssistant,
domain: string, domain: string,
options?: { brand?: string; domain?: string } options?: { brand?: string; domain?: string; config_entry?: string }
) => { ) => {
if (options?.domain) { if (options?.domain) {
const localize = await hass.loadBackendTranslation("title", options.domain); const localize = await hass.loadBackendTranslation("title", options.domain);
@ -32,11 +32,16 @@ export const protocolIntegrationPicked = async (
} }
if (domain === "zwave_js") { if (domain === "zwave_js") {
const entries = await getConfigEntries(hass, { const entries = options?.config_entry
domain, ? 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 // If the component isn't loaded, ask them to load the integration first
showConfirmationDialog(element, { showConfirmationDialog(element, {
title: hass.localize( title: hass.localize(
@ -71,14 +76,19 @@ export const protocolIntegrationPicked = async (
} }
showZWaveJSAddNodeDialog(element, { showZWaveJSAddNodeDialog(element, {
entry_id: entries[0].entry_id, entry_id: options?.config_entry || entries![0].entry_id,
}); });
} else if (domain === "zha") { } else if (domain === "zha") {
const entries = await getConfigEntries(hass, { const entries = options?.config_entry
domain, ? 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 // If the component isn't loaded, ask them to load the integration first
showConfirmationDialog(element, { showConfirmationDialog(element, {
title: hass.localize( title: hass.localize(
@ -117,10 +127,15 @@ export const protocolIntegrationPicked = async (
navigate("/config/zha/add"); navigate("/config/zha/add");
} else if (domain === "matter") { } else if (domain === "matter") {
const entries = await getConfigEntries(hass, { const entries = options?.config_entry
domain, ? undefined
}); : await getConfigEntries(hass, {
if (!isComponentLoaded(hass, domain) || !entries.length) { domain,
});
if (
!isComponentLoaded(hass, domain) ||
(!options?.config_entry && !entries?.length)
) {
// If the component isn't loaded, ask them to load the integration first // If the component isn't loaded, ask them to load the integration first
showConfirmationDialog(element, { showConfirmationDialog(element, {
title: hass.localize( title: hass.localize(

View File

@ -1,11 +1,15 @@
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item"; import type { RequestSelectedDetail } from "@material/mwc-list/mwc-list-item";
import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js"; import { mdiCancel, mdiFilterVariant, mdiPlus } from "@mdi/js";
import "@lrnwebcomponents/simple-tooltip/simple-tooltip";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { HASSDomEvent } from "../../../common/dom/fire_event"; import { HASSDomEvent } from "../../../common/dom/fire_event";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import {
protocolIntegrationPicked,
PROTOCOL_INTEGRATIONS,
} from "../../../common/integrations/protocolIntegrationPicked";
import { navigate } from "../../../common/navigate"; import { navigate } from "../../../common/navigate";
import { blankBeforePercent } from "../../../common/translations/blank_before_percent"; import { blankBeforePercent } from "../../../common/translations/blank_before_percent";
import { LocalizeFunc } from "../../../common/translations/localize"; import { LocalizeFunc } from "../../../common/translations/localize";
@ -39,8 +43,6 @@ import { HomeAssistant, Route } from "../../../types";
import { brandsUrl } from "../../../util/brands-url"; import { brandsUrl } from "../../../util/brands-url";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu"; 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"; import { showAddIntegrationDialog } from "../integrations/show-add-integration-dialog";
interface DeviceRowData extends DeviceRegistryEntry { interface DeviceRowData extends DeviceRegistryEntry {
@ -186,6 +188,8 @@ export class HaConfigDeviceDashboard extends LitElement {
let filterConfigEntry: ConfigEntry | undefined; let filterConfigEntry: ConfigEntry | undefined;
const filteredDomains = new Set<string>();
filters.forEach((value, key) => { filters.forEach((value, key) => {
if (key === "config_entry") { if (key === "config_entry") {
outputDevices = outputDevices.filter((device) => outputDevices = outputDevices.filter((device) =>
@ -193,6 +197,9 @@ export class HaConfigDeviceDashboard extends LitElement {
); );
startLength = outputDevices.length; startLength = outputDevices.length;
filterConfigEntry = entries.find((entry) => entry.entry_id === value); filterConfigEntry = entries.find((entry) => entry.entry_id === value);
if (filterConfigEntry) {
filteredDomains.add(filterConfigEntry.domain);
}
} }
if (key === "domain") { if (key === "domain") {
const entryIds = entries const entryIds = entries
@ -202,6 +209,7 @@ export class HaConfigDeviceDashboard extends LitElement {
device.config_entries.some((entryId) => entryIds.includes(entryId)) device.config_entries.some((entryId) => entryIds.includes(entryId))
); );
startLength = outputDevices.length; startLength = outputDevices.length;
filteredDomains.add(value);
} }
}); });
@ -251,6 +259,7 @@ export class HaConfigDeviceDashboard extends LitElement {
return { return {
devicesOutput: outputDevices, devicesOutput: outputDevices,
filteredConfigEntry: filterConfigEntry, filteredConfigEntry: filterConfigEntry,
filteredDomains,
}; };
} }
); );
@ -546,25 +555,25 @@ export class HaConfigDeviceDashboard extends LitElement {
} }
private _addDevice() { private _addDevice() {
const { filteredConfigEntry } = this._devicesAndFilterDomains( const { filteredConfigEntry, filteredDomains } =
this.devices, this._devicesAndFilterDomains(
this.entries, this.devices,
this.entities, this.entries,
this.areas, this.entities,
this._searchParms, this.areas,
this._showDisabled, this._searchParms,
this.hass.localize this._showDisabled,
); this.hass.localize
if (filteredConfigEntry?.domain === "zha") { );
navigate(`/config/zha/add`); if (
return; filteredDomains.size === 1 &&
} (PROTOCOL_INTEGRATIONS as ReadonlyArray<string>).includes(
if (filteredConfigEntry?.domain === "zwave_js") { [...filteredDomains][0]
this._showZJSAddDeviceDialog(filteredConfigEntry); )
return; ) {
} protocolIntegrationPicked(this, this.hass, [...filteredDomains][0], {
if (filteredConfigEntry?.domain === "matter") { config_entry: filteredConfigEntry?.entry_id,
showMatterAddDeviceDialog(this); });
return; return;
} }
showAddIntegrationDialog(this, { 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 { static get styles(): CSSResultGroup {
return [ return [
css` css`

View File

@ -67,6 +67,11 @@ import { haStyle } from "../../../resources/styles";
import type { HomeAssistant, Route } from "../../../types"; import type { HomeAssistant, Route } from "../../../types";
import { configSections } from "../ha-panel-config"; import { configSections } from "../ha-panel-config";
import "../integrations/ha-integration-overflow-menu"; 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 export interface StateEntity
extends Omit<EntityRegistryEntry, "id" | "unique_id"> { extends Omit<EntityRegistryEntry, "id" | "unique_id"> {
@ -348,7 +353,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
? entities.concat(stateEntities) ? entities.concat(stateEntities)
: entities; : entities;
const filteredDomains: string[] = []; let filteredConfigEntry: ConfigEntry | undefined;
const filteredDomains = new Set<string>();
filters.forEach((value, key) => { filters.forEach((value, key) => {
if (key === "config_entry") { if (key === "config_entry") {
@ -373,7 +379,8 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
const configEntry = entries.find((entry) => entry.entry_id === value); const configEntry = entries.find((entry) => entry.entry_id === value);
if (configEntry) { if (configEntry) {
filteredDomains.push(configEntry.domain); filteredDomains.add(configEntry.domain);
filteredConfigEntry = configEntry;
} }
} }
if (key === "domain") { if (key === "domain") {
@ -389,7 +396,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
entity.config_entry_id && entity.config_entry_id &&
entryIds.includes(entity.config_entry_id) entryIds.includes(entity.config_entry_id)
); );
filteredDomains.push(value); filteredDomains.add(value);
startLength = filteredEntities.length; startLength = filteredEntities.length;
} }
}); });
@ -444,7 +451,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
} }
this._numHiddenEntities = startLength - result.length; 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 this._entries
); );
const includeZHAFab = filteredDomains.includes("zha"); const includeAddDeviceFab =
filteredDomains.size === 1 &&
(PROTOCOL_INTEGRATIONS as ReadonlyArray<string>).includes(
[...filteredDomains][0]
);
return html` return html`
<hass-tabs-subpage-data-table <hass-tabs-subpage-data-table
@ -545,7 +556,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
@search-changed=${this._handleSearchChange} @search-changed=${this._handleSearchChange}
@row-click=${this._openEditEntry} @row-click=${this._openEditEntry}
id="entity_id" id="entity_id"
.hasFab=${includeZHAFab} .hasFab=${includeAddDeviceFab}
> >
<ha-integration-overflow-menu <ha-integration-overflow-menu
.hass=${this.hass} .hass=${this.hass}
@ -701,16 +712,16 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
</ha-check-list-item> </ha-check-list-item>
</ha-button-menu> </ha-button-menu>
`} `}
${includeZHAFab ${includeAddDeviceFab
? html`<a href="/config/zha/add" slot="fab"> ? html`<ha-fab
<ha-fab .label=${this.hass.localize("ui.panel.config.devices.add_device")}
.label=${this.hass.localize("ui.panel.config.zha.add_device")} extended
extended @click=${this._addDevice}
?rtl=${computeRTL(this.hass)} slot="fab"
> ?rtl=${computeRTL(this.hass)}
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon> >
</ha-fab> <ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
</a>` </ha-fab>`
: nothing} : nothing}
</hass-tabs-subpage-data-table> </hass-tabs-subpage-data-table>
`; `;
@ -959,6 +970,36 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
this._showHidden = true; 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<string>).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 { static get styles(): CSSResultGroup {
return [ return [
haStyle, haStyle,

View File

@ -427,13 +427,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
<ha-card> <ha-card>
<h1 class="card-header"> <h1 class="card-header">
${this.hass.localize( ${this.hass.localize(
`ui.panel.config.integrations.integration_page.entries` "ui.panel.config.integrations.integration_page.entries"
)} )}
</h1> </h1>
${normalEntries.length === 0 ${normalEntries.length === 0
? html`<div class="card-content no-entries"> ? html`<div class="card-content no-entries">
${this.hass.localize( ${this.hass.localize(
`ui.panel.config.integrations.integration_page.no_entries` "ui.panel.config.integrations.integration_page.no_entries"
)} )}
</div>` </div>`
: nothing} : nothing}
@ -446,7 +446,10 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
<ha-fab <ha-fab
slot="fab" slot="fab"
@click=${this._addIntegration} @click=${this._addIntegration}
.label=${`Add ${domainToName(this.hass.localize, this.domain)}`} .label=${this.hass.localize(
"ui.panel.config.integrations.integration_page.add",
{ integration: domainToName(this.hass.localize, this.domain) }
)}
extended extended
> >
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon> <ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>

View File

@ -3252,7 +3252,8 @@
"integration_page": { "integration_page": {
"entries": "Integration entries", "entries": "Integration entries",
"no_entries": "No entries", "no_entries": "No entries",
"attention_entries": "Needs attention" "attention_entries": "Needs attention",
"add": "Add {integration}"
}, },
"config_entry": { "config_entry": {
"application_credentials": { "application_credentials": {