mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-10 01:47:46 +00:00
Automation editor tweaks (#6713)
Co-authored-by: Joakim Sørensen <joasoe@gmail.com>
This commit is contained in:
parent
80224e6974
commit
de7ffb10cb
178
src/components/entity/ha-entity-attribute-picker.ts
Normal file
178
src/components/entity/ha-entity-attribute-picker.ts
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
|
import "@vaadin/vaadin-combo-box/theme/material/vaadin-combo-box-light";
|
||||||
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
PropertyValues,
|
||||||
|
query,
|
||||||
|
TemplateResult,
|
||||||
|
} from "lit-element";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
|
import { PolymerChangedEvent } from "../../polymer-types";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import "../ha-icon-button";
|
||||||
|
import "./state-badge";
|
||||||
|
|
||||||
|
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||||
|
|
||||||
|
const rowRenderer = (root: HTMLElement, _owner, model: { item: string }) => {
|
||||||
|
if (!root.firstElementChild) {
|
||||||
|
root.innerHTML = `
|
||||||
|
<style>
|
||||||
|
paper-item {
|
||||||
|
margin: -10px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<paper-item></paper-item>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
root.querySelector("paper-item")!.textContent = model.item;
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("ha-entity-attribute-picker")
|
||||||
|
class HaEntityAttributePicker extends LitElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public entityId?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public autofocus = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "allow-custom-value" })
|
||||||
|
public allowCustomValue;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public value?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) private _opened = false;
|
||||||
|
|
||||||
|
@query("vaadin-combo-box-light") private _comboBox!: HTMLElement;
|
||||||
|
|
||||||
|
protected shouldUpdate(changedProps: PropertyValues) {
|
||||||
|
return !(!changedProps.has("_opened") && this._opened);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected updated(changedProps: PropertyValues) {
|
||||||
|
if (changedProps.has("_opened") && this._opened) {
|
||||||
|
const state = this.entityId ? this.hass.states[this.entityId] : undefined;
|
||||||
|
(this._comboBox as any).items = state
|
||||||
|
? Object.keys(state.attributes)
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.hass) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<vaadin-combo-box-light
|
||||||
|
.value=${this._value}
|
||||||
|
.allowCustomValue=${this.allowCustomValue}
|
||||||
|
.renderer=${rowRenderer}
|
||||||
|
@opened-changed=${this._openedChanged}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
>
|
||||||
|
<paper-input
|
||||||
|
.autofocus=${this.autofocus}
|
||||||
|
.label=${this.label ??
|
||||||
|
this.hass.localize(
|
||||||
|
"ui.components.entity.entity-attribute-picker.attribute"
|
||||||
|
)}
|
||||||
|
.value=${this._value}
|
||||||
|
.disabled=${this.disabled || !this.entityId}
|
||||||
|
class="input"
|
||||||
|
autocapitalize="none"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
spellcheck="false"
|
||||||
|
>
|
||||||
|
${this.value
|
||||||
|
? html`
|
||||||
|
<ha-icon-button
|
||||||
|
aria-label=${this.hass.localize(
|
||||||
|
"ui.components.entity.entity-picker.clear"
|
||||||
|
)}
|
||||||
|
slot="suffix"
|
||||||
|
class="clear-button"
|
||||||
|
icon="hass:close"
|
||||||
|
@click=${this._clearValue}
|
||||||
|
no-ripple
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</ha-icon-button>
|
||||||
|
`
|
||||||
|
: ""}
|
||||||
|
|
||||||
|
<ha-icon-button
|
||||||
|
aria-label=${this.hass.localize(
|
||||||
|
"ui.components.entity.entity-attribute-picker.show_attributes"
|
||||||
|
)}
|
||||||
|
slot="suffix"
|
||||||
|
class="toggle-button"
|
||||||
|
.icon=${this._opened ? "hass:menu-up" : "hass:menu-down"}
|
||||||
|
>
|
||||||
|
Toggle
|
||||||
|
</ha-icon-button>
|
||||||
|
</paper-input>
|
||||||
|
</vaadin-combo-box-light>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _clearValue(ev: Event) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this._setValue("");
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _value() {
|
||||||
|
return this.value || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private _openedChanged(ev: PolymerChangedEvent<boolean>) {
|
||||||
|
this._opened = ev.detail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: PolymerChangedEvent<string>) {
|
||||||
|
const newValue = ev.detail.value;
|
||||||
|
if (newValue !== this._value) {
|
||||||
|
this._setValue(newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setValue(value: string) {
|
||||||
|
this.value = value;
|
||||||
|
setTimeout(() => {
|
||||||
|
fireEvent(this, "value-changed", { value });
|
||||||
|
fireEvent(this, "change");
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResult {
|
||||||
|
return css`
|
||||||
|
paper-input > ha-icon-button {
|
||||||
|
--mdc-icon-button-size: 24px;
|
||||||
|
padding: 0px 2px;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-entity-attribute-picker": HaEntityAttributePicker;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
import "../ha-icon-button";
|
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-item/paper-icon-item";
|
import "@polymer/paper-item/paper-icon-item";
|
||||||
import "@polymer/paper-item/paper-item-body";
|
import "@polymer/paper-item/paper-item-body";
|
||||||
@ -20,6 +19,7 @@ import { computeDomain } from "../../common/entity/compute_domain";
|
|||||||
import { computeStateName } from "../../common/entity/compute_state_name";
|
import { computeStateName } from "../../common/entity/compute_state_name";
|
||||||
import { PolymerChangedEvent } from "../../polymer-types";
|
import { PolymerChangedEvent } from "../../polymer-types";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
|
import "../ha-icon-button";
|
||||||
import "./state-badge";
|
import "./state-badge";
|
||||||
|
|
||||||
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
export type HaEntityPickerEntityFilterFunc = (entityId: HassEntity) => boolean;
|
||||||
@ -95,6 +95,8 @@ class HaEntityPicker extends LitElement {
|
|||||||
|
|
||||||
@query("vaadin-combo-box-light") private _comboBox!: HTMLElement;
|
@query("vaadin-combo-box-light") private _comboBox!: HTMLElement;
|
||||||
|
|
||||||
|
private _initedStates = false;
|
||||||
|
|
||||||
private _getStates = memoizeOne(
|
private _getStates = memoizeOne(
|
||||||
(
|
(
|
||||||
_opened: boolean,
|
_opened: boolean,
|
||||||
@ -148,11 +150,18 @@ class HaEntityPicker extends LitElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
protected shouldUpdate(changedProps: PropertyValues) {
|
protected shouldUpdate(changedProps: PropertyValues) {
|
||||||
|
if (
|
||||||
|
changedProps.has("value") ||
|
||||||
|
changedProps.has("label") ||
|
||||||
|
changedProps.has("disabled")
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return !(!changedProps.has("_opened") && this._opened);
|
return !(!changedProps.has("_opened") && this._opened);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues) {
|
protected updated(changedProps: PropertyValues) {
|
||||||
if (changedProps.has("_opened") && this._opened) {
|
if (!this._initedStates || (changedProps.has("_opened") && this._opened)) {
|
||||||
const states = this._getStates(
|
const states = this._getStates(
|
||||||
this._opened,
|
this._opened,
|
||||||
this.hass,
|
this.hass,
|
||||||
@ -162,6 +171,7 @@ class HaEntityPicker extends LitElement {
|
|||||||
this.includeDeviceClasses
|
this.includeDeviceClasses
|
||||||
);
|
);
|
||||||
(this._comboBox as any).items = states;
|
(this._comboBox as any).items = states;
|
||||||
|
this._initedStates = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +179,6 @@ class HaEntityPicker extends LitElement {
|
|||||||
if (!this.hass) {
|
if (!this.hass) {
|
||||||
return html``;
|
return html``;
|
||||||
}
|
}
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<vaadin-combo-box-light
|
<vaadin-combo-box-light
|
||||||
item-value-path="entity_id"
|
item-value-path="entity_id"
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
import { HomeAssistant, Context } from "../types";
|
import { Context, HomeAssistant } from "../types";
|
||||||
import { DeviceCondition, DeviceTrigger } from "./device_automation";
|
import { DeviceCondition, DeviceTrigger } from "./device_automation";
|
||||||
import { Action } from "./script";
|
import { Action } from "./script";
|
||||||
|
|
||||||
@ -15,6 +15,7 @@ export interface AutomationEntity extends HassEntityBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationConfig {
|
export interface AutomationConfig {
|
||||||
|
id?: string;
|
||||||
alias: string;
|
alias: string;
|
||||||
description: string;
|
description: string;
|
||||||
trigger: Trigger[];
|
trigger: Trigger[];
|
||||||
@ -32,7 +33,8 @@ export interface ForDict {
|
|||||||
|
|
||||||
export interface StateTrigger {
|
export interface StateTrigger {
|
||||||
platform: "state";
|
platform: "state";
|
||||||
entity_id?: string;
|
entity_id: string;
|
||||||
|
attribute?: string;
|
||||||
from?: string | number;
|
from?: string | number;
|
||||||
to?: string | number;
|
to?: string | number;
|
||||||
for?: string | number | ForDict;
|
for?: string | number | ForDict;
|
||||||
@ -59,6 +61,7 @@ export interface HassTrigger {
|
|||||||
export interface NumericStateTrigger {
|
export interface NumericStateTrigger {
|
||||||
platform: "numeric_state";
|
platform: "numeric_state";
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
|
attribute?: string;
|
||||||
above?: number;
|
above?: number;
|
||||||
below?: number;
|
below?: number;
|
||||||
value_template?: string;
|
value_template?: string;
|
||||||
@ -136,12 +139,14 @@ export interface LogicalCondition {
|
|||||||
export interface StateCondition {
|
export interface StateCondition {
|
||||||
condition: "state";
|
condition: "state";
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
|
attribute?: string;
|
||||||
state: string | number;
|
state: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NumericStateCondition {
|
export interface NumericStateCondition {
|
||||||
condition: "numeric_state";
|
condition: "numeric_state";
|
||||||
entity_id: string;
|
entity_id: string;
|
||||||
|
attribute?: string;
|
||||||
above?: number;
|
above?: number;
|
||||||
below?: number;
|
below?: number;
|
||||||
value_template?: string;
|
value_template?: string;
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
import { computeObjectId } from "../common/entity/compute_object_id";
|
import { computeObjectId } from "../common/entity/compute_object_id";
|
||||||
import { navigate } from "../common/navigate";
|
import { navigate } from "../common/navigate";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
import { Condition } from "./automation";
|
import { Condition, Trigger } from "./automation";
|
||||||
|
|
||||||
export const MODES = ["single", "restart", "queued", "parallel"];
|
export const MODES = ["single", "restart", "queued", "parallel"];
|
||||||
export const MODES_MAX = ["queued", "parallel"];
|
export const MODES_MAX = ["queued", "parallel"];
|
||||||
@ -56,6 +56,13 @@ export interface SceneAction {
|
|||||||
export interface WaitAction {
|
export interface WaitAction {
|
||||||
wait_template: string;
|
wait_template: string;
|
||||||
timeout?: number;
|
timeout?: number;
|
||||||
|
continue_on_timeout?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WaitForTriggerAction {
|
||||||
|
wait_for_trigger: Trigger[];
|
||||||
|
timeout?: number;
|
||||||
|
continue_on_timeout?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RepeatAction {
|
export interface RepeatAction {
|
||||||
@ -91,6 +98,7 @@ export type Action =
|
|||||||
| DelayAction
|
| DelayAction
|
||||||
| SceneAction
|
| SceneAction
|
||||||
| WaitAction
|
| WaitAction
|
||||||
|
| WaitForTriggerAction
|
||||||
| RepeatAction
|
| RepeatAction
|
||||||
| ChooseAction;
|
| ChooseAction;
|
||||||
|
|
||||||
|
@ -5,19 +5,19 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
|
import { fireEvent } from "../../common/dom/fire_event";
|
||||||
import "../../components/ha-dialog";
|
import "../../components/ha-dialog";
|
||||||
import "../../components/ha-switch";
|
import "../../components/ha-switch";
|
||||||
import { PolymerChangedEvent } from "../../polymer-types";
|
import { PolymerChangedEvent } from "../../polymer-types";
|
||||||
import { haStyleDialog } from "../../resources/styles";
|
import { haStyleDialog } from "../../resources/styles";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import { DialogParams } from "./show-dialog-box";
|
import { DialogParams } from "./show-dialog-box";
|
||||||
import { fireEvent } from "../../common/dom/fire_event";
|
|
||||||
|
|
||||||
@customElement("dialog-box")
|
@customElement("dialog-box")
|
||||||
class DialogBox extends LitElement {
|
class DialogBox extends LitElement {
|
||||||
@ -114,8 +114,8 @@ class DialogBox extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _dismiss(): void {
|
private _dismiss(): void {
|
||||||
if (this._params!.cancel) {
|
if (this._params?.cancel) {
|
||||||
this._params!.cancel();
|
this._params.cancel();
|
||||||
}
|
}
|
||||||
this._close();
|
this._close();
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import "@material/mwc-icon-button";
|
import "@material/mwc-icon-button";
|
||||||
import "../../../../components/ha-button-menu";
|
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||||
import "../../../../components/ha-svg-icon";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import { mdiDotsVertical, mdiArrowUp, mdiArrowDown } from "@mdi/js";
|
import { mdiArrowDown, mdiArrowUp, mdiDotsVertical } from "@mdi/js";
|
||||||
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import type { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
|
import type { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
|
||||||
@ -12,29 +11,31 @@ import {
|
|||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import "../../../../components/ha-button-menu";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-svg-icon";
|
||||||
import type { Action } from "../../../../data/script";
|
import type { Action } from "../../../../data/script";
|
||||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
|
import { haStyle } from "../../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
import { handleStructError } from "../../../lovelace/common/structs/handle-errors";
|
||||||
|
import "./types/ha-automation-action-choose";
|
||||||
import "./types/ha-automation-action-condition";
|
import "./types/ha-automation-action-condition";
|
||||||
import "./types/ha-automation-action-delay";
|
import "./types/ha-automation-action-delay";
|
||||||
import "./types/ha-automation-action-device_id";
|
import "./types/ha-automation-action-device_id";
|
||||||
import "./types/ha-automation-action-event";
|
import "./types/ha-automation-action-event";
|
||||||
|
import "./types/ha-automation-action-repeat";
|
||||||
import "./types/ha-automation-action-scene";
|
import "./types/ha-automation-action-scene";
|
||||||
import "./types/ha-automation-action-service";
|
import "./types/ha-automation-action-service";
|
||||||
|
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-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";
|
|
||||||
|
|
||||||
const OPTIONS = [
|
const OPTIONS = [
|
||||||
"condition",
|
"condition",
|
||||||
@ -44,6 +45,7 @@ const OPTIONS = [
|
|||||||
"scene",
|
"scene",
|
||||||
"service",
|
"service",
|
||||||
"wait_template",
|
"wait_template",
|
||||||
|
"wait_for_trigger",
|
||||||
"repeat",
|
"repeat",
|
||||||
"choose",
|
"choose",
|
||||||
];
|
];
|
||||||
@ -166,7 +168,7 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
"ui.panel.config.automation.editor.edit_yaml"
|
"ui.panel.config.automation.editor.edit_yaml"
|
||||||
)}
|
)}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item disabled>
|
<mwc-list-item>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.actions.duplicate"
|
"ui.panel.config.automation.editor.actions.duplicate"
|
||||||
)}
|
)}
|
||||||
@ -261,6 +263,7 @@ export default class HaAutomationActionRow extends LitElement {
|
|||||||
this._switchYamlMode();
|
this._switchYamlMode();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
fireEvent(this, "duplicate");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this._onDelete();
|
this._onDelete();
|
||||||
|
@ -28,6 +28,7 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
.index=${idx}
|
.index=${idx}
|
||||||
.totalActions=${this.actions.length}
|
.totalActions=${this.actions.length}
|
||||||
.action=${action}
|
.action=${action}
|
||||||
|
@duplicate=${this._duplicateAction}
|
||||||
@move-action=${this._move}
|
@move-action=${this._move}
|
||||||
@value-changed=${this._actionChanged}
|
@value-changed=${this._actionChanged}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
@ -78,6 +79,14 @@ export default class HaAutomationAction extends LitElement {
|
|||||||
fireEvent(this, "value-changed", { value: actions });
|
fireEvent(this, "value-changed", { value: actions });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _duplicateAction(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const index = (ev.target as any).index;
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: this.actions.concat(this.actions[index]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResult {
|
||||||
return css`
|
return css`
|
||||||
ha-automation-action-row,
|
ha-automation-action-row,
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
|
import { mdiDelete } from "@mdi/js";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import {
|
import {
|
||||||
|
css,
|
||||||
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
CSSResult,
|
|
||||||
css,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { html } from "lit-html";
|
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 { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import "../ha-automation-action";
|
|
||||||
import { Condition } from "../../../../../data/automation";
|
import { Condition } from "../../../../../data/automation";
|
||||||
|
import { Action, ChooseAction } from "../../../../../data/script";
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
import { mdiDelete } from "@mdi/js";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import "../ha-automation-action";
|
||||||
|
import { ActionElement } from "../ha-automation-action-row";
|
||||||
|
|
||||||
@customElement("ha-automation-action-choose")
|
@customElement("ha-automation-action-choose")
|
||||||
export class HaChooseAction extends LitElement implements ActionElement {
|
export class HaChooseAction extends LitElement implements ActionElement {
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
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 type { PaperListboxElement } from "@polymer/paper-listbox";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
|
import { CSSResult, customElement, LitElement, property } from "lit-element";
|
||||||
|
import { html } from "lit-html";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import "../ha-automation-action";
|
import {
|
||||||
import { Condition } from "../../../../lovelace/common/validate-condition";
|
Action,
|
||||||
|
CountRepeat,
|
||||||
|
RepeatAction,
|
||||||
|
UntilRepeat,
|
||||||
|
WhileRepeat,
|
||||||
|
} from "../../../../../data/script";
|
||||||
import { haStyle } from "../../../../../resources/styles";
|
import { haStyle } from "../../../../../resources/styles";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import { Condition } from "../../../../lovelace/common/validate-condition";
|
||||||
|
import "../ha-automation-action";
|
||||||
|
import { ActionElement } from "../ha-automation-action-row";
|
||||||
|
|
||||||
const OPTIONS = ["count", "while", "until"];
|
const OPTIONS = ["count", "while", "until"];
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { html } from "lit-html";
|
import { html } from "lit-html";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
|
import { any, assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { computeDomain } from "../../../../../common/entity/compute_domain";
|
import { computeDomain } from "../../../../../common/entity/compute_domain";
|
||||||
import { computeObjectId } from "../../../../../common/entity/compute_object_id";
|
import { computeObjectId } from "../../../../../common/entity/compute_object_id";
|
||||||
@ -18,14 +19,13 @@ import type { HaYamlEditor } from "../../../../../components/ha-yaml-editor";
|
|||||||
import { ServiceAction } from "../../../../../data/script";
|
import { ServiceAction } from "../../../../../data/script";
|
||||||
import type { PolymerChangedEvent } from "../../../../../polymer-types";
|
import type { PolymerChangedEvent } from "../../../../../polymer-types";
|
||||||
import type { HomeAssistant } from "../../../../../types";
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
|
||||||
import { assert, optional, object, string } from "superstruct";
|
|
||||||
import { EntityId } from "../../../../lovelace/common/structs/is-entity-id";
|
import { EntityId } from "../../../../lovelace/common/structs/is-entity-id";
|
||||||
|
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
||||||
|
|
||||||
const actionStruct = object({
|
const actionStruct = object({
|
||||||
service: optional(string()),
|
service: optional(string()),
|
||||||
entity_id: optional(EntityId),
|
entity_id: optional(EntityId),
|
||||||
data: optional(object()),
|
data: optional(any()),
|
||||||
});
|
});
|
||||||
|
|
||||||
@customElement("ha-automation-action-service")
|
@customElement("ha-automation-action-service")
|
||||||
|
@ -0,0 +1,70 @@
|
|||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
import "@polymer/paper-input/paper-textarea";
|
||||||
|
import { customElement, LitElement, property } from "lit-element";
|
||||||
|
import { html } from "lit-html";
|
||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
|
import "../../../../../components/ha-formfield";
|
||||||
|
import { WaitForTriggerAction } from "../../../../../data/script";
|
||||||
|
import { HomeAssistant } from "../../../../../types";
|
||||||
|
import "../../trigger/ha-automation-trigger";
|
||||||
|
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
||||||
|
|
||||||
|
@customElement("ha-automation-action-wait_for_trigger")
|
||||||
|
export class HaWaitForTriggerAction extends LitElement
|
||||||
|
implements ActionElement {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public action!: WaitForTriggerAction;
|
||||||
|
|
||||||
|
public static get defaultConfig() {
|
||||||
|
return { wait_for_trigger: [], timeout: "" };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
const { wait_for_trigger, continue_on_timeout, timeout } = this.action;
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<paper-input
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.type.wait_for_trigger.timeout"
|
||||||
|
)}
|
||||||
|
.name=${"timeout"}
|
||||||
|
.value=${timeout}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></paper-input>
|
||||||
|
<br />
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.actions.type.wait_for_trigger.timeout"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-switch
|
||||||
|
.checked=${continue_on_timeout}
|
||||||
|
@change=${this._continueChanged}
|
||||||
|
></ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-automation-trigger
|
||||||
|
.triggers=${wait_for_trigger}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.name=${"wait_for_trigger"}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-automation-trigger>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _continueChanged(ev) {
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: { ...this.action, continue_on_timeout: ev.target.checked },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
|
handleChangeEvent(this, ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-automation-action-wait_for_trigger": HaWaitForTriggerAction;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ import "@polymer/paper-input/paper-input";
|
|||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import { customElement, LitElement, property } from "lit-element";
|
import { customElement, LitElement, property } from "lit-element";
|
||||||
import { html } from "lit-html";
|
import { html } from "lit-html";
|
||||||
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import { WaitAction } from "../../../../../data/script";
|
import { WaitAction } from "../../../../../data/script";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
|
||||||
@ -13,11 +14,11 @@ export class HaWaitAction extends LitElement implements ActionElement {
|
|||||||
@property() public action!: WaitAction;
|
@property() public action!: WaitAction;
|
||||||
|
|
||||||
public static get defaultConfig() {
|
public static get defaultConfig() {
|
||||||
return { wait_template: "", timeout: "" };
|
return { wait_template: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const { wait_template, timeout } = this.action;
|
const { wait_template, timeout, continue_on_timeout } = this.action;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<paper-textarea
|
<paper-textarea
|
||||||
@ -37,9 +38,24 @@ export class HaWaitAction extends LitElement implements ActionElement {
|
|||||||
.value=${timeout}
|
.value=${timeout}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></paper-input>
|
></paper-input>
|
||||||
|
<br />
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass.localize("ui.panel.config.automation.editor.actions.type.wait_template.continue_timeout")}
|
||||||
|
>
|
||||||
|
<ha-switch
|
||||||
|
.checked=${continue_on_timeout}
|
||||||
|
@change=${this._continueChanged}
|
||||||
|
></ha-switch>
|
||||||
|
</ha-formfield>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _continueChanged(ev) {
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: { ...this.action, continue_on_timeout: ev.target.checked },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import "../../../../components/ha-icon-button";
|
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||||
import "@polymer/paper-item/paper-item";
|
|
||||||
import "@material/mwc-list/mwc-list-item";
|
import "@material/mwc-list/mwc-list-item";
|
||||||
import "../../../../components/ha-button-menu";
|
|
||||||
import { mdiDotsVertical } from "@mdi/js";
|
import { mdiDotsVertical } from "@mdi/js";
|
||||||
|
import "@polymer/paper-item/paper-item";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import "../../../../components/ha-button-menu";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-icon-button";
|
||||||
import { Condition } from "../../../../data/automation";
|
import { Condition } from "../../../../data/automation";
|
||||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import "./ha-automation-condition-editor";
|
import "./ha-automation-condition-editor";
|
||||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
|
||||||
|
|
||||||
export interface ConditionElement extends LitElement {
|
export interface ConditionElement extends LitElement {
|
||||||
condition: Condition;
|
condition: Condition;
|
||||||
@ -81,7 +81,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
"ui.panel.config.automation.editor.edit_yaml"
|
"ui.panel.config.automation.editor.edit_yaml"
|
||||||
)}
|
)}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item disabled>
|
<mwc-list-item>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.actions.duplicate"
|
"ui.panel.config.automation.editor.actions.duplicate"
|
||||||
)}
|
)}
|
||||||
@ -109,6 +109,7 @@ export default class HaAutomationConditionRow extends LitElement {
|
|||||||
this._switchYamlMode();
|
this._switchYamlMode();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
fireEvent(this, "duplicate");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this._onDelete();
|
this._onDelete();
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
html,
|
html,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
|
PropertyValues,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
@ -20,13 +21,43 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
|
|
||||||
@property() public conditions!: Condition[];
|
@property() public conditions!: Condition[];
|
||||||
|
|
||||||
|
protected updated(changedProperties: PropertyValues) {
|
||||||
|
if (!changedProperties.has("conditions")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let updatedConditions: Condition[] | undefined;
|
||||||
|
if (!Array.isArray(this.conditions)) {
|
||||||
|
updatedConditions = [this.conditions];
|
||||||
|
}
|
||||||
|
|
||||||
|
(updatedConditions || this.conditions).forEach((condition, index) => {
|
||||||
|
if (typeof condition === "string") {
|
||||||
|
updatedConditions = updatedConditions || [...this.conditions];
|
||||||
|
updatedConditions[index] = {
|
||||||
|
condition: "template",
|
||||||
|
value_template: condition,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (updatedConditions) {
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: updatedConditions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
|
if (!Array.isArray(this.conditions)) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
return html`
|
return html`
|
||||||
${this.conditions.map(
|
${this.conditions.map(
|
||||||
(cond, idx) => html`
|
(cond, idx) => html`
|
||||||
<ha-automation-condition-row
|
<ha-automation-condition-row
|
||||||
.index=${idx}
|
.index=${idx}
|
||||||
.condition=${cond}
|
.condition=${cond}
|
||||||
|
@duplicate=${this._duplicateCondition}
|
||||||
@value-changed=${this._conditionChanged}
|
@value-changed=${this._conditionChanged}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
></ha-automation-condition-row>
|
></ha-automation-condition-row>
|
||||||
@ -68,6 +99,14 @@ export default class HaAutomationCondition extends LitElement {
|
|||||||
fireEvent(this, "value-changed", { value: conditions });
|
fireEvent(this, "value-changed", { value: conditions });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _duplicateCondition(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const index = (ev.target as any).index;
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: this.conditions.concat(this.conditions[index]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResult {
|
||||||
return css`
|
return css`
|
||||||
ha-automation-condition-row,
|
ha-automation-condition-row,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import { customElement, html, LitElement, property } from "lit-element";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
|
||||||
import "../../../../../components/entity/ha-entity-picker";
|
import "../../../../../components/entity/ha-entity-picker";
|
||||||
import { NumericStateCondition } from "../../../../../data/automation";
|
import { NumericStateCondition } from "../../../../../data/automation";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
@ -19,16 +18,34 @@ export default class HaNumericStateCondition extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
public render() {
|
||||||
const { value_template, entity_id, below, above } = this.condition;
|
const {
|
||||||
|
value_template,
|
||||||
|
entity_id,
|
||||||
|
attribute,
|
||||||
|
below,
|
||||||
|
above,
|
||||||
|
} = this.condition;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.value="${entity_id}"
|
.value=${entity_id}
|
||||||
@value-changed="${this._entityPicked}"
|
.name=${"entity_id"}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
|
<ha-entity-attribute-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityId=${entity_id}
|
||||||
|
.value=${attribute}
|
||||||
|
.name=${"attribute"}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.state.attribute"
|
||||||
|
)}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
allow-custom-value
|
||||||
|
></ha-entity-attribute-picker>
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.conditions.type.numeric_state.above"
|
"ui.panel.config.automation.editor.conditions.type.numeric_state.above"
|
||||||
@ -60,13 +77,6 @@ export default class HaNumericStateCondition extends LitElement {
|
|||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entityPicked(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: { ...this.condition, entity_id: ev.detail.value },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import { customElement, html, LitElement, property } from "lit-element";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import "../../../../../components/entity/ha-entity-attribute-picker";
|
||||||
import "../../../../../components/entity/ha-entity-picker";
|
import "../../../../../components/entity/ha-entity-picker";
|
||||||
import { StateCondition } from "../../../../../data/automation";
|
import { StateCondition } from "../../../../../data/automation";
|
||||||
import { PolymerChangedEvent } from "../../../../../polymer-types";
|
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import {
|
import {
|
||||||
ConditionElement,
|
ConditionElement,
|
||||||
@ -21,15 +20,27 @@ export class HaStateCondition extends LitElement implements ConditionElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const { entity_id, state } = this.condition;
|
const { entity_id, attribute, state } = this.condition;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.value=${entity_id}
|
.value=${entity_id}
|
||||||
@value-changed=${this._entityPicked}
|
.name=${"entity_id"}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
|
<ha-entity-attribute-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityId=${entity_id}
|
||||||
|
.value=${attribute}
|
||||||
|
.name=${"attribute"}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.state.attribute"
|
||||||
|
)}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
allow-custom-value
|
||||||
|
></ha-entity-attribute-picker>
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.conditions.type.state.state"
|
"ui.panel.config.automation.editor.conditions.type.state.state"
|
||||||
@ -44,13 +55,6 @@ export class HaStateCondition extends LitElement implements ConditionElement {
|
|||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entityPicked(ev: PolymerChangedEvent<string>) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: { ...this.condition, entity_id: ev.detail.value },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
|
import { Radio } from "@material/mwc-radio";
|
||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import {
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import "../../../../../components/ha-formfield";
|
||||||
|
import "../../../../../components/ha-radio";
|
||||||
import { TimeCondition } from "../../../../../data/automation";
|
import { TimeCondition } from "../../../../../data/automation";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import {
|
import {
|
||||||
@ -7,38 +16,130 @@ import {
|
|||||||
handleChangeEvent,
|
handleChangeEvent,
|
||||||
} from "../ha-automation-condition-row";
|
} from "../ha-automation-condition-row";
|
||||||
|
|
||||||
|
const includeDomains = ["input_datetime"];
|
||||||
|
|
||||||
@customElement("ha-automation-condition-time")
|
@customElement("ha-automation-condition-time")
|
||||||
export class HaTimeCondition extends LitElement implements ConditionElement {
|
export class HaTimeCondition extends LitElement implements ConditionElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public condition!: TimeCondition;
|
@property() public condition!: TimeCondition;
|
||||||
|
|
||||||
|
@internalProperty() private _inputModeBefore?: boolean;
|
||||||
|
|
||||||
|
@internalProperty() private _inputModeAfter?: boolean;
|
||||||
|
|
||||||
public static get defaultConfig() {
|
public static get defaultConfig() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const { after, before } = this.condition;
|
const { after, before } = this.condition;
|
||||||
|
|
||||||
|
const inputModeBefore =
|
||||||
|
this._inputModeBefore ?? before?.startsWith("input_datetime.");
|
||||||
|
const inputModeAfter =
|
||||||
|
this._inputModeAfter ?? after?.startsWith("input_datetime.");
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<paper-input
|
<ha-formfield
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass!.localize(
|
||||||
"ui.panel.config.automation.editor.conditions.type.time.after"
|
"ui.panel.config.automation.editor.conditions.type.time.type_value"
|
||||||
)}
|
)}
|
||||||
name="after"
|
>
|
||||||
.value=${after}
|
<ha-radio
|
||||||
@value-changed=${this._valueChanged}
|
@change=${this._handleModeChanged}
|
||||||
></paper-input>
|
name="mode_after"
|
||||||
<paper-input
|
value="value"
|
||||||
.label=${this.hass.localize(
|
?checked=${!inputModeAfter}
|
||||||
"ui.panel.config.automation.editor.conditions.type.time.before"
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.type_input"
|
||||||
)}
|
)}
|
||||||
name="before"
|
>
|
||||||
.value=${before}
|
<ha-radio
|
||||||
@value-changed=${this._valueChanged}
|
@change=${this._handleModeChanged}
|
||||||
></paper-input>
|
name="mode_after"
|
||||||
|
value="input"
|
||||||
|
?checked=${inputModeAfter}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
${inputModeAfter
|
||||||
|
? html`<ha-entity-picker
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.after"
|
||||||
|
)}
|
||||||
|
.includeDomains=${includeDomains}
|
||||||
|
.name=${"after"}
|
||||||
|
.value=${after?.startsWith("input_datetime.") ? after : ""}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
></ha-entity-picker>`
|
||||||
|
: html`<paper-input
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.after"
|
||||||
|
)}
|
||||||
|
name="after"
|
||||||
|
.value=${after?.startsWith("input_datetime.") ? "" : after}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></paper-input>`}
|
||||||
|
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.type_value"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleModeChanged}
|
||||||
|
name="mode_before"
|
||||||
|
value="value"
|
||||||
|
?checked=${!inputModeBefore}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.type_input"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleModeChanged}
|
||||||
|
name="mode_before"
|
||||||
|
value="input"
|
||||||
|
?checked=${inputModeBefore}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
${inputModeBefore
|
||||||
|
? html`<ha-entity-picker
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.before"
|
||||||
|
)}
|
||||||
|
.includeDomains=${includeDomains}
|
||||||
|
.name=${"before"}
|
||||||
|
.value=${before?.startsWith("input_datetime.") ? before : ""}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
></ha-entity-picker>`
|
||||||
|
: html`<paper-input
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.conditions.type.time.before"
|
||||||
|
)}
|
||||||
|
name="before"
|
||||||
|
.value=${before?.startsWith("input_datetime.") ? "" : before}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></paper-input>`}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleModeChanged(ev: Event) {
|
||||||
|
const target = ev.target as Radio;
|
||||||
|
if (target.getAttribute("name") === "mode_after") {
|
||||||
|
this._inputModeAfter = target.value === "input";
|
||||||
|
} else {
|
||||||
|
this._inputModeBefore = target.value === "input";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,32 @@
|
|||||||
|
import "@material/mwc-fab";
|
||||||
|
import { mdiContentDuplicate, mdiContentSave, mdiDelete } from "@mdi/js";
|
||||||
import "@polymer/app-layout/app-header/app-header";
|
import "@polymer/app-layout/app-header/app-header";
|
||||||
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
import "@polymer/app-layout/app-toolbar/app-toolbar";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import "../../../components/ha-icon-button";
|
import { PaperListboxElement } from "@polymer/paper-listbox";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
import "../../../components/ha-card";
|
import "../../../components/ha-card";
|
||||||
|
import "../../../components/ha-icon-button";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import "@material/mwc-fab";
|
|
||||||
import {
|
import {
|
||||||
AutomationConfig,
|
AutomationConfig,
|
||||||
AutomationEntity,
|
AutomationEntity,
|
||||||
Condition,
|
Condition,
|
||||||
deleteAutomation,
|
deleteAutomation,
|
||||||
getAutomationEditorInitData,
|
getAutomationEditorInitData,
|
||||||
|
showAutomationEditor,
|
||||||
Trigger,
|
Trigger,
|
||||||
triggerAutomation,
|
triggerAutomation,
|
||||||
} from "../../../data/automation";
|
} from "../../../data/automation";
|
||||||
@ -42,9 +46,6 @@ import { HaDeviceAction } from "./action/types/ha-automation-action-device_id";
|
|||||||
import "./condition/ha-automation-condition";
|
import "./condition/ha-automation-condition";
|
||||||
import "./trigger/ha-automation-trigger";
|
import "./trigger/ha-automation-trigger";
|
||||||
import { HaDeviceTrigger } from "./trigger/types/ha-automation-trigger-device";
|
import { HaDeviceTrigger } from "./trigger/types/ha-automation-trigger-device";
|
||||||
import { mdiContentSave } from "@mdi/js";
|
|
||||||
import { PaperListboxElement } from "@polymer/paper-listbox";
|
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
|
||||||
|
|
||||||
const MODES = ["single", "restart", "queued", "parallel"];
|
const MODES = ["single", "restart", "queued", "parallel"];
|
||||||
const MODES_MAX = ["queued", "parallel"];
|
const MODES_MAX = ["queued", "parallel"];
|
||||||
@ -53,6 +54,7 @@ declare global {
|
|||||||
// for fire event
|
// for fire event
|
||||||
interface HASSDomEvents {
|
interface HASSDomEvents {
|
||||||
"ui-mode-not-available": Error;
|
"ui-mode-not-available": Error;
|
||||||
|
duplicate: undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,14 +94,24 @@ export class HaAutomationEditor extends LitElement {
|
|||||||
${!this.automationId
|
${!this.automationId
|
||||||
? ""
|
? ""
|
||||||
: html`
|
: html`
|
||||||
<ha-icon-button
|
<mwc-icon-button
|
||||||
|
slot="toolbar-icon"
|
||||||
|
title="${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.picker.duplicate_automation"
|
||||||
|
)}"
|
||||||
|
@click=${this._duplicate}
|
||||||
|
>
|
||||||
|
<ha-svg-icon .path=${mdiContentDuplicate}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
|
<mwc-icon-button
|
||||||
slot="toolbar-icon"
|
slot="toolbar-icon"
|
||||||
title="${this.hass.localize(
|
title="${this.hass.localize(
|
||||||
"ui.panel.config.automation.picker.delete_automation"
|
"ui.panel.config.automation.picker.delete_automation"
|
||||||
)}"
|
)}"
|
||||||
icon="hass:delete"
|
|
||||||
@click=${this._deleteConfirm}
|
@click=${this._deleteConfirm}
|
||||||
></ha-icon-button>
|
>
|
||||||
|
<ha-svg-icon .path=${mdiDelete}></ha-svg-icon>
|
||||||
|
</mwc-icon-button>
|
||||||
`}
|
`}
|
||||||
${this._config
|
${this._config
|
||||||
? html`
|
? html`
|
||||||
@ -473,6 +485,31 @@ export class HaAutomationEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _duplicate() {
|
||||||
|
if (this._dirty) {
|
||||||
|
if (
|
||||||
|
!(await showConfirmationDialog(this, {
|
||||||
|
text: this.hass!.localize(
|
||||||
|
"ui.panel.config.automation.editor.unsaved_confirm"
|
||||||
|
),
|
||||||
|
confirmText: this.hass!.localize("ui.common.yes"),
|
||||||
|
dismissText: this.hass!.localize("ui.common.no"),
|
||||||
|
}))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Wait for dialog to complate closing
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
}
|
||||||
|
showAutomationEditor(this, {
|
||||||
|
...this._config,
|
||||||
|
id: undefined,
|
||||||
|
alias: `${this._config?.alias} (${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.picker.duplicate"
|
||||||
|
)})`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async _deleteConfirm() {
|
private async _deleteConfirm() {
|
||||||
showConfirmationDialog(this, {
|
showConfirmationDialog(this, {
|
||||||
text: this.hass.localize(
|
text: this.hass.localize(
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
|
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
||||||
|
import "@material/mwc-list/mwc-list-item";
|
||||||
|
import { mdiDotsVertical } from "@mdi/js";
|
||||||
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
import "@polymer/paper-dropdown-menu/paper-dropdown-menu-light";
|
||||||
import "../../../../components/ha-icon-button";
|
|
||||||
import "@polymer/paper-item/paper-item";
|
import "@polymer/paper-item/paper-item";
|
||||||
import "@polymer/paper-listbox/paper-listbox";
|
import "@polymer/paper-listbox/paper-listbox";
|
||||||
import "@material/mwc-list/mwc-list-item";
|
|
||||||
import "../../../../components/ha-button-menu";
|
|
||||||
import { mdiDotsVertical } from "@mdi/js";
|
|
||||||
import type { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
|
import type { PaperListboxElement } from "@polymer/paper-listbox/paper-listbox";
|
||||||
import {
|
import {
|
||||||
css,
|
css,
|
||||||
CSSResult,
|
CSSResult,
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
import { dynamicElement } from "../../../../common/dom/dynamic-element-directive";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import "../../../../components/ha-button-menu";
|
||||||
import "../../../../components/ha-card";
|
import "../../../../components/ha-card";
|
||||||
|
import "../../../../components/ha-icon-button";
|
||||||
import type { Trigger } from "../../../../data/automation";
|
import type { Trigger } from "../../../../data/automation";
|
||||||
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||||
|
import { haStyle } from "../../../../resources/styles";
|
||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import "./types/ha-automation-trigger-device";
|
import "./types/ha-automation-trigger-device";
|
||||||
import "./types/ha-automation-trigger-event";
|
import "./types/ha-automation-trigger-event";
|
||||||
@ -29,14 +31,12 @@ import "./types/ha-automation-trigger-mqtt";
|
|||||||
import "./types/ha-automation-trigger-numeric_state";
|
import "./types/ha-automation-trigger-numeric_state";
|
||||||
import "./types/ha-automation-trigger-state";
|
import "./types/ha-automation-trigger-state";
|
||||||
import "./types/ha-automation-trigger-sun";
|
import "./types/ha-automation-trigger-sun";
|
||||||
|
import "./types/ha-automation-trigger-tag";
|
||||||
import "./types/ha-automation-trigger-template";
|
import "./types/ha-automation-trigger-template";
|
||||||
import "./types/ha-automation-trigger-time";
|
import "./types/ha-automation-trigger-time";
|
||||||
import "./types/ha-automation-trigger-time_pattern";
|
import "./types/ha-automation-trigger-time_pattern";
|
||||||
import "./types/ha-automation-trigger-webhook";
|
import "./types/ha-automation-trigger-webhook";
|
||||||
import "./types/ha-automation-trigger-zone";
|
import "./types/ha-automation-trigger-zone";
|
||||||
import "./types/ha-automation-trigger-tag";
|
|
||||||
import { ActionDetail } from "@material/mwc-list/mwc-list-foundation";
|
|
||||||
import { haStyle } from "../../../../resources/styles";
|
|
||||||
|
|
||||||
const OPTIONS = [
|
const OPTIONS = [
|
||||||
"device",
|
"device",
|
||||||
@ -113,7 +113,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
"ui.panel.config.automation.editor.edit_yaml"
|
"ui.panel.config.automation.editor.edit_yaml"
|
||||||
)}
|
)}
|
||||||
</mwc-list-item>
|
</mwc-list-item>
|
||||||
<mwc-list-item disabled>
|
<mwc-list-item>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.actions.duplicate"
|
"ui.panel.config.automation.editor.actions.duplicate"
|
||||||
)}
|
)}
|
||||||
@ -183,6 +183,7 @@ export default class HaAutomationTriggerRow extends LitElement {
|
|||||||
this._switchYamlMode();
|
this._switchYamlMode();
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
|
fireEvent(this, "duplicate");
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
this._onDelete();
|
this._onDelete();
|
||||||
|
@ -27,6 +27,7 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
<ha-automation-trigger-row
|
<ha-automation-trigger-row
|
||||||
.index=${idx}
|
.index=${idx}
|
||||||
.trigger=${trg}
|
.trigger=${trg}
|
||||||
|
@duplicate=${this._duplicateTrigger}
|
||||||
@value-changed=${this._triggerChanged}
|
@value-changed=${this._triggerChanged}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
></ha-automation-trigger-row>
|
></ha-automation-trigger-row>
|
||||||
@ -68,6 +69,14 @@ export default class HaAutomationTrigger extends LitElement {
|
|||||||
fireEvent(this, "value-changed", { value: triggers });
|
fireEvent(this, "value-changed", { value: triggers });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _duplicateTrigger(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const index = (ev.target as any).index;
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: this.triggers.concat(this.triggers[index]),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static get styles(): CSSResult {
|
static get styles(): CSSResult {
|
||||||
return css`
|
return css`
|
||||||
ha-automation-trigger-row,
|
ha-automation-trigger-row,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import "@polymer/paper-input/paper-textarea";
|
import "@polymer/paper-input/paper-textarea";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import { customElement, html, LitElement, property } from "lit-element";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
|
||||||
import "../../../../../components/entity/ha-entity-picker";
|
import "../../../../../components/entity/ha-entity-picker";
|
||||||
import { ForDict, NumericStateTrigger } from "../../../../../data/automation";
|
import { ForDict, NumericStateTrigger } from "../../../../../data/automation";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
@ -19,8 +18,8 @@ export default class HaNumericStateTrigger extends LitElement {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
public render() {
|
||||||
const { value_template, entity_id, below, above } = this.trigger;
|
const { value_template, entity_id, attribute, below, above } = this.trigger;
|
||||||
let trgFor = this.trigger.for;
|
let trgFor = this.trigger.for;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -41,10 +40,22 @@ export default class HaNumericStateTrigger extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.value="${entity_id}"
|
.value="${entity_id}"
|
||||||
@value-changed="${this._entityPicked}"
|
@value-changed="${this._valueChanged}"
|
||||||
|
.name=${"entity_id"}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
|
<ha-entity-attribute-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityId=${entity_id}
|
||||||
|
.value=${attribute}
|
||||||
|
.name=${"attribute"}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.state.attribute"
|
||||||
|
)}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
allow-custom-value
|
||||||
|
></ha-entity-attribute-picker>
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.triggers.type.numeric_state.above"
|
"ui.panel.config.automation.editor.triggers.type.numeric_state.above"
|
||||||
@ -84,13 +95,6 @@ export default class HaNumericStateTrigger extends LitElement {
|
|||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entityPicked(ev) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: { ...this.trigger, entity_id: ev.detail.value },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import { customElement, html, LitElement, property } from "lit-element";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import "../../../../../components/entity/ha-entity-attribute-picker";
|
||||||
import "../../../../../components/entity/ha-entity-picker";
|
import "../../../../../components/entity/ha-entity-picker";
|
||||||
import { ForDict, StateTrigger } from "../../../../../data/automation";
|
import { ForDict, StateTrigger } from "../../../../../data/automation";
|
||||||
import { PolymerChangedEvent } from "../../../../../polymer-types";
|
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import {
|
import {
|
||||||
handleChangeEvent,
|
handleChangeEvent,
|
||||||
@ -21,7 +20,7 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const { entity_id, to, from } = this.trigger;
|
const { entity_id, attribute, to, from } = this.trigger;
|
||||||
let trgFor = this.trigger.for;
|
let trgFor = this.trigger.for;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -43,10 +42,22 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
return html`
|
return html`
|
||||||
<ha-entity-picker
|
<ha-entity-picker
|
||||||
.value=${entity_id}
|
.value=${entity_id}
|
||||||
@value-changed=${this._entityPicked}
|
@value-changed=${this._valueChanged}
|
||||||
|
.name=${"entity_id"}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
></ha-entity-picker>
|
></ha-entity-picker>
|
||||||
|
<ha-entity-attribute-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityId=${entity_id}
|
||||||
|
.value=${attribute}
|
||||||
|
.name=${"attribute"}
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.state.attribute"
|
||||||
|
)}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
allow-custom-value
|
||||||
|
></ha-entity-attribute-picker>
|
||||||
<paper-input
|
<paper-input
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.triggers.type.state.from"
|
"ui.panel.config.automation.editor.triggers.type.state.from"
|
||||||
@ -77,13 +88,6 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
|
|||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _entityPicked(ev: PolymerChangedEvent<string>) {
|
|
||||||
ev.stopPropagation();
|
|
||||||
fireEvent(this, "value-changed", {
|
|
||||||
value: { ...this.trigger, entity_id: ev.detail.value },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
import "@polymer/paper-input/paper-input";
|
import "@polymer/paper-input/paper-input";
|
||||||
import { customElement, html, LitElement, property } from "lit-element";
|
import {
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import "../../../../../components/entity/ha-entity-picker";
|
||||||
|
import "../../../../../components/ha-formfield";
|
||||||
|
import "../../../../../components/ha-radio";
|
||||||
import { TimeTrigger } from "../../../../../data/automation";
|
import { TimeTrigger } from "../../../../../data/automation";
|
||||||
import { HomeAssistant } from "../../../../../types";
|
import { HomeAssistant } from "../../../../../types";
|
||||||
import {
|
import {
|
||||||
@ -7,31 +16,81 @@ import {
|
|||||||
TriggerElement,
|
TriggerElement,
|
||||||
} from "../ha-automation-trigger-row";
|
} from "../ha-automation-trigger-row";
|
||||||
|
|
||||||
|
const includeDomains = ["input_datetime"];
|
||||||
|
|
||||||
@customElement("ha-automation-trigger-time")
|
@customElement("ha-automation-trigger-time")
|
||||||
export class HaTimeTrigger extends LitElement implements TriggerElement {
|
export class HaTimeTrigger extends LitElement implements TriggerElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public trigger!: TimeTrigger;
|
@property() public trigger!: TimeTrigger;
|
||||||
|
|
||||||
|
@internalProperty() private _inputMode?: boolean;
|
||||||
|
|
||||||
public static get defaultConfig() {
|
public static get defaultConfig() {
|
||||||
return { at: "" };
|
return { at: "" };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const { at } = this.trigger;
|
const { at } = this.trigger;
|
||||||
|
const inputMode = this._inputMode ?? at?.startsWith("input_datetime.");
|
||||||
return html`
|
return html`
|
||||||
<paper-input
|
<ha-formfield
|
||||||
.label=${this.hass.localize(
|
.label=${this.hass!.localize(
|
||||||
"ui.panel.config.automation.editor.triggers.type.time.at"
|
"ui.panel.config.automation.editor.triggers.type.time.type_value"
|
||||||
)}
|
)}
|
||||||
name="at"
|
>
|
||||||
.value=${at}
|
<ha-radio
|
||||||
@value-changed=${this._valueChanged}
|
@change=${this._handleModeChanged}
|
||||||
></paper-input>
|
name="mode"
|
||||||
|
value="value"
|
||||||
|
?checked=${!inputMode}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
<ha-formfield
|
||||||
|
.label=${this.hass!.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time.type_input"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<ha-radio
|
||||||
|
@change=${this._handleModeChanged}
|
||||||
|
name="mode"
|
||||||
|
value="input"
|
||||||
|
?checked=${inputMode}
|
||||||
|
></ha-radio>
|
||||||
|
</ha-formfield>
|
||||||
|
${inputMode
|
||||||
|
? html`<ha-entity-picker
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time.at"
|
||||||
|
)}
|
||||||
|
.includeDomains=${includeDomains}
|
||||||
|
.name=${"at"}
|
||||||
|
.value=${at?.startsWith("input_datetime.") ? at : ""}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
.hass=${this.hass}
|
||||||
|
></ha-entity-picker>`
|
||||||
|
: html`<paper-input
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.config.automation.editor.triggers.type.time.at"
|
||||||
|
)}
|
||||||
|
name="at"
|
||||||
|
.value=${at?.startsWith("input_datetime.") ? "" : at}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></paper-input>`}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _handleModeChanged(ev: Event) {
|
||||||
|
this._inputMode = (ev.target as any).value === "input";
|
||||||
|
}
|
||||||
|
|
||||||
private _valueChanged(ev: CustomEvent): void {
|
private _valueChanged(ev: CustomEvent): void {
|
||||||
handleChangeEvent(this, ev);
|
handleChangeEvent(this, ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-automation-trigger-time": HaTimeTrigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,13 +2,15 @@ import "@polymer/paper-input/paper-input";
|
|||||||
import {
|
import {
|
||||||
customElement,
|
customElement,
|
||||||
html,
|
html,
|
||||||
|
internalProperty,
|
||||||
LitElement,
|
LitElement,
|
||||||
property,
|
property,
|
||||||
internalProperty,
|
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit-element";
|
} from "lit-element";
|
||||||
|
import { assert, object, optional, string } from "superstruct";
|
||||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
import { stateIcon } from "../../../../common/entity/state_icon";
|
import { stateIcon } from "../../../../common/entity/state_icon";
|
||||||
|
import "../../../../components/entity/ha-entity-attribute-picker";
|
||||||
import "../../../../components/ha-icon-input";
|
import "../../../../components/ha-icon-input";
|
||||||
import { HomeAssistant } from "../../../../types";
|
import { HomeAssistant } from "../../../../types";
|
||||||
import { EntityCardConfig } from "../../cards/types";
|
import { EntityCardConfig } from "../../cards/types";
|
||||||
@ -19,7 +21,6 @@ import { headerFooterConfigStructs } from "../../header-footer/types";
|
|||||||
import { LovelaceCardEditor } from "../../types";
|
import { LovelaceCardEditor } from "../../types";
|
||||||
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
import { EditorTarget, EntitiesEditorEvent } from "../types";
|
||||||
import { configElementStyle } from "./config-elements-style";
|
import { configElementStyle } from "./config-elements-style";
|
||||||
import { string, object, optional, assert } from "superstruct";
|
|
||||||
|
|
||||||
const cardConfigStruct = object({
|
const cardConfigStruct = object({
|
||||||
type: string(),
|
type: string(),
|
||||||
@ -113,7 +114,9 @@ export class HuiEntityCardEditor extends LitElement
|
|||||||
></ha-icon-input>
|
></ha-icon-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="side-by-side">
|
<div class="side-by-side">
|
||||||
<paper-input
|
<ha-entity-attribute-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.entityId=${this._entity}
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.attribute"
|
"ui.panel.lovelace.editor.card.generic.attribute"
|
||||||
)} (${this.hass.localize(
|
)} (${this.hass.localize(
|
||||||
@ -122,7 +125,7 @@ export class HuiEntityCardEditor extends LitElement
|
|||||||
.value=${this._attribute}
|
.value=${this._attribute}
|
||||||
.configValue=${"attribute"}
|
.configValue=${"attribute"}
|
||||||
@value-changed=${this._valueChanged}
|
@value-changed=${this._valueChanged}
|
||||||
></paper-input>
|
></ha-entity-attribute-picker>
|
||||||
<paper-input
|
<paper-input
|
||||||
.label="${this.hass.localize(
|
.label="${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.card.generic.unit"
|
"ui.panel.lovelace.editor.card.generic.unit"
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
import { UpdatingElement } from "lit-element";
|
||||||
|
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||||
import {
|
import {
|
||||||
closeDialog,
|
closeDialog,
|
||||||
showDialog,
|
|
||||||
DialogState,
|
|
||||||
DialogClosedParams,
|
DialogClosedParams,
|
||||||
|
DialogState,
|
||||||
|
showDialog,
|
||||||
} from "../dialogs/make-dialog-manager";
|
} from "../dialogs/make-dialog-manager";
|
||||||
import { Constructor } from "../types";
|
|
||||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
|
||||||
import { UpdatingElement } from "lit-element";
|
|
||||||
import { ProvideHassElement } from "../mixins/provide-hass-lit-mixin";
|
import { ProvideHassElement } from "../mixins/provide-hass-lit-mixin";
|
||||||
|
import { Constructor } from "../types";
|
||||||
|
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
|
||||||
|
@ -286,6 +286,10 @@
|
|||||||
"entity": "Entity",
|
"entity": "Entity",
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"show_entities": "Show entities"
|
"show_entities": "Show entities"
|
||||||
|
},
|
||||||
|
"entity-attribute-picker": {
|
||||||
|
"attribute": "Attribute",
|
||||||
|
"show_attributes": "Show attributes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"device-picker": {
|
"device-picker": {
|
||||||
@ -915,6 +919,8 @@
|
|||||||
"show_info_automation": "Show info about automation",
|
"show_info_automation": "Show info about automation",
|
||||||
"delete_automation": "Delete automation",
|
"delete_automation": "Delete automation",
|
||||||
"delete_confirm": "Are you sure you want to delete this automation?",
|
"delete_confirm": "Are you sure you want to delete this automation?",
|
||||||
|
"duplicate_automation": "Duplicate automation",
|
||||||
|
"duplicate": "Duplicate",
|
||||||
"headers": {
|
"headers": {
|
||||||
"name": "Name"
|
"name": "Name"
|
||||||
}
|
}
|
||||||
@ -985,6 +991,7 @@
|
|||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"label": "State",
|
"label": "State",
|
||||||
|
"attribute": "Attribute (Optional)",
|
||||||
"from": "From",
|
"from": "From",
|
||||||
"for": "For",
|
"for": "For",
|
||||||
"to": "To"
|
"to": "To"
|
||||||
@ -1021,8 +1028,10 @@
|
|||||||
"value_template": "Value template"
|
"value_template": "Value template"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
|
"type_value": "Fixed time",
|
||||||
|
"type_input": "Value of a date/time helper",
|
||||||
"label": "Time",
|
"label": "Time",
|
||||||
"at": "At"
|
"at": "At time"
|
||||||
},
|
},
|
||||||
"time_pattern": {
|
"time_pattern": {
|
||||||
"label": "Time Pattern",
|
"label": "Time Pattern",
|
||||||
@ -1098,6 +1107,8 @@
|
|||||||
"value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]"
|
"value_template": "[%key:ui::panel::config::automation::editor::triggers::type::template::value_template%]"
|
||||||
},
|
},
|
||||||
"time": {
|
"time": {
|
||||||
|
"type_value": "[%key:ui::panel::config::automation::editor::triggers::type::time::type_value%]",
|
||||||
|
"type_input": "[%key:ui::panel::config::automation::editor::triggers::type::time::type_input%]",
|
||||||
"label": "[%key:ui::panel::config::automation::editor::triggers::type::time::label%]",
|
"label": "[%key:ui::panel::config::automation::editor::triggers::type::time::label%]",
|
||||||
"after": "After",
|
"after": "After",
|
||||||
"before": "Before"
|
"before": "Before"
|
||||||
@ -1132,7 +1143,13 @@
|
|||||||
"wait_template": {
|
"wait_template": {
|
||||||
"label": "Wait",
|
"label": "Wait",
|
||||||
"wait_template": "Wait Template",
|
"wait_template": "Wait Template",
|
||||||
"timeout": "Timeout (optional)"
|
"timeout": "Timeout (optional)",
|
||||||
|
"continue_timeout": "Continue on timeout"
|
||||||
|
},
|
||||||
|
"wait_for_trigger": {
|
||||||
|
"label": "Wait for trigger",
|
||||||
|
"timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::timeout%]",
|
||||||
|
"continue_timeout": "[%key:ui::panel::config::automation::editor::actions::type::wait_template::continue_timeout%]"
|
||||||
},
|
},
|
||||||
"condition": {
|
"condition": {
|
||||||
"label": "Condition"
|
"label": "Condition"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user