From fb2a62274c564f834abc0e05a1670e8fb4ae28ee Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 25 Oct 2023 13:30:04 +0200 Subject: [PATCH 1/3] Display default action label in action selector --- .../ha-selector/ha-selector-ui-action.ts | 1 + src/data/selector.ts | 1 + src/panels/lovelace/cards/hui-tile-card.ts | 16 ++++++---- .../lovelace/components/hui-action-editor.ts | 30 +++++++++++++++++-- .../config-elements/hui-tile-card-editor.ts | 19 ++++++++---- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/components/ha-selector/ha-selector-ui-action.ts b/src/components/ha-selector/ha-selector-ui-action.ts index a2210212257f..bc60b45bc6da 100644 --- a/src/components/ha-selector/ha-selector-ui-action.ts +++ b/src/components/ha-selector/ha-selector-ui-action.ts @@ -25,6 +25,7 @@ export class HaSelectorUiAction extends LitElement { .hass=${this.hass} .config=${this.value} .actions=${this.selector.ui_action?.actions} + .defaultAction=${this.selector.ui_action?.default} .tooltipText=${this.helper} @value-changed=${this._valueChanged} > diff --git a/src/data/selector.ts b/src/data/selector.ts index aaa0a23c0f4a..5483efde3b3e 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -384,6 +384,7 @@ export interface TTSVoiceSelector { export interface UiActionSelector { ui_action: { actions?: UiAction[]; + default?: UiAction; } | null; } diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 3b7db1bf368d..c775a30984d0 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -50,6 +50,15 @@ import type { ThermostatCardConfig, TileCardConfig } from "./types"; const TIMESTAMP_STATE_DOMAINS = ["button", "input_button", "scene"]; +export const getEntityDefaultTileIconAction = (entityId: string) => { + const domain = computeDomain(entityId); + const supportsIconAction = + DOMAINS_TOGGLE.has(domain) || + ["button", "input_button", "scene"].includes(domain); + + return supportsIconAction ? "toggle" : "more-info"; +}; + @customElement("hui-tile-card") export class HuiTileCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -87,17 +96,12 @@ export class HuiTileCard extends LitElement implements LovelaceCard { throw new Error("Specify an entity"); } - const domain = computeDomain(config.entity); - const supportsIconAction = - DOMAINS_TOGGLE.has(domain) || - ["button", "input_button", "scene"].includes(domain); - this._config = { tap_action: { action: "more-info", }, icon_tap_action: { - action: supportsIconAction ? "toggle" : "more-info", + action: getEntityDefaultTileIconAction(config.entity), }, ...config, }; diff --git a/src/panels/lovelace/components/hui-action-editor.ts b/src/panels/lovelace/components/hui-action-editor.ts index 972d79b173a2..28e4a65902bc 100644 --- a/src/panels/lovelace/components/hui-action-editor.ts +++ b/src/panels/lovelace/components/hui-action-editor.ts @@ -1,5 +1,12 @@ -import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; -import { customElement, property } from "lit/decorators"; +import { + css, + CSSResultGroup, + html, + LitElement, + nothing, + PropertyValues, +} from "lit"; +import { customElement, property, query } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../common/dom/fire_event"; import { stopPropagation } from "../../../common/dom/stop_propagation"; @@ -17,6 +24,7 @@ import { import { ServiceAction } from "../../../data/script"; import { HomeAssistant } from "../../../types"; import { EditorTarget } from "../editor/types"; +import { HaSelect } from "../../../components/ha-select"; export type UiAction = Exclude; @@ -70,10 +78,14 @@ export class HuiActionEditor extends LitElement { @property() public actions?: UiAction[]; + @property() public defaultAction?: UiAction; + @property() public tooltipText?: string; @property() protected hass?: HomeAssistant; + @query("ha-select") private _select!: HaSelect; + get _navigation_path(): string { const config = this.config as NavigateActionConfig | undefined; return config?.navigation_path || ""; @@ -99,6 +111,15 @@ export class HuiActionEditor extends LitElement { }) ); + protected updated(changedProperties: PropertyValues) { + super.updated(changedProperties); + if (changedProperties.has("defaultAction")) { + if (changedProperties.get("defaultAction") !== this.defaultAction) { + this._select.layoutOptions(); + } + } + } + protected render() { if (!this.hass) { return nothing; @@ -121,6 +142,11 @@ export class HuiActionEditor extends LitElement { ${this.hass!.localize( "ui.panel.lovelace.editor.action-editor.actions.default_action" )} + ${this.defaultAction + ? ` (${this.hass!.localize( + `ui.panel.lovelace.editor.action-editor.actions.${this.defaultAction}` + ).toLowerCase()})` + : nothing} ${actions.map( (action) => html` diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts index ebff8fb27df7..1a17833b4b87 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts @@ -36,6 +36,7 @@ import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { EditSubElementEvent, SubElementEditorConfig } from "../types"; import { configElementStyle } from "./config-elements-style"; import "./hui-tile-card-features-editor"; +import { getEntityDefaultTileIconAction } from "../../cards/hui-tile-card"; const HIDDEN_ATTRIBUTES = [ "access_token", @@ -125,6 +126,7 @@ export class HuiTileCardEditor ( localize: LocalizeFunc, formatEntityAttributeName: formatEntityAttributeNameFunc, + entityId: string | undefined, stateObj: HassEntity | undefined, hideState: boolean ) => @@ -219,13 +221,19 @@ export class HuiTileCardEditor { name: "tap_action", selector: { - ui_action: {}, + ui_action: { + default: "more-info", + }, }, }, { name: "icon_tap_action", selector: { - ui_action: {}, + ui_action: { + default: entityId + ? getEntityDefaultTileIconAction(entityId) + : "more-info", + }, }, }, ], @@ -242,13 +250,14 @@ export class HuiTileCardEditor return nothing; } - const stateObj = this.hass.states[this._config.entity ?? ""] as - | HassEntity - | undefined; + const stateObj = this._config.entity + ? this.hass.states[this._config.entity] + : undefined; const schema = this._schema( this.hass!.localize, this.hass.formatEntityAttributeName, + this._config.entity, stateObj, this._config.hide_state ?? false ); From 39e1aec1fa62ffc21aa250476f69d3131e9dac18 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 25 Oct 2023 13:40:55 +0200 Subject: [PATCH 2/3] Add default for button card --- src/panels/lovelace/cards/hui-button-card.ts | 10 +- .../config-elements/hui-button-card-editor.ts | 122 +++++++++++------- 2 files changed, 78 insertions(+), 54 deletions(-) diff --git a/src/panels/lovelace/cards/hui-button-card.ts b/src/panels/lovelace/cards/hui-button-card.ts index 9cb0b359b1bc..af922760aa63 100644 --- a/src/panels/lovelace/cards/hui-button-card.ts +++ b/src/panels/lovelace/cards/hui-button-card.ts @@ -55,6 +55,11 @@ import { createEntityNotFoundWarning } from "../components/hui-warning"; import { LovelaceCard, LovelaceCardEditor } from "../types"; import { ButtonCardConfig } from "./types"; +export const getEntityDefaultButtonAction = (entityId?: string) => + entityId && DOMAINS_TOGGLE.has(computeDomain(entityId)) + ? "toggle" + : "more-info"; + @customElement("hui-button-card") export class HuiButtonCard extends LitElement implements LovelaceCard { public static async getConfigElement(): Promise { @@ -149,10 +154,7 @@ export class HuiButtonCard extends LitElement implements LovelaceCard { this._config = { tap_action: { - action: - config.entity && DOMAINS_TOGGLE.has(computeDomain(config.entity)) - ? "toggle" - : "more-info", + action: getEntityDefaultButtonAction(config.entity), }, hold_action: { action: "more-info" }, show_icon: true, diff --git a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts index 5f06792c46f3..c8bc27484383 100644 --- a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts @@ -1,10 +1,15 @@ import { CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; +import memoizeOne from "memoize-one"; import { assert, assign, boolean, object, optional, string } from "superstruct"; import { fireEvent } from "../../../../common/dom/fire_event"; import "../../../../components/ha-form/ha-form"; -import type { SchemaUnion } from "../../../../components/ha-form/types"; +import type { + HaFormSchema, + SchemaUnion, +} from "../../../../components/ha-form/types"; import type { HomeAssistant } from "../../../../types"; +import { getEntityDefaultButtonAction } from "../../cards/hui-button-card"; import type { ButtonCardConfig } from "../../cards/types"; import type { LovelaceCardEditor } from "../../types"; import { actionConfigStruct } from "../structs/action-struct"; @@ -27,52 +32,6 @@ const cardConfigStruct = assign( }) ); -const SCHEMA = [ - { name: "entity", selector: { entity: {} } }, - { - name: "", - type: "grid", - schema: [ - { name: "name", selector: { text: {} } }, - { - name: "icon", - selector: { - icon: {}, - }, - context: { - icon_entity: "entity", - }, - }, - ], - }, - { - name: "", - type: "grid", - column_min_width: "100px", - schema: [ - { name: "show_name", selector: { boolean: {} } }, - { name: "show_state", selector: { boolean: {} } }, - { name: "show_icon", selector: { boolean: {} } }, - ], - }, - { - name: "", - type: "grid", - schema: [ - { name: "icon_height", selector: { text: { suffix: "px" } } }, - { name: "theme", selector: { theme: {} } }, - ], - }, - { - name: "tap_action", - selector: { ui_action: {} }, - }, - { - name: "hold_action", - selector: { ui_action: {} }, - }, -] as const; - @customElement("hui-button-card-editor") export class HuiButtonCardEditor extends LitElement @@ -87,6 +46,63 @@ export class HuiButtonCardEditor this._config = config; } + private _schema = memoizeOne( + (entityId: string | undefined) => + [ + { name: "entity", selector: { entity: {} } }, + { + name: "", + type: "grid", + schema: [ + { name: "name", selector: { text: {} } }, + { + name: "icon", + selector: { + icon: {}, + }, + context: { + icon_entity: "entity", + }, + }, + ], + }, + { + name: "", + type: "grid", + column_min_width: "100px", + schema: [ + { name: "show_name", selector: { boolean: {} } }, + { name: "show_state", selector: { boolean: {} } }, + { name: "show_icon", selector: { boolean: {} } }, + ], + }, + { + name: "", + type: "grid", + schema: [ + { name: "icon_height", selector: { text: { suffix: "px" } } }, + { name: "theme", selector: { theme: {} } }, + ], + }, + { + name: "tap_action", + selector: { + ui_action: { + default: getEntityDefaultButtonAction(entityId), + }, + }, + }, + { + name: "hold_action", + selector: { + ui_action: { + default: "more-info", + }, + }, + }, + ] as const satisfies readonly HaFormSchema[] + ); + protected render() { if (!this.hass || !this._config) { return nothing; @@ -102,11 +118,13 @@ export class HuiButtonCardEditor data.icon_height = String(parseFloat(data.icon_height)); } + const schema = this._schema(this._config.entity); + return html` ) => { + private _computeHelperCallback = ( + schema: SchemaUnion> + ) => { switch (schema.name) { case "tap_action": case "hold_action": @@ -136,7 +156,9 @@ export class HuiButtonCardEditor } }; - private _computeLabelCallback = (schema: SchemaUnion) => { + private _computeLabelCallback = ( + schema: SchemaUnion> + ) => { switch (schema.name) { case "theme": case "tap_action": From 21cc625d3207f9a47524c2f638b9761ea92d7644 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Wed, 25 Oct 2023 13:48:21 +0200 Subject: [PATCH 3/3] rename option --- src/components/ha-selector/ha-selector-ui-action.ts | 2 +- src/data/selector.ts | 2 +- .../lovelace/editor/config-elements/hui-button-card-editor.ts | 4 ++-- .../lovelace/editor/config-elements/hui-tile-card-editor.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/ha-selector/ha-selector-ui-action.ts b/src/components/ha-selector/ha-selector-ui-action.ts index bc60b45bc6da..3b607160c198 100644 --- a/src/components/ha-selector/ha-selector-ui-action.ts +++ b/src/components/ha-selector/ha-selector-ui-action.ts @@ -25,7 +25,7 @@ export class HaSelectorUiAction extends LitElement { .hass=${this.hass} .config=${this.value} .actions=${this.selector.ui_action?.actions} - .defaultAction=${this.selector.ui_action?.default} + .defaultAction=${this.selector.ui_action?.default_action} .tooltipText=${this.helper} @value-changed=${this._valueChanged} > diff --git a/src/data/selector.ts b/src/data/selector.ts index 5483efde3b3e..51f8e8c9383a 100644 --- a/src/data/selector.ts +++ b/src/data/selector.ts @@ -384,7 +384,7 @@ export interface TTSVoiceSelector { export interface UiActionSelector { ui_action: { actions?: UiAction[]; - default?: UiAction; + default_action?: UiAction; } | null; } diff --git a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts index c8bc27484383..277eec42eb48 100644 --- a/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-button-card-editor.ts @@ -88,7 +88,7 @@ export class HuiButtonCardEditor name: "tap_action", selector: { ui_action: { - default: getEntityDefaultButtonAction(entityId), + default_action: getEntityDefaultButtonAction(entityId), }, }, }, @@ -96,7 +96,7 @@ export class HuiButtonCardEditor name: "hold_action", selector: { ui_action: { - default: "more-info", + default_action: "more-info", }, }, }, diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts index 1a17833b4b87..807bfaf5a829 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts @@ -222,7 +222,7 @@ export class HuiTileCardEditor name: "tap_action", selector: { ui_action: { - default: "more-info", + default_action: "more-info", }, }, }, @@ -230,7 +230,7 @@ export class HuiTileCardEditor name: "icon_tap_action", selector: { ui_action: { - default: entityId + default_action: entityId ? getEntityDefaultTileIconAction(entityId) : "more-info", },