Add positive_time_period_dict to ha-form (#4090)

* Add positive_time_period_dict to ha-form

* select input on focus

* Update ha-form-positive_time_period_dict.ts
This commit is contained in:
Bram Kragten 2019-10-21 21:36:26 +02:00 committed by Paulus Schoutsen
parent c25a38b82f
commit 3973374f3f
5 changed files with 279 additions and 23 deletions

View File

@ -32,7 +32,7 @@ export class HaFormFloat extends LitElement implements HaFormElement {
return html`
<paper-input
.label=${this.label}
.value=${this.data}
.value=${this._value}
.required=${this.schema.required}
.autoValidate=${this.schema.required}
@value-changed=${this._valueChanged}
@ -42,9 +42,13 @@ export class HaFormFloat extends LitElement implements HaFormElement {
`;
}
private get _value() {
return this.data || 0;
}
private _valueChanged(ev: Event) {
const value = Number((ev.target as PaperInputElement).value);
if (this.data === value) {
if (this._value === value) {
return;
}
fireEvent(

View File

@ -41,7 +41,7 @@ export class HaFormInteger extends LitElement implements HaFormElement {
${this.label}
<ha-paper-slider
pin=""
.value=${this.data}
.value=${this._value}
.min=${this.schema.valueMin}
.max=${this.schema.valueMax}
@value-changed=${this._valueChanged}
@ -60,11 +60,15 @@ export class HaFormInteger extends LitElement implements HaFormElement {
`;
}
private get _value() {
return this.data || 0;
}
private _valueChanged(ev: Event) {
const value = Number(
(ev.target as PaperInputElement | PaperSliderElement).value
);
if (this.data === value) {
if (this._value === value) {
return;
}
fireEvent(

View File

@ -0,0 +1,119 @@
import {
customElement,
LitElement,
html,
property,
TemplateResult,
query,
} from "lit-element";
import { HaFormElement, HaFormTimeData, HaFormTimeSchema } from "./ha-form";
import { fireEvent } from "../../common/dom/fire_event";
@customElement("ha-form-positive_time_period_dict")
export class HaFormTimePeriod extends LitElement implements HaFormElement {
@property() public schema!: HaFormTimeSchema;
@property() public data!: HaFormTimeData;
@property() public label!: string;
@property() public suffix!: string;
@query("paper-time-input") private _input?: HTMLElement;
public focus() {
if (this._input) {
this._input.focus();
}
}
protected render(): TemplateResult | void {
return html`
<paper-time-input
.label=${this.label}
.required=${this.schema.required}
.autoValidate=${this.schema.required}
error-message="Required"
enable-second
format="24"
.hour=${this._parseDuration(this._hours)}
.min=${this._parseDuration(this._minutes)}
.sec=${this._parseDuration(this._seconds)}
@hour-changed=${this._hourChanged}
@min-changed=${this._minChanged}
@sec-changed=${this._secChanged}
float-input-labels
no-hours-limit
always-float-input-labels
hour-label="hh"
min-label="mm"
sec-label="ss"
></paper-time-input>
`;
}
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 = minutes + Math.floor(value / 60);
value %= 60;
}
if (unit === "minutes" && value > 59) {
hours = hours + Math.floor(value / 60);
value %= 60;
}
fireEvent(
this,
"value-changed",
{
value: {
hours,
minutes,
seconds: this._seconds,
...{ [unit]: value },
},
},
{ bubbles: false }
);
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-form-positive_time_period_dict": HaFormTimePeriod;
}
}

View File

@ -14,6 +14,7 @@ import "./ha-form-integer";
import "./ha-form-float";
import "./ha-form-boolean";
import "./ha-form-select";
import "./ha-form-positive_time_period_dict";
import { fireEvent } from "../../common/dom/fire_event";
export type HaFormSchema =
@ -21,7 +22,8 @@ export type HaFormSchema =
| HaFormIntegerSchema
| HaFormFloatSchema
| HaFormBooleanSchema
| HaFormSelectSchema;
| HaFormSelectSchema
| HaFormTimeSchema;
export interface HaFormBaseSchema {
name: string;
@ -55,6 +57,10 @@ export interface HaFormBooleanSchema extends HaFormBaseSchema {
type: "boolean";
}
export interface HaFormTimeSchema extends HaFormBaseSchema {
type: "time";
}
export interface HaFormDataContainer {
[key: string]: HaFormData;
}
@ -64,13 +70,19 @@ export type HaFormData =
| HaFormIntegerData
| HaFormFloatData
| HaFormBooleanData
| HaFormSelectData;
| HaFormSelectData
| HaFormTimeData;
export type HaFormStringData = string;
export type HaFormIntegerData = number;
export type HaFormFloatData = number;
export type HaFormBooleanData = boolean;
export type HaFormSelectData = string;
export interface HaFormTimeData {
hours?: number;
minutes?: number;
seconds?: number;
}
export interface HaFormElement extends LitElement {
schema: HaFormSchema;

View File

@ -87,6 +87,10 @@ export class PaperTimeInput extends PolymerElement {
label {
@apply --paper-font-caption;
color: var(
--paper-input-container-color,
var(--secondary-text-color)
);
}
.time-input-wrap {
@ -106,14 +110,17 @@ export class PaperTimeInput extends PolymerElement {
id="hour"
type="number"
value="{{hour}}"
label="[[hourLabel]]"
on-change="_shouldFormatHour"
required=""
on-focus="_onFocus"
required
prevent-invalid-input
auto-validate="[[autoValidate]]"
prevent-invalid-input=""
maxlength="2"
max="[[_computeHourMax(format)]]"
min="0"
no-label-float=""
no-label-float$="[[!floatInputLabels]]"
always-float-label$="[[alwaysFloatInputLabels]]"
disabled="[[disabled]]"
>
<span suffix="" slot="suffix">:</span>
@ -124,15 +131,40 @@ export class PaperTimeInput extends PolymerElement {
id="min"
type="number"
value="{{min}}"
label="[[minLabel]]"
on-change="_formatMin"
required=""
on-focus="_onFocus"
required
auto-validate="[[autoValidate]]"
prevent-invalid-input=""
prevent-invalid-input
maxlength="2"
max="59"
min="0"
no-label-float=""
no-label-float$="[[!floatInputLabels]]"
always-float-label$="[[alwaysFloatInputLabels]]"
disabled="[[disabled]]"
>
<span hidden$="[[!enableSecond]]" suffix slot="suffix">:</span>
</paper-input>
<!-- Sec Input -->
<paper-input
id="sec"
type="number"
value="{{sec}}"
label="[[secLabel]]"
on-change="_formatSec"
on-focus="_onFocus"
required
auto-validate="[[autoValidate]]"
prevent-invalid-input
maxlength="2"
max="59"
min="0"
no-label-float$="[[!floatInputLabels]]"
always-float-label$="[[alwaysFloatInputLabels]]"
disabled="[[disabled]]"
hidden$="[[!enableSecond]]"
>
</paper-input>
@ -180,6 +212,20 @@ export class PaperTimeInput extends PolymerElement {
type: Boolean,
value: false,
},
/**
* float the input labels
*/
floatInputLabels: {
type: Boolean,
value: false,
},
/**
* always float the input labels
*/
alwaysFloatInputLabels: {
type: Boolean,
value: false,
},
/**
* 12 or 24 hr format
*/
@ -208,6 +254,48 @@ export class PaperTimeInput extends PolymerElement {
type: String,
notify: true,
},
/**
* second
*/
sec: {
type: String,
notify: true,
},
/**
* Suffix for the hour input
*/
hourLabel: {
type: String,
value: "",
},
/**
* Suffix for the min input
*/
minLabel: {
type: String,
value: ":",
},
/**
* Suffix for the sec input
*/
secLabel: {
type: String,
value: "",
},
/**
* show the sec field
*/
enableSecond: {
type: Boolean,
value: false,
},
/**
* limit hours input
*/
noHoursLimit: {
type: Boolean,
value: false,
},
/**
* AM or PM
*/
@ -223,7 +311,7 @@ export class PaperTimeInput extends PolymerElement {
type: String,
notify: true,
readOnly: true,
computed: "_computeTime(min, hour, amPm)",
computed: "_computeTime(min, hour, sec, amPm)",
},
};
}
@ -238,6 +326,10 @@ export class PaperTimeInput extends PolymerElement {
if (!this.$.hour.validate() | !this.$.min.validate()) {
valid = false;
}
// Validate second field
if (this.enableSecond && !this.$.sec.validate()) {
valid = false;
}
// Validate AM PM if 12 hour time
if (this.format === 12 && !this.$.dropdown.validate()) {
valid = false;
@ -248,15 +340,37 @@ export class PaperTimeInput extends PolymerElement {
/**
* Create time string
*/
_computeTime(min, hour, amPm) {
if (hour && min) {
// No ampm on 24 hr time
if (this.format === 24) {
amPm = "";
_computeTime(min, hour, sec, amPm) {
let str;
if (hour || min || (sec && this.enableSecond)) {
hour = hour || "00";
min = min || "00";
sec = sec || "00";
str = hour + ":" + min;
// add sec field
if (this.enableSecond && sec) {
str = str + ":" + sec;
}
// No ampm on 24 hr time
if (this.format === 12) {
str = str + " " + amPm;
}
return hour + ":" + min + " " + amPm;
}
return undefined;
return str;
}
_onFocus(ev) {
ev.target.inputElement.inputElement.select();
}
/**
* Format sec
*/
_formatSec() {
if (this.sec.toString().length === 1) {
this.sec = this.sec.toString().padStart(2, "0");
}
}
/**
@ -264,16 +378,16 @@ export class PaperTimeInput extends PolymerElement {
*/
_formatMin() {
if (this.min.toString().length === 1) {
this.min = this.min < 10 ? "0" + this.min : this.min;
this.min = this.min.toString().padStart(2, "0");
}
}
/**
* Hour needs a leading zero in 24hr format
* Format hour
*/
_shouldFormatHour() {
if (this.format === 24 && this.hour.toString().length === 1) {
this.hour = this.hour < 10 ? "0" + this.hour : this.hour;
this.hour = this.hour.toString().padStart(2, "0");
}
}
@ -281,6 +395,9 @@ export class PaperTimeInput extends PolymerElement {
* 24 hour format has a max hr of 23
*/
_computeHourMax(format) {
if (this.noHoursLimit) {
return null;
}
if (format === 12) {
return format;
}