1
0
mirror of https://github.com/home-assistant/frontend.git synced 2025-12-20 02:38:53 +00:00

Use entity picker for heading card entities editor (#28463)

* Use entity picker for heading card entities editor

* Use space tokens

* Pass index

* Lint

* Set undefined

* Iterate

* Spread

* Fixes

* Fixes
This commit is contained in:
Aidan Timson
2025-12-12 07:30:07 +00:00
committed by GitHub
parent 5d4c3ebfcd
commit de142e33a1
2 changed files with 70 additions and 29 deletions

View File

@@ -5,14 +5,17 @@ import { customElement, property } from "lit/decorators";
import { repeat } from "lit/directives/repeat"; import { repeat } from "lit/directives/repeat";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { preventDefault } from "../../../../common/dom/prevent_default"; import { preventDefault } from "../../../../common/dom/prevent_default";
import { computeStateName } from "../../../../common/entity/compute_state_name";
import "../../../../components/entity/ha-entity-picker"; import "../../../../components/entity/ha-entity-picker";
import type { HaEntityPicker } from "../../../../components/entity/ha-entity-picker";
import "../../../../components/ha-button"; import "../../../../components/ha-button";
import "../../../../components/ha-icon-button"; import "../../../../components/ha-icon-button";
import "../../../../components/ha-sortable"; import "../../../../components/ha-sortable";
import "../../../../components/ha-svg-icon"; import "../../../../components/ha-svg-icon";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import type { LovelaceHeadingBadgeConfig } from "../../heading-badges/types"; import type {
EntityHeadingBadgeConfig,
LovelaceHeadingBadgeConfig,
} from "../../heading-badges/types";
declare global { declare global {
interface HASSDomEvents { interface HASSDomEvents {
@@ -38,20 +41,8 @@ export class HuiHeadingBadgesEditor extends LitElement {
return this._badgesKeys.get(badge)!; return this._badgesKeys.get(badge)!;
} }
private _computeBadgeLabel(badge: LovelaceHeadingBadgeConfig) { private _createValueChangedHandler(index: number) {
const type = badge.type ?? "entity"; return (ev: CustomEvent) => this._valueChanged(ev, index);
if (type === "entity") {
const entityId = "entity" in badge ? (badge.entity as string) : undefined;
const stateObj = entityId ? this.hass.states[entityId] : undefined;
return (
(stateObj && computeStateName(stateObj)) ||
entityId ||
type ||
"Unknown badge"
);
}
return type;
} }
protected render() { protected render() {
@@ -71,7 +62,12 @@ export class HuiHeadingBadgesEditor extends LitElement {
this.badges, this.badges,
(badge) => this._getKey(badge), (badge) => this._getKey(badge),
(badge, index) => { (badge, index) => {
const label = this._computeBadgeLabel(badge); const type = badge.type ?? "entity";
const isEntityBadge =
type === "entity" && "entity" in badge;
const entityBadge = isEntityBadge
? (badge as EntityHeadingBadgeConfig)
: undefined;
return html` return html`
<div class="badge"> <div class="badge">
<div class="handle"> <div class="handle">
@@ -79,9 +75,23 @@ export class HuiHeadingBadgesEditor extends LitElement {
.path=${mdiDragHorizontalVariant} .path=${mdiDragHorizontalVariant}
></ha-svg-icon> ></ha-svg-icon>
</div> </div>
${isEntityBadge && entityBadge
? html`
<ha-entity-picker
allow-custom-entity
hide-clear-icon
.hass=${this.hass}
.value=${entityBadge.entity ?? ""}
@value-changed=${this._createValueChangedHandler(
index
)}
></ha-entity-picker>
`
: html`
<div class="badge-content"> <div class="badge-content">
<span>${label}</span> <span>${type}</span>
</div> </div>
`}
<ha-icon-button <ha-icon-button
.label=${this.hass!.localize( .label=${this.hass!.localize(
`ui.panel.lovelace.editor.entities.edit` `ui.panel.lovelace.editor.entities.edit`
@@ -128,7 +138,7 @@ export class HuiHeadingBadgesEditor extends LitElement {
`; `;
} }
private _entityPicked(ev) { private _entityPicked(ev: CustomEvent): void {
ev.stopPropagation(); ev.stopPropagation();
if (!ev.detail.value) { if (!ev.detail.value) {
return; return;
@@ -137,15 +147,32 @@ export class HuiHeadingBadgesEditor extends LitElement {
type: "entity", type: "entity",
entity: ev.detail.value, entity: ev.detail.value,
}; };
const newBadges = (this.badges || []).concat(newEntity); const newBadges = [...(this.badges || []), newEntity];
(ev.target as HaEntityPicker).value = undefined;
fireEvent(this, "heading-badges-changed", { badges: newBadges });
}
private _valueChanged(ev: CustomEvent, index: number): void {
ev.stopPropagation();
const value = ev.detail.value;
const newBadges = [...(this.badges || [])];
if (!value) {
newBadges.splice(index, 1);
} else {
newBadges[index] = {
...newBadges[index],
entity: value,
};
}
fireEvent(this, "heading-badges-changed", { badges: newBadges }); fireEvent(this, "heading-badges-changed", { badges: newBadges });
} }
private _badgeMoved(ev: CustomEvent): void { private _badgeMoved(ev: CustomEvent): void {
ev.stopPropagation(); ev.stopPropagation();
const { oldIndex, newIndex } = ev.detail; const { oldIndex, newIndex } = ev.detail;
const newBadges = [...(this.badges || [])];
const newBadges = (this.badges || []).concat();
newBadges.splice(newIndex, 0, newBadges.splice(oldIndex, 1)[0]); newBadges.splice(newIndex, 0, newBadges.splice(oldIndex, 1)[0]);
@@ -154,7 +181,7 @@ export class HuiHeadingBadgesEditor extends LitElement {
private _removeEntity(ev: CustomEvent): void { private _removeEntity(ev: CustomEvent): void {
const index = (ev.currentTarget as any).index; const index = (ev.currentTarget as any).index;
const newBadges = (this.badges || []).concat(); const newBadges = [...(this.badges || [])];
newBadges.splice(index, 1); newBadges.splice(index, 1);
@@ -174,8 +201,15 @@ export class HuiHeadingBadgesEditor extends LitElement {
flex-direction: column; flex-direction: column;
} }
ha-button { ha-button {
margin-top: 8px; margin-top: var(--ha-space-2);
} }
.entities {
display: flex;
flex-direction: column;
gap: var(--ha-space-2);
}
.badge { .badge {
display: flex; display: flex;
align-items: center; align-items: center;
@@ -183,8 +217,8 @@ export class HuiHeadingBadgesEditor extends LitElement {
.badge .handle { .badge .handle {
cursor: move; /* fallback if grab cursor is unsupported */ cursor: move; /* fallback if grab cursor is unsupported */
cursor: grab; cursor: grab;
padding-right: 8px; padding-right: var(--ha-space-2);
padding-inline-end: 8px; padding-inline-end: var(--ha-space-2);
padding-inline-start: initial; padding-inline-start: initial;
direction: var(--direction); direction: var(--direction);
} }
@@ -206,6 +240,12 @@ export class HuiHeadingBadgesEditor extends LitElement {
flex-direction: column; flex-direction: column;
} }
.badge ha-entity-picker {
flex-grow: 1;
min-width: 0;
margin-top: 0;
}
.remove-icon, .remove-icon,
.edit-icon { .edit-icon {
--mdc-icon-button-size: 36px; --mdc-icon-button-size: 36px;
@@ -224,6 +264,7 @@ export class HuiHeadingBadgesEditor extends LitElement {
.add-container { .add-container {
position: relative; position: relative;
width: 100%; width: 100%;
margin-top: var(--ha-space-2);
} }
mwc-menu-surface { mwc-menu-surface {

View File

@@ -228,7 +228,7 @@ export class HuiHeadingCardEditor
} }
ha-form { ha-form {
display: block; display: block;
margin-bottom: 24px; margin-bottom: var(--ha-space-6);
} }
`, `,
]; ];