discourse-calendar/assets/javascripts/discourse/components/upcoming-events-calendar.js

144 lines
4.0 KiB
JavaScript

import Component from "@ember/component";
import { schedule } from "@ember/runloop";
import { Promise } from "rsvp";
import loadScript from "discourse/lib/load-script";
import Category from "discourse/models/category";
import getURL from "discourse-common/lib/get-url";
import { formatEventName } from "../helpers/format-event-name";
import addRecurrentEvents from "../lib/add-recurrent-events";
import fullCalendarDefaultOptions from "../lib/full-calendar-default-options";
import { isNotFullDayEvent } from "../lib/guess-best-date-format";
export default Component.extend({
tagName: "",
events: null,
init() {
this._super(...arguments);
this._calendar = null;
},
willDestroyElement() {
this._super(...arguments);
this._calendar && this._calendar.destroy();
this._calendar = null;
},
didInsertElement() {
this._super(...arguments);
this._renderCalendar();
},
_renderCalendar() {
const siteSettings = this.site.siteSettings;
const calendarNode = document.getElementById("upcoming-events-calendar");
if (!calendarNode) {
return;
}
calendarNode.innerHTML = "";
this._loadCalendar().then(() => {
const fullCalendar = new window.FullCalendar.Calendar(calendarNode, {
...fullCalendarDefaultOptions(),
height: "parent",
eventPositioned: (info) => {
if (siteSettings.events_max_rows === 0) {
return;
}
let fcContent = info.el.querySelector(".fc-content");
let computedStyle = window.getComputedStyle(fcContent);
let lineHeight = parseInt(computedStyle.lineHeight, 10);
if (lineHeight === 0) {
lineHeight = 20;
}
let maxHeight = lineHeight * siteSettings.events_max_rows;
if (fcContent) {
fcContent.style.maxHeight = `${maxHeight}px`;
}
let fcTitle = info.el.querySelector(".fc-title");
if (fcTitle) {
fcTitle.style.overflow = "hidden";
fcTitle.style.whiteSpace = "pre-wrap";
}
fullCalendar.updateSize();
},
});
this._calendar = fullCalendar;
const tagsColorsMap = JSON.parse(siteSettings.map_events_to_color);
const originalEventAndRecurrents = addRecurrentEvents(this.events);
(originalEventAndRecurrents || []).forEach((event) => {
const { startsAt, endsAt, post, categoryId } = event;
let backgroundColor;
if (post.topic.tags) {
const tagColorEntry = tagsColorsMap.find(
(entry) =>
entry.type === "tag" && post.topic.tags.includes(entry.slug)
);
backgroundColor = tagColorEntry?.color;
}
if (!backgroundColor) {
const categoryColorEntry = tagsColorsMap.find(
(entry) =>
entry.type === "category" &&
entry.slug === post.topic.category_slug
);
backgroundColor = categoryColorEntry?.color;
}
const categoryColor = Category.findById(categoryId)?.color;
if (!backgroundColor && categoryColor) {
backgroundColor = `#${categoryColor}`;
}
let classNames;
if (moment(endsAt || startsAt).isBefore(moment())) {
classNames = "fc-past-event";
}
this._calendar.addEvent({
title: formatEventName(event),
start: startsAt,
end: endsAt || startsAt,
allDay: !isNotFullDayEvent(moment(startsAt), moment(endsAt)),
url: getURL(`/t/-/${post.topic.id}/${post.post_number}`),
backgroundColor,
classNames,
});
});
this._calendar.render();
});
},
_loadCalendar() {
return new Promise((resolve) => {
loadScript(
"/plugins/discourse-calendar/javascripts/fullcalendar-with-moment-timezone.min.js"
).then(() => {
schedule("afterRender", () => {
if (this.isDestroying || this.isDestroyed) {
return;
}
resolve();
});
});
});
},
});