mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 07:16:39 +00:00
Add UI for new script functions (#6491)
This commit is contained in:
parent
ca171afe6f
commit
a2153bc6aa
@ -58,6 +58,31 @@ export interface WaitAction {
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
export interface RepeatAction {
|
||||
repeat: CountRepeat | WhileRepeat | UntilRepeat;
|
||||
}
|
||||
|
||||
interface BaseRepeat {
|
||||
sequence: Action[];
|
||||
}
|
||||
|
||||
export interface CountRepeat extends BaseRepeat {
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface WhileRepeat extends BaseRepeat {
|
||||
while: Condition[];
|
||||
}
|
||||
|
||||
export interface UntilRepeat extends BaseRepeat {
|
||||
until: Condition[];
|
||||
}
|
||||
|
||||
export interface ChooseAction {
|
||||
choose: [{ conditions: Condition[]; sequence: Action[] }];
|
||||
default?: Action[];
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| EventAction
|
||||
| DeviceAction
|
||||
@ -65,7 +90,9 @@ export type Action =
|
||||
| Condition
|
||||
| DelayAction
|
||||
| SceneAction
|
||||
| WaitAction;
|
||||
| WaitAction
|
||||
| RepeatAction
|
||||
| ChooseAction;
|
||||
|
||||
export const triggerScript = (
|
||||
hass: HomeAssistant,
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
LitElement,
|
||||
property,
|
||||
internalProperty,
|
||||
PropertyValues,
|
||||
} from "lit-element";
|
||||
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
@ -29,6 +30,8 @@ import "./types/ha-automation-action-event";
|
||||
import "./types/ha-automation-action-scene";
|
||||
import "./types/ha-automation-action-service";
|
||||
import "./types/ha-automation-action-wait_template";
|
||||
import "./types/ha-automation-action-repeat";
|
||||
import "./types/ha-automation-action-choose";
|
||||
import { handleStructError } from "../../../lovelace/common/structs/handle-errors";
|
||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||
import { haStyle } from "../../../../resources/styles";
|
||||
@ -41,6 +44,8 @@ const OPTIONS = [
|
||||
"scene",
|
||||
"service",
|
||||
"wait_template",
|
||||
"repeat",
|
||||
"choose",
|
||||
];
|
||||
|
||||
const getType = (action: Action) => {
|
||||
@ -96,6 +101,16 @@ export default class HaAutomationActionRow extends LitElement {
|
||||
|
||||
@internalProperty() private _yamlMode = false;
|
||||
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
if (!changedProperties.has("action")) {
|
||||
return;
|
||||
}
|
||||
this._uiModeAvailable = Boolean(getType(this.action));
|
||||
if (!this._uiModeAvailable && !this._yamlMode) {
|
||||
this._yamlMode = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const type = getType(this.action);
|
||||
const selected = type ? OPTIONS.indexOf(type) : -1;
|
||||
|
@ -0,0 +1,176 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import {
|
||||
customElement,
|
||||
LitElement,
|
||||
property,
|
||||
CSSResult,
|
||||
css,
|
||||
} from "lit-element";
|
||||
import { html } from "lit-html";
|
||||
import { Action, ChooseAction } from "../../../../../data/script";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { ActionElement } from "../ha-automation-action-row";
|
||||
import "../../condition/ha-automation-condition-editor";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import "../ha-automation-action";
|
||||
import { Condition } from "../../../../../data/automation";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
import { mdiDelete } from "@mdi/js";
|
||||
|
||||
@customElement("ha-automation-action-choose")
|
||||
export class HaChooseAction extends LitElement implements ActionElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public action!: ChooseAction;
|
||||
|
||||
public static get defaultConfig() {
|
||||
return { choose: [{ conditions: [], sequence: [] }], default: [] };
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const action = this.action;
|
||||
|
||||
return html`
|
||||
${action.choose.map(
|
||||
(option, idx) => html`<ha-card>
|
||||
<mwc-icon-button
|
||||
.idx=${idx}
|
||||
@click=${this._removeOption}
|
||||
title=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.remove_option"
|
||||
)}
|
||||
>
|
||||
<ha-svg-icon path=${mdiDelete}></ha-svg-icon>
|
||||
</mwc-icon-button>
|
||||
<div class="card-content">
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.option",
|
||||
"number",
|
||||
idx + 1
|
||||
)}:
|
||||
</h2>
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.conditions"
|
||||
)}:
|
||||
</h3>
|
||||
<ha-automation-condition
|
||||
.conditions=${option.conditions}
|
||||
.hass=${this.hass}
|
||||
.idx=${idx}
|
||||
@value-changed=${this._conditionChanged}
|
||||
></ha-automation-condition>
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.sequence"
|
||||
)}:
|
||||
</h3>
|
||||
<ha-automation-action
|
||||
.actions=${option.sequence}
|
||||
.hass=${this.hass}
|
||||
.idx=${idx}
|
||||
@value-changed=${this._actionChanged}
|
||||
></ha-automation-action>
|
||||
</div>
|
||||
</ha-card>`
|
||||
)}
|
||||
<ha-card>
|
||||
<div class="card-actions add-card">
|
||||
<mwc-button @click=${this._addOption}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.add_option"
|
||||
)}
|
||||
</mwc-button>
|
||||
</div>
|
||||
</ha-card>
|
||||
<h2>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.choose.default"
|
||||
)}:
|
||||
</h2>
|
||||
<ha-automation-action
|
||||
.actions=${action.default || []}
|
||||
@value-changed=${this._defaultChanged}
|
||||
.hass=${this.hass}
|
||||
></ha-automation-action>
|
||||
`;
|
||||
}
|
||||
|
||||
private _conditionChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const value = ev.detail.value as Condition[];
|
||||
const index = (ev.target as any).idx;
|
||||
const choose = [...this.action.choose];
|
||||
choose[index].conditions = value;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.action, choose },
|
||||
});
|
||||
}
|
||||
|
||||
private _actionChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const value = ev.detail.value as Action[];
|
||||
const index = (ev.target as any).idx;
|
||||
const choose = [...this.action.choose];
|
||||
choose[index].sequence = value;
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.action, choose },
|
||||
});
|
||||
}
|
||||
|
||||
private _addOption() {
|
||||
const choose = [...this.action.choose];
|
||||
choose.push({ conditions: [], sequence: [] });
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.action, choose },
|
||||
});
|
||||
}
|
||||
|
||||
private _removeOption(ev: CustomEvent) {
|
||||
const index = (ev.currentTarget as any).idx;
|
||||
const choose = [...this.action.choose];
|
||||
choose.splice(index, 1);
|
||||
fireEvent(this, "value-changed", {
|
||||
value: { ...this.action, choose },
|
||||
});
|
||||
}
|
||||
|
||||
private _defaultChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const value = ev.detail.value as Action[];
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
...this.action,
|
||||
default: value,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
haStyle,
|
||||
css`
|
||||
ha-card {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.add-card mwc-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
mwc-icon-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
padding: 4px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-automation-action-choose": HaChooseAction;
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
import "@polymer/paper-input/paper-input";
|
||||
import { customElement, LitElement, property, CSSResult } from "lit-element";
|
||||
import { html } from "lit-html";
|
||||
import {
|
||||
RepeatAction,
|
||||
Action,
|
||||
CountRepeat,
|
||||
WhileRepeat,
|
||||
UntilRepeat,
|
||||
} from "../../../../../data/script";
|
||||
import { HomeAssistant } from "../../../../../types";
|
||||
import { ActionElement } from "../ha-automation-action-row";
|
||||
import "../../condition/ha-automation-condition-editor";
|
||||
import type { PaperListboxElement } from "@polymer/paper-listbox";
|
||||
import "@polymer/paper-listbox/paper-listbox";
|
||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||
import "../ha-automation-action";
|
||||
import { Condition } from "../../../../lovelace/common/validate-condition";
|
||||
import { haStyle } from "../../../../../resources/styles";
|
||||
|
||||
const OPTIONS = ["count", "while", "until"];
|
||||
|
||||
const getType = (action) => {
|
||||
return OPTIONS.find((option) => option in action);
|
||||
};
|
||||
|
||||
@customElement("ha-automation-action-repeat")
|
||||
export class HaRepeatAction extends LitElement implements ActionElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public action!: RepeatAction;
|
||||
|
||||
public static get defaultConfig() {
|
||||
return { repeat: { count: 2, sequence: [] } };
|
||||
}
|
||||
|
||||
protected render() {
|
||||
const action = this.action.repeat;
|
||||
|
||||
const type = getType(action);
|
||||
const selected = type ? OPTIONS.indexOf(type) : -1;
|
||||
|
||||
return html`
|
||||
<paper-dropdown-menu-light
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.repeat.type_select"
|
||||
)}
|
||||
no-animations
|
||||
>
|
||||
<paper-listbox
|
||||
slot="dropdown-content"
|
||||
.selected=${selected}
|
||||
@iron-select=${this._typeChanged}
|
||||
>
|
||||
${OPTIONS.map(
|
||||
(opt) => html`
|
||||
<paper-item .action=${opt}>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.actions.type.repeat.type.${opt}.label`
|
||||
)}
|
||||
</paper-item>
|
||||
`
|
||||
)}
|
||||
</paper-listbox>
|
||||
</paper-dropdown-menu-light>
|
||||
${type === "count"
|
||||
? html`<paper-input
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.repeat.type.count.label"
|
||||
)}
|
||||
name="count"
|
||||
.value=${(action as CountRepeat).count || "0"}
|
||||
@value-changed=${this._countChanged}
|
||||
></paper-input>`
|
||||
: ""}
|
||||
${type === "while"
|
||||
? html` <h3>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.actions.type.repeat.type.while.conditions`
|
||||
)}:
|
||||
</h3>
|
||||
<ha-automation-condition
|
||||
.conditions=${(action as WhileRepeat).while || []}
|
||||
.hass=${this.hass}
|
||||
@value-changed=${this._conditionChanged}
|
||||
></ha-automation-condition>`
|
||||
: ""}
|
||||
${type === "until"
|
||||
? html` <h3>
|
||||
${this.hass.localize(
|
||||
`ui.panel.config.automation.editor.actions.type.repeat.type.until.conditions`
|
||||
)}:
|
||||
</h3>
|
||||
<ha-automation-condition
|
||||
.conditions=${(action as UntilRepeat).until || []}
|
||||
.hass=${this.hass}
|
||||
@value-changed=${this._conditionChanged}
|
||||
></ha-automation-condition>`
|
||||
: ""}
|
||||
<h3>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.actions.type.repeat.sequence"
|
||||
)}:
|
||||
</h3>
|
||||
<ha-automation-action
|
||||
.actions=${action.sequence}
|
||||
@value-changed=${this._actionChanged}
|
||||
.hass=${this.hass}
|
||||
></ha-automation-action>
|
||||
`;
|
||||
}
|
||||
|
||||
private _typeChanged(ev: CustomEvent) {
|
||||
const type = ((ev.target as PaperListboxElement)?.selectedItem as any)
|
||||
?.action;
|
||||
|
||||
if (!type || type === getType(this.action.repeat)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = type === "count" ? 2 : [];
|
||||
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
repeat: { [type]: value, sequence: this.action.repeat.sequence },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _conditionChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const value = ev.detail.value as Condition[];
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
repeat: {
|
||||
...this.action.repeat,
|
||||
[getType(this.action.repeat)!]: value,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _actionChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const value = ev.detail.value as Action[];
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
repeat: {
|
||||
...this.action.repeat,
|
||||
sequence: value,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _countChanged(ev: CustomEvent): void {
|
||||
const newVal = ev.detail.value;
|
||||
if ((this.action.repeat as CountRepeat).count === newVal) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "value-changed", {
|
||||
value: {
|
||||
repeat: {
|
||||
...this.action.repeat,
|
||||
count: newVal,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
return haStyle;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-automation-action-repeat": HaRepeatAction;
|
||||
}
|
||||
}
|
@ -106,9 +106,9 @@ export class HaIntegrationCard extends LitElement {
|
||||
@error=${this._onImageError}
|
||||
@load=${this._onImageLoad}
|
||||
/>
|
||||
<h1>
|
||||
<h2>
|
||||
${domainToName(this.hass.localize, this.domain)}
|
||||
</h1>
|
||||
</h2>
|
||||
</div>
|
||||
<paper-listbox>
|
||||
${this.items.map(
|
||||
@ -156,12 +156,12 @@ export class HaIntegrationCard extends LitElement {
|
||||
@load=${this._onImageLoad}
|
||||
/>
|
||||
</div>
|
||||
<h1>
|
||||
${item.localized_domain_name}
|
||||
</h1>
|
||||
<h2>
|
||||
${item.localized_domain_name === item.title ? "" : item.title}
|
||||
${item.localized_domain_name}
|
||||
</h2>
|
||||
<h3>
|
||||
${item.localized_domain_name === item.title ? "" : item.title}
|
||||
</h3>
|
||||
${devices.length || entities.length
|
||||
? html`
|
||||
<div>
|
||||
|
@ -79,6 +79,17 @@ export const haStyle = css`
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: var(--paper-font-headline_-_font-family);
|
||||
-webkit-font-smoothing: var(--paper-font-headline_-_-webkit-font-smoothing);
|
||||
white-space: var(--paper-font-headline_-_white-space);
|
||||
overflow: var(--paper-font-headline_-_overflow);
|
||||
text-overflow: var(--paper-font-headline_-_text-overflow);
|
||||
font-size: var(--paper-font-headline_-_font-size);
|
||||
font-weight: var(--paper-font-headline_-_font-weight);
|
||||
line-height: var(--paper-font-headline_-_line-height);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-family: var(--paper-font-title_-_font-family);
|
||||
-webkit-font-smoothing: var(--paper-font-title_-_-webkit-font-smoothing);
|
||||
white-space: var(--paper-font-title_-_white-space);
|
||||
@ -89,7 +100,7 @@ export const haStyle = css`
|
||||
line-height: var(--paper-font-title_-_line-height);
|
||||
}
|
||||
|
||||
h2 {
|
||||
h3 {
|
||||
font-family: var(--paper-font-subhead_-_font-family);
|
||||
-webkit-font-smoothing: var(--paper-font-subhead_-_-webkit-font-smoothing);
|
||||
white-space: var(--paper-font-subhead_-_white-space);
|
||||
|
@ -1058,6 +1058,31 @@
|
||||
},
|
||||
"scene": {
|
||||
"label": "Activate scene"
|
||||
},
|
||||
"repeat": {
|
||||
"label": "Repeat",
|
||||
"type_select": "Repeat type",
|
||||
"type": {
|
||||
"count": { "label": "Count" },
|
||||
"while": {
|
||||
"label": "While",
|
||||
"conditions": "While conditions"
|
||||
},
|
||||
"until": {
|
||||
"label": "Until",
|
||||
"conditions": "Until conditions"
|
||||
}
|
||||
},
|
||||
"sequence": "Actions"
|
||||
},
|
||||
"choose": {
|
||||
"label": "Choose",
|
||||
"default": "Default actions",
|
||||
"option": "Option {number}",
|
||||
"add_option": "Add option",
|
||||
"remove_option": "Remove option",
|
||||
"conditions": "Conditions",
|
||||
"sequence": "Actions"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user