Fix various issues in time/duration input (#13462)

This commit is contained in:
Steve Repsher 2022-08-24 05:25:29 -04:00 committed by GitHub
parent 807bb10199
commit 8fd5273fae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 46 additions and 55 deletions

View File

@ -1,10 +1,11 @@
import "@material/mwc-list/mwc-list-item"; import "@material/mwc-list/mwc-list-item";
import { css, html, LitElement, TemplateResult } from "lit"; import { css, html, LitElement, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import { stopPropagation } from "../common/dom/stop_propagation"; import { stopPropagation } from "../common/dom/stop_propagation";
import "./ha-select"; import "./ha-select";
import "./ha-textfield"; import { HaTextField } from "./ha-textfield";
import "./ha-input-helper-text"; import "./ha-input-helper-text";
export interface TimeChangedEvent { export interface TimeChangedEvent {
@ -36,7 +37,7 @@ export class HaBaseTimeInput extends LitElement {
/** /**
* determines if inputs are required * determines if inputs are required
*/ */
@property({ type: Boolean }) public required?: boolean; @property({ type: Boolean }) public required = false;
/** /**
* 12 or 24 hr format * 12 or 24 hr format
@ -123,11 +124,6 @@ export class HaBaseTimeInput extends LitElement {
*/ */
@property() amPm: "AM" | "PM" = "AM"; @property() amPm: "AM" | "PM" = "AM";
/**
* Formatted time string
*/
@property() value?: string;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
${this.label ${this.label
@ -140,11 +136,11 @@ export class HaBaseTimeInput extends LitElement {
id="day" id="day"
type="number" type="number"
inputmode="numeric" inputmode="numeric"
.value=${this.days} .value=${this.days.toFixed()}
.label=${this.dayLabel} .label=${this.dayLabel}
name="days" name="days"
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focusin=${this._onFocus}
no-spinner no-spinner
.required=${this.required} .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
@ -161,16 +157,16 @@ export class HaBaseTimeInput extends LitElement {
id="hour" id="hour"
type="number" type="number"
inputmode="numeric" inputmode="numeric"
.value=${this.hours} .value=${this.hours.toFixed()}
.label=${this.hourLabel} .label=${this.hourLabel}
name="hours" name="hours"
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focusin=${this._onFocus}
no-spinner no-spinner
.required=${this.required} .required=${this.required}
.autoValidate=${this.autoValidate} .autoValidate=${this.autoValidate}
maxlength="2" maxlength="2"
.max=${this._hourMax} max=${ifDefined(this._hourMax)}
min="0" min="0"
.disabled=${this.disabled} .disabled=${this.disabled}
suffix=":" suffix=":"
@ -184,7 +180,7 @@ export class HaBaseTimeInput extends LitElement {
.value=${this._formatValue(this.minutes)} .value=${this._formatValue(this.minutes)}
.label=${this.minLabel} .label=${this.minLabel}
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focusin=${this._onFocus}
name="minutes" name="minutes"
no-spinner no-spinner
.required=${this.required} .required=${this.required}
@ -205,7 +201,7 @@ export class HaBaseTimeInput extends LitElement {
.value=${this._formatValue(this.seconds)} .value=${this._formatValue(this.seconds)}
.label=${this.secLabel} .label=${this.secLabel}
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focusin=${this._onFocus}
name="seconds" name="seconds"
no-spinner no-spinner
.required=${this.required} .required=${this.required}
@ -226,7 +222,7 @@ export class HaBaseTimeInput extends LitElement {
.value=${this._formatValue(this.milliseconds, 3)} .value=${this._formatValue(this.milliseconds, 3)}
.label=${this.millisecLabel} .label=${this.millisecLabel}
@input=${this._valueChanged} @input=${this._valueChanged}
@focus=${this._onFocus} @focusin=${this._onFocus}
name="milliseconds" name="milliseconds"
no-spinner no-spinner
.required=${this.required} .required=${this.required}
@ -260,9 +256,10 @@ export class HaBaseTimeInput extends LitElement {
`; `;
} }
private _valueChanged(ev) { private _valueChanged(ev: InputEvent) {
this[ev.target.name] = const textField = ev.currentTarget as HaTextField;
ev.target.name === "amPm" ? ev.target.value : Number(ev.target.value); this[textField.name] =
textField.name === "amPm" ? textField.value : Number(textField.value);
const value: TimeChangedEvent = { const value: TimeChangedEvent = {
hours: this.hours, hours: this.hours,
minutes: this.minutes, minutes: this.minutes,
@ -277,8 +274,8 @@ export class HaBaseTimeInput extends LitElement {
}); });
} }
private _onFocus(ev) { private _onFocus(ev: FocusEvent) {
ev.target.select(); (ev.currentTarget as HaTextField).select();
} }
/** /**
@ -293,7 +290,7 @@ export class HaBaseTimeInput extends LitElement {
*/ */
private get _hourMax() { private get _hourMax() {
if (this.noHoursLimit) { if (this.noHoursLimit) {
return null; return undefined;
} }
if (this.format === 12) { if (this.format === 12) {
return 12; return 12;

View File

@ -14,17 +14,17 @@ export interface HaDurationData {
@customElement("ha-duration-input") @customElement("ha-duration-input")
class HaDurationInput extends LitElement { class HaDurationInput extends LitElement {
@property({ attribute: false }) public data!: HaDurationData; @property({ attribute: false }) public data?: HaDurationData;
@property() public label?: string; @property() public label?: string;
@property() public helper?: string; @property() public helper?: string;
@property({ type: Boolean }) public required?: boolean; @property({ type: Boolean }) public required = false;
@property({ type: Boolean }) public enableMillisecond?: boolean; @property({ type: Boolean }) public enableMillisecond = false;
@property({ type: Boolean }) public enableDay?: boolean; @property({ type: Boolean }) public enableDay = false;
@property({ type: Boolean }) public disabled = false; @property({ type: Boolean }) public disabled = false;

View File

@ -5,9 +5,9 @@ import { HaFormElement, HaFormTimeData, HaFormTimeSchema } from "./types";
@customElement("ha-form-positive_time_period_dict") @customElement("ha-form-positive_time_period_dict")
export class HaFormTimePeriod extends LitElement implements HaFormElement { export class HaFormTimePeriod extends LitElement implements HaFormElement {
@property() public schema!: HaFormTimeSchema; @property({ attribute: false }) public schema!: HaFormTimeSchema;
@property() public data!: HaFormTimeData; @property({ attribute: false }) public data!: HaFormTimeData;
@property() public label!: string; @property() public label!: string;
@ -25,7 +25,7 @@ export class HaFormTimePeriod extends LitElement implements HaFormElement {
return html` return html`
<ha-duration-input <ha-duration-input
.label=${this.label} .label=${this.label}
.required=${this.schema.required} ?required=${this.schema.required}
.data=${this.data} .data=${this.data}
.disabled=${this.disabled} .disabled=${this.disabled}
></ha-duration-input> ></ha-duration-input>

View File

@ -11,9 +11,9 @@ import type { HaTimeInput } from "../ha-time-input";
@customElement("ha-selector-datetime") @customElement("ha-selector-datetime")
export class HaDateTimeSelector extends LitElement { export class HaDateTimeSelector extends LitElement {
@property() public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public selector!: DateTimeSelector; @property({ attribute: false }) public selector!: DateTimeSelector;
@property() public value?: string; @property() public value?: string;

View File

@ -2,15 +2,15 @@ import { html, LitElement } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property } from "lit/decorators";
import type { DurationSelector } from "../../data/selector"; import type { DurationSelector } from "../../data/selector";
import type { HomeAssistant } from "../../types"; import type { HomeAssistant } from "../../types";
import "../ha-duration-input"; import { HaDurationData } from "../ha-duration-input";
@customElement("ha-selector-duration") @customElement("ha-selector-duration")
export class HaTimeDuration extends LitElement { export class HaTimeDuration extends LitElement {
@property() public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public selector!: DurationSelector; @property({ attribute: false }) public selector!: DurationSelector;
@property() public value?: string; @property({ attribute: false }) public value?: HaDurationData;
@property() public label?: string; @property() public label?: string;
@ -28,7 +28,7 @@ export class HaTimeDuration extends LitElement {
.data=${this.value} .data=${this.value}
.disabled=${this.disabled} .disabled=${this.disabled}
.required=${this.required} .required=${this.required}
.enableDay=${this.selector.duration.enable_day} ?enableDay=${this.selector.duration.enable_day}
></ha-duration-input> ></ha-duration-input>
`; `;
} }

View File

@ -6,9 +6,9 @@ import "../ha-time-input";
@customElement("ha-selector-time") @customElement("ha-selector-time")
export class HaTimeSelector extends LitElement { export class HaTimeSelector extends LitElement {
@property() public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public selector!: TimeSelector; @property({ attribute: false }) public selector!: TimeSelector;
@property() public value?: string; @property() public value?: string;

View File

@ -43,7 +43,7 @@ export class HaTimeInput extends LitElement {
.minutes=${Number(parts[1])} .minutes=${Number(parts[1])}
.seconds=${Number(parts[2])} .seconds=${Number(parts[2])}
.format=${useAMPM ? 12 : 24} .format=${useAMPM ? 12 : 24}
.amPm=${useAMPM && (numberHours >= 12 ? "PM" : "AM")} .amPm=${useAMPM && numberHours >= 12 ? "PM" : "AM"}
.disabled=${this.disabled} .disabled=${this.disabled}
@value-changed=${this._timeChanged} @value-changed=${this._timeChanged}
.enableSecond=${this.enableSecond} .enableSecond=${this.enableSecond}

View File

@ -60,7 +60,7 @@ class MoreInfoInputDatetime extends LitElement {
ev.stopPropagation(); ev.stopPropagation();
} }
private _timeChanged(ev): void { private _timeChanged(ev: CustomEvent<{ value: string }>): void {
setInputDateTimeValue( setInputDateTimeValue(
this.hass!, this.hass!,
this.stateObj!.entity_id, this.stateObj!.entity_id,
@ -69,10 +69,9 @@ class MoreInfoInputDatetime extends LitElement {
? this.stateObj!.state.split(" ")[0] ? this.stateObj!.state.split(" ")[0]
: undefined : undefined
); );
ev.target.blur();
} }
private _dateChanged(ev): void { private _dateChanged(ev: CustomEvent<{ value: string }>): void {
setInputDateTimeValue( setInputDateTimeValue(
this.hass!, this.hass!,
this.stateObj!.entity_id, this.stateObj!.entity_id,
@ -81,8 +80,6 @@ class MoreInfoInputDatetime extends LitElement {
: undefined, : undefined,
ev.detail.value ev.detail.value
); );
ev.target.blur();
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {

View File

@ -1,5 +1,5 @@
import { html, LitElement, PropertyValues } from "lit"; import { html, LitElement, PropertyValues } from "lit";
import { customElement, property } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
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 type { HaDurationData } from "../../../../../components/ha-duration-input"; import type { HaDurationData } from "../../../../../components/ha-duration-input";
@ -13,9 +13,9 @@ import { createDurationData } from "../../../../../common/datetime/create_durati
export class HaDelayAction extends LitElement implements ActionElement { export class HaDelayAction extends LitElement implements ActionElement {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public action!: DelayAction; @property({ attribute: false }) public action!: DelayAction;
@property() public _timeData?: HaDurationData; @state() private _timeData?: HaDurationData;
public static get defaultConfig() { public static get defaultConfig() {
return { delay: "" }; return { delay: "" };

View File

@ -10,6 +10,7 @@ import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
import "../../../../../components/ha-duration-input"; import "../../../../../components/ha-duration-input";
import { createDurationData } from "../../../../../common/datetime/create_duration_data"; import { createDurationData } from "../../../../../common/datetime/create_duration_data";
import { TimeChangedEvent } from "../../../../../components/ha-base-time-input"; import { TimeChangedEvent } from "../../../../../components/ha-base-time-input";
import { ensureArray } from "../../../../../common/ensure-array";
@customElement("ha-automation-action-wait_for_trigger") @customElement("ha-automation-action-wait_for_trigger")
export class HaWaitForTriggerAction export class HaWaitForTriggerAction
@ -18,14 +19,13 @@ export class HaWaitForTriggerAction
{ {
@property({ attribute: false }) public hass!: HomeAssistant; @property({ attribute: false }) public hass!: HomeAssistant;
@property() public action!: WaitForTriggerAction; @property({ attribute: false }) public action!: WaitForTriggerAction;
public static get defaultConfig() { public static get defaultConfig() {
return { wait_for_trigger: [] }; return { wait_for_trigger: [] };
} }
protected render() { protected render() {
const { wait_for_trigger, continue_on_timeout } = this.action;
const timeData = createDurationData(this.action.timeout); const timeData = createDurationData(this.action.timeout);
return html` return html`
@ -43,12 +43,12 @@ export class HaWaitForTriggerAction
)} )}
> >
<ha-switch <ha-switch
.checked=${continue_on_timeout ?? true} .checked=${this.action.continue_on_timeout ?? true}
@change=${this._continueChanged} @change=${this._continueChanged}
></ha-switch> ></ha-switch>
</ha-formfield> </ha-formfield>
<ha-automation-trigger <ha-automation-trigger
.triggers=${wait_for_trigger} .triggers=${ensureArray(this.action.wait_for_trigger)}
.hass=${this.hass} .hass=${this.hass}
.name=${"wait_for_trigger"} .name=${"wait_for_trigger"}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}

View File

@ -97,7 +97,7 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
ev.stopPropagation(); ev.stopPropagation();
} }
private _timeChanged(ev): void { private _timeChanged(ev: CustomEvent<{ value: string }>): void {
const stateObj = this.hass!.states[this._config!.entity]; const stateObj = this.hass!.states[this._config!.entity];
setInputDateTimeValue( setInputDateTimeValue(
this.hass!, this.hass!,
@ -105,10 +105,9 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
ev.detail.value, ev.detail.value,
stateObj.attributes.has_date ? stateObj.state.split(" ")[0] : undefined stateObj.attributes.has_date ? stateObj.state.split(" ")[0] : undefined
); );
ev.target.blur();
} }
private _dateChanged(ev): void { private _dateChanged(ev: CustomEvent<{ value: string }>): void {
const stateObj = this.hass!.states[this._config!.entity]; const stateObj = this.hass!.states[this._config!.entity];
setInputDateTimeValue( setInputDateTimeValue(
@ -117,8 +116,6 @@ class HuiInputDatetimeEntityRow extends LitElement implements LovelaceRow {
stateObj.attributes.has_time ? stateObj.state.split(" ")[1] : undefined, stateObj.attributes.has_time ? stateObj.state.split(" ")[1] : undefined,
ev.detail.value ev.detail.value
); );
ev.target.blur();
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {