FEATURE: customizable event colors by tags and adjustable max rows in calendar (#482)
* FEATURE: customizable event colors by tags and adjustable max rows
This commit is contained in:
parent
07ff8f4f1b
commit
d27e52e340
|
@ -51,4 +51,4 @@ DEPENDENCIES
|
||||||
syntax_tree
|
syntax_tree
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.1.4
|
2.4.22
|
||||||
|
|
|
@ -14,7 +14,7 @@ module DiscoursePostEvent
|
||||||
# lightweight post object containing
|
# lightweight post object containing
|
||||||
# only needed info for client
|
# only needed info for client
|
||||||
def post
|
def post
|
||||||
{
|
post_hash = {
|
||||||
id: object.post.id,
|
id: object.post.id,
|
||||||
post_number: object.post.post_number,
|
post_number: object.post.post_number,
|
||||||
url: object.post.url,
|
url: object.post.url,
|
||||||
|
@ -23,6 +23,13 @@ module DiscoursePostEvent
|
||||||
title: object.post.topic.title,
|
title: object.post.topic.title,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if JSON.parse(SiteSetting.map_events_to_color).size > 0
|
||||||
|
post_hash[:topic][:category_slug] = object.post.topic&.category&.slug
|
||||||
|
post_hash[:topic][:tags] = object.post.topic.tags&.map(&:name)
|
||||||
|
end
|
||||||
|
|
||||||
|
post_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
def category_id
|
def category_id
|
||||||
|
|
|
@ -5,6 +5,7 @@ import loadScript from "discourse/lib/load-script";
|
||||||
import getURL from "discourse-common/lib/get-url";
|
import getURL from "discourse-common/lib/get-url";
|
||||||
import { formatEventName } from "../helpers/format-event-name";
|
import { formatEventName } from "../helpers/format-event-name";
|
||||||
import { isNotFullDayEvent } from "../lib/guess-best-date-format";
|
import { isNotFullDayEvent } from "../lib/guess-best-date-format";
|
||||||
|
import { buildPopover, destroyPopover } from "../lib/popover";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
tagName: "",
|
tagName: "",
|
||||||
|
@ -46,6 +47,8 @@ export default Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderCalendar() {
|
_renderCalendar() {
|
||||||
|
const siteSettings = this.site.siteSettings;
|
||||||
|
|
||||||
const calendarNode = document.getElementById("upcoming-events-calendar");
|
const calendarNode = document.getElementById("upcoming-events-calendar");
|
||||||
if (!calendarNode) {
|
if (!calendarNode) {
|
||||||
return;
|
return;
|
||||||
|
@ -54,7 +57,47 @@ export default Component.extend({
|
||||||
calendarNode.innerHTML = "";
|
calendarNode.innerHTML = "";
|
||||||
|
|
||||||
this._loadCalendar().then(() => {
|
this._loadCalendar().then(() => {
|
||||||
this._calendar = new window.FullCalendar.Calendar(calendarNode, {});
|
const fullCalendar = new window.FullCalendar.Calendar(calendarNode, {
|
||||||
|
eventClick: function () {
|
||||||
|
destroyPopover();
|
||||||
|
},
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
eventMouseEnter: function ({ event, jsEvent }) {
|
||||||
|
destroyPopover();
|
||||||
|
const htmlContent = event.title;
|
||||||
|
buildPopover(jsEvent, htmlContent);
|
||||||
|
},
|
||||||
|
eventMouseLeave: function () {
|
||||||
|
destroyPopover();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this._calendar = fullCalendar;
|
||||||
|
|
||||||
|
const tagsColorsMap = JSON.parse(siteSettings.map_events_to_color);
|
||||||
|
|
||||||
const originalEventAndRecurrents = this.addRecurrentEvents(
|
const originalEventAndRecurrents = this.addRecurrentEvents(
|
||||||
this.events.content
|
this.events.content
|
||||||
|
@ -62,8 +105,28 @@ export default Component.extend({
|
||||||
|
|
||||||
(originalEventAndRecurrents || []).forEach((event) => {
|
(originalEventAndRecurrents || []).forEach((event) => {
|
||||||
const { starts_at, ends_at, post, category_id } = event;
|
const { starts_at, ends_at, post, category_id } = event;
|
||||||
const categoryColor = this.site.categoriesById[category_id]?.color;
|
|
||||||
const backgroundColor = categoryColor ? `#${categoryColor}` : undefined;
|
let backgroundColor;
|
||||||
|
|
||||||
|
if (post.topic.tags) {
|
||||||
|
const tagColorEntry = tagsColorsMap.find(
|
||||||
|
(entry) =>
|
||||||
|
entry.type === "tag" && post.topic.tags.includes(entry.slug)
|
||||||
|
);
|
||||||
|
backgroundColor = tagColorEntry ? tagColorEntry.color : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!backgroundColor) {
|
||||||
|
const categoryColorFromMap = tagsColorsMap.find(
|
||||||
|
(entry) =>
|
||||||
|
entry.type === "category" &&
|
||||||
|
entry.slug === post.topic.category_slug
|
||||||
|
)?.color;
|
||||||
|
backgroundColor =
|
||||||
|
categoryColorFromMap ||
|
||||||
|
`#${this.site.categoriesById[category_id]?.color}`;
|
||||||
|
}
|
||||||
|
|
||||||
this._calendar.addEvent({
|
this._calendar.addEvent({
|
||||||
title: formatEventName(event),
|
title: formatEventName(event),
|
||||||
start: starts_at,
|
start: starts_at,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { isPresent } from "@ember/utils";
|
import { isPresent } from "@ember/utils";
|
||||||
import { createPopper } from "@popperjs/core";
|
|
||||||
import $ from "jquery";
|
import $ from "jquery";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
@ -15,6 +14,7 @@ import I18n from "I18n";
|
||||||
import { formatEventName } from "../helpers/format-event-name";
|
import { formatEventName } from "../helpers/format-event-name";
|
||||||
import { colorToHex, contrastColor, stringToColor } from "../lib/colors";
|
import { colorToHex, contrastColor, stringToColor } from "../lib/colors";
|
||||||
import { isNotFullDayEvent } from "../lib/guess-best-date-format";
|
import { isNotFullDayEvent } from "../lib/guess-best-date-format";
|
||||||
|
import { buildPopover, destroyPopover } from "../lib/popover";
|
||||||
|
|
||||||
function loadFullCalendar() {
|
function loadFullCalendar() {
|
||||||
return loadScript(
|
return loadScript(
|
||||||
|
@ -36,9 +36,6 @@ function getCalendarButtonsText() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventPopper;
|
|
||||||
const EVENT_POPOVER_ID = "event-popover";
|
|
||||||
|
|
||||||
function initializeDiscourseCalendar(api) {
|
function initializeDiscourseCalendar(api) {
|
||||||
const siteSettings = api.container.lookup("service:site-settings");
|
const siteSettings = api.container.lookup("service:site-settings");
|
||||||
|
|
||||||
|
@ -140,8 +137,44 @@ function initializeDiscourseCalendar(api) {
|
||||||
let fullCalendar = new window.FullCalendar.Calendar(
|
let fullCalendar = new window.FullCalendar.Calendar(
|
||||||
categoryEventNode,
|
categoryEventNode,
|
||||||
{
|
{
|
||||||
|
eventClick: function () {
|
||||||
|
destroyPopover();
|
||||||
|
},
|
||||||
locale: getCurrentBcp47Locale(),
|
locale: getCurrentBcp47Locale(),
|
||||||
buttonText: getCalendarButtonsText(),
|
buttonText: getCalendarButtonsText(),
|
||||||
|
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();
|
||||||
|
},
|
||||||
|
eventMouseEnter: function ({ event, jsEvent }) {
|
||||||
|
destroyPopover();
|
||||||
|
const htmlContent = event.title;
|
||||||
|
buildPopover(jsEvent, htmlContent);
|
||||||
|
},
|
||||||
|
eventMouseLeave: function () {
|
||||||
|
destroyPopover();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const loadEvents = ajax(
|
const loadEvents = ajax(
|
||||||
|
@ -151,9 +184,32 @@ function initializeDiscourseCalendar(api) {
|
||||||
Promise.all([loadEvents]).then((results) => {
|
Promise.all([loadEvents]).then((results) => {
|
||||||
const events = results[0];
|
const events = results[0];
|
||||||
|
|
||||||
|
const tagsColorsMap = JSON.parse(siteSettings.map_events_to_color);
|
||||||
|
|
||||||
events[Object.keys(events)[0]].forEach((event) => {
|
events[Object.keys(events)[0]].forEach((event) => {
|
||||||
const { starts_at, ends_at, post, category_id } = event;
|
const { starts_at, ends_at, post, category_id } = event;
|
||||||
const backgroundColor = `#${site.categoriesById[category_id]?.color}`;
|
|
||||||
|
let backgroundColor;
|
||||||
|
|
||||||
|
if (post.topic.tags) {
|
||||||
|
const tagColorEntry = tagsColorsMap.find(
|
||||||
|
(entry) =>
|
||||||
|
entry.type === "tag" && post.topic.tags.includes(entry.slug)
|
||||||
|
);
|
||||||
|
backgroundColor = tagColorEntry ? tagColorEntry.color : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!backgroundColor) {
|
||||||
|
const categoryColorFromMap = tagsColorsMap.find(
|
||||||
|
(entry) =>
|
||||||
|
entry.type === "category" &&
|
||||||
|
entry.slug === post.topic.category_slug
|
||||||
|
)?.color;
|
||||||
|
backgroundColor =
|
||||||
|
categoryColorFromMap ||
|
||||||
|
`#${site.categoriesById[category_id]?.color}`;
|
||||||
|
}
|
||||||
|
|
||||||
fullCalendar.addEvent({
|
fullCalendar.addEvent({
|
||||||
title: formatEventName(event),
|
title: formatEventName(event),
|
||||||
start: starts_at,
|
start: starts_at,
|
||||||
|
@ -438,41 +494,6 @@ function initializeDiscourseCalendar(api) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _buildPopover(jsEvent, htmlContent) {
|
|
||||||
const node = document.createElement("div");
|
|
||||||
node.setAttribute("id", EVENT_POPOVER_ID);
|
|
||||||
node.innerHTML = htmlContent;
|
|
||||||
|
|
||||||
const arrow = document.createElement("span");
|
|
||||||
arrow.dataset.popperArrow = true;
|
|
||||||
node.appendChild(arrow);
|
|
||||||
document.body.appendChild(node);
|
|
||||||
|
|
||||||
eventPopper = createPopper(
|
|
||||||
jsEvent.target,
|
|
||||||
document.getElementById(EVENT_POPOVER_ID),
|
|
||||||
{
|
|
||||||
placement: "bottom",
|
|
||||||
modifiers: [
|
|
||||||
{
|
|
||||||
name: "arrow",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "offset",
|
|
||||||
options: {
|
|
||||||
offset: [20, 10],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _destroyPopover() {
|
|
||||||
eventPopper?.destroy();
|
|
||||||
document.getElementById(EVENT_POPOVER_ID)?.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _setDynamicCalendarOptions(calendar, $calendar) {
|
function _setDynamicCalendarOptions(calendar, $calendar) {
|
||||||
const skipWeekends = $calendar.attr("data-weekends") === "false";
|
const skipWeekends = $calendar.attr("data-weekends") === "false";
|
||||||
const hiddenDays = $calendar.attr("data-hidden-days");
|
const hiddenDays = $calendar.attr("data-hidden-days");
|
||||||
|
@ -489,7 +510,7 @@ function initializeDiscourseCalendar(api) {
|
||||||
}
|
}
|
||||||
|
|
||||||
calendar.setOption("eventClick", ({ event, jsEvent }) => {
|
calendar.setOption("eventClick", ({ event, jsEvent }) => {
|
||||||
_destroyPopover();
|
destroyPopover();
|
||||||
const { htmlContent, postNumber, postUrl } = event.extendedProps;
|
const { htmlContent, postNumber, postUrl } = event.extendedProps;
|
||||||
|
|
||||||
if (postUrl) {
|
if (postUrl) {
|
||||||
|
@ -499,18 +520,18 @@ function initializeDiscourseCalendar(api) {
|
||||||
_topicController || api.container.lookup("controller:topic");
|
_topicController || api.container.lookup("controller:topic");
|
||||||
_topicController.send("jumpToPost", postNumber);
|
_topicController.send("jumpToPost", postNumber);
|
||||||
} else if (isMobileView && htmlContent) {
|
} else if (isMobileView && htmlContent) {
|
||||||
_buildPopover(jsEvent, htmlContent);
|
buildPopover(jsEvent, htmlContent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
calendar.setOption("eventMouseEnter", ({ event, jsEvent }) => {
|
calendar.setOption("eventMouseEnter", ({ event, jsEvent }) => {
|
||||||
_destroyPopover();
|
destroyPopover();
|
||||||
const { htmlContent } = event.extendedProps;
|
const { htmlContent } = event.extendedProps;
|
||||||
_buildPopover(jsEvent, htmlContent);
|
buildPopover(jsEvent, htmlContent);
|
||||||
});
|
});
|
||||||
|
|
||||||
calendar.setOption("eventMouseLeave", () => {
|
calendar.setOption("eventMouseLeave", () => {
|
||||||
_destroyPopover();
|
destroyPopover();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { createPopper } from "@popperjs/core";
|
||||||
|
|
||||||
|
let eventPopper;
|
||||||
|
const EVENT_POPOVER_ID = "event-popover";
|
||||||
|
|
||||||
|
export function buildPopover(jsEvent, htmlContent) {
|
||||||
|
const node = document.createElement("div");
|
||||||
|
node.setAttribute("id", EVENT_POPOVER_ID);
|
||||||
|
node.innerHTML = htmlContent;
|
||||||
|
|
||||||
|
const arrow = document.createElement("span");
|
||||||
|
arrow.dataset.popperArrow = true;
|
||||||
|
node.appendChild(arrow);
|
||||||
|
document.body.appendChild(node);
|
||||||
|
|
||||||
|
eventPopper = createPopper(
|
||||||
|
jsEvent.target,
|
||||||
|
document.getElementById(EVENT_POPOVER_ID),
|
||||||
|
{
|
||||||
|
placement: "bottom",
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: "arrow",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "offset",
|
||||||
|
options: {
|
||||||
|
offset: [20, 10],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function destroyPopover() {
|
||||||
|
eventPopper?.destroy();
|
||||||
|
document.getElementById(EVENT_POPOVER_ID)?.remove();
|
||||||
|
}
|
|
@ -119,10 +119,19 @@ export default createWidget("discourse-post-event", {
|
||||||
this.state.eventModel.watching_invitee.id,
|
this.state.eventModel.watching_invitee.id,
|
||||||
{ status: newStatus, post_id: this.state.eventModel.id }
|
{ status: newStatus, post_id: this.state.eventModel.id }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.appEvents.trigger("calendar:update-invitee-status", {
|
||||||
|
status: newStatus,
|
||||||
|
postId: this.state.eventModel.id,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.store
|
this.store
|
||||||
.createRecord("discourse-post-event-invitee")
|
.createRecord("discourse-post-event-invitee")
|
||||||
.save({ post_id: this.state.eventModel.id, status });
|
.save({ post_id: this.state.eventModel.id, status });
|
||||||
|
this.appEvents.trigger("calendar:create-invitee-status", {
|
||||||
|
status,
|
||||||
|
postId: this.state.eventModel.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -180,12 +189,14 @@ export default createWidget("discourse-post-event", {
|
||||||
post_id: postId,
|
post_id: postId,
|
||||||
})
|
})
|
||||||
.then((invitees) => {
|
.then((invitees) => {
|
||||||
invitees
|
let invitee = invitees.find(
|
||||||
.find(
|
(inv) => inv.id === this.state.eventModel.watching_invitee.id
|
||||||
(invitee) =>
|
);
|
||||||
invitee.id === this.state.eventModel.watching_invitee.id
|
this.appEvents.trigger("calendar:invitee-left-event", {
|
||||||
)
|
invitee,
|
||||||
.destroyRecord();
|
postId,
|
||||||
|
});
|
||||||
|
invitee.destroyRecord();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ en:
|
||||||
```
|
```
|
||||||
|
|
||||||
site_settings:
|
site_settings:
|
||||||
|
events_max_rows: "Maximum text rows per event in the Calendar."
|
||||||
|
map_events_to_color: "Assign a color to each tag or category."
|
||||||
calendar_enabled: "Enable the discourse-calendar plugin. This will add support for a [calendar][/calendar] tag in the first post of a topic."
|
calendar_enabled: "Enable the discourse-calendar plugin. This will add support for a [calendar][/calendar] tag in the first post of a topic."
|
||||||
discourse_post_event_enabled: "Enables the Event features. Note: also needs `calendar enabled` to be enabled."
|
discourse_post_event_enabled: "Enables the Event features. Note: also needs `calendar enabled` to be enabled."
|
||||||
displayed_invitees_limit: "Limits the numbers of invitees displayed on an event."
|
displayed_invitees_limit: "Limits the numbers of invitees displayed on an event."
|
||||||
|
|
|
@ -105,3 +105,10 @@ discourse_post_event:
|
||||||
sidebar_show_upcoming_events:
|
sidebar_show_upcoming_events:
|
||||||
default: true
|
default: true
|
||||||
client: true
|
client: true
|
||||||
|
events_max_rows:
|
||||||
|
default: 2
|
||||||
|
client: true
|
||||||
|
map_events_to_color:
|
||||||
|
client: true
|
||||||
|
default: "[]"
|
||||||
|
json_schema: DiscourseCalendar::SiteSettings::MapEventTagColorsJsonSchema
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module DiscourseCalendar
|
||||||
|
module SiteSettings
|
||||||
|
class MapEventTagColorsJsonSchema
|
||||||
|
def self.schema
|
||||||
|
@schema ||= {
|
||||||
|
type: "array",
|
||||||
|
uniqueItems: true,
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
title: "Color Mapping",
|
||||||
|
properties: {
|
||||||
|
type: {
|
||||||
|
type: "string",
|
||||||
|
description: "Type of mapping (tag or category)",
|
||||||
|
enum: %w[tag category],
|
||||||
|
},
|
||||||
|
slug: {
|
||||||
|
type: "string",
|
||||||
|
description: "Slug of the tag or category",
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
type: "string",
|
||||||
|
description: "Color associated with the tag or category",
|
||||||
|
pattern: "^#(?:[0-9a-fA-F]{3}){1,2}$",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: %w[slug type color],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -77,6 +77,10 @@ end
|
||||||
|
|
||||||
require_relative "lib/discourse_calendar/engine"
|
require_relative "lib/discourse_calendar/engine"
|
||||||
|
|
||||||
|
Dir
|
||||||
|
.glob(File.expand_path("../lib/discourse_calendar/site_settings/*.rb", __FILE__))
|
||||||
|
.each { |f| require(f) }
|
||||||
|
|
||||||
after_initialize do
|
after_initialize do
|
||||||
reloadable_patch do
|
reloadable_patch do
|
||||||
Category.register_custom_field_type("sort_topics_by_event_start_date", :boolean)
|
Category.register_custom_field_type("sort_topics_by_event_start_date", :boolean)
|
||||||
|
|
|
@ -148,4 +148,36 @@ describe DiscoursePostEvent::EventSummarySerializer do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "map_events_to_color" do
|
||||||
|
context "when map_events_to_color is empty" do
|
||||||
|
let(:json) do
|
||||||
|
DiscoursePostEvent::EventSummarySerializer.new(event, scope: Guardian.new).as_json
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the event summary with category_slug and tags" do
|
||||||
|
summary = json[:event_summary]
|
||||||
|
expect(summary[:post][:topic][:category_slug]).to be_nil
|
||||||
|
expect(summary[:post][:topic][:tags]).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when map_events_to_color is set" do
|
||||||
|
let(:json) do
|
||||||
|
DiscoursePostEvent::EventSummarySerializer.new(event, scope: Guardian.new).as_json
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.map_events_to_color = [
|
||||||
|
{ type: "tag", color: "#21d939", slug: "nice-tag" },
|
||||||
|
].to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the event summary with category_slug and tags" do
|
||||||
|
summary = json[:event_summary]
|
||||||
|
expect(summary[:post][:topic][:category_slug]).to eq(category.slug)
|
||||||
|
expect(summary[:post][:topic][:tags]).to eq(topic.tags.map(&:name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ const eventsPretender = (server, helper) => {
|
||||||
topic: {
|
topic: {
|
||||||
id: 18449,
|
id: 18449,
|
||||||
title: "This is an event",
|
title: "This is an event",
|
||||||
|
tags: ["awesome-event"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
name: "Awesome Event",
|
name: "Awesome Event",
|
||||||
|
|
|
@ -10,6 +10,18 @@ acceptance("Discourse Calendar - Category Events Calendar", function (needs) {
|
||||||
discourse_post_event_enabled: true,
|
discourse_post_event_enabled: true,
|
||||||
events_calendar_categories: "1",
|
events_calendar_categories: "1",
|
||||||
calendar_categories: "",
|
calendar_categories: "",
|
||||||
|
map_events_to_color: JSON.stringify([
|
||||||
|
{
|
||||||
|
type: "tag",
|
||||||
|
color: "rgb(231, 76, 60)",
|
||||||
|
slug: "awesome-tag",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "category",
|
||||||
|
color: "rgb(140,24,193)",
|
||||||
|
slug: "awesome-category",
|
||||||
|
},
|
||||||
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
needs.pretender((server, helper) => {
|
needs.pretender((server, helper) => {
|
||||||
|
@ -18,8 +30,14 @@ acceptance("Discourse Calendar - Category Events Calendar", function (needs) {
|
||||||
events: [
|
events: [
|
||||||
{
|
{
|
||||||
id: 67501,
|
id: 67501,
|
||||||
starts_at: "2022-04-25T15:14:00.000Z",
|
starts_at: moment()
|
||||||
ends_at: "2022-04-30T16:14:00.000Z",
|
.tz("Asia/Calcutta")
|
||||||
|
.add(1, "days")
|
||||||
|
.format("YYYY-MM-DDT15:14:00.000Z"),
|
||||||
|
ends_at: moment()
|
||||||
|
.tz("Asia/Calcutta")
|
||||||
|
.add(1, "days")
|
||||||
|
.format("YYYY-MM-DDT16:14:00.000Z"),
|
||||||
timezone: "Asia/Calcutta",
|
timezone: "Asia/Calcutta",
|
||||||
post: {
|
post: {
|
||||||
id: 67501,
|
id: 67501,
|
||||||
|
@ -28,15 +46,55 @@ acceptance("Discourse Calendar - Category Events Calendar", function (needs) {
|
||||||
topic: {
|
topic: {
|
||||||
id: 18449,
|
id: 18449,
|
||||||
title: "This is an event",
|
title: "This is an event",
|
||||||
|
tags: ["awesome-tag"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
name: "Awesome Event",
|
name: "Awesome Event",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 67502,
|
||||||
|
starts_at: moment()
|
||||||
|
.tz("Asia/Calcutta")
|
||||||
|
.add(2, "days")
|
||||||
|
.format("YYYY-MM-DDT15:14:00.000Z"),
|
||||||
|
ends_at: moment()
|
||||||
|
.tz("Asia/Calcutta")
|
||||||
|
.add(2, "days")
|
||||||
|
.format("YYYY-MM-DDT16:14:00.000Z"),
|
||||||
|
timezone: "Asia/Calcutta",
|
||||||
|
post: {
|
||||||
|
id: 67502,
|
||||||
|
post_number: 1,
|
||||||
|
url: "/t/this-is-an-event/18450/1",
|
||||||
|
topic: {
|
||||||
|
id: 18450,
|
||||||
|
title: "This is an event",
|
||||||
|
category_slug: "awesome-category",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: "Awesome Event 2",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("events display the color configured in the map_events_to_color site setting", async (assert) => {
|
||||||
|
await visit("/c/bug/1");
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(".fc-event")
|
||||||
|
.exists({ count: 2 }, "One event is displayed on the calendar");
|
||||||
|
|
||||||
|
assert.dom(".fc-event[href='/t/-/18449/1']").hasStyle({
|
||||||
|
"background-color": "rgb(231, 76, 60)",
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.dom(".fc-event[href='/t/-/18450/1']").hasStyle({
|
||||||
|
"background-color": "rgb(140, 24, 193)",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test("shows event calendar on category page", async (assert) => {
|
test("shows event calendar on category page", async (assert) => {
|
||||||
await visit("/c/bug/1");
|
await visit("/c/bug/1");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue