Basic input-datetime entity row (#3121)

* Basic input-datetime entity row

* Address review comments

* Fix imports
This commit is contained in:
Thomas Lovén 2019-04-26 06:47:46 +02:00 committed by Paulus Schoutsen
parent cd6250c495
commit 981dd5df63
5 changed files with 268 additions and 1 deletions

View File

@ -0,0 +1,126 @@
import {
html,
css,
LitElement,
TemplateResult,
property,
customElement,
} from "lit-element";
import "@polymer/paper-input/paper-input";
// tslint:disable-next-line:no-duplicate-imports
import { PaperInputElement } from "@polymer/paper-input/paper-input";
@customElement("ha-date-input")
export class HaDateInput extends LitElement {
@property() public year?: string;
@property() public month?: string;
@property() public day?: string;
@property({ type: Boolean }) public disabled = false;
static get styles() {
return css`
:host {
display: block;
font-family: var(--paper-font-common-base_-_font-family);
-webkit-font-smoothing: var(
--paper-font-common-base_-_-webkit-font-smoothing
);
}
paper-input {
width: 30px;
text-align: center;
--paper-input-container-input_-_-moz-appearance: textfield;
--paper-input-container-input-webkit-spinner_-_-webkit-appearance: none;
--paper-input-container-input-webkit-spinner_-_margin: 0;
--paper-input-container-input-webkit-spinner_-_display: none;
}
paper-input#year {
width: 50px;
}
.date-input-wrap {
display: flex;
flex-direction: row;
}
`;
}
protected render(): TemplateResult {
return html`
<div class="date-input-wrap">
<paper-input
id="year"
type="number"
.value=${this.year}
@change=${this._formatYear}
maxlength="4"
max="9999"
min="0"
.disabled=${this.disabled}
no-label-float
>
<span suffix="" slot="suffix">-</span>
</paper-input>
<paper-input
id="month"
type="number"
.value=${this.month}
@change=${this._formatMonth}
maxlength="2"
max="12"
min="1"
.disabled=${this.disabled}
no-label-float
>
<span suffix="" slot="suffix">-</span>
</paper-input>
<paper-input
id="day"
type="number"
.value=${this.day}
@change=${this._formatDay}
maxlength="2"
max="31"
min="1"
.disabled=${this.disabled}
no-label-float
>
</paper-input>
</div>
`;
}
private _formatYear() {
const yearElement = this.shadowRoot!.getElementById(
"year"
) as PaperInputElement;
this.year = yearElement.value!;
}
private _formatMonth() {
const monthElement = this.shadowRoot!.getElementById(
"month"
) as PaperInputElement;
this.month = ("0" + monthElement.value!).slice(-2);
}
private _formatDay() {
const dayElement = this.shadowRoot!.getElementById(
"day"
) as PaperInputElement;
this.day = ("0" + dayElement.value!).slice(-2);
}
get value() {
return `${this.year}-${this.month}-${this.day}`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-date-input": HaDateInput;
}
}

View File

@ -23,7 +23,7 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
class PaperTimeInput extends PolymerElement {
export class PaperTimeInput extends PolymerElement {
static get template() {
return html`
<style>

View File

@ -0,0 +1,11 @@
import { HomeAssistant } from "../types";
export const setInputDateTimeValue = (
hass: HomeAssistant,
entityId: string,
time: string | undefined = undefined,
date: string | undefined = undefined
) => {
const param = { entity_id: entityId, time, date };
hass.callService(entityId.split(".", 1)[0], "set_datetime", param);
};

View File

@ -10,6 +10,7 @@ import {
import "../entity-rows/hui-climate-entity-row";
import "../entity-rows/hui-cover-entity-row";
import "../entity-rows/hui-group-entity-row";
import "../entity-rows/hui-input-datetime-entity-row";
import "../entity-rows/hui-input-number-entity-row";
import "../entity-rows/hui-input-select-entity-row";
import "../entity-rows/hui-input-text-entity-row";
@ -58,6 +59,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
// Temporary. Once climate is rewritten,
// water heater should get it's own row.
water_heater: "climate",
input_datetime: "input-datetime",
};
const TIMEOUT = 2000;

View File

@ -0,0 +1,128 @@
import {
html,
LitElement,
TemplateResult,
property,
PropertyValues,
customElement,
} from "lit-element";
import "../components/hui-generic-entity-row";
import "../../../components/paper-time-input.js";
// tslint:disable-next-line:no-duplicate-imports
import { PaperTimeInput } from "../../../components/paper-time-input.js";
import "../../../components/ha-date-input";
// tslint:disable-next-line:no-duplicate-imports
import { HaDateInput } from "../../../components/ha-date-input";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
import { setInputDateTimeValue } from "../../../data/input_datetime";
import { hasConfigOrEntityChanged } from "../common/has-changed";
@customElement("hui-input-datetime-entity-row")
class HuiInputDatetimeEntityRow extends LitElement implements EntityRow {
@property() public hass?: HomeAssistant;
@property() private _config?: EntityConfig;
public setConfig(config: EntityConfig): void {
if (!config) {
throw new Error("Configuration error");
}
this._config = config;
}
protected shouldUpdate(changedProps: PropertyValues): boolean {
return hasConfigOrEntityChanged(this, changedProps);
}
protected render(): TemplateResult | void {
if (!this._config || !this.hass) {
return html``;
}
const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<hui-warning
>${this.hass.localize(
"ui.panel.lovelace.warning.entity_not_found",
"entity",
this._config.entity
)}</hui-warning
>
`;
}
return html`
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
${stateObj.attributes.has_date
? html`
<ha-date-input
.year=${stateObj.attributes.year}
.month=${("0" + stateObj.attributes.month).slice(-2)}
.day=${("0" + stateObj.attributes.day).slice(-2)}
@change=${this._selectedValueChanged}
@click=${this._stopEventPropagation}
></ha-date-input>
${stateObj.attributes.has_time ? "," : ""}
`
: ``}
${stateObj.attributes.has_time
? html`
<paper-time-input
.hour=${stateObj.state === "unknown"
? ""
: ("0" + stateObj.attributes.hour).slice(-2)}
.min=${stateObj.state === "unknown"
? ""
: ("0" + stateObj.attributes.minute).slice(-2)}
.amPm=${false}
@change=${this._selectedValueChanged}
@click=${this._stopEventPropagation}
hide-label
format="24"
></paper-time-input>
`
: ``}
</hui-generic-entity-row>
`;
}
private _stopEventPropagation(ev: Event): void {
ev.stopPropagation();
}
private get _timeInputEl(): PaperTimeInput {
return this.shadowRoot!.querySelector("paper-time-input")!;
}
private get _dateInputEl(): HaDateInput {
return this.shadowRoot!.querySelector("ha-date-input")!;
}
private _selectedValueChanged(ev): void {
const stateObj = this.hass!.states[this._config!.entity];
const time =
this._timeInputEl !== null
? this._timeInputEl.value.trim() + ":00"
: undefined;
const date =
this._dateInputEl !== null ? this._dateInputEl.value : undefined;
if (time !== stateObj.state) {
setInputDateTimeValue(this.hass!, stateObj.entity_id, time, date);
}
ev.target.blur();
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-input-datetime-entity-row": HuiInputDatetimeEntityRow;
}
}