diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 090bb0dfc0..32886dfc36 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -148,6 +148,11 @@ export interface CustomActionConfig extends BaseActionConfig { action: "fire-dom-event"; } +export interface MultipleActionConfig extends BaseActionConfig { + action: "multiple"; + actions: ActionConfig[]; +} + export interface BaseActionConfig { confirmation?: ConfirmationRestrictionConfig; } @@ -168,7 +173,8 @@ export type ActionConfig = | UrlActionConfig | MoreInfoActionConfig | NoActionConfig - | CustomActionConfig; + | CustomActionConfig + | MultipleActionConfig; type LovelaceUpdatedEvent = HassEventBase & { event_type: "lovelace_updated"; diff --git a/src/panels/lovelace/common/handle-action.ts b/src/panels/lovelace/common/handle-action.ts index bb6467b2c1..15c3b7d26a 100644 --- a/src/panels/lovelace/common/handle-action.ts +++ b/src/panels/lovelace/common/handle-action.ts @@ -40,69 +40,74 @@ export const handleAction = async ( }; } - if ( - actionConfig.confirmation && - (!actionConfig.confirmation.exemptions || - !actionConfig.confirmation.exemptions.some( - (e) => e.user === hass!.user!.id - )) - ) { - forwardHaptic("warning"); + const actionConfigs = + actionConfig.action === "multiple" ? actionConfig.actions : [actionConfig]; + for await (actionConfig of actionConfigs) { if ( - !(await showConfirmationDialog(node, { - text: - actionConfig.confirmation.text || - hass.localize( - "ui.panel.lovelace.cards.action_confirmation", - "action", - actionConfig.action - ), - })) + actionConfig.confirmation && + (!actionConfig.confirmation.exemptions || + !actionConfig.confirmation.exemptions.some( + (e) => e.user === hass!.user!.id + )) ) { - return; - } - } + forwardHaptic("warning"); - switch (actionConfig.action) { - case "more-info": { - if (config.entity || config.camera_image) { - fireEvent(node, "hass-more-info", { - entityId: config.entity ? config.entity : config.camera_image!, - }); - } - break; - } - case "navigate": - if (actionConfig.navigation_path) { - navigate(node, actionConfig.navigation_path); - } - break; - case "url": { - if (actionConfig.url_path) { - window.open(actionConfig.url_path); - } - break; - } - case "toggle": { - if (config.entity) { - toggleEntity(hass, config.entity!); - forwardHaptic("light"); - } - break; - } - case "call-service": { - if (!actionConfig.service) { - forwardHaptic("failure"); + if ( + !(await showConfirmationDialog(node, { + text: + actionConfig.confirmation.text || + hass.localize( + "ui.panel.lovelace.cards.action_confirmation", + "action", + actionConfig.action + ), + })) + ) { return; } - const [domain, service] = actionConfig.service.split(".", 2); - hass.callService(domain, service, actionConfig.service_data); - forwardHaptic("light"); - break; } - case "fire-dom-event": { - fireEvent(node, "ll-custom", actionConfig); + + switch (actionConfig.action) { + case "more-info": { + if (config.entity || config.camera_image) { + fireEvent(node, "hass-more-info", { + entityId: config.entity ? config.entity : config.camera_image!, + }); + } + break; + } + case "navigate": + if (actionConfig.navigation_path) { + navigate(node, actionConfig.navigation_path); + } + break; + case "url": { + if (actionConfig.url_path) { + window.open(actionConfig.url_path); + } + break; + } + case "toggle": { + if (config.entity) { + toggleEntity(hass, config.entity!); + forwardHaptic("light"); + } + break; + } + case "call-service": { + if (!actionConfig.service) { + forwardHaptic("failure"); + return; + } + const [domain, service] = actionConfig.service.split(".", 2); + hass.callService(domain, service, actionConfig.service_data); + forwardHaptic("light"); + break; + } + case "fire-dom-event": { + fireEvent(node, "ll-custom", actionConfig); + } } } }; diff --git a/src/panels/lovelace/components/hui-action-editor.ts b/src/panels/lovelace/components/hui-action-editor.ts index 7946138d6e..78d72b9865 100644 --- a/src/panels/lovelace/components/hui-action-editor.ts +++ b/src/panels/lovelace/components/hui-action-editor.ts @@ -130,6 +130,15 @@ export class HuiActionEditor extends LitElement { ` : ""} + ${this.config?.action === "multiple" + ? html` + + ${this.hass!.localize( + "ui.panel.lovelace.editor.action-editor.editor_multiple_actions" + )} + + ` + : ""} `; } 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 2b4ff6acfd..32813fe46e 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 @@ -46,6 +46,7 @@ const actions = [ "url", "call-service", "none", + "multiple", ]; @customElement("hui-button-card-editor") diff --git a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts index 3a21299e95..931e50b94a 100644 --- a/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-light-card-editor.ts @@ -82,6 +82,7 @@ export class HuiLightCardEditor extends LitElement "url", "call-service", "none", + "multiple", ]; return html` diff --git a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts index 26d66d2baf..1ecd7a07e5 100644 --- a/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-picture-card-editor.ts @@ -60,7 +60,7 @@ export class HuiPictureCardEditor extends LitElement return html``; } - const actions = ["navigate", "url", "call-service", "none"]; + const actions = ["navigate", "url", "call-service", "none", "multiple"]; return html`