Add UI for the script and automation modes (#6367)

This commit is contained in:
Bram Kragten 2020-07-13 10:52:37 +02:00 committed by GitHub
parent bd9b72fb22
commit 352214ba0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 187 additions and 6 deletions

View File

@ -20,6 +20,8 @@ export interface AutomationConfig {
trigger: Trigger[];
condition?: Condition[];
action: Action[];
mode?: "single" | "restart" | "queued" | "parallel";
max?: number;
}
export interface ForDict {

View File

@ -16,6 +16,8 @@ export interface ScriptEntity extends HassEntityBase {
export interface ScriptConfig {
alias: string;
sequence: Action[];
mode?: "single" | "restart" | "queued" | "parallel";
max?: number;
}
export interface EventAction {

View File

@ -1,5 +1,6 @@
import "@polymer/app-layout/app-header/app-header";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
import "@polymer/paper-input/paper-textarea";
import "../../../components/ha-icon-button";
import {
@ -43,6 +44,10 @@ import "./condition/ha-automation-condition";
import "./trigger/ha-automation-trigger";
import { HaDeviceTrigger } from "./trigger/types/ha-automation-trigger-device";
import { mdiContentSave } from "@mdi/js";
import { PaperListboxElement } from "@polymer/paper-listbox";
const MODES = ["parallel", "single", "restart", "queued"];
const MODES_MAX = ["queued", "parallel"];
export class HaAutomationEditor extends LitElement {
@property() public hass!: HomeAssistant;
@ -129,6 +134,57 @@ export class HaAutomationEditor extends LitElement {
.value=${this._config.description}
@value-changed=${this._valueChanged}
></paper-textarea>
<p>
${this.hass.localize(
"ui.panel.config.automation.editor.modes.description",
"documentation_link",
html`<a
href="https://www.home-assistant.io/docs/automation/#automation-modes"
target="_blank"
rel="noreferrer"
>${this.hass.localize(
"ui.panel.config.automation.editor.modes.documentation"
)}</a
>`
)}
</p>
<paper-dropdown-menu-light
.label=${this.hass.localize(
"ui.panel.config.automation.editor.modes.label"
)}
no-animations
>
<paper-listbox
slot="dropdown-content"
.selected=${this._config.mode
? MODES.indexOf(this._config.mode)
: 0}
@iron-select=${this._modeChanged}
>
${MODES.map(
(mode) => html`
<paper-item .mode=${mode}>
${this.hass.localize(
`ui.panel.config.automation.editor.modes.${mode}`
) || mode}
</paper-item>
`
)}
</paper-listbox>
</paper-dropdown-menu-light>
${this._config.mode &&
MODES_MAX.includes(this._config.mode)
? html` <paper-input
.label=${this.hass.localize(
`ui.panel.config.automation.editor.max.${this._config.mode}`
)}
type="number"
name="max"
.value=${this._config.max || "10"}
@value-changed=${this._valueChanged}
>
</paper-input>`
: html``}
</div>
${stateObj
? html`
@ -343,14 +399,28 @@ export class HaAutomationEditor extends LitElement {
this._entityId = automation?.entity_id;
}
private _modeChanged(ev: CustomEvent) {
const mode = ((ev.target as PaperListboxElement)?.selectedItem as any)
?.mode;
this._config = { ...this._config!, mode };
if (!MODES_MAX.includes(mode)) {
delete this._config.max;
}
this._dirty = true;
}
private _valueChanged(ev: CustomEvent) {
ev.stopPropagation();
const name = (ev.target as any)?.name;
const target = ev.target as any;
const name = target.name;
if (!name) {
return;
}
const newVal = ev.detail.value;
let newVal = ev.detail.value;
if (target.type === "number") {
newVal = Number(newVal);
}
if ((this._config![name] || "") === newVal) {
return;
}
@ -453,6 +523,9 @@ export class HaAutomationEditor extends LitElement {
span[slot="introduction"] a {
color: var(--primary-color);
}
p {
margin-bottom: 0;
}
ha-entity-toggle {
margin-right: 8px;
}

View File

@ -1,4 +1,5 @@
import "@polymer/app-layout/app-header/app-header";
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
import "@polymer/app-layout/app-toolbar/app-toolbar";
import "../../../components/ha-icon-button";
import {
@ -32,6 +33,10 @@ import "../ha-config-section";
import { configSections } from "../ha-panel-config";
import "../../../components/ha-svg-icon";
import { mdiContentSave } from "@mdi/js";
import { PaperListboxElement } from "@polymer/paper-listbox";
const MODES = ["single", "restart", "queued", "parallel"];
const MODES_MAX = ["queued", "parallel"];
export class HaScriptEditor extends LitElement {
@property() public hass!: HomeAssistant;
@ -105,6 +110,58 @@ export class HaScriptEditor extends LitElement {
@value-changed=${this._valueChanged}
>
</paper-input>
<p>
${this.hass.localize(
"ui.panel.config.script.editor.modes.description",
"documentation_link",
html`<a
href="https://www.home-assistant.io/integrations/script/#script-modes"
target="_blank"
rel="noreferrer"
>${this.hass.localize(
"ui.panel.config.script.editor.modes.documentation"
)}</a
>`
)}
</p>
<paper-dropdown-menu-light
.label=${this.hass.localize(
"ui.panel.config.script.editor.modes.label"
)}
no-animations
>
<paper-listbox
slot="dropdown-content"
.selected=${this._config.mode
? MODES.indexOf(this._config.mode)
: 0}
@iron-select=${this._modeChanged}
>
${MODES.map(
(mode) => html`
<paper-item .mode=${mode}>
${this.hass.localize(
`ui.panel.config.script.editor.modes.${mode}`
) || mode}
</paper-item>
`
)}
</paper-listbox>
</paper-dropdown-menu-light>
${this._config.mode &&
MODES_MAX.includes(this._config.mode)
? html` <paper-input
.label=${this.hass.localize(
`ui.panel.config.script.editor.max.${this._config.mode}`
)}
type="number"
name="max"
.value=${this._config.max || "10"}
@value-changed=${this._valueChanged}
>
</paper-input>`
: html``}
</div>
</ha-card>
</ha-config-section>
@ -216,14 +273,28 @@ export class HaScriptEditor extends LitElement {
}
}
private _modeChanged(ev: CustomEvent) {
const mode = ((ev.target as PaperListboxElement)?.selectedItem as any)
?.mode;
this._config = { ...this._config!, mode };
if (!MODES_MAX.includes(mode)) {
delete this._config.max;
}
this._dirty = true;
}
private _valueChanged(ev: CustomEvent) {
ev.stopPropagation();
const name = (ev.target as any)?.name;
const target = ev.target as any;
const name = target.name;
if (!name) {
return;
}
const newVal = ev.detail.value;
let newVal = ev.detail.value;
if (target.type === "number") {
newVal = Number(newVal);
}
if ((this._config![name] || "") === newVal) {
return;
}
@ -292,6 +363,9 @@ export class HaScriptEditor extends LitElement {
ha-card {
overflow: hidden;
}
p {
margin-bottom: 0;
}
.errors {
padding: 20px;
font-weight: bold;

View File

@ -100,6 +100,10 @@ export const haStyle = css`
line-height: var(--paper-font-subhead_-_line-height);
}
a {
color: var(--primary-color);
}
.secondary {
color: var(--secondary-text-color);
}

View File

@ -841,6 +841,19 @@
"label": "Description",
"placeholder": "Optional description"
},
"modes": {
"label": "Mode",
"description": "The mode controls what happens when the automation is triggered while the actions are still running from a previous trigger. Check the {documentation_link} for more info.",
"documentation": "automation documentation",
"single": "Single",
"restart": "Restart",
"queued": "Queued",
"parallel": "Parallel (default)"
},
"max": {
"queued": "Queue length",
"parallel": "Max number of parallel runs"
},
"edit_yaml": "Edit as YAML",
"edit_ui": "Edit with UI",
"triggers": {
@ -1068,6 +1081,19 @@
"introduction": "Use scripts to execute a sequence of actions.",
"header": "Script: {name}",
"default_name": "New Script",
"modes": {
"label": "Mode",
"description": "The mode controls what happens when script is invoked while it is still running from one or more previous invocations. Check the {documentation_link} for more info.",
"documentation": "script documentation",
"single": "Single (default)",
"restart": "Restart",
"queued": "Queued",
"parallel": "Parallel"
},
"max": {
"queued": "Queue length",
"parallel": "Max number of parallel runs"
},
"load_error_not_editable": "Only scripts inside scripts.yaml are editable.",
"delete_confirm": "Are you sure you want to delete this script?",
"delete_script": "Delete script",