import {
css,
html,
LitElement,
} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module";
import dayjs from "https://unpkg.com/dayjs@1.8.24/esm/index.js?module";
import localizedFormat from "https://unpkg.com/dayjs@1.8.24/esm/plugin/localizedFormat/index.js";
dayjs.extend(localizedFormat);
function hashCode(str) {
return Array.from(str).reduce(
(hash, letter) => letter.charCodeAt(0) + ((hash << 5) - hash),
0
);
}
function intToRGB(i) {
const c = (i & 0x00ffffff).toString(16).toUpperCase();
return "#" + "00000".substring(0, 6 - c.length) + c;
}
class NonowCalendar extends LitElement {
constructor() {
super();
this.events = [];
this.lastUpdate = dayjs("2000-01-01T00:00:00.000Z");
this.loading = true;
}
static get properties() {
return {
hass: {},
config: {},
};
}
async getCalendarData(entity) {
const timeOffset = -dayjs().utcOffset();
const start = dayjs()
.startOf("day")
.add(timeOffset, "minutes")
.format("YYYY-MM-DDTHH:mm:ss");
const end = dayjs()
.add(this.config.daysToShow, "days")
.endOf("day")
.add(timeOffset, "minutes")
.format("YYYY-MM-DDTHH:mm:ss");
const url = `calendars/${entity.entity}?start=${start}Z&end=${end}Z`;
const events = await this.hass.callApi("get", url);
const color = entity.color || intToRGB(hashCode(entity.entity));
return events.map((event) => ({
...event,
color,
}));
}
async getEvents() {
if (dayjs().diff(this.lastUpdate, "minute") < 15) {
return;
}
this.lastUpdate = dayjs();
const calendarEvents = await Promise.all(
this.config.entities.map((entity) => this.getCalendarData(entity))
);
this.loading = false;
this.events = Array.prototype.concat
.apply([], calendarEvents)
.sort((a, b) =>
dayjs(a.start.dateTime).diff(dayjs(b.start.dateTime)) > 0 ? 1 : -1
);
if (this.config.limit > -1) {
this.events = this.events.slice(0, this.config.limit);
}
}
renderChip(color) {
if (this.config.showColor && color) {
return html``;
}
return "";
}
renderEvent(event, i, events) {
const startDay = dayjs(event.start.dateTime);
const endDay = dayjs(event.end.dateTime);
const pad = (value) => String(value).padStart(2, "0");
const location = this.renderLocation(event.location);
const progress = this.renderProgress(startDay, endDay);
const title = this.renderTitle(startDay, events, i);
const chip = this.renderChip(event.color);
const endedClass = dayjs().isAfter(endDay) ? "nonow-calendar--ended" : "";
return html`
${title}