Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions src/components/ha-base-time-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export class HaBaseTimeInput extends LitElement {
*/
@property({ type: Boolean }) autoValidate = false;

/**
* determines if inputs are required
*/
@property({ type: Boolean }) public required?: boolean;

/**
* 12 or 24 hr format
*/
Expand Down Expand Up @@ -115,7 +120,7 @@ export class HaBaseTimeInput extends LitElement {
@input=${this._valueChanged}
@focus=${this._onFocus}
no-spinner
required
.required=${this.required}
.autoValidate=${this.autoValidate}
maxlength="2"
.max=${this._hourMax}
Expand All @@ -135,7 +140,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus}
name="minutes"
no-spinner
required
.required=${this.required}
.autoValidate=${this.autoValidate}
maxlength="2"
max="59"
Expand All @@ -156,7 +161,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus}
name="seconds"
no-spinner
required
.required=${this.required}
.autoValidate=${this.autoValidate}
maxlength="2"
max="59"
Expand All @@ -177,7 +182,7 @@ export class HaBaseTimeInput extends LitElement {
@focus=${this._onFocus}
name="milliseconds"
no-spinner
required
.required=${this.required}
.autoValidate=${this.autoValidate}
maxlength="3"
max="999"
Expand All @@ -189,7 +194,7 @@ export class HaBaseTimeInput extends LitElement {
${this.format === 24
? ""
: html`<mwc-select
required
.required=${this.required}
.value=${this.amPm}
.disabled=${this.disabled}
name="amPm"
Expand Down
2 changes: 1 addition & 1 deletion src/components/ha-form/ha-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,12 @@ export class HaForm extends LitElement implements HaFormElement {
: ""}
${"selector" in item
? html`<ha-selector
.schema=${item}
.hass=${this.hass}
.selector=${item.selector}
.value=${getValue(this.data, item)}
.label=${this._computeLabel(item)}
.disabled=${this.disabled}
.required=${item.required}
></ha-selector>`
: dynamicElement(`ha-form-${item.type}`, {
schema: item,
Expand Down
37 changes: 37 additions & 0 deletions src/components/ha-selector/ha-selector-duration.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
6 changes: 4 additions & 2 deletions src/components/ha-selector/ha-selector-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class HaTextSelector extends LitElement {

@property({ type: Boolean }) public disabled = false;

@property({ type: Boolean }) public required = true;

@state() private _unmaskedPassword = false;

protected render() {
Expand All @@ -35,7 +37,7 @@ export class HaTextSelector extends LitElement {
autocapitalize="none"
autocomplete="off"
spellcheck="false"
required
.required=${this.required}
autogrow
></ha-textarea>`;
}
Expand All @@ -50,7 +52,7 @@ export class HaTextSelector extends LitElement {
? // reserve some space for the icon.
html`<div style="width: 24px"></div>`
: this.selector.text?.suffix}
required
.required=${this.required}
></ha-textfield>
${this.selector.text?.type === "password"
? html`<ha-icon-button
Expand Down
4 changes: 4 additions & 0 deletions src/components/ha-selector/ha-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import "./ha-selector-select";
import "./ha-selector-target";
import "./ha-selector-text";
import "./ha-selector-time";
import "./ha-selector-duration";

@customElement("ha-selector")
export class HaSelector extends LitElement {
Expand All @@ -30,6 +31,8 @@ export class HaSelector extends LitElement {

@property({ type: Boolean }) public disabled = false;

@property({ type: Boolean }) public required = true;

public focus() {
this.shadowRoot!.getElementById("selector")?.focus();
}
Expand All @@ -47,6 +50,7 @@ export class HaSelector extends LitElement {
label: this.label,
placeholder: this.placeholder,
disabled: this.disabled,
required: this.required,
id: "selector",
})}
`;
Expand Down
5 changes: 5 additions & 0 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export interface DeviceSelector {
};
}

export interface DurationSelector {
// eslint-disable-next-line @typescript-eslint/ban-types
duration: {};
}

export interface AddonSelector {
addon: {
name?: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import "@polymer/paper-input/paper-input";
import { html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators";
import {
Expand All @@ -10,19 +9,15 @@ import {
string,
union,
} from "superstruct";
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
import { fireEvent } from "../../../../../common/dom/fire_event";
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 { HomeAssistant } from "../../../../../types";
import { baseTriggerStruct, forDictStruct } from "../../structs";
import {
handleChangeEvent,
TriggerElement,
} from "../ha-automation-trigger-row";
import { TriggerElement } from "../ha-automation-trigger-row";
import "../../../../../components/ha-form/ha-form";
import { createDurationData } from "../../../../../common/datetime/create_duration_data";
import { HaFormSchema } from "../../../../../components/ha-form/types";

const stateTriggerStruct = assign(
baseTriggerStruct,
Expand All @@ -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")
export class HaStateTrigger extends LitElement implements TriggerElement {
@property({ attribute: false }) public hass!: HomeAssistant;
Expand Down Expand Up @@ -76,57 +78,40 @@ export class HaStateTrigger extends LitElement implements TriggerElement {
}

protected render() {
const { entity_id, attribute, to, from } = this.trigger;
const trgFor = createDurationData(this.trigger.for);

const data = { ...this.trigger, ...{ for: trgFor } };

return html`
<ha-entity-picker
.value=${entity_id}
@value-changed=${this._valueChanged}
.name=${"entity_id"}
.hass=${this.hass}
allow-custom-entity
></ha-entity-picker>
<ha-entity-attribute-picker
<ha-form
.hass=${this.hass}
.entityId=${entity_id}
.value=${attribute}
.name=${"attribute"}
.label=${this.hass.localize(
"ui.panel.config.automation.editor.triggers.type.state.attribute"
)}
.data=${data}
.schema=${SCHEMA}
@value-changed=${this._valueChanged}
allow-custom-value
></ha-entity-attribute-picker>
<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>
.computeLabel=${this._computeLabelCallback}
></ha-form>
`;
}

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}`
);
}
}

Expand Down