diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts
index d4323b15f7..9fc36f7dc2 100644
--- a/src/dialogs/config-flow/show-dialog-config-flow.ts
+++ b/src/dialogs/config-flow/show-dialog-config-flow.ts
@@ -1,4 +1,4 @@
-import { html } from "lit";
+import { html, nothing } from "lit";
import {
createConfigFlow,
deleteConfigFlow,
@@ -194,13 +194,7 @@ export const showConfigFlowDialog = (
.content=${description}
>
`
- : ""}
-
- ${hass.localize(
- "ui.panel.config.integrations.config_flow.created_config",
- { name: step.title }
- )}
-
+ : nothing}
`;
},
diff --git a/src/dialogs/config-flow/show-dialog-sub-config-flow.ts b/src/dialogs/config-flow/show-dialog-sub-config-flow.ts
index 5c58671bea..a2cbfca060 100644
--- a/src/dialogs/config-flow/show-dialog-sub-config-flow.ts
+++ b/src/dialogs/config-flow/show-dialog-sub-config-flow.ts
@@ -1,4 +1,4 @@
-import { html } from "lit";
+import { html, nothing } from "lit";
import type { ConfigEntry } from "../../data/config_entries";
import { domainToName } from "../../data/integration";
import {
@@ -200,13 +200,7 @@ export const showSubConfigFlowDialog = (
.content=${description}
>
`
- : ""}
-
- ${hass.localize(
- "ui.panel.config.integrations.config_flow.created_config",
- { name: step.title }
- )}
-
+ : nothing}
`;
},
diff --git a/src/dialogs/config-flow/step-flow-create-entry.ts b/src/dialogs/config-flow/step-flow-create-entry.ts
index db6b147f57..683771a567 100644
--- a/src/dialogs/config-flow/step-flow-create-entry.ts
+++ b/src/dialogs/config-flow/step-flow-create-entry.ts
@@ -1,10 +1,13 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
-import { customElement, property } from "lit/decorators";
+import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event";
-import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
+import {
+ computeDeviceName,
+ computeDeviceNameDisplay,
+} from "../../common/entity/compute_device_name";
import { computeDomain } from "../../common/entity/compute_domain";
import { navigate } from "../../common/navigate";
import "../../components/ha-area-picker";
@@ -18,6 +21,8 @@ import { showAlertDialog } from "../generic/show-dialog-box";
import { showVoiceAssistantSetupDialog } from "../voice-assistant-setup/show-voice-assistant-setup-dialog";
import type { FlowConfig } from "./show-dialog-data-entry-flow";
import { configFlowContentStyles } from "./styles";
+import { brandsUrl } from "../../util/brands-url";
+import { domainToName } from "../../data/integration";
@customElement("step-flow-create-entry")
class StepFlowCreateEntry extends LitElement {
@@ -27,7 +32,12 @@ class StepFlowCreateEntry extends LitElement {
@property({ attribute: false }) public step!: DataEntryFlowStepCreateEntry;
- navigateToResult = false;
+ public navigateToResult = false;
+
+ @state() private _deviceUpdate: Record<
+ string,
+ { name?: string; area?: string }
+ > = {};
private _devices = memoizeOne(
(
@@ -99,7 +109,13 @@ class StepFlowCreateEntry extends LitElement {
this.step.result?.entry_id
);
return html`
-
${this.flowConfig.renderCreateEntryDescription(this.hass, this.step)}
${this.step.result?.state === "not_loaded"
@@ -110,31 +126,62 @@ class StepFlowCreateEntry extends LitElement {
>`
: nothing}
${devices.length === 0
- ? nothing
+ ? html`
+ ${localize(
+ "ui.panel.config.integrations.config_flow.created_config",
+ { name: this.step.title }
+ )}
+
`
: html`
-
- ${localize(
- "ui.panel.config.integrations.config_flow.found_following_devices"
- )}:
-
${devices.map(
(device) => html`
-
-
${computeDeviceNameDisplay(device, this.hass)}
- ${!device.model && !device.manufacturer
- ? html` `
- : html`${device.model}
- ${device.manufacturer
- ? html`(${device.manufacturer})`
- : ""}`}
+
+ ${this.step.result?.domain
+ ? html`

`
+ : nothing}
+
+ ${device.model || device.manufacturer}
+ ${device.model
+ ? html`
+ ${device.manufacturer}
+ `
+ : nothing}
+
+
@@ -146,14 +193,32 @@ class StepFlowCreateEntry extends LitElement {
${localize(
- "ui.panel.config.integrations.config_flow.finish"
+ `ui.panel.config.integrations.config_flow.${!devices.length || Object.keys(this._deviceUpdate).length ? "finish" : "finish_skip"}`
)}
`;
}
- private _flowDone(): void {
+ private async _flowDone(): Promise
{
+ if (Object.keys(this._deviceUpdate).length) {
+ await Promise.all(
+ Object.entries(this._deviceUpdate).map(([deviceId, update]) =>
+ updateDeviceRegistryEntry(this.hass, deviceId, {
+ name_by_user: update.name,
+ area_id: update.area,
+ }).catch((err: any) => {
+ showAlertDialog(this, {
+ text: this.hass.localize(
+ "ui.panel.config.integrations.config_flow.error_saving_device",
+ { error: err.message }
+ ),
+ });
+ })
+ )
+ );
+ }
+
fireEvent(this, "flow-update", { step: undefined });
if (this.step.result && this.navigateToResult) {
navigate(
@@ -165,21 +230,25 @@ class StepFlowCreateEntry extends LitElement {
private async _areaPicked(ev: CustomEvent) {
const picker = ev.currentTarget as any;
const device = picker.device;
-
const area = ev.detail.value;
- try {
- await updateDeviceRegistryEntry(this.hass, device, {
- area_id: area,
- });
- } catch (err: any) {
- showAlertDialog(this, {
- text: this.hass.localize(
- "ui.panel.config.integrations.config_flow.error_saving_area",
- { error: err.message }
- ),
- });
- picker.value = null;
+
+ if (!(device in this._deviceUpdate)) {
+ this._deviceUpdate[device] = {};
}
+ this._deviceUpdate[device].area = area;
+ this.requestUpdate("_deviceUpdate");
+ }
+
+ private _deviceNameChanged(ev): void {
+ const picker = ev.currentTarget as any;
+ const device = picker.device;
+ const name = picker.value;
+
+ if (!(device in this._deviceUpdate)) {
+ this._deviceUpdate[device] = {};
+ }
+ this._deviceUpdate[device].name = name;
+ this.requestUpdate("_deviceUpdate");
}
static get styles(): CSSResultGroup {
@@ -188,18 +257,41 @@ class StepFlowCreateEntry extends LitElement {
css`
.devices {
display: flex;
- flex-wrap: wrap;
margin: -4px;
max-height: 600px;
overflow-y: auto;
+ flex-direction: column;
}
.device {
border: 1px solid var(--divider-color);
- padding: 5px;
+ padding: 6px;
border-radius: 4px;
margin: 4px;
display: inline-block;
- width: 250px;
+ }
+ .device-info {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+ .device-info img {
+ width: 40px;
+ height: 40px;
+ }
+ .device-info-details {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+ .secondary {
+ color: var(--secondary-text-color);
+ }
+ ha-textfield,
+ ha-area-picker {
+ display: block;
+ }
+ ha-textfield {
+ margin: 8px 0;
}
.buttons > *:last-child {
margin-left: auto;
diff --git a/src/panels/config/integrations/integration-panels/zha/zha-device-card.ts b/src/panels/config/integrations/integration-panels/zha/zha-device-card.ts
index 0c411f8ad6..dca4ce1cd2 100644
--- a/src/panels/config/integrations/integration-panels/zha/zha-device-card.ts
+++ b/src/panels/config/integrations/integration-panels/zha/zha-device-card.ts
@@ -189,7 +189,7 @@ class ZHADeviceCard extends SubscribeMixin(LitElement) {
} catch (err: any) {
showAlertDialog(this, {
text: this.hass.localize(
- "ui.panel.config.integrations.config_flow.error_saving_area",
+ "ui.panel.config.integrations.config_flow.error_saving_device",
{ error: err.message }
),
});
diff --git a/src/translations/en.json b/src/translations/en.json
index 990c7a5079..1624b08491 100644
--- a/src/translations/en.json
+++ b/src/translations/en.json
@@ -5304,19 +5304,21 @@
},
"config_flow": {
"success": "Success",
+ "assign_area": "Assign {number, plural,\n one {device}\n other {devices}\n} to area",
+ "device_name": "Device name",
"aborted": "Aborted",
"close": "Close",
"finish": "Finish",
+ "finish_skip": "Skip and finish",
"submit": "Submit",
"next": "Next",
"preview": "Preview",
- "found_following_devices": "We found the following devices",
"yaml_only_title": "This integration cannot be added from the UI",
"yaml_only": "You can add this integration by adding it to your ''configuration.yaml''. See the documentation for more information.",
"open_documentation": "Open documentation",
"no_config_flow": "This integration does not support configuration via the UI. If you followed this link from the Home Assistant website, make sure you run the latest version of Home Assistant.",
"not_all_required_fields": "Not all required fields are filled in.",
- "error_saving_area": "Error saving area: {error}",
+ "error_saving_device": "Error updating device: {error}",
"created_config": "Created configuration for {name}.",
"external_step": {
"description": "This step requires you to visit an external website to be completed.",