diff --git a/gallery/src/pages/components/ha-form.ts b/gallery/src/pages/components/ha-form.ts
index ccc287fd85..e33b7f8780 100644
--- a/gallery/src/pages/components/ha-form.ts
+++ b/gallery/src/pages/components/ha-form.ts
@@ -64,6 +64,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
{
area_id: "backyard",
@@ -86,6 +87,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
{
area_id: null,
@@ -108,6 +110,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
];
diff --git a/gallery/src/pages/components/ha-selector.ts b/gallery/src/pages/components/ha-selector.ts
index cb3a1f2f49..8230fceccf 100644
--- a/gallery/src/pages/components/ha-selector.ts
+++ b/gallery/src/pages/components/ha-selector.ts
@@ -64,6 +64,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
{
area_id: "backyard",
@@ -86,6 +87,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
{
area_id: null,
@@ -108,6 +110,7 @@ const DEVICES: DeviceRegistryEntry[] = [
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
];
diff --git a/gallery/src/pages/misc/integration-card.ts b/gallery/src/pages/misc/integration-card.ts
index cab686e210..ac89788440 100644
--- a/gallery/src/pages/misc/integration-card.ts
+++ b/gallery/src/pages/misc/integration-card.ts
@@ -232,6 +232,7 @@ const createDeviceRegistryEntries = (
labels: [],
created_at: 0,
modified_at: 0,
+ primary_config_entry: null,
},
];
diff --git a/package.json b/package.json
index 7d0cd25dbe..f9f5892a33 100644
--- a/package.json
+++ b/package.json
@@ -216,7 +216,7 @@
"husky": "9.1.5",
"instant-mocha": "1.5.2",
"jszip": "3.10.1",
- "lint-staged": "15.2.9",
+ "lint-staged": "15.2.10",
"lit-analyzer": "2.0.3",
"lodash.merge": "4.6.2",
"lodash.template": "4.5.0",
diff --git a/pyproject.toml b/pyproject.toml
index 8fc228d388..758245b668 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "home-assistant-frontend"
-version = "20240904.0"
+version = "20240906.0"
license = {text = "Apache-2.0"}
description = "The Home Assistant frontend"
readme = "README.md"
diff --git a/src/components/ha-selector/ha-selector-number.ts b/src/components/ha-selector/ha-selector-number.ts
index 418432ef27..8949082cfb 100644
--- a/src/components/ha-selector/ha-selector-number.ts
+++ b/src/components/ha-selector/ha-selector-number.ts
@@ -67,7 +67,9 @@ export class HaNumberSelector extends LitElement {
}
return html`
- ${this.label ? html`${this.label}${this.required ? "*" : ""}` : nothing}
+ ${this.label && !isBox
+ ? html`${this.label}${this.required ? "*" : ""}`
+ : nothing}
${!isBox
? html`
diff --git a/src/data/config_entries.ts b/src/data/config_entries.ts
index 37af47885d..3558d6e109 100644
--- a/src/data/config_entries.ts
+++ b/src/data/config_entries.ts
@@ -1,6 +1,6 @@
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type { HomeAssistant } from "../types";
-import type { IntegrationManifest, IntegrationType } from "./integration";
+import type { IntegrationType } from "./integration";
export interface ConfigEntry {
entry_id: string;
@@ -149,20 +149,19 @@ export const enableConfigEntry = (hass: HomeAssistant, configEntryId: string) =>
export const sortConfigEntries = (
configEntries: ConfigEntry[],
- manifestLookup: { [domain: string]: IntegrationManifest }
+ primaryConfigEntry: string | null
): ConfigEntry[] => {
- const sortedConfigEntries = [...configEntries];
-
- const getScore = (entry: ConfigEntry) => {
- const manifest = manifestLookup[entry.domain] as
- | IntegrationManifest
- | undefined;
- const isHelper = manifest?.integration_type === "helper";
- return isHelper ? -1 : 1;
- };
-
- const configEntriesCompare = (a: ConfigEntry, b: ConfigEntry) =>
- getScore(b) - getScore(a);
-
- return sortedConfigEntries.sort(configEntriesCompare);
+ if (!primaryConfigEntry) {
+ return configEntries;
+ }
+ const primaryEntry = configEntries.find(
+ (e) => e.entry_id === primaryConfigEntry
+ );
+ if (!primaryEntry) {
+ return configEntries;
+ }
+ const otherEntries = configEntries.filter(
+ (e) => e.entry_id !== primaryConfigEntry
+ );
+ return [primaryEntry, ...otherEntries];
};
diff --git a/src/data/device_registry.ts b/src/data/device_registry.ts
index f758f19b8d..2a1a334b2a 100644
--- a/src/data/device_registry.ts
+++ b/src/data/device_registry.ts
@@ -33,6 +33,7 @@ export interface DeviceRegistryEntry extends RegistryEntry {
entry_type: "service" | null;
disabled_by: "user" | "integration" | "config_entry" | null;
configuration_url: string | null;
+ primary_config_entry: string | null;
}
export interface DeviceEntityDisplayLookup {
diff --git a/src/panels/config/devices/ha-config-device-page.ts b/src/panels/config/devices/ha-config-device-page.ts
index fb691cc7e0..7d54a6596b 100644
--- a/src/panels/config/devices/ha-config-device-page.ts
+++ b/src/panels/config/devices/ha-config-device-page.ts
@@ -153,7 +153,7 @@ export class HaConfigDevicePage extends LitElement {
.filter((entId) => entId in entryLookup)
.map((entry) => entryLookup[entry]);
- return sortConfigEntries(deviceEntries, manifestLookup);
+ return sortConfigEntries(deviceEntries, device.primary_config_entry);
}
);
diff --git a/src/panels/config/devices/ha-config-devices-dashboard.ts b/src/panels/config/devices/ha-config-devices-dashboard.ts
index d7cfd5498b..a4744166fd 100644
--- a/src/panels/config/devices/ha-config-devices-dashboard.ts
+++ b/src/panels/config/devices/ha-config-devices-dashboard.ts
@@ -388,7 +388,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
device.config_entries
.filter((entId) => entId in entryLookup)
.map((entId) => entryLookup[entId]),
- manifestLookup
+ device.primary_config_entry
);
const labels = labelReg && device?.labels;
diff --git a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
index 90b440dcff..7d5b1e46d5 100644
--- a/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
+++ b/src/panels/config/integrations/integration-panels/zwave_js/zwave_js-node-config.ts
@@ -6,19 +6,18 @@ import {
mdiCloseCircle,
mdiProgressClock,
} from "@mdi/js";
-import { UnsubscribeFunc } from "home-assistant-js-websocket";
import {
- css,
CSSResultGroup,
- html,
LitElement,
- nothing,
PropertyValues,
TemplateResult,
+ css,
+ html,
+ nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
-import memoizeOne from "memoize-one";
+import { groupBy } from "../../../../../common/util/group-by";
import "../../../../../components/ha-alert";
import "../../../../../components/ha-card";
import "../../../../../components/ha-icon-next";
@@ -27,25 +26,19 @@ import "../../../../../components/ha-settings-row";
import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-switch";
import "../../../../../components/ha-textfield";
-import { groupBy } from "../../../../../common/util/group-by";
-import {
- computeDeviceName,
- DeviceRegistryEntry,
- subscribeDeviceRegistry,
-} from "../../../../../data/device_registry";
+import { computeDeviceName } from "../../../../../data/device_registry";
import {
+ ZWaveJSNodeConfigParam,
+ ZWaveJSNodeConfigParams,
+ ZWaveJSSetConfigParamResult,
+ ZwaveJSNodeMetadata,
fetchZwaveNodeConfigParameters,
fetchZwaveNodeMetadata,
setZwaveNodeConfigParameter,
- ZWaveJSNodeConfigParam,
- ZWaveJSNodeConfigParams,
- ZwaveJSNodeMetadata,
- ZWaveJSSetConfigParamResult,
} from "../../../../../data/zwave_js";
import "../../../../../layouts/hass-error-screen";
import "../../../../../layouts/hass-loading-screen";
import "../../../../../layouts/hass-tabs-subpage";
-import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types";
import "../../../ha-config-section";
@@ -57,16 +50,8 @@ const icons = {
error: mdiCloseCircle,
};
-const getDevice = memoizeOne(
- (
- deviceId: string,
- entries?: DeviceRegistryEntry[]
- ): DeviceRegistryEntry | undefined =>
- entries?.find((device) => device.id === deviceId)
-);
-
@customElement("zwave_js-node-config")
-class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
+class ZWaveJSNodeConfig extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public route!: Route;
@@ -79,8 +64,6 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
@property() public deviceId!: string;
- @state() private _deviceRegistryEntries?: DeviceRegistryEntry[];
-
@state() private _nodeMetadata?: ZwaveJSNodeMetadata;
@state() private _config?: ZWaveJSNodeConfigParams;
@@ -94,19 +77,8 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
this.deviceId = this.route.path.substr(1);
}
- public hassSubscribe(): UnsubscribeFunc[] {
- return [
- subscribeDeviceRegistry(this.hass.connection, (entries) => {
- this._deviceRegistryEntries = entries;
- }),
- ];
- }
-
protected updated(changedProps: PropertyValues): void {
- if (
- (!this._config || changedProps.has("deviceId")) &&
- changedProps.has("_deviceRegistryEntries")
- ) {
+ if (!this._config || changedProps.has("deviceId")) {
this._fetchData();
}
}
@@ -125,7 +97,7 @@ class ZWaveJSNodeConfig extends SubscribeMixin(LitElement) {
return html``;
}
- const device = this._device!;
+ const device = this.hass.devices[this.deviceId];
return html`