Add set_conversation_response action (#19512)

This commit is contained in:
Bram Kragten 2024-01-23 13:16:49 +01:00 committed by GitHub
parent 88f67230fc
commit cc4cfe1b5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 85 additions and 109 deletions

View File

@ -13,14 +13,9 @@ import {
mdiClose, mdiClose,
mdiCodeBraces, mdiCodeBraces,
mdiCodeBrackets, mdiCodeBrackets,
mdiDevices,
mdiGestureDoubleTap,
mdiHandBackRight,
mdiPalette,
mdiRefresh, mdiRefresh,
mdiRoomService, mdiRoomService,
mdiShuffleDisabled, mdiShuffleDisabled,
mdiTimerOutline,
} from "@mdi/js"; } from "@mdi/js";
import { css, html, LitElement, PropertyValues } from "lit"; import { css, html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
@ -30,17 +25,14 @@ import { Condition, Trigger } from "../../data/automation";
import { import {
Action, Action,
ChooseAction, ChooseAction,
DelayAction,
DeviceAction,
EventAction,
IfAction, IfAction,
ManualScriptConfig, ManualScriptConfig,
ParallelAction, ParallelAction,
RepeatAction, RepeatAction,
SceneAction,
ServiceAction, ServiceAction,
WaitAction, WaitAction,
WaitForTriggerAction, WaitForTriggerAction,
getActionType,
} from "../../data/script"; } from "../../data/script";
import { import {
ChooseActionTraceStep, ChooseActionTraceStep,
@ -53,6 +45,7 @@ import "./hat-graph-branch";
import { BRANCH_HEIGHT, NODE_SIZE, SPACING } from "./hat-graph-const"; import { BRANCH_HEIGHT, NODE_SIZE, SPACING } from "./hat-graph-const";
import "./hat-graph-node"; import "./hat-graph-node";
import "./hat-graph-spacer"; import "./hat-graph-spacer";
import { ACTION_ICONS } from "../../data/action";
export interface NodeInfo { export interface NodeInfo {
path: string; path: string;
@ -115,17 +108,12 @@ export class HatScriptGraph extends LitElement {
and: this.render_condition_node, and: this.render_condition_node,
or: this.render_condition_node, or: this.render_condition_node,
not: this.render_condition_node, not: this.render_condition_node,
delay: this.render_delay_node,
event: this.render_event_node,
scene: this.render_scene_node,
service: this.render_service_node, service: this.render_service_node,
wait_template: this.render_wait_node, wait_template: this.render_wait_node,
wait_for_trigger: this.render_wait_node, wait_for_trigger: this.render_wait_node,
repeat: this.render_repeat_node, repeat: this.render_repeat_node,
choose: this.render_choose_node, choose: this.render_choose_node,
device_id: this.render_device_node,
if: this.render_if_node, if: this.render_if_node,
stop: this.render_stop_node,
parallel: this.render_parallel_node, parallel: this.render_parallel_node,
other: this.render_other_node, other: this.render_other_node,
}; };
@ -371,63 +359,6 @@ export class HatScriptGraph extends LitElement {
`; `;
} }
private render_delay_node(
node: DelayAction,
path: string,
graphStart = false,
disabled = false
) {
return html`
<hat-graph-node
.graphStart=${graphStart}
.iconPath=${mdiTimerOutline}
@focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace}
?active=${this.selected === path}
.notEnabled=${disabled || node.enabled === false}
tabindex=${this.trace && path in this.trace.trace ? "0" : "-1"}
></hat-graph-node>
`;
}
private render_device_node(
node: DeviceAction,
path: string,
graphStart = false,
disabled = false
) {
return html`
<hat-graph-node
.graphStart=${graphStart}
.iconPath=${mdiDevices}
@focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace}
?active=${this.selected === path}
.notEnabled=${disabled || node.enabled === false}
tabindex=${this.trace && path in this.trace.trace ? "0" : "-1"}
></hat-graph-node>
`;
}
private render_event_node(
node: EventAction,
path: string,
graphStart = false,
disabled = false
) {
return html`
<hat-graph-node
.graphStart=${graphStart}
.iconPath=${mdiGestureDoubleTap}
@focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace}
?active=${this.selected === path}
.notEnabled=${disabled || node.enabled === false}
tabindex=${this.trace && path in this.trace.trace ? "0" : "-1"}
></hat-graph-node>
`;
}
private render_repeat_node( private render_repeat_node(
node: RepeatAction, node: RepeatAction,
path: string, path: string,
@ -475,25 +406,6 @@ export class HatScriptGraph extends LitElement {
`; `;
} }
private render_scene_node(
node: SceneAction,
path: string,
graphStart = false,
disabled = false
) {
return html`
<hat-graph-node
.graphStart=${graphStart}
.iconPath=${mdiPalette}
@focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace}
?active=${this.selected === path}
.notEnabled=${disabled || node.enabled === false}
tabindex=${this.trace && path in this.trace.trace ? "0" : "-1"}
></hat-graph-node>
`;
}
private render_service_node( private render_service_node(
node: ServiceAction, node: ServiceAction,
path: string, path: string,
@ -580,24 +492,6 @@ export class HatScriptGraph extends LitElement {
`; `;
} }
private render_stop_node(
node: Action,
path: string,
graphStart = false,
disabled = false
) {
return html`
<hat-graph-node
.graphStart=${graphStart}
.iconPath=${mdiHandBackRight}
@focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace}
?active=${this.selected === path}
.notEnabled=${disabled || node.enabled === false}
></hat-graph-node>
`;
}
private render_other_node( private render_other_node(
node: Action, node: Action,
path: string, path: string,
@ -607,7 +501,7 @@ export class HatScriptGraph extends LitElement {
return html` return html`
<hat-graph-node <hat-graph-node
.graphStart=${graphStart} .graphStart=${graphStart}
.iconPath=${mdiCodeBrackets} .iconPath=${ACTION_ICONS[getActionType(node)] || mdiCodeBrackets}
@focus=${this.selectNode(node, path)} @focus=${this.selectNode(node, path)}
?track=${path in this.trace.trace} ?track=${path in this.trace.trace}
?active=${this.selected === path} ?active=${this.selected === path}

View File

@ -2,6 +2,7 @@ import {
mdiAbTesting, mdiAbTesting,
mdiApplicationVariableOutline, mdiApplicationVariableOutline,
mdiArrowDecision, mdiArrowDecision,
mdiBullhorn,
mdiCallSplit, mdiCallSplit,
mdiCodeBraces, mdiCodeBraces,
mdiDevices, mdiDevices,
@ -36,6 +37,7 @@ export const ACTION_ICONS = {
stop: mdiHandBackRight, stop: mdiHandBackRight,
parallel: mdiShuffleDisabled, parallel: mdiShuffleDisabled,
variables: mdiApplicationVariableOutline, variables: mdiApplicationVariableOutline,
set_conversation_response: mdiBullhorn,
} as const; } as const;
export const YAML_ONLY_ACTION_TYPES = new Set<keyof typeof ACTION_ICONS>([ export const YAML_ONLY_ACTION_TYPES = new Set<keyof typeof ACTION_ICONS>([
@ -68,6 +70,7 @@ export const ACTION_GROUPS: AutomationElementGroup = {
members: { members: {
event: {}, event: {},
service: {}, service: {},
set_conversation_response: {},
}, },
}, },
} as const; } as const;

View File

@ -248,6 +248,10 @@ export interface ParallelAction extends BaseAction {
parallel: ManualScriptConfig | Action | (ManualScriptConfig | Action)[]; parallel: ManualScriptConfig | Action | (ManualScriptConfig | Action)[];
} }
export interface SetConversationResponseAction extends BaseAction {
set_conversation_response: string;
}
interface UnknownAction extends BaseAction { interface UnknownAction extends BaseAction {
[key: string]: unknown; [key: string]: unknown;
} }
@ -292,6 +296,7 @@ export interface ActionTypes {
play_media: PlayMediaAction; play_media: PlayMediaAction;
stop: StopAction; stop: StopAction;
parallel: ParallelAction; parallel: ParallelAction;
set_conversation_response: SetConversationResponseAction;
unknown: UnknownAction; unknown: UnknownAction;
} }
@ -383,6 +388,9 @@ export const getActionType = (action: Action): ActionType => {
if ("parallel" in action) { if ("parallel" in action) {
return "parallel"; return "parallel";
} }
if ("set_conversation_response" in action) {
return "set_conversation_response";
}
if ("service" in action) { if ("service" in action) {
if ("metadata" in action) { if ("metadata" in action) {
if (is(action, activateSceneActionStruct)) { if (is(action, activateSceneActionStruct)) {

View File

@ -27,6 +27,7 @@ import {
PlayMediaAction, PlayMediaAction,
RepeatAction, RepeatAction,
SceneAction, SceneAction,
SetConversationResponseAction,
StopAction, StopAction,
VariablesAction, VariablesAction,
WaitForTriggerAction, WaitForTriggerAction,
@ -443,5 +444,13 @@ const tryDescribeAction = <T extends ActionType>(
); );
} }
if (actionType === "set_conversation_response") {
const config = action as SetConversationResponseAction;
return hass.localize(
`${actionTranslationBaseKey}.set_conversation_response.description.full`,
{ response: config.set_conversation_response }
);
}
return actionType; return actionType;
}; };

View File

@ -77,6 +77,7 @@ import "./types/ha-automation-action-service";
import "./types/ha-automation-action-stop"; import "./types/ha-automation-action-stop";
import "./types/ha-automation-action-wait_for_trigger"; import "./types/ha-automation-action-wait_for_trigger";
import "./types/ha-automation-action-wait_template"; import "./types/ha-automation-action-wait_template";
import "./types/ha-automation-action-set_conversation_response";
export const getType = (action: Action | undefined) => { export const getType = (action: Action | undefined) => {
if (!action) { if (!action) {

View File

@ -0,0 +1,54 @@
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../../../components/ha-form/ha-form";
import type { SetConversationResponseAction } from "../../../../../data/script";
import type { HomeAssistant } from "../../../../../types";
import type { ActionElement } from "../ha-automation-action-row";
const SCHEMA = [
{
name: "set_conversation_response",
selector: {
template: {},
},
},
] as const;
@customElement("ha-automation-action-set_conversation_response")
export class HaSetConversationResponseAction
extends LitElement
implements ActionElement
{
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ attribute: false }) public action!: SetConversationResponseAction;
@property({ type: Boolean }) public disabled = false;
public static get defaultConfig() {
return { set_conversation_response: "" };
}
protected render() {
return html`
<ha-form
.hass=${this.hass}
.data=${this.action}
.schema=${SCHEMA}
.disabled=${this.disabled}
.computeLabel=${this._computeLabelCallback}
></ha-form>
`;
}
private _computeLabelCallback = (): string =>
this.hass.localize(
"ui.panel.config.automation.editor.actions.type.set_conversation_response.label"
);
}
declare global {
interface HTMLElementTagNameMap {
"ha-automation-action-set_conversation_response": HaSetConversationResponseAction;
}
}

View File

@ -3117,6 +3117,13 @@
"full": "Test {condition}" "full": "Test {condition}"
} }
}, },
"set_conversation_response": {
"label": "Set conversation response",
"description": {
"picker": "Set response of conversation when automation was triggered by conversation trigger.",
"full": "Set response of conversation to {response}"
}
},
"unknown": { "unknown": {
"label": "Unknown" "label": "Unknown"
} }