Add support for timestamp device class (#2087)

This commit is contained in:
Paulus Schoutsen 2018-11-23 19:38:28 +01:00 committed by GitHub
parent d41a4cf78b
commit a7ab652dd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 244 additions and 12 deletions

View File

@ -10,31 +10,43 @@ const langKey = ["second", "minute", "hour", "day"];
export default function relativeTime(
dateObj: Date,
localize: LocalizeFunc
localize: LocalizeFunc,
options: {
compareTime?: Date;
includeTense?: boolean;
} = {}
): string {
let delta = (new Date().getTime() - dateObj.getTime()) / 1000;
const compareTime = options.compareTime || new Date();
let delta = (compareTime.getTime() - dateObj.getTime()) / 1000;
const tense = delta >= 0 ? "past" : "future";
delta = Math.abs(delta);
let timeDesc;
for (let i = 0; i < tests.length; i++) {
if (delta < tests[i]) {
delta = Math.floor(delta);
const timeDesc = localize(
timeDesc = localize(
`ui.components.relative_time.duration.${langKey[i]}`,
"count",
delta
);
return localize(`ui.components.relative_time.${tense}`, "time", timeDesc);
break;
}
delta /= tests[i];
}
delta = Math.floor(delta);
const time = localize(
"ui.components.relative_time.duration.week",
"count",
delta
);
return localize(`ui.components.relative_time.${tense}`, "time", time);
if (timeDesc === undefined) {
delta = Math.floor(delta);
timeDesc = localize(
"ui.components.relative_time.duration.week",
"count",
delta
);
}
return options.includeTense === false
? timeDesc
: localize(`ui.components.relative_time.${tense}`, "time", timeDesc);
}

View File

@ -10,6 +10,7 @@ import "../entity-rows/hui-lock-entity-row";
import "../entity-rows/hui-media-player-entity-row";
import "../entity-rows/hui-scene-entity-row";
import "../entity-rows/hui-script-entity-row";
import "../entity-rows/hui-sensor-entity-row";
import "../entity-rows/hui-text-entity-row";
import "../entity-rows/hui-timer-entity-row";
import "../entity-rows/hui-toggle-entity-row";
@ -42,6 +43,7 @@ const DOMAIN_TO_ELEMENT_TYPE = {
lock: "lock",
scene: "scene",
script: "script",
sensor: "sensor",
timer: "timer",
switch: "toggle",
vacuum: "toggle",

View File

@ -0,0 +1,130 @@
import {
html,
LitElement,
PropertyDeclarations,
PropertyValues,
} from "@polymer/lit-element";
import { TemplateResult } from "lit-html";
import { HomeAssistant } from "../../../types";
import format_date from "../../../common/datetime/format_date";
import format_date_time from "../../../common/datetime/format_date_time";
import format_time from "../../../common/datetime/format_time";
import relativeTime from "../../../common/datetime/relative_time";
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
const FORMATS: { [key: string]: (ts: Date, lang: string) => string } = {
date: format_date,
datetime: format_date_time,
time: format_time,
};
const INTERVAL_FORMAT = ["relative", "total"];
class HuiTimestampDisplay extends hassLocalizeLitMixin(LitElement) {
public hass?: HomeAssistant;
public ts?: Date;
public format?: "relative" | "total" | "date" | "datetime" | "time";
private _relative?: string;
private _connected?: boolean;
private _interval?: number;
static get properties(): PropertyDeclarations {
return {
ts: {},
hass: {},
format: {},
_relative: {},
};
}
public connectedCallback() {
super.connectedCallback();
this._connected = true;
this._startInterval();
}
public disconnectedCallback() {
super.disconnectedCallback();
this._connected = false;
this._clearInterval();
}
protected render(): TemplateResult {
if (!this.ts || !this.hass) {
return html``;
}
if (isNaN(this.ts.getTime())) {
return html`
Invalid date
`;
}
const format = this._format;
if (INTERVAL_FORMAT.includes(format)) {
return html`
${this._relative}
`;
} else if (format in FORMATS) {
return html`
${FORMATS[format](this.ts, this.hass.language)}
`;
} else {
return html`
Invalid format
`;
}
}
protected updated(changedProperties: PropertyValues) {
if (!changedProperties.has("format") || !this._connected) {
return;
}
if (INTERVAL_FORMAT.includes("relative")) {
this._startInterval();
} else {
this._clearInterval();
}
}
private get _format() {
return this.format || "relative";
}
private _startInterval() {
this._clearInterval();
if (this._connected && INTERVAL_FORMAT.includes(this._format)) {
this._updateRelative();
this._interval = window.setInterval(() => this._updateRelative(), 1000);
}
}
private _clearInterval() {
if (this._interval) {
clearInterval(this._interval);
this._interval = undefined;
}
}
private _updateRelative() {
if (this.ts && this.localize) {
this._relative =
this._format === "relative"
? relativeTime(this.ts, this.localize)
: (this._relative = relativeTime(new Date(), this.localize, {
compareTime: this.ts,
includeTense: false,
}));
}
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-timestamp-display": HuiTimestampDisplay;
}
}
customElements.define("hui-timestamp-display", HuiTimestampDisplay);

View File

@ -3,16 +3,19 @@ import { TemplateResult } from "lit-html";
class HuiErrorEntityRow extends LitElement {
public entity?: string;
public error?: string;
static get properties() {
return {
error: {},
entity: {},
};
}
protected render(): TemplateResult {
return html`
${this.renderStyle()} Entity not available: ${this.entity || ""}
${this.renderStyle()} ${this.error || "Entity not available"}:
${this.entity || ""}
`;
}

View File

@ -0,0 +1,85 @@
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
import { TemplateResult } from "lit-html";
import "../components/hui-generic-entity-row";
import "../components/hui-timestamp-display";
import "./hui-error-entity-row";
import { HomeAssistant } from "../../../types";
import { EntityRow, EntityConfig } from "./types";
interface SensorEntityConfig extends EntityConfig {
format?: "relative" | "date" | "time" | "datetime";
}
class HuiSensorEntityRow extends LitElement implements EntityRow {
public hass?: HomeAssistant;
private _config?: SensorEntityConfig;
static get properties(): PropertyDeclarations {
return {
hass: {},
_config: {},
};
}
public setConfig(config: SensorEntityConfig): void {
if (!config) {
throw new Error("Configuration error");
}
this._config = config;
}
protected render(): TemplateResult {
if (!this._config || !this.hass) {
return html``;
}
const stateObj = this.hass.states[this._config.entity];
if (!stateObj) {
return html`
<hui-error-entity-row
.entity="${this._config.entity}"
></hui-error-entity-row>
`;
}
return html`
${this.renderStyle()}
<hui-generic-entity-row .hass="${this.hass}" .config="${this._config}">
<div>
${
stateObj.attributes.device_class === "timestamp"
? html`
<hui-timestamp-display
.hass="${this.hass}"
.ts="${new Date(stateObj.state)}"
.format="${this._config.format}"
></hui-timestamp-display>
`
: stateObj.state
}
</div>
</hui-generic-entity-row>
`;
}
private renderStyle(): TemplateResult {
return html`
<style>
div {
text-align: right;
}
</style>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-sensor-entity-row": HuiSensorEntityRow;
}
}
customElements.define("hui-sensor-entity-row", HuiSensorEntityRow);