State Trigger -> HA Form (#11631)

Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
Zack Barett 2022-02-10 09:26:28 -06:00 committed by GitHub
parent 0eeed85193
commit cefa2ee183
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 97 additions and 59 deletions

View File

@ -26,6 +26,11 @@ export class HaBaseTimeInput extends LitElement {
*/ */
@property({ type: Boolean }) autoValidate = false; @property({ type: Boolean }) autoValidate = false;
/**
* determines if inputs are required
*/
@property({ type: Boolean }) public required?: boolean;
/** /**
* 12 or 24 hr format * 12 or 24 hr format
*/ */
@ -115,7 +120,7 @@ export class HaBaseTimeInput extends LitElement {
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focus=${this._onFocus}
no-spinner no-spinner
required .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
maxlength="2" maxlength="2"
.max=${this._hourMax} .max=${this._hourMax}
@ -135,7 +140,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus} @focus=${this._onFocus}
name="minutes" name="minutes"
no-spinner no-spinner
required .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
maxlength="2" maxlength="2"
max="59" max="59"
@ -156,7 +161,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus} @focus=${this._onFocus}
name="seconds" name="seconds"
no-spinner no-spinner
required .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
maxlength="2" maxlength="2"
max="59" max="59"
@ -177,7 +182,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus} @focus=${this._onFocus}
name="milliseconds" name="milliseconds"
no-spinner no-spinner
required .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
maxlength="3" maxlength="3"
max="999" max="999"
@ -189,7 +194,7 @@ export class HaBaseTimeInput extends LitElement {
${this.format === 24 ${this.format === 24
? "" ? ""
: html`<mwc-select : html`<mwc-select
required .required=${this.required}
.value=${this.amPm} .value=${this.amPm}
.disabled=${this.disabled} .disabled=${this.disabled}
name="amPm" name="amPm"

View File

@ -81,12 +81,12 @@ export class HaForm extends LitElement implements HaFormElement {
: ""} : ""}
${"selector" in item ${"selector" in item
? html`<ha-selector ? html`<ha-selector
.schema=${item}
.hass=${this.hass} .hass=${this.hass}
.selector=${item.selector} .selector=${item.selector}
.value=${getValue(this.data, item)} .value=${getValue(this.data, item)}
.label=${this._computeLabel(item)} .label=${this._computeLabel(item)}
.disabled=${this.disabled} .disabled=${this.disabled}
.required=${item.required}
></ha-selector>` ></ha-selector>`
: dynamicElement(`ha-form-${item.type}`, { : dynamicElement(`ha-form-${item.type}`, {
schema: item, schema: item,

View File

@ -0,0 +1,37 @@
import "../ha-duration-input";
import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import { DurationSelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
@customElement("ha-selector-duration")
export class HaTimeDuration extends LitElement {
@property() public hass!: HomeAssistant;
@property() public selector!: DurationSelector;
@property() public value?: string;
@property() public label?: string;
@property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required = true;
protected render() {
return html`
<ha-duration-input
.label=${this.label}
.data=${this.value}
.disabled=${this.disabled}
.required=${this.required}
></ha-duration-input>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-selector-duration": HaTimeDuration;
}
}

View File

@ -22,6 +22,8 @@ export class HaTextSelector extends LitElement {
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required = true;
@state() private _unmaskedPassword = false; @state() private _unmaskedPassword = false;
protected render() { protected render() {
@ -35,7 +37,7 @@ export class HaTextSelector extends LitElement {
autocapitalize="none" autocapitalize="none"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
required .required=${this.required}
autogrow autogrow
></ha-textarea>`; ></ha-textarea>`;
} }
@ -50,7 +52,7 @@ export class HaTextSelector extends LitElement {
? // reserve some space for the icon. ? // reserve some space for the icon.
html`<div style="width: 24px"></div>` html`<div style="width: 24px"></div>`
: this.selector.text?.suffix} : this.selector.text?.suffix}
required .required=${this.required}
></ha-textfield> ></ha-textfield>
${this.selector.text?.type === "password" ${this.selector.text?.type === "password"
? html`<ha-icon-button ? html`<ha-icon-button

View File

@ -15,6 +15,7 @@ import "./ha-selector-select";
import "./ha-selector-target"; import "./ha-selector-target";
import "./ha-selector-text"; import "./ha-selector-text";
import "./ha-selector-time"; import "./ha-selector-time";
import "./ha-selector-duration";
@customElement("ha-selector") @customElement("ha-selector")
export class HaSelector extends LitElement { export class HaSelector extends LitElement {
@ -30,6 +31,8 @@ export class HaSelector extends LitElement {
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;
@property({ type: Boolean }) public required = true;
public focus() { public focus() {
this.shadowRoot?.getElementById("selector")?.focus(); this.shadowRoot?.getElementById("selector")?.focus();
} }
@ -47,6 +50,7 @@ export class HaSelector extends LitElement {
label: this.label, label: this.label,
placeholder: this.placeholder, placeholder: this.placeholder,
disabled: this.disabled, disabled: this.disabled,
required: this.required,
id: "selector", id: "selector",
})} })}
`; `;

View File

@ -31,6 +31,11 @@ export interface DeviceSelector {
}; };
} }
export interface DurationSelector {
// eslint-disable-next-line @typescript-eslint/ban-types
duration: {};
}
export interface AddonSelector { export interface AddonSelector {
addon: { addon: {
name?: string; name?: string;

View File

@ -1,4 +1,3 @@
import "@polymer/paper-input/paper-input";
import { html, LitElement, PropertyValues } from "lit"; import { html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { import {
@ -10,19 +9,15 @@ import {
string, string,
union, union,
} from "superstruct"; } from "superstruct";
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
import { fireEvent } from "../../../../../common/dom/fire_event"; import { fireEvent } from "../../../../../common/dom/fire_event";
import { hasTemplate } from "../../../../../common/string/has-template"; import { hasTemplate } from "../../../../../common/string/has-template";
import "../../../../../components/entity/ha-entity-attribute-picker";
import "../../../../../components/entity/ha-entity-picker";
import "../../../../../components/ha-duration-input";
import { StateTrigger } from "../../../../../data/automation"; import { StateTrigger } from "../../../../../data/automation";
import { HomeAssistant } from "../../../../../types"; import { HomeAssistant } from "../../../../../types";
import { baseTriggerStruct, forDictStruct } from "../../structs"; import { baseTriggerStruct, forDictStruct } from "../../structs";
import { import { TriggerElement } from "../ha-automation-trigger-row";
handleChangeEvent, import "../../../../../components/ha-form/ha-form";
TriggerElement, import { createDurationData } from "../../../../../common/datetime/create_duration_data";
} from "../ha-automation-trigger-row"; import { HaFormSchema } from "../../../../../components/ha-form/types";
const stateTriggerStruct = assign( const stateTriggerStruct = assign(
baseTriggerStruct, baseTriggerStruct,
@ -36,6 +31,13 @@ const stateTriggerStruct = assign(
}) })
); );
const SCHEMA = [
{ name: "entity_id", selector: { entity: {} } },
{ name: "from", required: false, selector: { text: {} } },
{ name: "to", required: false, selector: { text: {} } },
{ name: "for", required: false, selector: { duration: {} } },
];
@customElement("ha-automation-trigger-state") @customElement("ha-automation-trigger-state")
export class HaStateTrigger extends LitElement implements TriggerElement { export class HaStateTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@ -76,57 +78,40 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
} }
protected render() { protected render() {
const { entity_id, attribute, to, from } = this.trigger;
const trgFor = createDurationData(this.trigger.for); const trgFor = createDurationData(this.trigger.for);
const data = { ...this.trigger, ...{ for: trgFor } };
return html` return html`
<ha-entity-picker <ha-form
.value=${entity_id}
@value-changed=${this._valueChanged}
.name=${"entity_id"}
.hass=${this.hass} .hass=${this.hass}
allow-custom-entity .data=${data}
></ha-entity-picker> .schema=${SCHEMA}
<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} @value-changed=${this._valueChanged}
allow-custom-value .computeLabel=${this._computeLabelCallback}
></ha-entity-attribute-picker> ></ha-form>
<paper-input
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.state.from"
)}
.name=${"from"}
.value=${from}
@value-changed=${this._valueChanged}
></paper-input>
<paper-input
label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.state.to"
)}
.name=${"to"}
.value=${to}
@value-changed=${this._valueChanged}
></paper-input>
<ha-duration-input
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.state.for"
)}
.name=${"for"}
.data=${trgFor}
@value-changed=${this._valueChanged}
></ha-duration-input>
`; `;
} }
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
handleChangeEvent(this, ev); ev.stopPropagation();
const newTrigger = ev.detail.value;
Object.keys(newTrigger).forEach((key) =>
newTrigger[key] === undefined || newTrigger[key] === ""
? delete newTrigger[key]
: {}
);
fireEvent(this, "value-changed", { value: newTrigger });
}
private _computeLabelCallback(schema: HaFormSchema): string {
return this.hass.localize(
schema.name === "entity_id"
? "ui.components.entity.entity-picker.entity"
: `ui.panel.config.automation.editor.triggers.type.state.${schema.name}`
);
} }
} }