mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Add UI for conversation trigger (#17037)
This commit is contained in:
parent
d656269d75
commit
87aad75cc7
@ -51,6 +51,11 @@ const triggers = [
|
||||
{ platform: "tag" },
|
||||
{ platform: "time", at: "15:32" },
|
||||
{ platform: "template" },
|
||||
{ platform: "conversation", command: "Turn on the lights" },
|
||||
{
|
||||
platform: "conversation",
|
||||
command: ["Turn on the lights", "Turn the lights on"],
|
||||
},
|
||||
{ platform: "event", event_type: "homeassistant_started" },
|
||||
];
|
||||
|
||||
|
@ -25,6 +25,7 @@ import { HaDeviceTrigger } from "../../../../src/panels/config/automation/trigge
|
||||
import { HaStateTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-state";
|
||||
import { HaMQTTTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-mqtt";
|
||||
import "../../../../src/panels/config/automation/trigger/ha-automation-trigger";
|
||||
import { HaConversationTrigger } from "../../../../src/panels/config/automation/trigger/types/ha-automation-trigger-conversation";
|
||||
|
||||
const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
||||
{
|
||||
@ -112,6 +113,16 @@ const SCHEMAS: { name: string; triggers: Trigger[] }[] = [
|
||||
name: "Device Trigger",
|
||||
triggers: [{ platform: "device", ...HaDeviceTrigger.defaultConfig }],
|
||||
},
|
||||
{
|
||||
name: "Sentence",
|
||||
triggers: [
|
||||
{ platform: "conversation", ...HaConversationTrigger.defaultConfig },
|
||||
{
|
||||
platform: "conversation",
|
||||
command: ["Turn on the lights", "Turn the lights on"],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@customElement("demo-automation-editor-trigger")
|
||||
|
@ -107,6 +107,11 @@ export interface NumericStateTrigger extends BaseTrigger {
|
||||
for?: string | number | ForDict;
|
||||
}
|
||||
|
||||
export interface ConversationTrigger extends BaseTrigger {
|
||||
platform: "conversation";
|
||||
command: string | string[];
|
||||
}
|
||||
|
||||
export interface SunTrigger extends BaseTrigger {
|
||||
platform: "sun";
|
||||
offset: number;
|
||||
@ -178,6 +183,7 @@ export type Trigger =
|
||||
| HassTrigger
|
||||
| NumericStateTrigger
|
||||
| SunTrigger
|
||||
| ConversationTrigger
|
||||
| TimePatternTrigger
|
||||
| WebhookTrigger
|
||||
| PersistentNotificationTrigger
|
||||
|
@ -610,6 +610,24 @@ const tryDescribeTrigger = (
|
||||
);
|
||||
}
|
||||
|
||||
// Conversation Trigger
|
||||
if (trigger.platform === "conversation") {
|
||||
if (!trigger.command) {
|
||||
return hass.localize(
|
||||
`${triggerTranslationBaseKey}.conversation.description.empty`
|
||||
);
|
||||
}
|
||||
|
||||
return hass.localize(
|
||||
`${triggerTranslationBaseKey}.conversation.description.full`,
|
||||
{
|
||||
sentence: disjunctionFormatter.format(
|
||||
ensureArray(trigger.command).map((cmd) => `'${cmd}'`)
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Persistent Notification Trigger
|
||||
if (trigger.platform === "persistent_notification") {
|
||||
return "When a persistent notification is updated";
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
mdiMapMarker,
|
||||
mdiMapMarkerRadius,
|
||||
mdiMessageAlert,
|
||||
mdiMicrophoneMessage,
|
||||
mdiNfcVariant,
|
||||
mdiNumeric,
|
||||
mdiStateMachine,
|
||||
@ -27,6 +28,7 @@ export const TRIGGER_TYPES = {
|
||||
mqtt: mdiSwapHorizontal,
|
||||
numeric_state: mdiNumeric,
|
||||
sun: mdiWeatherSunny,
|
||||
conversation: mdiMicrophoneMessage,
|
||||
tag: mdiNfcVariant,
|
||||
template: mdiCodeBraces,
|
||||
time: mdiClockOutline,
|
||||
|
@ -53,6 +53,7 @@ import "./types/ha-automation-trigger-homeassistant";
|
||||
import "./types/ha-automation-trigger-mqtt";
|
||||
import "./types/ha-automation-trigger-numeric_state";
|
||||
import "./types/ha-automation-trigger-persistent_notification";
|
||||
import "./types/ha-automation-trigger-conversation";
|
||||
import "./types/ha-automation-trigger-state";
|
||||
import "./types/ha-automation-trigger-sun";
|
||||
import "./types/ha-automation-trigger-tag";
|
||||
|
@ -43,6 +43,7 @@ import "./types/ha-automation-trigger-homeassistant";
|
||||
import "./types/ha-automation-trigger-mqtt";
|
||||
import "./types/ha-automation-trigger-numeric_state";
|
||||
import "./types/ha-automation-trigger-persistent_notification";
|
||||
import "./types/ha-automation-trigger-conversation";
|
||||
import "./types/ha-automation-trigger-state";
|
||||
import "./types/ha-automation-trigger-sun";
|
||||
import "./types/ha-automation-trigger-tag";
|
||||
|
@ -0,0 +1,174 @@
|
||||
import { mdiClose } from "@mdi/js";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { ensureArray } from "../../../../../common/array/ensure-array";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import "../../../../../components/ha-textfield";
|
||||
import type { HaTextField } from "../../../../../components/ha-textfield";
|
||||
import { ConversationTrigger } from "../../../../../data/automation";
|
||||
import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { TriggerElement } from "../ha-automation-trigger-row";
|
||||
|
||||
@customElement("ha-automation-trigger-conversation")
|
||||
export class HaConversationTrigger
|
||||
extends LitElement
|
||||
implements TriggerElement
|
||||
{
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public trigger!: ConversationTrigger;
|
||||
|
||||
@property({ type: Boolean }) public disabled = false;
|
||||
|
||||
@query("#option_input", true) private _optionInput?: HaTextField;
|
||||
|
||||
public static get defaultConfig(): Omit<ConversationTrigger, "platform"> {
|
||||
return { command: "" };
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const { command } = this.trigger;
|
||||
const commands = command ? ensureArray(command) : [];
|
||||
|
||||
return html`${commands.length
|
||||
? commands.map(
|
||||
(option, index) => html`
|
||||
<ha-textfield
|
||||
class="option"
|
||||
iconTrailing
|
||||
.index=${index}
|
||||
.value=${option}
|
||||
@change=${this._updateOption}
|
||||
>
|
||||
<ha-icon-button
|
||||
@click=${this._removeOption}
|
||||
slot="trailingIcon"
|
||||
.path=${mdiClose}
|
||||
></ha-icon-button>
|
||||
</ha-textfield>
|
||||
`
|
||||
)
|
||||
: nothing}
|
||||
<ha-textfield
|
||||
class="flex-auto"
|
||||
id="option_input"
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.type.conversation.add_sentence"
|
||||
)}
|
||||
@keydown=${this._handleKeyAdd}
|
||||
@change=${this._addOption}
|
||||
></ha-textfield>`;
|
||||
}
|
||||
|
||||
private _handleKeyAdd(ev: KeyboardEvent) {
|
||||
ev.stopPropagation();
|
||||
if (ev.key !== "Enter") {
|
||||
return;
|
||||
}
|
||||
this._addOption();
|
||||
}
|
||||
|
||||
private _addOption() {
|
||||
const input = this._optionInput;
|
||||
if (!input?.value) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.trigger,
|
||||
command: this.trigger.command.length
|
||||
? [
|
||||
...(Array.isArray(this.trigger.command)
|
||||
? this.trigger.command
|
||||
: [this.trigger.command]),
|
||||
input.value,
|
||||
]
|
||||
: input.value,
|
||||
},
|
||||
});
|
||||
input.value = "";
|
||||
}
|
||||
|
||||
private async _updateOption(ev: Event) {
|
||||
const index = (ev.target as any).index;
|
||||
const command = [...this.trigger.command];
|
||||
command.splice(index, 1, (ev.target as HaTextField).value);
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.trigger, command },
|
||||
});
|
||||
}
|
||||
|
||||
private async _removeOption(ev: Event) {
|
||||
const index = (ev.target as any).parentElement.index;
|
||||
if (
|
||||
!(await showConfirmationDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.type.conversation.delete"
|
||||
),
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.automation.editor.triggers.type.conversation.confirm_delete"
|
||||
),
|
||||
destructive: true,
|
||||
}))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
let command: string[] | string;
|
||||
if (!Array.isArray(this.trigger.command)) {
|
||||
command = "";
|
||||
} else {
|
||||
command = [...this.trigger.command];
|
||||
command.splice(index, 1);
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.trigger, command },
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.option {
|
||||
margin-top: 4px;
|
||||
}
|
||||
mwc-button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
ha-textfield {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
--textfield-icon-trailing-padding: 0;
|
||||
}
|
||||
ha-textfield > ha-icon-button {
|
||||
position: relative;
|
||||
right: -8px;
|
||||
--mdc-icon-button-size: 36px;
|
||||
--mdc-icon-size: 20px;
|
||||
color: var(--secondary-text-color);
|
||||
inset-inline-start: initial;
|
||||
inset-inline-end: -8px;
|
||||
direction: var(--direction);
|
||||
}
|
||||
#option_input {
|
||||
margin-top: 8px;
|
||||
}
|
||||
.header {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-automation-trigger-conversation": HaConversationTrigger;
|
||||
}
|
||||
}
|
@ -2378,6 +2378,16 @@
|
||||
"rises": "When the sun rises{hasDuration, select, \n true { offset by {duration}} \n other {}\n }"
|
||||
}
|
||||
},
|
||||
"conversation": {
|
||||
"label": "Sentence",
|
||||
"add_sentence": "Add sentence",
|
||||
"delete": "Delete sentence",
|
||||
"confirm_delete": "Are you sure you want to delete this sentence?",
|
||||
"description": {
|
||||
"empty": "When a sentence is said",
|
||||
"full": "When the sentence {sentence} is said"
|
||||
}
|
||||
},
|
||||
"tag": {
|
||||
"label": "Tag",
|
||||
"description": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user