WIP: add an input_datetime (#418)

* Initial work on input_datetime

* Properly format date and time

* Linting

* Use dom-if

* Converting to Polymer 2 class

* Some linting

* Cache domain, linting

* More linting

* Use on-value-changed instead of value observer.

Also, fix off-by-one b/c of 0-indexed months. Thanks, JavaScript.
This commit is contained in:
Lukas Barth 2017-10-25 08:17:26 +02:00 committed by Paulus Schoutsen
parent 417d8e7ed8
commit 27ce63bb0c
4 changed files with 197 additions and 2 deletions

View File

@ -46,6 +46,7 @@
"paper-spinner": "PolymerElements/paper-spinner#^2.0.0",
"paper-styles": "PolymerElements/paper-styles#^2.0.0",
"paper-tabs": "PolymerElements/paper-tabs#^2.0.0",
"paper-time-input": "ryanburns23/paper-time-input#^2.0.4",
"paper-toast": "PolymerElements/paper-toast#^2.0.0",
"paper-toggle-button": "PolymerElements/paper-toggle-button#^2.0.0",
"polymer": "^2.1.1",

View File

@ -17,6 +17,7 @@
<link rel='import' href='more-info-sun.html'>
<link rel='import' href='more-info-updater.html'>
<link rel='import' href='more-info-vacuum.html'>
<link rel='import' href='more-info-input_datetime.html'>
<script>
Polymer({

View File

@ -0,0 +1,168 @@
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../components/ha-relative-time.html">
<link rel="import" href="../../bower_components/vaadin-date-picker/vaadin-date-picker.html">
<link rel="import" href="../../bower_components/paper-time-input/paper-time-input.html">
<dom-module id="more-info-input_datetime">
<template>
<div class$='[[computeClassNames(stateObj)]]'>
<template is="dom-if" if="[[doesHaveDate(stateObj)]]" restamp>
<div>
<vaadin-date-picker id="dateInput" on-value-changed="dateTimeChanged" label="Date" value="{{selectedDate}}"></vaadin-date-picker>
</div>
</template>
<template is="dom-if" if="[[doesHaveTime(stateObj)]]" restamp>
<div>
<paper-time-input hour="{{selectedHour}}" min="{{selectedMinute}}" format="24"></paper-time-input>
</div>
</template>
</div>
</template>
</dom-module>
<script>
class DatetimeInput extends Polymer.Element {
static get is() {
return 'more-info-input_datetime';
}
constructor() {
super();
this.is_ready = false;
}
static get properties() {
return {
hass: {
type: Object,
},
stateObj: {
type: Object,
observer: 'stateObjChanged',
},
selectedHour: {
type: Number,
observer: 'dateTimeChanged',
},
selectedMinute: {
type: Number,
observer: 'dateTimeChanged',
},
selectedDate: {
type: String,
}
};
}
ready() {
super.ready();
this.is_ready = true;
}
/* Convert the date in the stateObj into a string useable by vaadin-date-picker */
getDateString(stateObj) {
var monthFiller;
if (stateObj.attributes.month < 10) {
monthFiller = '0';
} else {
monthFiller = '';
}
var dayFiller;
if (stateObj.attributes.day < 10) {
dayFiller = '0';
} else {
dayFiller = '';
}
return stateObj.attributes.year + '-' + monthFiller + stateObj.attributes.month + '-' + dayFiller + stateObj.attributes.day;
}
/* Should fire when any value was changed *by the user*, not b/c of setting
* initial values. */
dateTimeChanged() {
// Check if the change is really coming from the user
if (!this.is_ready) {
return;
}
var minuteFiller;
var changed = false;
var serviceData = {
entity_id: this.stateObj.entity_id
};
if (this.stateObj.attributes.has_time) {
changed |= (parseInt(this.selectedMinute) !== this.stateObj.attributes.minute);
changed |= (parseInt(this.selectedHour) !== this.stateObj.attributes.hour);
if (this.selectedMinute < 10) {
minuteFiller = '0';
} else {
minuteFiller = '';
}
var timeStr = this.selectedHour + ':' + minuteFiller + this.selectedMinute;
serviceData.time = timeStr;
}
if (this.stateObj.attributes.has_date) {
const dateInput = this.shadowRoot.querySelector('#dateInput');
const dateValInput = new Date(dateInput.value);
const dateValState = new Date(
this.stateObj.attributes.year,
this.stateObj.attributes.month - 1,
this.stateObj.attributes.day
);
changed |= (dateValState !== dateValInput);
serviceData.date = dateInput.value;
if (dateInput.value.length < 1) {
return; // Date was not set
}
}
if (changed) {
this.hass.callService('input_datetime', 'set_datetime', serviceData);
}
}
stateObjChanged(newVal) {
// Set to non-ready s.t. dateTimeChanged does not fire
this.is_ready = false;
if (newVal.attributes.has_time) {
this.selectedHour = newVal.attributes.hour;
this.selectedMinute = newVal.attributes.minute;
}
if (newVal.attributes.has_date) {
this.selectedDate = this.getDateString(newVal);
}
this.is_ready = true;
}
doesHaveDate(stateObj) {
return stateObj.attributes.has_date;
}
doesHaveTime(stateObj) {
return stateObj.attributes.has_time;
}
computeClassNames(stateObj) {
return 'more-info-input_datetime ' + window.hassUtil.attributeClassNames(stateObj, ['has_time', 'has_date']);
}
}
customElements.define(DatetimeInput.is, DatetimeInput);
</script>

View File

@ -26,7 +26,7 @@ window.hassUtil.DOMAINS_WITH_CARD = [
window.hassUtil.DOMAINS_WITH_MORE_INFO = [
'alarm_control_panel', 'automation', 'camera', 'climate', 'configurator',
'cover', 'fan', 'group', 'history_graph', 'light', 'lock', 'media_player', 'script',
'sun', 'updater', 'vacuum',
'sun', 'updater', 'vacuum', 'input_datetime',
];
window.hassUtil.DOMAINS_WITH_NO_HISTORY = ['camera', 'configurator', 'history_graph', 'scene'];
@ -467,11 +467,12 @@ window.hassUtil.sortByName = function (entityA, entityB) {
window.hassUtil.computeStateState = function (stateObj) {
if (!stateObj._stateDisplay) {
stateObj._stateDisplay = stateObj.state.replace(/_/g, ' ');
const domain = window.hassUtil.computeDomain(stateObj);
if (stateObj.attributes.unit_of_measurement) {
stateObj._stateDisplay += ' ' + stateObj.attributes.unit_of_measurement;
}
if (window.hassUtil.computeDomain(stateObj) === 'binary_sensor') {
if (domain === 'binary_sensor') {
switch (stateObj.attributes.device_class) {
case 'moisture':
stateObj._stateDisplay = (stateObj._stateDisplay === 'off') ? 'dry' : 'wet';
@ -498,6 +499,30 @@ window.hassUtil.computeStateState = function (stateObj) {
case 'power':
default:
}
} else if (domain === 'input_datetime') {
let date;
if (!stateObj.attributes.has_time) {
date = new Date(
stateObj.attributes.year,
stateObj.attributes.month - 1,
stateObj.attributes.day
);
stateObj._stateDisplay = window.hassUtil.formatDate(date);
} else if (!stateObj.attributes.has_date) {
date = new Date(
1970, 0, 1,
stateObj.attributes.hour,
stateObj.attributes.minute
);
stateObj._stateDisplay = window.hassUtil.formatTime(date);
} else {
date = new Date(
stateObj.attributes.year, stateObj.attributes.month - 1,
stateObj.attributes.day, stateObj.attributes.hour,
stateObj.attributes.minute
);
stateObj._stateDisplay = window.hassUtil.formatDateTime(date);
}
}
}