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>
This commit is contained in:
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 path = require("path");
const rspack = require("@rspack/core");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { StatsWriterPlugin } = require("webpack-stats-plugin");
const filterStats = require("@bundle-stats/plugin-webpack-filter");
// eslint-disable-next-line @typescript-eslint/naming-convention
const TerserPlugin = require("terser-webpack-plugin");
// eslint-disable-next-line @typescript-eslint/naming-convention
const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
const log = require("fancy-log");
// eslint-disable-next-line @typescript-eslint/naming-convention
const WebpackBar = require("webpackbar/rspack");
const paths = require("./paths.cjs");
const bundle = require("./bundle.cjs");
@ -190,6 +195,7 @@ const createRspackConfig = ({
"lit/directives/if-defined$": "lit/directives/if-defined.js",
"lit/directives/guard$": "lit/directives/guard.js",
"lit/directives/cache$": "lit/directives/cache.js",
"lit/directives/join$": "lit/directives/join.js",
"lit/directives/repeat$": "lit/directives/repeat.js",
"lit/directives/live$": "lit/directives/live.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.
* @param entityName the entity name
* @param lowerCasedPrefix the prefix to strip, lower cased
* @param prefix the prefix to strip
* @returns
*/
export const stripPrefixFromEntityName = (
entityName: string,
lowerCasedPrefix: string
prefix: string
) => {
const lowerCasedEntityName = entityName.toLowerCase();
const lowerCasedPrefix = prefix.toLowerCase();
for (const suffix of SUFFIXES) {
const lowerCasedPrefixWithSuffix = `${lowerCasedPrefix}${suffix}`;

View File

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

View File

@ -5,8 +5,8 @@ import { css, html, LitElement, nothing } from "lit";
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 { stringCompare } from "../common/string/compare";
import { computeDeviceName } from "../data/device_registry";
import type { RelatedResult } from "../data/search";
import { findRelated } from "../data/search";
import { haStyleScrollbar } from "../resources/styles";
@ -95,7 +95,7 @@ export class HaFilterDevices extends LitElement {
.value=${device.id}
.selected=${this.value?.includes(device.id) ?? false}
>
${computeDeviceName(device, this.hass)}
${computeDeviceNameDisplay(device, this.hass)}
</ha-check-list-item>`;
private _handleItemClick(ev) {
@ -142,12 +142,14 @@ export class HaFilterDevices extends LitElement {
.filter(
(device) =>
!filter ||
computeDeviceName(device, this.hass).toLowerCase().includes(filter)
computeDeviceNameDisplay(device, this.hass)
.toLowerCase()
.includes(filter)
)
.sort((a, b) =>
stringCompare(
computeDeviceName(a, this.hass),
computeDeviceName(b, this.hass),
computeDeviceNameDisplay(a, this.hass),
computeDeviceNameDisplay(b, this.hass),
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 { fireEvent } from "../common/dom/fire_event";
import { stopPropagation } from "../common/dom/stop_propagation";
import { computeDeviceNameDisplay } from "../common/entity/compute_device_name";
import { computeDomain } from "../common/entity/compute_domain";
import { computeStateName } from "../common/entity/compute_state_name";
import { isValidEntityId } from "../common/entity/valid_entity_id";
import type { AreaRegistryEntry } from "../data/area_registry";
import type { DeviceRegistryEntry } from "../data/device_registry";
import { computeDeviceName } from "../data/device_registry";
import type { EntityRegistryDisplayEntry } from "../data/entity_registry";
import type { LabelRegistryEntry } from "../data/label_registry";
import { subscribeLabelRegistry } from "../data/label_registry";
@ -150,7 +150,9 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
return this._renderChip(
"device_id",
device_id,
device ? computeDeviceName(device, this.hass) : device_id,
device
? computeDeviceNameDisplay(device, this.hass)
: device_id,
undefined,
undefined,
mdiDevices

View File

@ -65,20 +65,6 @@ export const fallbackDeviceName = (
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) =>
devices.filter((device) => device.area_id === areaId);

View File

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

View File

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

View File

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

View File

@ -14,11 +14,15 @@ import type { PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { cache } from "lit/directives/cache";
import { join } from "lit/directives/join";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event";
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 { 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 { navigate } from "../../common/navigate";
import "../../components/ha-button-menu";
@ -34,7 +38,9 @@ import type {
} from "../../data/entity_registry";
import { getExtendedEntityRegistryEntry } from "../../data/entity_registry";
import { lightSupportsFavoriteColors } from "../../data/light";
import type { ItemType } from "../../data/search";
import { SearchableDomains } from "../../data/search";
import { getSensorNumericDeviceClasses } from "../../data/sensor";
import { haStyleDialog } from "../../resources/styles";
import "../../state-summary/state-card-content";
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-settings";
import "./more-info-content";
import { getSensorNumericDeviceClasses } from "../../data/sensor";
export interface MoreInfoDialogParams {
entityId: string | null;
@ -278,19 +283,31 @@ export class MoreInfoDialog extends LitElement {
const stateObj = this.hass.states[entityId] as HassEntity | undefined;
const domain = computeDomain(entityId);
const name = (stateObj && computeStateName(stateObj)) || entityId;
const isAdmin = this.hass.user!.is_admin;
const deviceId = this._getDeviceId();
const title = this._childView?.viewTitle ?? name;
const isDefaultView = this._currView === DEFAULT_VIEW && !this._childView;
const isSpecificInitialView =
this._initialView !== DEFAULT_VIEW && !this._childView;
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`
<ha-dialog
open
@ -320,8 +337,20 @@ export class MoreInfoDialog extends LitElement {
)}
></ha-icon-button-prev>
`}
<span slot="title" .title=${title} @click=${this._enlarge}>
${title}
<span
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>
${isDefaultView
? html`
@ -512,7 +541,7 @@ export class MoreInfoDialog extends LitElement {
.hass=${this.hass}
.itemId=${entityId}
.itemType=${SearchableDomains.has(domain)
? domain
? (domain as ItemType)
: "entity"}
></ha-related-items>
`
@ -610,6 +639,36 @@ export class MoreInfoDialog extends LitElement {
--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 { isComponentLoaded } from "../../common/config/is_component_loaded";
import { fireEvent } from "../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../common/entity/compute_device_name";
import { computeStateName } from "../../common/entity/compute_state_name";
import { navigate } from "../../common/navigate";
import { caseInsensitiveStringCompare } from "../../common/string/compare";
import type { ScorableTextItem } from "../../common/string/filter/sequence-matching";
import { fuzzyFilterSort } from "../../common/string/filter/sequence-matching";
import { debounce } from "../../common/util/debounce";
import "../../components/ha-spinner";
import "../../components/ha-icon-button";
import "../../components/ha-label";
import "../../components/ha-list-item";
import "../../components/ha-spinner";
import "../../components/ha-textfield";
import { fetchHassioAddonsInfo } from "../../data/hassio/addon";
import { domainToName } from "../../data/integration";
@ -40,7 +41,6 @@ import { loadVirtualizer } from "../../resources/virtualizer";
import type { HomeAssistant } from "../../types";
import { showConfirmationDialog } from "../generic/show-dialog-box";
import { QuickBarMode, type QuickBarParams } from "./show-dialog-quick-bar";
import { computeDeviceName } from "../../data/device_registry";
interface QuickBarItem extends ScorableTextItem {
primaryText: string;
@ -529,9 +529,7 @@ export class QuickBar extends LitElement {
? this.hass.areas[device.area_id]
: undefined;
const deviceItem = {
primaryText:
computeDeviceName(device, this.hass) ||
this.hass.localize("ui.components.device-picker.unnamed_device"),
primaryText: computeDeviceNameDisplay(device, this.hass),
deviceId: device.id,
area: area?.name,
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 "@material/mwc-button";
import "@material/mwc-list";
import "@material/mwc-list/mwc-list-item";
import { mdiDelete, mdiDotsVertical, mdiImagePlus, mdiPencil } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket/dist/types";
import type { CSSResultGroup } from "lit";
@ -10,16 +10,17 @@ import { customElement, property, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { caseInsensitiveStringCompare } from "../../../common/string/compare";
import { groupBy } from "../../../common/util/group-by";
import { afterNextRender } from "../../../common/util/render-status";
import "../../../components/ha-button-menu";
import "../../../components/ha-card";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-next";
import "../../../components/ha-list-item";
import "../../../components/ha-button-menu";
import "../../../components/ha-tooltip";
import type { AreaRegistryEntry } from "../../../data/area_registry";
import {
@ -29,10 +30,7 @@ import {
import type { AutomationEntity } from "../../../data/automation";
import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import {
computeDeviceName,
sortDeviceRegistryByName,
} from "../../../data/device_registry";
import { sortDeviceRegistryByName } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry";
import {
computeEntityRegistryName,
@ -166,7 +164,7 @@ class HaConfigAreaPage extends LitElement {
// Pre-compute the entity and device names, so we can sort by them
if (devices) {
devices.forEach((entry) => {
entry.name = computeDeviceName(entry, this.hass);
entry.name = computeDeviceNameDisplay(entry, this.hass);
});
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 memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import "../../../components/entity/state-badge";
import "../../../components/ha-alert";
import "../../../components/ha-spinner";
import "../../../components/ha-icon-next";
import "../../../components/ha-list-item";
import "../../../components/ha-spinner";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import {
computeDeviceName,
subscribeDeviceRegistry,
} from "../../../data/device_registry";
import { subscribeDeviceRegistry } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { subscribeEntityRegistry } from "../../../data/entity_registry";
import type { UpdateEntity } from "../../../data/update";
@ -114,7 +112,7 @@ class HaConfigUpdates extends SubscribeMixin(LitElement) {
: ""}
<span
>${deviceEntry
? computeDeviceName(deviceEntry, this.hass)
? computeDeviceNameDisplay(deviceEntry, this.hass)
: entity.attributes.friendly_name}</span
>
<span slot="secondary">

View File

@ -4,7 +4,7 @@ import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
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 "../../../../components/ha-card";
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 type { HomeAssistant } from "../../../../types";
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 {
computeCards,
computeSection,
} 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")
export class HaDeviceEntitiesCard extends LitElement {
@ -171,18 +171,7 @@ export class HaDeviceEntitiesCard extends LitElement {
element.hass = this.hass;
const stateObj = this.hass.states[entry.entity_id];
let name = entry.name
? 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);
}
let name = computeEntityName(stateObj, this.hass) || this.deviceName;
if (entry.hidden_by) {
name += ` (${this.hass.localize(
@ -216,8 +205,7 @@ export class HaDeviceEntitiesCard extends LitElement {
<ha-icon slot="graphic" .icon=${icon}></ha-icon>
<div class="name">
${name
? stripPrefixFromEntityName(name, this.deviceName.toLowerCase()) ||
name
? stripPrefixFromEntityName(name, this.deviceName) || name
: entry.entity_id}
</div>
</ha-list-item>

View File

@ -1,10 +1,10 @@
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import { titleCase } from "../../../../common/string/title-case";
import "../../../../components/ha-card";
import type { DeviceRegistryEntry } from "../../../../data/device_registry";
import { computeDeviceName } from "../../../../data/device_registry";
import { haStyle } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
@ -56,7 +56,9 @@ export class HaDeviceCard extends LitElement {
<span class="hub"
><a
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
>
</div>
@ -118,10 +120,10 @@ export class HaDeviceCard extends LitElement {
);
}
private _computeDeviceName(deviceId) {
private _computeDeviceNameDislay(deviceId) {
const device = this.hass.devices[deviceId];
return device
? computeDeviceName(device, this.hass)
? computeDeviceNameDisplay(device, this.hass)
: `<${this.hass.localize(
"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 { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { computeDeviceNameDisplay } from "../../../../common/entity/compute_device_name";
import { caseInsensitiveStringCompare } from "../../../../common/string/compare";
import "../../../../components/ha-card";
import "../../../../components/ha-icon-next";
import type { DeviceRegistryEntry } from "../../../../data/device_registry";
import { computeDeviceName } from "../../../../data/device_registry";
import type { HomeAssistant } from "../../../../types";
const MAX_VISIBLE_VIA_DEVICES = 10;
@ -28,8 +28,8 @@ export class HaDeviceViaDevicesCard extends LitElement {
.filter((device) => device.via_device_id === deviceId)
.sort((d1, d2) =>
caseInsensitiveStringCompare(
computeDeviceName(d1, this.hass),
computeDeviceName(d2, this.hass),
computeDeviceNameDisplay(d1, this.hass),
computeDeviceNameDisplay(d2, this.hass),
this.hass.locale.language
)
)
@ -56,7 +56,7 @@ export class HaDeviceViaDevicesCard extends LitElement {
(viaDevice) => html`
<a href=${`/config/devices/device/${viaDevice.id}`}>
<mwc-list-item hasMeta>
${computeDeviceName(viaDevice, this.hass)}
${computeDeviceNameDisplay(viaDevice, this.hass)}
<ha-icon-next slot="meta"></ha-icon-next>
</mwc-list-item>
</a>

View File

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

View File

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

View File

@ -16,7 +16,9 @@ import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { ASSIST_ENTITIES, SENSOR_ENTITIES } from "../../../common/const";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeEntityEntryName } from "../../../common/entity/compute_entity_name";
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
import { computeStateName } from "../../../common/entity/compute_state_name";
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/ha-alert";
import "../../../components/ha-button-menu";
import "../../../components/ha-expansion-panel";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-next";
import "../../../components/ha-svg-icon";
import "../../../components/ha-expansion-panel";
import "../../../components/ha-tooltip";
import { assistSatelliteSupportsSetupFlow } from "../../../data/assist_satellite";
import { getSignedPath } from "../../../data/auth";
import type {
ConfigEntry,
@ -42,7 +45,6 @@ import {
import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import {
computeDeviceName,
removeConfigEntryFromDevice,
updateDeviceRegistryEntry,
} from "../../../data/device_registry";
@ -68,6 +70,7 @@ import {
showAlertDialog,
showConfirmationDialog,
} 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-subpage";
import { haStyle } from "../../../resources/styles";
@ -83,8 +86,6 @@ import {
loadDeviceRegistryDetailDialog,
showDeviceRegistryDetailDialog,
} 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 {
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(
device,
this.entries,
@ -1155,11 +1156,11 @@ export class HaConfigDevicePage extends LitElement {
}
private _computeEntityName(entity: EntityRegistryEntry) {
if (entity.name) {
return entity.name;
}
const entityState = this.hass.states[entity.entity_id];
return entityState ? computeStateName(entityState) : null;
const device = this.hass.devices[this.deviceId];
return (
computeEntityEntryName(entity, this.hass) ||
computeDeviceNameDisplay(device, this.hass)
);
}
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 { storage } from "../../../common/decorators/storage";
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 {
PROTOCOL_INTEGRATIONS,
@ -40,7 +41,6 @@ import "../../../components/entity/ha-battery-icon";
import "../../../components/ha-alert";
import "../../../components/ha-button-menu";
import "../../../components/ha-check-list-item";
import "../../../components/ha-md-divider";
import "../../../components/ha-fab";
import "../../../components/ha-filter-devices";
import "../../../components/ha-filter-floor-areas";
@ -48,6 +48,7 @@ import "../../../components/ha-filter-integrations";
import "../../../components/ha-filter-labels";
import "../../../components/ha-filter-states";
import "../../../components/ha-icon-button";
import "../../../components/ha-md-divider";
import "../../../components/ha-md-menu-item";
import "../../../components/ha-sub-menu";
import { createAreaRegistryEntry } from "../../../data/area_registry";
@ -63,10 +64,7 @@ import type {
DeviceEntityLookup,
DeviceRegistryEntry,
} from "../../../data/device_registry";
import {
computeDeviceName,
updateDeviceRegistryEntry,
} from "../../../data/device_registry";
import { updateDeviceRegistryEntry } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry";
import {
findBatteryChargingEntity,
@ -426,7 +424,7 @@ export class HaConfigDeviceDashboard extends SubscribeMixin(LitElement) {
return {
...device,
name: computeDeviceName(
name: computeDeviceNameDisplay(
device,
this.hass,
deviceEntityLookup[device.id]

View File

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

View File

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

View File

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

View File

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

View File

@ -4,8 +4,8 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { dynamicElement } from "../../../../../common/dom/dynamic-element-directive";
import { computeDeviceNameDisplay } from "../../../../../common/entity/compute_device_name";
import "../../../../../components/ha-card";
import { computeDeviceName } from "../../../../../data/device_registry";
import type {
ZWaveJSNodeCapabilities,
ZwaveJSNodeMetadata,
@ -20,10 +20,10 @@ import "../../../../../layouts/hass-subpage";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types";
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-thermostat-setback";
import "./capability-controls/zwave_js-capability-control-door-lock";
import "./capability-controls/zwave_js-capability-control-color-switch";
const CAPABILITY_CONTROLS = {
38: "multilevel_switch",
@ -109,7 +109,7 @@ class ZWaveJSNodeInstaller extends LitElement {
${device
? html`
<div class="device-info">
<h2>${computeDeviceName(device, this.hass)}</h2>
<h2>${computeDeviceNameDisplay(device, this.hass)}</h2>
<p>${device.manufacturer} ${device.model}</p>
</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 "@material/mwc-list/mwc-list";
import type { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
import {
mdiCog,
mdiContentDuplicate,
@ -21,19 +21,18 @@ import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeDeviceNameDisplay } from "../../../common/entity/compute_device_name";
import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { navigate } from "../../../common/navigate";
import { computeRTL } from "../../../common/util/compute_rtl";
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/entity/ha-entities-picker";
import "../../../components/ha-area-picker";
import "../../../components/ha-button-menu";
import "../../../components/ha-alert";
import "../../../components/ha-area-picker";
import "../../../components/ha-button";
import "../../../components/ha-button-menu";
import "../../../components/ha-card";
import "../../../components/ha-fab";
import "../../../components/ha-icon-button";
@ -41,8 +40,8 @@ import "../../../components/ha-icon-picker";
import "../../../components/ha-list-item";
import "../../../components/ha-svg-icon";
import "../../../components/ha-textfield";
import { fullEntitiesContext } from "../../../data/context";
import type { DeviceRegistryEntry } from "../../../data/device_registry";
import { computeDeviceName } from "../../../data/device_registry";
import type { EntityRegistryEntry } from "../../../data/entity_registry";
import { updateEntityRegistryEntry } from "../../../data/entity_registry";
import type {
@ -65,14 +64,15 @@ import {
showAlertDialog,
showConfirmationDialog,
} from "../../../dialogs/generic/show-dialog-box";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import "../../../layouts/hass-subpage";
import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant, Route } from "../../../types";
import { showToast } from "../../../util/toast";
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
import "../ha-config-section";
import { PreventUnsavedMixin } from "../../../mixins/prevent-unsaved-mixin";
import { fullEntitiesContext } from "../../../data/context";
interface DeviceEntities {
id: string;
@ -175,7 +175,7 @@ export class HaSceneEditor extends PreventUnsavedMixin(
const device = deviceLookup[deviceId];
const deviceEntities: string[] = deviceEntityLookup[deviceId] || [];
outputDevices.push({
name: computeDeviceName(
name: computeDeviceNameDisplay(
device,
this.hass,
this._deviceEntityLookup[device.id]

View File

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

View File

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

View File

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