mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 01:06:35 +00:00
Basic input-datetime entity row (#3121)
* Basic input-datetime entity row * Address review comments * Fix imports
This commit is contained in:
parent
cd6250c495
commit
981dd5df63
126
src/components/ha-date-input.ts
Normal file
126
src/components/ha-date-input.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@ import "@polymer/paper-dropdown-menu/paper-dropdown-menu";
|
|||||||
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
import { html } from "@polymer/polymer/lib/utils/html-tag";
|
||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
class PaperTimeInput extends PolymerElement {
|
export class PaperTimeInput extends PolymerElement {
|
||||||
static get template() {
|
static get template() {
|
||||||
return html`
|
return html`
|
||||||
<style>
|
<style>
|
||||||
|
11
src/data/input_datetime.ts
Normal file
11
src/data/input_datetime.ts
Normal 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);
|
||||||
|
};
|
@ -10,6 +10,7 @@ import {
|
|||||||
import "../entity-rows/hui-climate-entity-row";
|
import "../entity-rows/hui-climate-entity-row";
|
||||||
import "../entity-rows/hui-cover-entity-row";
|
import "../entity-rows/hui-cover-entity-row";
|
||||||
import "../entity-rows/hui-group-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-number-entity-row";
|
||||||
import "../entity-rows/hui-input-select-entity-row";
|
import "../entity-rows/hui-input-select-entity-row";
|
||||||
import "../entity-rows/hui-input-text-entity-row";
|
import "../entity-rows/hui-input-text-entity-row";
|
||||||
@ -58,6 +59,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
|
|||||||
// Temporary. Once climate is rewritten,
|
// Temporary. Once climate is rewritten,
|
||||||
// water heater should get it's own row.
|
// water heater should get it's own row.
|
||||||
water_heater: "climate",
|
water_heater: "climate",
|
||||||
|
input_datetime: "input-datetime",
|
||||||
};
|
};
|
||||||
const TIMEOUT = 2000;
|
const TIMEOUT = 2000;
|
||||||
|
|
||||||
|
128
src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts
Normal file
128
src/panels/lovelace/entity-rows/hui-input-datetime-entity-row.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user