mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Improve protocol integration add device / integration (#16767)
This commit is contained in:
parent
e044ddcb57
commit
10ee8fda5b
@ -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(
|
||||
|
@ -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<string>();
|
||||
|
||||
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<string>).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`
|
||||
|
@ -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<EntityRegistryEntry, "id" | "unique_id"> {
|
||||
@ -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<string>();
|
||||
|
||||
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<string>).includes(
|
||||
[...filteredDomains][0]
|
||||
);
|
||||
|
||||
return html`
|
||||
<hass-tabs-subpage-data-table
|
||||
@ -545,7 +556,7 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
@search-changed=${this._handleSearchChange}
|
||||
@row-click=${this._openEditEntry}
|
||||
id="entity_id"
|
||||
.hasFab=${includeZHAFab}
|
||||
.hasFab=${includeAddDeviceFab}
|
||||
>
|
||||
<ha-integration-overflow-menu
|
||||
.hass=${this.hass}
|
||||
@ -701,16 +712,16 @@ export class HaConfigEntities extends SubscribeMixin(LitElement) {
|
||||
</ha-check-list-item>
|
||||
</ha-button-menu>
|
||||
`}
|
||||
${includeZHAFab
|
||||
? html`<a href="/config/zha/add" slot="fab">
|
||||
<ha-fab
|
||||
.label=${this.hass.localize("ui.panel.config.zha.add_device")}
|
||||
extended
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
</a>`
|
||||
${includeAddDeviceFab
|
||||
? html`<ha-fab
|
||||
.label=${this.hass.localize("ui.panel.config.devices.add_device")}
|
||||
extended
|
||||
@click=${this._addDevice}
|
||||
slot="fab"
|
||||
?rtl=${computeRTL(this.hass)}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
</ha-fab>`
|
||||
: nothing}
|
||||
</hass-tabs-subpage-data-table>
|
||||
`;
|
||||
@ -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<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 {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -427,13 +427,13 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
|
||||
<ha-card>
|
||||
<h1 class="card-header">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.integrations.integration_page.entries`
|
||||
"ui.panel.config.integrations.integration_page.entries"
|
||||
)}
|
||||
</h1>
|
||||
${normalEntries.length === 0
|
||||
? html`<div class="card-content no-entries">
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.integrations.integration_page.no_entries`
|
||||
"ui.panel.config.integrations.integration_page.no_entries"
|
||||
)}
|
||||
</div>`
|
||||
: nothing}
|
||||
@ -446,7 +446,10 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
|
||||
<ha-fab
|
||||
slot="fab"
|
||||
@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
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
|
||||
|
@ -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": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user