122 lines
3.2 KiB
TypeScript
122 lines
3.2 KiB
TypeScript
import { html, LitElement, PropertyValues, TemplateResult } from "lit";
|
|
import { customElement, property, state } from "lit/decorators";
|
|
import { formatDate } from "../../../common/datetime/format_date";
|
|
import { formatDateTime } from "../../../common/datetime/format_date_time";
|
|
import { formatTime } from "../../../common/datetime/format_time";
|
|
import { relativeTime } from "../../../common/datetime/relative_time";
|
|
import { FrontendLocaleData } from "../../../data/translation";
|
|
import { HomeAssistant } from "../../../types";
|
|
import { TimestampRenderingFormat } from "./types";
|
|
|
|
const FORMATS: {
|
|
[key: string]: (ts: Date, lang: FrontendLocaleData) => string;
|
|
} = {
|
|
date: formatDate,
|
|
datetime: formatDateTime,
|
|
time: formatTime,
|
|
};
|
|
const INTERVAL_FORMAT = ["relative", "total"];
|
|
|
|
@customElement("hui-timestamp-display")
|
|
class HuiTimestampDisplay extends LitElement {
|
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
|
|
|
@property() public ts?: Date;
|
|
|
|
@property() public format?: TimestampRenderingFormat;
|
|
|
|
@state() private _relative?: string;
|
|
|
|
private _connected?: boolean;
|
|
|
|
private _interval?: number;
|
|
|
|
public connectedCallback(): void {
|
|
super.connectedCallback();
|
|
this._connected = true;
|
|
this._startInterval();
|
|
}
|
|
|
|
public disconnectedCallback(): void {
|
|
super.disconnectedCallback();
|
|
this._connected = false;
|
|
this._clearInterval();
|
|
}
|
|
|
|
protected render(): TemplateResult {
|
|
if (!this.ts || !this.hass) {
|
|
return html``;
|
|
}
|
|
|
|
if (isNaN(this.ts.getTime())) {
|
|
return html`${this.hass.localize(
|
|
"ui.panel.lovelace.components.timestamp-display.invalid"
|
|
)}`;
|
|
}
|
|
|
|
const format = this._format;
|
|
|
|
if (INTERVAL_FORMAT.includes(format)) {
|
|
return html` ${this._relative} `;
|
|
}
|
|
if (format in FORMATS) {
|
|
return html` ${FORMATS[format](this.ts, this.hass.locale)} `;
|
|
}
|
|
return html`${this.hass.localize(
|
|
"ui.panel.lovelace.components.timestamp-display.invalid_format"
|
|
)}`;
|
|
}
|
|
|
|
protected updated(changedProperties: PropertyValues): void {
|
|
super.updated(changedProperties);
|
|
if (!changedProperties.has("format") || !this._connected) {
|
|
return;
|
|
}
|
|
|
|
if (INTERVAL_FORMAT.includes("relative")) {
|
|
this._startInterval();
|
|
} else {
|
|
this._clearInterval();
|
|
}
|
|
}
|
|
|
|
private get _format(): string {
|
|
return this.format || "relative";
|
|
}
|
|
|
|
private _startInterval(): void {
|
|
this._clearInterval();
|
|
if (this._connected && INTERVAL_FORMAT.includes(this._format)) {
|
|
this._updateRelative();
|
|
this._interval = window.setInterval(() => this._updateRelative(), 1000);
|
|
}
|
|
}
|
|
|
|
private _clearInterval(): void {
|
|
if (this._interval) {
|
|
clearInterval(this._interval);
|
|
this._interval = undefined;
|
|
}
|
|
}
|
|
|
|
private _updateRelative(): void {
|
|
if (this.ts && this.hass!.localize) {
|
|
this._relative =
|
|
this._format === "relative"
|
|
? relativeTime(this.ts, this.hass!.locale)
|
|
: (this._relative = relativeTime(
|
|
new Date(),
|
|
this.hass!.locale,
|
|
this.ts,
|
|
false
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"hui-timestamp-display": HuiTimestampDisplay;
|
|
}
|
|
}
|