mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
Allow to select a pipeline in voice command dialog (#16291)
This commit is contained in:
parent
63de324224
commit
8c06712ab7
@ -13,6 +13,9 @@ export class HaButton extends Button {
|
|||||||
margin-inline-end: 8px;
|
margin-inline-end: 8px;
|
||||||
direction: var(--direction);
|
direction: var(--direction);
|
||||||
}
|
}
|
||||||
|
.mdc-button {
|
||||||
|
height: var(--button-height, 36px);
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import "@material/mwc-button/mwc-button";
|
import "@material/mwc-button/mwc-button";
|
||||||
import {
|
import {
|
||||||
|
mdiChevronDown,
|
||||||
mdiClose,
|
mdiClose,
|
||||||
mdiHelpCircleOutline,
|
mdiHelpCircleOutline,
|
||||||
mdiMicrophone,
|
mdiMicrophone,
|
||||||
mdiSend,
|
mdiSend,
|
||||||
|
mdiStar,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
@ -16,14 +18,19 @@ import {
|
|||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
import { LocalStorage } from "../../common/decorators/local-storage";
|
import { LocalStorage } from "../../common/decorators/local-storage";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { stopPropagation } from "../../common/dom/stop_propagation";
|
||||||
|
import "../../components/ha-button";
|
||||||
|
import "../../components/ha-button-menu";
|
||||||
import "../../components/ha-dialog";
|
import "../../components/ha-dialog";
|
||||||
import "../../components/ha-header-bar";
|
import "../../components/ha-header-bar";
|
||||||
import "../../components/ha-icon-button";
|
import "../../components/ha-icon-button";
|
||||||
|
import "../../components/ha-list-item";
|
||||||
import "../../components/ha-textfield";
|
import "../../components/ha-textfield";
|
||||||
import type { HaTextField } from "../../components/ha-textfield";
|
import type { HaTextField } from "../../components/ha-textfield";
|
||||||
import {
|
import {
|
||||||
AssistPipeline,
|
AssistPipeline,
|
||||||
getAssistPipeline,
|
getAssistPipeline,
|
||||||
|
listAssistPipelines,
|
||||||
runAssistPipeline,
|
runAssistPipeline,
|
||||||
} from "../../data/assist_pipeline";
|
} from "../../data/assist_pipeline";
|
||||||
import { AgentInfo, getAgentInfo } from "../../data/conversation";
|
import { AgentInfo, getAgentInfo } from "../../data/conversation";
|
||||||
@ -55,6 +62,10 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
|
|
||||||
@state() private _showSendButton = false;
|
@state() private _showSendButton = false;
|
||||||
|
|
||||||
|
@state() private _pipelines?: AssistPipeline[];
|
||||||
|
|
||||||
|
@state() private _preferredPipeline?: string;
|
||||||
|
|
||||||
@query("#scroll-container") private _scrollContainer!: HTMLDivElement;
|
@query("#scroll-container") private _scrollContainer!: HTMLDivElement;
|
||||||
|
|
||||||
@query("#message-input") private _messageInput!: HaTextField;
|
@query("#message-input") private _messageInput!: HaTextField;
|
||||||
@ -84,6 +95,7 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
public async closeDialog(): Promise<void> {
|
public async closeDialog(): Promise<void> {
|
||||||
this._opened = false;
|
this._opened = false;
|
||||||
this._pipeline = undefined;
|
this._pipeline = undefined;
|
||||||
|
this._pipelines = undefined;
|
||||||
this._agentInfo = undefined;
|
this._agentInfo = undefined;
|
||||||
this._conversation = undefined;
|
this._conversation = undefined;
|
||||||
this._conversationId = null;
|
this._conversationId = null;
|
||||||
@ -107,15 +119,56 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
>
|
>
|
||||||
<div slot="heading">
|
<div slot="heading">
|
||||||
<ha-header-bar>
|
<ha-header-bar>
|
||||||
<span slot="title">
|
|
||||||
${this.hass.localize("ui.dialogs.voice_command.title")}
|
|
||||||
</span>
|
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
slot="navigationIcon"
|
slot="navigationIcon"
|
||||||
dialogAction="cancel"
|
dialogAction="cancel"
|
||||||
.label=${this.hass.localize("ui.common.close")}
|
.label=${this.hass.localize("ui.common.close")}
|
||||||
.path=${mdiClose}
|
.path=${mdiClose}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
|
<div slot="title">
|
||||||
|
${this.hass.localize("ui.dialogs.voice_command.title")}
|
||||||
|
<ha-button-menu
|
||||||
|
@opened=${this._loadPipelines}
|
||||||
|
@closed=${stopPropagation}
|
||||||
|
activatable
|
||||||
|
fixed
|
||||||
|
>
|
||||||
|
<ha-button slot="trigger">
|
||||||
|
${this._pipeline?.name}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="trailingIcon"
|
||||||
|
.path=${mdiChevronDown}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-button>
|
||||||
|
${this._pipelines?.map(
|
||||||
|
(pipeline) => html`<ha-list-item
|
||||||
|
?selected=${pipeline.id === this._pipelineId ||
|
||||||
|
(!this._pipelineId &&
|
||||||
|
pipeline.id === this._preferredPipeline)}
|
||||||
|
.pipeline=${pipeline.id}
|
||||||
|
@click=${this._selectPipeline}
|
||||||
|
.hasMeta=${pipeline.id === this._preferredPipeline}
|
||||||
|
>
|
||||||
|
${pipeline.name}${pipeline.id === this._preferredPipeline
|
||||||
|
? html`<ha-svg-icon
|
||||||
|
slot="meta"
|
||||||
|
.path=${mdiStar}
|
||||||
|
></ha-svg-icon>`
|
||||||
|
: nothing}
|
||||||
|
</ha-list-item>`
|
||||||
|
)}
|
||||||
|
${this.hass.user?.is_admin
|
||||||
|
? html`<li divider role="separator"></li>
|
||||||
|
<a href="/config/voice-assistants/assistants"
|
||||||
|
><ha-list-item @click=${this.closeDialog}
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.dialogs.voice_command.manage_assistants"
|
||||||
|
)}</ha-list-item
|
||||||
|
></a
|
||||||
|
>`
|
||||||
|
: nothing}
|
||||||
|
</ha-button-menu>
|
||||||
|
</div>
|
||||||
<a
|
<a
|
||||||
href=${documentationUrl(this.hass, "/docs/assist/")}
|
href=${documentationUrl(this.hass, "/docs/assist/")}
|
||||||
slot="actionItems"
|
slot="actionItems"
|
||||||
@ -211,13 +264,43 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _getPipeline() {
|
private async _getPipeline() {
|
||||||
this._pipeline = await getAssistPipeline(this.hass, this._pipelineId);
|
try {
|
||||||
|
this._pipeline = await getAssistPipeline(this.hass, this._pipelineId);
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e.code === "not_found") {
|
||||||
|
this._pipelineId = undefined;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._agentInfo = await getAgentInfo(
|
this._agentInfo = await getAgentInfo(
|
||||||
this.hass,
|
this.hass,
|
||||||
this._pipeline.conversation_engine
|
this._pipeline.conversation_engine
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _loadPipelines() {
|
||||||
|
if (this._pipelines) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { pipelines, preferred_pipeline } = await listAssistPipelines(
|
||||||
|
this.hass
|
||||||
|
);
|
||||||
|
this._pipelines = pipelines;
|
||||||
|
this._preferredPipeline = preferred_pipeline || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _selectPipeline(ev: CustomEvent) {
|
||||||
|
this._pipelineId = (ev.currentTarget as any).pipeline;
|
||||||
|
this._conversation = [
|
||||||
|
{
|
||||||
|
who: "hass",
|
||||||
|
text: this.hass.localize("ui.dialogs.voice_command.how_can_i_help"),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
await this.updateComplete;
|
||||||
|
this._scrollMessagesBottom();
|
||||||
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
super.updated(changedProps);
|
super.updated(changedProps);
|
||||||
if (changedProps.has("_conversation") || changedProps.has("results")) {
|
if (changedProps.has("_conversation") || changedProps.has("results")) {
|
||||||
@ -490,18 +573,50 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
ha-dialog {
|
ha-dialog {
|
||||||
--primary-action-button-flex: 1;
|
--primary-action-button-flex: 1;
|
||||||
--secondary-action-button-flex: 0;
|
--secondary-action-button-flex: 0;
|
||||||
--mdc-dialog-max-width: 450px;
|
--mdc-dialog-max-width: 500px;
|
||||||
--mdc-dialog-max-height: 500px;
|
--mdc-dialog-max-height: 500px;
|
||||||
--dialog-content-padding: 0;
|
--dialog-content-padding: 0;
|
||||||
}
|
}
|
||||||
ha-header-bar {
|
ha-header-bar {
|
||||||
--mdc-theme-on-primary: var(--primary-text-color);
|
--mdc-theme-on-primary: var(--primary-text-color);
|
||||||
--mdc-theme-primary: var(--mdc-theme-surface);
|
--mdc-theme-primary: var(--mdc-theme-surface);
|
||||||
|
--header-height: 64px;
|
||||||
}
|
}
|
||||||
ha-header-bar a {
|
ha-header-bar a {
|
||||||
color: var(--primary-text-color);
|
color: var(--primary-text-color);
|
||||||
}
|
}
|
||||||
|
div[slot="title"] {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
ha-button-menu {
|
||||||
|
--mdc-theme-on-primary: var(--text-primary-color);
|
||||||
|
--mdc-theme-primary: var(--primary-color);
|
||||||
|
margin: -8px 0 0 -8px;
|
||||||
|
}
|
||||||
|
ha-button-menu ha-button {
|
||||||
|
--mdc-theme-primary: var(--secondary-text-color);
|
||||||
|
--mdc-typography-button-text-transform: none;
|
||||||
|
--mdc-typography-button-font-size: unset;
|
||||||
|
--mdc-typography-button-font-weight: 400;
|
||||||
|
--mdc-typography-button-letter-spacing: var(
|
||||||
|
--mdc-typography-headline6-letter-spacing,
|
||||||
|
0.0125em
|
||||||
|
);
|
||||||
|
--mdc-typography-button-line-height: var(
|
||||||
|
--mdc-typography-headline6-line-height,
|
||||||
|
2rem
|
||||||
|
);
|
||||||
|
--button-height: auto;
|
||||||
|
}
|
||||||
|
ha-button-menu ha-button ha-svg-icon {
|
||||||
|
height: 28px;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
ha-button-menu a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
ha-textfield {
|
ha-textfield {
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -521,14 +636,20 @@ export class HaVoiceCommandDialog extends LitElement {
|
|||||||
padding: 4px;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
.attribution {
|
.attribution {
|
||||||
|
display: block;
|
||||||
color: var(--secondary-text-color);
|
color: var(--secondary-text-color);
|
||||||
|
padding-top: 4px;
|
||||||
|
margin-bottom: -8px;
|
||||||
}
|
}
|
||||||
.messages {
|
.messages {
|
||||||
display: block;
|
display: block;
|
||||||
height: 300px;
|
height: 400px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
@media all and (max-width: 450px), all and (max-height: 500px) {
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-max-width: 100%;
|
||||||
|
}
|
||||||
.messages {
|
.messages {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
@ -837,7 +837,8 @@
|
|||||||
"how_can_i_help": "How can I assist?",
|
"how_can_i_help": "How can I assist?",
|
||||||
"input_label": "Enter a request",
|
"input_label": "Enter a request",
|
||||||
"send_text": "Send text",
|
"send_text": "Send text",
|
||||||
"start_listening": "Start listening"
|
"start_listening": "Start listening",
|
||||||
|
"manage_assistants": "Manage assistants"
|
||||||
},
|
},
|
||||||
"generic": {
|
"generic": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user