Avoid starting config flow and show alert dialog early if single config entry only (#19648)

* Add note that integration only supports one entry on the integration page

* Set on error

* Move single instance info to the manifest and add it to the add integration dialog as well

* Get config entries only when single_instance_only set and add check to redirect

* Make single_instance_only optional

* Add missing import

* Use new manifest option name

* Fix translation key

* Rename dialog and re-add button

* Fix linting error

* Use alert dialog instead of new one

* Remove ha-alert on integration page

* Remove css change

* Apply language tweak

Co-authored-by: Bram Kragten <mail@bramkragten.nl>

---------

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Jan-Philipp Benecke 2024-03-13 16:20:28 +01:00 committed by GitHub
parent 91d3fb0ea8
commit 7facc375bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 68 additions and 2 deletions

View File

@ -43,6 +43,7 @@ export interface IntegrationManifest {
| "cloud_push"
| "local_polling"
| "local_push";
single_config_entry?: boolean;
}
export interface IntegrationSetup {
domain: string;

View File

@ -11,6 +11,7 @@ export interface Integration {
iot_class?: string;
supported_by?: string;
is_built_in?: boolean;
single_config_entry?: boolean;
}
export interface Integrations {

View File

@ -54,6 +54,7 @@ import {
AddIntegrationDialogParams,
showYamlIntegrationDialog,
} from "./show-add-integration-dialog";
import { getConfigEntries } from "../../../data/config_entries";
export interface IntegrationListItem {
name: string;
@ -67,6 +68,7 @@ export interface IntegrationListItem {
cloud?: boolean;
is_built_in?: boolean;
is_add?: boolean;
single_config_entry?: boolean;
}
@customElement("dialog-add-integration")
@ -208,6 +210,7 @@ class AddIntegrationDialog extends LitElement {
supported_by: integration.supported_by,
is_built_in: supportedIntegration.is_built_in !== false,
cloud: supportedIntegration.iot_class?.startsWith("cloud_"),
single_config_entry: integration.single_config_entry,
});
} else if (
!("integration_type" in integration) &&
@ -572,6 +575,27 @@ class AddIntegrationDialog extends LitElement {
return;
}
if (integration.single_config_entry) {
const configEntries = await getConfigEntries(this.hass, {
domain: integration.domain,
});
if (configEntries.length > 0) {
this.closeDialog();
showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry_title"
),
text: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry",
{
integration_name: integration.name,
}
),
});
return;
}
}
if (integration.config_flow) {
this._createFlow(integration.domain);
return;

View File

@ -1318,6 +1318,26 @@ class HaConfigIntegrationPage extends SubscribeMixin(LitElement) {
}
private async _addIntegration() {
if (this._manifest?.single_config_entry) {
const entries = this._domainConfigEntries(
this.domain,
this._extraConfigEntries || this.configEntries
);
if (entries.length > 0) {
await showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry_title"
),
text: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry",
{
integration_name: this._manifest.name,
}
),
});
return;
}
}
showAddIntegrationDialog(this, {
domain: this.domain,
});

View File

@ -29,7 +29,7 @@ import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
import "../../../components/ha-svg-icon";
import "../../../components/search-input";
import { ConfigEntry } from "../../../data/config_entries";
import { ConfigEntry, getConfigEntries } from "../../../data/config_entries";
import { getConfigFlowInProgressCollection } from "../../../data/config_flow";
import { fetchDiagnosticHandlers } from "../../../data/diagnostics";
import {
@ -658,6 +658,24 @@ class HaConfigIntegrationsDashboard extends SubscribeMixin(LitElement) {
const integration = findIntegration(integrations, domain);
if (integration?.config_flow) {
if (integration.single_config_entry) {
const configEntries = await getConfigEntries(this.hass, { domain });
if (configEntries.length > 0) {
showAlertDialog(this, {
title: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry_title"
),
text: this.hass.localize(
"ui.panel.config.integrations.config_flow.single_config_entry",
{
integration_name: integration.name,
}
),
});
return;
}
}
// Integration exists, so we can just create a flow
const localize = await this.hass.loadBackendTranslation(
"title",

View File

@ -4043,7 +4043,9 @@
"missing_matter": "To add a {brand} device, you first need the {integration} integration and {supported_hardware_link}. Do you want to proceed with the setup of {integration}?",
"matter_mobile_app": "You need to use the Home Assistant Companion app on your mobile phone to commission Matter devices.",
"supported_hardware": "supported hardware",
"proceed": "Proceed"
"proceed": "Proceed",
"single_config_entry_title": "This integration allows only one configuration",
"single_config_entry": "{integration_name} supports only one configuration. Adding additional ones is not needed."
}
},
"users": {