Separate entity, device and area name in more info dialog header (#21951)

* Separate entity, device and area name in more info dialog header

* Use has_entity_name

* Separate entity, device and area name in entity picker

* Fix entity name with has entity name

* Fix compute entity name

* Add full name

* Add floor

* Improve code quality

* Use compute entity name in device entities card

* Use context functions

* Remove floor

* Use state name provided by backend

* Use breadcrumb for more info

* Revert entity picker changes

* Use new logic in device page

* Use breadcrumb

* Use join directive

* Add comments

* Use secondary text color

* Update compute_entity_name.ts

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

* Remove html join

* Improve computeDeviceNameDisplay

* Fallback to original name

* Simplify more info logic

* Include breadcrumb for child view (voice assistant)

---------

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
pull/24599/head^2
Paul Bottein 2025-03-26 14:58:34 +01:00 committed by GitHub
parent f6467a35db
commit 53bb8251fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 377 additions and 163 deletions

View File

@ -1,12 +1,17 @@
const { existsSync } = require("fs"); const { existsSync } = require("fs");
const path = require("path"); const path = require("path");
const rspack = require("@rspack/core"); const rspack = require("@rspack/core");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin"); const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { StatsWriterPlugin } = require("webpack-stats-plugin"); const { StatsWriterPlugin } = require("webpack-stats-plugin");
const filterStats = require("@bundle-stats/plugin-webpack-filter"); const filterStats = require("@bundle-stats/plugin-webpack-filter");
// eslint-disable-next-line @typescript-eslint/naming-convention
const TerserPlugin = require("terser-webpack-plugin"); const TerserPlugin = require("terser-webpack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { WebpackManifestPlugin } = require("rspack-manifest-plugin"); const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
const log = require("fancy-log"); const log = require("fancy-log");
// eslint-disable-next-line @typescript-eslint/naming-convention
const WebpackBar = require("webpackbar/rspack"); const WebpackBar = require("webpackbar/rspack");
const paths = require("./paths.cjs"); const paths = require("./paths.cjs");
const bundle = require("./bundle.cjs"); const bundle = require("./bundle.cjs");
@ -190,6 +195,7 @@ const createRspackConfig = ({
"lit/directives/if-defined$": "lit/directives/if-defined.js", "lit/directives/if-defined$": "lit/directives/if-defined.js",
"lit/directives/guard$": "lit/directives/guard.js", "lit/directives/guard$": "lit/directives/guard.js",
"lit/directives/cache$": "lit/directives/cache.js", "lit/directives/cache$": "lit/directives/cache.js",
"lit/directives/join$": "lit/directives/join.js",
"lit/directives/repeat$": "lit/directives/repeat.js", "lit/directives/repeat$": "lit/directives/repeat.js",
"lit/directives/live$": "lit/directives/live.js", "lit/directives/live$": "lit/directives/live.js",
"lit/directives/keyed$": "lit/directives/keyed.js", "lit/directives/keyed$": "lit/directives/keyed.js",

View File

@ -0,0 +1,4 @@
import type { AreaRegistryEntry } from "../../data/area_registry";
export const computeAreaName = (area: AreaRegistryEntry): string | undefined =>
area.name?.trim();

View File

@ -0,0 +1,38 @@
import type { DeviceRegistryEntry } from "../../data/device_registry";
import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
} from "../../data/entity_registry";
import type { HomeAssistant } from "../../types";
import { computeStateName } from "./compute_state_name";
export const computeDeviceName = (
device: DeviceRegistryEntry
): string | undefined => (device.name_by_user || device.name)?.trim();
export const computeDeviceNameDisplay = (
device: DeviceRegistryEntry,
hass: HomeAssistant,
entities?: EntityRegistryEntry[] | EntityRegistryDisplayEntry[] | string[]
) =>
computeDeviceName(device) ||
(entities && fallbackDeviceName(hass, entities)) ||
hass.localize("ui.panel.config.devices.unnamed_device", {
type: hass.localize(
`ui.panel.config.devices.type.${device.entry_type || "device"}`
),
});
export const fallbackDeviceName = (
hass: HomeAssistant,
entities: EntityRegistryEntry[] | EntityRegistryDisplayEntry[] | string[]
) => {
for (const entity of entities || []) {
const entityId = typeof entity === "string" ? entity : entity.entity_id;
const stateObj = hass.states[entityId];
if (stateObj) {
return computeStateName(stateObj);
}
}
return undefined;
};

View File

@ -0,0 +1,52 @@
import type { HassEntity } from "home-assistant-js-websocket";
import type {
EntityRegistryDisplayEntry,
EntityRegistryEntry,
} from "../../data/entity_registry";
import type { HomeAssistant } from "../../types";
import { computeDeviceName } from "./compute_device_name";
import { computeStateName } from "./compute_state_name";
import { stripPrefixFromEntityName } from "./strip_prefix_from_entity_name";
export const computeEntityName = (
stateObj: HassEntity,
hass: HomeAssistant
): string | undefined => {
const entry = hass.entities[stateObj.entity_id] as
| EntityRegistryDisplayEntry
| undefined;
if (!entry) {
// Fall back to state name if not in the entity registry (friendly name)
return computeStateName(stateObj);
}
return computeEntityEntryName(entry, hass);
};
export const computeEntityEntryName = (
entry: EntityRegistryDisplayEntry | EntityRegistryEntry,
hass: HomeAssistant
): string | undefined => {
const name =
entry.name || ("original_name" in entry ? entry.original_name : undefined);
const device = entry.device_id ? hass.devices[entry.device_id] : undefined;
if (!device) {
return name;
}
const deviceName = computeDeviceName(device);
// If the device name is the same as the entity name, consider empty entity name
if (deviceName === name) {
return undefined;
}
// Remove the device name from the entity name if it starts with it
if (deviceName && name) {
return stripPrefixFromEntityName(name, deviceName) || name;
}
return name;
};

View File

@ -0,0 +1,4 @@
import type { FloorRegistryEntry } from "../../data/floor_registry";
export const computeFloorName = (floor: FloorRegistryEntry): string =>
floor.name?.trim();

View File

@ -0,0 +1,18 @@
import type { AreaRegistryEntry } from "../../data/area_registry";
import type { FloorRegistryEntry } from "../../data/floor_registry";
import type { HomeAssistant } from "../../types";
interface AreaContext {
floor: FloorRegistryEntry | null;
}
export const getAreaContext = (
area: AreaRegistryEntry,
hass: HomeAssistant
): AreaContext => {
const floorId = area.floor_id;
const floor = floorId ? hass.floors[floorId] : null;
return {
floor: floor,
};
};

View File

@ -0,0 +1,24 @@
import type { AreaRegistryEntry } from "../../data/area_registry";
import type { DeviceRegistryEntry } from "../../data/device_registry";
import type { FloorRegistryEntry } from "../../data/floor_registry";
import type { HomeAssistant } from "../../types";
interface DeviceContext {
area: AreaRegistryEntry | null;
floor: FloorRegistryEntry | null;
}
export const getDeviceContext = (
device: DeviceRegistryEntry,
hass: HomeAssistant
): DeviceContext => {
const areaId = device.area_id;
const area = areaId ? hass.areas[areaId] : null;
const floorId = area?.floor_id;
const floor = floorId ? hass.floors[floorId] : null;
return {
area: area,
floor: floor,
};
};

View File

@ -0,0 +1,34 @@
import type { HassEntity } from "home-assistant-js-websocket";
import type { AreaRegistryEntry } from "../../data/area_registry";
import type { DeviceRegistryEntry } from "../../data/device_registry";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import type { FloorRegistryEntry } from "../../data/floor_registry";
import type { HomeAssistant } from "../../types";
interface EntityContext {
device: DeviceRegistryEntry | null;
area: AreaRegistryEntry | null;
floor: FloorRegistryEntry | null;
}
export const getEntityContext = (
stateObj: HassEntity,
hass: HomeAssistant
): EntityContext => {
const entry = hass.entities[stateObj.entity_id] as
| EntityRegistryDisplayEntry
| undefined;
const deviceId = entry?.device_id;
const device = deviceId ? hass.devices[deviceId] : null;
const areaId = entry?.area_id || device?.area_id;
const area = areaId ? hass.areas[areaId] : null;
const floorId = area?.floor_id;
const floor = floorId ? hass.floors[floorId] : null;
return {
device: device,
area: area,
floor: floor,
};
};

View File

@ -1,17 +1,17 @@
const SUFFIXES = [" ", ": "]; const SUFFIXES = [" ", ": ", " - "];
/** /**
* Strips a device name from an entity name. * Strips a device name from an entity name.
* @param entityName the entity name * @param entityName the entity name
* @param lowerCasedPrefix the prefix to strip, lower cased * @param prefix the prefix to strip
* @returns * @returns
*/ */
export const stripPrefixFromEntityName = ( export const stripPrefixFromEntityName = (
entityName: string, entityName: string,
lowerCasedPrefix: string prefix: string
) => { ) => {
const lowerCasedEntityName = entityName.toLowerCase(); const lowerCasedEntityName = entityName.toLowerCase();
const lowerCasedPrefix = prefix.toLowerCase();
for (const suffix of SUFFIXES) { for (const suffix of SUFFIXES) {
const lowerCasedPrefixWithSuffix = `${lowerCasedPrefix}${suffix}`; const lowerCasedPrefixWithSuffix = `${lowerCasedPrefix}${suffix}`;

View File

@ -5,6 +5,7 @@ import { LitElement, html } from "lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
import { computeDomain } from "../../common/entity/compute_domain"; import { computeDomain } from "../../common/entity/compute_domain";
import { stringCompare } from "../../common/string/compare"; import { stringCompare } from "../../common/string/compare";
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching"; import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
@ -13,10 +14,7 @@ import type {
DeviceEntityDisplayLookup, DeviceEntityDisplayLookup,
DeviceRegistryEntry, DeviceRegistryEntry,
} from "../../data/device_registry"; } from "../../data/device_registry";
import { import { getDeviceEntityDisplayLookup } from "../../data/device_registry";
computeDeviceName,
getDeviceEntityDisplayLookup,
} from "../../data/device_registry";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry"; import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import type { HomeAssistant, ValueChangedEvent } from "../../types"; import type { HomeAssistant, ValueChangedEvent } from "../../types";
import "../ha-combo-box"; import "../ha-combo-box";
@ -214,7 +212,7 @@ export class HaDevicePicker extends LitElement {
} }
const outputDevices = inputDevices.map((device) => { const outputDevices = inputDevices.map((device) => {
const name = computeDeviceName( const name = computeDeviceNameDisplay(
device, device,
this.hass, this.hass,
deviceEntityLookup[device.id] deviceEntityLookup[device.id]

View File

@ -5,8 +5,8 @@ import { css, html, LitElement, nothing } 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 { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
import { stringCompare } from "../common/string/compare"; import { stringCompare } from "../common/string/compare";
import { computeDeviceName } from "../data/device_registry";
import type { RelatedResult } from "../data/search"; import type { RelatedResult } from "../data/search";
import { findRelated } from "../data/search"; import { findRelated } from "../data/search";
import { haStyleScrollbar } from "../resources/styles"; import { haStyleScrollbar } from "../resources/styles";
@ -95,7 +95,7 @@ export class HaFilterDevices extends LitElement {
.value=${device.id} .value=${device.id}
.selected=${this.value?.includes(device.id) ?? false} .selected=${this.value?.includes(device.id) ?? false}
> >
${computeDeviceName(device, this.hass)} ${computeDeviceNameDisplay(device, this.hass)}
</ha-check-list-item>`; </ha-check-list-item>`;
private _handleItemClick(ev) { private _handleItemClick(ev) {
@ -142,12 +142,14 @@ export class HaFilterDevices extends LitElement {
.filter( .filter(
(device) => (device) =>
!filter || !filter ||
computeDeviceName(device, this.hass).toLowerCase().includes(filter) computeDeviceNameDisplay(device, this.hass)
.toLowerCase()
.includes(filter)
) )
.sort((a, b) => .sort((a, b) =>
stringCompare( stringCompare(
computeDeviceName(a, this.hass), computeDeviceNameDisplay(a, this.hass),
computeDeviceName(b, this.hass), computeDeviceNameDisplay(b, this.hass),
this.hass.locale.language this.hass.locale.language
) )
); );

View File

@ -26,12 +26,12 @@ import { computeCssColor } from "../common/color/compute-color";
import { hex2rgb } from "../common/color/convert-color"; import { hex2rgb } from "../common/color/convert-color";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { stopPropagation } from "../common/dom/stop_propagation"; import { stopPropagation } from "../common/dom/stop_propagation";
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
import { computeDomain } from "../common/entity/compute_domain"; import { computeDomain } from "../common/entity/compute_domain";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import { isValidEntityId } from "../common/entity/valid_entity_id"; import { isValidEntityId } from "../common/entity/valid_entity_id";
import type { AreaRegistryEntry } from "../data/area_registry"; import type { AreaRegistryEntry } from "../data/area_registry";
import type { DeviceRegistryEntry } from "../data/device_registry"; import type { DeviceRegistryEntry } from "../data/device_registry";
import { computeDeviceName } from "../data/device_registry";
import type { EntityRegistryDisplayEntry } from "../data/entity_registry"; import type { EntityRegistryDisplayEntry } from "../data/entity_registry";
import type { LabelRegistryEntry } from "../data/label_registry"; import type { LabelRegistryEntry } from "../data/label_registry";
import { subscribeLabelRegistry } from "../data/label_registry"; import { subscribeLabelRegistry } from "../data/label_registry";
@ -150,7 +150,9 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
return this._renderChip( return this._renderChip(
"device_id", "device_id",
device_id, device_id,
device ? computeDeviceName(device, this.hass) : device_id, device
? computeDeviceNameDisplay(device, this.hass)
: device_id,
undefined, undefined,
undefined, undefined,
mdiDevices mdiDevices

View File

@ -65,20 +65,6 @@ export const fallbackDeviceName = (
return undefined; return undefined;
}; };
export const computeDeviceName = (
device: DeviceRegistryEntry,
hass: HomeAssistant,
entities?: EntityRegistryEntry[] | EntityRegistryDisplayEntry[] | string[]
) =>
device.name_by_user ||
device.name ||
(entities && fallbackDeviceName(hass, entities)) ||
hass.localize("ui.panel.config.devices.unnamed_device", {
type: hass.localize(
`ui.panel.config.devices.type.${device.entry_type || "device"}`
),
});
export const devicesInArea = (devices: DeviceRegistryEntry[], areaId: string) => export const devicesInArea = (devices: DeviceRegistryEntry[], areaId: string) =>
devices.filter((device) => device.area_id === areaId); devices.filter((device) => device.area_id === areaId);

View File

@ -24,6 +24,7 @@ export interface EntityRegistryDisplayEntry {
translation_key?: string; translation_key?: string;
platform?: string; platform?: string;
display_precision?: number; display_precision?: number;
has_entity_name?: boolean;
} }
export interface EntityRegistryDisplayEntryResponse { export interface EntityRegistryDisplayEntryResponse {
@ -39,6 +40,7 @@ export interface EntityRegistryDisplayEntryResponse {
tk?: string; tk?: string;
hb?: boolean; hb?: boolean;
dp?: number; dp?: number;
hn?: boolean;
}[]; }[];
entity_categories: Record<number, EntityCategory>; entity_categories: Record<number, EntityCategory>;
} }

View File

@ -1,6 +1,7 @@
import { ensureArray } from "../common/array/ensure-array"; import { ensureArray } from "../common/array/ensure-array";
import { formatNumericDuration } from "../common/datetime/format_duration"; import { formatNumericDuration } from "../common/datetime/format_duration";
import secondsToDuration from "../common/datetime/seconds_to_duration"; import secondsToDuration from "../common/datetime/seconds_to_duration";
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
import { formatListWithAnds } from "../common/string/format-list"; import { formatListWithAnds } from "../common/string/format-list";
import { isTemplate } from "../common/string/has-template"; import { isTemplate } from "../common/string/has-template";
@ -8,7 +9,6 @@ import type { HomeAssistant } from "../types";
import type { Condition } from "./automation"; import type { Condition } from "./automation";
import { describeCondition } from "./automation_i18n"; import { describeCondition } from "./automation_i18n";
import { localizeDeviceAutomationAction } from "./device_automation"; import { localizeDeviceAutomationAction } from "./device_automation";
import { computeDeviceName } from "./device_registry";
import type { EntityRegistryEntry } from "./entity_registry"; import type { EntityRegistryEntry } from "./entity_registry";
import { import {
computeEntityRegistryName, computeEntityRegistryName,
@ -147,7 +147,7 @@ const tryDescribeAction = <T extends ActionType>(
} else if (key === "device_id") { } else if (key === "device_id") {
const device = hass.devices[targetThing]; const device = hass.devices[targetThing];
if (device) { if (device) {
targets.push(computeDeviceName(device, hass)); targets.push(computeDeviceNameDisplay(device, hass));
} else { } else {
targets.push( targets.push(
hass.localize( hass.localize(

View File

@ -4,22 +4,20 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
import { computeDomain } from "../../common/entity/compute_domain"; import { computeDomain } from "../../common/entity/compute_domain";
import { navigate } from "../../common/navigate";
import "../../components/ha-area-picker"; import "../../components/ha-area-picker";
import { assistSatelliteSupportsSetupFlow } from "../../data/assist_satellite"; import { assistSatelliteSupportsSetupFlow } from "../../data/assist_satellite";
import type { DataEntryFlowStepCreateEntry } from "../../data/data_entry_flow"; import type { DataEntryFlowStepCreateEntry } from "../../data/data_entry_flow";
import type { DeviceRegistryEntry } from "../../data/device_registry"; import type { DeviceRegistryEntry } from "../../data/device_registry";
import { import { updateDeviceRegistryEntry } from "../../data/device_registry";
computeDeviceName,
updateDeviceRegistryEntry,
} from "../../data/device_registry";
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry"; import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import { showAlertDialog } from "../generic/show-dialog-box"; import { showAlertDialog } from "../generic/show-dialog-box";
import { showVoiceAssistantSetupDialog } from "../voice-assistant-setup/show-voice-assistant-setup-dialog"; import { showVoiceAssistantSetupDialog } from "../voice-assistant-setup/show-voice-assistant-setup-dialog";
import type { FlowConfig } from "./show-dialog-data-entry-flow"; import type { FlowConfig } from "./show-dialog-data-entry-flow";
import { configFlowContentStyles } from "./styles"; import { configFlowContentStyles } from "./styles";
import { navigate } from "../../common/navigate";
@customElement("step-flow-create-entry") @customElement("step-flow-create-entry")
class StepFlowCreateEntry extends LitElement { class StepFlowCreateEntry extends LitElement {
@ -124,7 +122,8 @@ class StepFlowCreateEntry extends LitElement {
(device) => html` (device) => html`
<div class="device"> <div class="device">
<div> <div>
<b>${computeDeviceName(device, this.hass)}</b><br /> <b>${computeDeviceNameDisplay(device, this.hass)}</b
><br />
${!device.model && !device.manufacturer ${!device.model && !device.manufacturer
? html`&nbsp;` ? html`&nbsp;`
: html`${device.model} : html`${device.model}

View File

@ -14,11 +14,15 @@ import type { PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit"; import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { cache } from "lit/directives/cache"; import { cache } from "lit/directives/cache";
import { join } from "lit/directives/join";
import { dynamicElement } from "../../common/dom/dynamic-element-directive"; import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { stopPropagation } from "../../common/dom/stop_propagation"; import { stopPropagation } from "../../common/dom/stop_propagation";
import { computeAreaName } from "../../common/entity/compute_area_name";
import { computeDeviceName } from "../../common/entity/compute_device_name";
import { computeDomain } from "../../common/entity/compute_domain"; import { computeDomain } from "../../common/entity/compute_domain";
import { computeStateName } from "../../common/entity/compute_state_name"; import { computeEntityName } from "../../common/entity/compute_entity_name";
import { getEntityContext } from "../../common/entity/get_entity_context";
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event"; import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
import { navigate } from "../../common/navigate"; import { navigate } from "../../common/navigate";
import "../../components/ha-button-menu"; import "../../components/ha-button-menu";
@ -34,7 +38,9 @@ import type {
} from "../../data/entity_registry"; } from "../../data/entity_registry";
import { getExtendedEntityRegistryEntry } from "../../data/entity_registry"; import { getExtendedEntityRegistryEntry } from "../../data/entity_registry";
import { lightSupportsFavoriteColors } from "../../data/light"; import { lightSupportsFavoriteColors } from "../../data/light";
import type { ItemType } from "../../data/search";
import { SearchableDomains } from "../../data/search"; import { SearchableDomains } from "../../data/search";
import { getSensorNumericDeviceClasses } from "../../data/sensor";
import { haStyleDialog } from "../../resources/styles"; import { haStyleDialog } from "../../resources/styles";
import "../../state-summary/state-card-content"; import "../../state-summary/state-card-content";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
@ -50,7 +56,6 @@ import "./ha-more-info-history-and-logbook";
import "./ha-more-info-info"; import "./ha-more-info-info";
import "./ha-more-info-settings"; import "./ha-more-info-settings";
import "./more-info-content"; import "./more-info-content";
import { getSensorNumericDeviceClasses } from "../../data/sensor";
export interface MoreInfoDialogParams { export interface MoreInfoDialogParams {
entityId: string | null; entityId: string | null;
@ -278,19 +283,31 @@ export class MoreInfoDialog extends LitElement {
const stateObj = this.hass.states[entityId] as HassEntity | undefined; const stateObj = this.hass.states[entityId] as HassEntity | undefined;
const domain = computeDomain(entityId); const domain = computeDomain(entityId);
const name = (stateObj && computeStateName(stateObj)) || entityId;
const isAdmin = this.hass.user!.is_admin; const isAdmin = this.hass.user!.is_admin;
const deviceId = this._getDeviceId(); const deviceId = this._getDeviceId();
const title = this._childView?.viewTitle ?? name;
const isDefaultView = this._currView === DEFAULT_VIEW && !this._childView; const isDefaultView = this._currView === DEFAULT_VIEW && !this._childView;
const isSpecificInitialView = const isSpecificInitialView =
this._initialView !== DEFAULT_VIEW && !this._childView; this._initialView !== DEFAULT_VIEW && !this._childView;
const showCloseIcon = isDefaultView || isSpecificInitialView; const showCloseIcon = isDefaultView || isSpecificInitialView;
const context = stateObj ? getEntityContext(stateObj, this.hass) : null;
const entityName = stateObj
? computeEntityName(stateObj, this.hass)
: undefined;
const deviceName = context?.device
? computeDeviceName(context.device)
: undefined;
const areaName = context?.area ? computeAreaName(context.area) : undefined;
const breadcrumb = [areaName, deviceName, entityName].filter(
(v): v is string => Boolean(v)
);
const title = this._childView?.viewTitle || breadcrumb.pop();
return html` return html`
<ha-dialog <ha-dialog
open open
@ -320,8 +337,20 @@ export class MoreInfoDialog extends LitElement {
)} )}
></ha-icon-button-prev> ></ha-icon-button-prev>
`} `}
<span slot="title" .title=${title} @click=${this._enlarge}> <span
${title} slot="title"
.title=${title}
@click=${this._enlarge}
class="title"
>
${breadcrumb.length > 0
? html`
<p class="breadcrumb">
${join(breadcrumb, html`<ha-icon-next></ha-icon-next>`)}
</p>
`
: nothing}
<p class="main">${title}</p>
</span> </span>
${isDefaultView ${isDefaultView
? html` ? html`
@ -512,7 +541,7 @@ export class MoreInfoDialog extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.itemId=${entityId} .itemId=${entityId}
.itemType=${SearchableDomains.has(domain) .itemType=${SearchableDomains.has(domain)
? domain ? (domain as ItemType)
: "entity"} : "entity"}
></ha-related-items> ></ha-related-items>
` `
@ -610,6 +639,36 @@ export class MoreInfoDialog extends LitElement {
--mdc-dialog-max-width: 90vw; --mdc-dialog-max-width: 90vw;
} }
} }
.title {
display: flex;
flex-direction: column;
}
.title p {
margin: 0;
min-width: 0;
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
}
.title .main {
color: var(--primary-text-color);
font-size: 20px;
line-height: 24px;
}
.title .breadcrumb {
color: var(--secondary-text-color);
font-size: 14px;
line-height: 16px;
margin-top: -6px;
}
.title .breadcrumb {
--mdc-icon-size: 16px;
}
`, `,
]; ];
} }

View File

@ -19,16 +19,17 @@ import { canShowPage } from "../../common/config/can_show_page";
import { componentsWithService } from "../../common/config/components_with_service"; import { componentsWithService } from "../../common/config/components_with_service";
import { isComponentLoaded } from "../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../common/config/is_component_loaded";
import { fireEvent } from "../../common/dom/fire_event"; import { fireEvent } from "../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
import { computeStateName } from "../../common/entity/compute_state_name"; import { computeStateName } from "../../common/entity/compute_state_name";
import { navigate } from "../../common/navigate"; import { navigate } from "../../common/navigate";
import { caseInsensitiveStringCompare } from "../../common/string/compare"; import { caseInsensitiveStringCompare } from "../../common/string/compare";
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching"; import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
import { fuzzyFilterSort } from "../../common/string/filter/sequence-matching"; import { fuzzyFilterSort } from "../../common/string/filter/sequence-matching";
import { debounce } from "../../common/util/debounce"; import { debounce } from "../../common/util/debounce";
import "../../components/ha-spinner";
import "../../components/ha-icon-button"; import "../../components/ha-icon-button";
import "../../components/ha-label"; import "../../components/ha-label";
import "../../components/ha-list-item"; import "../../components/ha-list-item";
import "../../components/ha-spinner";
import "../../components/ha-textfield"; import "../../components/ha-textfield";
import { fetchHassioAddonsInfo } from "../../data/hassio/addon"; import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
import { domainToName } from "../../data/integration"; import { domainToName } from "../../data/integration";
@ -40,7 +41,6 @@ import { loadVirtualizer } from "../../resources/virtualizer";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import { showConfirmationDialog } from "../generic/show-dialog-box"; import { showConfirmationDialog } from "../generic/show-dialog-box";
import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar"; import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar";
import { computeDeviceName } from "../../data/device_registry";
interface QuickBarItem extends ScorableTextItem { interface QuickBarItem extends ScorableTextItem {
primaryText: string; primaryText: string;
@ -529,9 +529,7 @@ export class QuickBar extends LitElement {
? this.hass.areas[device.area_id] ? this.hass.areas[device.area_id]
: undefined; : undefined;
const deviceItem = { const deviceItem = {
primaryText: primaryText: computeDeviceNameDisplay(device, this.hass),
computeDeviceName(device, this.hass) ||
this.hass.localize("ui.components.device-picker.unnamed_device"),
deviceId: device.id, deviceId: device.id,
area: area?.name, area: area?.name,
action: () => navigate(`/config/devices/device/${device.id}`), action: () => navigate(`/config/devices/device/${device.id}`),

View File

@ -1,7 +1,7 @@
import "@material/mwc-list/mwc-list-item";
import { consume } from "@lit-labs/context"; import { consume } from "@lit-labs/context";
import "@material/mwc-button"; import "@material/mwc-button";
import "@material/mwc-list"; import "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiDelete, mdiDotsVertical, mdiImagePlus, mdiPencil } from "@mdi/js"; import { mdiDelete, mdiDotsVertical, mdiImagePlus, mdiPencil } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket/dist/types"; import type { HassEntity } from "home-assistant-js-websocket/dist/types";
import type { CSSResultGroup } from "lit"; import type { CSSResultGroup } from "lit";
@ -10,16 +10,17 @@ import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { caseInsensitiveStringCompare } from "../../../common/string/compare"; import { caseInsensitiveStringCompare } from "../../../common/string/compare";
import { groupBy } from "../../../common/util/group-by"; import { groupBy } from "../../../common/util/group-by";
import { afterNextRender } from "../../../common/util/render-status"; import { afterNextRender } from "../../../common/util/render-status";
import "../../../components/ha-button-menu";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-icon-next"; import "../../../components/ha-icon-next";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
import "../../../components/ha-button-menu";
import "../../../components/ha-tooltip"; import "../../../components/ha-tooltip";
import type { AreaRegistryEntry } from "../../../data/area_registry"; import type { AreaRegistryEntry } from "../../../data/area_registry";
import { import {
@ -29,10 +30,7 @@ import {
import type { AutomationEntity } from "../../../data/automation"; import type { AutomationEntity } from "../../../data/automation";
import { fullEntitiesContext } from "../../../data/context"; import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../data/device_registry";
import { import { sortDeviceRegistryByName } from "../../../data/device_registry";
computeDeviceName,
sortDeviceRegistryByName,
} from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry"; import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { import {
computeEntityRegistryName, computeEntityRegistryName,
@ -166,7 +164,7 @@ class HaConfigAreaPage extends LitElement {
// Pre-compute the entity and device names, so we can sort by them // Pre-compute the entity and device names, so we can sort by them
if (devices) { if (devices) {
devices.forEach((entry) => { devices.forEach((entry) => {
entry.name = computeDeviceName(entry, this.hass); entry.name = computeDeviceNameDisplay(entry, this.hass);
}); });
sortDeviceRegistryByName(devices, this.hass.locale.language); sortDeviceRegistryByName(devices, this.hass.locale.language);
} }

View File

@ -7,16 +7,14 @@ import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import "../../../components/entity/state-badge"; import "../../../components/entity/state-badge";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-spinner";
import "../../../components/ha-icon-next"; import "../../../components/ha-icon-next";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
import "../../../components/ha-spinner";
import type { DeviceRegistryEntry } from "../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../data/device_registry";
import { import { subscribeDeviceRegistry } from "../../../data/device_registry";
computeDeviceName,
subscribeDeviceRegistry,
} from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry"; import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { subscribeEntityRegistry } from "../../../data/entity_registry"; import { subscribeEntityRegistry } from "../../../data/entity_registry";
import type { UpdateEntity } from "../../../data/update"; import type { UpdateEntity } from "../../../data/update";
@ -114,7 +112,7 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) {
: ""} : ""}
<span <span
>${deviceEntry >${deviceEntry
? computeDeviceName(deviceEntry, this.hass) ? computeDeviceNameDisplay(deviceEntry, this.hass)
: entity.attributes.friendly_name}</span : entity.attributes.friendly_name}</span
> >
<span slot="secondary"> <span slot="secondary">

View File

@ -4,7 +4,7 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { until } from "lit/directives/until"; import { until } from "lit/directives/until";
import { computeStateName } from "../../../../common/entity/compute_state_name"; import { computeEntityName } from "../../../../common/entity/compute_entity_name";
import { stripPrefixFromEntityName } from "../../../../common/entity/strip_prefix_from_entity_name"; import { stripPrefixFromEntityName } from "../../../../common/entity/strip_prefix_from_entity_name";
import "../../../../components/ha-card"; import "../../../../components/ha-card";
import "../../../../components/ha-icon"; import "../../../../components/ha-icon";
@ -15,17 +15,17 @@ import { entryIcon } from "../../../../data/icons";
import { showMoreInfoDialog } from "../../../../dialogs/more-info/show-ha-more-info-dialog"; import { showMoreInfoDialog } from "../../../../dialogs/more-info/show-ha-more-info-dialog";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { HuiErrorCard } from "../../../lovelace/cards/hui-error-card"; import type { HuiErrorCard } from "../../../lovelace/cards/hui-error-card";
import { createRowElement } from "../../../lovelace/create-element/create-row-element";
import { addEntitiesToLovelaceView } from "../../../lovelace/editor/add-entities-to-view";
import type {
LovelaceRowConfig,
LovelaceRow,
} from "../../../lovelace/entity-rows/types";
import type { EntityRegistryStateEntry } from "../ha-config-device-page";
import { import {
computeCards, computeCards,
computeSection, computeSection,
} from "../../../lovelace/common/generate-lovelace-config"; } from "../../../lovelace/common/generate-lovelace-config";
import { createRowElement } from "../../../lovelace/create-element/create-row-element";
import { addEntitiesToLovelaceView } from "../../../lovelace/editor/add-entities-to-view";
import type {
LovelaceRow,
LovelaceRowConfig,
} from "../../../lovelace/entity-rows/types";
import type { EntityRegistryStateEntry } from "../ha-config-device-page";
@customElement("ha-device-entities-card") @customElement("ha-device-entities-card")
export class HaDeviceEntitiesCard extends LitElement { export class HaDeviceEntitiesCard extends LitElement {
@ -171,18 +171,7 @@ export class HaDeviceEntitiesCard extends LitElement {
element.hass = this.hass; element.hass = this.hass;
const stateObj = this.hass.states[entry.entity_id]; const stateObj = this.hass.states[entry.entity_id];
let name = entry.name let name = computeEntityName(stateObj, this.hass) || this.deviceName;
? stripPrefixFromEntityName(entry.name, this.deviceName.toLowerCase())
: entry.has_entity_name
? entry.original_name || this.deviceName
: stripPrefixFromEntityName(
computeStateName(stateObj),
this.deviceName.toLowerCase()
);
if (!name) {
name = computeStateName(stateObj);
}
if (entry.hidden_by) { if (entry.hidden_by) {
name += ` (${this.hass.localize( name += ` (${this.hass.localize(
@ -216,8 +205,7 @@ export class HaDeviceEntitiesCard extends LitElement {
<ha-icon slot="graphic" .icon=${icon}></ha-icon> <ha-icon slot="graphic" .icon=${icon}></ha-icon>
<div class="name"> <div class="name">
${name ${name
? stripPrefixFromEntityName(name, this.deviceName.toLowerCase()) || ? stripPrefixFromEntityName(name, this.deviceName) || name
name
: entry.entity_id} : entry.entity_id}
</div> </div>
</ha-list-item> </ha-list-item>

View File

@ -1,10 +1,10 @@
import type { CSSResultGroup, TemplateResult } from "lit"; import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit"; import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import { titleCase } from "../../../../common/string/title-case"; import { titleCase } from "../../../../common/string/title-case";
import "../../../../components/ha-card"; import "../../../../components/ha-card";
import type { DeviceRegistryEntry } from "../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../data/device_registry";
import { computeDeviceName } from "../../../../data/device_registry";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
@ -56,7 +56,9 @@ export class HaDeviceCard extends LitElement {
<span class="hub" <span class="hub"
><a ><a
href="/config/devices/device/${this.device.via_device_id}" href="/config/devices/device/${this.device.via_device_id}"
>${this._computeDeviceName(this.device.via_device_id)}</a >${this._computeDeviceNameDislay(
this.device.via_device_id
)}</a
></span ></span
> >
</div> </div>
@ -118,10 +120,10 @@ export class HaDeviceCard extends LitElement {
); );
} }
private _computeDeviceName(deviceId) { private _computeDeviceNameDislay(deviceId) {
const device = this.hass.devices[deviceId]; const device = this.hass.devices[deviceId];
return device return device
? computeDeviceName(device, this.hass) ? computeDeviceNameDisplay(device, this.hass)
: `<${this.hass.localize( : `<${this.hass.localize(
"ui.panel.config.integrations.config_entry.unknown_via_device" "ui.panel.config.integrations.config_entry.unknown_via_device"
)}>`; )}>`;

View File

@ -2,11 +2,11 @@ import "@material/mwc-list/mwc-list-item";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } 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 { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import { caseInsensitiveStringCompare } from "../../../../common/string/compare"; import { caseInsensitiveStringCompare } from "../../../../common/string/compare";
import "../../../../components/ha-card"; import "../../../../components/ha-card";
import "../../../../components/ha-icon-next"; import "../../../../components/ha-icon-next";
import type { DeviceRegistryEntry } from "../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../data/device_registry";
import { computeDeviceName } from "../../../../data/device_registry";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
const MAX_VISIBLE_VIA_DEVICES = 10; const MAX_VISIBLE_VIA_DEVICES = 10;
@ -28,8 +28,8 @@ export class HaDeviceViaDevicesCard extends LitElement {
.filter((device) => device.via_device_id === deviceId) .filter((device) => device.via_device_id === deviceId)
.sort((d1, d2) => .sort((d1, d2) =>
caseInsensitiveStringCompare( caseInsensitiveStringCompare(
computeDeviceName(d1, this.hass), computeDeviceNameDisplay(d1, this.hass),
computeDeviceName(d2, this.hass), computeDeviceNameDisplay(d2, this.hass),
this.hass.locale.language this.hass.locale.language
) )
) )
@ -56,7 +56,7 @@ export class HaDeviceViaDevicesCard extends LitElement {
(viaDevice) => html` (viaDevice) => html`
<a href=${`/config/devices/device/${viaDevice.id}`}> <a href=${`/config/devices/device/${viaDevice.id}`}>
<mwc-list-item hasMeta> <mwc-list-item hasMeta>
${computeDeviceName(viaDevice, this.hass)} ${computeDeviceNameDisplay(viaDevice, this.hass)}
<ha-icon-next slot="meta"></ha-icon-next> <ha-icon-next slot="meta"></ha-icon-next>
</mwc-list-item> </mwc-list-item>
</a> </a>

View File

@ -2,12 +2,12 @@ import "@material/mwc-button/mwc-button";
import type { CSSResultGroup, TemplateResult } from "lit"; import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, state } from "lit/decorators"; import { customElement, state } from "lit/decorators";
import { computeDeviceNameDisplay } from "../../../../../../common/entity/compute_device_name";
import { computeStateName } from "../../../../../../common/entity/compute_state_name"; import { computeStateName } from "../../../../../../common/entity/compute_state_name";
import "../../../../../../components/ha-dialog"; import "../../../../../../components/ha-dialog";
import "../../../../../../components/ha-formfield"; import "../../../../../../components/ha-formfield";
import "../../../../../../components/ha-switch"; import "../../../../../../components/ha-switch";
import type { HaSwitch } from "../../../../../../components/ha-switch"; import type { HaSwitch } from "../../../../../../components/ha-switch";
import { computeDeviceName } from "../../../../../../data/device_registry";
import type { MQTTDeviceDebugInfo } from "../../../../../../data/mqtt"; import type { MQTTDeviceDebugInfo } from "../../../../../../data/mqtt";
import { fetchMQTTDebugInfo } from "../../../../../../data/mqtt"; import { fetchMQTTDebugInfo } from "../../../../../../data/mqtt";
import { haStyleDialog } from "../../../../../../resources/styles"; import { haStyleDialog } from "../../../../../../resources/styles";
@ -48,7 +48,7 @@ class DialogMQTTDeviceDebugInfo extends LitElement {
@closed=${this._close} @closed=${this._close}
.heading=${this.hass!.localize( .heading=${this.hass!.localize(
"ui.dialogs.mqtt_device_debug_info.title", "ui.dialogs.mqtt_device_debug_info.title",
{ device: computeDeviceName(this._params.device, this.hass) } { device: computeDeviceNameDisplay(this._params.device, this.hass) }
)} )}
> >
<h4> <h4>

View File

@ -3,6 +3,7 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import "../../../../components/ha-alert"; import "../../../../components/ha-alert";
import "../../../../components/ha-area-picker"; import "../../../../components/ha-area-picker";
import "../../../../components/ha-dialog"; import "../../../../components/ha-dialog";
@ -10,7 +11,6 @@ import "../../../../components/ha-labels-picker";
import type { HaSwitch } from "../../../../components/ha-switch"; import type { HaSwitch } from "../../../../components/ha-switch";
import "../../../../components/ha-textfield"; import "../../../../components/ha-textfield";
import type { DeviceRegistryEntry } from "../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../data/device_registry";
import { computeDeviceName } from "../../../../data/device_registry";
import { haStyle, haStyleDialog } from "../../../../resources/styles"; import { haStyle, haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { DeviceRegistryDetailDialogParams } from "./show-dialog-device-registry-detail"; import type { DeviceRegistryDetailDialogParams } from "./show-dialog-device-registry-detail";
@ -60,7 +60,7 @@ class DialogDeviceRegistryDetail extends LitElement {
<ha-dialog <ha-dialog
open open
@closed=${this.closeDialog} @closed=${this.closeDialog}
.heading=${computeDeviceName(device, this.hass)} .heading=${computeDeviceNameDisplay(device, this.hass)}
> >
<div> <div>
${this._error ${this._error

View File

@ -16,7 +16,9 @@ import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded"; import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { ASSIST_ENTITIES, SENSOR_ENTITIES } from "../../../common/const"; import { ASSIST_ENTITIES, SENSOR_ENTITIES } from "../../../common/const";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeEntityEntryName } from "../../../common/entity/compute_entity_name";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { stringCompare } from "../../../common/string/compare"; import { stringCompare } from "../../../common/string/compare";
@ -25,11 +27,12 @@ import { groupBy } from "../../../common/util/group-by";
import "../../../components/entity/ha-battery-icon"; import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-button-menu"; import "../../../components/ha-button-menu";
import "../../../components/ha-expansion-panel";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-icon-next"; import "../../../components/ha-icon-next";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-expansion-panel";
import "../../../components/ha-tooltip"; import "../../../components/ha-tooltip";
import { assistSatelliteSupportsSetupFlow } from "../../../data/assist_satellite";
import { getSignedPath } from "../../../data/auth"; import { getSignedPath } from "../../../data/auth";
import type { import type {
ConfigEntry, ConfigEntry,
@ -42,7 +45,6 @@ import {
import { fullEntitiesContext } from "../../../data/context"; import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../data/device_registry";
import { import {
computeDeviceName,
removeConfigEntryFromDevice, removeConfigEntryFromDevice,
updateDeviceRegistryEntry, updateDeviceRegistryEntry,
} from "../../../data/device_registry"; } from "../../../data/device_registry";
@ -68,6 +70,7 @@ import {
showAlertDialog, showAlertDialog,
showConfirmationDialog, showConfirmationDialog,
} from "../../../dialogs/generic/show-dialog-box"; } from "../../../dialogs/generic/show-dialog-box";
import { showVoiceAssistantSetupDialog } from "../../../dialogs/voice-assistant-setup/show-voice-assistant-setup-dialog";
import "../../../layouts/hass-error-screen"; import "../../../layouts/hass-error-screen";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
@ -83,8 +86,6 @@ import {
loadDeviceRegistryDetailDialog, loadDeviceRegistryDetailDialog,
showDeviceRegistryDetailDialog, showDeviceRegistryDetailDialog,
} from "./device-registry-detail/show-dialog-device-registry-detail"; } from "./device-registry-detail/show-dialog-device-registry-detail";
import { showVoiceAssistantSetupDialog } from "../../../dialogs/voice-assistant-setup/show-voice-assistant-setup-dialog";
import { assistSatelliteSupportsSetupFlow } from "../../../data/assist_satellite";
export interface EntityRegistryStateEntry extends EntityRegistryEntry { export interface EntityRegistryStateEntry extends EntityRegistryEntry {
stateName?: string | null; stateName?: string | null;
@ -310,7 +311,7 @@ export class HaConfigDevicePage extends LitElement {
`; `;
} }
const deviceName = computeDeviceName(device, this.hass); const deviceName = computeDeviceNameDisplay(device, this.hass);
const integrations = this._integrations( const integrations = this._integrations(
device, device,
this.entries, this.entries,
@ -1155,11 +1156,11 @@ export class HaConfigDevicePage extends LitElement {
} }
private _computeEntityName(entity: EntityRegistryEntry) { private _computeEntityName(entity: EntityRegistryEntry) {
if (entity.name) { const device = this.hass.devices[this.deviceId];
return entity.name; return (
} computeEntityEntryName(entity, this.hass) ||
const entityState = this.hass.states[entity.entity_id]; computeDeviceNameDisplay(device, this.hass)
return entityState ? computeStateName(entityState) : null; );
} }
private _onImageLoad(ev) { private _onImageLoad(ev) {

View File

@ -18,6 +18,7 @@ import { computeCssColor } from "../../../common/color/compute-color";
import { formatShortDateTime } from "../../../common/datetime/format_date_time"; import { formatShortDateTime } from "../../../common/datetime/format_date_time";
import { storage } from "../../../common/decorators/storage"; import { storage } from "../../../common/decorators/storage";
import type { HASSDomEvent } from "../../../common/dom/fire_event"; import type { HASSDomEvent } from "../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { import {
PROTOCOL_INTEGRATIONS, PROTOCOL_INTEGRATIONS,
@ -40,7 +41,6 @@ import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-button-menu"; import "../../../components/ha-button-menu";
import "../../../components/ha-check-list-item"; import "../../../components/ha-check-list-item";
import "../../../components/ha-md-divider";
import "../../../components/ha-fab"; import "../../../components/ha-fab";
import "../../../components/ha-filter-devices"; import "../../../components/ha-filter-devices";
import "../../../components/ha-filter-floor-areas"; import "../../../components/ha-filter-floor-areas";
@ -48,6 +48,7 @@ import "../../../components/ha-filter-integrations";
import "../../../components/ha-filter-labels"; import "../../../components/ha-filter-labels";
import "../../../components/ha-filter-states"; import "../../../components/ha-filter-states";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
import "../../../components/ha-md-divider";
import "../../../components/ha-md-menu-item"; import "../../../components/ha-md-menu-item";
import "../../../components/ha-sub-menu"; import "../../../components/ha-sub-menu";
import { createAreaRegistryEntry } from "../../../data/area_registry"; import { createAreaRegistryEntry } from "../../../data/area_registry";
@ -63,10 +64,7 @@ import type {
DeviceEntityLookup, DeviceEntityLookup,
DeviceRegistryEntry, DeviceRegistryEntry,
} from "../../../data/device_registry"; } from "../../../data/device_registry";
import { import { updateDeviceRegistryEntry } from "../../../data/device_registry";
computeDeviceName,
updateDeviceRegistryEntry,
} from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry"; import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { import {
findBatteryChargingEntity, findBatteryChargingEntity,
@ -426,7 +424,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
return { return {
...device, ...device,
name: computeDeviceName( name: computeDeviceNameDisplay(
device, device,
this.hass, this.hass,
deviceEntityLookup[device.id] deviceEntityLookup[device.id]

View File

@ -6,15 +6,13 @@ import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event"; import { fireEvent } from "../../../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import { createCloseHeading } from "../../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../../components/ha-dialog";
import "../../../../../components/ha-expansion-panel"; import "../../../../../components/ha-expansion-panel";
import "../../../../../components/ha-help-tooltip"; import "../../../../../components/ha-help-tooltip";
import "../../../../../components/ha-svg-icon"; import "../../../../../components/ha-svg-icon";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import { import { subscribeDeviceRegistry } from "../../../../../data/device_registry";
computeDeviceName,
subscribeDeviceRegistry,
} from "../../../../../data/device_registry";
import type { import type {
ZWaveJSNodeStatisticsUpdatedMessage, ZWaveJSNodeStatisticsUpdatedMessage,
ZWaveJSRouteStatistics, ZWaveJSRouteStatistics,
@ -419,7 +417,10 @@ class DialogZWaveJSNodeStatistics extends LitElement {
(devices: DeviceRegistryEntry[]) => { (devices: DeviceRegistryEntry[]) => {
const devicesIdToName = {}; const devicesIdToName = {};
devices.forEach((device) => { devices.forEach((device) => {
devicesIdToName[device.id] = computeDeviceName(device, this.hass); devicesIdToName[device.id] = computeDeviceNameDisplay(
device,
this.hass
);
}); });
this._deviceIDsToName = devicesIdToName; this._deviceIDsToName = devicesIdToName;
} }

View File

@ -4,10 +4,10 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event"; import { fireEvent } from "../../../../../common/dom/fire_event";
import "../../../../../components/ha-spinner"; import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import { createCloseHeading } from "../../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../../components/ha-dialog";
import "../../../../../components/ha-spinner";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import { computeDeviceName } from "../../../../../data/device_registry";
import type { ZWaveJSNetwork } from "../../../../../data/zwave_js"; import type { ZWaveJSNetwork } from "../../../../../data/zwave_js";
import { import {
fetchZwaveNetworkStatus, fetchZwaveNetworkStatus,
@ -68,9 +68,9 @@ class DialogZWaveJSRebuildNodeRoutes extends LitElement {
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.zwave_js.rebuild_node_routes.introduction", "ui.panel.config.zwave_js.rebuild_node_routes.introduction",
{ {
device: html`<em device: html`<em>
>${computeDeviceName(this.device, this.hass!)}</em ${computeDeviceNameDisplay(this.device, this.hass!)}
>`, </em>`,
} }
)} )}
</p> </p>
@ -102,9 +102,9 @@ class DialogZWaveJSRebuildNodeRoutes extends LitElement {
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.zwave_js.rebuild_node_routes.in_progress", "ui.panel.config.zwave_js.rebuild_node_routes.in_progress",
{ {
device: html`<em device: html`<em>
>${computeDeviceName(this.device, this.hass!)}</em ${computeDeviceNameDisplay(this.device, this.hass!)}
>`, </em>`,
} }
)} )}
</p> </p>
@ -128,7 +128,10 @@ class DialogZWaveJSRebuildNodeRoutes extends LitElement {
"ui.panel.config.zwave_js.rebuild_node_routes.rebuilding_routes_failed", "ui.panel.config.zwave_js.rebuild_node_routes.rebuilding_routes_failed",
{ {
device: html`<em device: html`<em
>${computeDeviceName(this.device, this.hass!)}</em >${computeDeviceNameDisplay(
this.device,
this.hass!
)}</em
>`, >`,
} }
)} )}
@ -161,9 +164,9 @@ class DialogZWaveJSRebuildNodeRoutes extends LitElement {
${this.hass.localize( ${this.hass.localize(
"ui.panel.config.zwave_js.rebuild_node_routes.rebuilding_routes_complete", "ui.panel.config.zwave_js.rebuild_node_routes.rebuilding_routes_complete",
{ {
device: html`<em device: html`<em>
>${computeDeviceName(this.device, this.hass!)}</em ${computeDeviceNameDisplay(this.device, this.hass!)}
>`, </em>`,
} }
)} )}
</p> </p>

View File

@ -6,13 +6,13 @@ import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit"; import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../../../common/dom/fire_event"; import { fireEvent } from "../../../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import { createCloseHeading } from "../../../../../components/ha-dialog"; import { createCloseHeading } from "../../../../../components/ha-dialog";
import "../../../../../components/ha-file-upload"; import "../../../../../components/ha-file-upload";
import "../../../../../components/ha-form/ha-form"; import "../../../../../components/ha-form/ha-form";
import type { HaFormSchema } from "../../../../../components/ha-form/types"; import type { HaFormSchema } from "../../../../../components/ha-form/types";
import "../../../../../components/ha-svg-icon"; import "../../../../../components/ha-svg-icon";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import { computeDeviceName } from "../../../../../data/device_registry";
import type { import type {
ZWaveJSControllerFirmwareUpdateFinishedMessage, ZWaveJSControllerFirmwareUpdateFinishedMessage,
ZWaveJSFirmwareUpdateProgressMessage, ZWaveJSFirmwareUpdateProgressMessage,
@ -78,7 +78,7 @@ class DialogZWaveJSUpdateFirmwareNode extends LitElement {
private _deviceName?: string; private _deviceName?: string;
public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void { public showDialog(params: ZWaveJSUpdateFirmwareNodeDialogParams): void {
this._deviceName = computeDeviceName(params.device, this.hass!); this._deviceName = computeDeviceNameDisplay(params.device, this.hass!);
this.device = params.device; this.device = params.device;
this._fetchData(); this._fetchData();
this._subscribeNodeStatus(); this._subscribeNodeStatus();

View File

@ -10,17 +10,18 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit"; import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import { groupBy } from "../../../../../common/util/group-by"; import { groupBy } from "../../../../../common/util/group-by";
import "../../../../../components/buttons/ha-progress-button";
import type { HaProgressButton } from "../../../../../components/buttons/ha-progress-button";
import "../../../../../components/ha-alert"; import "../../../../../components/ha-alert";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import "../../../../../components/ha-select"; import "../../../../../components/ha-select";
import "../../../../../components/ha-selector/ha-selector-boolean";
import "../../../../../components/ha-settings-row"; import "../../../../../components/ha-settings-row";
import "../../../../../components/ha-svg-icon"; import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-textfield"; import "../../../../../components/ha-textfield";
import "../../../../../components/ha-selector/ha-selector-boolean";
import "../../../../../components/buttons/ha-progress-button";
import type { HaProgressButton } from "../../../../../components/buttons/ha-progress-button";
import { computeDeviceName } from "../../../../../data/device_registry";
import type { import type {
ZWaveJSNodeCapabilities, ZWaveJSNodeCapabilities,
ZWaveJSNodeConfigParam, ZWaveJSNodeConfigParam,
@ -35,6 +36,7 @@ import {
invokeZWaveCCApi, invokeZWaveCCApi,
setZwaveNodeConfigParameter, setZwaveNodeConfigParameter,
} from "../../../../../data/zwave_js"; } from "../../../../../data/zwave_js";
import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box";
import "../../../../../layouts/hass-error-screen"; import "../../../../../layouts/hass-error-screen";
import "../../../../../layouts/hass-loading-screen"; import "../../../../../layouts/hass-loading-screen";
import "../../../../../layouts/hass-tabs-subpage"; import "../../../../../layouts/hass-tabs-subpage";
@ -43,8 +45,6 @@ import type { HomeAssistant, Route } from "../../../../../types";
import "../../../ha-config-section"; import "../../../ha-config-section";
import { configTabs } from "./zwave_js-config-router"; import { configTabs } from "./zwave_js-config-router";
import "./zwave_js-custom-param"; import "./zwave_js-custom-param";
import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box";
import { fireEvent } from "../../../../../common/dom/fire_event";
const icons = { const icons = {
accepted: mdiCheckCircle, accepted: mdiCheckCircle,
@ -105,7 +105,9 @@ class ZWaveJSNodeConfig extends LitElement {
const device = this.hass.devices[this.deviceId]; const device = this.hass.devices[this.deviceId];
const deviceName = device ? computeDeviceName(device, this.hass) : ""; const deviceName = device
? computeDeviceNameDisplay(device, this.hass)
: "";
return html` return html`
<hass-tabs-subpage <hass-tabs-subpage

View File

@ -4,8 +4,8 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit"; import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive"; import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import "../../../../../components/ha-card"; import "../../../../../components/ha-card";
import { computeDeviceName } from "../../../../../data/device_registry";
import type { import type {
ZWaveJSNodeCapabilities, ZWaveJSNodeCapabilities,
ZwaveJSNodeMetadata, ZwaveJSNodeMetadata,
@ -20,10 +20,10 @@ import "../../../../../layouts/hass-subpage";
import { haStyle } from "../../../../../resources/styles"; import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types"; import type { HomeAssistant, Route } from "../../../../../types";
import "../../../ha-config-section"; import "../../../ha-config-section";
import "./capability-controls/zwave_js-capability-control-color-switch";
import "./capability-controls/zwave_js-capability-control-door-lock";
import "./capability-controls/zwave_js-capability-control-multilevel-switch"; import "./capability-controls/zwave_js-capability-control-multilevel-switch";
import "./capability-controls/zwave_js-capability-control-thermostat-setback"; import "./capability-controls/zwave_js-capability-control-thermostat-setback";
import "./capability-controls/zwave_js-capability-control-door-lock";
import "./capability-controls/zwave_js-capability-control-color-switch";
const CAPABILITY_CONTROLS = { const CAPABILITY_CONTROLS = {
38: "multilevel_switch", 38: "multilevel_switch",
@ -109,7 +109,7 @@ class ZWaveJSNodeInstaller extends LitElement {
${device ${device
? html` ? html`
<div class="device-info"> <div class="device-info">
<h2>${computeDeviceName(device, this.hass)}</h2> <h2>${computeDeviceNameDisplay(device, this.hass)}</h2>
<p>${device.manufacturer} ${device.model}</p> <p>${device.manufacturer} ${device.model}</p>
</div> </div>
` `

View File

@ -1,6 +1,6 @@
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import "@material/mwc-list/mwc-list";
import { consume } from "@lit-labs/context"; import { consume } from "@lit-labs/context";
import "@material/mwc-list/mwc-list";
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import { import {
mdiCog, mdiCog,
mdiContentDuplicate, mdiContentDuplicate,
@ -21,19 +21,18 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event"; import { fireEvent } from "../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name"; import { computeStateName } from "../../../common/entity/compute_state_name";
import { navigate } from "../../../common/navigate"; import { navigate } from "../../../common/navigate";
import { computeRTL } from "../../../common/util/compute_rtl"; import { computeRTL } from "../../../common/util/compute_rtl";
import { afterNextRender } from "../../../common/util/render-status"; import { afterNextRender } from "../../../common/util/render-status";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import "../../../components/device/ha-device-picker"; import "../../../components/device/ha-device-picker";
import "../../../components/entity/ha-entities-picker"; import "../../../components/entity/ha-entities-picker";
import "../../../components/ha-area-picker";
import "../../../components/ha-button-menu";
import "../../../components/ha-alert"; import "../../../components/ha-alert";
import "../../../components/ha-area-picker";
import "../../../components/ha-button"; import "../../../components/ha-button";
import "../../../components/ha-button-menu";
import "../../../components/ha-card"; import "../../../components/ha-card";
import "../../../components/ha-fab"; import "../../../components/ha-fab";
import "../../../components/ha-icon-button"; import "../../../components/ha-icon-button";
@ -41,8 +40,8 @@ import "../../../components/ha-icon-picker";
import "../../../components/ha-list-item"; import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon"; import "../../../components/ha-svg-icon";
import "../../../components/ha-textfield"; import "../../../components/ha-textfield";
import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry"; import type { DeviceRegistryEntry } from "../../../data/device_registry";
import { computeDeviceName } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry"; import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { updateEntityRegistryEntry } from "../../../data/entity_registry"; import { updateEntityRegistryEntry } from "../../../data/entity_registry";
import type { import type {
@ -65,14 +64,15 @@ import {
showAlertDialog, showAlertDialog,
showConfirmationDialog, showConfirmationDialog,
} from "../../../dialogs/generic/show-dialog-box"; } from "../../../dialogs/generic/show-dialog-box";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import "../../../layouts/hass-subpage"; import "../../../layouts/hass-subpage";
import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin"; import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { haStyle } from "../../../resources/styles"; import { haStyle } from "../../../resources/styles";
import type { HomeAssistant, Route } from "../../../types"; import type { HomeAssistant, Route } from "../../../types";
import { showToast } from "../../../util/toast"; import { showToast } from "../../../util/toast";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import "../ha-config-section"; import "../ha-config-section";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { fullEntitiesContext } from "../../../data/context";
interface DeviceEntities { interface DeviceEntities {
id: string; id: string;
@ -175,7 +175,7 @@ export class HaSceneEditor extends PreventUnsavedMixin(
const device = deviceLookup[deviceId]; const device = deviceLookup[deviceId];
const deviceEntities: string[] = deviceEntityLookup[deviceId] || []; const deviceEntities: string[] = deviceEntityLookup[deviceId] || [];
outputDevices.push({ outputDevices.push({
name: computeDeviceName( name: computeDeviceNameDisplay(
device, device,
this.hass, this.hass,
this._deviceEntityLookup[device.id] this._deviceEntityLookup[device.id]

View File

@ -2,6 +2,7 @@ import type { PropertyValues } from "lit";
import { LitElement, html } from "lit"; import { LitElement, html } 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 { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import { navigate } from "../../../../common/navigate"; import { navigate } from "../../../../common/navigate";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/data-table/ha-data-table"; import "../../../../components/data-table/ha-data-table";
@ -14,7 +15,6 @@ import {
listAssistDevices, listAssistDevices,
listAssistPipelines, listAssistPipelines,
} from "../../../../data/assist_pipeline"; } from "../../../../data/assist_pipeline";
import { computeDeviceName } from "../../../../data/device_registry";
import "../../../../layouts/hass-subpage"; import "../../../../layouts/hass-subpage";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
@ -87,7 +87,7 @@ class AssistDevicesPage extends LitElement {
return { return {
...assistDevice, ...assistDevice,
name: device ? computeDeviceName(device, this.hass) : "", name: device ? computeDeviceNameDisplay(device, this.hass) : "",
pipeline: isPreferred pipeline: isPreferred
? localize("ui.components.pipeline-picker.preferred", { ? localize("ui.components.pipeline-picker.preferred", {
preferred: pipelineName, preferred: pipelineName,

View File

@ -1,7 +1,8 @@
import type { HassEntity } from "home-assistant-js-websocket"; import type { HassEntity } from "home-assistant-js-websocket";
import type { TemplateResult } from "lit"; import type { TemplateResult } from "lit";
import { html, LitElement, nothing } from "lit"; import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { join } from "lit/directives/join";
import { ensureArray } from "../common/array/ensure-array"; import { ensureArray } from "../common/array/ensure-array";
import { computeStateDomain } from "../common/entity/compute_state_domain"; import { computeStateDomain } from "../common/entity/compute_state_domain";
import { computeStateName } from "../common/entity/compute_state_name"; import { computeStateName } from "../common/entity/compute_state_name";
@ -182,12 +183,7 @@ class StateDisplay extends LitElement {
return html`${this.hass!.formatEntityState(stateObj)}`; return html`${this.hass!.formatEntityState(stateObj)}`;
} }
return html` return join(values, " ⸱ ");
${values.map(
(value, index, array) =>
html`${value}${index < array.length - 1 ? " ⸱ " : nothing}`
)}
`;
} }
} }

View File

@ -247,6 +247,7 @@ export const connectionMixin = <T extends Constructor<HassBaseEl>>(
entity.ec !== undefined entity.ec !== undefined
? entityReg.entity_categories[entity.ec] ? entityReg.entity_categories[entity.ec]
: undefined, : undefined,
has_entity_name: entity.hn,
name: entity.en, name: entity.en,
icon: entity.ic, icon: entity.ic,
hidden: entity.hb, hidden: entity.hb,