-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Separate entity, device and area name in more info dialog header #21951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
573124a
44c3ffc
f5a591c
0ddd6ec
19f4cfb
5f4b0c4
cbc7cb6
4887ac2
5b762c6
e046e4a
1b4b1c4
7ba7a74
980ade9
790bcde
e1e76e0
b9ec948
98c089b
1fbd673
af5280c
b8f69b2
4989443
55c9fe2
5ce969f
f943d09
e1f3169
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import type { AreaRegistryEntry } from "../../data/area_registry"; | ||
|
||
export const computeAreaName = (area: AreaRegistryEntry): string | undefined => | ||
area.name?.trim(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this should use |
||
if (stateObj) { | ||
return computeStateName(stateObj); | ||
} | ||
} | ||
return undefined; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't it weird that if we request the entity name we get undefined if the name is the same as the device? I feel like the default behavior of |
||
} | ||
|
||
// Remove the device name from the entity name if it starts with it | ||
if (deviceName && name) { | ||
return stripPrefixFromEntityName(name, deviceName) || name; | ||
} | ||
|
||
return name; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import type { FloorRegistryEntry } from "../../data/floor_registry"; | ||
|
||
export const computeFloorName = (floor: FloorRegistryEntry): string => | ||
floor.name?.trim(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
}; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ export interface EntityRegistryDisplayEntry { | |
translation_key?: string; | ||
platform?: string; | ||
display_precision?: number; | ||
has_entity_name?: boolean; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't seem used now right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was used in entity picker but I removed it from this PR. I will be useful if we want to compute something similar to friendly_name in the front-end directly. |
||
} | ||
|
||
export interface EntityRegistryDisplayEntryResponse { | ||
|
@@ -39,6 +40,7 @@ export interface EntityRegistryDisplayEntryResponse { | |
tk?: string; | ||
hb?: boolean; | ||
dp?: number; | ||
hn?: boolean; | ||
}[]; | ||
entity_categories: Record<number, EntityCategory>; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already have a
computeDeviceName
function https://github.com/home-assistant/frontend/blob/dev/src/data/device_registry.ts#L68There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, in my opinion this function does too much with the entities fallback and translation fallback.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
entities is optional, we could make the translation fallback optional too. We can also wrap the functions (have a
computeDeviceNameWithFallback()
), but we can not have 2 functions with the same name in the code base, that will go wrong with importing and is highly confusing.