diff --git a/src/components/ha-form/ha-form-positive_time_period_dict.ts b/src/components/ha-form/ha-form-positive_time_period_dict.ts
index d5a0db5975..453eaf2a68 100644
--- a/src/components/ha-form/ha-form-positive_time_period_dict.ts
+++ b/src/components/ha-form/ha-form-positive_time_period_dict.ts
@@ -6,8 +6,7 @@ import {
query,
TemplateResult,
} from "lit-element";
-import { fireEvent } from "../../common/dom/fire_event";
-import "../paper-time-input";
+import "../ha-time-input";
import { HaFormElement, HaFormTimeData, HaFormTimeSchema } from "./ha-form";
@customElement("ha-form-positive_time_period_dict")
@@ -20,7 +19,7 @@ export class HaFormTimePeriod extends LitElement implements HaFormElement {
@property() public suffix!: string;
- @query("paper-time-input", true) private _input?: HTMLElement;
+ @query("ha-time-input", true) private _input?: HTMLElement;
public focus() {
if (this._input) {
@@ -30,86 +29,13 @@ export class HaFormTimePeriod extends LitElement implements HaFormElement {
protected render(): TemplateResult {
return html`
-
+ .data=${this.data}
+ >
`;
}
-
- private get _hours() {
- return this.data && this.data.hours ? Number(this.data.hours) : 0;
- }
-
- private get _minutes() {
- return this.data && this.data.minutes ? Number(this.data.minutes) : 0;
- }
-
- private get _seconds() {
- return this.data && this.data.seconds ? Number(this.data.seconds) : 0;
- }
-
- private _parseDuration(value) {
- return value.toString().padStart(2, "0");
- }
-
- private _hourChanged(ev) {
- this._durationChanged(ev, "hours");
- }
-
- private _minChanged(ev) {
- this._durationChanged(ev, "minutes");
- }
-
- private _secChanged(ev) {
- this._durationChanged(ev, "seconds");
- }
-
- private _durationChanged(ev, unit) {
- let value = Number(ev.detail.value);
-
- if (value === this[`_${unit}`]) {
- return;
- }
-
- let hours = this._hours;
- let minutes = this._minutes;
-
- if (unit === "seconds" && value > 59) {
- minutes += Math.floor(value / 60);
- value %= 60;
- }
-
- if (unit === "minutes" && value > 59) {
- hours += Math.floor(value / 60);
- value %= 60;
- }
-
- fireEvent(this, "value-changed", {
- value: {
- hours,
- minutes,
- seconds: this._seconds,
- ...{ [unit]: value },
- },
- });
- }
}
declare global {
diff --git a/src/components/ha-form/ha-form.ts b/src/components/ha-form/ha-form.ts
index bab97d6a22..25cf8cd18d 100644
--- a/src/components/ha-form/ha-form.ts
+++ b/src/components/ha-form/ha-form.ts
@@ -8,6 +8,7 @@ import {
} from "lit-element";
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
import { fireEvent } from "../../common/dom/fire_event";
+import { HaTimeData } from "../ha-time-input";
import "./ha-form-boolean";
import "./ha-form-constant";
import "./ha-form-float";
@@ -71,7 +72,7 @@ export interface HaFormBooleanSchema extends HaFormBaseSchema {
}
export interface HaFormTimeSchema extends HaFormBaseSchema {
- type: "time";
+ type: "positive_time_period_dict";
}
export interface HaFormDataContainer {
@@ -93,11 +94,7 @@ export type HaFormFloatData = number;
export type HaFormBooleanData = boolean;
export type HaFormSelectData = string;
export type HaFormMultiSelectData = string[];
-export interface HaFormTimeData {
- hours?: number;
- minutes?: number;
- seconds?: number;
-}
+export type HaFormTimeData = HaTimeData;
export interface HaFormElement extends LitElement {
schema: HaFormSchema | HaFormSchema[];
diff --git a/src/components/ha-time-input.ts b/src/components/ha-time-input.ts
new file mode 100644
index 0000000000..e72e1a09d9
--- /dev/null
+++ b/src/components/ha-time-input.ts
@@ -0,0 +1,146 @@
+import {
+ customElement,
+ html,
+ LitElement,
+ property,
+ query,
+ TemplateResult,
+} from "lit-element";
+import { fireEvent } from "../common/dom/fire_event";
+import "./paper-time-input";
+
+export interface HaTimeData {
+ hours?: number;
+ minutes?: number;
+ seconds?: number;
+ milliseconds?: number;
+}
+
+@customElement("ha-time-input")
+class HaTimeInput extends LitElement {
+ @property() public data!: HaTimeData;
+
+ @property() public label?: string;
+
+ @property() public suffix?: string;
+
+ @property({ type: Boolean }) public required?: boolean;
+
+ @property({ type: Boolean }) public enableMillisecond?: boolean;
+
+ @query("paper-time-input", true) private _input?: HTMLElement;
+
+ public focus() {
+ if (this._input) {
+ this._input.focus();
+ }
+ }
+
+ protected render(): TemplateResult {
+ return html`
+
+ `;
+ }
+
+ private get _hours() {
+ return this.data && this.data.hours ? Number(this.data.hours) : 0;
+ }
+
+ private get _minutes() {
+ return this.data && this.data.minutes ? Number(this.data.minutes) : 0;
+ }
+
+ private get _seconds() {
+ return this.data && this.data.seconds ? Number(this.data.seconds) : 0;
+ }
+
+ private get _milliseconds() {
+ return this.data && this.data.milliseconds
+ ? Number(this.data.milliseconds)
+ : 0;
+ }
+
+ private _parseDuration(value) {
+ return value.toString().padStart(2, "0");
+ }
+
+ private _parseDurationMillisec(value) {
+ return value.toString().padStart(3, "0");
+ }
+
+ private _hourChanged(ev) {
+ this._durationChanged(ev, "hours");
+ }
+
+ private _minChanged(ev) {
+ this._durationChanged(ev, "minutes");
+ }
+
+ private _secChanged(ev) {
+ this._durationChanged(ev, "seconds");
+ }
+
+ private _millisecChanged(ev) {
+ this._durationChanged(ev, "milliseconds");
+ }
+
+ private _durationChanged(ev, unit) {
+ let value = Number(ev.detail.value);
+
+ if (value === this[`_${unit}`]) {
+ return;
+ }
+
+ let hours = this._hours;
+ let minutes = this._minutes;
+
+ if (unit === "seconds" && value > 59) {
+ minutes += Math.floor(value / 60);
+ value %= 60;
+ }
+
+ if (unit === "minutes" && value > 59) {
+ hours += Math.floor(value / 60);
+ value %= 60;
+ }
+
+ fireEvent(this, "value-changed", {
+ value: {
+ hours,
+ minutes,
+ seconds: this._seconds,
+ milliseconds: this._milliseconds,
+ ...{ [unit]: value },
+ },
+ });
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "ha-time-input": HaTimeInput;
+ }
+}
diff --git a/src/components/paper-time-input.js b/src/components/paper-time-input.js
index 7ec7cc64ad..944360227d 100644
--- a/src/components/paper-time-input.js
+++ b/src/components/paper-time-input.js
@@ -103,6 +103,10 @@ export class PaperTimeInput extends PolymerElement {
[hidden] {
display: none !important;
}
+
+ #millisec {
+ width: 38px;
+ }
@@ -167,6 +171,28 @@ export class PaperTimeInput extends PolymerElement {
always-float-label$="[[alwaysFloatInputLabels]]"
disabled="[[disabled]]"
hidden$="[[!enableSecond]]"
+ >
+ :
+
+
+
+
@@ -263,6 +289,13 @@ export class PaperTimeInput extends PolymerElement {
type: String,
notify: true,
},
+ /**
+ * milli second
+ */
+ millisec: {
+ type: String,
+ notify: true,
+ },
/**
* Suffix for the hour input
*/
@@ -284,6 +317,13 @@ export class PaperTimeInput extends PolymerElement {
type: String,
value: "",
},
+ /**
+ * Suffix for the milli sec input
+ */
+ millisecLabel: {
+ type: String,
+ value: "",
+ },
/**
* show the sec field
*/
@@ -291,6 +331,13 @@ export class PaperTimeInput extends PolymerElement {
type: Boolean,
value: false,
},
+ /**
+ * show the milli sec field
+ */
+ enableMillisecond: {
+ type: Boolean,
+ value: false,
+ },
/**
* limit hours input
*/
@@ -313,7 +360,7 @@ export class PaperTimeInput extends PolymerElement {
type: String,
notify: true,
readOnly: true,
- computed: "_computeTime(min, hour, sec, amPm)",
+ computed: "_computeTime(min, hour, sec, millisec, amPm)",
},
};
}
@@ -332,6 +379,10 @@ export class PaperTimeInput extends PolymerElement {
if (this.enableSecond && !this.$.sec.validate()) {
valid = false;
}
+ // Validate milli second field
+ if (this.enableMillisecond && !this.$.millisec.validate()) {
+ valid = false;
+ }
// Validate AM PM if 12 hour time
if (this.format === 12 && !this.$.dropdown.validate()) {
valid = false;
@@ -342,17 +393,27 @@ export class PaperTimeInput extends PolymerElement {
/**
* Create time string
*/
- _computeTime(min, hour, sec, amPm) {
+ _computeTime(min, hour, sec, millisec, amPm) {
let str;
- if (hour || min || (sec && this.enableSecond)) {
+ if (
+ hour ||
+ min ||
+ (sec && this.enableSecond) ||
+ (millisec && this.enableMillisecond)
+ ) {
hour = hour || "00";
min = min || "00";
sec = sec || "00";
+ millisec = millisec || "000";
str = hour + ":" + min;
// add sec field
if (this.enableSecond && sec) {
str = str + ":" + sec;
}
+ // add milli sec field
+ if (this.enableMillisecond && millisec) {
+ str = str + ":" + millisec;
+ }
// No ampm on 24 hr time
if (this.format === 12) {
str = str + " " + amPm;
@@ -366,6 +427,15 @@ export class PaperTimeInput extends PolymerElement {
ev.target.inputElement.inputElement.select();
}
+ /**
+ * Format milli sec
+ */
+ _formatMillisec() {
+ if (this.millisec.toString().length === 1) {
+ this.millisec = this.millisec.toString().padStart(3, "0");
+ }
+ }
+
/**
* Format sec
*/
diff --git a/src/data/script.ts b/src/data/script.ts
index a7cfa7506a..e528754f5e 100644
--- a/src/data/script.ts
+++ b/src/data/script.ts
@@ -45,8 +45,15 @@ export interface DeviceAction {
entity_id: string;
}
+export interface DelayActionParts {
+ milliseconds?: number;
+ seconds?: number;
+ minutes?: number;
+ hours?: number;
+ days?: number;
+}
export interface DelayAction {
- delay: number;
+ delay: number | Partial;
}
export interface SceneAction {
diff --git a/src/panels/config/automation/action/types/ha-automation-action-delay.ts b/src/panels/config/automation/action/types/ha-automation-action-delay.ts
index 9b44078768..b8e7cee0a5 100644
--- a/src/panels/config/automation/action/types/ha-automation-action-delay.ts
+++ b/src/panels/config/automation/action/types/ha-automation-action-delay.ts
@@ -1,10 +1,12 @@
import "@polymer/paper-input/paper-input";
import { customElement, html, LitElement, property } from "lit-element";
+import { fireEvent } from "../../../../../common/dom/fire_event";
import "../../../../../components/entity/ha-entity-picker";
+import { HaFormTimeData } from "../../../../../components/ha-form/ha-form";
import "../../../../../components/ha-service-picker";
import { DelayAction } from "../../../../../data/script";
import { HomeAssistant } from "../../../../../types";
-import { ActionElement, handleChangeEvent } from "../ha-automation-action-row";
+import { ActionElement } from "../ha-automation-action-row";
@customElement("ha-automation-action-delay")
export class HaDelayAction extends LitElement implements ActionElement {
@@ -17,22 +19,46 @@ export class HaDelayAction extends LitElement implements ActionElement {
}
protected render() {
- const { delay } = this.action;
+ let data: HaFormTimeData = {};
+
+ if (typeof this.action.delay !== "object") {
+ const parts = this.action.delay?.toString().split(":") || [];
+ data = {
+ hours: Number(parts[0]),
+ minutes: Number(parts[1]),
+ seconds: Number(parts[2]),
+ milliseconds: Number(parts[3]),
+ };
+ } else {
+ const { days, minutes, seconds, milliseconds } = this.action.delay;
+ let { hours } = this.action.delay || 0;
+ hours = (hours || 0) + (days || 0) * 24;
+ data = {
+ hours: hours,
+ minutes: minutes,
+ seconds: seconds,
+ milliseconds: milliseconds,
+ };
+ }
return html`
-
+ >
`;
}
- private _valueChanged(ev: CustomEvent): void {
- handleChangeEvent(this, ev);
+ private _valueChanged(ev: CustomEvent) {
+ ev.stopPropagation();
+ const value = ev.detail.value;
+ if (!value) {
+ return;
+ }
+ fireEvent(this, "value-changed", {
+ value: { ...this.action, delay: value },
+ });
}
}