diff --git a/js/common/util/compute_domain.js b/js/common/util/compute_domain.js new file mode 100644 index 0000000000..58faa51be7 --- /dev/null +++ b/js/common/util/compute_domain.js @@ -0,0 +1,7 @@ +export default function computeDomain(stateObj) { + if (!stateObj._domain) { + stateObj._domain = stateObj.entity_id.substr(0, stateObj.entity_id.indexOf('.')); + } + + return stateObj._domain; +} diff --git a/js/common/util/compute_state_display.js b/js/common/util/compute_state_display.js new file mode 100644 index 0000000000..a43175de4a --- /dev/null +++ b/js/common/util/compute_state_display.js @@ -0,0 +1,59 @@ +import computeDomain from './compute_domain'; +import formatDateTime from './format_date_time'; +import formatDate from './format_date'; +import formatTime from './format_time'; + +export default function computeStateDisplay(haLocalize, stateObj, language) { + if (!stateObj._stateDisplay) { + const domain = computeDomain(stateObj); + if (domain === 'binary_sensor') { + // Try device class translation, then default binary sensor translation + if (stateObj.attributes.device_class) { + stateObj._stateDisplay = + haLocalize(`state.${domain}.${stateObj.attributes.device_class}`, stateObj.state); + } + if (!stateObj._stateDisplay) { + stateObj._stateDisplay = haLocalize(`state.${domain}.default`, stateObj.state); + } + } else if (stateObj.attributes.unit_of_measurement) { + stateObj._stateDisplay = stateObj.state + ' ' + stateObj.attributes.unit_of_measurement; + } 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 = formatDate(date, language); + } else if (!stateObj.attributes.has_date) { + date = new Date( + 1970, 0, 1, + stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatTime(date, language); + } else { + date = new Date( + stateObj.attributes.year, stateObj.attributes.month - 1, + stateObj.attributes.day, stateObj.attributes.hour, + stateObj.attributes.minute + ); + stateObj._stateDisplay = formatDateTime(date, language); + } + } else if (domain === 'zwave') { + if (['initializing', 'dead'].includes(stateObj.state)) { + stateObj._stateDisplay = haLocalize('state.zwave.query_stage', stateObj.state, 'query_stage', stateObj.attributes.query_stage); + } else { + stateObj._stateDisplay = haLocalize('state.zwave.default', stateObj.state); + } + } else { + stateObj._stateDisplay = haLocalize(`state.${domain}`, stateObj.state); + } + // Fall back to default or raw state if nothing else matches. + stateObj._stateDisplay = stateObj._stateDisplay + || haLocalize('state.default', stateObj.state) || stateObj.state; + } + + return stateObj._stateDisplay; +} diff --git a/js/common/util/format_date.js b/js/common/util/format_date.js new file mode 100644 index 0000000000..006e736f88 --- /dev/null +++ b/js/common/util/format_date.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleDateStringSupportsOptions() { + try { + new Date().toLocaleDateString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleDateStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleDateString( + locales, + { year: 'numeric', month: 'long', day: 'numeric' }, + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'mediumDate'); + }); diff --git a/js/common/util/format_date_time.js b/js/common/util/format_date_time.js new file mode 100644 index 0000000000..f695511b86 --- /dev/null +++ b/js/common/util/format_date_time.js @@ -0,0 +1,22 @@ +// Check for support of native locale string options +function toLocaleStringSupportsOptions() { + try { + new Date().toLocaleString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleString(locales, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: '2-digit', + }); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'haDateTime'); + }); diff --git a/js/common/util/format_time.js b/js/common/util/format_time.js new file mode 100644 index 0000000000..5ff05a67da --- /dev/null +++ b/js/common/util/format_time.js @@ -0,0 +1,19 @@ +// Check for support of native locale string options +function toLocaleTimeStringSupportsOptions() { + try { + new Date().toLocaleTimeString('i'); + } catch (e) { + return e.name === 'RangeError'; + } + return false; +} + +export default (toLocaleTimeStringSupportsOptions() ? + function (dateObj, locales) { + return dateObj.toLocaleTimeString( + locales, + { hour: 'numeric', minute: '2-digit' } + ); + } : function (dateObj, locales) { // eslint-disable-line no-unused-vars + return window.fecha.format(dateObj, 'shortTime'); + }); diff --git a/js/util.js b/js/util.js index 621f7e0019..eb97c013ac 100644 --- a/js/util.js +++ b/js/util.js @@ -7,7 +7,22 @@ */ import attributeClassNames from './common/util/attribute_class_names'; +import computeDomain from './common/util/compute_domain'; +import computeStateDisplay from './common/util/compute_state_display'; +import formatDate from './common/util/format_date'; +import formatDateTime from './common/util/format_date_time'; +import formatTime from './common/util/format_time'; window.hassUtil = window.hassUtil || {}; +const language = navigator.languages ? + navigator.languages[0] : navigator.language || navigator.userLanguage; + +window.fecha.masks.haDateTime = window.fecha.masks.shortTime + ' ' + window.fecha.masks.mediumDate; + window.hassUtil.attributeClassNames = attributeClassNames; +window.hassUtil.computeDomain = computeDomain; +window.hassUtil.computeStateDisplay = computeStateDisplay; +window.hassUtil.formatDate = dateObj => formatDate(dateObj, language); +window.hassUtil.formatDateTime = dateObj => formatDateTime(dateObj, language); +window.hassUtil.formatTime = dateObj => formatTime(dateObj, language); diff --git a/src/components/ha-cards.html b/src/components/ha-cards.html index e4d35670ea..f6e81a4ff5 100644 --- a/src/components/ha-cards.html +++ b/src/components/ha-cards.html @@ -7,6 +7,8 @@ + +