diff --git a/src/data/lovelace/config/badge.ts b/src/data/lovelace/config/badge.ts index e3f92b1ac4..ee586b5abf 100644 --- a/src/data/lovelace/config/badge.ts +++ b/src/data/lovelace/config/badge.ts @@ -13,7 +13,7 @@ export const ensureBadgeConfig = ( return { type: "entity", entity: config, - display_type: "complete", + show_name: true, }; } if ("type" in config && config.type) { diff --git a/src/panels/lovelace/badges/hui-entity-badge.ts b/src/panels/lovelace/badges/hui-entity-badge.ts index 390f64704e..af5b05e3e9 100644 --- a/src/panels/lovelace/badges/hui-entity-badge.ts +++ b/src/panels/lovelace/badges/hui-entity-badge.ts @@ -1,3 +1,4 @@ +import { mdiAlertCircle } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; @@ -5,15 +6,16 @@ import { classMap } from "lit/directives/class-map"; import { ifDefined } from "lit/directives/if-defined"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; -import { mdiAlertCircle } from "@mdi/js"; import { computeCssColor } from "../../../common/color/compute-color"; import { hsv2rgb, rgb2hex, rgb2hsv } from "../../../common/color/convert-color"; import { computeDomain } from "../../../common/entity/compute_domain"; +import { computeStateDomain } from "../../../common/entity/compute_state_domain"; import { stateActive } from "../../../common/entity/state_active"; import { stateColorCss } from "../../../common/entity/state_color"; import "../../../components/ha-ripple"; import "../../../components/ha-state-icon"; import "../../../components/ha-svg-icon"; +import { cameraUrlWithWidthHeight } from "../../../data/camera"; import { ActionHandlerEvent } from "../../../data/lovelace/action_handler"; import { HomeAssistant } from "../../../types"; import { actionHandler } from "../common/directives/action-handler-directive"; @@ -22,15 +24,38 @@ import { handleAction } from "../common/handle-action"; import { hasAction } from "../common/has-action"; import { LovelaceBadge, LovelaceBadgeEditor } from "../types"; import { EntityBadgeConfig } from "./types"; -import { computeStateDomain } from "../../../common/entity/compute_state_domain"; -import { cameraUrlWithWidthHeight } from "../../../data/camera"; export const DISPLAY_TYPES = ["minimal", "standard", "complete"] as const; - export type DisplayType = (typeof DISPLAY_TYPES)[number]; - export const DEFAULT_DISPLAY_TYPE: DisplayType = "standard"; +export const DEFAULT_CONFIG: EntityBadgeConfig = { + type: "entity", + show_name: false, + show_state: true, + show_icon: true, +}; + +export const migrateLegacyEntityBadgeConfig = ( + config: EntityBadgeConfig +): EntityBadgeConfig => { + const newConfig = { ...config }; + if (config.display_type) { + if (config.show_name === undefined) { + if (config.display_type === "complete") { + newConfig.show_name = true; + } + } + if (config.show_state === undefined) { + if (config.display_type === "minimal") { + newConfig.show_state = false; + } + } + delete newConfig.display_type; + } + return newConfig; +}; + @customElement("hui-entity-badge") export class HuiEntityBadge extends LitElement implements LovelaceBadge { public static async getConfigElement(): Promise { @@ -64,7 +89,10 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { @state() protected _config?: EntityBadgeConfig; public setConfig(config: EntityBadgeConfig): void { - this._config = config; + this._config = { + ...DEFAULT_CONFIG, + ...migrateLegacyEntityBadgeConfig(config), + }; } get hasAction() { @@ -134,9 +162,9 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { return html`
- - ${entityId} - + + ${entityId} + ${this.hass.localize("ui.badge.entity.not_found")} @@ -163,18 +191,25 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { const name = this._config.name || stateObj.attributes.friendly_name; - const displayType = this._config.display_type || DEFAULT_DISPLAY_TYPE; + const showState = this._config.show_state; + const showName = this._config.show_name; + const showIcon = this._config.show_icon; + const showEntityPicture = this._config.show_entity_picture; - const imageUrl = this._config.show_entity_picture + const imageUrl = showEntityPicture ? this._getImageUrl(stateObj) : undefined; + const label = showState && showName ? name : undefined; + const content = showState ? stateDisplay : showName ? name : undefined; + return html`
- ${imageUrl - ? html`` - : html` - - `} - ${displayType !== "minimal" + ${showIcon + ? imageUrl + ? html`` + : html` + + ` + : nothing} + ${content ? html` - - ${displayType === "complete" - ? html`${name}` - : nothing} - ${stateDisplay} + + ${label ? html`${name}` : nothing} + ${content} ` : nothing} @@ -277,7 +312,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { .badge.active { --badge-color: var(--primary-color); } - .content { + .info { display: flex; flex-direction: column; align-items: flex-start; @@ -285,7 +320,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { padding-inline-end: 4px; padding-inline-start: initial; } - .name { + .label { font-size: 10px; font-style: normal; font-weight: 500; @@ -293,7 +328,7 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { letter-spacing: 0.1px; color: var(--secondary-text-color); } - .state { + .content { font-size: 12px; font-style: normal; font-weight: 500; @@ -313,14 +348,20 @@ export class HuiEntityBadge extends LitElement implements LovelaceBadge { object-fit: cover; overflow: hidden; } - .badge.minimal { + .badge.no-info { padding: 0; } - .badge:not(.minimal) img { + .badge:not(.no-icon) img { margin-left: -6px; margin-inline-start: -6px; margin-inline-end: initial; } + .badge.no-icon .info { + padding-right: 4px; + padding-left: 4px; + padding-inline-end: 4px; + padding-inline-start: 4px; + } `; } } diff --git a/src/panels/lovelace/badges/hui-state-label-badge.ts b/src/panels/lovelace/badges/hui-state-label-badge.ts index c3c273cc62..989d46cf9c 100644 --- a/src/panels/lovelace/badges/hui-state-label-badge.ts +++ b/src/panels/lovelace/badges/hui-state-label-badge.ts @@ -16,10 +16,10 @@ export class HuiStateLabelBadge extends HuiEntityBadge { const entityBadgeConfig: EntityBadgeConfig = { type: "entity", entity: config.entity, - display_type: config.show_name === false ? "standard" : "complete", + show_name: config.show_name ?? true, }; - this._config = entityBadgeConfig; + super.setConfig(entityBadgeConfig); } } diff --git a/src/panels/lovelace/badges/types.ts b/src/panels/lovelace/badges/types.ts index 682308d39a..6a5b479943 100644 --- a/src/panels/lovelace/badges/types.ts +++ b/src/panels/lovelace/badges/types.ts @@ -3,6 +3,7 @@ import type { LovelaceBadgeConfig } from "../../../data/lovelace/config/badge"; import type { LegacyStateFilter } from "../common/evaluate-filter"; import type { Condition } from "../common/validate-condition"; import type { EntityFilterEntityConfig } from "../entity-rows/types"; +import type { DisplayType } from "./hui-entity-badge"; export interface EntityFilterBadgeConfig extends LovelaceBadgeConfig { type: "entity-filter"; @@ -33,10 +34,16 @@ export interface EntityBadgeConfig extends LovelaceBadgeConfig { name?: string; icon?: string; color?: string; + show_name?: boolean; + show_state?: boolean; + show_icon?: boolean; show_entity_picture?: boolean; - display_type?: "minimal" | "standard" | "complete"; state_content?: string | string[]; tap_action?: ActionConfig; hold_action?: ActionConfig; double_tap_action?: ActionConfig; + /** + * @deprecated use `show_state`, `show_name`, `icon_type` + */ + display_type?: DisplayType; } diff --git a/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts index 64944fbe2f..d2a9d155d2 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entity-badge-editor.ts @@ -22,8 +22,9 @@ import type { } from "../../../../components/ha-form/types"; import type { HomeAssistant } from "../../../../types"; import { - DEFAULT_DISPLAY_TYPE, + DEFAULT_CONFIG, DISPLAY_TYPES, + migrateLegacyEntityBadgeConfig, } from "../../badges/hui-entity-badge"; import { EntityBadgeConfig } from "../../badges/types"; import type { LovelaceBadgeEditor } from "../../types"; @@ -42,10 +43,12 @@ const badgeConfigStruct = assign( icon: optional(string()), state_content: optional(union([string(), array(string())])), color: optional(string()), + show_name: optional(boolean()), + show_state: optional(boolean()), + show_icon: optional(boolean()), show_entity_picture: optional(boolean()), tap_action: optional(actionConfigStruct), - show_name: optional(boolean()), - image: optional(string()), + image: optional(string()), // For old badge config support }) ); @@ -60,7 +63,10 @@ export class HuiEntityBadgeEditor public setConfig(config: EntityBadgeConfig): void { assert(config, badgeConfigStruct); - this._config = config; + this._config = { + ...DEFAULT_CONFIG, + ...migrateLegacyEntityBadgeConfig(config), + }; } private _schema = memoizeOne( @@ -73,20 +79,6 @@ export class HuiEntityBadgeEditor iconPath: mdiPalette, title: localize(`ui.panel.lovelace.editor.badge.entity.appearance`), schema: [ - { - name: "display_type", - selector: { - select: { - mode: "dropdown", - options: DISPLAY_TYPES.map((type) => ({ - value: type, - label: localize( - `ui.panel.lovelace.editor.badge.entity.display_type_options.${type}` - ), - })), - }, - }, - }, { name: "", type: "grid", @@ -97,6 +89,12 @@ export class HuiEntityBadgeEditor text: {}, }, }, + { + name: "color", + selector: { + ui_color: { default_color: true }, + }, + }, { name: "icon", selector: { @@ -104,12 +102,6 @@ export class HuiEntityBadgeEditor }, context: { icon_entity: "entity" }, }, - { - name: "color", - selector: { - ui_color: { default_color: true }, - }, - }, { name: "show_entity_picture", selector: { @@ -118,7 +110,35 @@ export class HuiEntityBadgeEditor }, ], }, - + { + name: "displayed_elements", + selector: { + select: { + mode: "list", + multiple: true, + options: [ + { + value: "name", + label: localize( + `ui.panel.lovelace.editor.badge.entity.displayed_elements_options.name` + ), + }, + { + value: "state", + label: localize( + `ui.panel.lovelace.editor.badge.entity.displayed_elements_options.state` + ), + }, + { + value: "icon", + label: localize( + `ui.panel.lovelace.editor.badge.entity.displayed_elements_options.icon` + ), + }, + ], + }, + }, + }, { name: "state_content", selector: { @@ -151,6 +171,20 @@ export class HuiEntityBadgeEditor ] as const satisfies readonly HaFormSchema[] ); + _displayedElements = memoizeOne((config: EntityBadgeConfig) => { + const elements: string[] = []; + if (config.show_name) { + elements.push("name"); + } + if (config.show_state) { + elements.push("state"); + } + if (config.show_icon) { + elements.push("icon"); + } + return elements; + }); + protected render() { if (!this.hass || !this._config) { return nothing; @@ -158,11 +192,10 @@ export class HuiEntityBadgeEditor const schema = this._schema(this.hass!.localize); - const data = { ...this._config }; - - if (!data.display_type) { - data.display_type = DEFAULT_DISPLAY_TYPE; - } + const data = { + ...this._config, + displayed_elements: this._displayedElements(this._config), + }; return html`