Skip to content

Commit

Permalink
Add confirmations to some interactive entity-rows (#21453)
Browse files Browse the repository at this point in the history
  • Loading branch information
karwosts authored Oct 28, 2024
1 parent f92c631 commit 9db1e52
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 26 deletions.
25 changes: 25 additions & 0 deletions src/panels/lovelace/common/confirm-action.ts
Original file line number Diff line number Diff line change
@@ -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,
}),
});
};
2 changes: 1 addition & 1 deletion src/panels/lovelace/editor/structs/action-struct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const actionConfigStructUser = object({
user: string(),
});

const actionConfigStructConfirmation = union([
export const actionConfigStructConfirmation = union([
boolean(),
object({
text: optional(string()),
Expand Down
6 changes: 5 additions & 1 deletion src/panels/lovelace/editor/structs/entities-struct.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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(),
]);
19 changes: 15 additions & 4 deletions src/panels/lovelace/entity-rows/hui-button-entity-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
});
}
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/panels/lovelace/entity-rows/hui-input-button-entity-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
});
}
}
}

Expand Down
27 changes: 17 additions & 10 deletions src/panels/lovelace/entity-rows/hui-lock-entity-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
15 changes: 13 additions & 2 deletions src/panels/lovelace/entity-rows/hui-scene-entity-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
}
}

Expand Down
13 changes: 11 additions & 2 deletions src/panels/lovelace/entity-rows/hui-script-entity-row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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");
}
}
Expand Down
12 changes: 10 additions & 2 deletions src/panels/lovelace/entity-rows/types.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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 {
Expand Down

0 comments on commit 9db1e52

Please sign in to comment.