Add confirmations to some interactive entity-rows (#21453)

This commit is contained in:
karwosts 2024-10-28 05:09:41 -07:00 committed by GitHub
parent f92c63135c
commit 9db1e52a55
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 112 additions and 26 deletions

View File

@ -0,0 +1,25 @@
import type { ConfirmationRestrictionConfig } from "../../../data/lovelace/config/action";
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
import { HomeAssistant } from "../../../types";
export const confirmAction = async (
node: HTMLElement,
hass: HomeAssistant,
config: ConfirmationRestrictionConfig,
action: string
): Promise<boolean> => {
if (
config.exemptions &&
config.exemptions.some((e) => e.user === hass!.user?.id)
) {
return true;
}
return showConfirmationDialog(node, {
text:
config.text ||
hass.localize("ui.panel.lovelace.cards.actions.action_confirmation", {
action,
}),
});
};

View File

@ -16,7 +16,7 @@ const actionConfigStructUser = object({
user: string(),
});
const actionConfigStructConfirmation = union([
export const actionConfigStructConfirmation = union([
boolean(),
object({
text: optional(string()),

View File

@ -1,6 +1,9 @@
import { union, object, string, optional, boolean, enums } from "superstruct";
import { TIMESTAMP_RENDERING_FORMATS } from "../../components/types";
import { actionConfigStruct } from "./action-struct";
import {
actionConfigStruct,
actionConfigStructConfirmation,
} from "./action-struct";
export const entitiesConfigStruct = union([
object({
@ -14,6 +17,7 @@ export const entitiesConfigStruct = union([
tap_action: optional(actionConfigStruct),
hold_action: optional(actionConfigStruct),
double_tap_action: optional(actionConfigStruct),
confirmation: optional(actionConfigStructConfirmation),
}),
string(),
]);

View File

@ -14,6 +14,7 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { ActionRowConfig, LovelaceRow } from "./types";
import { confirmAction } from "../common/confirm-action";
@customElement("hui-button-entity-row")
class HuiButtonEntityRow extends LitElement implements LovelaceRow {
@ -69,11 +70,21 @@ class HuiButtonEntityRow extends LitElement implements LovelaceRow {
`;
}
private _pressButton(ev): void {
private async _pressButton(ev): Promise<void> {
ev.stopPropagation();
this.hass.callService("button", "press", {
entity_id: this._config!.entity,
});
if (
!this._config?.confirmation ||
(await confirmAction(
this,
this.hass,
this._config.confirmation,
this.hass.localize("ui.card.button.press")
))
) {
this.hass.callService("button", "press", {
entity_id: this._config!.entity,
});
}
}
}

View File

@ -14,6 +14,7 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { ActionRowConfig, LovelaceRow } from "./types";
import { confirmAction } from "../common/confirm-action";
@customElement("hui-input-button-entity-row")
class HuiInputButtonEntityRow extends LitElement implements LovelaceRow {
@ -69,11 +70,21 @@ class HuiInputButtonEntityRow extends LitElement implements LovelaceRow {
`;
}
private _pressButton(ev): void {
private async _pressButton(ev): Promise<void> {
ev.stopPropagation();
this.hass.callService("input_button", "press", {
entity_id: this._config!.entity,
});
if (
!this._config?.confirmation ||
(await confirmAction(
this,
this.hass,
this._config.confirmation,
this.hass.localize("ui.card.button.press")
))
) {
this.hass.callService("input_button", "press", {
entity_id: this._config!.entity,
});
}
}
}

View File

@ -13,16 +13,17 @@ import { HomeAssistant } from "../../../types";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { EntityConfig, LovelaceRow } from "./types";
import { ConfirmableRowConfig, LovelaceRow } from "./types";
import { callProtectedLockService } from "../../../data/lock";
import { confirmAction } from "../common/confirm-action";
@customElement("hui-lock-entity-row")
class HuiLockEntityRow extends LitElement implements LovelaceRow {
@property({ attribute: false }) public hass?: HomeAssistant;
@state() private _config?: EntityConfig;
@state() private _config?: ConfirmableRowConfig;
public setConfig(config: EntityConfig): void {
public setConfig(config: ConfirmableRowConfig): void {
if (!config) {
throw new Error("Invalid configuration");
}
@ -73,15 +74,21 @@ class HuiLockEntityRow extends LitElement implements LovelaceRow {
`;
}
private _callService(ev): void {
private async _callService(ev): Promise<void> {
ev.stopPropagation();
const stateObj = this.hass!.states[this._config!.entity];
callProtectedLockService(
this,
this.hass!,
stateObj,
stateObj.state === "locked" ? "unlock" : "lock"
);
const action = stateObj.state === "locked" ? "unlock" : "lock";
if (
!this._config?.confirmation ||
(await confirmAction(
this,
this.hass!,
this._config.confirmation,
this.hass!.localize(`ui.card.lock.${action}`)
))
) {
callProtectedLockService(this, this.hass!, stateObj, action);
}
}
}

View File

@ -16,6 +16,7 @@ import { hasConfigOrEntityChanged } from "../common/has-changed";
import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { ActionRowConfig, LovelaceRow } from "./types";
import { confirmAction } from "../common/confirm-action";
@customElement("hui-scene-entity-row")
class HuiSceneEntityRow extends LitElement implements LovelaceRow {
@ -73,9 +74,19 @@ class HuiSceneEntityRow extends LitElement implements LovelaceRow {
`;
}
private _callService(ev: Event): void {
private async _callService(ev: Event): Promise<void> {
ev.stopPropagation();
activateScene(this.hass, this._config!.entity);
if (
!this._config?.confirmation ||
(await confirmAction(
this,
this.hass,
this._config.confirmation,
this._config.action_name || this.hass.localize("ui.card.scene.activate")
))
) {
activateScene(this.hass, this._config!.entity);
}
}
}

View File

@ -16,6 +16,7 @@ import "../components/hui-generic-entity-row";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { ActionRowConfig, LovelaceRow } from "./types";
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
import { confirmAction } from "../common/confirm-action";
@customElement("hui-script-entity-row")
class HuiScriptEntityRow extends LitElement implements LovelaceRow {
@ -91,12 +92,20 @@ class HuiScriptEntityRow extends LitElement implements LovelaceRow {
this._callService("turn_off");
}
private _runScript(ev): void {
private async _runScript(ev): Promise<void> {
ev.stopPropagation();
if (hasScriptFields(this.hass!, this._config!.entity)) {
showMoreInfoDialog(this, { entityId: this._config!.entity });
} else {
} else if (
!this._config?.confirmation ||
(await confirmAction(
this,
this.hass!,
this._config.confirmation,
this._config.action_name || this.hass!.localize("ui.card.script.run")
))
) {
this._callService("turn_on");
}
}

View File

@ -1,4 +1,7 @@
import type { ActionConfig } from "../../../data/lovelace/config/action";
import type {
ActionConfig,
ConfirmationRestrictionConfig,
} from "../../../data/lovelace/config/action";
import type { HomeAssistant } from "../../../types";
import type { LegacyStateFilter } from "../common/evaluate-filter";
import type { Condition } from "../common/validate-condition";
@ -11,7 +14,12 @@ export interface EntityConfig {
icon?: string;
image?: string;
}
export interface ActionRowConfig extends EntityConfig {
export interface ConfirmableRowConfig extends EntityConfig {
confirmation?: ConfirmationRestrictionConfig;
}
export interface ActionRowConfig extends ConfirmableRowConfig {
action_name?: string;
}
export interface EntityFilterEntityConfig extends EntityConfig {